Line data Source code
1 : /*************************************************************************
2 : ALGLIB 3.17.0 (source code generated 2020-12-27)
3 : Copyright (c) Sergey Bochkanov (ALGLIB project).
4 :
5 : >>> SOURCE LICENSE >>>
6 : This program is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation (www.fsf.org); either version 2 of the
9 : License, or (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : A copy of the GNU General Public License is available at
17 : http://www.fsf.org/licensing/licenses
18 : >>> END OF LICENSE >>>
19 : *************************************************************************/
20 : #ifdef _MSC_VER
21 : #define _CRT_SECURE_NO_WARNINGS
22 : #endif
23 : #include "stdafx.h"
24 : #include "optimization.h"
25 :
26 : // disable some irrelevant warnings
27 : #if (AE_COMPILER==AE_MSVC) && !defined(AE_ALL_WARNINGS)
28 : #pragma warning(disable:4100)
29 : #pragma warning(disable:4127)
30 : #pragma warning(disable:4611)
31 : #pragma warning(disable:4702)
32 : #pragma warning(disable:4996)
33 : #endif
34 :
35 : /////////////////////////////////////////////////////////////////////////
36 : //
37 : // THIS SECTION CONTAINS IMPLEMENTATION OF C++ INTERFACE
38 : //
39 : /////////////////////////////////////////////////////////////////////////
40 : namespace alglib
41 : {
42 :
43 : #if defined(AE_COMPILE_CQMODELS) || !defined(AE_PARTIAL_BUILD)
44 :
45 : #endif
46 :
47 : #if defined(AE_COMPILE_OPTGUARDAPI) || !defined(AE_PARTIAL_BUILD)
48 :
49 : #endif
50 :
51 : #if defined(AE_COMPILE_OPTSERV) || !defined(AE_PARTIAL_BUILD)
52 :
53 : #endif
54 :
55 : #if defined(AE_COMPILE_SNNLS) || !defined(AE_PARTIAL_BUILD)
56 :
57 : #endif
58 :
59 : #if defined(AE_COMPILE_SACTIVESETS) || !defined(AE_PARTIAL_BUILD)
60 :
61 : #endif
62 :
63 : #if defined(AE_COMPILE_QQPSOLVER) || !defined(AE_PARTIAL_BUILD)
64 :
65 : #endif
66 :
67 : #if defined(AE_COMPILE_MINLBFGS) || !defined(AE_PARTIAL_BUILD)
68 :
69 : #endif
70 :
71 : #if defined(AE_COMPILE_LPQPSERV) || !defined(AE_PARTIAL_BUILD)
72 :
73 : #endif
74 :
75 : #if defined(AE_COMPILE_VIPMSOLVER) || !defined(AE_PARTIAL_BUILD)
76 :
77 : #endif
78 :
79 : #if defined(AE_COMPILE_NLCSQP) || !defined(AE_PARTIAL_BUILD)
80 :
81 : #endif
82 :
83 : #if defined(AE_COMPILE_QPDENSEAULSOLVER) || !defined(AE_PARTIAL_BUILD)
84 :
85 : #endif
86 :
87 : #if defined(AE_COMPILE_MINBLEIC) || !defined(AE_PARTIAL_BUILD)
88 :
89 : #endif
90 :
91 : #if defined(AE_COMPILE_QPBLEICSOLVER) || !defined(AE_PARTIAL_BUILD)
92 :
93 : #endif
94 :
95 : #if defined(AE_COMPILE_MINQP) || !defined(AE_PARTIAL_BUILD)
96 :
97 : #endif
98 :
99 : #if defined(AE_COMPILE_LPQPPRESOLVE) || !defined(AE_PARTIAL_BUILD)
100 :
101 : #endif
102 :
103 : #if defined(AE_COMPILE_REVISEDDUALSIMPLEX) || !defined(AE_PARTIAL_BUILD)
104 :
105 : #endif
106 :
107 : #if defined(AE_COMPILE_MINLP) || !defined(AE_PARTIAL_BUILD)
108 :
109 : #endif
110 :
111 : #if defined(AE_COMPILE_NLCSLP) || !defined(AE_PARTIAL_BUILD)
112 :
113 : #endif
114 :
115 : #if defined(AE_COMPILE_MINNLC) || !defined(AE_PARTIAL_BUILD)
116 :
117 : #endif
118 :
119 : #if defined(AE_COMPILE_MINBC) || !defined(AE_PARTIAL_BUILD)
120 :
121 : #endif
122 :
123 : #if defined(AE_COMPILE_MINNS) || !defined(AE_PARTIAL_BUILD)
124 :
125 : #endif
126 :
127 : #if defined(AE_COMPILE_MINCOMP) || !defined(AE_PARTIAL_BUILD)
128 :
129 : #endif
130 :
131 : #if defined(AE_COMPILE_MINCG) || !defined(AE_PARTIAL_BUILD)
132 :
133 : #endif
134 :
135 : #if defined(AE_COMPILE_MINLM) || !defined(AE_PARTIAL_BUILD)
136 :
137 : #endif
138 :
139 : #if defined(AE_COMPILE_CQMODELS) || !defined(AE_PARTIAL_BUILD)
140 :
141 : #endif
142 :
143 : #if defined(AE_COMPILE_OPTGUARDAPI) || !defined(AE_PARTIAL_BUILD)
144 : /*************************************************************************
145 : This structure is used to store OptGuard report, i.e. report on the
146 : properties of the nonlinear function being optimized with ALGLIB.
147 :
148 : After you tell your optimizer to activate OptGuard this technology starts
149 : to silently monitor function values and gradients/Jacobians being passed
150 : all around during your optimization session. Depending on specific set of
151 : checks enabled OptGuard may perform additional function evaluations (say,
152 : about 3*N evaluations if you want to check analytic gradient for errors).
153 :
154 : Upon discovering that something strange happens (function values and/or
155 : gradient components change too sharply and/or unexpectedly) OptGuard sets
156 : one of the "suspicion flags" (without interrupting optimization session).
157 : After optimization is done, you can examine OptGuard report.
158 :
159 : Following report fields can be set:
160 : * nonc0suspected
161 : * nonc1suspected
162 : * badgradsuspected
163 :
164 :
165 : === WHAT CAN BE DETECTED WITH OptGuard INTEGRITY CHECKER =================
166 :
167 : Following types of errors in your target function (constraints) can be
168 : caught:
169 : a) discontinuous functions ("non-C0" part of the report)
170 : b) functions with discontinuous derivative ("non-C1" part of the report)
171 : c) errors in the analytic gradient provided by user
172 :
173 : These types of errors result in optimizer stopping well before reaching
174 : solution (most often - right after encountering discontinuity).
175 :
176 : Type A errors are usually coding errors during implementation of the
177 : target function. Most "normal" problems involve continuous functions, and
178 : anyway you can't reliably optimize discontinuous function.
179 :
180 : Type B errors are either coding errors or (in case code itself is correct)
181 : evidence of the fact that your problem is an "incorrect" one. Most
182 : optimizers (except for ones provided by MINNS subpackage) do not support
183 : nonsmooth problems.
184 :
185 : Type C errors are coding errors which often prevent optimizer from making
186 : even one step or result in optimizing stopping too early, as soon as
187 : actual descent direction becomes too different from one suggested by user-
188 : supplied gradient.
189 :
190 :
191 : === WHAT IS REPORTED =====================================================
192 :
193 : Following set of report fields deals with discontinuous target functions,
194 : ones not belonging to C0 continuity class:
195 :
196 : * nonc0suspected - is a flag which is set upon discovering some indication
197 : of the discontinuity. If this flag is false, the rest of "non-C0" fields
198 : should be ignored
199 : * nonc0fidx - is an index of the function (0 for target function, 1 or
200 : higher for nonlinear constraints) which is suspected of being "non-C0"
201 : * nonc0lipshitzc - a Lipchitz constant for a function which was suspected
202 : of being non-continuous.
203 : * nonc0test0positive - set to indicate specific test which detected
204 : continuity violation (test #0)
205 :
206 : Following set of report fields deals with discontinuous gradient/Jacobian,
207 : i.e. with functions violating C1 continuity:
208 :
209 : * nonc1suspected - is a flag which is set upon discovering some indication
210 : of the discontinuity. If this flag is false, the rest of "non-C1" fields
211 : should be ignored
212 : * nonc1fidx - is an index of the function (0 for target function, 1 or
213 : higher for nonlinear constraints) which is suspected of being "non-C1"
214 : * nonc1lipshitzc - a Lipchitz constant for a function gradient which was
215 : suspected of being non-smooth.
216 : * nonc1test0positive - set to indicate specific test which detected
217 : continuity violation (test #0)
218 : * nonc1test1positive - set to indicate specific test which detected
219 : continuity violation (test #1)
220 :
221 : Following set of report fields deals with errors in the gradient:
222 : * badgradsuspected - is a flad which is set upon discovering an error in
223 : the analytic gradient supplied by user
224 : * badgradfidx - index of the function with bad gradient (0 for target
225 : function, 1 or higher for nonlinear constraints)
226 : * badgradvidx - index of the variable
227 : * badgradxbase - location where Jacobian is tested
228 : * following matrices store user-supplied Jacobian and its numerical
229 : differentiation version (which is assumed to be free from the coding
230 : errors), both of them computed near the initial point:
231 : * badgraduser, an array[K,N], analytic Jacobian supplied by user
232 : * badgradnum, an array[K,N], numeric Jacobian computed by ALGLIB
233 : Here K is a total number of nonlinear functions (target + nonlinear
234 : constraints), N is a variable number.
235 : The element of badgraduser[] with index [badgradfidx,badgradvidx] is
236 : assumed to be wrong.
237 :
238 : More detailed error log can be obtained from optimizer by explicitly
239 : requesting reports for tests C0.0, C1.0, C1.1.
240 :
241 : -- ALGLIB --
242 : Copyright 19.11.2018 by Bochkanov Sergey
243 : *************************************************************************/
244 0 : _optguardreport_owner::_optguardreport_owner()
245 : {
246 : jmp_buf _break_jump;
247 : alglib_impl::ae_state _state;
248 :
249 0 : alglib_impl::ae_state_init(&_state);
250 0 : if( setjmp(_break_jump) )
251 : {
252 0 : if( p_struct!=NULL )
253 : {
254 0 : alglib_impl::_optguardreport_destroy(p_struct);
255 0 : alglib_impl::ae_free(p_struct);
256 : }
257 0 : p_struct = NULL;
258 : #if !defined(AE_NO_EXCEPTIONS)
259 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
260 : #else
261 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
262 : return;
263 : #endif
264 : }
265 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
266 0 : p_struct = NULL;
267 0 : p_struct = (alglib_impl::optguardreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::optguardreport), &_state);
268 0 : memset(p_struct, 0, sizeof(alglib_impl::optguardreport));
269 0 : alglib_impl::_optguardreport_init(p_struct, &_state, ae_false);
270 0 : ae_state_clear(&_state);
271 0 : }
272 :
273 0 : _optguardreport_owner::_optguardreport_owner(const _optguardreport_owner &rhs)
274 : {
275 : jmp_buf _break_jump;
276 : alglib_impl::ae_state _state;
277 :
278 0 : alglib_impl::ae_state_init(&_state);
279 0 : if( setjmp(_break_jump) )
280 : {
281 0 : if( p_struct!=NULL )
282 : {
283 0 : alglib_impl::_optguardreport_destroy(p_struct);
284 0 : alglib_impl::ae_free(p_struct);
285 : }
286 0 : p_struct = NULL;
287 : #if !defined(AE_NO_EXCEPTIONS)
288 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
289 : #else
290 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
291 : return;
292 : #endif
293 : }
294 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
295 0 : p_struct = NULL;
296 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: optguardreport copy constructor failure (source is not initialized)", &_state);
297 0 : p_struct = (alglib_impl::optguardreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::optguardreport), &_state);
298 0 : memset(p_struct, 0, sizeof(alglib_impl::optguardreport));
299 0 : alglib_impl::_optguardreport_init_copy(p_struct, const_cast<alglib_impl::optguardreport*>(rhs.p_struct), &_state, ae_false);
300 0 : ae_state_clear(&_state);
301 0 : }
302 :
303 0 : _optguardreport_owner& _optguardreport_owner::operator=(const _optguardreport_owner &rhs)
304 : {
305 0 : if( this==&rhs )
306 0 : return *this;
307 : jmp_buf _break_jump;
308 : alglib_impl::ae_state _state;
309 :
310 0 : alglib_impl::ae_state_init(&_state);
311 0 : if( setjmp(_break_jump) )
312 : {
313 : #if !defined(AE_NO_EXCEPTIONS)
314 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
315 : #else
316 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
317 : return *this;
318 : #endif
319 : }
320 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
321 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: optguardreport assignment constructor failure (destination is not initialized)", &_state);
322 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: optguardreport assignment constructor failure (source is not initialized)", &_state);
323 0 : alglib_impl::_optguardreport_destroy(p_struct);
324 0 : memset(p_struct, 0, sizeof(alglib_impl::optguardreport));
325 0 : alglib_impl::_optguardreport_init_copy(p_struct, const_cast<alglib_impl::optguardreport*>(rhs.p_struct), &_state, ae_false);
326 0 : ae_state_clear(&_state);
327 0 : return *this;
328 : }
329 :
330 0 : _optguardreport_owner::~_optguardreport_owner()
331 : {
332 0 : if( p_struct!=NULL )
333 : {
334 0 : alglib_impl::_optguardreport_destroy(p_struct);
335 0 : ae_free(p_struct);
336 : }
337 0 : }
338 :
339 0 : alglib_impl::optguardreport* _optguardreport_owner::c_ptr()
340 : {
341 0 : return p_struct;
342 : }
343 :
344 0 : alglib_impl::optguardreport* _optguardreport_owner::c_ptr() const
345 : {
346 0 : return const_cast<alglib_impl::optguardreport*>(p_struct);
347 : }
348 0 : optguardreport::optguardreport() : _optguardreport_owner() ,nonc0suspected(p_struct->nonc0suspected),nonc0test0positive(p_struct->nonc0test0positive),nonc0fidx(p_struct->nonc0fidx),nonc0lipschitzc(p_struct->nonc0lipschitzc),nonc1suspected(p_struct->nonc1suspected),nonc1test0positive(p_struct->nonc1test0positive),nonc1test1positive(p_struct->nonc1test1positive),nonc1fidx(p_struct->nonc1fidx),nonc1lipschitzc(p_struct->nonc1lipschitzc),badgradsuspected(p_struct->badgradsuspected),badgradfidx(p_struct->badgradfidx),badgradvidx(p_struct->badgradvidx),badgradxbase(&p_struct->badgradxbase),badgraduser(&p_struct->badgraduser),badgradnum(&p_struct->badgradnum)
349 : {
350 0 : }
351 :
352 0 : optguardreport::optguardreport(const optguardreport &rhs):_optguardreport_owner(rhs) ,nonc0suspected(p_struct->nonc0suspected),nonc0test0positive(p_struct->nonc0test0positive),nonc0fidx(p_struct->nonc0fidx),nonc0lipschitzc(p_struct->nonc0lipschitzc),nonc1suspected(p_struct->nonc1suspected),nonc1test0positive(p_struct->nonc1test0positive),nonc1test1positive(p_struct->nonc1test1positive),nonc1fidx(p_struct->nonc1fidx),nonc1lipschitzc(p_struct->nonc1lipschitzc),badgradsuspected(p_struct->badgradsuspected),badgradfidx(p_struct->badgradfidx),badgradvidx(p_struct->badgradvidx),badgradxbase(&p_struct->badgradxbase),badgraduser(&p_struct->badgraduser),badgradnum(&p_struct->badgradnum)
353 : {
354 0 : }
355 :
356 0 : optguardreport& optguardreport::operator=(const optguardreport &rhs)
357 : {
358 0 : if( this==&rhs )
359 0 : return *this;
360 0 : _optguardreport_owner::operator=(rhs);
361 0 : return *this;
362 : }
363 :
364 0 : optguardreport::~optguardreport()
365 : {
366 0 : }
367 :
368 :
369 : /*************************************************************************
370 : This structure is used for detailed reporting about suspected C0
371 : continuity violation.
372 :
373 : === WHAT IS TESTED =======================================================
374 :
375 : C0 test studies function values (not gradient!) obtained during line
376 : searches and monitors estimate of the Lipschitz constant. Sudden spikes
377 : usually indicate that discontinuity was detected.
378 :
379 :
380 : === WHAT IS REPORTED =====================================================
381 :
382 : Actually, report retrieval function returns TWO report structures:
383 :
384 : * one for most suspicious point found so far (one with highest change in
385 : the function value), so called "strongest" report
386 : * another one for most detailed line search (more function evaluations =
387 : easier to understand what's going on) which triggered test #0 criteria,
388 : so called "longest" report
389 :
390 : In both cases following fields are returned:
391 :
392 : * positive - is TRUE when test flagged suspicious point; FALSE if test
393 : did not notice anything (in the latter cases fields below are empty).
394 : * fidx - is an index of the function (0 for target function, 1 or higher
395 : for nonlinear constraints) which is suspected of being "non-C1"
396 : * x0[], d[] - arrays of length N which store initial point and direction
397 : for line search (d[] can be normalized, but does not have to)
398 : * stp[], f[] - arrays of length CNT which store step lengths and function
399 : values at these points; f[i] is evaluated in x0+stp[i]*d.
400 : * stpidxa, stpidxb - we suspect that function violates C1 continuity
401 : between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3,
402 : with most likely position of the violation between stpidxa+1 and
403 : stpidxa+2.
404 :
405 : You can plot function values stored in stp[] and f[] arrays and study
406 : behavior of your function by your own eyes, just to be sure that test
407 : correctly reported C1 violation.
408 :
409 : -- ALGLIB --
410 : Copyright 19.11.2018 by Bochkanov Sergey
411 : *************************************************************************/
412 0 : _optguardnonc0report_owner::_optguardnonc0report_owner()
413 : {
414 : jmp_buf _break_jump;
415 : alglib_impl::ae_state _state;
416 :
417 0 : alglib_impl::ae_state_init(&_state);
418 0 : if( setjmp(_break_jump) )
419 : {
420 0 : if( p_struct!=NULL )
421 : {
422 0 : alglib_impl::_optguardnonc0report_destroy(p_struct);
423 0 : alglib_impl::ae_free(p_struct);
424 : }
425 0 : p_struct = NULL;
426 : #if !defined(AE_NO_EXCEPTIONS)
427 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
428 : #else
429 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
430 : return;
431 : #endif
432 : }
433 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
434 0 : p_struct = NULL;
435 0 : p_struct = (alglib_impl::optguardnonc0report*)alglib_impl::ae_malloc(sizeof(alglib_impl::optguardnonc0report), &_state);
436 0 : memset(p_struct, 0, sizeof(alglib_impl::optguardnonc0report));
437 0 : alglib_impl::_optguardnonc0report_init(p_struct, &_state, ae_false);
438 0 : ae_state_clear(&_state);
439 0 : }
440 :
441 0 : _optguardnonc0report_owner::_optguardnonc0report_owner(const _optguardnonc0report_owner &rhs)
442 : {
443 : jmp_buf _break_jump;
444 : alglib_impl::ae_state _state;
445 :
446 0 : alglib_impl::ae_state_init(&_state);
447 0 : if( setjmp(_break_jump) )
448 : {
449 0 : if( p_struct!=NULL )
450 : {
451 0 : alglib_impl::_optguardnonc0report_destroy(p_struct);
452 0 : alglib_impl::ae_free(p_struct);
453 : }
454 0 : p_struct = NULL;
455 : #if !defined(AE_NO_EXCEPTIONS)
456 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
457 : #else
458 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
459 : return;
460 : #endif
461 : }
462 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
463 0 : p_struct = NULL;
464 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: optguardnonc0report copy constructor failure (source is not initialized)", &_state);
465 0 : p_struct = (alglib_impl::optguardnonc0report*)alglib_impl::ae_malloc(sizeof(alglib_impl::optguardnonc0report), &_state);
466 0 : memset(p_struct, 0, sizeof(alglib_impl::optguardnonc0report));
467 0 : alglib_impl::_optguardnonc0report_init_copy(p_struct, const_cast<alglib_impl::optguardnonc0report*>(rhs.p_struct), &_state, ae_false);
468 0 : ae_state_clear(&_state);
469 0 : }
470 :
471 0 : _optguardnonc0report_owner& _optguardnonc0report_owner::operator=(const _optguardnonc0report_owner &rhs)
472 : {
473 0 : if( this==&rhs )
474 0 : return *this;
475 : jmp_buf _break_jump;
476 : alglib_impl::ae_state _state;
477 :
478 0 : alglib_impl::ae_state_init(&_state);
479 0 : if( setjmp(_break_jump) )
480 : {
481 : #if !defined(AE_NO_EXCEPTIONS)
482 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
483 : #else
484 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
485 : return *this;
486 : #endif
487 : }
488 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
489 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: optguardnonc0report assignment constructor failure (destination is not initialized)", &_state);
490 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: optguardnonc0report assignment constructor failure (source is not initialized)", &_state);
491 0 : alglib_impl::_optguardnonc0report_destroy(p_struct);
492 0 : memset(p_struct, 0, sizeof(alglib_impl::optguardnonc0report));
493 0 : alglib_impl::_optguardnonc0report_init_copy(p_struct, const_cast<alglib_impl::optguardnonc0report*>(rhs.p_struct), &_state, ae_false);
494 0 : ae_state_clear(&_state);
495 0 : return *this;
496 : }
497 :
498 0 : _optguardnonc0report_owner::~_optguardnonc0report_owner()
499 : {
500 0 : if( p_struct!=NULL )
501 : {
502 0 : alglib_impl::_optguardnonc0report_destroy(p_struct);
503 0 : ae_free(p_struct);
504 : }
505 0 : }
506 :
507 0 : alglib_impl::optguardnonc0report* _optguardnonc0report_owner::c_ptr()
508 : {
509 0 : return p_struct;
510 : }
511 :
512 0 : alglib_impl::optguardnonc0report* _optguardnonc0report_owner::c_ptr() const
513 : {
514 0 : return const_cast<alglib_impl::optguardnonc0report*>(p_struct);
515 : }
516 0 : optguardnonc0report::optguardnonc0report() : _optguardnonc0report_owner() ,positive(p_struct->positive),fidx(p_struct->fidx),x0(&p_struct->x0),d(&p_struct->d),n(p_struct->n),stp(&p_struct->stp),f(&p_struct->f),cnt(p_struct->cnt),stpidxa(p_struct->stpidxa),stpidxb(p_struct->stpidxb)
517 : {
518 0 : }
519 :
520 0 : optguardnonc0report::optguardnonc0report(const optguardnonc0report &rhs):_optguardnonc0report_owner(rhs) ,positive(p_struct->positive),fidx(p_struct->fidx),x0(&p_struct->x0),d(&p_struct->d),n(p_struct->n),stp(&p_struct->stp),f(&p_struct->f),cnt(p_struct->cnt),stpidxa(p_struct->stpidxa),stpidxb(p_struct->stpidxb)
521 : {
522 0 : }
523 :
524 0 : optguardnonc0report& optguardnonc0report::operator=(const optguardnonc0report &rhs)
525 : {
526 0 : if( this==&rhs )
527 0 : return *this;
528 0 : _optguardnonc0report_owner::operator=(rhs);
529 0 : return *this;
530 : }
531 :
532 0 : optguardnonc0report::~optguardnonc0report()
533 : {
534 0 : }
535 :
536 :
537 : /*************************************************************************
538 : This structure is used for detailed reporting about suspected C1
539 : continuity violation as flagged by C1 test #0 (OptGuard has several tests
540 : for C1 continuity, this report is used by #0).
541 :
542 : === WHAT IS TESTED =======================================================
543 :
544 : C1 test #0 studies function values (not gradient!) obtained during line
545 : searches and monitors behavior of directional derivative estimate. This
546 : test is less powerful than test #1, but it does not depend on gradient
547 : values and thus it is more robust against artifacts introduced by
548 : numerical differentiation.
549 :
550 :
551 : === WHAT IS REPORTED =====================================================
552 :
553 : Actually, report retrieval function returns TWO report structures:
554 :
555 : * one for most suspicious point found so far (one with highest change in
556 : the directional derivative), so called "strongest" report
557 : * another one for most detailed line search (more function evaluations =
558 : easier to understand what's going on) which triggered test #0 criteria,
559 : so called "longest" report
560 :
561 : In both cases following fields are returned:
562 :
563 : * positive - is TRUE when test flagged suspicious point; FALSE if test
564 : did not notice anything (in the latter cases fields below are empty).
565 : * fidx - is an index of the function (0 for target function, 1 or higher
566 : for nonlinear constraints) which is suspected of being "non-C1"
567 : * x0[], d[] - arrays of length N which store initial point and direction
568 : for line search (d[] can be normalized, but does not have to)
569 : * stp[], f[] - arrays of length CNT which store step lengths and function
570 : values at these points; f[i] is evaluated in x0+stp[i]*d.
571 : * stpidxa, stpidxb - we suspect that function violates C1 continuity
572 : between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3,
573 : with most likely position of the violation between stpidxa+1 and
574 : stpidxa+2.
575 :
576 : You can plot function values stored in stp[] and f[] arrays and study
577 : behavior of your function by your own eyes, just to be sure that test
578 : correctly reported C1 violation.
579 :
580 : -- ALGLIB --
581 : Copyright 19.11.2018 by Bochkanov Sergey
582 : *************************************************************************/
583 0 : _optguardnonc1test0report_owner::_optguardnonc1test0report_owner()
584 : {
585 : jmp_buf _break_jump;
586 : alglib_impl::ae_state _state;
587 :
588 0 : alglib_impl::ae_state_init(&_state);
589 0 : if( setjmp(_break_jump) )
590 : {
591 0 : if( p_struct!=NULL )
592 : {
593 0 : alglib_impl::_optguardnonc1test0report_destroy(p_struct);
594 0 : alglib_impl::ae_free(p_struct);
595 : }
596 0 : p_struct = NULL;
597 : #if !defined(AE_NO_EXCEPTIONS)
598 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
599 : #else
600 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
601 : return;
602 : #endif
603 : }
604 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
605 0 : p_struct = NULL;
606 0 : p_struct = (alglib_impl::optguardnonc1test0report*)alglib_impl::ae_malloc(sizeof(alglib_impl::optguardnonc1test0report), &_state);
607 0 : memset(p_struct, 0, sizeof(alglib_impl::optguardnonc1test0report));
608 0 : alglib_impl::_optguardnonc1test0report_init(p_struct, &_state, ae_false);
609 0 : ae_state_clear(&_state);
610 0 : }
611 :
612 0 : _optguardnonc1test0report_owner::_optguardnonc1test0report_owner(const _optguardnonc1test0report_owner &rhs)
613 : {
614 : jmp_buf _break_jump;
615 : alglib_impl::ae_state _state;
616 :
617 0 : alglib_impl::ae_state_init(&_state);
618 0 : if( setjmp(_break_jump) )
619 : {
620 0 : if( p_struct!=NULL )
621 : {
622 0 : alglib_impl::_optguardnonc1test0report_destroy(p_struct);
623 0 : alglib_impl::ae_free(p_struct);
624 : }
625 0 : p_struct = NULL;
626 : #if !defined(AE_NO_EXCEPTIONS)
627 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
628 : #else
629 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
630 : return;
631 : #endif
632 : }
633 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
634 0 : p_struct = NULL;
635 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: optguardnonc1test0report copy constructor failure (source is not initialized)", &_state);
636 0 : p_struct = (alglib_impl::optguardnonc1test0report*)alglib_impl::ae_malloc(sizeof(alglib_impl::optguardnonc1test0report), &_state);
637 0 : memset(p_struct, 0, sizeof(alglib_impl::optguardnonc1test0report));
638 0 : alglib_impl::_optguardnonc1test0report_init_copy(p_struct, const_cast<alglib_impl::optguardnonc1test0report*>(rhs.p_struct), &_state, ae_false);
639 0 : ae_state_clear(&_state);
640 0 : }
641 :
642 0 : _optguardnonc1test0report_owner& _optguardnonc1test0report_owner::operator=(const _optguardnonc1test0report_owner &rhs)
643 : {
644 0 : if( this==&rhs )
645 0 : return *this;
646 : jmp_buf _break_jump;
647 : alglib_impl::ae_state _state;
648 :
649 0 : alglib_impl::ae_state_init(&_state);
650 0 : if( setjmp(_break_jump) )
651 : {
652 : #if !defined(AE_NO_EXCEPTIONS)
653 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
654 : #else
655 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
656 : return *this;
657 : #endif
658 : }
659 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
660 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: optguardnonc1test0report assignment constructor failure (destination is not initialized)", &_state);
661 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: optguardnonc1test0report assignment constructor failure (source is not initialized)", &_state);
662 0 : alglib_impl::_optguardnonc1test0report_destroy(p_struct);
663 0 : memset(p_struct, 0, sizeof(alglib_impl::optguardnonc1test0report));
664 0 : alglib_impl::_optguardnonc1test0report_init_copy(p_struct, const_cast<alglib_impl::optguardnonc1test0report*>(rhs.p_struct), &_state, ae_false);
665 0 : ae_state_clear(&_state);
666 0 : return *this;
667 : }
668 :
669 0 : _optguardnonc1test0report_owner::~_optguardnonc1test0report_owner()
670 : {
671 0 : if( p_struct!=NULL )
672 : {
673 0 : alglib_impl::_optguardnonc1test0report_destroy(p_struct);
674 0 : ae_free(p_struct);
675 : }
676 0 : }
677 :
678 0 : alglib_impl::optguardnonc1test0report* _optguardnonc1test0report_owner::c_ptr()
679 : {
680 0 : return p_struct;
681 : }
682 :
683 0 : alglib_impl::optguardnonc1test0report* _optguardnonc1test0report_owner::c_ptr() const
684 : {
685 0 : return const_cast<alglib_impl::optguardnonc1test0report*>(p_struct);
686 : }
687 0 : optguardnonc1test0report::optguardnonc1test0report() : _optguardnonc1test0report_owner() ,positive(p_struct->positive),fidx(p_struct->fidx),x0(&p_struct->x0),d(&p_struct->d),n(p_struct->n),stp(&p_struct->stp),f(&p_struct->f),cnt(p_struct->cnt),stpidxa(p_struct->stpidxa),stpidxb(p_struct->stpidxb)
688 : {
689 0 : }
690 :
691 0 : optguardnonc1test0report::optguardnonc1test0report(const optguardnonc1test0report &rhs):_optguardnonc1test0report_owner(rhs) ,positive(p_struct->positive),fidx(p_struct->fidx),x0(&p_struct->x0),d(&p_struct->d),n(p_struct->n),stp(&p_struct->stp),f(&p_struct->f),cnt(p_struct->cnt),stpidxa(p_struct->stpidxa),stpidxb(p_struct->stpidxb)
692 : {
693 0 : }
694 :
695 0 : optguardnonc1test0report& optguardnonc1test0report::operator=(const optguardnonc1test0report &rhs)
696 : {
697 0 : if( this==&rhs )
698 0 : return *this;
699 0 : _optguardnonc1test0report_owner::operator=(rhs);
700 0 : return *this;
701 : }
702 :
703 0 : optguardnonc1test0report::~optguardnonc1test0report()
704 : {
705 0 : }
706 :
707 :
708 : /*************************************************************************
709 : This structure is used for detailed reporting about suspected C1
710 : continuity violation as flagged by C1 test #1 (OptGuard has several tests
711 : for C1 continuity, this report is used by #1).
712 :
713 : === WHAT IS TESTED =======================================================
714 :
715 : C1 test #1 studies individual components of the gradient as recorded
716 : during line searches. Upon discovering discontinuity in the gradient this
717 : test records specific component which was suspected (or one with highest
718 : indication of discontinuity if multiple components are suspected).
719 :
720 : When precise analytic gradient is provided this test is more powerful than
721 : test #0 which works with function values and ignores user-provided
722 : gradient. However, test #0 becomes more powerful when numerical
723 : differentiation is employed (in such cases test #1 detects higher levels
724 : of numerical noise and becomes too conservative).
725 :
726 : This test also tells specific components of the gradient which violate C1
727 : continuity, which makes it more informative than #0, which just tells that
728 : continuity is violated.
729 :
730 :
731 : === WHAT IS REPORTED =====================================================
732 :
733 : Actually, report retrieval function returns TWO report structures:
734 :
735 : * one for most suspicious point found so far (one with highest change in
736 : the directional derivative), so called "strongest" report
737 : * another one for most detailed line search (more function evaluations =
738 : easier to understand what's going on) which triggered test #1 criteria,
739 : so called "longest" report
740 :
741 : In both cases following fields are returned:
742 :
743 : * positive - is TRUE when test flagged suspicious point; FALSE if test
744 : did not notice anything (in the latter cases fields below are empty).
745 : * fidx - is an index of the function (0 for target function, 1 or higher
746 : for nonlinear constraints) which is suspected of being "non-C1"
747 : * vidx - is an index of the variable in [0,N) with nonsmooth derivative
748 : * x0[], d[] - arrays of length N which store initial point and direction
749 : for line search (d[] can be normalized, but does not have to)
750 : * stp[], g[] - arrays of length CNT which store step lengths and gradient
751 : values at these points; g[i] is evaluated in x0+stp[i]*d and contains
752 : vidx-th component of the gradient.
753 : * stpidxa, stpidxb - we suspect that function violates C1 continuity
754 : between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3,
755 : with most likely position of the violation between stpidxa+1 and
756 : stpidxa+2.
757 :
758 : You can plot function values stored in stp[] and g[] arrays and study
759 : behavior of your function by your own eyes, just to be sure that test
760 : correctly reported C1 violation.
761 :
762 : -- ALGLIB --
763 : Copyright 19.11.2018 by Bochkanov Sergey
764 : *************************************************************************/
765 0 : _optguardnonc1test1report_owner::_optguardnonc1test1report_owner()
766 : {
767 : jmp_buf _break_jump;
768 : alglib_impl::ae_state _state;
769 :
770 0 : alglib_impl::ae_state_init(&_state);
771 0 : if( setjmp(_break_jump) )
772 : {
773 0 : if( p_struct!=NULL )
774 : {
775 0 : alglib_impl::_optguardnonc1test1report_destroy(p_struct);
776 0 : alglib_impl::ae_free(p_struct);
777 : }
778 0 : p_struct = NULL;
779 : #if !defined(AE_NO_EXCEPTIONS)
780 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
781 : #else
782 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
783 : return;
784 : #endif
785 : }
786 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
787 0 : p_struct = NULL;
788 0 : p_struct = (alglib_impl::optguardnonc1test1report*)alglib_impl::ae_malloc(sizeof(alglib_impl::optguardnonc1test1report), &_state);
789 0 : memset(p_struct, 0, sizeof(alglib_impl::optguardnonc1test1report));
790 0 : alglib_impl::_optguardnonc1test1report_init(p_struct, &_state, ae_false);
791 0 : ae_state_clear(&_state);
792 0 : }
793 :
794 0 : _optguardnonc1test1report_owner::_optguardnonc1test1report_owner(const _optguardnonc1test1report_owner &rhs)
795 : {
796 : jmp_buf _break_jump;
797 : alglib_impl::ae_state _state;
798 :
799 0 : alglib_impl::ae_state_init(&_state);
800 0 : if( setjmp(_break_jump) )
801 : {
802 0 : if( p_struct!=NULL )
803 : {
804 0 : alglib_impl::_optguardnonc1test1report_destroy(p_struct);
805 0 : alglib_impl::ae_free(p_struct);
806 : }
807 0 : p_struct = NULL;
808 : #if !defined(AE_NO_EXCEPTIONS)
809 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
810 : #else
811 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
812 : return;
813 : #endif
814 : }
815 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
816 0 : p_struct = NULL;
817 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: optguardnonc1test1report copy constructor failure (source is not initialized)", &_state);
818 0 : p_struct = (alglib_impl::optguardnonc1test1report*)alglib_impl::ae_malloc(sizeof(alglib_impl::optguardnonc1test1report), &_state);
819 0 : memset(p_struct, 0, sizeof(alglib_impl::optguardnonc1test1report));
820 0 : alglib_impl::_optguardnonc1test1report_init_copy(p_struct, const_cast<alglib_impl::optguardnonc1test1report*>(rhs.p_struct), &_state, ae_false);
821 0 : ae_state_clear(&_state);
822 0 : }
823 :
824 0 : _optguardnonc1test1report_owner& _optguardnonc1test1report_owner::operator=(const _optguardnonc1test1report_owner &rhs)
825 : {
826 0 : if( this==&rhs )
827 0 : return *this;
828 : jmp_buf _break_jump;
829 : alglib_impl::ae_state _state;
830 :
831 0 : alglib_impl::ae_state_init(&_state);
832 0 : if( setjmp(_break_jump) )
833 : {
834 : #if !defined(AE_NO_EXCEPTIONS)
835 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
836 : #else
837 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
838 : return *this;
839 : #endif
840 : }
841 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
842 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: optguardnonc1test1report assignment constructor failure (destination is not initialized)", &_state);
843 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: optguardnonc1test1report assignment constructor failure (source is not initialized)", &_state);
844 0 : alglib_impl::_optguardnonc1test1report_destroy(p_struct);
845 0 : memset(p_struct, 0, sizeof(alglib_impl::optguardnonc1test1report));
846 0 : alglib_impl::_optguardnonc1test1report_init_copy(p_struct, const_cast<alglib_impl::optguardnonc1test1report*>(rhs.p_struct), &_state, ae_false);
847 0 : ae_state_clear(&_state);
848 0 : return *this;
849 : }
850 :
851 0 : _optguardnonc1test1report_owner::~_optguardnonc1test1report_owner()
852 : {
853 0 : if( p_struct!=NULL )
854 : {
855 0 : alglib_impl::_optguardnonc1test1report_destroy(p_struct);
856 0 : ae_free(p_struct);
857 : }
858 0 : }
859 :
860 0 : alglib_impl::optguardnonc1test1report* _optguardnonc1test1report_owner::c_ptr()
861 : {
862 0 : return p_struct;
863 : }
864 :
865 0 : alglib_impl::optguardnonc1test1report* _optguardnonc1test1report_owner::c_ptr() const
866 : {
867 0 : return const_cast<alglib_impl::optguardnonc1test1report*>(p_struct);
868 : }
869 0 : optguardnonc1test1report::optguardnonc1test1report() : _optguardnonc1test1report_owner() ,positive(p_struct->positive),fidx(p_struct->fidx),vidx(p_struct->vidx),x0(&p_struct->x0),d(&p_struct->d),n(p_struct->n),stp(&p_struct->stp),g(&p_struct->g),cnt(p_struct->cnt),stpidxa(p_struct->stpidxa),stpidxb(p_struct->stpidxb)
870 : {
871 0 : }
872 :
873 0 : optguardnonc1test1report::optguardnonc1test1report(const optguardnonc1test1report &rhs):_optguardnonc1test1report_owner(rhs) ,positive(p_struct->positive),fidx(p_struct->fidx),vidx(p_struct->vidx),x0(&p_struct->x0),d(&p_struct->d),n(p_struct->n),stp(&p_struct->stp),g(&p_struct->g),cnt(p_struct->cnt),stpidxa(p_struct->stpidxa),stpidxb(p_struct->stpidxb)
874 : {
875 0 : }
876 :
877 0 : optguardnonc1test1report& optguardnonc1test1report::operator=(const optguardnonc1test1report &rhs)
878 : {
879 0 : if( this==&rhs )
880 0 : return *this;
881 0 : _optguardnonc1test1report_owner::operator=(rhs);
882 0 : return *this;
883 : }
884 :
885 0 : optguardnonc1test1report::~optguardnonc1test1report()
886 : {
887 0 : }
888 : #endif
889 :
890 : #if defined(AE_COMPILE_OPTSERV) || !defined(AE_PARTIAL_BUILD)
891 :
892 : #endif
893 :
894 : #if defined(AE_COMPILE_SNNLS) || !defined(AE_PARTIAL_BUILD)
895 :
896 : #endif
897 :
898 : #if defined(AE_COMPILE_SACTIVESETS) || !defined(AE_PARTIAL_BUILD)
899 :
900 : #endif
901 :
902 : #if defined(AE_COMPILE_QQPSOLVER) || !defined(AE_PARTIAL_BUILD)
903 :
904 : #endif
905 :
906 : #if defined(AE_COMPILE_MINLBFGS) || !defined(AE_PARTIAL_BUILD)
907 : /*************************************************************************
908 :
909 : *************************************************************************/
910 498 : _minlbfgsstate_owner::_minlbfgsstate_owner()
911 : {
912 : jmp_buf _break_jump;
913 : alglib_impl::ae_state _state;
914 :
915 498 : alglib_impl::ae_state_init(&_state);
916 498 : if( setjmp(_break_jump) )
917 : {
918 0 : if( p_struct!=NULL )
919 : {
920 0 : alglib_impl::_minlbfgsstate_destroy(p_struct);
921 0 : alglib_impl::ae_free(p_struct);
922 : }
923 0 : p_struct = NULL;
924 : #if !defined(AE_NO_EXCEPTIONS)
925 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
926 : #else
927 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
928 : return;
929 : #endif
930 : }
931 498 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
932 498 : p_struct = NULL;
933 498 : p_struct = (alglib_impl::minlbfgsstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlbfgsstate), &_state);
934 498 : memset(p_struct, 0, sizeof(alglib_impl::minlbfgsstate));
935 498 : alglib_impl::_minlbfgsstate_init(p_struct, &_state, ae_false);
936 498 : ae_state_clear(&_state);
937 498 : }
938 :
939 0 : _minlbfgsstate_owner::_minlbfgsstate_owner(const _minlbfgsstate_owner &rhs)
940 : {
941 : jmp_buf _break_jump;
942 : alglib_impl::ae_state _state;
943 :
944 0 : alglib_impl::ae_state_init(&_state);
945 0 : if( setjmp(_break_jump) )
946 : {
947 0 : if( p_struct!=NULL )
948 : {
949 0 : alglib_impl::_minlbfgsstate_destroy(p_struct);
950 0 : alglib_impl::ae_free(p_struct);
951 : }
952 0 : p_struct = NULL;
953 : #if !defined(AE_NO_EXCEPTIONS)
954 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
955 : #else
956 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
957 : return;
958 : #endif
959 : }
960 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
961 0 : p_struct = NULL;
962 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlbfgsstate copy constructor failure (source is not initialized)", &_state);
963 0 : p_struct = (alglib_impl::minlbfgsstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlbfgsstate), &_state);
964 0 : memset(p_struct, 0, sizeof(alglib_impl::minlbfgsstate));
965 0 : alglib_impl::_minlbfgsstate_init_copy(p_struct, const_cast<alglib_impl::minlbfgsstate*>(rhs.p_struct), &_state, ae_false);
966 0 : ae_state_clear(&_state);
967 0 : }
968 :
969 0 : _minlbfgsstate_owner& _minlbfgsstate_owner::operator=(const _minlbfgsstate_owner &rhs)
970 : {
971 0 : if( this==&rhs )
972 0 : return *this;
973 : jmp_buf _break_jump;
974 : alglib_impl::ae_state _state;
975 :
976 0 : alglib_impl::ae_state_init(&_state);
977 0 : if( setjmp(_break_jump) )
978 : {
979 : #if !defined(AE_NO_EXCEPTIONS)
980 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
981 : #else
982 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
983 : return *this;
984 : #endif
985 : }
986 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
987 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minlbfgsstate assignment constructor failure (destination is not initialized)", &_state);
988 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlbfgsstate assignment constructor failure (source is not initialized)", &_state);
989 0 : alglib_impl::_minlbfgsstate_destroy(p_struct);
990 0 : memset(p_struct, 0, sizeof(alglib_impl::minlbfgsstate));
991 0 : alglib_impl::_minlbfgsstate_init_copy(p_struct, const_cast<alglib_impl::minlbfgsstate*>(rhs.p_struct), &_state, ae_false);
992 0 : ae_state_clear(&_state);
993 0 : return *this;
994 : }
995 :
996 996 : _minlbfgsstate_owner::~_minlbfgsstate_owner()
997 : {
998 498 : if( p_struct!=NULL )
999 : {
1000 498 : alglib_impl::_minlbfgsstate_destroy(p_struct);
1001 498 : ae_free(p_struct);
1002 : }
1003 498 : }
1004 :
1005 5885 : alglib_impl::minlbfgsstate* _minlbfgsstate_owner::c_ptr()
1006 : {
1007 5885 : return p_struct;
1008 : }
1009 :
1010 1494 : alglib_impl::minlbfgsstate* _minlbfgsstate_owner::c_ptr() const
1011 : {
1012 1494 : return const_cast<alglib_impl::minlbfgsstate*>(p_struct);
1013 : }
1014 498 : 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)
1015 : {
1016 498 : }
1017 :
1018 0 : minlbfgsstate::minlbfgsstate(const minlbfgsstate &rhs):_minlbfgsstate_owner(rhs) ,needf(p_struct->needf),needfg(p_struct->needfg),xupdated(p_struct->xupdated),f(p_struct->f),g(&p_struct->g),x(&p_struct->x)
1019 : {
1020 0 : }
1021 :
1022 0 : minlbfgsstate& minlbfgsstate::operator=(const minlbfgsstate &rhs)
1023 : {
1024 0 : if( this==&rhs )
1025 0 : return *this;
1026 0 : _minlbfgsstate_owner::operator=(rhs);
1027 0 : return *this;
1028 : }
1029 :
1030 498 : minlbfgsstate::~minlbfgsstate()
1031 : {
1032 498 : }
1033 :
1034 :
1035 : /*************************************************************************
1036 : This structure stores optimization report:
1037 : * IterationsCount total number of inner iterations
1038 : * NFEV number of gradient evaluations
1039 : * TerminationType termination type (see below)
1040 :
1041 : TERMINATION CODES
1042 :
1043 : TerminationType field contains completion code, which can be:
1044 : -8 internal integrity control detected infinite or NAN values in
1045 : function/gradient. Abnormal termination signalled.
1046 : 1 relative function improvement is no more than EpsF.
1047 : 2 relative step is no more than EpsX.
1048 : 4 gradient norm is no more than EpsG
1049 : 5 MaxIts steps was taken
1050 : 7 stopping conditions are too stringent,
1051 : further improvement is impossible,
1052 : X contains best point found so far.
1053 : 8 terminated by user who called minlbfgsrequesttermination().
1054 : X contains point which was "current accepted" when termination
1055 : request was submitted.
1056 :
1057 : Other fields of this structure are not documented and should not be used!
1058 : *************************************************************************/
1059 498 : _minlbfgsreport_owner::_minlbfgsreport_owner()
1060 : {
1061 : jmp_buf _break_jump;
1062 : alglib_impl::ae_state _state;
1063 :
1064 498 : alglib_impl::ae_state_init(&_state);
1065 498 : if( setjmp(_break_jump) )
1066 : {
1067 0 : if( p_struct!=NULL )
1068 : {
1069 0 : alglib_impl::_minlbfgsreport_destroy(p_struct);
1070 0 : alglib_impl::ae_free(p_struct);
1071 : }
1072 0 : p_struct = NULL;
1073 : #if !defined(AE_NO_EXCEPTIONS)
1074 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
1075 : #else
1076 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
1077 : return;
1078 : #endif
1079 : }
1080 498 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
1081 498 : p_struct = NULL;
1082 498 : p_struct = (alglib_impl::minlbfgsreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlbfgsreport), &_state);
1083 498 : memset(p_struct, 0, sizeof(alglib_impl::minlbfgsreport));
1084 498 : alglib_impl::_minlbfgsreport_init(p_struct, &_state, ae_false);
1085 498 : ae_state_clear(&_state);
1086 498 : }
1087 :
1088 0 : _minlbfgsreport_owner::_minlbfgsreport_owner(const _minlbfgsreport_owner &rhs)
1089 : {
1090 : jmp_buf _break_jump;
1091 : alglib_impl::ae_state _state;
1092 :
1093 0 : alglib_impl::ae_state_init(&_state);
1094 0 : if( setjmp(_break_jump) )
1095 : {
1096 0 : if( p_struct!=NULL )
1097 : {
1098 0 : alglib_impl::_minlbfgsreport_destroy(p_struct);
1099 0 : alglib_impl::ae_free(p_struct);
1100 : }
1101 0 : p_struct = NULL;
1102 : #if !defined(AE_NO_EXCEPTIONS)
1103 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
1104 : #else
1105 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
1106 : return;
1107 : #endif
1108 : }
1109 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
1110 0 : p_struct = NULL;
1111 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlbfgsreport copy constructor failure (source is not initialized)", &_state);
1112 0 : p_struct = (alglib_impl::minlbfgsreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlbfgsreport), &_state);
1113 0 : memset(p_struct, 0, sizeof(alglib_impl::minlbfgsreport));
1114 0 : alglib_impl::_minlbfgsreport_init_copy(p_struct, const_cast<alglib_impl::minlbfgsreport*>(rhs.p_struct), &_state, ae_false);
1115 0 : ae_state_clear(&_state);
1116 0 : }
1117 :
1118 0 : _minlbfgsreport_owner& _minlbfgsreport_owner::operator=(const _minlbfgsreport_owner &rhs)
1119 : {
1120 0 : if( this==&rhs )
1121 0 : return *this;
1122 : jmp_buf _break_jump;
1123 : alglib_impl::ae_state _state;
1124 :
1125 0 : alglib_impl::ae_state_init(&_state);
1126 0 : if( setjmp(_break_jump) )
1127 : {
1128 : #if !defined(AE_NO_EXCEPTIONS)
1129 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
1130 : #else
1131 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
1132 : return *this;
1133 : #endif
1134 : }
1135 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
1136 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minlbfgsreport assignment constructor failure (destination is not initialized)", &_state);
1137 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlbfgsreport assignment constructor failure (source is not initialized)", &_state);
1138 0 : alglib_impl::_minlbfgsreport_destroy(p_struct);
1139 0 : memset(p_struct, 0, sizeof(alglib_impl::minlbfgsreport));
1140 0 : alglib_impl::_minlbfgsreport_init_copy(p_struct, const_cast<alglib_impl::minlbfgsreport*>(rhs.p_struct), &_state, ae_false);
1141 0 : ae_state_clear(&_state);
1142 0 : return *this;
1143 : }
1144 :
1145 996 : _minlbfgsreport_owner::~_minlbfgsreport_owner()
1146 : {
1147 498 : if( p_struct!=NULL )
1148 : {
1149 498 : alglib_impl::_minlbfgsreport_destroy(p_struct);
1150 498 : ae_free(p_struct);
1151 : }
1152 498 : }
1153 :
1154 498 : alglib_impl::minlbfgsreport* _minlbfgsreport_owner::c_ptr()
1155 : {
1156 498 : return p_struct;
1157 : }
1158 :
1159 0 : alglib_impl::minlbfgsreport* _minlbfgsreport_owner::c_ptr() const
1160 : {
1161 0 : return const_cast<alglib_impl::minlbfgsreport*>(p_struct);
1162 : }
1163 498 : minlbfgsreport::minlbfgsreport() : _minlbfgsreport_owner() ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),terminationtype(p_struct->terminationtype)
1164 : {
1165 498 : }
1166 :
1167 0 : minlbfgsreport::minlbfgsreport(const minlbfgsreport &rhs):_minlbfgsreport_owner(rhs) ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),terminationtype(p_struct->terminationtype)
1168 : {
1169 0 : }
1170 :
1171 0 : minlbfgsreport& minlbfgsreport::operator=(const minlbfgsreport &rhs)
1172 : {
1173 0 : if( this==&rhs )
1174 0 : return *this;
1175 0 : _minlbfgsreport_owner::operator=(rhs);
1176 0 : return *this;
1177 : }
1178 :
1179 498 : minlbfgsreport::~minlbfgsreport()
1180 : {
1181 498 : }
1182 :
1183 : /*************************************************************************
1184 : LIMITED MEMORY BFGS METHOD FOR LARGE SCALE OPTIMIZATION
1185 :
1186 : DESCRIPTION:
1187 : The subroutine minimizes function F(x) of N arguments by using a quasi-
1188 : Newton method (LBFGS scheme) which is optimized to use a minimum amount
1189 : of memory.
1190 : The subroutine generates the approximation of an inverse Hessian matrix by
1191 : using information about the last M steps of the algorithm (instead of N).
1192 : It lessens a required amount of memory from a value of order N^2 to a
1193 : value of order 2*N*M.
1194 :
1195 :
1196 : REQUIREMENTS:
1197 : Algorithm will request following information during its operation:
1198 : * function value F and its gradient G (simultaneously) at given point X
1199 :
1200 :
1201 : USAGE:
1202 : 1. User initializes algorithm state with MinLBFGSCreate() call
1203 : 2. User tunes solver parameters with MinLBFGSSetCond() MinLBFGSSetStpMax()
1204 : and other functions
1205 : 3. User calls MinLBFGSOptimize() function which takes algorithm state and
1206 : pointer (delegate, etc.) to callback function which calculates F/G.
1207 : 4. User calls MinLBFGSResults() to get solution
1208 : 5. Optionally user may call MinLBFGSRestartFrom() to solve another problem
1209 : with same N/M but another starting point and/or another function.
1210 : MinLBFGSRestartFrom() allows to reuse already initialized structure.
1211 :
1212 :
1213 : INPUT PARAMETERS:
1214 : N - problem dimension. N>0
1215 : M - number of corrections in the BFGS scheme of Hessian
1216 : approximation update. Recommended value: 3<=M<=7. The smaller
1217 : value causes worse convergence, the bigger will not cause a
1218 : considerably better convergence, but will cause a fall in the
1219 : performance. M<=N.
1220 : X - initial solution approximation, array[0..N-1].
1221 :
1222 :
1223 : OUTPUT PARAMETERS:
1224 : State - structure which stores algorithm state
1225 :
1226 :
1227 : NOTES:
1228 : 1. you may tune stopping conditions with MinLBFGSSetCond() function
1229 : 2. if target function contains exp() or other fast growing functions, and
1230 : optimization algorithm makes too large steps which leads to overflow,
1231 : use MinLBFGSSetStpMax() function to bound algorithm's steps. However,
1232 : L-BFGS rarely needs such a tuning.
1233 :
1234 :
1235 : -- ALGLIB --
1236 : Copyright 02.04.2010 by Bochkanov Sergey
1237 : *************************************************************************/
1238 0 : void minlbfgscreate(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlbfgsstate &state, const xparams _xparams)
1239 : {
1240 : jmp_buf _break_jump;
1241 : alglib_impl::ae_state _alglib_env_state;
1242 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1243 0 : if( setjmp(_break_jump) )
1244 : {
1245 : #if !defined(AE_NO_EXCEPTIONS)
1246 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1247 : #else
1248 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1249 : return;
1250 : #endif
1251 : }
1252 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1253 0 : if( _xparams.flags!=0x0 )
1254 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1255 0 : 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);
1256 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1257 0 : return;
1258 : }
1259 :
1260 : /*************************************************************************
1261 : LIMITED MEMORY BFGS METHOD FOR LARGE SCALE OPTIMIZATION
1262 :
1263 : DESCRIPTION:
1264 : The subroutine minimizes function F(x) of N arguments by using a quasi-
1265 : Newton method (LBFGS scheme) which is optimized to use a minimum amount
1266 : of memory.
1267 : The subroutine generates the approximation of an inverse Hessian matrix by
1268 : using information about the last M steps of the algorithm (instead of N).
1269 : It lessens a required amount of memory from a value of order N^2 to a
1270 : value of order 2*N*M.
1271 :
1272 :
1273 : REQUIREMENTS:
1274 : Algorithm will request following information during its operation:
1275 : * function value F and its gradient G (simultaneously) at given point X
1276 :
1277 :
1278 : USAGE:
1279 : 1. User initializes algorithm state with MinLBFGSCreate() call
1280 : 2. User tunes solver parameters with MinLBFGSSetCond() MinLBFGSSetStpMax()
1281 : and other functions
1282 : 3. User calls MinLBFGSOptimize() function which takes algorithm state and
1283 : pointer (delegate, etc.) to callback function which calculates F/G.
1284 : 4. User calls MinLBFGSResults() to get solution
1285 : 5. Optionally user may call MinLBFGSRestartFrom() to solve another problem
1286 : with same N/M but another starting point and/or another function.
1287 : MinLBFGSRestartFrom() allows to reuse already initialized structure.
1288 :
1289 :
1290 : INPUT PARAMETERS:
1291 : N - problem dimension. N>0
1292 : M - number of corrections in the BFGS scheme of Hessian
1293 : approximation update. Recommended value: 3<=M<=7. The smaller
1294 : value causes worse convergence, the bigger will not cause a
1295 : considerably better convergence, but will cause a fall in the
1296 : performance. M<=N.
1297 : X - initial solution approximation, array[0..N-1].
1298 :
1299 :
1300 : OUTPUT PARAMETERS:
1301 : State - structure which stores algorithm state
1302 :
1303 :
1304 : NOTES:
1305 : 1. you may tune stopping conditions with MinLBFGSSetCond() function
1306 : 2. if target function contains exp() or other fast growing functions, and
1307 : optimization algorithm makes too large steps which leads to overflow,
1308 : use MinLBFGSSetStpMax() function to bound algorithm's steps. However,
1309 : L-BFGS rarely needs such a tuning.
1310 :
1311 :
1312 : -- ALGLIB --
1313 : Copyright 02.04.2010 by Bochkanov Sergey
1314 : *************************************************************************/
1315 : #if !defined(AE_NO_EXCEPTIONS)
1316 498 : void minlbfgscreate(const ae_int_t m, const real_1d_array &x, minlbfgsstate &state, const xparams _xparams)
1317 : {
1318 : jmp_buf _break_jump;
1319 : alglib_impl::ae_state _alglib_env_state;
1320 : ae_int_t n;
1321 :
1322 498 : n = x.length();
1323 498 : alglib_impl::ae_state_init(&_alglib_env_state);
1324 498 : if( setjmp(_break_jump) )
1325 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1326 498 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1327 498 : if( _xparams.flags!=0x0 )
1328 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1329 498 : 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);
1330 :
1331 498 : alglib_impl::ae_state_clear(&_alglib_env_state);
1332 996 : return;
1333 : }
1334 : #endif
1335 :
1336 : /*************************************************************************
1337 : The subroutine is finite difference variant of MinLBFGSCreate(). It uses
1338 : finite differences in order to differentiate target function.
1339 :
1340 : Description below contains information which is specific to this function
1341 : only. We recommend to read comments on MinLBFGSCreate() in order to get
1342 : more information about creation of LBFGS optimizer.
1343 :
1344 : INPUT PARAMETERS:
1345 : N - problem dimension, N>0:
1346 : * if given, only leading N elements of X are used
1347 : * if not given, automatically determined from size of X
1348 : M - number of corrections in the BFGS scheme of Hessian
1349 : approximation update. Recommended value: 3<=M<=7. The smaller
1350 : value causes worse convergence, the bigger will not cause a
1351 : considerably better convergence, but will cause a fall in the
1352 : performance. M<=N.
1353 : X - starting point, array[0..N-1].
1354 : DiffStep- differentiation step, >0
1355 :
1356 : OUTPUT PARAMETERS:
1357 : State - structure which stores algorithm state
1358 :
1359 : NOTES:
1360 : 1. algorithm uses 4-point central formula for differentiation.
1361 : 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
1362 : S[] is scaling vector which can be set by MinLBFGSSetScale() call.
1363 : 3. we recommend you to use moderate values of differentiation step. Too
1364 : large step will result in too large truncation errors, while too small
1365 : step will result in too large numerical errors. 1.0E-6 can be good
1366 : value to start with.
1367 : 4. Numerical differentiation is very inefficient - one gradient
1368 : calculation needs 4*N function evaluations. This function will work for
1369 : any N - either small (1...10), moderate (10...100) or large (100...).
1370 : However, performance penalty will be too severe for any N's except for
1371 : small ones.
1372 : We should also say that code which relies on numerical differentiation
1373 : is less robust and precise. LBFGS needs exact gradient values.
1374 : Imprecise gradient may slow down convergence, especially on highly
1375 : nonlinear problems.
1376 : Thus we recommend to use this function for fast prototyping on small-
1377 : dimensional problems only, and to implement analytical gradient as soon
1378 : as possible.
1379 :
1380 : -- ALGLIB --
1381 : Copyright 16.05.2011 by Bochkanov Sergey
1382 : *************************************************************************/
1383 0 : void minlbfgscreatef(const ae_int_t n, const ae_int_t m, const real_1d_array &x, const double diffstep, minlbfgsstate &state, const xparams _xparams)
1384 : {
1385 : jmp_buf _break_jump;
1386 : alglib_impl::ae_state _alglib_env_state;
1387 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1388 0 : if( setjmp(_break_jump) )
1389 : {
1390 : #if !defined(AE_NO_EXCEPTIONS)
1391 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1392 : #else
1393 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1394 : return;
1395 : #endif
1396 : }
1397 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1398 0 : if( _xparams.flags!=0x0 )
1399 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1400 0 : 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);
1401 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1402 0 : return;
1403 : }
1404 :
1405 : /*************************************************************************
1406 : The subroutine is finite difference variant of MinLBFGSCreate(). It uses
1407 : finite differences in order to differentiate target function.
1408 :
1409 : Description below contains information which is specific to this function
1410 : only. We recommend to read comments on MinLBFGSCreate() in order to get
1411 : more information about creation of LBFGS optimizer.
1412 :
1413 : INPUT PARAMETERS:
1414 : N - problem dimension, N>0:
1415 : * if given, only leading N elements of X are used
1416 : * if not given, automatically determined from size of X
1417 : M - number of corrections in the BFGS scheme of Hessian
1418 : approximation update. Recommended value: 3<=M<=7. The smaller
1419 : value causes worse convergence, the bigger will not cause a
1420 : considerably better convergence, but will cause a fall in the
1421 : performance. M<=N.
1422 : X - starting point, array[0..N-1].
1423 : DiffStep- differentiation step, >0
1424 :
1425 : OUTPUT PARAMETERS:
1426 : State - structure which stores algorithm state
1427 :
1428 : NOTES:
1429 : 1. algorithm uses 4-point central formula for differentiation.
1430 : 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
1431 : S[] is scaling vector which can be set by MinLBFGSSetScale() call.
1432 : 3. we recommend you to use moderate values of differentiation step. Too
1433 : large step will result in too large truncation errors, while too small
1434 : step will result in too large numerical errors. 1.0E-6 can be good
1435 : value to start with.
1436 : 4. Numerical differentiation is very inefficient - one gradient
1437 : calculation needs 4*N function evaluations. This function will work for
1438 : any N - either small (1...10), moderate (10...100) or large (100...).
1439 : However, performance penalty will be too severe for any N's except for
1440 : small ones.
1441 : We should also say that code which relies on numerical differentiation
1442 : is less robust and precise. LBFGS needs exact gradient values.
1443 : Imprecise gradient may slow down convergence, especially on highly
1444 : nonlinear problems.
1445 : Thus we recommend to use this function for fast prototyping on small-
1446 : dimensional problems only, and to implement analytical gradient as soon
1447 : as possible.
1448 :
1449 : -- ALGLIB --
1450 : Copyright 16.05.2011 by Bochkanov Sergey
1451 : *************************************************************************/
1452 : #if !defined(AE_NO_EXCEPTIONS)
1453 0 : void minlbfgscreatef(const ae_int_t m, const real_1d_array &x, const double diffstep, minlbfgsstate &state, const xparams _xparams)
1454 : {
1455 : jmp_buf _break_jump;
1456 : alglib_impl::ae_state _alglib_env_state;
1457 : ae_int_t n;
1458 :
1459 0 : n = x.length();
1460 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1461 0 : if( setjmp(_break_jump) )
1462 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1463 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1464 0 : if( _xparams.flags!=0x0 )
1465 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1466 0 : 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);
1467 :
1468 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1469 0 : return;
1470 : }
1471 : #endif
1472 :
1473 : /*************************************************************************
1474 : This function sets stopping conditions for L-BFGS optimization algorithm.
1475 :
1476 : INPUT PARAMETERS:
1477 : State - structure which stores algorithm state
1478 : EpsG - >=0
1479 : The subroutine finishes its work if the condition
1480 : |v|<EpsG is satisfied, where:
1481 : * |.| means Euclidian norm
1482 : * v - scaled gradient vector, v[i]=g[i]*s[i]
1483 : * g - gradient
1484 : * s - scaling coefficients set by MinLBFGSSetScale()
1485 : EpsF - >=0
1486 : The subroutine finishes its work if on k+1-th iteration
1487 : the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
1488 : is satisfied.
1489 : EpsX - >=0
1490 : The subroutine finishes its work if on k+1-th iteration
1491 : the condition |v|<=EpsX is fulfilled, where:
1492 : * |.| means Euclidian norm
1493 : * v - scaled step vector, v[i]=dx[i]/s[i]
1494 : * dx - ste pvector, dx=X(k+1)-X(k)
1495 : * s - scaling coefficients set by MinLBFGSSetScale()
1496 : MaxIts - maximum number of iterations. If MaxIts=0, the number of
1497 : iterations is unlimited.
1498 :
1499 : Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to
1500 : automatic stopping criterion selection (small EpsX).
1501 :
1502 : -- ALGLIB --
1503 : Copyright 02.04.2010 by Bochkanov Sergey
1504 : *************************************************************************/
1505 498 : void minlbfgssetcond(const minlbfgsstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits, const xparams _xparams)
1506 : {
1507 : jmp_buf _break_jump;
1508 : alglib_impl::ae_state _alglib_env_state;
1509 498 : alglib_impl::ae_state_init(&_alglib_env_state);
1510 498 : if( setjmp(_break_jump) )
1511 : {
1512 : #if !defined(AE_NO_EXCEPTIONS)
1513 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1514 : #else
1515 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1516 : return;
1517 : #endif
1518 : }
1519 498 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1520 498 : if( _xparams.flags!=0x0 )
1521 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1522 498 : alglib_impl::minlbfgssetcond(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), epsg, epsf, epsx, maxits, &_alglib_env_state);
1523 498 : alglib_impl::ae_state_clear(&_alglib_env_state);
1524 996 : return;
1525 : }
1526 :
1527 : /*************************************************************************
1528 : This function turns on/off reporting.
1529 :
1530 : INPUT PARAMETERS:
1531 : State - structure which stores algorithm state
1532 : NeedXRep- whether iteration reports are needed or not
1533 :
1534 : If NeedXRep is True, algorithm will call rep() callback function if it is
1535 : provided to MinLBFGSOptimize().
1536 :
1537 :
1538 : -- ALGLIB --
1539 : Copyright 02.04.2010 by Bochkanov Sergey
1540 : *************************************************************************/
1541 0 : void minlbfgssetxrep(const minlbfgsstate &state, const bool needxrep, const xparams _xparams)
1542 : {
1543 : jmp_buf _break_jump;
1544 : alglib_impl::ae_state _alglib_env_state;
1545 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1546 0 : if( setjmp(_break_jump) )
1547 : {
1548 : #if !defined(AE_NO_EXCEPTIONS)
1549 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1550 : #else
1551 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1552 : return;
1553 : #endif
1554 : }
1555 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1556 0 : if( _xparams.flags!=0x0 )
1557 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1558 0 : alglib_impl::minlbfgssetxrep(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), needxrep, &_alglib_env_state);
1559 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1560 0 : return;
1561 : }
1562 :
1563 : /*************************************************************************
1564 : This function sets maximum step length
1565 :
1566 : INPUT PARAMETERS:
1567 : State - structure which stores algorithm state
1568 : StpMax - maximum step length, >=0. Set StpMax to 0.0 (default), if
1569 : you don't want to limit step length.
1570 :
1571 : Use this subroutine when you optimize target function which contains exp()
1572 : or other fast growing functions, and optimization algorithm makes too
1573 : large steps which leads to overflow. This function allows us to reject
1574 : steps that are too large (and therefore expose us to the possible
1575 : overflow) without actually calculating function value at the x+stp*d.
1576 :
1577 : -- ALGLIB --
1578 : Copyright 02.04.2010 by Bochkanov Sergey
1579 : *************************************************************************/
1580 0 : void minlbfgssetstpmax(const minlbfgsstate &state, const double stpmax, const xparams _xparams)
1581 : {
1582 : jmp_buf _break_jump;
1583 : alglib_impl::ae_state _alglib_env_state;
1584 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1585 0 : if( setjmp(_break_jump) )
1586 : {
1587 : #if !defined(AE_NO_EXCEPTIONS)
1588 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1589 : #else
1590 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1591 : return;
1592 : #endif
1593 : }
1594 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1595 0 : if( _xparams.flags!=0x0 )
1596 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1597 0 : alglib_impl::minlbfgssetstpmax(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), stpmax, &_alglib_env_state);
1598 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1599 0 : return;
1600 : }
1601 :
1602 : /*************************************************************************
1603 : This function sets scaling coefficients for LBFGS optimizer.
1604 :
1605 : ALGLIB optimizers use scaling matrices to test stopping conditions (step
1606 : size and gradient are scaled before comparison with tolerances). Scale of
1607 : the I-th variable is a translation invariant measure of:
1608 : a) "how large" the variable is
1609 : b) how large the step should be to make significant changes in the function
1610 :
1611 : Scaling is also used by finite difference variant of the optimizer - step
1612 : along I-th axis is equal to DiffStep*S[I].
1613 :
1614 : In most optimizers (and in the LBFGS too) scaling is NOT a form of
1615 : preconditioning. It just affects stopping conditions. You should set
1616 : preconditioner by separate call to one of the MinLBFGSSetPrec...()
1617 : functions.
1618 :
1619 : There is special preconditioning mode, however, which uses scaling
1620 : coefficients to form diagonal preconditioning matrix. You can turn this
1621 : mode on, if you want. But you should understand that scaling is not the
1622 : same thing as preconditioning - these are two different, although related
1623 : forms of tuning solver.
1624 :
1625 : INPUT PARAMETERS:
1626 : State - structure stores algorithm state
1627 : S - array[N], non-zero scaling coefficients
1628 : S[i] may be negative, sign doesn't matter.
1629 :
1630 : -- ALGLIB --
1631 : Copyright 14.01.2011 by Bochkanov Sergey
1632 : *************************************************************************/
1633 498 : void minlbfgssetscale(const minlbfgsstate &state, const real_1d_array &s, const xparams _xparams)
1634 : {
1635 : jmp_buf _break_jump;
1636 : alglib_impl::ae_state _alglib_env_state;
1637 498 : alglib_impl::ae_state_init(&_alglib_env_state);
1638 498 : if( setjmp(_break_jump) )
1639 : {
1640 : #if !defined(AE_NO_EXCEPTIONS)
1641 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1642 : #else
1643 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1644 : return;
1645 : #endif
1646 : }
1647 498 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1648 498 : if( _xparams.flags!=0x0 )
1649 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1650 498 : alglib_impl::minlbfgssetscale(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(s.c_ptr()), &_alglib_env_state);
1651 498 : alglib_impl::ae_state_clear(&_alglib_env_state);
1652 996 : return;
1653 : }
1654 :
1655 : /*************************************************************************
1656 : Modification of the preconditioner: default preconditioner (simple
1657 : scaling, same for all elements of X) is used.
1658 :
1659 : INPUT PARAMETERS:
1660 : State - structure which stores algorithm state
1661 :
1662 : NOTE: you can change preconditioner "on the fly", during algorithm
1663 : iterations.
1664 :
1665 : -- ALGLIB --
1666 : Copyright 13.10.2010 by Bochkanov Sergey
1667 : *************************************************************************/
1668 0 : void minlbfgssetprecdefault(const minlbfgsstate &state, const xparams _xparams)
1669 : {
1670 : jmp_buf _break_jump;
1671 : alglib_impl::ae_state _alglib_env_state;
1672 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1673 0 : if( setjmp(_break_jump) )
1674 : {
1675 : #if !defined(AE_NO_EXCEPTIONS)
1676 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1677 : #else
1678 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1679 : return;
1680 : #endif
1681 : }
1682 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1683 0 : if( _xparams.flags!=0x0 )
1684 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1685 0 : alglib_impl::minlbfgssetprecdefault(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), &_alglib_env_state);
1686 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1687 0 : return;
1688 : }
1689 :
1690 : /*************************************************************************
1691 : Modification of the preconditioner: Cholesky factorization of approximate
1692 : Hessian is used.
1693 :
1694 : INPUT PARAMETERS:
1695 : State - structure which stores algorithm state
1696 : P - triangular preconditioner, Cholesky factorization of
1697 : the approximate Hessian. array[0..N-1,0..N-1],
1698 : (if larger, only leading N elements are used).
1699 : IsUpper - whether upper or lower triangle of P is given
1700 : (other triangle is not referenced)
1701 :
1702 : After call to this function preconditioner is changed to P (P is copied
1703 : into the internal buffer).
1704 :
1705 : NOTE: you can change preconditioner "on the fly", during algorithm
1706 : iterations.
1707 :
1708 : NOTE 2: P should be nonsingular. Exception will be thrown otherwise.
1709 :
1710 : -- ALGLIB --
1711 : Copyright 13.10.2010 by Bochkanov Sergey
1712 : *************************************************************************/
1713 0 : void minlbfgssetpreccholesky(const minlbfgsstate &state, const real_2d_array &p, const bool isupper, const xparams _xparams)
1714 : {
1715 : jmp_buf _break_jump;
1716 : alglib_impl::ae_state _alglib_env_state;
1717 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1718 0 : if( setjmp(_break_jump) )
1719 : {
1720 : #if !defined(AE_NO_EXCEPTIONS)
1721 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1722 : #else
1723 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1724 : return;
1725 : #endif
1726 : }
1727 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1728 0 : if( _xparams.flags!=0x0 )
1729 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1730 0 : alglib_impl::minlbfgssetpreccholesky(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(p.c_ptr()), isupper, &_alglib_env_state);
1731 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1732 0 : return;
1733 : }
1734 :
1735 : /*************************************************************************
1736 : Modification of the preconditioner: diagonal of approximate Hessian is
1737 : used.
1738 :
1739 : INPUT PARAMETERS:
1740 : State - structure which stores algorithm state
1741 : D - diagonal of the approximate Hessian, array[0..N-1],
1742 : (if larger, only leading N elements are used).
1743 :
1744 : NOTE: you can change preconditioner "on the fly", during algorithm
1745 : iterations.
1746 :
1747 : NOTE 2: D[i] should be positive. Exception will be thrown otherwise.
1748 :
1749 : NOTE 3: you should pass diagonal of approximate Hessian - NOT ITS INVERSE.
1750 :
1751 : -- ALGLIB --
1752 : Copyright 13.10.2010 by Bochkanov Sergey
1753 : *************************************************************************/
1754 0 : void minlbfgssetprecdiag(const minlbfgsstate &state, const real_1d_array &d, const xparams _xparams)
1755 : {
1756 : jmp_buf _break_jump;
1757 : alglib_impl::ae_state _alglib_env_state;
1758 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1759 0 : if( setjmp(_break_jump) )
1760 : {
1761 : #if !defined(AE_NO_EXCEPTIONS)
1762 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1763 : #else
1764 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1765 : return;
1766 : #endif
1767 : }
1768 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1769 0 : if( _xparams.flags!=0x0 )
1770 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1771 0 : alglib_impl::minlbfgssetprecdiag(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(d.c_ptr()), &_alglib_env_state);
1772 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1773 0 : return;
1774 : }
1775 :
1776 : /*************************************************************************
1777 : Modification of the preconditioner: scale-based diagonal preconditioning.
1778 :
1779 : This preconditioning mode can be useful when you don't have approximate
1780 : diagonal of Hessian, but you know that your variables are badly scaled
1781 : (for example, one variable is in [1,10], and another in [1000,100000]),
1782 : and most part of the ill-conditioning comes from different scales of vars.
1783 :
1784 : In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2),
1785 : can greatly improve convergence.
1786 :
1787 : IMPRTANT: you should set scale of your variables with MinLBFGSSetScale()
1788 : call (before or after MinLBFGSSetPrecScale() call). Without knowledge of
1789 : the scale of your variables scale-based preconditioner will be just unit
1790 : matrix.
1791 :
1792 : INPUT PARAMETERS:
1793 : State - structure which stores algorithm state
1794 :
1795 : -- ALGLIB --
1796 : Copyright 13.10.2010 by Bochkanov Sergey
1797 : *************************************************************************/
1798 0 : void minlbfgssetprecscale(const minlbfgsstate &state, const xparams _xparams)
1799 : {
1800 : jmp_buf _break_jump;
1801 : alglib_impl::ae_state _alglib_env_state;
1802 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1803 0 : if( setjmp(_break_jump) )
1804 : {
1805 : #if !defined(AE_NO_EXCEPTIONS)
1806 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1807 : #else
1808 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1809 : return;
1810 : #endif
1811 : }
1812 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1813 0 : if( _xparams.flags!=0x0 )
1814 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1815 0 : alglib_impl::minlbfgssetprecscale(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), &_alglib_env_state);
1816 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1817 0 : return;
1818 : }
1819 :
1820 : /*************************************************************************
1821 : This function provides reverse communication interface
1822 : Reverse communication interface is not documented or recommended to use.
1823 : See below for functions which provide better documented API
1824 : *************************************************************************/
1825 0 : bool minlbfgsiteration(const minlbfgsstate &state, const xparams _xparams)
1826 : {
1827 : jmp_buf _break_jump;
1828 : alglib_impl::ae_state _alglib_env_state;
1829 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1830 0 : if( setjmp(_break_jump) )
1831 : {
1832 : #if !defined(AE_NO_EXCEPTIONS)
1833 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1834 : #else
1835 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1836 : return 0;
1837 : #endif
1838 : }
1839 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1840 0 : if( _xparams.flags!=0x0 )
1841 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1842 0 : ae_bool result = alglib_impl::minlbfgsiteration(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), &_alglib_env_state);
1843 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1844 0 : return *(reinterpret_cast<bool*>(&result));
1845 : }
1846 :
1847 :
1848 0 : void minlbfgsoptimize(minlbfgsstate &state,
1849 : void (*func)(const real_1d_array &x, double &func, void *ptr),
1850 : void (*rep)(const real_1d_array &x, double func, void *ptr),
1851 : void *ptr,
1852 : const xparams _xparams)
1853 : {
1854 : jmp_buf _break_jump;
1855 : alglib_impl::ae_state _alglib_env_state;
1856 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1857 0 : if( setjmp(_break_jump) )
1858 : {
1859 : #if !defined(AE_NO_EXCEPTIONS)
1860 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1861 : #else
1862 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1863 : return;
1864 : #endif
1865 : }
1866 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1867 0 : if( _xparams.flags!=0x0 )
1868 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1869 0 : alglib_impl::ae_assert(func!=NULL, "ALGLIB: error in 'minlbfgsoptimize()' (func is NULL)", &_alglib_env_state);
1870 0 : while( alglib_impl::minlbfgsiteration(state.c_ptr(), &_alglib_env_state) )
1871 : {
1872 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN
1873 0 : if( state.needf )
1874 : {
1875 0 : func(state.x, state.f, ptr);
1876 0 : continue;
1877 : }
1878 0 : if( state.xupdated )
1879 : {
1880 0 : if( rep!=NULL )
1881 0 : rep(state.x, state.f, ptr);
1882 0 : continue;
1883 : }
1884 0 : goto lbl_no_callback;
1885 0 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_END
1886 0 : lbl_no_callback:
1887 0 : alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minlbfgsoptimize' (some derivatives were not provided?)", &_alglib_env_state);
1888 : }
1889 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1890 0 : }
1891 :
1892 :
1893 498 : void minlbfgsoptimize(minlbfgsstate &state,
1894 : void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr),
1895 : void (*rep)(const real_1d_array &x, double func, void *ptr),
1896 : void *ptr,
1897 : const xparams _xparams)
1898 : {
1899 : jmp_buf _break_jump;
1900 : alglib_impl::ae_state _alglib_env_state;
1901 498 : alglib_impl::ae_state_init(&_alglib_env_state);
1902 498 : if( setjmp(_break_jump) )
1903 : {
1904 : #if !defined(AE_NO_EXCEPTIONS)
1905 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1906 : #else
1907 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1908 : return;
1909 : #endif
1910 : }
1911 498 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1912 498 : if( _xparams.flags!=0x0 )
1913 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1914 498 : alglib_impl::ae_assert(grad!=NULL, "ALGLIB: error in 'minlbfgsoptimize()' (grad is NULL)", &_alglib_env_state);
1915 5387 : while( alglib_impl::minlbfgsiteration(state.c_ptr(), &_alglib_env_state) )
1916 : {
1917 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN
1918 4889 : if( state.needfg )
1919 : {
1920 4889 : grad(state.x, state.f, state.g, ptr);
1921 4889 : continue;
1922 : }
1923 0 : if( state.xupdated )
1924 : {
1925 0 : if( rep!=NULL )
1926 0 : rep(state.x, state.f, ptr);
1927 0 : continue;
1928 : }
1929 0 : goto lbl_no_callback;
1930 0 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_END
1931 0 : lbl_no_callback:
1932 0 : alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minlbfgsoptimize' (some derivatives were not provided?)", &_alglib_env_state);
1933 : }
1934 498 : alglib_impl::ae_state_clear(&_alglib_env_state);
1935 498 : }
1936 :
1937 :
1938 :
1939 : /*************************************************************************
1940 : This function activates/deactivates verification of the user-supplied
1941 : analytic gradient.
1942 :
1943 : Upon activation of this option OptGuard integrity checker performs
1944 : numerical differentiation of your target function at the initial point
1945 : (note: future versions may also perform check at the final point) and
1946 : compares numerical gradient with analytic one provided by you.
1947 :
1948 : If difference is too large, an error flag is set and optimization session
1949 : continues. After optimization session is over, you can retrieve the report
1950 : which stores both gradients and specific components highlighted as
1951 : suspicious by the OptGuard.
1952 :
1953 : The primary OptGuard report can be retrieved with minlbfgsoptguardresults().
1954 :
1955 : IMPORTANT: gradient check is a high-overhead option which will cost you
1956 : about 3*N additional function evaluations. In many cases it may
1957 : cost as much as the rest of the optimization session.
1958 :
1959 : YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO
1960 : CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY.
1961 :
1962 : NOTE: unlike previous incarnation of the gradient checking code, OptGuard
1963 : does NOT interrupt optimization even if it discovers bad gradient.
1964 :
1965 : INPUT PARAMETERS:
1966 : State - structure used to store algorithm state
1967 : TestStep - verification step used for numerical differentiation:
1968 : * TestStep=0 turns verification off
1969 : * TestStep>0 activates verification
1970 : You should carefully choose TestStep. Value which is
1971 : too large (so large that function behavior is non-
1972 : cubic at this scale) will lead to false alarms. Too
1973 : short step will result in rounding errors dominating
1974 : numerical derivative.
1975 :
1976 : You may use different step for different parameters by
1977 : means of setting scale with minlbfgssetscale().
1978 :
1979 : === EXPLANATION ==========================================================
1980 :
1981 : In order to verify gradient algorithm performs following steps:
1982 : * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i],
1983 : where X[i] is i-th component of the initial point and S[i] is a scale
1984 : of i-th parameter
1985 : * F(X) is evaluated at these trial points
1986 : * we perform one more evaluation in the middle point of the interval
1987 : * we build cubic model using function values and derivatives at trial
1988 : points and we compare its prediction with actual value in the middle
1989 : point
1990 :
1991 : -- ALGLIB --
1992 : Copyright 15.06.2014 by Bochkanov Sergey
1993 : *************************************************************************/
1994 0 : void minlbfgsoptguardgradient(const minlbfgsstate &state, const double teststep, const xparams _xparams)
1995 : {
1996 : jmp_buf _break_jump;
1997 : alglib_impl::ae_state _alglib_env_state;
1998 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1999 0 : if( setjmp(_break_jump) )
2000 : {
2001 : #if !defined(AE_NO_EXCEPTIONS)
2002 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2003 : #else
2004 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2005 : return;
2006 : #endif
2007 : }
2008 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2009 0 : if( _xparams.flags!=0x0 )
2010 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2011 0 : alglib_impl::minlbfgsoptguardgradient(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), teststep, &_alglib_env_state);
2012 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2013 0 : return;
2014 : }
2015 :
2016 : /*************************************************************************
2017 : This function activates/deactivates nonsmoothness monitoring option of
2018 : the OptGuard integrity checker. Smoothness monitor silently observes
2019 : solution process and tries to detect ill-posed problems, i.e. ones with:
2020 : a) discontinuous target function (non-C0)
2021 : b) nonsmooth target function (non-C1)
2022 :
2023 : Smoothness monitoring does NOT interrupt optimization even if it suspects
2024 : that your problem is nonsmooth. It just sets corresponding flags in the
2025 : OptGuard report which can be retrieved after optimization is over.
2026 :
2027 : Smoothness monitoring is a moderate overhead option which often adds less
2028 : than 1% to the optimizer running time. Thus, you can use it even for large
2029 : scale problems.
2030 :
2031 : NOTE: OptGuard does NOT guarantee that it will always detect C0/C1
2032 : continuity violations.
2033 :
2034 : First, minor errors are hard to catch - say, a 0.0001 difference in
2035 : the model values at two sides of the gap may be due to discontinuity
2036 : of the model - or simply because the model has changed.
2037 :
2038 : Second, C1-violations are especially difficult to detect in a
2039 : noninvasive way. The optimizer usually performs very short steps
2040 : near the nonsmoothness, and differentiation usually introduces a
2041 : lot of numerical noise. It is hard to tell whether some tiny
2042 : discontinuity in the slope is due to real nonsmoothness or just due
2043 : to numerical noise alone.
2044 :
2045 : Our top priority was to avoid false positives, so in some rare cases
2046 : minor errors may went unnoticed (however, in most cases they can be
2047 : spotted with restart from different initial point).
2048 :
2049 : INPUT PARAMETERS:
2050 : state - algorithm state
2051 : level - monitoring level:
2052 : * 0 - monitoring is disabled
2053 : * 1 - noninvasive low-overhead monitoring; function values
2054 : and/or gradients are recorded, but OptGuard does not
2055 : try to perform additional evaluations in order to
2056 : get more information about suspicious locations.
2057 :
2058 : === EXPLANATION ==========================================================
2059 :
2060 : One major source of headache during optimization is the possibility of
2061 : the coding errors in the target function/constraints (or their gradients).
2062 : Such errors most often manifest themselves as discontinuity or
2063 : nonsmoothness of the target/constraints.
2064 :
2065 : Another frequent situation is when you try to optimize something involving
2066 : lots of min() and max() operations, i.e. nonsmooth target. Although not a
2067 : coding error, it is nonsmoothness anyway - and smooth optimizers usually
2068 : stop right after encountering nonsmoothness, well before reaching solution.
2069 :
2070 : OptGuard integrity checker helps you to catch such situations: it monitors
2071 : function values/gradients being passed to the optimizer and tries to
2072 : errors. Upon discovering suspicious pair of points it raises appropriate
2073 : flag (and allows you to continue optimization). When optimization is done,
2074 : you can study OptGuard result.
2075 :
2076 : -- ALGLIB --
2077 : Copyright 21.11.2018 by Bochkanov Sergey
2078 : *************************************************************************/
2079 0 : void minlbfgsoptguardsmoothness(const minlbfgsstate &state, const ae_int_t level, const xparams _xparams)
2080 : {
2081 : jmp_buf _break_jump;
2082 : alglib_impl::ae_state _alglib_env_state;
2083 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2084 0 : if( setjmp(_break_jump) )
2085 : {
2086 : #if !defined(AE_NO_EXCEPTIONS)
2087 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2088 : #else
2089 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2090 : return;
2091 : #endif
2092 : }
2093 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2094 0 : if( _xparams.flags!=0x0 )
2095 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2096 0 : alglib_impl::minlbfgsoptguardsmoothness(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), level, &_alglib_env_state);
2097 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2098 0 : return;
2099 : }
2100 :
2101 : /*************************************************************************
2102 : This function activates/deactivates nonsmoothness monitoring option of
2103 : the OptGuard integrity checker. Smoothness monitor silently observes
2104 : solution process and tries to detect ill-posed problems, i.e. ones with:
2105 : a) discontinuous target function (non-C0)
2106 : b) nonsmooth target function (non-C1)
2107 :
2108 : Smoothness monitoring does NOT interrupt optimization even if it suspects
2109 : that your problem is nonsmooth. It just sets corresponding flags in the
2110 : OptGuard report which can be retrieved after optimization is over.
2111 :
2112 : Smoothness monitoring is a moderate overhead option which often adds less
2113 : than 1% to the optimizer running time. Thus, you can use it even for large
2114 : scale problems.
2115 :
2116 : NOTE: OptGuard does NOT guarantee that it will always detect C0/C1
2117 : continuity violations.
2118 :
2119 : First, minor errors are hard to catch - say, a 0.0001 difference in
2120 : the model values at two sides of the gap may be due to discontinuity
2121 : of the model - or simply because the model has changed.
2122 :
2123 : Second, C1-violations are especially difficult to detect in a
2124 : noninvasive way. The optimizer usually performs very short steps
2125 : near the nonsmoothness, and differentiation usually introduces a
2126 : lot of numerical noise. It is hard to tell whether some tiny
2127 : discontinuity in the slope is due to real nonsmoothness or just due
2128 : to numerical noise alone.
2129 :
2130 : Our top priority was to avoid false positives, so in some rare cases
2131 : minor errors may went unnoticed (however, in most cases they can be
2132 : spotted with restart from different initial point).
2133 :
2134 : INPUT PARAMETERS:
2135 : state - algorithm state
2136 : level - monitoring level:
2137 : * 0 - monitoring is disabled
2138 : * 1 - noninvasive low-overhead monitoring; function values
2139 : and/or gradients are recorded, but OptGuard does not
2140 : try to perform additional evaluations in order to
2141 : get more information about suspicious locations.
2142 :
2143 : === EXPLANATION ==========================================================
2144 :
2145 : One major source of headache during optimization is the possibility of
2146 : the coding errors in the target function/constraints (or their gradients).
2147 : Such errors most often manifest themselves as discontinuity or
2148 : nonsmoothness of the target/constraints.
2149 :
2150 : Another frequent situation is when you try to optimize something involving
2151 : lots of min() and max() operations, i.e. nonsmooth target. Although not a
2152 : coding error, it is nonsmoothness anyway - and smooth optimizers usually
2153 : stop right after encountering nonsmoothness, well before reaching solution.
2154 :
2155 : OptGuard integrity checker helps you to catch such situations: it monitors
2156 : function values/gradients being passed to the optimizer and tries to
2157 : errors. Upon discovering suspicious pair of points it raises appropriate
2158 : flag (and allows you to continue optimization). When optimization is done,
2159 : you can study OptGuard result.
2160 :
2161 : -- ALGLIB --
2162 : Copyright 21.11.2018 by Bochkanov Sergey
2163 : *************************************************************************/
2164 : #if !defined(AE_NO_EXCEPTIONS)
2165 0 : void minlbfgsoptguardsmoothness(const minlbfgsstate &state, const xparams _xparams)
2166 : {
2167 : jmp_buf _break_jump;
2168 : alglib_impl::ae_state _alglib_env_state;
2169 : ae_int_t level;
2170 :
2171 0 : level = 1;
2172 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2173 0 : if( setjmp(_break_jump) )
2174 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2175 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2176 0 : if( _xparams.flags!=0x0 )
2177 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2178 0 : alglib_impl::minlbfgsoptguardsmoothness(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), level, &_alglib_env_state);
2179 :
2180 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2181 0 : return;
2182 : }
2183 : #endif
2184 :
2185 : /*************************************************************************
2186 : Results of OptGuard integrity check, should be called after optimization
2187 : session is over.
2188 :
2189 : === PRIMARY REPORT =======================================================
2190 :
2191 : OptGuard performs several checks which are intended to catch common errors
2192 : in the implementation of nonlinear function/gradient:
2193 : * incorrect analytic gradient
2194 : * discontinuous (non-C0) target functions (constraints)
2195 : * nonsmooth (non-C1) target functions (constraints)
2196 :
2197 : Each of these checks is activated with appropriate function:
2198 : * minlbfgsoptguardgradient() for gradient verification
2199 : * minlbfgsoptguardsmoothness() for C0/C1 checks
2200 :
2201 : Following flags are set when these errors are suspected:
2202 : * rep.badgradsuspected, and additionally:
2203 : * rep.badgradvidx for specific variable (gradient element) suspected
2204 : * rep.badgradxbase, a point where gradient is tested
2205 : * rep.badgraduser, user-provided gradient (stored as 2D matrix with
2206 : single row in order to make report structure compatible with more
2207 : complex optimizers like MinNLC or MinLM)
2208 : * rep.badgradnum, reference gradient obtained via numerical
2209 : differentiation (stored as 2D matrix with single row in order to make
2210 : report structure compatible with more complex optimizers like MinNLC
2211 : or MinLM)
2212 : * rep.nonc0suspected
2213 : * rep.nonc1suspected
2214 :
2215 : === ADDITIONAL REPORTS/LOGS ==============================================
2216 :
2217 : Several different tests are performed to catch C0/C1 errors, you can find
2218 : out specific test signaled error by looking to:
2219 : * rep.nonc0test0positive, for non-C0 test #0
2220 : * rep.nonc1test0positive, for non-C1 test #0
2221 : * rep.nonc1test1positive, for non-C1 test #1
2222 :
2223 : Additional information (including line search logs) can be obtained by
2224 : means of:
2225 : * minlbfgsoptguardnonc1test0results()
2226 : * minlbfgsoptguardnonc1test1results()
2227 : which return detailed error reports, specific points where discontinuities
2228 : were found, and so on.
2229 :
2230 : ==========================================================================
2231 :
2232 : INPUT PARAMETERS:
2233 : state - algorithm state
2234 :
2235 : OUTPUT PARAMETERS:
2236 : rep - generic OptGuard report; more detailed reports can be
2237 : retrieved with other functions.
2238 :
2239 : NOTE: false negatives (nonsmooth problems are not identified as nonsmooth
2240 : ones) are possible although unlikely.
2241 :
2242 : The reason is that you need to make several evaluations around
2243 : nonsmoothness in order to accumulate enough information about
2244 : function curvature. Say, if you start right from the nonsmooth point,
2245 : optimizer simply won't get enough data to understand what is going
2246 : wrong before it terminates due to abrupt changes in the derivative.
2247 : It is also possible that "unlucky" step will move us to the
2248 : termination too quickly.
2249 :
2250 : Our current approach is to have less than 0.1% false negatives in
2251 : our test examples (measured with multiple restarts from random
2252 : points), and to have exactly 0% false positives.
2253 :
2254 : -- ALGLIB --
2255 : Copyright 21.11.2018 by Bochkanov Sergey
2256 : *************************************************************************/
2257 0 : void minlbfgsoptguardresults(const minlbfgsstate &state, optguardreport &rep, const xparams _xparams)
2258 : {
2259 : jmp_buf _break_jump;
2260 : alglib_impl::ae_state _alglib_env_state;
2261 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2262 0 : if( setjmp(_break_jump) )
2263 : {
2264 : #if !defined(AE_NO_EXCEPTIONS)
2265 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2266 : #else
2267 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2268 : return;
2269 : #endif
2270 : }
2271 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2272 0 : if( _xparams.flags!=0x0 )
2273 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2274 0 : alglib_impl::minlbfgsoptguardresults(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), const_cast<alglib_impl::optguardreport*>(rep.c_ptr()), &_alglib_env_state);
2275 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2276 0 : return;
2277 : }
2278 :
2279 : /*************************************************************************
2280 : Detailed results of the OptGuard integrity check for nonsmoothness test #0
2281 :
2282 : Nonsmoothness (non-C1) test #0 studies function values (not gradient!)
2283 : obtained during line searches and monitors behavior of the directional
2284 : derivative estimate.
2285 :
2286 : This test is less powerful than test #1, but it does not depend on the
2287 : gradient values and thus it is more robust against artifacts introduced by
2288 : numerical differentiation.
2289 :
2290 : Two reports are returned:
2291 : * a "strongest" one, corresponding to line search which had highest
2292 : value of the nonsmoothness indicator
2293 : * a "longest" one, corresponding to line search which had more function
2294 : evaluations, and thus is more detailed
2295 :
2296 : In both cases following fields are returned:
2297 :
2298 : * positive - is TRUE when test flagged suspicious point; FALSE if test
2299 : did not notice anything (in the latter cases fields below are empty).
2300 : * x0[], d[] - arrays of length N which store initial point and direction
2301 : for line search (d[] can be normalized, but does not have to)
2302 : * stp[], f[] - arrays of length CNT which store step lengths and function
2303 : values at these points; f[i] is evaluated in x0+stp[i]*d.
2304 : * stpidxa, stpidxb - we suspect that function violates C1 continuity
2305 : between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3,
2306 : with most likely position of the violation between stpidxa+1 and
2307 : stpidxa+2.
2308 :
2309 : ==========================================================================
2310 : = SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will
2311 : = see where C1 continuity is violated.
2312 : ==========================================================================
2313 :
2314 : INPUT PARAMETERS:
2315 : state - algorithm state
2316 :
2317 : OUTPUT PARAMETERS:
2318 : strrep - C1 test #0 "strong" report
2319 : lngrep - C1 test #0 "long" report
2320 :
2321 : -- ALGLIB --
2322 : Copyright 21.11.2018 by Bochkanov Sergey
2323 : *************************************************************************/
2324 0 : void minlbfgsoptguardnonc1test0results(const minlbfgsstate &state, optguardnonc1test0report &strrep, optguardnonc1test0report &lngrep, const xparams _xparams)
2325 : {
2326 : jmp_buf _break_jump;
2327 : alglib_impl::ae_state _alglib_env_state;
2328 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2329 0 : if( setjmp(_break_jump) )
2330 : {
2331 : #if !defined(AE_NO_EXCEPTIONS)
2332 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2333 : #else
2334 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2335 : return;
2336 : #endif
2337 : }
2338 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2339 0 : if( _xparams.flags!=0x0 )
2340 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2341 0 : alglib_impl::minlbfgsoptguardnonc1test0results(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), const_cast<alglib_impl::optguardnonc1test0report*>(strrep.c_ptr()), const_cast<alglib_impl::optguardnonc1test0report*>(lngrep.c_ptr()), &_alglib_env_state);
2342 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2343 0 : return;
2344 : }
2345 :
2346 : /*************************************************************************
2347 : Detailed results of the OptGuard integrity check for nonsmoothness test #1
2348 :
2349 : Nonsmoothness (non-C1) test #1 studies individual components of the
2350 : gradient computed during line search.
2351 :
2352 : When precise analytic gradient is provided this test is more powerful than
2353 : test #0 which works with function values and ignores user-provided
2354 : gradient. However, test #0 becomes more powerful when numerical
2355 : differentiation is employed (in such cases test #1 detects higher levels
2356 : of numerical noise and becomes too conservative).
2357 :
2358 : This test also tells specific components of the gradient which violate C1
2359 : continuity, which makes it more informative than #0, which just tells that
2360 : continuity is violated.
2361 :
2362 : Two reports are returned:
2363 : * a "strongest" one, corresponding to line search which had highest
2364 : value of the nonsmoothness indicator
2365 : * a "longest" one, corresponding to line search which had more function
2366 : evaluations, and thus is more detailed
2367 :
2368 : In both cases following fields are returned:
2369 :
2370 : * positive - is TRUE when test flagged suspicious point; FALSE if test
2371 : did not notice anything (in the latter cases fields below are empty).
2372 : * vidx - is an index of the variable in [0,N) with nonsmooth derivative
2373 : * x0[], d[] - arrays of length N which store initial point and direction
2374 : for line search (d[] can be normalized, but does not have to)
2375 : * stp[], g[] - arrays of length CNT which store step lengths and gradient
2376 : values at these points; g[i] is evaluated in x0+stp[i]*d and contains
2377 : vidx-th component of the gradient.
2378 : * stpidxa, stpidxb - we suspect that function violates C1 continuity
2379 : between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3,
2380 : with most likely position of the violation between stpidxa+1 and
2381 : stpidxa+2.
2382 :
2383 : ==========================================================================
2384 : = SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will
2385 : = see where C1 continuity is violated.
2386 : ==========================================================================
2387 :
2388 : INPUT PARAMETERS:
2389 : state - algorithm state
2390 :
2391 : OUTPUT PARAMETERS:
2392 : strrep - C1 test #1 "strong" report
2393 : lngrep - C1 test #1 "long" report
2394 :
2395 : -- ALGLIB --
2396 : Copyright 21.11.2018 by Bochkanov Sergey
2397 : *************************************************************************/
2398 0 : void minlbfgsoptguardnonc1test1results(const minlbfgsstate &state, optguardnonc1test1report &strrep, optguardnonc1test1report &lngrep, const xparams _xparams)
2399 : {
2400 : jmp_buf _break_jump;
2401 : alglib_impl::ae_state _alglib_env_state;
2402 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2403 0 : if( setjmp(_break_jump) )
2404 : {
2405 : #if !defined(AE_NO_EXCEPTIONS)
2406 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2407 : #else
2408 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2409 : return;
2410 : #endif
2411 : }
2412 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2413 0 : if( _xparams.flags!=0x0 )
2414 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2415 0 : alglib_impl::minlbfgsoptguardnonc1test1results(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), const_cast<alglib_impl::optguardnonc1test1report*>(strrep.c_ptr()), const_cast<alglib_impl::optguardnonc1test1report*>(lngrep.c_ptr()), &_alglib_env_state);
2416 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2417 0 : return;
2418 : }
2419 :
2420 : /*************************************************************************
2421 : L-BFGS algorithm results
2422 :
2423 : INPUT PARAMETERS:
2424 : State - algorithm state
2425 :
2426 : OUTPUT PARAMETERS:
2427 : X - array[0..N-1], solution
2428 : Rep - optimization report:
2429 : * Rep.TerminationType completetion code:
2430 : * -8 internal integrity control detected infinite
2431 : or NAN values in function/gradient. Abnormal
2432 : termination signalled.
2433 : * -2 rounding errors prevent further improvement.
2434 : X contains best point found.
2435 : * -1 incorrect parameters were specified
2436 : * 1 relative function improvement is no more than
2437 : EpsF.
2438 : * 2 relative step is no more than EpsX.
2439 : * 4 gradient norm is no more than EpsG
2440 : * 5 MaxIts steps was taken
2441 : * 7 stopping conditions are too stringent,
2442 : further improvement is impossible
2443 : * 8 terminated by user who called minlbfgsrequesttermination().
2444 : X contains point which was "current accepted" when
2445 : termination request was submitted.
2446 : * Rep.IterationsCount contains iterations count
2447 : * NFEV countains number of function calculations
2448 :
2449 : -- ALGLIB --
2450 : Copyright 02.04.2010 by Bochkanov Sergey
2451 : *************************************************************************/
2452 498 : void minlbfgsresults(const minlbfgsstate &state, real_1d_array &x, minlbfgsreport &rep, const xparams _xparams)
2453 : {
2454 : jmp_buf _break_jump;
2455 : alglib_impl::ae_state _alglib_env_state;
2456 498 : alglib_impl::ae_state_init(&_alglib_env_state);
2457 498 : if( setjmp(_break_jump) )
2458 : {
2459 : #if !defined(AE_NO_EXCEPTIONS)
2460 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2461 : #else
2462 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2463 : return;
2464 : #endif
2465 : }
2466 498 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2467 498 : if( _xparams.flags!=0x0 )
2468 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2469 498 : 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);
2470 498 : alglib_impl::ae_state_clear(&_alglib_env_state);
2471 996 : return;
2472 : }
2473 :
2474 : /*************************************************************************
2475 : L-BFGS algorithm results
2476 :
2477 : Buffered implementation of MinLBFGSResults which uses pre-allocated buffer
2478 : to store X[]. If buffer size is too small, it resizes buffer. It is
2479 : intended to be used in the inner cycles of performance critical algorithms
2480 : where array reallocation penalty is too large to be ignored.
2481 :
2482 : -- ALGLIB --
2483 : Copyright 20.08.2010 by Bochkanov Sergey
2484 : *************************************************************************/
2485 0 : void minlbfgsresultsbuf(const minlbfgsstate &state, real_1d_array &x, minlbfgsreport &rep, const xparams _xparams)
2486 : {
2487 : jmp_buf _break_jump;
2488 : alglib_impl::ae_state _alglib_env_state;
2489 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2490 0 : if( setjmp(_break_jump) )
2491 : {
2492 : #if !defined(AE_NO_EXCEPTIONS)
2493 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2494 : #else
2495 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2496 : return;
2497 : #endif
2498 : }
2499 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2500 0 : if( _xparams.flags!=0x0 )
2501 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2502 0 : 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);
2503 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2504 0 : return;
2505 : }
2506 :
2507 : /*************************************************************************
2508 : This subroutine restarts LBFGS algorithm from new point. All optimization
2509 : parameters are left unchanged.
2510 :
2511 : This function allows to solve multiple optimization problems (which
2512 : must have same number of dimensions) without object reallocation penalty.
2513 :
2514 : INPUT PARAMETERS:
2515 : State - structure used to store algorithm state
2516 : X - new starting point.
2517 :
2518 : -- ALGLIB --
2519 : Copyright 30.07.2010 by Bochkanov Sergey
2520 : *************************************************************************/
2521 0 : void minlbfgsrestartfrom(const minlbfgsstate &state, const real_1d_array &x, const xparams _xparams)
2522 : {
2523 : jmp_buf _break_jump;
2524 : alglib_impl::ae_state _alglib_env_state;
2525 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2526 0 : if( setjmp(_break_jump) )
2527 : {
2528 : #if !defined(AE_NO_EXCEPTIONS)
2529 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2530 : #else
2531 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2532 : return;
2533 : #endif
2534 : }
2535 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2536 0 : if( _xparams.flags!=0x0 )
2537 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2538 0 : alglib_impl::minlbfgsrestartfrom(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
2539 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2540 0 : return;
2541 : }
2542 :
2543 : /*************************************************************************
2544 : This subroutine submits request for termination of running optimizer. It
2545 : should be called from user-supplied callback when user decides that it is
2546 : time to "smoothly" terminate optimization process. As result, optimizer
2547 : stops at point which was "current accepted" when termination request was
2548 : submitted and returns error code 8 (successful termination).
2549 :
2550 : INPUT PARAMETERS:
2551 : State - optimizer structure
2552 :
2553 : NOTE: after request for termination optimizer may perform several
2554 : additional calls to user-supplied callbacks. It does NOT guarantee
2555 : to stop immediately - it just guarantees that these additional calls
2556 : will be discarded later.
2557 :
2558 : NOTE: calling this function on optimizer which is NOT running will have no
2559 : effect.
2560 :
2561 : NOTE: multiple calls to this function are possible. First call is counted,
2562 : subsequent calls are silently ignored.
2563 :
2564 : -- ALGLIB --
2565 : Copyright 08.10.2014 by Bochkanov Sergey
2566 : *************************************************************************/
2567 0 : void minlbfgsrequesttermination(const minlbfgsstate &state, const xparams _xparams)
2568 : {
2569 : jmp_buf _break_jump;
2570 : alglib_impl::ae_state _alglib_env_state;
2571 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2572 0 : if( setjmp(_break_jump) )
2573 : {
2574 : #if !defined(AE_NO_EXCEPTIONS)
2575 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2576 : #else
2577 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2578 : return;
2579 : #endif
2580 : }
2581 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2582 0 : if( _xparams.flags!=0x0 )
2583 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2584 0 : alglib_impl::minlbfgsrequesttermination(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), &_alglib_env_state);
2585 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2586 0 : return;
2587 : }
2588 : #endif
2589 :
2590 : #if defined(AE_COMPILE_LPQPSERV) || !defined(AE_PARTIAL_BUILD)
2591 :
2592 : #endif
2593 :
2594 : #if defined(AE_COMPILE_VIPMSOLVER) || !defined(AE_PARTIAL_BUILD)
2595 :
2596 : #endif
2597 :
2598 : #if defined(AE_COMPILE_NLCSQP) || !defined(AE_PARTIAL_BUILD)
2599 :
2600 : #endif
2601 :
2602 : #if defined(AE_COMPILE_QPDENSEAULSOLVER) || !defined(AE_PARTIAL_BUILD)
2603 :
2604 : #endif
2605 :
2606 : #if defined(AE_COMPILE_MINBLEIC) || !defined(AE_PARTIAL_BUILD)
2607 : /*************************************************************************
2608 : This object stores nonlinear optimizer state.
2609 : You should use functions provided by MinBLEIC subpackage to work with this
2610 : object
2611 : *************************************************************************/
2612 0 : _minbleicstate_owner::_minbleicstate_owner()
2613 : {
2614 : jmp_buf _break_jump;
2615 : alglib_impl::ae_state _state;
2616 :
2617 0 : alglib_impl::ae_state_init(&_state);
2618 0 : if( setjmp(_break_jump) )
2619 : {
2620 0 : if( p_struct!=NULL )
2621 : {
2622 0 : alglib_impl::_minbleicstate_destroy(p_struct);
2623 0 : alglib_impl::ae_free(p_struct);
2624 : }
2625 0 : p_struct = NULL;
2626 : #if !defined(AE_NO_EXCEPTIONS)
2627 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
2628 : #else
2629 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
2630 : return;
2631 : #endif
2632 : }
2633 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
2634 0 : p_struct = NULL;
2635 0 : p_struct = (alglib_impl::minbleicstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minbleicstate), &_state);
2636 0 : memset(p_struct, 0, sizeof(alglib_impl::minbleicstate));
2637 0 : alglib_impl::_minbleicstate_init(p_struct, &_state, ae_false);
2638 0 : ae_state_clear(&_state);
2639 0 : }
2640 :
2641 0 : _minbleicstate_owner::_minbleicstate_owner(const _minbleicstate_owner &rhs)
2642 : {
2643 : jmp_buf _break_jump;
2644 : alglib_impl::ae_state _state;
2645 :
2646 0 : alglib_impl::ae_state_init(&_state);
2647 0 : if( setjmp(_break_jump) )
2648 : {
2649 0 : if( p_struct!=NULL )
2650 : {
2651 0 : alglib_impl::_minbleicstate_destroy(p_struct);
2652 0 : alglib_impl::ae_free(p_struct);
2653 : }
2654 0 : p_struct = NULL;
2655 : #if !defined(AE_NO_EXCEPTIONS)
2656 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
2657 : #else
2658 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
2659 : return;
2660 : #endif
2661 : }
2662 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
2663 0 : p_struct = NULL;
2664 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minbleicstate copy constructor failure (source is not initialized)", &_state);
2665 0 : p_struct = (alglib_impl::minbleicstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minbleicstate), &_state);
2666 0 : memset(p_struct, 0, sizeof(alglib_impl::minbleicstate));
2667 0 : alglib_impl::_minbleicstate_init_copy(p_struct, const_cast<alglib_impl::minbleicstate*>(rhs.p_struct), &_state, ae_false);
2668 0 : ae_state_clear(&_state);
2669 0 : }
2670 :
2671 0 : _minbleicstate_owner& _minbleicstate_owner::operator=(const _minbleicstate_owner &rhs)
2672 : {
2673 0 : if( this==&rhs )
2674 0 : return *this;
2675 : jmp_buf _break_jump;
2676 : alglib_impl::ae_state _state;
2677 :
2678 0 : alglib_impl::ae_state_init(&_state);
2679 0 : if( setjmp(_break_jump) )
2680 : {
2681 : #if !defined(AE_NO_EXCEPTIONS)
2682 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
2683 : #else
2684 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
2685 : return *this;
2686 : #endif
2687 : }
2688 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
2689 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minbleicstate assignment constructor failure (destination is not initialized)", &_state);
2690 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minbleicstate assignment constructor failure (source is not initialized)", &_state);
2691 0 : alglib_impl::_minbleicstate_destroy(p_struct);
2692 0 : memset(p_struct, 0, sizeof(alglib_impl::minbleicstate));
2693 0 : alglib_impl::_minbleicstate_init_copy(p_struct, const_cast<alglib_impl::minbleicstate*>(rhs.p_struct), &_state, ae_false);
2694 0 : ae_state_clear(&_state);
2695 0 : return *this;
2696 : }
2697 :
2698 0 : _minbleicstate_owner::~_minbleicstate_owner()
2699 : {
2700 0 : if( p_struct!=NULL )
2701 : {
2702 0 : alglib_impl::_minbleicstate_destroy(p_struct);
2703 0 : ae_free(p_struct);
2704 : }
2705 0 : }
2706 :
2707 0 : alglib_impl::minbleicstate* _minbleicstate_owner::c_ptr()
2708 : {
2709 0 : return p_struct;
2710 : }
2711 :
2712 0 : alglib_impl::minbleicstate* _minbleicstate_owner::c_ptr() const
2713 : {
2714 0 : return const_cast<alglib_impl::minbleicstate*>(p_struct);
2715 : }
2716 0 : 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)
2717 : {
2718 0 : }
2719 :
2720 0 : minbleicstate::minbleicstate(const minbleicstate &rhs):_minbleicstate_owner(rhs) ,needf(p_struct->needf),needfg(p_struct->needfg),xupdated(p_struct->xupdated),f(p_struct->f),g(&p_struct->g),x(&p_struct->x)
2721 : {
2722 0 : }
2723 :
2724 0 : minbleicstate& minbleicstate::operator=(const minbleicstate &rhs)
2725 : {
2726 0 : if( this==&rhs )
2727 0 : return *this;
2728 0 : _minbleicstate_owner::operator=(rhs);
2729 0 : return *this;
2730 : }
2731 :
2732 0 : minbleicstate::~minbleicstate()
2733 : {
2734 0 : }
2735 :
2736 :
2737 : /*************************************************************************
2738 : This structure stores optimization report:
2739 : * IterationsCount number of iterations
2740 : * NFEV number of gradient evaluations
2741 : * TerminationType termination type (see below)
2742 :
2743 : TERMINATION CODES
2744 :
2745 : TerminationType field contains completion code, which can be:
2746 : -8 internal integrity control detected infinite or NAN values in
2747 : function/gradient. Abnormal termination signalled.
2748 : -3 inconsistent constraints. Feasible point is
2749 : either nonexistent or too hard to find. Try to
2750 : restart optimizer with better initial approximation
2751 : 1 relative function improvement is no more than EpsF.
2752 : 2 relative step is no more than EpsX.
2753 : 4 gradient norm is no more than EpsG
2754 : 5 MaxIts steps was taken
2755 : 7 stopping conditions are too stringent,
2756 : further improvement is impossible,
2757 : X contains best point found so far.
2758 : 8 terminated by user who called minbleicrequesttermination(). X contains
2759 : point which was "current accepted" when termination request was
2760 : submitted.
2761 :
2762 : ADDITIONAL FIELDS
2763 :
2764 : There are additional fields which can be used for debugging:
2765 : * DebugEqErr error in the equality constraints (2-norm)
2766 : * DebugFS f, calculated at projection of initial point
2767 : to the feasible set
2768 : * DebugFF f, calculated at the final point
2769 : * DebugDX |X_start-X_final|
2770 : *************************************************************************/
2771 0 : _minbleicreport_owner::_minbleicreport_owner()
2772 : {
2773 : jmp_buf _break_jump;
2774 : alglib_impl::ae_state _state;
2775 :
2776 0 : alglib_impl::ae_state_init(&_state);
2777 0 : if( setjmp(_break_jump) )
2778 : {
2779 0 : if( p_struct!=NULL )
2780 : {
2781 0 : alglib_impl::_minbleicreport_destroy(p_struct);
2782 0 : alglib_impl::ae_free(p_struct);
2783 : }
2784 0 : p_struct = NULL;
2785 : #if !defined(AE_NO_EXCEPTIONS)
2786 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
2787 : #else
2788 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
2789 : return;
2790 : #endif
2791 : }
2792 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
2793 0 : p_struct = NULL;
2794 0 : p_struct = (alglib_impl::minbleicreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minbleicreport), &_state);
2795 0 : memset(p_struct, 0, sizeof(alglib_impl::minbleicreport));
2796 0 : alglib_impl::_minbleicreport_init(p_struct, &_state, ae_false);
2797 0 : ae_state_clear(&_state);
2798 0 : }
2799 :
2800 0 : _minbleicreport_owner::_minbleicreport_owner(const _minbleicreport_owner &rhs)
2801 : {
2802 : jmp_buf _break_jump;
2803 : alglib_impl::ae_state _state;
2804 :
2805 0 : alglib_impl::ae_state_init(&_state);
2806 0 : if( setjmp(_break_jump) )
2807 : {
2808 0 : if( p_struct!=NULL )
2809 : {
2810 0 : alglib_impl::_minbleicreport_destroy(p_struct);
2811 0 : alglib_impl::ae_free(p_struct);
2812 : }
2813 0 : p_struct = NULL;
2814 : #if !defined(AE_NO_EXCEPTIONS)
2815 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
2816 : #else
2817 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
2818 : return;
2819 : #endif
2820 : }
2821 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
2822 0 : p_struct = NULL;
2823 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minbleicreport copy constructor failure (source is not initialized)", &_state);
2824 0 : p_struct = (alglib_impl::minbleicreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minbleicreport), &_state);
2825 0 : memset(p_struct, 0, sizeof(alglib_impl::minbleicreport));
2826 0 : alglib_impl::_minbleicreport_init_copy(p_struct, const_cast<alglib_impl::minbleicreport*>(rhs.p_struct), &_state, ae_false);
2827 0 : ae_state_clear(&_state);
2828 0 : }
2829 :
2830 0 : _minbleicreport_owner& _minbleicreport_owner::operator=(const _minbleicreport_owner &rhs)
2831 : {
2832 0 : if( this==&rhs )
2833 0 : return *this;
2834 : jmp_buf _break_jump;
2835 : alglib_impl::ae_state _state;
2836 :
2837 0 : alglib_impl::ae_state_init(&_state);
2838 0 : if( setjmp(_break_jump) )
2839 : {
2840 : #if !defined(AE_NO_EXCEPTIONS)
2841 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
2842 : #else
2843 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
2844 : return *this;
2845 : #endif
2846 : }
2847 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
2848 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minbleicreport assignment constructor failure (destination is not initialized)", &_state);
2849 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minbleicreport assignment constructor failure (source is not initialized)", &_state);
2850 0 : alglib_impl::_minbleicreport_destroy(p_struct);
2851 0 : memset(p_struct, 0, sizeof(alglib_impl::minbleicreport));
2852 0 : alglib_impl::_minbleicreport_init_copy(p_struct, const_cast<alglib_impl::minbleicreport*>(rhs.p_struct), &_state, ae_false);
2853 0 : ae_state_clear(&_state);
2854 0 : return *this;
2855 : }
2856 :
2857 0 : _minbleicreport_owner::~_minbleicreport_owner()
2858 : {
2859 0 : if( p_struct!=NULL )
2860 : {
2861 0 : alglib_impl::_minbleicreport_destroy(p_struct);
2862 0 : ae_free(p_struct);
2863 : }
2864 0 : }
2865 :
2866 0 : alglib_impl::minbleicreport* _minbleicreport_owner::c_ptr()
2867 : {
2868 0 : return p_struct;
2869 : }
2870 :
2871 0 : alglib_impl::minbleicreport* _minbleicreport_owner::c_ptr() const
2872 : {
2873 0 : return const_cast<alglib_impl::minbleicreport*>(p_struct);
2874 : }
2875 0 : 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)
2876 : {
2877 0 : }
2878 :
2879 0 : minbleicreport::minbleicreport(const minbleicreport &rhs):_minbleicreport_owner(rhs) ,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)
2880 : {
2881 0 : }
2882 :
2883 0 : minbleicreport& minbleicreport::operator=(const minbleicreport &rhs)
2884 : {
2885 0 : if( this==&rhs )
2886 0 : return *this;
2887 0 : _minbleicreport_owner::operator=(rhs);
2888 0 : return *this;
2889 : }
2890 :
2891 0 : minbleicreport::~minbleicreport()
2892 : {
2893 0 : }
2894 :
2895 : /*************************************************************************
2896 : BOUND CONSTRAINED OPTIMIZATION
2897 : WITH ADDITIONAL LINEAR EQUALITY AND INEQUALITY CONSTRAINTS
2898 :
2899 : DESCRIPTION:
2900 : The subroutine minimizes function F(x) of N arguments subject to any
2901 : combination of:
2902 : * bound constraints
2903 : * linear inequality constraints
2904 : * linear equality constraints
2905 :
2906 : REQUIREMENTS:
2907 : * user must provide function value and gradient
2908 : * starting point X0 must be feasible or
2909 : not too far away from the feasible set
2910 : * grad(f) must be Lipschitz continuous on a level set:
2911 : L = { x : f(x)<=f(x0) }
2912 : * function must be defined everywhere on the feasible set F
2913 :
2914 : USAGE:
2915 :
2916 : Constrained optimization if far more complex than the unconstrained one.
2917 : Here we give very brief outline of the BLEIC optimizer. We strongly recommend
2918 : you to read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide
2919 : on optimization, which is available at http://www.alglib.net/optimization/
2920 :
2921 : 1. User initializes algorithm state with MinBLEICCreate() call
2922 :
2923 : 2. USer adds boundary and/or linear constraints by calling
2924 : MinBLEICSetBC() and MinBLEICSetLC() functions.
2925 :
2926 : 3. User sets stopping conditions with MinBLEICSetCond().
2927 :
2928 : 4. User calls MinBLEICOptimize() function which takes algorithm state and
2929 : pointer (delegate, etc.) to callback function which calculates F/G.
2930 :
2931 : 5. User calls MinBLEICResults() to get solution
2932 :
2933 : 6. Optionally user may call MinBLEICRestartFrom() to solve another problem
2934 : with same N but another starting point.
2935 : MinBLEICRestartFrom() allows to reuse already initialized structure.
2936 :
2937 : NOTE: if you have box-only constraints (no general linear constraints),
2938 : then MinBC optimizer can be better option. It uses special, faster
2939 : constraint activation method, which performs better on problems with
2940 : multiple constraints active at the solution.
2941 :
2942 : On small-scale problems performance of MinBC is similar to that of
2943 : MinBLEIC, but on large-scale ones (hundreds and thousands of active
2944 : constraints) it can be several times faster than MinBLEIC.
2945 :
2946 : INPUT PARAMETERS:
2947 : N - problem dimension, N>0:
2948 : * if given, only leading N elements of X are used
2949 : * if not given, automatically determined from size ofX
2950 : X - starting point, array[N]:
2951 : * it is better to set X to a feasible point
2952 : * but X can be infeasible, in which case algorithm will try
2953 : to find feasible point first, using X as initial
2954 : approximation.
2955 :
2956 : OUTPUT PARAMETERS:
2957 : State - structure stores algorithm state
2958 :
2959 : -- ALGLIB --
2960 : Copyright 28.11.2010 by Bochkanov Sergey
2961 : *************************************************************************/
2962 0 : void minbleiccreate(const ae_int_t n, const real_1d_array &x, minbleicstate &state, const xparams _xparams)
2963 : {
2964 : jmp_buf _break_jump;
2965 : alglib_impl::ae_state _alglib_env_state;
2966 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2967 0 : if( setjmp(_break_jump) )
2968 : {
2969 : #if !defined(AE_NO_EXCEPTIONS)
2970 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2971 : #else
2972 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2973 : return;
2974 : #endif
2975 : }
2976 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2977 0 : if( _xparams.flags!=0x0 )
2978 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2979 0 : alglib_impl::minbleiccreate(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), &_alglib_env_state);
2980 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2981 0 : return;
2982 : }
2983 :
2984 : /*************************************************************************
2985 : BOUND CONSTRAINED OPTIMIZATION
2986 : WITH ADDITIONAL LINEAR EQUALITY AND INEQUALITY CONSTRAINTS
2987 :
2988 : DESCRIPTION:
2989 : The subroutine minimizes function F(x) of N arguments subject to any
2990 : combination of:
2991 : * bound constraints
2992 : * linear inequality constraints
2993 : * linear equality constraints
2994 :
2995 : REQUIREMENTS:
2996 : * user must provide function value and gradient
2997 : * starting point X0 must be feasible or
2998 : not too far away from the feasible set
2999 : * grad(f) must be Lipschitz continuous on a level set:
3000 : L = { x : f(x)<=f(x0) }
3001 : * function must be defined everywhere on the feasible set F
3002 :
3003 : USAGE:
3004 :
3005 : Constrained optimization if far more complex than the unconstrained one.
3006 : Here we give very brief outline of the BLEIC optimizer. We strongly recommend
3007 : you to read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide
3008 : on optimization, which is available at http://www.alglib.net/optimization/
3009 :
3010 : 1. User initializes algorithm state with MinBLEICCreate() call
3011 :
3012 : 2. USer adds boundary and/or linear constraints by calling
3013 : MinBLEICSetBC() and MinBLEICSetLC() functions.
3014 :
3015 : 3. User sets stopping conditions with MinBLEICSetCond().
3016 :
3017 : 4. User calls MinBLEICOptimize() function which takes algorithm state and
3018 : pointer (delegate, etc.) to callback function which calculates F/G.
3019 :
3020 : 5. User calls MinBLEICResults() to get solution
3021 :
3022 : 6. Optionally user may call MinBLEICRestartFrom() to solve another problem
3023 : with same N but another starting point.
3024 : MinBLEICRestartFrom() allows to reuse already initialized structure.
3025 :
3026 : NOTE: if you have box-only constraints (no general linear constraints),
3027 : then MinBC optimizer can be better option. It uses special, faster
3028 : constraint activation method, which performs better on problems with
3029 : multiple constraints active at the solution.
3030 :
3031 : On small-scale problems performance of MinBC is similar to that of
3032 : MinBLEIC, but on large-scale ones (hundreds and thousands of active
3033 : constraints) it can be several times faster than MinBLEIC.
3034 :
3035 : INPUT PARAMETERS:
3036 : N - problem dimension, N>0:
3037 : * if given, only leading N elements of X are used
3038 : * if not given, automatically determined from size ofX
3039 : X - starting point, array[N]:
3040 : * it is better to set X to a feasible point
3041 : * but X can be infeasible, in which case algorithm will try
3042 : to find feasible point first, using X as initial
3043 : approximation.
3044 :
3045 : OUTPUT PARAMETERS:
3046 : State - structure stores algorithm state
3047 :
3048 : -- ALGLIB --
3049 : Copyright 28.11.2010 by Bochkanov Sergey
3050 : *************************************************************************/
3051 : #if !defined(AE_NO_EXCEPTIONS)
3052 0 : void minbleiccreate(const real_1d_array &x, minbleicstate &state, const xparams _xparams)
3053 : {
3054 : jmp_buf _break_jump;
3055 : alglib_impl::ae_state _alglib_env_state;
3056 : ae_int_t n;
3057 :
3058 0 : n = x.length();
3059 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3060 0 : if( setjmp(_break_jump) )
3061 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3062 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3063 0 : if( _xparams.flags!=0x0 )
3064 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3065 0 : alglib_impl::minbleiccreate(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), &_alglib_env_state);
3066 :
3067 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3068 0 : return;
3069 : }
3070 : #endif
3071 :
3072 : /*************************************************************************
3073 : The subroutine is finite difference variant of MinBLEICCreate(). It uses
3074 : finite differences in order to differentiate target function.
3075 :
3076 : Description below contains information which is specific to this function
3077 : only. We recommend to read comments on MinBLEICCreate() in order to get
3078 : more information about creation of BLEIC optimizer.
3079 :
3080 : INPUT PARAMETERS:
3081 : N - problem dimension, N>0:
3082 : * if given, only leading N elements of X are used
3083 : * if not given, automatically determined from size of X
3084 : X - starting point, array[0..N-1].
3085 : DiffStep- differentiation step, >0
3086 :
3087 : OUTPUT PARAMETERS:
3088 : State - structure which stores algorithm state
3089 :
3090 : NOTES:
3091 : 1. algorithm uses 4-point central formula for differentiation.
3092 : 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
3093 : S[] is scaling vector which can be set by MinBLEICSetScale() call.
3094 : 3. we recommend you to use moderate values of differentiation step. Too
3095 : large step will result in too large truncation errors, while too small
3096 : step will result in too large numerical errors. 1.0E-6 can be good
3097 : value to start with.
3098 : 4. Numerical differentiation is very inefficient - one gradient
3099 : calculation needs 4*N function evaluations. This function will work for
3100 : any N - either small (1...10), moderate (10...100) or large (100...).
3101 : However, performance penalty will be too severe for any N's except for
3102 : small ones.
3103 : We should also say that code which relies on numerical differentiation
3104 : is less robust and precise. CG needs exact gradient values. Imprecise
3105 : gradient may slow down convergence, especially on highly nonlinear
3106 : problems.
3107 : Thus we recommend to use this function for fast prototyping on small-
3108 : dimensional problems only, and to implement analytical gradient as soon
3109 : as possible.
3110 :
3111 : -- ALGLIB --
3112 : Copyright 16.05.2011 by Bochkanov Sergey
3113 : *************************************************************************/
3114 0 : void minbleiccreatef(const ae_int_t n, const real_1d_array &x, const double diffstep, minbleicstate &state, const xparams _xparams)
3115 : {
3116 : jmp_buf _break_jump;
3117 : alglib_impl::ae_state _alglib_env_state;
3118 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3119 0 : if( setjmp(_break_jump) )
3120 : {
3121 : #if !defined(AE_NO_EXCEPTIONS)
3122 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3123 : #else
3124 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3125 : return;
3126 : #endif
3127 : }
3128 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3129 0 : if( _xparams.flags!=0x0 )
3130 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3131 0 : 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);
3132 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3133 0 : return;
3134 : }
3135 :
3136 : /*************************************************************************
3137 : The subroutine is finite difference variant of MinBLEICCreate(). It uses
3138 : finite differences in order to differentiate target function.
3139 :
3140 : Description below contains information which is specific to this function
3141 : only. We recommend to read comments on MinBLEICCreate() in order to get
3142 : more information about creation of BLEIC optimizer.
3143 :
3144 : INPUT PARAMETERS:
3145 : N - problem dimension, N>0:
3146 : * if given, only leading N elements of X are used
3147 : * if not given, automatically determined from size of X
3148 : X - starting point, array[0..N-1].
3149 : DiffStep- differentiation step, >0
3150 :
3151 : OUTPUT PARAMETERS:
3152 : State - structure which stores algorithm state
3153 :
3154 : NOTES:
3155 : 1. algorithm uses 4-point central formula for differentiation.
3156 : 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
3157 : S[] is scaling vector which can be set by MinBLEICSetScale() call.
3158 : 3. we recommend you to use moderate values of differentiation step. Too
3159 : large step will result in too large truncation errors, while too small
3160 : step will result in too large numerical errors. 1.0E-6 can be good
3161 : value to start with.
3162 : 4. Numerical differentiation is very inefficient - one gradient
3163 : calculation needs 4*N function evaluations. This function will work for
3164 : any N - either small (1...10), moderate (10...100) or large (100...).
3165 : However, performance penalty will be too severe for any N's except for
3166 : small ones.
3167 : We should also say that code which relies on numerical differentiation
3168 : is less robust and precise. CG needs exact gradient values. Imprecise
3169 : gradient may slow down convergence, especially on highly nonlinear
3170 : problems.
3171 : Thus we recommend to use this function for fast prototyping on small-
3172 : dimensional problems only, and to implement analytical gradient as soon
3173 : as possible.
3174 :
3175 : -- ALGLIB --
3176 : Copyright 16.05.2011 by Bochkanov Sergey
3177 : *************************************************************************/
3178 : #if !defined(AE_NO_EXCEPTIONS)
3179 0 : void minbleiccreatef(const real_1d_array &x, const double diffstep, minbleicstate &state, const xparams _xparams)
3180 : {
3181 : jmp_buf _break_jump;
3182 : alglib_impl::ae_state _alglib_env_state;
3183 : ae_int_t n;
3184 :
3185 0 : n = x.length();
3186 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3187 0 : if( setjmp(_break_jump) )
3188 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3189 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3190 0 : if( _xparams.flags!=0x0 )
3191 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3192 0 : 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);
3193 :
3194 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3195 0 : return;
3196 : }
3197 : #endif
3198 :
3199 : /*************************************************************************
3200 : This function sets boundary constraints for BLEIC optimizer.
3201 :
3202 : Boundary constraints are inactive by default (after initial creation).
3203 : They are preserved after algorithm restart with MinBLEICRestartFrom().
3204 :
3205 : NOTE: if you have box-only constraints (no general linear constraints),
3206 : then MinBC optimizer can be better option. It uses special, faster
3207 : constraint activation method, which performs better on problems with
3208 : multiple constraints active at the solution.
3209 :
3210 : On small-scale problems performance of MinBC is similar to that of
3211 : MinBLEIC, but on large-scale ones (hundreds and thousands of active
3212 : constraints) it can be several times faster than MinBLEIC.
3213 :
3214 : INPUT PARAMETERS:
3215 : State - structure stores algorithm state
3216 : BndL - lower bounds, array[N].
3217 : If some (all) variables are unbounded, you may specify
3218 : very small number or -INF.
3219 : BndU - upper bounds, array[N].
3220 : If some (all) variables are unbounded, you may specify
3221 : very large number or +INF.
3222 :
3223 : NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th
3224 : variable will be "frozen" at X[i]=BndL[i]=BndU[i].
3225 :
3226 : NOTE 2: this solver has following useful properties:
3227 : * bound constraints are always satisfied exactly
3228 : * function is evaluated only INSIDE area specified by bound constraints,
3229 : even when numerical differentiation is used (algorithm adjusts nodes
3230 : according to boundary constraints)
3231 :
3232 : -- ALGLIB --
3233 : Copyright 28.11.2010 by Bochkanov Sergey
3234 : *************************************************************************/
3235 0 : void minbleicsetbc(const minbleicstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams)
3236 : {
3237 : jmp_buf _break_jump;
3238 : alglib_impl::ae_state _alglib_env_state;
3239 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3240 0 : if( setjmp(_break_jump) )
3241 : {
3242 : #if !defined(AE_NO_EXCEPTIONS)
3243 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3244 : #else
3245 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3246 : return;
3247 : #endif
3248 : }
3249 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3250 0 : if( _xparams.flags!=0x0 )
3251 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3252 0 : 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);
3253 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3254 0 : return;
3255 : }
3256 :
3257 : /*************************************************************************
3258 : This function sets linear constraints for BLEIC optimizer.
3259 :
3260 : Linear constraints are inactive by default (after initial creation).
3261 : They are preserved after algorithm restart with MinBLEICRestartFrom().
3262 :
3263 : INPUT PARAMETERS:
3264 : State - structure previously allocated with MinBLEICCreate call.
3265 : C - linear constraints, array[K,N+1].
3266 : Each row of C represents one constraint, either equality
3267 : or inequality (see below):
3268 : * first N elements correspond to coefficients,
3269 : * last element corresponds to the right part.
3270 : All elements of C (including right part) must be finite.
3271 : CT - type of constraints, array[K]:
3272 : * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n]
3273 : * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n]
3274 : * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n]
3275 : K - number of equality/inequality constraints, K>=0:
3276 : * if given, only leading K elements of C/CT are used
3277 : * if not given, automatically determined from sizes of C/CT
3278 :
3279 : NOTE 1: linear (non-bound) constraints are satisfied only approximately:
3280 : * there always exists some minor violation (about Epsilon in magnitude)
3281 : due to rounding errors
3282 : * numerical differentiation, if used, may lead to function evaluations
3283 : outside of the feasible area, because algorithm does NOT change
3284 : numerical differentiation formula according to linear constraints.
3285 : If you want constraints to be satisfied exactly, try to reformulate your
3286 : problem in such manner that all constraints will become boundary ones
3287 : (this kind of constraints is always satisfied exactly, both in the final
3288 : solution and in all intermediate points).
3289 :
3290 : -- ALGLIB --
3291 : Copyright 28.11.2010 by Bochkanov Sergey
3292 : *************************************************************************/
3293 0 : void minbleicsetlc(const minbleicstate &state, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams)
3294 : {
3295 : jmp_buf _break_jump;
3296 : alglib_impl::ae_state _alglib_env_state;
3297 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3298 0 : if( setjmp(_break_jump) )
3299 : {
3300 : #if !defined(AE_NO_EXCEPTIONS)
3301 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3302 : #else
3303 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3304 : return;
3305 : #endif
3306 : }
3307 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3308 0 : if( _xparams.flags!=0x0 )
3309 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3310 0 : 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);
3311 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3312 0 : return;
3313 : }
3314 :
3315 : /*************************************************************************
3316 : This function sets linear constraints for BLEIC optimizer.
3317 :
3318 : Linear constraints are inactive by default (after initial creation).
3319 : They are preserved after algorithm restart with MinBLEICRestartFrom().
3320 :
3321 : INPUT PARAMETERS:
3322 : State - structure previously allocated with MinBLEICCreate call.
3323 : C - linear constraints, array[K,N+1].
3324 : Each row of C represents one constraint, either equality
3325 : or inequality (see below):
3326 : * first N elements correspond to coefficients,
3327 : * last element corresponds to the right part.
3328 : All elements of C (including right part) must be finite.
3329 : CT - type of constraints, array[K]:
3330 : * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n]
3331 : * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n]
3332 : * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n]
3333 : K - number of equality/inequality constraints, K>=0:
3334 : * if given, only leading K elements of C/CT are used
3335 : * if not given, automatically determined from sizes of C/CT
3336 :
3337 : NOTE 1: linear (non-bound) constraints are satisfied only approximately:
3338 : * there always exists some minor violation (about Epsilon in magnitude)
3339 : due to rounding errors
3340 : * numerical differentiation, if used, may lead to function evaluations
3341 : outside of the feasible area, because algorithm does NOT change
3342 : numerical differentiation formula according to linear constraints.
3343 : If you want constraints to be satisfied exactly, try to reformulate your
3344 : problem in such manner that all constraints will become boundary ones
3345 : (this kind of constraints is always satisfied exactly, both in the final
3346 : solution and in all intermediate points).
3347 :
3348 : -- ALGLIB --
3349 : Copyright 28.11.2010 by Bochkanov Sergey
3350 : *************************************************************************/
3351 : #if !defined(AE_NO_EXCEPTIONS)
3352 0 : void minbleicsetlc(const minbleicstate &state, const real_2d_array &c, const integer_1d_array &ct, const xparams _xparams)
3353 : {
3354 : jmp_buf _break_jump;
3355 : alglib_impl::ae_state _alglib_env_state;
3356 : ae_int_t k;
3357 0 : if( (c.rows()!=ct.length()))
3358 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'minbleicsetlc': looks like one of arguments has wrong size");
3359 0 : k = c.rows();
3360 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3361 0 : if( setjmp(_break_jump) )
3362 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3363 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3364 0 : if( _xparams.flags!=0x0 )
3365 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3366 0 : 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);
3367 :
3368 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3369 0 : return;
3370 : }
3371 : #endif
3372 :
3373 : /*************************************************************************
3374 : This function sets stopping conditions for the optimizer.
3375 :
3376 : INPUT PARAMETERS:
3377 : State - structure which stores algorithm state
3378 : EpsG - >=0
3379 : The subroutine finishes its work if the condition
3380 : |v|<EpsG is satisfied, where:
3381 : * |.| means Euclidian norm
3382 : * v - scaled gradient vector, v[i]=g[i]*s[i]
3383 : * g - gradient
3384 : * s - scaling coefficients set by MinBLEICSetScale()
3385 : EpsF - >=0
3386 : The subroutine finishes its work if on k+1-th iteration
3387 : the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
3388 : is satisfied.
3389 : EpsX - >=0
3390 : The subroutine finishes its work if on k+1-th iteration
3391 : the condition |v|<=EpsX is fulfilled, where:
3392 : * |.| means Euclidian norm
3393 : * v - scaled step vector, v[i]=dx[i]/s[i]
3394 : * dx - step vector, dx=X(k+1)-X(k)
3395 : * s - scaling coefficients set by MinBLEICSetScale()
3396 : MaxIts - maximum number of iterations. If MaxIts=0, the number of
3397 : iterations is unlimited.
3398 :
3399 : Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead
3400 : to automatic stopping criterion selection.
3401 :
3402 : NOTE: when SetCond() called with non-zero MaxIts, BLEIC solver may perform
3403 : slightly more than MaxIts iterations. I.e., MaxIts sets non-strict
3404 : limit on iterations count.
3405 :
3406 : -- ALGLIB --
3407 : Copyright 28.11.2010 by Bochkanov Sergey
3408 : *************************************************************************/
3409 0 : void minbleicsetcond(const minbleicstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits, const xparams _xparams)
3410 : {
3411 : jmp_buf _break_jump;
3412 : alglib_impl::ae_state _alglib_env_state;
3413 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3414 0 : if( setjmp(_break_jump) )
3415 : {
3416 : #if !defined(AE_NO_EXCEPTIONS)
3417 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3418 : #else
3419 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3420 : return;
3421 : #endif
3422 : }
3423 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3424 0 : if( _xparams.flags!=0x0 )
3425 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3426 0 : alglib_impl::minbleicsetcond(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), epsg, epsf, epsx, maxits, &_alglib_env_state);
3427 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3428 0 : return;
3429 : }
3430 :
3431 : /*************************************************************************
3432 : This function sets scaling coefficients for BLEIC optimizer.
3433 :
3434 : ALGLIB optimizers use scaling matrices to test stopping conditions (step
3435 : size and gradient are scaled before comparison with tolerances). Scale of
3436 : the I-th variable is a translation invariant measure of:
3437 : a) "how large" the variable is
3438 : b) how large the step should be to make significant changes in the function
3439 :
3440 : Scaling is also used by finite difference variant of the optimizer - step
3441 : along I-th axis is equal to DiffStep*S[I].
3442 :
3443 : In most optimizers (and in the BLEIC too) scaling is NOT a form of
3444 : preconditioning. It just affects stopping conditions. You should set
3445 : preconditioner by separate call to one of the MinBLEICSetPrec...()
3446 : functions.
3447 :
3448 : There is a special preconditioning mode, however, which uses scaling
3449 : coefficients to form diagonal preconditioning matrix. You can turn this
3450 : mode on, if you want. But you should understand that scaling is not the
3451 : same thing as preconditioning - these are two different, although related
3452 : forms of tuning solver.
3453 :
3454 : INPUT PARAMETERS:
3455 : State - structure stores algorithm state
3456 : S - array[N], non-zero scaling coefficients
3457 : S[i] may be negative, sign doesn't matter.
3458 :
3459 : -- ALGLIB --
3460 : Copyright 14.01.2011 by Bochkanov Sergey
3461 : *************************************************************************/
3462 0 : void minbleicsetscale(const minbleicstate &state, const real_1d_array &s, const xparams _xparams)
3463 : {
3464 : jmp_buf _break_jump;
3465 : alglib_impl::ae_state _alglib_env_state;
3466 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3467 0 : if( setjmp(_break_jump) )
3468 : {
3469 : #if !defined(AE_NO_EXCEPTIONS)
3470 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3471 : #else
3472 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3473 : return;
3474 : #endif
3475 : }
3476 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3477 0 : if( _xparams.flags!=0x0 )
3478 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3479 0 : alglib_impl::minbleicsetscale(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(s.c_ptr()), &_alglib_env_state);
3480 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3481 0 : return;
3482 : }
3483 :
3484 : /*************************************************************************
3485 : Modification of the preconditioner: preconditioning is turned off.
3486 :
3487 : INPUT PARAMETERS:
3488 : State - structure which stores algorithm state
3489 :
3490 : -- ALGLIB --
3491 : Copyright 13.10.2010 by Bochkanov Sergey
3492 : *************************************************************************/
3493 0 : void minbleicsetprecdefault(const minbleicstate &state, const xparams _xparams)
3494 : {
3495 : jmp_buf _break_jump;
3496 : alglib_impl::ae_state _alglib_env_state;
3497 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3498 0 : if( setjmp(_break_jump) )
3499 : {
3500 : #if !defined(AE_NO_EXCEPTIONS)
3501 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3502 : #else
3503 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3504 : return;
3505 : #endif
3506 : }
3507 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3508 0 : if( _xparams.flags!=0x0 )
3509 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3510 0 : alglib_impl::minbleicsetprecdefault(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), &_alglib_env_state);
3511 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3512 0 : return;
3513 : }
3514 :
3515 : /*************************************************************************
3516 : Modification of the preconditioner: diagonal of approximate Hessian is
3517 : used.
3518 :
3519 : INPUT PARAMETERS:
3520 : State - structure which stores algorithm state
3521 : D - diagonal of the approximate Hessian, array[0..N-1],
3522 : (if larger, only leading N elements are used).
3523 :
3524 : NOTE 1: D[i] should be positive. Exception will be thrown otherwise.
3525 :
3526 : NOTE 2: you should pass diagonal of approximate Hessian - NOT ITS INVERSE.
3527 :
3528 : -- ALGLIB --
3529 : Copyright 13.10.2010 by Bochkanov Sergey
3530 : *************************************************************************/
3531 0 : void minbleicsetprecdiag(const minbleicstate &state, const real_1d_array &d, const xparams _xparams)
3532 : {
3533 : jmp_buf _break_jump;
3534 : alglib_impl::ae_state _alglib_env_state;
3535 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3536 0 : if( setjmp(_break_jump) )
3537 : {
3538 : #if !defined(AE_NO_EXCEPTIONS)
3539 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3540 : #else
3541 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3542 : return;
3543 : #endif
3544 : }
3545 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3546 0 : if( _xparams.flags!=0x0 )
3547 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3548 0 : alglib_impl::minbleicsetprecdiag(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(d.c_ptr()), &_alglib_env_state);
3549 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3550 0 : return;
3551 : }
3552 :
3553 : /*************************************************************************
3554 : Modification of the preconditioner: scale-based diagonal preconditioning.
3555 :
3556 : This preconditioning mode can be useful when you don't have approximate
3557 : diagonal of Hessian, but you know that your variables are badly scaled
3558 : (for example, one variable is in [1,10], and another in [1000,100000]),
3559 : and most part of the ill-conditioning comes from different scales of vars.
3560 :
3561 : In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2),
3562 : can greatly improve convergence.
3563 :
3564 : IMPRTANT: you should set scale of your variables with MinBLEICSetScale()
3565 : call (before or after MinBLEICSetPrecScale() call). Without knowledge of
3566 : the scale of your variables scale-based preconditioner will be just unit
3567 : matrix.
3568 :
3569 : INPUT PARAMETERS:
3570 : State - structure which stores algorithm state
3571 :
3572 : -- ALGLIB --
3573 : Copyright 13.10.2010 by Bochkanov Sergey
3574 : *************************************************************************/
3575 0 : void minbleicsetprecscale(const minbleicstate &state, const xparams _xparams)
3576 : {
3577 : jmp_buf _break_jump;
3578 : alglib_impl::ae_state _alglib_env_state;
3579 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3580 0 : if( setjmp(_break_jump) )
3581 : {
3582 : #if !defined(AE_NO_EXCEPTIONS)
3583 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3584 : #else
3585 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3586 : return;
3587 : #endif
3588 : }
3589 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3590 0 : if( _xparams.flags!=0x0 )
3591 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3592 0 : alglib_impl::minbleicsetprecscale(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), &_alglib_env_state);
3593 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3594 0 : return;
3595 : }
3596 :
3597 : /*************************************************************************
3598 : This function turns on/off reporting.
3599 :
3600 : INPUT PARAMETERS:
3601 : State - structure which stores algorithm state
3602 : NeedXRep- whether iteration reports are needed or not
3603 :
3604 : If NeedXRep is True, algorithm will call rep() callback function if it is
3605 : provided to MinBLEICOptimize().
3606 :
3607 : -- ALGLIB --
3608 : Copyright 28.11.2010 by Bochkanov Sergey
3609 : *************************************************************************/
3610 0 : void minbleicsetxrep(const minbleicstate &state, const bool needxrep, const xparams _xparams)
3611 : {
3612 : jmp_buf _break_jump;
3613 : alglib_impl::ae_state _alglib_env_state;
3614 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3615 0 : if( setjmp(_break_jump) )
3616 : {
3617 : #if !defined(AE_NO_EXCEPTIONS)
3618 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3619 : #else
3620 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3621 : return;
3622 : #endif
3623 : }
3624 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3625 0 : if( _xparams.flags!=0x0 )
3626 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3627 0 : alglib_impl::minbleicsetxrep(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), needxrep, &_alglib_env_state);
3628 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3629 0 : return;
3630 : }
3631 :
3632 : /*************************************************************************
3633 : This function sets maximum step length
3634 :
3635 : IMPORTANT: this feature is hard to combine with preconditioning. You can't
3636 : set upper limit on step length, when you solve optimization problem with
3637 : linear (non-boundary) constraints AND preconditioner turned on.
3638 :
3639 : When non-boundary constraints are present, you have to either a) use
3640 : preconditioner, or b) use upper limit on step length. YOU CAN'T USE BOTH!
3641 : In this case algorithm will terminate with appropriate error code.
3642 :
3643 : INPUT PARAMETERS:
3644 : State - structure which stores algorithm state
3645 : StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't
3646 : want to limit step length.
3647 :
3648 : Use this subroutine when you optimize target function which contains exp()
3649 : or other fast growing functions, and optimization algorithm makes too
3650 : large steps which lead to overflow. This function allows us to reject
3651 : steps that are too large (and therefore expose us to the possible
3652 : overflow) without actually calculating function value at the x+stp*d.
3653 :
3654 : -- ALGLIB --
3655 : Copyright 02.04.2010 by Bochkanov Sergey
3656 : *************************************************************************/
3657 0 : void minbleicsetstpmax(const minbleicstate &state, const double stpmax, const xparams _xparams)
3658 : {
3659 : jmp_buf _break_jump;
3660 : alglib_impl::ae_state _alglib_env_state;
3661 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3662 0 : if( setjmp(_break_jump) )
3663 : {
3664 : #if !defined(AE_NO_EXCEPTIONS)
3665 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3666 : #else
3667 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3668 : return;
3669 : #endif
3670 : }
3671 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3672 0 : if( _xparams.flags!=0x0 )
3673 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3674 0 : alglib_impl::minbleicsetstpmax(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), stpmax, &_alglib_env_state);
3675 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3676 0 : return;
3677 : }
3678 :
3679 : /*************************************************************************
3680 : This function provides reverse communication interface
3681 : Reverse communication interface is not documented or recommended to use.
3682 : See below for functions which provide better documented API
3683 : *************************************************************************/
3684 0 : bool minbleiciteration(const minbleicstate &state, const xparams _xparams)
3685 : {
3686 : jmp_buf _break_jump;
3687 : alglib_impl::ae_state _alglib_env_state;
3688 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3689 0 : if( setjmp(_break_jump) )
3690 : {
3691 : #if !defined(AE_NO_EXCEPTIONS)
3692 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3693 : #else
3694 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3695 : return 0;
3696 : #endif
3697 : }
3698 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3699 0 : if( _xparams.flags!=0x0 )
3700 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3701 0 : ae_bool result = alglib_impl::minbleiciteration(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), &_alglib_env_state);
3702 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3703 0 : return *(reinterpret_cast<bool*>(&result));
3704 : }
3705 :
3706 :
3707 0 : void minbleicoptimize(minbleicstate &state,
3708 : void (*func)(const real_1d_array &x, double &func, void *ptr),
3709 : void (*rep)(const real_1d_array &x, double func, void *ptr),
3710 : void *ptr,
3711 : const xparams _xparams)
3712 : {
3713 : jmp_buf _break_jump;
3714 : alglib_impl::ae_state _alglib_env_state;
3715 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3716 0 : if( setjmp(_break_jump) )
3717 : {
3718 : #if !defined(AE_NO_EXCEPTIONS)
3719 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3720 : #else
3721 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3722 : return;
3723 : #endif
3724 : }
3725 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3726 0 : if( _xparams.flags!=0x0 )
3727 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3728 0 : alglib_impl::ae_assert(func!=NULL, "ALGLIB: error in 'minbleicoptimize()' (func is NULL)", &_alglib_env_state);
3729 0 : while( alglib_impl::minbleiciteration(state.c_ptr(), &_alglib_env_state) )
3730 : {
3731 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN
3732 0 : if( state.needf )
3733 : {
3734 0 : func(state.x, state.f, ptr);
3735 0 : continue;
3736 : }
3737 0 : if( state.xupdated )
3738 : {
3739 0 : if( rep!=NULL )
3740 0 : rep(state.x, state.f, ptr);
3741 0 : continue;
3742 : }
3743 0 : goto lbl_no_callback;
3744 0 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_END
3745 0 : lbl_no_callback:
3746 0 : alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minbleicoptimize' (some derivatives were not provided?)", &_alglib_env_state);
3747 : }
3748 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3749 0 : }
3750 :
3751 :
3752 0 : void minbleicoptimize(minbleicstate &state,
3753 : void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr),
3754 : void (*rep)(const real_1d_array &x, double func, void *ptr),
3755 : void *ptr,
3756 : const xparams _xparams)
3757 : {
3758 : jmp_buf _break_jump;
3759 : alglib_impl::ae_state _alglib_env_state;
3760 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3761 0 : if( setjmp(_break_jump) )
3762 : {
3763 : #if !defined(AE_NO_EXCEPTIONS)
3764 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3765 : #else
3766 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3767 : return;
3768 : #endif
3769 : }
3770 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3771 0 : if( _xparams.flags!=0x0 )
3772 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3773 0 : alglib_impl::ae_assert(grad!=NULL, "ALGLIB: error in 'minbleicoptimize()' (grad is NULL)", &_alglib_env_state);
3774 0 : while( alglib_impl::minbleiciteration(state.c_ptr(), &_alglib_env_state) )
3775 : {
3776 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN
3777 0 : if( state.needfg )
3778 : {
3779 0 : grad(state.x, state.f, state.g, ptr);
3780 0 : continue;
3781 : }
3782 0 : if( state.xupdated )
3783 : {
3784 0 : if( rep!=NULL )
3785 0 : rep(state.x, state.f, ptr);
3786 0 : continue;
3787 : }
3788 0 : goto lbl_no_callback;
3789 0 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_END
3790 0 : lbl_no_callback:
3791 0 : alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minbleicoptimize' (some derivatives were not provided?)", &_alglib_env_state);
3792 : }
3793 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3794 0 : }
3795 :
3796 :
3797 :
3798 : /*************************************************************************
3799 : This function activates/deactivates verification of the user-supplied
3800 : analytic gradient.
3801 :
3802 : Upon activation of this option OptGuard integrity checker performs
3803 : numerical differentiation of your target function at the initial point
3804 : (note: future versions may also perform check at the final point) and
3805 : compares numerical gradient with analytic one provided by you.
3806 :
3807 : If difference is too large, an error flag is set and optimization session
3808 : continues. After optimization session is over, you can retrieve the report
3809 : which stores both gradients and specific components highlighted as
3810 : suspicious by the OptGuard.
3811 :
3812 : The primary OptGuard report can be retrieved with minbleicoptguardresults().
3813 :
3814 : IMPORTANT: gradient check is a high-overhead option which will cost you
3815 : about 3*N additional function evaluations. In many cases it may
3816 : cost as much as the rest of the optimization session.
3817 :
3818 : YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO
3819 : CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY.
3820 :
3821 : NOTE: unlike previous incarnation of the gradient checking code, OptGuard
3822 : does NOT interrupt optimization even if it discovers bad gradient.
3823 :
3824 : INPUT PARAMETERS:
3825 : State - structure used to store algorithm state
3826 : TestStep - verification step used for numerical differentiation:
3827 : * TestStep=0 turns verification off
3828 : * TestStep>0 activates verification
3829 : You should carefully choose TestStep. Value which is
3830 : too large (so large that function behavior is non-
3831 : cubic at this scale) will lead to false alarms. Too
3832 : short step will result in rounding errors dominating
3833 : numerical derivative.
3834 :
3835 : You may use different step for different parameters by
3836 : means of setting scale with minbleicsetscale().
3837 :
3838 : === EXPLANATION ==========================================================
3839 :
3840 : In order to verify gradient algorithm performs following steps:
3841 : * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i],
3842 : where X[i] is i-th component of the initial point and S[i] is a scale
3843 : of i-th parameter
3844 : * F(X) is evaluated at these trial points
3845 : * we perform one more evaluation in the middle point of the interval
3846 : * we build cubic model using function values and derivatives at trial
3847 : points and we compare its prediction with actual value in the middle
3848 : point
3849 :
3850 : -- ALGLIB --
3851 : Copyright 15.06.2014 by Bochkanov Sergey
3852 : *************************************************************************/
3853 0 : void minbleicoptguardgradient(const minbleicstate &state, const double teststep, const xparams _xparams)
3854 : {
3855 : jmp_buf _break_jump;
3856 : alglib_impl::ae_state _alglib_env_state;
3857 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3858 0 : if( setjmp(_break_jump) )
3859 : {
3860 : #if !defined(AE_NO_EXCEPTIONS)
3861 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3862 : #else
3863 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3864 : return;
3865 : #endif
3866 : }
3867 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3868 0 : if( _xparams.flags!=0x0 )
3869 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3870 0 : alglib_impl::minbleicoptguardgradient(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), teststep, &_alglib_env_state);
3871 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3872 0 : return;
3873 : }
3874 :
3875 : /*************************************************************************
3876 : This function activates/deactivates nonsmoothness monitoring option of
3877 : the OptGuard integrity checker. Smoothness monitor silently observes
3878 : solution process and tries to detect ill-posed problems, i.e. ones with:
3879 : a) discontinuous target function (non-C0)
3880 : b) nonsmooth target function (non-C1)
3881 :
3882 : Smoothness monitoring does NOT interrupt optimization even if it suspects
3883 : that your problem is nonsmooth. It just sets corresponding flags in the
3884 : OptGuard report which can be retrieved after optimization is over.
3885 :
3886 : Smoothness monitoring is a moderate overhead option which often adds less
3887 : than 1% to the optimizer running time. Thus, you can use it even for large
3888 : scale problems.
3889 :
3890 : NOTE: OptGuard does NOT guarantee that it will always detect C0/C1
3891 : continuity violations.
3892 :
3893 : First, minor errors are hard to catch - say, a 0.0001 difference in
3894 : the model values at two sides of the gap may be due to discontinuity
3895 : of the model - or simply because the model has changed.
3896 :
3897 : Second, C1-violations are especially difficult to detect in a
3898 : noninvasive way. The optimizer usually performs very short steps
3899 : near the nonsmoothness, and differentiation usually introduces a
3900 : lot of numerical noise. It is hard to tell whether some tiny
3901 : discontinuity in the slope is due to real nonsmoothness or just due
3902 : to numerical noise alone.
3903 :
3904 : Our top priority was to avoid false positives, so in some rare cases
3905 : minor errors may went unnoticed (however, in most cases they can be
3906 : spotted with restart from different initial point).
3907 :
3908 : INPUT PARAMETERS:
3909 : state - algorithm state
3910 : level - monitoring level:
3911 : * 0 - monitoring is disabled
3912 : * 1 - noninvasive low-overhead monitoring; function values
3913 : and/or gradients are recorded, but OptGuard does not
3914 : try to perform additional evaluations in order to
3915 : get more information about suspicious locations.
3916 :
3917 : === EXPLANATION ==========================================================
3918 :
3919 : One major source of headache during optimization is the possibility of
3920 : the coding errors in the target function/constraints (or their gradients).
3921 : Such errors most often manifest themselves as discontinuity or
3922 : nonsmoothness of the target/constraints.
3923 :
3924 : Another frequent situation is when you try to optimize something involving
3925 : lots of min() and max() operations, i.e. nonsmooth target. Although not a
3926 : coding error, it is nonsmoothness anyway - and smooth optimizers usually
3927 : stop right after encountering nonsmoothness, well before reaching solution.
3928 :
3929 : OptGuard integrity checker helps you to catch such situations: it monitors
3930 : function values/gradients being passed to the optimizer and tries to
3931 : errors. Upon discovering suspicious pair of points it raises appropriate
3932 : flag (and allows you to continue optimization). When optimization is done,
3933 : you can study OptGuard result.
3934 :
3935 : -- ALGLIB --
3936 : Copyright 21.11.2018 by Bochkanov Sergey
3937 : *************************************************************************/
3938 0 : void minbleicoptguardsmoothness(const minbleicstate &state, const ae_int_t level, const xparams _xparams)
3939 : {
3940 : jmp_buf _break_jump;
3941 : alglib_impl::ae_state _alglib_env_state;
3942 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3943 0 : if( setjmp(_break_jump) )
3944 : {
3945 : #if !defined(AE_NO_EXCEPTIONS)
3946 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3947 : #else
3948 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3949 : return;
3950 : #endif
3951 : }
3952 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3953 0 : if( _xparams.flags!=0x0 )
3954 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3955 0 : alglib_impl::minbleicoptguardsmoothness(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), level, &_alglib_env_state);
3956 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3957 0 : return;
3958 : }
3959 :
3960 : /*************************************************************************
3961 : This function activates/deactivates nonsmoothness monitoring option of
3962 : the OptGuard integrity checker. Smoothness monitor silently observes
3963 : solution process and tries to detect ill-posed problems, i.e. ones with:
3964 : a) discontinuous target function (non-C0)
3965 : b) nonsmooth target function (non-C1)
3966 :
3967 : Smoothness monitoring does NOT interrupt optimization even if it suspects
3968 : that your problem is nonsmooth. It just sets corresponding flags in the
3969 : OptGuard report which can be retrieved after optimization is over.
3970 :
3971 : Smoothness monitoring is a moderate overhead option which often adds less
3972 : than 1% to the optimizer running time. Thus, you can use it even for large
3973 : scale problems.
3974 :
3975 : NOTE: OptGuard does NOT guarantee that it will always detect C0/C1
3976 : continuity violations.
3977 :
3978 : First, minor errors are hard to catch - say, a 0.0001 difference in
3979 : the model values at two sides of the gap may be due to discontinuity
3980 : of the model - or simply because the model has changed.
3981 :
3982 : Second, C1-violations are especially difficult to detect in a
3983 : noninvasive way. The optimizer usually performs very short steps
3984 : near the nonsmoothness, and differentiation usually introduces a
3985 : lot of numerical noise. It is hard to tell whether some tiny
3986 : discontinuity in the slope is due to real nonsmoothness or just due
3987 : to numerical noise alone.
3988 :
3989 : Our top priority was to avoid false positives, so in some rare cases
3990 : minor errors may went unnoticed (however, in most cases they can be
3991 : spotted with restart from different initial point).
3992 :
3993 : INPUT PARAMETERS:
3994 : state - algorithm state
3995 : level - monitoring level:
3996 : * 0 - monitoring is disabled
3997 : * 1 - noninvasive low-overhead monitoring; function values
3998 : and/or gradients are recorded, but OptGuard does not
3999 : try to perform additional evaluations in order to
4000 : get more information about suspicious locations.
4001 :
4002 : === EXPLANATION ==========================================================
4003 :
4004 : One major source of headache during optimization is the possibility of
4005 : the coding errors in the target function/constraints (or their gradients).
4006 : Such errors most often manifest themselves as discontinuity or
4007 : nonsmoothness of the target/constraints.
4008 :
4009 : Another frequent situation is when you try to optimize something involving
4010 : lots of min() and max() operations, i.e. nonsmooth target. Although not a
4011 : coding error, it is nonsmoothness anyway - and smooth optimizers usually
4012 : stop right after encountering nonsmoothness, well before reaching solution.
4013 :
4014 : OptGuard integrity checker helps you to catch such situations: it monitors
4015 : function values/gradients being passed to the optimizer and tries to
4016 : errors. Upon discovering suspicious pair of points it raises appropriate
4017 : flag (and allows you to continue optimization). When optimization is done,
4018 : you can study OptGuard result.
4019 :
4020 : -- ALGLIB --
4021 : Copyright 21.11.2018 by Bochkanov Sergey
4022 : *************************************************************************/
4023 : #if !defined(AE_NO_EXCEPTIONS)
4024 0 : void minbleicoptguardsmoothness(const minbleicstate &state, const xparams _xparams)
4025 : {
4026 : jmp_buf _break_jump;
4027 : alglib_impl::ae_state _alglib_env_state;
4028 : ae_int_t level;
4029 :
4030 0 : level = 1;
4031 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4032 0 : if( setjmp(_break_jump) )
4033 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4034 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4035 0 : if( _xparams.flags!=0x0 )
4036 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4037 0 : alglib_impl::minbleicoptguardsmoothness(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), level, &_alglib_env_state);
4038 :
4039 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4040 0 : return;
4041 : }
4042 : #endif
4043 :
4044 : /*************************************************************************
4045 : Results of OptGuard integrity check, should be called after optimization
4046 : session is over.
4047 :
4048 : === PRIMARY REPORT =======================================================
4049 :
4050 : OptGuard performs several checks which are intended to catch common errors
4051 : in the implementation of nonlinear function/gradient:
4052 : * incorrect analytic gradient
4053 : * discontinuous (non-C0) target functions (constraints)
4054 : * nonsmooth (non-C1) target functions (constraints)
4055 :
4056 : Each of these checks is activated with appropriate function:
4057 : * minbleicoptguardgradient() for gradient verification
4058 : * minbleicoptguardsmoothness() for C0/C1 checks
4059 :
4060 : Following flags are set when these errors are suspected:
4061 : * rep.badgradsuspected, and additionally:
4062 : * rep.badgradvidx for specific variable (gradient element) suspected
4063 : * rep.badgradxbase, a point where gradient is tested
4064 : * rep.badgraduser, user-provided gradient (stored as 2D matrix with
4065 : single row in order to make report structure compatible with more
4066 : complex optimizers like MinNLC or MinLM)
4067 : * rep.badgradnum, reference gradient obtained via numerical
4068 : differentiation (stored as 2D matrix with single row in order to make
4069 : report structure compatible with more complex optimizers like MinNLC
4070 : or MinLM)
4071 : * rep.nonc0suspected
4072 : * rep.nonc1suspected
4073 :
4074 : === ADDITIONAL REPORTS/LOGS ==============================================
4075 :
4076 : Several different tests are performed to catch C0/C1 errors, you can find
4077 : out specific test signaled error by looking to:
4078 : * rep.nonc0test0positive, for non-C0 test #0
4079 : * rep.nonc1test0positive, for non-C1 test #0
4080 : * rep.nonc1test1positive, for non-C1 test #1
4081 :
4082 : Additional information (including line search logs) can be obtained by
4083 : means of:
4084 : * minbleicoptguardnonc1test0results()
4085 : * minbleicoptguardnonc1test1results()
4086 : which return detailed error reports, specific points where discontinuities
4087 : were found, and so on.
4088 :
4089 : ==========================================================================
4090 :
4091 : INPUT PARAMETERS:
4092 : state - algorithm state
4093 :
4094 : OUTPUT PARAMETERS:
4095 : rep - generic OptGuard report; more detailed reports can be
4096 : retrieved with other functions.
4097 :
4098 : NOTE: false negatives (nonsmooth problems are not identified as nonsmooth
4099 : ones) are possible although unlikely.
4100 :
4101 : The reason is that you need to make several evaluations around
4102 : nonsmoothness in order to accumulate enough information about
4103 : function curvature. Say, if you start right from the nonsmooth point,
4104 : optimizer simply won't get enough data to understand what is going
4105 : wrong before it terminates due to abrupt changes in the derivative.
4106 : It is also possible that "unlucky" step will move us to the
4107 : termination too quickly.
4108 :
4109 : Our current approach is to have less than 0.1% false negatives in
4110 : our test examples (measured with multiple restarts from random
4111 : points), and to have exactly 0% false positives.
4112 :
4113 : -- ALGLIB --
4114 : Copyright 21.11.2018 by Bochkanov Sergey
4115 : *************************************************************************/
4116 0 : void minbleicoptguardresults(const minbleicstate &state, optguardreport &rep, const xparams _xparams)
4117 : {
4118 : jmp_buf _break_jump;
4119 : alglib_impl::ae_state _alglib_env_state;
4120 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4121 0 : if( setjmp(_break_jump) )
4122 : {
4123 : #if !defined(AE_NO_EXCEPTIONS)
4124 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4125 : #else
4126 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4127 : return;
4128 : #endif
4129 : }
4130 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4131 0 : if( _xparams.flags!=0x0 )
4132 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4133 0 : alglib_impl::minbleicoptguardresults(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), const_cast<alglib_impl::optguardreport*>(rep.c_ptr()), &_alglib_env_state);
4134 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4135 0 : return;
4136 : }
4137 :
4138 : /*************************************************************************
4139 : Detailed results of the OptGuard integrity check for nonsmoothness test #0
4140 :
4141 : Nonsmoothness (non-C1) test #0 studies function values (not gradient!)
4142 : obtained during line searches and monitors behavior of the directional
4143 : derivative estimate.
4144 :
4145 : This test is less powerful than test #1, but it does not depend on the
4146 : gradient values and thus it is more robust against artifacts introduced by
4147 : numerical differentiation.
4148 :
4149 : Two reports are returned:
4150 : * a "strongest" one, corresponding to line search which had highest
4151 : value of the nonsmoothness indicator
4152 : * a "longest" one, corresponding to line search which had more function
4153 : evaluations, and thus is more detailed
4154 :
4155 : In both cases following fields are returned:
4156 :
4157 : * positive - is TRUE when test flagged suspicious point; FALSE if test
4158 : did not notice anything (in the latter cases fields below are empty).
4159 : * x0[], d[] - arrays of length N which store initial point and direction
4160 : for line search (d[] can be normalized, but does not have to)
4161 : * stp[], f[] - arrays of length CNT which store step lengths and function
4162 : values at these points; f[i] is evaluated in x0+stp[i]*d.
4163 : * stpidxa, stpidxb - we suspect that function violates C1 continuity
4164 : between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3,
4165 : with most likely position of the violation between stpidxa+1 and
4166 : stpidxa+2.
4167 :
4168 : ==========================================================================
4169 : = SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will
4170 : = see where C1 continuity is violated.
4171 : ==========================================================================
4172 :
4173 : INPUT PARAMETERS:
4174 : state - algorithm state
4175 :
4176 : OUTPUT PARAMETERS:
4177 : strrep - C1 test #0 "strong" report
4178 : lngrep - C1 test #0 "long" report
4179 :
4180 : -- ALGLIB --
4181 : Copyright 21.11.2018 by Bochkanov Sergey
4182 : *************************************************************************/
4183 0 : void minbleicoptguardnonc1test0results(const minbleicstate &state, optguardnonc1test0report &strrep, optguardnonc1test0report &lngrep, const xparams _xparams)
4184 : {
4185 : jmp_buf _break_jump;
4186 : alglib_impl::ae_state _alglib_env_state;
4187 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4188 0 : if( setjmp(_break_jump) )
4189 : {
4190 : #if !defined(AE_NO_EXCEPTIONS)
4191 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4192 : #else
4193 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4194 : return;
4195 : #endif
4196 : }
4197 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4198 0 : if( _xparams.flags!=0x0 )
4199 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4200 0 : alglib_impl::minbleicoptguardnonc1test0results(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), const_cast<alglib_impl::optguardnonc1test0report*>(strrep.c_ptr()), const_cast<alglib_impl::optguardnonc1test0report*>(lngrep.c_ptr()), &_alglib_env_state);
4201 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4202 0 : return;
4203 : }
4204 :
4205 : /*************************************************************************
4206 : Detailed results of the OptGuard integrity check for nonsmoothness test #1
4207 :
4208 : Nonsmoothness (non-C1) test #1 studies individual components of the
4209 : gradient computed during line search.
4210 :
4211 : When precise analytic gradient is provided this test is more powerful than
4212 : test #0 which works with function values and ignores user-provided
4213 : gradient. However, test #0 becomes more powerful when numerical
4214 : differentiation is employed (in such cases test #1 detects higher levels
4215 : of numerical noise and becomes too conservative).
4216 :
4217 : This test also tells specific components of the gradient which violate C1
4218 : continuity, which makes it more informative than #0, which just tells that
4219 : continuity is violated.
4220 :
4221 : Two reports are returned:
4222 : * a "strongest" one, corresponding to line search which had highest
4223 : value of the nonsmoothness indicator
4224 : * a "longest" one, corresponding to line search which had more function
4225 : evaluations, and thus is more detailed
4226 :
4227 : In both cases following fields are returned:
4228 :
4229 : * positive - is TRUE when test flagged suspicious point; FALSE if test
4230 : did not notice anything (in the latter cases fields below are empty).
4231 : * vidx - is an index of the variable in [0,N) with nonsmooth derivative
4232 : * x0[], d[] - arrays of length N which store initial point and direction
4233 : for line search (d[] can be normalized, but does not have to)
4234 : * stp[], g[] - arrays of length CNT which store step lengths and gradient
4235 : values at these points; g[i] is evaluated in x0+stp[i]*d and contains
4236 : vidx-th component of the gradient.
4237 : * stpidxa, stpidxb - we suspect that function violates C1 continuity
4238 : between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3,
4239 : with most likely position of the violation between stpidxa+1 and
4240 : stpidxa+2.
4241 :
4242 : ==========================================================================
4243 : = SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will
4244 : = see where C1 continuity is violated.
4245 : ==========================================================================
4246 :
4247 : INPUT PARAMETERS:
4248 : state - algorithm state
4249 :
4250 : OUTPUT PARAMETERS:
4251 : strrep - C1 test #1 "strong" report
4252 : lngrep - C1 test #1 "long" report
4253 :
4254 : -- ALGLIB --
4255 : Copyright 21.11.2018 by Bochkanov Sergey
4256 : *************************************************************************/
4257 0 : void minbleicoptguardnonc1test1results(const minbleicstate &state, optguardnonc1test1report &strrep, optguardnonc1test1report &lngrep, const xparams _xparams)
4258 : {
4259 : jmp_buf _break_jump;
4260 : alglib_impl::ae_state _alglib_env_state;
4261 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4262 0 : if( setjmp(_break_jump) )
4263 : {
4264 : #if !defined(AE_NO_EXCEPTIONS)
4265 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4266 : #else
4267 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4268 : return;
4269 : #endif
4270 : }
4271 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4272 0 : if( _xparams.flags!=0x0 )
4273 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4274 0 : alglib_impl::minbleicoptguardnonc1test1results(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), const_cast<alglib_impl::optguardnonc1test1report*>(strrep.c_ptr()), const_cast<alglib_impl::optguardnonc1test1report*>(lngrep.c_ptr()), &_alglib_env_state);
4275 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4276 0 : return;
4277 : }
4278 :
4279 : /*************************************************************************
4280 : BLEIC results
4281 :
4282 : INPUT PARAMETERS:
4283 : State - algorithm state
4284 :
4285 : OUTPUT PARAMETERS:
4286 : X - array[0..N-1], solution
4287 : Rep - optimization report. You should check Rep.TerminationType
4288 : in order to distinguish successful termination from
4289 : unsuccessful one:
4290 : * -8 internal integrity control detected infinite or
4291 : NAN values in function/gradient. Abnormal
4292 : termination signalled.
4293 : * -3 inconsistent constraints. Feasible point is
4294 : either nonexistent or too hard to find. Try to
4295 : restart optimizer with better initial approximation
4296 : * 1 relative function improvement is no more than EpsF.
4297 : * 2 scaled step is no more than EpsX.
4298 : * 4 scaled gradient norm is no more than EpsG.
4299 : * 5 MaxIts steps was taken
4300 : * 8 terminated by user who called minbleicrequesttermination().
4301 : X contains point which was "current accepted" when
4302 : termination request was submitted.
4303 : More information about fields of this structure can be
4304 : found in the comments on MinBLEICReport datatype.
4305 :
4306 : -- ALGLIB --
4307 : Copyright 28.11.2010 by Bochkanov Sergey
4308 : *************************************************************************/
4309 0 : void minbleicresults(const minbleicstate &state, real_1d_array &x, minbleicreport &rep, const xparams _xparams)
4310 : {
4311 : jmp_buf _break_jump;
4312 : alglib_impl::ae_state _alglib_env_state;
4313 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4314 0 : if( setjmp(_break_jump) )
4315 : {
4316 : #if !defined(AE_NO_EXCEPTIONS)
4317 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4318 : #else
4319 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4320 : return;
4321 : #endif
4322 : }
4323 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4324 0 : if( _xparams.flags!=0x0 )
4325 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4326 0 : 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);
4327 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4328 0 : return;
4329 : }
4330 :
4331 : /*************************************************************************
4332 : BLEIC results
4333 :
4334 : Buffered implementation of MinBLEICResults() which uses pre-allocated buffer
4335 : to store X[]. If buffer size is too small, it resizes buffer. It is
4336 : intended to be used in the inner cycles of performance critical algorithms
4337 : where array reallocation penalty is too large to be ignored.
4338 :
4339 : -- ALGLIB --
4340 : Copyright 28.11.2010 by Bochkanov Sergey
4341 : *************************************************************************/
4342 0 : void minbleicresultsbuf(const minbleicstate &state, real_1d_array &x, minbleicreport &rep, const xparams _xparams)
4343 : {
4344 : jmp_buf _break_jump;
4345 : alglib_impl::ae_state _alglib_env_state;
4346 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4347 0 : if( setjmp(_break_jump) )
4348 : {
4349 : #if !defined(AE_NO_EXCEPTIONS)
4350 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4351 : #else
4352 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4353 : return;
4354 : #endif
4355 : }
4356 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4357 0 : if( _xparams.flags!=0x0 )
4358 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4359 0 : 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);
4360 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4361 0 : return;
4362 : }
4363 :
4364 : /*************************************************************************
4365 : This subroutine restarts algorithm from new point.
4366 : All optimization parameters (including constraints) are left unchanged.
4367 :
4368 : This function allows to solve multiple optimization problems (which
4369 : must have same number of dimensions) without object reallocation penalty.
4370 :
4371 : INPUT PARAMETERS:
4372 : State - structure previously allocated with MinBLEICCreate call.
4373 : X - new starting point.
4374 :
4375 : -- ALGLIB --
4376 : Copyright 28.11.2010 by Bochkanov Sergey
4377 : *************************************************************************/
4378 0 : void minbleicrestartfrom(const minbleicstate &state, const real_1d_array &x, const xparams _xparams)
4379 : {
4380 : jmp_buf _break_jump;
4381 : alglib_impl::ae_state _alglib_env_state;
4382 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4383 0 : if( setjmp(_break_jump) )
4384 : {
4385 : #if !defined(AE_NO_EXCEPTIONS)
4386 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4387 : #else
4388 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4389 : return;
4390 : #endif
4391 : }
4392 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4393 0 : if( _xparams.flags!=0x0 )
4394 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4395 0 : alglib_impl::minbleicrestartfrom(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
4396 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4397 0 : return;
4398 : }
4399 :
4400 : /*************************************************************************
4401 : This subroutine submits request for termination of running optimizer. It
4402 : should be called from user-supplied callback when user decides that it is
4403 : time to "smoothly" terminate optimization process. As result, optimizer
4404 : stops at point which was "current accepted" when termination request was
4405 : submitted and returns error code 8 (successful termination).
4406 :
4407 : INPUT PARAMETERS:
4408 : State - optimizer structure
4409 :
4410 : NOTE: after request for termination optimizer may perform several
4411 : additional calls to user-supplied callbacks. It does NOT guarantee
4412 : to stop immediately - it just guarantees that these additional calls
4413 : will be discarded later.
4414 :
4415 : NOTE: calling this function on optimizer which is NOT running will have no
4416 : effect.
4417 :
4418 : NOTE: multiple calls to this function are possible. First call is counted,
4419 : subsequent calls are silently ignored.
4420 :
4421 : -- ALGLIB --
4422 : Copyright 08.10.2014 by Bochkanov Sergey
4423 : *************************************************************************/
4424 0 : void minbleicrequesttermination(const minbleicstate &state, const xparams _xparams)
4425 : {
4426 : jmp_buf _break_jump;
4427 : alglib_impl::ae_state _alglib_env_state;
4428 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4429 0 : if( setjmp(_break_jump) )
4430 : {
4431 : #if !defined(AE_NO_EXCEPTIONS)
4432 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4433 : #else
4434 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4435 : return;
4436 : #endif
4437 : }
4438 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4439 0 : if( _xparams.flags!=0x0 )
4440 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4441 0 : alglib_impl::minbleicrequesttermination(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), &_alglib_env_state);
4442 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4443 0 : return;
4444 : }
4445 : #endif
4446 :
4447 : #if defined(AE_COMPILE_QPBLEICSOLVER) || !defined(AE_PARTIAL_BUILD)
4448 :
4449 : #endif
4450 :
4451 : #if defined(AE_COMPILE_MINQP) || !defined(AE_PARTIAL_BUILD)
4452 : /*************************************************************************
4453 : This object stores nonlinear optimizer state.
4454 : You should use functions provided by MinQP subpackage to work with this
4455 : object
4456 : *************************************************************************/
4457 0 : _minqpstate_owner::_minqpstate_owner()
4458 : {
4459 : jmp_buf _break_jump;
4460 : alglib_impl::ae_state _state;
4461 :
4462 0 : alglib_impl::ae_state_init(&_state);
4463 0 : if( setjmp(_break_jump) )
4464 : {
4465 0 : if( p_struct!=NULL )
4466 : {
4467 0 : alglib_impl::_minqpstate_destroy(p_struct);
4468 0 : alglib_impl::ae_free(p_struct);
4469 : }
4470 0 : p_struct = NULL;
4471 : #if !defined(AE_NO_EXCEPTIONS)
4472 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
4473 : #else
4474 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
4475 : return;
4476 : #endif
4477 : }
4478 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
4479 0 : p_struct = NULL;
4480 0 : p_struct = (alglib_impl::minqpstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minqpstate), &_state);
4481 0 : memset(p_struct, 0, sizeof(alglib_impl::minqpstate));
4482 0 : alglib_impl::_minqpstate_init(p_struct, &_state, ae_false);
4483 0 : ae_state_clear(&_state);
4484 0 : }
4485 :
4486 0 : _minqpstate_owner::_minqpstate_owner(const _minqpstate_owner &rhs)
4487 : {
4488 : jmp_buf _break_jump;
4489 : alglib_impl::ae_state _state;
4490 :
4491 0 : alglib_impl::ae_state_init(&_state);
4492 0 : if( setjmp(_break_jump) )
4493 : {
4494 0 : if( p_struct!=NULL )
4495 : {
4496 0 : alglib_impl::_minqpstate_destroy(p_struct);
4497 0 : alglib_impl::ae_free(p_struct);
4498 : }
4499 0 : p_struct = NULL;
4500 : #if !defined(AE_NO_EXCEPTIONS)
4501 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
4502 : #else
4503 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
4504 : return;
4505 : #endif
4506 : }
4507 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
4508 0 : p_struct = NULL;
4509 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minqpstate copy constructor failure (source is not initialized)", &_state);
4510 0 : p_struct = (alglib_impl::minqpstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minqpstate), &_state);
4511 0 : memset(p_struct, 0, sizeof(alglib_impl::minqpstate));
4512 0 : alglib_impl::_minqpstate_init_copy(p_struct, const_cast<alglib_impl::minqpstate*>(rhs.p_struct), &_state, ae_false);
4513 0 : ae_state_clear(&_state);
4514 0 : }
4515 :
4516 0 : _minqpstate_owner& _minqpstate_owner::operator=(const _minqpstate_owner &rhs)
4517 : {
4518 0 : if( this==&rhs )
4519 0 : return *this;
4520 : jmp_buf _break_jump;
4521 : alglib_impl::ae_state _state;
4522 :
4523 0 : alglib_impl::ae_state_init(&_state);
4524 0 : if( setjmp(_break_jump) )
4525 : {
4526 : #if !defined(AE_NO_EXCEPTIONS)
4527 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
4528 : #else
4529 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
4530 : return *this;
4531 : #endif
4532 : }
4533 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
4534 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minqpstate assignment constructor failure (destination is not initialized)", &_state);
4535 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minqpstate assignment constructor failure (source is not initialized)", &_state);
4536 0 : alglib_impl::_minqpstate_destroy(p_struct);
4537 0 : memset(p_struct, 0, sizeof(alglib_impl::minqpstate));
4538 0 : alglib_impl::_minqpstate_init_copy(p_struct, const_cast<alglib_impl::minqpstate*>(rhs.p_struct), &_state, ae_false);
4539 0 : ae_state_clear(&_state);
4540 0 : return *this;
4541 : }
4542 :
4543 0 : _minqpstate_owner::~_minqpstate_owner()
4544 : {
4545 0 : if( p_struct!=NULL )
4546 : {
4547 0 : alglib_impl::_minqpstate_destroy(p_struct);
4548 0 : ae_free(p_struct);
4549 : }
4550 0 : }
4551 :
4552 0 : alglib_impl::minqpstate* _minqpstate_owner::c_ptr()
4553 : {
4554 0 : return p_struct;
4555 : }
4556 :
4557 0 : alglib_impl::minqpstate* _minqpstate_owner::c_ptr() const
4558 : {
4559 0 : return const_cast<alglib_impl::minqpstate*>(p_struct);
4560 : }
4561 0 : minqpstate::minqpstate() : _minqpstate_owner()
4562 : {
4563 0 : }
4564 :
4565 0 : minqpstate::minqpstate(const minqpstate &rhs):_minqpstate_owner(rhs)
4566 : {
4567 0 : }
4568 :
4569 0 : minqpstate& minqpstate::operator=(const minqpstate &rhs)
4570 : {
4571 0 : if( this==&rhs )
4572 0 : return *this;
4573 0 : _minqpstate_owner::operator=(rhs);
4574 0 : return *this;
4575 : }
4576 :
4577 0 : minqpstate::~minqpstate()
4578 : {
4579 0 : }
4580 :
4581 :
4582 : /*************************************************************************
4583 : This structure stores optimization report:
4584 : * InnerIterationsCount number of inner iterations
4585 : * OuterIterationsCount number of outer iterations
4586 : * NCholesky number of Cholesky decomposition
4587 : * NMV number of matrix-vector products
4588 : (only products calculated as part of iterative
4589 : process are counted)
4590 : * TerminationType completion code (see below)
4591 : * LagBC Lagrange multipliers for box constraints,
4592 : array[N], not filled by QP-BLEIC solver
4593 : * LagLC Lagrange multipliers for linear constraints,
4594 : array[MSparse+MDense], ignored by QP-BLEIC solver
4595 :
4596 : === COMPLETION CODES =====================================================
4597 :
4598 : Completion codes:
4599 : * -9 failure of the automatic scale evaluation: one of the diagonal
4600 : elements of the quadratic term is non-positive. Specify variable
4601 : scales manually!
4602 : * -5 inappropriate solver was used:
4603 : * QuickQP solver for problem with general linear constraints (dense/sparse)
4604 : * -4 BLEIC-QP or QuickQP solver found unconstrained direction
4605 : of negative curvature (function is unbounded from
4606 : below even under constraints), no meaningful
4607 : minimum can be found.
4608 : * -3 inconsistent constraints (or, maybe, feasible point is
4609 : too hard to find). If you are sure that constraints are feasible,
4610 : try to restart optimizer with better initial approximation.
4611 : * -2 IPM solver has difficulty finding primal/dual feasible point.
4612 : It is likely that the problem is either infeasible or unbounded,
4613 : but it is difficult to determine exact reason for termination.
4614 : X contains best point found so far.
4615 : * 1..4 successful completion
4616 : * 5 MaxIts steps was taken
4617 : * 7 stopping conditions are too stringent,
4618 : further improvement is impossible,
4619 : X contains best point found so far.
4620 :
4621 : === LAGRANGE MULTIPLIERS =================================================
4622 :
4623 : Some optimizers report values of Lagrange multipliers on successful
4624 : completion (positive completion code):
4625 : * DENSE-IPM-QP and SPARSE-IPM-QP return very precise Lagrange multipliers
4626 : as determined during solution process.
4627 : * DENSE-AUL-QP returns approximate Lagrange multipliers (which are very
4628 : close to "true" Lagrange multipliers except for overconstrained or
4629 : degenerate problems)
4630 :
4631 : Two arrays of multipliers are returned:
4632 : * LagBC is array[N] which is loaded with multipliers from box constraints;
4633 : LagBC[i]>0 means that I-th constraint is at the upper bound, LagBC[I]<0
4634 : means that I-th constraint is at the lower bound, LagBC[I]=0 means that
4635 : I-th box constraint is inactive.
4636 : * LagLC is array[MSparse+MDense] which is loaded with multipliers from
4637 : general linear constraints (former MSparse elements corresponds to
4638 : sparse part of the constraint matrix, latter MDense are for the dense
4639 : constraints, as was specified by user).
4640 : LagLC[i]>0 means that I-th constraint at the upper bound, LagLC[i]<0
4641 : means that I-th constraint is at the lower bound, LagLC[i]=0 means that
4642 : I-th linear constraint is inactive.
4643 :
4644 : On failure (or when optimizer does not support Lagrange multipliers) these
4645 : arrays are zero-filled.
4646 :
4647 : It is expected that at solution the dual feasibility condition holds:
4648 :
4649 : C+H*(Xs-X0) + SUM(Ei*LagBC[i],i=0..n-1) + SUM(Ai*LagLC[i],i=0..m-1) ~ 0
4650 :
4651 : where
4652 : * C is a linear term
4653 : * H is a quadratic term
4654 : * Xs is a solution, and X0 is an origin term (zero by default)
4655 : * Ei is a vector with 1.0 at position I and 0 in other positions
4656 : * Ai is an I-th row of linear constraint matrix
4657 :
4658 : NOTE: methods from IPM family may also return meaningful Lagrange
4659 : multipliers on completion with code -2 (infeasibility or
4660 : unboundedness detected).
4661 : *************************************************************************/
4662 0 : _minqpreport_owner::_minqpreport_owner()
4663 : {
4664 : jmp_buf _break_jump;
4665 : alglib_impl::ae_state _state;
4666 :
4667 0 : alglib_impl::ae_state_init(&_state);
4668 0 : if( setjmp(_break_jump) )
4669 : {
4670 0 : if( p_struct!=NULL )
4671 : {
4672 0 : alglib_impl::_minqpreport_destroy(p_struct);
4673 0 : alglib_impl::ae_free(p_struct);
4674 : }
4675 0 : p_struct = NULL;
4676 : #if !defined(AE_NO_EXCEPTIONS)
4677 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
4678 : #else
4679 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
4680 : return;
4681 : #endif
4682 : }
4683 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
4684 0 : p_struct = NULL;
4685 0 : p_struct = (alglib_impl::minqpreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minqpreport), &_state);
4686 0 : memset(p_struct, 0, sizeof(alglib_impl::minqpreport));
4687 0 : alglib_impl::_minqpreport_init(p_struct, &_state, ae_false);
4688 0 : ae_state_clear(&_state);
4689 0 : }
4690 :
4691 0 : _minqpreport_owner::_minqpreport_owner(const _minqpreport_owner &rhs)
4692 : {
4693 : jmp_buf _break_jump;
4694 : alglib_impl::ae_state _state;
4695 :
4696 0 : alglib_impl::ae_state_init(&_state);
4697 0 : if( setjmp(_break_jump) )
4698 : {
4699 0 : if( p_struct!=NULL )
4700 : {
4701 0 : alglib_impl::_minqpreport_destroy(p_struct);
4702 0 : alglib_impl::ae_free(p_struct);
4703 : }
4704 0 : p_struct = NULL;
4705 : #if !defined(AE_NO_EXCEPTIONS)
4706 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
4707 : #else
4708 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
4709 : return;
4710 : #endif
4711 : }
4712 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
4713 0 : p_struct = NULL;
4714 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minqpreport copy constructor failure (source is not initialized)", &_state);
4715 0 : p_struct = (alglib_impl::minqpreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minqpreport), &_state);
4716 0 : memset(p_struct, 0, sizeof(alglib_impl::minqpreport));
4717 0 : alglib_impl::_minqpreport_init_copy(p_struct, const_cast<alglib_impl::minqpreport*>(rhs.p_struct), &_state, ae_false);
4718 0 : ae_state_clear(&_state);
4719 0 : }
4720 :
4721 0 : _minqpreport_owner& _minqpreport_owner::operator=(const _minqpreport_owner &rhs)
4722 : {
4723 0 : if( this==&rhs )
4724 0 : return *this;
4725 : jmp_buf _break_jump;
4726 : alglib_impl::ae_state _state;
4727 :
4728 0 : alglib_impl::ae_state_init(&_state);
4729 0 : if( setjmp(_break_jump) )
4730 : {
4731 : #if !defined(AE_NO_EXCEPTIONS)
4732 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
4733 : #else
4734 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
4735 : return *this;
4736 : #endif
4737 : }
4738 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
4739 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minqpreport assignment constructor failure (destination is not initialized)", &_state);
4740 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minqpreport assignment constructor failure (source is not initialized)", &_state);
4741 0 : alglib_impl::_minqpreport_destroy(p_struct);
4742 0 : memset(p_struct, 0, sizeof(alglib_impl::minqpreport));
4743 0 : alglib_impl::_minqpreport_init_copy(p_struct, const_cast<alglib_impl::minqpreport*>(rhs.p_struct), &_state, ae_false);
4744 0 : ae_state_clear(&_state);
4745 0 : return *this;
4746 : }
4747 :
4748 0 : _minqpreport_owner::~_minqpreport_owner()
4749 : {
4750 0 : if( p_struct!=NULL )
4751 : {
4752 0 : alglib_impl::_minqpreport_destroy(p_struct);
4753 0 : ae_free(p_struct);
4754 : }
4755 0 : }
4756 :
4757 0 : alglib_impl::minqpreport* _minqpreport_owner::c_ptr()
4758 : {
4759 0 : return p_struct;
4760 : }
4761 :
4762 0 : alglib_impl::minqpreport* _minqpreport_owner::c_ptr() const
4763 : {
4764 0 : return const_cast<alglib_impl::minqpreport*>(p_struct);
4765 : }
4766 0 : minqpreport::minqpreport() : _minqpreport_owner() ,inneriterationscount(p_struct->inneriterationscount),outeriterationscount(p_struct->outeriterationscount),nmv(p_struct->nmv),ncholesky(p_struct->ncholesky),terminationtype(p_struct->terminationtype),lagbc(&p_struct->lagbc),laglc(&p_struct->laglc)
4767 : {
4768 0 : }
4769 :
4770 0 : minqpreport::minqpreport(const minqpreport &rhs):_minqpreport_owner(rhs) ,inneriterationscount(p_struct->inneriterationscount),outeriterationscount(p_struct->outeriterationscount),nmv(p_struct->nmv),ncholesky(p_struct->ncholesky),terminationtype(p_struct->terminationtype),lagbc(&p_struct->lagbc),laglc(&p_struct->laglc)
4771 : {
4772 0 : }
4773 :
4774 0 : minqpreport& minqpreport::operator=(const minqpreport &rhs)
4775 : {
4776 0 : if( this==&rhs )
4777 0 : return *this;
4778 0 : _minqpreport_owner::operator=(rhs);
4779 0 : return *this;
4780 : }
4781 :
4782 0 : minqpreport::~minqpreport()
4783 : {
4784 0 : }
4785 :
4786 : /*************************************************************************
4787 : CONSTRAINED QUADRATIC PROGRAMMING
4788 :
4789 : The subroutine creates QP optimizer. After initial creation, it contains
4790 : default optimization problem with zero quadratic and linear terms and no
4791 : constraints.
4792 :
4793 : In order to actually solve something you should:
4794 : * set cost vector with minqpsetlinearterm()
4795 : * set variable bounds with minqpsetbc() or minqpsetbcall()
4796 : * specify constraint matrix with one of the following functions:
4797 : * modern API:
4798 : * minqpsetlc2() for sparse two-sided constraints AL <= A*x <= AU
4799 : * minqpsetlc2dense() for dense two-sided constraints AL <= A*x <= AU
4800 : * minqpsetlc2mixed() for mixed two-sided constraints AL <= A*x <= AU
4801 : * minqpaddlc2dense() to add one dense row to dense constraint submatrix
4802 : * minqpaddlc2() to add one sparse row to sparse constraint submatrix
4803 : * legacy API:
4804 : * minqpsetlc() for dense one-sided equality/inequality constraints
4805 : * minqpsetlcsparse() for sparse one-sided equality/inequality constraints
4806 : * minqpsetlcmixed() for mixed dense/sparse one-sided equality/inequality constraints
4807 : * choose appropriate QP solver and set it and its stopping criteria by
4808 : means of minqpsetalgo??????() function
4809 : * call minqpoptimize() to run the solver and minqpresults() to get the
4810 : solution vector and additional information.
4811 :
4812 : Following solvers are recommended for convex and semidefinite problems:
4813 : * QuickQP for dense problems with box-only constraints (or no constraints
4814 : at all)
4815 : * DENSE-IPM-QP for convex or semidefinite problems with medium (up
4816 : to several thousands) variable count, dense/sparse quadratic term and
4817 : any number (up to many thousands) of dense/sparse general linear
4818 : constraints
4819 : * SPARSE-IPM-QP for convex or semidefinite problems with large (many
4820 : thousands) variable count, sparse quadratic term AND linear constraints.
4821 :
4822 : If your problem happens to be nonconvex, but either (a) is effectively
4823 : convexified under constraints, or (b) has unique solution even with
4824 : nonconvex target, then you can use:
4825 : * QuickQP for dense nonconvex problems with box-only constraints
4826 : * DENSE-AUL-QP for dense nonconvex problems which are effectively
4827 : convexified under constraints with up to several thousands of variables
4828 : and any (small or large) number of general linear constraints
4829 : * QP-BLEIC for dense/sparse problems with small (up to several hundreds)
4830 : number of general linear constraints and arbitrarily large variable
4831 : count.
4832 :
4833 : INPUT PARAMETERS:
4834 : N - problem size
4835 :
4836 : OUTPUT PARAMETERS:
4837 : State - optimizer with zero quadratic/linear terms
4838 : and no constraints
4839 :
4840 : -- ALGLIB --
4841 : Copyright 11.01.2011 by Bochkanov Sergey
4842 : *************************************************************************/
4843 0 : void minqpcreate(const ae_int_t n, minqpstate &state, const xparams _xparams)
4844 : {
4845 : jmp_buf _break_jump;
4846 : alglib_impl::ae_state _alglib_env_state;
4847 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4848 0 : if( setjmp(_break_jump) )
4849 : {
4850 : #if !defined(AE_NO_EXCEPTIONS)
4851 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4852 : #else
4853 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4854 : return;
4855 : #endif
4856 : }
4857 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4858 0 : if( _xparams.flags!=0x0 )
4859 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4860 0 : alglib_impl::minqpcreate(n, const_cast<alglib_impl::minqpstate*>(state.c_ptr()), &_alglib_env_state);
4861 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4862 0 : return;
4863 : }
4864 :
4865 : /*************************************************************************
4866 : This function sets linear term for QP solver.
4867 :
4868 : By default, linear term is zero.
4869 :
4870 : INPUT PARAMETERS:
4871 : State - structure which stores algorithm state
4872 : B - linear term, array[N].
4873 :
4874 : -- ALGLIB --
4875 : Copyright 11.01.2011 by Bochkanov Sergey
4876 : *************************************************************************/
4877 0 : void minqpsetlinearterm(const minqpstate &state, const real_1d_array &b, const xparams _xparams)
4878 : {
4879 : jmp_buf _break_jump;
4880 : alglib_impl::ae_state _alglib_env_state;
4881 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4882 0 : if( setjmp(_break_jump) )
4883 : {
4884 : #if !defined(AE_NO_EXCEPTIONS)
4885 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4886 : #else
4887 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4888 : return;
4889 : #endif
4890 : }
4891 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4892 0 : if( _xparams.flags!=0x0 )
4893 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4894 0 : alglib_impl::minqpsetlinearterm(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(b.c_ptr()), &_alglib_env_state);
4895 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4896 0 : return;
4897 : }
4898 :
4899 : /*************************************************************************
4900 : This function sets dense quadratic term for QP solver. By default,
4901 : quadratic term is zero.
4902 :
4903 : IMPORTANT:
4904 :
4905 : This solver minimizes following function:
4906 : f(x) = 0.5*x'*A*x + b'*x.
4907 : Note that quadratic term has 0.5 before it. So if you want to minimize
4908 : f(x) = x^2 + x
4909 : you should rewrite your problem as follows:
4910 : f(x) = 0.5*(2*x^2) + x
4911 : and your matrix A will be equal to [[2.0]], not to [[1.0]]
4912 :
4913 : INPUT PARAMETERS:
4914 : State - structure which stores algorithm state
4915 : A - matrix, array[N,N]
4916 : IsUpper - (optional) storage type:
4917 : * if True, symmetric matrix A is given by its upper
4918 : triangle, and the lower triangle isn't used
4919 : * if False, symmetric matrix A is given by its lower
4920 : triangle, and the upper triangle isn't used
4921 : * if not given, both lower and upper triangles must be
4922 : filled.
4923 :
4924 : -- ALGLIB --
4925 : Copyright 11.01.2011 by Bochkanov Sergey
4926 : *************************************************************************/
4927 0 : void minqpsetquadraticterm(const minqpstate &state, const real_2d_array &a, const bool isupper, const xparams _xparams)
4928 : {
4929 : jmp_buf _break_jump;
4930 : alglib_impl::ae_state _alglib_env_state;
4931 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4932 0 : if( setjmp(_break_jump) )
4933 : {
4934 : #if !defined(AE_NO_EXCEPTIONS)
4935 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4936 : #else
4937 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4938 : return;
4939 : #endif
4940 : }
4941 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4942 0 : if( _xparams.flags!=0x0 )
4943 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4944 0 : alglib_impl::minqpsetquadraticterm(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), isupper, &_alglib_env_state);
4945 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4946 0 : return;
4947 : }
4948 :
4949 : /*************************************************************************
4950 : This function sets dense quadratic term for QP solver. By default,
4951 : quadratic term is zero.
4952 :
4953 : IMPORTANT:
4954 :
4955 : This solver minimizes following function:
4956 : f(x) = 0.5*x'*A*x + b'*x.
4957 : Note that quadratic term has 0.5 before it. So if you want to minimize
4958 : f(x) = x^2 + x
4959 : you should rewrite your problem as follows:
4960 : f(x) = 0.5*(2*x^2) + x
4961 : and your matrix A will be equal to [[2.0]], not to [[1.0]]
4962 :
4963 : INPUT PARAMETERS:
4964 : State - structure which stores algorithm state
4965 : A - matrix, array[N,N]
4966 : IsUpper - (optional) storage type:
4967 : * if True, symmetric matrix A is given by its upper
4968 : triangle, and the lower triangle isn't used
4969 : * if False, symmetric matrix A is given by its lower
4970 : triangle, and the upper triangle isn't used
4971 : * if not given, both lower and upper triangles must be
4972 : filled.
4973 :
4974 : -- ALGLIB --
4975 : Copyright 11.01.2011 by Bochkanov Sergey
4976 : *************************************************************************/
4977 : #if !defined(AE_NO_EXCEPTIONS)
4978 0 : void minqpsetquadraticterm(const minqpstate &state, const real_2d_array &a, const xparams _xparams)
4979 : {
4980 : jmp_buf _break_jump;
4981 : alglib_impl::ae_state _alglib_env_state;
4982 : bool isupper;
4983 0 : if( !alglib_impl::ae_is_symmetric(const_cast<alglib_impl::ae_matrix*>(a.c_ptr())) )
4984 0 : _ALGLIB_CPP_EXCEPTION("'a' parameter is not symmetric matrix");
4985 0 : isupper = false;
4986 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4987 0 : if( setjmp(_break_jump) )
4988 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4989 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4990 0 : if( _xparams.flags!=0x0 )
4991 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4992 0 : alglib_impl::minqpsetquadraticterm(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), isupper, &_alglib_env_state);
4993 :
4994 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4995 0 : return;
4996 : }
4997 : #endif
4998 :
4999 : /*************************************************************************
5000 : This function sets sparse quadratic term for QP solver. By default,
5001 : quadratic term is zero. This function overrides previous calls to
5002 : minqpsetquadraticterm() or minqpsetquadratictermsparse().
5003 :
5004 : NOTE: dense solvers like DENSE-AUL-QP or DENSE-IPM-QP will convert this
5005 : matrix to dense storage anyway.
5006 :
5007 : IMPORTANT:
5008 :
5009 : This solver minimizes following function:
5010 : f(x) = 0.5*x'*A*x + b'*x.
5011 : Note that quadratic term has 0.5 before it. So if you want to minimize
5012 : f(x) = x^2 + x
5013 : you should rewrite your problem as follows:
5014 : f(x) = 0.5*(2*x^2) + x
5015 : and your matrix A will be equal to [[2.0]], not to [[1.0]]
5016 :
5017 : INPUT PARAMETERS:
5018 : State - structure which stores algorithm state
5019 : A - matrix, array[N,N]
5020 : IsUpper - (optional) storage type:
5021 : * if True, symmetric matrix A is given by its upper
5022 : triangle, and the lower triangle isn't used
5023 : * if False, symmetric matrix A is given by its lower
5024 : triangle, and the upper triangle isn't used
5025 : * if not given, both lower and upper triangles must be
5026 : filled.
5027 :
5028 : -- ALGLIB --
5029 : Copyright 11.01.2011 by Bochkanov Sergey
5030 : *************************************************************************/
5031 0 : void minqpsetquadratictermsparse(const minqpstate &state, const sparsematrix &a, const bool isupper, const xparams _xparams)
5032 : {
5033 : jmp_buf _break_jump;
5034 : alglib_impl::ae_state _alglib_env_state;
5035 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5036 0 : if( setjmp(_break_jump) )
5037 : {
5038 : #if !defined(AE_NO_EXCEPTIONS)
5039 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5040 : #else
5041 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5042 : return;
5043 : #endif
5044 : }
5045 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5046 0 : if( _xparams.flags!=0x0 )
5047 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5048 0 : alglib_impl::minqpsetquadratictermsparse(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::sparsematrix*>(a.c_ptr()), isupper, &_alglib_env_state);
5049 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5050 0 : return;
5051 : }
5052 :
5053 : /*************************************************************************
5054 : This function sets starting point for QP solver. It is useful to have good
5055 : initial approximation to the solution, because it will increase speed of
5056 : convergence and identification of active constraints.
5057 :
5058 : NOTE: interior point solvers ignore initial point provided by user.
5059 :
5060 : INPUT PARAMETERS:
5061 : State - structure which stores algorithm state
5062 : X - starting point, array[N].
5063 :
5064 : -- ALGLIB --
5065 : Copyright 11.01.2011 by Bochkanov Sergey
5066 : *************************************************************************/
5067 0 : void minqpsetstartingpoint(const minqpstate &state, const real_1d_array &x, const xparams _xparams)
5068 : {
5069 : jmp_buf _break_jump;
5070 : alglib_impl::ae_state _alglib_env_state;
5071 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5072 0 : if( setjmp(_break_jump) )
5073 : {
5074 : #if !defined(AE_NO_EXCEPTIONS)
5075 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5076 : #else
5077 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5078 : return;
5079 : #endif
5080 : }
5081 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5082 0 : if( _xparams.flags!=0x0 )
5083 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5084 0 : alglib_impl::minqpsetstartingpoint(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
5085 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5086 0 : return;
5087 : }
5088 :
5089 : /*************************************************************************
5090 : This function sets origin for QP solver. By default, following QP program
5091 : is solved:
5092 :
5093 : min(0.5*x'*A*x+b'*x)
5094 :
5095 : This function allows to solve different problem:
5096 :
5097 : min(0.5*(x-x_origin)'*A*(x-x_origin)+b'*(x-x_origin))
5098 :
5099 : Specification of non-zero origin affects function being minimized, but not
5100 : constraints. Box and linear constraints are still calculated without
5101 : origin.
5102 :
5103 : INPUT PARAMETERS:
5104 : State - structure which stores algorithm state
5105 : XOrigin - origin, array[N].
5106 :
5107 : -- ALGLIB --
5108 : Copyright 11.01.2011 by Bochkanov Sergey
5109 : *************************************************************************/
5110 0 : void minqpsetorigin(const minqpstate &state, const real_1d_array &xorigin, const xparams _xparams)
5111 : {
5112 : jmp_buf _break_jump;
5113 : alglib_impl::ae_state _alglib_env_state;
5114 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5115 0 : if( setjmp(_break_jump) )
5116 : {
5117 : #if !defined(AE_NO_EXCEPTIONS)
5118 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5119 : #else
5120 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5121 : return;
5122 : #endif
5123 : }
5124 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5125 0 : if( _xparams.flags!=0x0 )
5126 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5127 0 : alglib_impl::minqpsetorigin(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(xorigin.c_ptr()), &_alglib_env_state);
5128 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5129 0 : return;
5130 : }
5131 :
5132 : /*************************************************************************
5133 : This function sets scaling coefficients.
5134 :
5135 : ALGLIB optimizers use scaling matrices to test stopping conditions (step
5136 : size and gradient are scaled before comparison with tolerances) and as
5137 : preconditioner.
5138 :
5139 : Scale of the I-th variable is a translation invariant measure of:
5140 : a) "how large" the variable is
5141 : b) how large the step should be to make significant changes in the
5142 : function
5143 :
5144 : If you do not know how to choose scales of your variables, you can:
5145 : * read www.alglib.net/optimization/scaling.php article
5146 : * use minqpsetscaleautodiag(), which calculates scale using diagonal of
5147 : the quadratic term: S is set to 1/sqrt(diag(A)), which works well
5148 : sometimes.
5149 :
5150 : INPUT PARAMETERS:
5151 : State - structure stores algorithm state
5152 : S - array[N], non-zero scaling coefficients
5153 : S[i] may be negative, sign doesn't matter.
5154 :
5155 : -- ALGLIB --
5156 : Copyright 14.01.2011 by Bochkanov Sergey
5157 : *************************************************************************/
5158 0 : void minqpsetscale(const minqpstate &state, const real_1d_array &s, const xparams _xparams)
5159 : {
5160 : jmp_buf _break_jump;
5161 : alglib_impl::ae_state _alglib_env_state;
5162 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5163 0 : if( setjmp(_break_jump) )
5164 : {
5165 : #if !defined(AE_NO_EXCEPTIONS)
5166 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5167 : #else
5168 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5169 : return;
5170 : #endif
5171 : }
5172 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5173 0 : if( _xparams.flags!=0x0 )
5174 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5175 0 : alglib_impl::minqpsetscale(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(s.c_ptr()), &_alglib_env_state);
5176 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5177 0 : return;
5178 : }
5179 :
5180 : /*************************************************************************
5181 : This function sets automatic evaluation of variable scaling.
5182 :
5183 : IMPORTANT: this function works only for matrices with positive diagonal
5184 : elements! Zero or negative elements will result in -9 error
5185 : code being returned. Specify scale vector manually with
5186 : minqpsetscale() in such cases.
5187 :
5188 : ALGLIB optimizers use scaling matrices to test stopping conditions (step
5189 : size and gradient are scaled before comparison with tolerances) and as
5190 : preconditioner.
5191 :
5192 : The best way to set scaling is to manually specify variable scales.
5193 : However, sometimes you just need quick-and-dirty solution - either when
5194 : you perform fast prototyping, or when you know your problem well and you
5195 : are 100% sure that this quick solution is robust enough in your case.
5196 :
5197 : One such solution is to evaluate scale of I-th variable as 1/Sqrt(A[i,i]),
5198 : where A[i,i] is an I-th diagonal element of the quadratic term.
5199 :
5200 : Such approach works well sometimes, but you have to be careful here.
5201 :
5202 : INPUT PARAMETERS:
5203 : State - structure stores algorithm state
5204 :
5205 : -- ALGLIB --
5206 : Copyright 26.12.2017 by Bochkanov Sergey
5207 : *************************************************************************/
5208 0 : void minqpsetscaleautodiag(const minqpstate &state, const xparams _xparams)
5209 : {
5210 : jmp_buf _break_jump;
5211 : alglib_impl::ae_state _alglib_env_state;
5212 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5213 0 : if( setjmp(_break_jump) )
5214 : {
5215 : #if !defined(AE_NO_EXCEPTIONS)
5216 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5217 : #else
5218 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5219 : return;
5220 : #endif
5221 : }
5222 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5223 0 : if( _xparams.flags!=0x0 )
5224 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5225 0 : alglib_impl::minqpsetscaleautodiag(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), &_alglib_env_state);
5226 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5227 0 : return;
5228 : }
5229 :
5230 : /*************************************************************************
5231 : This function tells solver to use BLEIC-based algorithm and sets stopping
5232 : criteria for the algorithm.
5233 :
5234 : This algorithm is intended for large-scale problems, possibly nonconvex,
5235 : with small number of general linear constraints. Feasible initial point is
5236 : essential for good performance.
5237 :
5238 : IMPORTANT: when DENSE-IPM (or DENSE-AUL for nonconvex problems) solvers
5239 : are applicable, their performance is much better than that of
5240 : BLEIC-QP.
5241 : We recommend you to use BLEIC only when other solvers can not
5242 : be used.
5243 :
5244 : ALGORITHM FEATURES:
5245 :
5246 : * supports dense and sparse QP problems
5247 : * supports box and general linear equality/inequality constraints
5248 : * can solve all types of problems (convex, semidefinite, nonconvex) as
5249 : long as they are bounded from below under constraints.
5250 : Say, it is possible to solve "min{-x^2} subject to -1<=x<=+1".
5251 : Of course, global minimum is found only for positive definite and
5252 : semidefinite problems. As for indefinite ones - only local minimum is
5253 : found.
5254 :
5255 : ALGORITHM OUTLINE:
5256 :
5257 : * BLEIC-QP solver is just a driver function for MinBLEIC solver; it solves
5258 : quadratic programming problem as general linearly constrained
5259 : optimization problem, which is solved by means of BLEIC solver (part of
5260 : ALGLIB, active set method).
5261 :
5262 : ALGORITHM LIMITATIONS:
5263 : * This algorithm is inefficient on problems with hundreds and thousands
5264 : of general inequality constraints and infeasible initial point. Initial
5265 : feasibility detection stage may take too long on such constraint sets.
5266 : Consider using DENSE-IPM or DENSE-AUL instead.
5267 : * unlike QuickQP solver, this algorithm does not perform Newton steps and
5268 : does not use Level 3 BLAS. Being general-purpose active set method, it
5269 : can activate constraints only one-by-one. Thus, its performance is lower
5270 : than that of QuickQP.
5271 : * its precision is also a bit inferior to that of QuickQP. BLEIC-QP
5272 : performs only LBFGS steps (no Newton steps), which are good at detecting
5273 : neighborhood of the solution, buy needs many iterations to find solution
5274 : with more than 6 digits of precision.
5275 :
5276 : INPUT PARAMETERS:
5277 : State - structure which stores algorithm state
5278 : EpsG - >=0
5279 : The subroutine finishes its work if the condition
5280 : |v|<EpsG is satisfied, where:
5281 : * |.| means Euclidian norm
5282 : * v - scaled constrained gradient vector, v[i]=g[i]*s[i]
5283 : * g - gradient
5284 : * s - scaling coefficients set by MinQPSetScale()
5285 : EpsF - >=0
5286 : The subroutine finishes its work if exploratory steepest
5287 : descent step on k+1-th iteration satisfies following
5288 : condition: |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
5289 : EpsX - >=0
5290 : The subroutine finishes its work if exploratory steepest
5291 : descent step on k+1-th iteration satisfies following
5292 : condition:
5293 : * |.| means Euclidian norm
5294 : * v - scaled step vector, v[i]=dx[i]/s[i]
5295 : * dx - step vector, dx=X(k+1)-X(k)
5296 : * s - scaling coefficients set by MinQPSetScale()
5297 : MaxIts - maximum number of iterations. If MaxIts=0, the number of
5298 : iterations is unlimited. NOTE: this algorithm uses LBFGS
5299 : iterations, which are relatively cheap, but improve
5300 : function value only a bit. So you will need many iterations
5301 : to converge - from 0.1*N to 10*N, depending on problem's
5302 : condition number.
5303 :
5304 : IT IS VERY IMPORTANT TO CALL MinQPSetScale() WHEN YOU USE THIS ALGORITHM
5305 : BECAUSE ITS STOPPING CRITERIA ARE SCALE-DEPENDENT!
5306 :
5307 : Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead
5308 : to automatic stopping criterion selection (presently it is small step
5309 : length, but it may change in the future versions of ALGLIB).
5310 :
5311 : -- ALGLIB --
5312 : Copyright 11.01.2011 by Bochkanov Sergey
5313 : *************************************************************************/
5314 0 : void minqpsetalgobleic(const minqpstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits, const xparams _xparams)
5315 : {
5316 : jmp_buf _break_jump;
5317 : alglib_impl::ae_state _alglib_env_state;
5318 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5319 0 : if( setjmp(_break_jump) )
5320 : {
5321 : #if !defined(AE_NO_EXCEPTIONS)
5322 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5323 : #else
5324 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5325 : return;
5326 : #endif
5327 : }
5328 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5329 0 : if( _xparams.flags!=0x0 )
5330 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5331 0 : alglib_impl::minqpsetalgobleic(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), epsg, epsf, epsx, maxits, &_alglib_env_state);
5332 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5333 0 : return;
5334 : }
5335 :
5336 : /*************************************************************************
5337 : This function tells QP solver to use DENSE-AUL algorithm and sets stopping
5338 : criteria for the algorithm.
5339 :
5340 : This algorithm is intended for non-convex problems with moderate (up
5341 : to several thousands) variable count and arbitrary number of constraints
5342 : which are either (a) effectively convexified under constraints or (b) have
5343 : unique solution even with nonconvex target.
5344 :
5345 : IMPORTANT: when DENSE-IPM solver is applicable, its performance is usually
5346 : much better than that of DENSE-AUL.
5347 : We recommend you to use DENSE-AUL only when other solvers can
5348 : not be used.
5349 :
5350 : ALGORITHM FEATURES:
5351 :
5352 : * supports box and dense/sparse general linear equality/inequality
5353 : constraints
5354 : * convergence is theoretically proved for positive-definite (convex) QP
5355 : problems. Semidefinite and non-convex problems can be solved as long as
5356 : they are bounded from below under constraints, although without
5357 : theoretical guarantees.
5358 :
5359 : ALGORITHM OUTLINE:
5360 :
5361 : * this algorithm is an augmented Lagrangian method with dense
5362 : preconditioner (hence its name).
5363 : * it performs several outer iterations in order to refine values of the
5364 : Lagrange multipliers. Single outer iteration is a solution of some
5365 : unconstrained optimization problem: first it performs dense Cholesky
5366 : factorization of the Hessian in order to build preconditioner (adaptive
5367 : regularization is applied to enforce positive definiteness), and then
5368 : it uses L-BFGS optimizer to solve optimization problem.
5369 : * typically you need about 5-10 outer iterations to converge to solution
5370 :
5371 : ALGORITHM LIMITATIONS:
5372 :
5373 : * because dense Cholesky driver is used, this algorithm has O(N^2) memory
5374 : requirements and O(OuterIterations*N^3) minimum running time. From the
5375 : practical point of view, it limits its applicability by several
5376 : thousands of variables.
5377 : From the other side, variables count is the most limiting factor,
5378 : and dependence on constraint count is much more lower. Assuming that
5379 : constraint matrix is sparse, it may handle tens of thousands of general
5380 : linear constraints.
5381 :
5382 : INPUT PARAMETERS:
5383 : State - structure which stores algorithm state
5384 : EpsX - >=0, stopping criteria for inner optimizer.
5385 : Inner iterations are stopped when step length (with
5386 : variable scaling being applied) is less than EpsX.
5387 : See minqpsetscale() for more information on variable
5388 : scaling.
5389 : Rho - penalty coefficient, Rho>0:
5390 : * large enough that algorithm converges with desired
5391 : precision.
5392 : * not TOO large to prevent ill-conditioning
5393 : * recommended values are 100, 1000 or 10000
5394 : ItsCnt - number of outer iterations:
5395 : * recommended values: 10-15 (although in most cases it
5396 : converges within 5 iterations, you may need a few more
5397 : to be sure).
5398 : * ItsCnt=0 means that small number of outer iterations is
5399 : automatically chosen (10 iterations in current version).
5400 : * ItsCnt=1 means that AUL algorithm performs just as usual
5401 : penalty method.
5402 : * ItsCnt>1 means that AUL algorithm performs specified
5403 : number of outer iterations
5404 :
5405 : IT IS VERY IMPORTANT TO CALL minqpsetscale() WHEN YOU USE THIS ALGORITHM
5406 : BECAUSE ITS CONVERGENCE PROPERTIES AND STOPPING CRITERIA ARE SCALE-DEPENDENT!
5407 :
5408 : NOTE: Passing EpsX=0 will lead to automatic step length selection
5409 : (specific step length chosen may change in the future versions of
5410 : ALGLIB, so it is better to specify step length explicitly).
5411 :
5412 : -- ALGLIB --
5413 : Copyright 20.08.2016 by Bochkanov Sergey
5414 : *************************************************************************/
5415 0 : void minqpsetalgodenseaul(const minqpstate &state, const double epsx, const double rho, const ae_int_t itscnt, const xparams _xparams)
5416 : {
5417 : jmp_buf _break_jump;
5418 : alglib_impl::ae_state _alglib_env_state;
5419 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5420 0 : if( setjmp(_break_jump) )
5421 : {
5422 : #if !defined(AE_NO_EXCEPTIONS)
5423 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5424 : #else
5425 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5426 : return;
5427 : #endif
5428 : }
5429 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5430 0 : if( _xparams.flags!=0x0 )
5431 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5432 0 : alglib_impl::minqpsetalgodenseaul(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), epsx, rho, itscnt, &_alglib_env_state);
5433 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5434 0 : return;
5435 : }
5436 :
5437 : /*************************************************************************
5438 : This function tells QP solver to use DENSE-IPM QP algorithm and sets
5439 : stopping criteria for the algorithm.
5440 :
5441 : This algorithm is intended for convex and semidefinite problems with
5442 : moderate (up to several thousands) variable count and arbitrary number of
5443 : constraints.
5444 :
5445 : IMPORTANT: this algorithm won't work for nonconvex problems, use DENSE-AUL
5446 : or BLEIC-QP instead. If you try to run DENSE-IPM on problem
5447 : with indefinite matrix (matrix having at least one negative
5448 : eigenvalue) then depending on circumstances it may either (a)
5449 : stall at some arbitrary point, or (b) throw exception on
5450 : failure of Cholesky decomposition.
5451 :
5452 : ALGORITHM FEATURES:
5453 :
5454 : * supports box and dense/sparse general linear equality/inequality
5455 : constraints
5456 :
5457 : ALGORITHM OUTLINE:
5458 :
5459 : * this algorithm is our implementation of interior point method as
5460 : formulated by R.J.Vanderbei, with minor modifications to the algorithm
5461 : (damped Newton directions are extensively used)
5462 : * like all interior point methods, this algorithm tends to converge in
5463 : roughly same number of iterations (between 15 and 50) independently from
5464 : the problem dimensionality
5465 :
5466 : ALGORITHM LIMITATIONS:
5467 :
5468 : * because dense Cholesky driver is used, for N-dimensional problem with
5469 : M dense constaints this algorithm has O(N^2+N*M) memory requirements and
5470 : O(N^3+N*M^2) running time.
5471 : Having sparse constraints with Z nonzeros per row relaxes storage and
5472 : running time down to O(N^2+M*Z) and O(N^3+N*Z^2)
5473 : From the practical point of view, it limits its applicability by
5474 : several thousands of variables.
5475 : From the other side, variables count is the most limiting factor,
5476 : and dependence on constraint count is much more lower. Assuming that
5477 : constraint matrix is sparse, it may handle tens of thousands of general
5478 : linear constraints.
5479 :
5480 : INPUT PARAMETERS:
5481 : State - structure which stores algorithm state
5482 : Eps - >=0, stopping criteria. The algorithm stops when primal
5483 : and dual infeasiblities as well as complementarity gap are
5484 : less than Eps.
5485 :
5486 : IT IS VERY IMPORTANT TO CALL minqpsetscale() WHEN YOU USE THIS ALGORITHM
5487 : BECAUSE ITS CONVERGENCE PROPERTIES AND STOPPING CRITERIA ARE SCALE-DEPENDENT!
5488 :
5489 : NOTE: Passing EpsX=0 will lead to automatic selection of small epsilon.
5490 :
5491 : ===== TRACING IPM SOLVER =================================================
5492 :
5493 : IPM solver supports advanced tracing capabilities. You can trace algorithm
5494 : output by specifying following trace symbols (case-insensitive) by means
5495 : of trace_file() call:
5496 : * 'IPM' - for basic trace of algorithm steps and decisions. Only
5497 : short scalars (function values and deltas) are printed.
5498 : N-dimensional quantities like search directions are NOT
5499 : printed.
5500 : * 'IPM.DETAILED'- for output of points being visited and search directions
5501 : This symbol also implicitly defines 'IPM'. You can
5502 : control output format by additionally specifying:
5503 : * nothing to output in 6-digit exponential format
5504 : * 'PREC.E15' to output in 15-digit exponential format
5505 : * 'PREC.F6' to output in 6-digit fixed-point format
5506 :
5507 : By default trace is disabled and adds no overhead to the optimization
5508 : process. However, specifying any of the symbols adds some formatting and
5509 : output-related overhead.
5510 :
5511 : You may specify multiple symbols by separating them with commas:
5512 : >
5513 : > alglib::trace_file("IPM,PREC.F6", "path/to/trace.log")
5514 : >
5515 :
5516 : -- ALGLIB --
5517 : Copyright 01.11.2019 by Bochkanov Sergey
5518 : *************************************************************************/
5519 0 : void minqpsetalgodenseipm(const minqpstate &state, const double eps, const xparams _xparams)
5520 : {
5521 : jmp_buf _break_jump;
5522 : alglib_impl::ae_state _alglib_env_state;
5523 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5524 0 : if( setjmp(_break_jump) )
5525 : {
5526 : #if !defined(AE_NO_EXCEPTIONS)
5527 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5528 : #else
5529 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5530 : return;
5531 : #endif
5532 : }
5533 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5534 0 : if( _xparams.flags!=0x0 )
5535 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5536 0 : alglib_impl::minqpsetalgodenseipm(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), eps, &_alglib_env_state);
5537 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5538 0 : return;
5539 : }
5540 :
5541 : /*************************************************************************
5542 : This function tells QP solver to use SPARSE-IPM QP algorithm and sets
5543 : stopping criteria for the algorithm.
5544 :
5545 : This algorithm is intended for convex and semidefinite problems with
5546 : large variable and constraint count and sparse quadratic term and
5547 : constraints. It is possible to have some limited set of dense linear
5548 : constraints - they will be handled separately by dense BLAS - but the more
5549 : dense constraints you have, the more time solver needs.
5550 :
5551 : IMPORTANT: internally this solver performs large and sparse (N+M)x(N+M)
5552 : triangular factorization. So it expects both quadratic term and
5553 : constraints to be highly sparse. However, its running time is
5554 : influenced by BOTH fill factor and sparsity pattern.
5555 :
5556 : Generally we expect that no more than few nonzero elements per
5557 : row are present. However different sparsity patterns may result
5558 : in completely different running times even given same fill
5559 : factor.
5560 :
5561 : In many cases this algorithm outperforms DENSE-IPM by order of
5562 : magnitude. However, in some cases you may get better results
5563 : with DENSE-IPM even when solving sparse task.
5564 :
5565 : IMPORTANT: this algorithm won't work for nonconvex problems, use DENSE-AUL
5566 : or BLEIC-QP instead. If you try to run DENSE-IPM on problem
5567 : with indefinite matrix (matrix having at least one negative
5568 : eigenvalue) then depending on circumstances it may either (a)
5569 : stall at some arbitrary point, or (b) throw exception on
5570 : failure of Cholesky decomposition.
5571 :
5572 : ALGORITHM FEATURES:
5573 :
5574 : * supports box and dense/sparse general linear equality/inequality
5575 : constraints
5576 : * specializes on large-scale sparse problems
5577 :
5578 : ALGORITHM OUTLINE:
5579 :
5580 : * this algorithm is our implementation of interior point method as
5581 : formulated by R.J.Vanderbei, with minor modifications to the algorithm
5582 : (damped Newton directions are extensively used)
5583 : * like all interior point methods, this algorithm tends to converge in
5584 : roughly same number of iterations (between 15 and 50) independently from
5585 : the problem dimensionality
5586 :
5587 : ALGORITHM LIMITATIONS:
5588 :
5589 : * this algorithm may handle moderate number of dense constraints, usually
5590 : no more than a thousand of dense ones without losing its efficiency.
5591 :
5592 : INPUT PARAMETERS:
5593 : State - structure which stores algorithm state
5594 : Eps - >=0, stopping criteria. The algorithm stops when primal
5595 : and dual infeasiblities as well as complementarity gap are
5596 : less than Eps.
5597 :
5598 : IT IS VERY IMPORTANT TO CALL minqpsetscale() WHEN YOU USE THIS ALGORITHM
5599 : BECAUSE ITS CONVERGENCE PROPERTIES AND STOPPING CRITERIA ARE SCALE-DEPENDENT!
5600 :
5601 : NOTE: Passing EpsX=0 will lead to automatic selection of small epsilon.
5602 :
5603 : ===== TRACING IPM SOLVER =================================================
5604 :
5605 : IPM solver supports advanced tracing capabilities. You can trace algorithm
5606 : output by specifying following trace symbols (case-insensitive) by means
5607 : of trace_file() call:
5608 : * 'IPM' - for basic trace of algorithm steps and decisions. Only
5609 : short scalars (function values and deltas) are printed.
5610 : N-dimensional quantities like search directions are NOT
5611 : printed.
5612 : * 'IPM.DETAILED'- for output of points being visited and search directions
5613 : This symbol also implicitly defines 'IPM'. You can
5614 : control output format by additionally specifying:
5615 : * nothing to output in 6-digit exponential format
5616 : * 'PREC.E15' to output in 15-digit exponential format
5617 : * 'PREC.F6' to output in 6-digit fixed-point format
5618 :
5619 : By default trace is disabled and adds no overhead to the optimization
5620 : process. However, specifying any of the symbols adds some formatting and
5621 : output-related overhead.
5622 :
5623 : You may specify multiple symbols by separating them with commas:
5624 : >
5625 : > alglib::trace_file("IPM,PREC.F6", "path/to/trace.log")
5626 : >
5627 :
5628 : -- ALGLIB --
5629 : Copyright 01.11.2019 by Bochkanov Sergey
5630 : *************************************************************************/
5631 0 : void minqpsetalgosparseipm(const minqpstate &state, const double eps, const xparams _xparams)
5632 : {
5633 : jmp_buf _break_jump;
5634 : alglib_impl::ae_state _alglib_env_state;
5635 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5636 0 : if( setjmp(_break_jump) )
5637 : {
5638 : #if !defined(AE_NO_EXCEPTIONS)
5639 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5640 : #else
5641 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5642 : return;
5643 : #endif
5644 : }
5645 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5646 0 : if( _xparams.flags!=0x0 )
5647 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5648 0 : alglib_impl::minqpsetalgosparseipm(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), eps, &_alglib_env_state);
5649 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5650 0 : return;
5651 : }
5652 :
5653 : /*************************************************************************
5654 : This function tells solver to use QuickQP algorithm: special extra-fast
5655 : algorithm for problems with box-only constrants. It may solve non-convex
5656 : problems as long as they are bounded from below under constraints.
5657 :
5658 : ALGORITHM FEATURES:
5659 : * several times faster than DENSE-IPM when running on box-only problem
5660 : * utilizes accelerated methods for activation of constraints.
5661 : * supports dense and sparse QP problems
5662 : * supports ONLY box constraints; general linear constraints are NOT
5663 : supported by this solver
5664 : * can solve all types of problems (convex, semidefinite, nonconvex) as
5665 : long as they are bounded from below under constraints.
5666 : Say, it is possible to solve "min{-x^2} subject to -1<=x<=+1".
5667 : In convex/semidefinite case global minimum is returned, in nonconvex
5668 : case - algorithm returns one of the local minimums.
5669 :
5670 : ALGORITHM OUTLINE:
5671 :
5672 : * algorithm performs two kinds of iterations: constrained CG iterations
5673 : and constrained Newton iterations
5674 : * initially it performs small number of constrained CG iterations, which
5675 : can efficiently activate/deactivate multiple constraints
5676 : * after CG phase algorithm tries to calculate Cholesky decomposition and
5677 : to perform several constrained Newton steps. If Cholesky decomposition
5678 : failed (matrix is indefinite even under constraints), we perform more
5679 : CG iterations until we converge to such set of constraints that system
5680 : matrix becomes positive definite. Constrained Newton steps greatly
5681 : increase convergence speed and precision.
5682 : * algorithm interleaves CG and Newton iterations which allows to handle
5683 : indefinite matrices (CG phase) and quickly converge after final set of
5684 : constraints is found (Newton phase). Combination of CG and Newton phases
5685 : is called "outer iteration".
5686 : * it is possible to turn off Newton phase (beneficial for semidefinite
5687 : problems - Cholesky decomposition will fail too often)
5688 :
5689 : ALGORITHM LIMITATIONS:
5690 :
5691 : * algorithm does not support general linear constraints; only box ones
5692 : are supported
5693 : * Cholesky decomposition for sparse problems is performed with Skyline
5694 : Cholesky solver, which is intended for low-profile matrices. No profile-
5695 : reducing reordering of variables is performed in this version of ALGLIB.
5696 : * problems with near-zero negative eigenvalues (or exacty zero ones) may
5697 : experience about 2-3x performance penalty. The reason is that Cholesky
5698 : decomposition can not be performed until we identify directions of zero
5699 : and negative curvature and activate corresponding boundary constraints -
5700 : but we need a lot of trial and errors because these directions are hard
5701 : to notice in the matrix spectrum.
5702 : In this case you may turn off Newton phase of algorithm.
5703 : Large negative eigenvalues are not an issue, so highly non-convex
5704 : problems can be solved very efficiently.
5705 :
5706 : INPUT PARAMETERS:
5707 : State - structure which stores algorithm state
5708 : EpsG - >=0
5709 : The subroutine finishes its work if the condition
5710 : |v|<EpsG is satisfied, where:
5711 : * |.| means Euclidian norm
5712 : * v - scaled constrained gradient vector, v[i]=g[i]*s[i]
5713 : * g - gradient
5714 : * s - scaling coefficients set by MinQPSetScale()
5715 : EpsF - >=0
5716 : The subroutine finishes its work if exploratory steepest
5717 : descent step on k+1-th iteration satisfies following
5718 : condition: |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
5719 : EpsX - >=0
5720 : The subroutine finishes its work if exploratory steepest
5721 : descent step on k+1-th iteration satisfies following
5722 : condition:
5723 : * |.| means Euclidian norm
5724 : * v - scaled step vector, v[i]=dx[i]/s[i]
5725 : * dx - step vector, dx=X(k+1)-X(k)
5726 : * s - scaling coefficients set by MinQPSetScale()
5727 : MaxOuterIts-maximum number of OUTER iterations. One outer iteration
5728 : includes some amount of CG iterations (from 5 to ~N) and
5729 : one or several (usually small amount) Newton steps. Thus,
5730 : one outer iteration has high cost, but can greatly reduce
5731 : funcation value.
5732 : Use 0 if you do not want to limit number of outer iterations.
5733 : UseNewton- use Newton phase or not:
5734 : * Newton phase improves performance of positive definite
5735 : dense problems (about 2 times improvement can be observed)
5736 : * can result in some performance penalty on semidefinite
5737 : or slightly negative definite problems - each Newton
5738 : phase will bring no improvement (Cholesky failure), but
5739 : still will require computational time.
5740 : * if you doubt, you can turn off this phase - optimizer
5741 : will retain its most of its high speed.
5742 :
5743 : IT IS VERY IMPORTANT TO CALL MinQPSetScale() WHEN YOU USE THIS ALGORITHM
5744 : BECAUSE ITS STOPPING CRITERIA ARE SCALE-DEPENDENT!
5745 :
5746 : Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead
5747 : to automatic stopping criterion selection (presently it is small step
5748 : length, but it may change in the future versions of ALGLIB).
5749 :
5750 : -- ALGLIB --
5751 : Copyright 22.05.2014 by Bochkanov Sergey
5752 : *************************************************************************/
5753 0 : void minqpsetalgoquickqp(const minqpstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxouterits, const bool usenewton, const xparams _xparams)
5754 : {
5755 : jmp_buf _break_jump;
5756 : alglib_impl::ae_state _alglib_env_state;
5757 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5758 0 : if( setjmp(_break_jump) )
5759 : {
5760 : #if !defined(AE_NO_EXCEPTIONS)
5761 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5762 : #else
5763 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5764 : return;
5765 : #endif
5766 : }
5767 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5768 0 : if( _xparams.flags!=0x0 )
5769 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5770 0 : alglib_impl::minqpsetalgoquickqp(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), epsg, epsf, epsx, maxouterits, usenewton, &_alglib_env_state);
5771 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5772 0 : return;
5773 : }
5774 :
5775 : /*************************************************************************
5776 : This function sets box constraints for QP solver
5777 :
5778 : Box constraints are inactive by default (after initial creation). After
5779 : being set, they are preserved until explicitly overwritten with another
5780 : minqpsetbc() or minqpsetbcall() call, or partially overwritten with
5781 : minqpsetbci() call.
5782 :
5783 : Following types of constraints are supported:
5784 :
5785 : DESCRIPTION CONSTRAINT HOW TO SPECIFY
5786 : fixed variable x[i]=Bnd[i] BndL[i]=BndU[i]
5787 : lower bound BndL[i]<=x[i] BndU[i]=+INF
5788 : upper bound x[i]<=BndU[i] BndL[i]=-INF
5789 : range BndL[i]<=x[i]<=BndU[i] ...
5790 : free variable - BndL[I]=-INF, BndU[I]+INF
5791 :
5792 : INPUT PARAMETERS:
5793 : State - structure stores algorithm state
5794 : BndL - lower bounds, array[N].
5795 : If some (all) variables are unbounded, you may specify
5796 : very small number or -INF (latter is recommended because
5797 : it will allow solver to use better algorithm).
5798 : BndU - upper bounds, array[N].
5799 : If some (all) variables are unbounded, you may specify
5800 : very large number or +INF (latter is recommended because
5801 : it will allow solver to use better algorithm).
5802 :
5803 : NOTE: infinite values can be specified by means of Double.PositiveInfinity
5804 : and Double.NegativeInfinity (in C#) and alglib::fp_posinf and
5805 : alglib::fp_neginf (in C++).
5806 :
5807 : NOTE: you may replace infinities by very small/very large values, but it
5808 : is not recommended because large numbers may introduce large numerical
5809 : errors in the algorithm.
5810 :
5811 : NOTE: if constraints for all variables are same you may use minqpsetbcall()
5812 : which allows to specify constraints without using arrays.
5813 :
5814 : NOTE: BndL>BndU will result in QP problem being recognized as infeasible.
5815 :
5816 : -- ALGLIB --
5817 : Copyright 11.01.2011 by Bochkanov Sergey
5818 : *************************************************************************/
5819 0 : void minqpsetbc(const minqpstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams)
5820 : {
5821 : jmp_buf _break_jump;
5822 : alglib_impl::ae_state _alglib_env_state;
5823 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5824 0 : if( setjmp(_break_jump) )
5825 : {
5826 : #if !defined(AE_NO_EXCEPTIONS)
5827 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5828 : #else
5829 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5830 : return;
5831 : #endif
5832 : }
5833 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5834 0 : if( _xparams.flags!=0x0 )
5835 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5836 0 : 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);
5837 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5838 0 : return;
5839 : }
5840 :
5841 : /*************************************************************************
5842 : This function sets box constraints for QP solver (all variables at once,
5843 : same constraints for all variables)
5844 :
5845 : Box constraints are inactive by default (after initial creation). After
5846 : being set, they are preserved until explicitly overwritten with another
5847 : minqpsetbc() or minqpsetbcall() call, or partially overwritten with
5848 : minqpsetbci() call.
5849 :
5850 : Following types of constraints are supported:
5851 :
5852 : DESCRIPTION CONSTRAINT HOW TO SPECIFY
5853 : fixed variable x[i]=Bnd BndL=BndU
5854 : lower bound BndL<=x[i] BndU=+INF
5855 : upper bound x[i]<=BndU BndL=-INF
5856 : range BndL<=x[i]<=BndU ...
5857 : free variable - BndL=-INF, BndU+INF
5858 :
5859 : INPUT PARAMETERS:
5860 : State - structure stores algorithm state
5861 : BndL - lower bound, same for all variables
5862 : BndU - upper bound, same for all variables
5863 :
5864 : NOTE: infinite values can be specified by means of Double.PositiveInfinity
5865 : and Double.NegativeInfinity (in C#) and alglib::fp_posinf and
5866 : alglib::fp_neginf (in C++).
5867 :
5868 : NOTE: you may replace infinities by very small/very large values, but it
5869 : is not recommended because large numbers may introduce large numerical
5870 : errors in the algorithm.
5871 :
5872 : NOTE: BndL>BndU will result in QP problem being recognized as infeasible.
5873 :
5874 : -- ALGLIB --
5875 : Copyright 11.01.2011 by Bochkanov Sergey
5876 : *************************************************************************/
5877 0 : void minqpsetbcall(const minqpstate &state, const double bndl, const double bndu, const xparams _xparams)
5878 : {
5879 : jmp_buf _break_jump;
5880 : alglib_impl::ae_state _alglib_env_state;
5881 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5882 0 : if( setjmp(_break_jump) )
5883 : {
5884 : #if !defined(AE_NO_EXCEPTIONS)
5885 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5886 : #else
5887 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5888 : return;
5889 : #endif
5890 : }
5891 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5892 0 : if( _xparams.flags!=0x0 )
5893 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5894 0 : alglib_impl::minqpsetbcall(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), bndl, bndu, &_alglib_env_state);
5895 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5896 0 : return;
5897 : }
5898 :
5899 : /*************************************************************************
5900 : This function sets box constraints for I-th variable (other variables are
5901 : not modified).
5902 :
5903 : Following types of constraints are supported:
5904 :
5905 : DESCRIPTION CONSTRAINT HOW TO SPECIFY
5906 : fixed variable x[i]=Bnd BndL=BndU
5907 : lower bound BndL<=x[i] BndU=+INF
5908 : upper bound x[i]<=BndU BndL=-INF
5909 : range BndL<=x[i]<=BndU ...
5910 : free variable - BndL=-INF, BndU+INF
5911 :
5912 : INPUT PARAMETERS:
5913 : State - structure stores algorithm state
5914 : BndL - lower bound
5915 : BndU - upper bound
5916 :
5917 : NOTE: infinite values can be specified by means of Double.PositiveInfinity
5918 : and Double.NegativeInfinity (in C#) and alglib::fp_posinf and
5919 : alglib::fp_neginf (in C++).
5920 :
5921 : NOTE: you may replace infinities by very small/very large values, but it
5922 : is not recommended because large numbers may introduce large numerical
5923 : errors in the algorithm.
5924 :
5925 : NOTE: BndL>BndU will result in QP problem being recognized as infeasible.
5926 :
5927 : -- ALGLIB --
5928 : Copyright 11.01.2011 by Bochkanov Sergey
5929 : *************************************************************************/
5930 0 : void minqpsetbci(const minqpstate &state, const ae_int_t i, const double bndl, const double bndu, const xparams _xparams)
5931 : {
5932 : jmp_buf _break_jump;
5933 : alglib_impl::ae_state _alglib_env_state;
5934 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5935 0 : if( setjmp(_break_jump) )
5936 : {
5937 : #if !defined(AE_NO_EXCEPTIONS)
5938 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5939 : #else
5940 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5941 : return;
5942 : #endif
5943 : }
5944 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5945 0 : if( _xparams.flags!=0x0 )
5946 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5947 0 : alglib_impl::minqpsetbci(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), i, bndl, bndu, &_alglib_env_state);
5948 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5949 0 : return;
5950 : }
5951 :
5952 : /*************************************************************************
5953 : This function sets dense linear constraints for QP optimizer.
5954 :
5955 : This function overrides results of previous calls to minqpsetlc(),
5956 : minqpsetlcsparse() and minqpsetlcmixed(). After call to this function
5957 : all non-box constraints are dropped, and you have only those constraints
5958 : which were specified in the present call.
5959 :
5960 : If you want to specify mixed (with dense and sparse terms) linear
5961 : constraints, you should call minqpsetlcmixed().
5962 :
5963 : INPUT PARAMETERS:
5964 : State - structure previously allocated with MinQPCreate call.
5965 : C - linear constraints, array[K,N+1].
5966 : Each row of C represents one constraint, either equality
5967 : or inequality (see below):
5968 : * first N elements correspond to coefficients,
5969 : * last element corresponds to the right part.
5970 : All elements of C (including right part) must be finite.
5971 : CT - type of constraints, array[K]:
5972 : * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
5973 : * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
5974 : * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
5975 : K - number of equality/inequality constraints, K>=0:
5976 : * if given, only leading K elements of C/CT are used
5977 : * if not given, automatically determined from sizes of C/CT
5978 :
5979 : NOTE 1: linear (non-bound) constraints are satisfied only approximately -
5980 : there always exists some violation due to numerical errors and
5981 : algorithmic limitations (BLEIC-QP solver is most precise, AUL-QP
5982 : solver is less precise).
5983 :
5984 : -- ALGLIB --
5985 : Copyright 19.06.2012 by Bochkanov Sergey
5986 : *************************************************************************/
5987 0 : void minqpsetlc(const minqpstate &state, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams)
5988 : {
5989 : jmp_buf _break_jump;
5990 : alglib_impl::ae_state _alglib_env_state;
5991 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5992 0 : if( setjmp(_break_jump) )
5993 : {
5994 : #if !defined(AE_NO_EXCEPTIONS)
5995 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5996 : #else
5997 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5998 : return;
5999 : #endif
6000 : }
6001 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6002 0 : if( _xparams.flags!=0x0 )
6003 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6004 0 : 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);
6005 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6006 0 : return;
6007 : }
6008 :
6009 : /*************************************************************************
6010 : This function sets dense linear constraints for QP optimizer.
6011 :
6012 : This function overrides results of previous calls to minqpsetlc(),
6013 : minqpsetlcsparse() and minqpsetlcmixed(). After call to this function
6014 : all non-box constraints are dropped, and you have only those constraints
6015 : which were specified in the present call.
6016 :
6017 : If you want to specify mixed (with dense and sparse terms) linear
6018 : constraints, you should call minqpsetlcmixed().
6019 :
6020 : INPUT PARAMETERS:
6021 : State - structure previously allocated with MinQPCreate call.
6022 : C - linear constraints, array[K,N+1].
6023 : Each row of C represents one constraint, either equality
6024 : or inequality (see below):
6025 : * first N elements correspond to coefficients,
6026 : * last element corresponds to the right part.
6027 : All elements of C (including right part) must be finite.
6028 : CT - type of constraints, array[K]:
6029 : * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
6030 : * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
6031 : * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
6032 : K - number of equality/inequality constraints, K>=0:
6033 : * if given, only leading K elements of C/CT are used
6034 : * if not given, automatically determined from sizes of C/CT
6035 :
6036 : NOTE 1: linear (non-bound) constraints are satisfied only approximately -
6037 : there always exists some violation due to numerical errors and
6038 : algorithmic limitations (BLEIC-QP solver is most precise, AUL-QP
6039 : solver is less precise).
6040 :
6041 : -- ALGLIB --
6042 : Copyright 19.06.2012 by Bochkanov Sergey
6043 : *************************************************************************/
6044 : #if !defined(AE_NO_EXCEPTIONS)
6045 0 : void minqpsetlc(const minqpstate &state, const real_2d_array &c, const integer_1d_array &ct, const xparams _xparams)
6046 : {
6047 : jmp_buf _break_jump;
6048 : alglib_impl::ae_state _alglib_env_state;
6049 : ae_int_t k;
6050 0 : if( (c.rows()!=ct.length()))
6051 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'minqpsetlc': looks like one of arguments has wrong size");
6052 0 : k = c.rows();
6053 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6054 0 : if( setjmp(_break_jump) )
6055 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6056 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6057 0 : if( _xparams.flags!=0x0 )
6058 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6059 0 : 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);
6060 :
6061 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6062 0 : return;
6063 : }
6064 : #endif
6065 :
6066 : /*************************************************************************
6067 : This function sets sparse linear constraints for QP optimizer.
6068 :
6069 : This function overrides results of previous calls to minqpsetlc(),
6070 : minqpsetlcsparse() and minqpsetlcmixed(). After call to this function
6071 : all non-box constraints are dropped, and you have only those constraints
6072 : which were specified in the present call.
6073 :
6074 : If you want to specify mixed (with dense and sparse terms) linear
6075 : constraints, you should call minqpsetlcmixed().
6076 :
6077 : INPUT PARAMETERS:
6078 : State - structure previously allocated with MinQPCreate call.
6079 : C - linear constraints, sparse matrix with dimensions at
6080 : least [K,N+1]. If matrix has larger size, only leading
6081 : Kx(N+1) rectangle is used.
6082 : Each row of C represents one constraint, either equality
6083 : or inequality (see below):
6084 : * first N elements correspond to coefficients,
6085 : * last element corresponds to the right part.
6086 : All elements of C (including right part) must be finite.
6087 : CT - type of constraints, array[K]:
6088 : * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
6089 : * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
6090 : * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
6091 : K - number of equality/inequality constraints, K>=0
6092 :
6093 : NOTE 1: linear (non-bound) constraints are satisfied only approximately -
6094 : there always exists some violation due to numerical errors and
6095 : algorithmic limitations (BLEIC-QP solver is most precise, AUL-QP
6096 : solver is less precise).
6097 :
6098 : -- ALGLIB --
6099 : Copyright 22.08.2016 by Bochkanov Sergey
6100 : *************************************************************************/
6101 0 : void minqpsetlcsparse(const minqpstate &state, const sparsematrix &c, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams)
6102 : {
6103 : jmp_buf _break_jump;
6104 : alglib_impl::ae_state _alglib_env_state;
6105 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6106 0 : if( setjmp(_break_jump) )
6107 : {
6108 : #if !defined(AE_NO_EXCEPTIONS)
6109 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6110 : #else
6111 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6112 : return;
6113 : #endif
6114 : }
6115 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6116 0 : if( _xparams.flags!=0x0 )
6117 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6118 0 : alglib_impl::minqpsetlcsparse(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::sparsematrix*>(c.c_ptr()), const_cast<alglib_impl::ae_vector*>(ct.c_ptr()), k, &_alglib_env_state);
6119 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6120 0 : return;
6121 : }
6122 :
6123 : /*************************************************************************
6124 : This function sets mixed linear constraints, which include a set of dense
6125 : rows, and a set of sparse rows.
6126 :
6127 : This function overrides results of previous calls to minqpsetlc(),
6128 : minqpsetlcsparse() and minqpsetlcmixed().
6129 :
6130 : This function may be useful if constraint matrix includes large number of
6131 : both types of rows - dense and sparse. If you have just a few sparse rows,
6132 : you may represent them in dense format without losing performance.
6133 : Similarly, if you have just a few dense rows, you may store them in sparse
6134 : format with almost same performance.
6135 :
6136 : INPUT PARAMETERS:
6137 : State - structure previously allocated with MinQPCreate call.
6138 : SparseC - linear constraints, sparse matrix with dimensions EXACTLY
6139 : EQUAL TO [SparseK,N+1]. Each row of C represents one
6140 : constraint, either equality or inequality (see below):
6141 : * first N elements correspond to coefficients,
6142 : * last element corresponds to the right part.
6143 : All elements of C (including right part) must be finite.
6144 : SparseCT- type of sparse constraints, array[K]:
6145 : * if SparseCT[i]>0, then I-th constraint is SparseC[i,*]*x >= SparseC[i,n+1]
6146 : * if SparseCT[i]=0, then I-th constraint is SparseC[i,*]*x = SparseC[i,n+1]
6147 : * if SparseCT[i]<0, then I-th constraint is SparseC[i,*]*x <= SparseC[i,n+1]
6148 : SparseK - number of sparse equality/inequality constraints, K>=0
6149 : DenseC - dense linear constraints, array[K,N+1].
6150 : Each row of DenseC represents one constraint, either equality
6151 : or inequality (see below):
6152 : * first N elements correspond to coefficients,
6153 : * last element corresponds to the right part.
6154 : All elements of DenseC (including right part) must be finite.
6155 : DenseCT - type of constraints, array[K]:
6156 : * if DenseCT[i]>0, then I-th constraint is DenseC[i,*]*x >= DenseC[i,n+1]
6157 : * if DenseCT[i]=0, then I-th constraint is DenseC[i,*]*x = DenseC[i,n+1]
6158 : * if DenseCT[i]<0, then I-th constraint is DenseC[i,*]*x <= DenseC[i,n+1]
6159 : DenseK - number of equality/inequality constraints, DenseK>=0
6160 :
6161 : NOTE 1: linear (non-box) constraints are satisfied only approximately -
6162 : there always exists some violation due to numerical errors and
6163 : algorithmic limitations (BLEIC-QP solver is most precise, AUL-QP
6164 : solver is less precise).
6165 :
6166 : NOTE 2: due to backward compatibility reasons SparseC can be larger than
6167 : [SparseK,N+1]. In this case only leading [SparseK,N+1] submatrix
6168 : will be used. However, the rest of ALGLIB has more strict
6169 : requirements on the input size, so we recommend you to pass sparse
6170 : term whose size exactly matches algorithm expectations.
6171 :
6172 : -- ALGLIB --
6173 : Copyright 22.08.2016 by Bochkanov Sergey
6174 : *************************************************************************/
6175 0 : void minqpsetlcmixed(const minqpstate &state, const sparsematrix &sparsec, const integer_1d_array &sparsect, const ae_int_t sparsek, const real_2d_array &densec, const integer_1d_array &densect, const ae_int_t densek, const xparams _xparams)
6176 : {
6177 : jmp_buf _break_jump;
6178 : alglib_impl::ae_state _alglib_env_state;
6179 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6180 0 : if( setjmp(_break_jump) )
6181 : {
6182 : #if !defined(AE_NO_EXCEPTIONS)
6183 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6184 : #else
6185 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6186 : return;
6187 : #endif
6188 : }
6189 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6190 0 : if( _xparams.flags!=0x0 )
6191 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6192 0 : alglib_impl::minqpsetlcmixed(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::sparsematrix*>(sparsec.c_ptr()), const_cast<alglib_impl::ae_vector*>(sparsect.c_ptr()), sparsek, const_cast<alglib_impl::ae_matrix*>(densec.c_ptr()), const_cast<alglib_impl::ae_vector*>(densect.c_ptr()), densek, &_alglib_env_state);
6193 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6194 0 : return;
6195 : }
6196 :
6197 : /*************************************************************************
6198 : This function provides legacy API for specification of mixed dense/sparse
6199 : linear constraints.
6200 :
6201 : New conventions used by ALGLIB since release 3.16.0 state that set of
6202 : sparse constraints comes first, followed by set of dense ones. This
6203 : convention is essential when you talk about things like order of Lagrange
6204 : multipliers.
6205 :
6206 : However, legacy API accepted mixed constraints in reverse order. This
6207 : function is here to simplify situation with code relying on legacy API. It
6208 : simply accepts constraints in one order (old) and passes them to new API,
6209 : now in correct order.
6210 :
6211 : -- ALGLIB --
6212 : Copyright 01.11.2019 by Bochkanov Sergey
6213 : *************************************************************************/
6214 0 : void minqpsetlcmixedlegacy(const minqpstate &state, const real_2d_array &densec, const integer_1d_array &densect, const ae_int_t densek, const sparsematrix &sparsec, const integer_1d_array &sparsect, const ae_int_t sparsek, const xparams _xparams)
6215 : {
6216 : jmp_buf _break_jump;
6217 : alglib_impl::ae_state _alglib_env_state;
6218 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6219 0 : if( setjmp(_break_jump) )
6220 : {
6221 : #if !defined(AE_NO_EXCEPTIONS)
6222 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6223 : #else
6224 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6225 : return;
6226 : #endif
6227 : }
6228 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6229 0 : if( _xparams.flags!=0x0 )
6230 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6231 0 : alglib_impl::minqpsetlcmixedlegacy(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(densec.c_ptr()), const_cast<alglib_impl::ae_vector*>(densect.c_ptr()), densek, const_cast<alglib_impl::sparsematrix*>(sparsec.c_ptr()), const_cast<alglib_impl::ae_vector*>(sparsect.c_ptr()), sparsek, &_alglib_env_state);
6232 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6233 0 : return;
6234 : }
6235 :
6236 : /*************************************************************************
6237 : This function sets two-sided linear constraints AL <= A*x <= AU with dense
6238 : constraint matrix A.
6239 :
6240 : NOTE: knowing that constraint matrix is dense helps some QP solvers
6241 : (especially modern IPM method) to utilize efficient dense Level 3
6242 : BLAS for dense parts of the problem. If your problem has both dense
6243 : and sparse constraints, you can use minqpsetlc2mixed() function,
6244 : which will result in dense algebra being applied to dense terms, and
6245 : sparse sparse linear algebra applied to sparse terms.
6246 :
6247 : INPUT PARAMETERS:
6248 : State - structure previously allocated with minqpcreate() call.
6249 : A - linear constraints, array[K,N]. Each row of A represents
6250 : one constraint. One-sided inequality constraints, two-
6251 : sided inequality constraints, equality constraints are
6252 : supported (see below)
6253 : AL, AU - lower and upper bounds, array[K];
6254 : * AL[i]=AU[i] => equality constraint Ai*x
6255 : * AL[i]<AU[i] => two-sided constraint AL[i]<=Ai*x<=AU[i]
6256 : * AL[i]=-INF => one-sided constraint Ai*x<=AU[i]
6257 : * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x
6258 : * AL[i]=-INF, AU[i]=+INF => constraint is ignored
6259 : K - number of equality/inequality constraints, K>=0; if not
6260 : given, inferred from sizes of A, AL, AU.
6261 :
6262 : -- ALGLIB --
6263 : Copyright 01.11.2019 by Bochkanov Sergey
6264 : *************************************************************************/
6265 0 : void minqpsetlc2dense(const minqpstate &state, const real_2d_array &a, const real_1d_array &al, const real_1d_array &au, const ae_int_t k, const xparams _xparams)
6266 : {
6267 : jmp_buf _break_jump;
6268 : alglib_impl::ae_state _alglib_env_state;
6269 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6270 0 : if( setjmp(_break_jump) )
6271 : {
6272 : #if !defined(AE_NO_EXCEPTIONS)
6273 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6274 : #else
6275 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6276 : return;
6277 : #endif
6278 : }
6279 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6280 0 : if( _xparams.flags!=0x0 )
6281 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6282 0 : alglib_impl::minqpsetlc2dense(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), const_cast<alglib_impl::ae_vector*>(al.c_ptr()), const_cast<alglib_impl::ae_vector*>(au.c_ptr()), k, &_alglib_env_state);
6283 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6284 0 : return;
6285 : }
6286 :
6287 : /*************************************************************************
6288 : This function sets two-sided linear constraints AL <= A*x <= AU with dense
6289 : constraint matrix A.
6290 :
6291 : NOTE: knowing that constraint matrix is dense helps some QP solvers
6292 : (especially modern IPM method) to utilize efficient dense Level 3
6293 : BLAS for dense parts of the problem. If your problem has both dense
6294 : and sparse constraints, you can use minqpsetlc2mixed() function,
6295 : which will result in dense algebra being applied to dense terms, and
6296 : sparse sparse linear algebra applied to sparse terms.
6297 :
6298 : INPUT PARAMETERS:
6299 : State - structure previously allocated with minqpcreate() call.
6300 : A - linear constraints, array[K,N]. Each row of A represents
6301 : one constraint. One-sided inequality constraints, two-
6302 : sided inequality constraints, equality constraints are
6303 : supported (see below)
6304 : AL, AU - lower and upper bounds, array[K];
6305 : * AL[i]=AU[i] => equality constraint Ai*x
6306 : * AL[i]<AU[i] => two-sided constraint AL[i]<=Ai*x<=AU[i]
6307 : * AL[i]=-INF => one-sided constraint Ai*x<=AU[i]
6308 : * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x
6309 : * AL[i]=-INF, AU[i]=+INF => constraint is ignored
6310 : K - number of equality/inequality constraints, K>=0; if not
6311 : given, inferred from sizes of A, AL, AU.
6312 :
6313 : -- ALGLIB --
6314 : Copyright 01.11.2019 by Bochkanov Sergey
6315 : *************************************************************************/
6316 : #if !defined(AE_NO_EXCEPTIONS)
6317 0 : void minqpsetlc2dense(const minqpstate &state, const real_2d_array &a, const real_1d_array &al, const real_1d_array &au, const xparams _xparams)
6318 : {
6319 : jmp_buf _break_jump;
6320 : alglib_impl::ae_state _alglib_env_state;
6321 : ae_int_t k;
6322 0 : if( (a.rows()!=al.length()) || (a.rows()!=au.length()))
6323 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'minqpsetlc2dense': looks like one of arguments has wrong size");
6324 0 : k = a.rows();
6325 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6326 0 : if( setjmp(_break_jump) )
6327 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6328 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6329 0 : if( _xparams.flags!=0x0 )
6330 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6331 0 : alglib_impl::minqpsetlc2dense(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), const_cast<alglib_impl::ae_vector*>(al.c_ptr()), const_cast<alglib_impl::ae_vector*>(au.c_ptr()), k, &_alglib_env_state);
6332 :
6333 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6334 0 : return;
6335 : }
6336 : #endif
6337 :
6338 : /*************************************************************************
6339 : This function sets two-sided linear constraints AL <= A*x <= AU with
6340 : sparse constraining matrix A. Recommended for large-scale problems.
6341 :
6342 : This function overwrites linear (non-box) constraints set by previous
6343 : calls (if such calls were made).
6344 :
6345 : INPUT PARAMETERS:
6346 : State - structure previously allocated with minqpcreate() call.
6347 : A - sparse matrix with size [K,N] (exactly!).
6348 : Each row of A represents one general linear constraint.
6349 : A can be stored in any sparse storage format.
6350 : AL, AU - lower and upper bounds, array[K];
6351 : * AL[i]=AU[i] => equality constraint Ai*x
6352 : * AL[i]<AU[i] => two-sided constraint AL[i]<=Ai*x<=AU[i]
6353 : * AL[i]=-INF => one-sided constraint Ai*x<=AU[i]
6354 : * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x
6355 : * AL[i]=-INF, AU[i]=+INF => constraint is ignored
6356 : K - number of equality/inequality constraints, K>=0. If K=0
6357 : is specified, A, AL, AU are ignored.
6358 :
6359 : -- ALGLIB --
6360 : Copyright 01.11.2019 by Bochkanov Sergey
6361 : *************************************************************************/
6362 0 : void minqpsetlc2(const minqpstate &state, const sparsematrix &a, const real_1d_array &al, const real_1d_array &au, const ae_int_t k, const xparams _xparams)
6363 : {
6364 : jmp_buf _break_jump;
6365 : alglib_impl::ae_state _alglib_env_state;
6366 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6367 0 : if( setjmp(_break_jump) )
6368 : {
6369 : #if !defined(AE_NO_EXCEPTIONS)
6370 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6371 : #else
6372 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6373 : return;
6374 : #endif
6375 : }
6376 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6377 0 : if( _xparams.flags!=0x0 )
6378 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6379 0 : alglib_impl::minqpsetlc2(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::sparsematrix*>(a.c_ptr()), const_cast<alglib_impl::ae_vector*>(al.c_ptr()), const_cast<alglib_impl::ae_vector*>(au.c_ptr()), k, &_alglib_env_state);
6380 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6381 0 : return;
6382 : }
6383 :
6384 : /*************************************************************************
6385 : This function sets two-sided linear constraints AL <= A*x <= AU with
6386 : mixed constraining matrix A including sparse part (first SparseK rows) and
6387 : dense part (last DenseK rows). Recommended for large-scale problems.
6388 :
6389 : This function overwrites linear (non-box) constraints set by previous
6390 : calls (if such calls were made).
6391 :
6392 : This function may be useful if constraint matrix includes large number of
6393 : both types of rows - dense and sparse. If you have just a few sparse rows,
6394 : you may represent them in dense format without losing performance.
6395 : Similarly, if you have just a few dense rows, you may store them in sparse
6396 : format with almost same performance.
6397 :
6398 : INPUT PARAMETERS:
6399 : State - structure previously allocated with minqpcreate() call.
6400 : SparseA - sparse matrix with size [K,N] (exactly!).
6401 : Each row of A represents one general linear constraint.
6402 : A can be stored in any sparse storage format.
6403 : SparseK - number of sparse constraints, SparseK>=0
6404 : DenseA - linear constraints, array[K,N], set of dense constraints.
6405 : Each row of A represents one general linear constraint.
6406 : DenseK - number of dense constraints, DenseK>=0
6407 : AL, AU - lower and upper bounds, array[SparseK+DenseK], with former
6408 : SparseK elements corresponding to sparse constraints, and
6409 : latter DenseK elements corresponding to dense constraints;
6410 : * AL[i]=AU[i] => equality constraint Ai*x
6411 : * AL[i]<AU[i] => two-sided constraint AL[i]<=Ai*x<=AU[i]
6412 : * AL[i]=-INF => one-sided constraint Ai*x<=AU[i]
6413 : * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x
6414 : * AL[i]=-INF, AU[i]=+INF => constraint is ignored
6415 : K - number of equality/inequality constraints, K>=0. If K=0
6416 : is specified, A, AL, AU are ignored.
6417 :
6418 : -- ALGLIB --
6419 : Copyright 01.11.2019 by Bochkanov Sergey
6420 : *************************************************************************/
6421 0 : void minqpsetlc2mixed(const minqpstate &state, const sparsematrix &sparsea, const ae_int_t ksparse, const real_2d_array &densea, const ae_int_t kdense, const real_1d_array &al, const real_1d_array &au, const xparams _xparams)
6422 : {
6423 : jmp_buf _break_jump;
6424 : alglib_impl::ae_state _alglib_env_state;
6425 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6426 0 : if( setjmp(_break_jump) )
6427 : {
6428 : #if !defined(AE_NO_EXCEPTIONS)
6429 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6430 : #else
6431 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6432 : return;
6433 : #endif
6434 : }
6435 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6436 0 : if( _xparams.flags!=0x0 )
6437 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6438 0 : alglib_impl::minqpsetlc2mixed(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::sparsematrix*>(sparsea.c_ptr()), ksparse, const_cast<alglib_impl::ae_matrix*>(densea.c_ptr()), kdense, const_cast<alglib_impl::ae_vector*>(al.c_ptr()), const_cast<alglib_impl::ae_vector*>(au.c_ptr()), &_alglib_env_state);
6439 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6440 0 : return;
6441 : }
6442 :
6443 : /*************************************************************************
6444 : This function appends two-sided linear constraint AL <= A*x <= AU to the
6445 : list of currently present dense constraints.
6446 :
6447 : INPUT PARAMETERS:
6448 : State - structure previously allocated with minqpcreate() call.
6449 : A - linear constraint coefficient, array[N], right side is NOT
6450 : included.
6451 : AL, AU - lower and upper bounds;
6452 : * AL=AU => equality constraint Ai*x
6453 : * AL<AU => two-sided constraint AL<=A*x<=AU
6454 : * AL=-INF => one-sided constraint Ai*x<=AU
6455 : * AU=+INF => one-sided constraint AL<=Ai*x
6456 : * AL=-INF, AU=+INF => constraint is ignored
6457 :
6458 : -- ALGLIB --
6459 : Copyright 19.07.2018 by Bochkanov Sergey
6460 : *************************************************************************/
6461 0 : void minqpaddlc2dense(const minqpstate &state, const real_1d_array &a, const double al, const double au, const xparams _xparams)
6462 : {
6463 : jmp_buf _break_jump;
6464 : alglib_impl::ae_state _alglib_env_state;
6465 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6466 0 : if( setjmp(_break_jump) )
6467 : {
6468 : #if !defined(AE_NO_EXCEPTIONS)
6469 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6470 : #else
6471 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6472 : return;
6473 : #endif
6474 : }
6475 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6476 0 : if( _xparams.flags!=0x0 )
6477 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6478 0 : alglib_impl::minqpaddlc2dense(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(a.c_ptr()), al, au, &_alglib_env_state);
6479 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6480 0 : return;
6481 : }
6482 :
6483 : /*************************************************************************
6484 : This function appends two-sided linear constraint AL <= A*x <= AU to the
6485 : list of currently present sparse constraints.
6486 :
6487 : Constraint is passed in compressed format: as list of non-zero entries of
6488 : coefficient vector A. Such approach is more efficient than dense storage
6489 : for highly sparse constraint vectors.
6490 :
6491 : INPUT PARAMETERS:
6492 : State - structure previously allocated with minqpcreate() call.
6493 : IdxA - array[NNZ], indexes of non-zero elements of A:
6494 : * can be unsorted
6495 : * can include duplicate indexes (corresponding entries of
6496 : ValA[] will be summed)
6497 : ValA - array[NNZ], values of non-zero elements of A
6498 : NNZ - number of non-zero coefficients in A
6499 : AL, AU - lower and upper bounds;
6500 : * AL=AU => equality constraint A*x
6501 : * AL<AU => two-sided constraint AL<=A*x<=AU
6502 : * AL=-INF => one-sided constraint A*x<=AU
6503 : * AU=+INF => one-sided constraint AL<=A*x
6504 : * AL=-INF, AU=+INF => constraint is ignored
6505 :
6506 : -- ALGLIB --
6507 : Copyright 19.07.2018 by Bochkanov Sergey
6508 : *************************************************************************/
6509 0 : void minqpaddlc2(const minqpstate &state, const integer_1d_array &idxa, const real_1d_array &vala, const ae_int_t nnz, const double al, const double au, const xparams _xparams)
6510 : {
6511 : jmp_buf _break_jump;
6512 : alglib_impl::ae_state _alglib_env_state;
6513 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6514 0 : if( setjmp(_break_jump) )
6515 : {
6516 : #if !defined(AE_NO_EXCEPTIONS)
6517 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6518 : #else
6519 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6520 : return;
6521 : #endif
6522 : }
6523 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6524 0 : if( _xparams.flags!=0x0 )
6525 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6526 0 : alglib_impl::minqpaddlc2(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(idxa.c_ptr()), const_cast<alglib_impl::ae_vector*>(vala.c_ptr()), nnz, al, au, &_alglib_env_state);
6527 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6528 0 : return;
6529 : }
6530 :
6531 : /*************************************************************************
6532 : This function solves quadratic programming problem.
6533 :
6534 : Prior to calling this function you should choose solver by means of one of
6535 : the following functions:
6536 :
6537 : * minqpsetalgoquickqp() - for QuickQP solver
6538 : * minqpsetalgobleic() - for BLEIC-QP solver
6539 : * minqpsetalgodenseaul() - for Dense-AUL-QP solver
6540 : * minqpsetalgodenseipm() - for Dense-IPM-QP solver
6541 :
6542 : These functions also allow you to control stopping criteria of the solver.
6543 : If you did not set solver, MinQP subpackage will automatically select
6544 : solver for your problem and will run it with default stopping criteria.
6545 :
6546 : However, it is better to set explicitly solver and its stopping criteria.
6547 :
6548 : INPUT PARAMETERS:
6549 : State - algorithm state
6550 :
6551 : You should use MinQPResults() function to access results after calls
6552 : to this function.
6553 :
6554 : -- ALGLIB --
6555 : Copyright 11.01.2011 by Bochkanov Sergey.
6556 : Special thanks to Elvira Illarionova for important suggestions on
6557 : the linearly constrained QP algorithm.
6558 : *************************************************************************/
6559 0 : void minqpoptimize(const minqpstate &state, const xparams _xparams)
6560 : {
6561 : jmp_buf _break_jump;
6562 : alglib_impl::ae_state _alglib_env_state;
6563 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6564 0 : if( setjmp(_break_jump) )
6565 : {
6566 : #if !defined(AE_NO_EXCEPTIONS)
6567 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6568 : #else
6569 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6570 : return;
6571 : #endif
6572 : }
6573 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6574 0 : if( _xparams.flags!=0x0 )
6575 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6576 0 : alglib_impl::minqpoptimize(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), &_alglib_env_state);
6577 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6578 0 : return;
6579 : }
6580 :
6581 : /*************************************************************************
6582 : QP solver results
6583 :
6584 : INPUT PARAMETERS:
6585 : State - algorithm state
6586 :
6587 : OUTPUT PARAMETERS:
6588 : X - array[0..N-1], solution (on failure - the best point found
6589 : so far).
6590 : Rep - optimization report, contains:
6591 : * completion code in Rep.TerminationType (positive values
6592 : denote some kind of success, negative - failures)
6593 : * Lagrange multipliers - for QP solvers which support them
6594 : * other statistics
6595 : See comments on minqpreport structure for more information
6596 :
6597 : Following completion codes are returned in Rep.TerminationType:
6598 : * -9 failure of the automatic scale evaluation: one of the diagonal
6599 : elements of the quadratic term is non-positive. Specify variable
6600 : scales manually!
6601 : * -5 inappropriate solver was used:
6602 : * QuickQP solver for problem with general linear constraints
6603 : * -4 the function is unbounded from below even under constraints,
6604 : no meaningful minimum can be found.
6605 : * -3 inconsistent constraints (or, maybe, feasible point is too hard to
6606 : find).
6607 : * -2 IPM solver has difficulty finding primal/dual feasible point.
6608 : It is likely that the problem is either infeasible or unbounded,
6609 : but it is difficult to determine exact reason for termination.
6610 : X contains best point found so far.
6611 : * >0 success
6612 : * 7 stopping conditions are too stringent,
6613 : further improvement is impossible,
6614 : X contains best point found so far.
6615 :
6616 : -- ALGLIB --
6617 : Copyright 11.01.2011 by Bochkanov Sergey
6618 : *************************************************************************/
6619 0 : void minqpresults(const minqpstate &state, real_1d_array &x, minqpreport &rep, const xparams _xparams)
6620 : {
6621 : jmp_buf _break_jump;
6622 : alglib_impl::ae_state _alglib_env_state;
6623 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6624 0 : if( setjmp(_break_jump) )
6625 : {
6626 : #if !defined(AE_NO_EXCEPTIONS)
6627 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6628 : #else
6629 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6630 : return;
6631 : #endif
6632 : }
6633 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6634 0 : if( _xparams.flags!=0x0 )
6635 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6636 0 : 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);
6637 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6638 0 : return;
6639 : }
6640 :
6641 : /*************************************************************************
6642 : QP results
6643 :
6644 : Buffered implementation of MinQPResults() which uses pre-allocated buffer
6645 : to store X[]. If buffer size is too small, it resizes buffer. It is
6646 : intended to be used in the inner cycles of performance critical algorithms
6647 : where array reallocation penalty is too large to be ignored.
6648 :
6649 : -- ALGLIB --
6650 : Copyright 11.01.2011 by Bochkanov Sergey
6651 : *************************************************************************/
6652 0 : void minqpresultsbuf(const minqpstate &state, real_1d_array &x, minqpreport &rep, const xparams _xparams)
6653 : {
6654 : jmp_buf _break_jump;
6655 : alglib_impl::ae_state _alglib_env_state;
6656 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6657 0 : if( setjmp(_break_jump) )
6658 : {
6659 : #if !defined(AE_NO_EXCEPTIONS)
6660 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6661 : #else
6662 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6663 : return;
6664 : #endif
6665 : }
6666 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6667 0 : if( _xparams.flags!=0x0 )
6668 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6669 0 : 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);
6670 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6671 0 : return;
6672 : }
6673 : #endif
6674 :
6675 : #if defined(AE_COMPILE_LPQPPRESOLVE) || !defined(AE_PARTIAL_BUILD)
6676 :
6677 : #endif
6678 :
6679 : #if defined(AE_COMPILE_REVISEDDUALSIMPLEX) || !defined(AE_PARTIAL_BUILD)
6680 :
6681 : #endif
6682 :
6683 : #if defined(AE_COMPILE_MINLP) || !defined(AE_PARTIAL_BUILD)
6684 : /*************************************************************************
6685 : This object stores linear solver state.
6686 : You should use functions provided by MinLP subpackage to work with this
6687 : object
6688 : *************************************************************************/
6689 0 : _minlpstate_owner::_minlpstate_owner()
6690 : {
6691 : jmp_buf _break_jump;
6692 : alglib_impl::ae_state _state;
6693 :
6694 0 : alglib_impl::ae_state_init(&_state);
6695 0 : if( setjmp(_break_jump) )
6696 : {
6697 0 : if( p_struct!=NULL )
6698 : {
6699 0 : alglib_impl::_minlpstate_destroy(p_struct);
6700 0 : alglib_impl::ae_free(p_struct);
6701 : }
6702 0 : p_struct = NULL;
6703 : #if !defined(AE_NO_EXCEPTIONS)
6704 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
6705 : #else
6706 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
6707 : return;
6708 : #endif
6709 : }
6710 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
6711 0 : p_struct = NULL;
6712 0 : p_struct = (alglib_impl::minlpstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlpstate), &_state);
6713 0 : memset(p_struct, 0, sizeof(alglib_impl::minlpstate));
6714 0 : alglib_impl::_minlpstate_init(p_struct, &_state, ae_false);
6715 0 : ae_state_clear(&_state);
6716 0 : }
6717 :
6718 0 : _minlpstate_owner::_minlpstate_owner(const _minlpstate_owner &rhs)
6719 : {
6720 : jmp_buf _break_jump;
6721 : alglib_impl::ae_state _state;
6722 :
6723 0 : alglib_impl::ae_state_init(&_state);
6724 0 : if( setjmp(_break_jump) )
6725 : {
6726 0 : if( p_struct!=NULL )
6727 : {
6728 0 : alglib_impl::_minlpstate_destroy(p_struct);
6729 0 : alglib_impl::ae_free(p_struct);
6730 : }
6731 0 : p_struct = NULL;
6732 : #if !defined(AE_NO_EXCEPTIONS)
6733 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
6734 : #else
6735 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
6736 : return;
6737 : #endif
6738 : }
6739 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
6740 0 : p_struct = NULL;
6741 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlpstate copy constructor failure (source is not initialized)", &_state);
6742 0 : p_struct = (alglib_impl::minlpstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlpstate), &_state);
6743 0 : memset(p_struct, 0, sizeof(alglib_impl::minlpstate));
6744 0 : alglib_impl::_minlpstate_init_copy(p_struct, const_cast<alglib_impl::minlpstate*>(rhs.p_struct), &_state, ae_false);
6745 0 : ae_state_clear(&_state);
6746 0 : }
6747 :
6748 0 : _minlpstate_owner& _minlpstate_owner::operator=(const _minlpstate_owner &rhs)
6749 : {
6750 0 : if( this==&rhs )
6751 0 : return *this;
6752 : jmp_buf _break_jump;
6753 : alglib_impl::ae_state _state;
6754 :
6755 0 : alglib_impl::ae_state_init(&_state);
6756 0 : if( setjmp(_break_jump) )
6757 : {
6758 : #if !defined(AE_NO_EXCEPTIONS)
6759 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
6760 : #else
6761 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
6762 : return *this;
6763 : #endif
6764 : }
6765 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
6766 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minlpstate assignment constructor failure (destination is not initialized)", &_state);
6767 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlpstate assignment constructor failure (source is not initialized)", &_state);
6768 0 : alglib_impl::_minlpstate_destroy(p_struct);
6769 0 : memset(p_struct, 0, sizeof(alglib_impl::minlpstate));
6770 0 : alglib_impl::_minlpstate_init_copy(p_struct, const_cast<alglib_impl::minlpstate*>(rhs.p_struct), &_state, ae_false);
6771 0 : ae_state_clear(&_state);
6772 0 : return *this;
6773 : }
6774 :
6775 0 : _minlpstate_owner::~_minlpstate_owner()
6776 : {
6777 0 : if( p_struct!=NULL )
6778 : {
6779 0 : alglib_impl::_minlpstate_destroy(p_struct);
6780 0 : ae_free(p_struct);
6781 : }
6782 0 : }
6783 :
6784 0 : alglib_impl::minlpstate* _minlpstate_owner::c_ptr()
6785 : {
6786 0 : return p_struct;
6787 : }
6788 :
6789 0 : alglib_impl::minlpstate* _minlpstate_owner::c_ptr() const
6790 : {
6791 0 : return const_cast<alglib_impl::minlpstate*>(p_struct);
6792 : }
6793 0 : minlpstate::minlpstate() : _minlpstate_owner()
6794 : {
6795 0 : }
6796 :
6797 0 : minlpstate::minlpstate(const minlpstate &rhs):_minlpstate_owner(rhs)
6798 : {
6799 0 : }
6800 :
6801 0 : minlpstate& minlpstate::operator=(const minlpstate &rhs)
6802 : {
6803 0 : if( this==&rhs )
6804 0 : return *this;
6805 0 : _minlpstate_owner::operator=(rhs);
6806 0 : return *this;
6807 : }
6808 :
6809 0 : minlpstate::~minlpstate()
6810 : {
6811 0 : }
6812 :
6813 :
6814 : /*************************************************************************
6815 : This structure stores optimization report:
6816 : * f target function value
6817 : * lagbc Lagrange coefficients for box constraints
6818 : * laglc Lagrange coefficients for linear constraints
6819 : * y dual variables
6820 : * stats array[N+M], statuses of box (N) and linear (M)
6821 : constraints. This array is filled only by DSS
6822 : algorithm because IPM always stops at INTERIOR
6823 : point:
6824 : * stats[i]>0 => constraint at upper bound
6825 : (also used for free non-basic
6826 : variables set to zero)
6827 : * stats[i]<0 => constraint at lower bound
6828 : * stats[i]=0 => constraint is inactive, basic
6829 : variable
6830 : * primalerror primal feasibility error
6831 : * dualerror dual feasibility error
6832 : * slackerror complementary slackness error
6833 : * iterationscount iteration count
6834 : * terminationtype completion code (see below)
6835 :
6836 : COMPLETION CODES
6837 :
6838 : Completion codes:
6839 : * -4 LP problem is primal unbounded (dual infeasible)
6840 : * -3 LP problem is primal infeasible (dual unbounded)
6841 : * 1..4 successful completion
6842 : * 5 MaxIts steps was taken
6843 : * 7 stopping conditions are too stringent,
6844 : further improvement is impossible,
6845 : X contains best point found so far.
6846 :
6847 : LAGRANGE COEFFICIENTS
6848 :
6849 : Positive Lagrange coefficient means that constraint is at its upper bound.
6850 : Negative coefficient means that constraint is at its lower bound. It is
6851 : expected that at solution the dual feasibility condition holds:
6852 :
6853 : C + SUM(Ei*LagBC[i],i=0..n-1) + SUM(Ai*LagLC[i],i=0..m-1) ~ 0
6854 :
6855 : where
6856 : * C is a cost vector (linear term)
6857 : * Ei is a vector with 1.0 at position I and 0 in other positions
6858 : * Ai is an I-th row of linear constraint matrix
6859 : *************************************************************************/
6860 0 : _minlpreport_owner::_minlpreport_owner()
6861 : {
6862 : jmp_buf _break_jump;
6863 : alglib_impl::ae_state _state;
6864 :
6865 0 : alglib_impl::ae_state_init(&_state);
6866 0 : if( setjmp(_break_jump) )
6867 : {
6868 0 : if( p_struct!=NULL )
6869 : {
6870 0 : alglib_impl::_minlpreport_destroy(p_struct);
6871 0 : alglib_impl::ae_free(p_struct);
6872 : }
6873 0 : p_struct = NULL;
6874 : #if !defined(AE_NO_EXCEPTIONS)
6875 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
6876 : #else
6877 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
6878 : return;
6879 : #endif
6880 : }
6881 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
6882 0 : p_struct = NULL;
6883 0 : p_struct = (alglib_impl::minlpreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlpreport), &_state);
6884 0 : memset(p_struct, 0, sizeof(alglib_impl::minlpreport));
6885 0 : alglib_impl::_minlpreport_init(p_struct, &_state, ae_false);
6886 0 : ae_state_clear(&_state);
6887 0 : }
6888 :
6889 0 : _minlpreport_owner::_minlpreport_owner(const _minlpreport_owner &rhs)
6890 : {
6891 : jmp_buf _break_jump;
6892 : alglib_impl::ae_state _state;
6893 :
6894 0 : alglib_impl::ae_state_init(&_state);
6895 0 : if( setjmp(_break_jump) )
6896 : {
6897 0 : if( p_struct!=NULL )
6898 : {
6899 0 : alglib_impl::_minlpreport_destroy(p_struct);
6900 0 : alglib_impl::ae_free(p_struct);
6901 : }
6902 0 : p_struct = NULL;
6903 : #if !defined(AE_NO_EXCEPTIONS)
6904 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
6905 : #else
6906 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
6907 : return;
6908 : #endif
6909 : }
6910 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
6911 0 : p_struct = NULL;
6912 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlpreport copy constructor failure (source is not initialized)", &_state);
6913 0 : p_struct = (alglib_impl::minlpreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlpreport), &_state);
6914 0 : memset(p_struct, 0, sizeof(alglib_impl::minlpreport));
6915 0 : alglib_impl::_minlpreport_init_copy(p_struct, const_cast<alglib_impl::minlpreport*>(rhs.p_struct), &_state, ae_false);
6916 0 : ae_state_clear(&_state);
6917 0 : }
6918 :
6919 0 : _minlpreport_owner& _minlpreport_owner::operator=(const _minlpreport_owner &rhs)
6920 : {
6921 0 : if( this==&rhs )
6922 0 : return *this;
6923 : jmp_buf _break_jump;
6924 : alglib_impl::ae_state _state;
6925 :
6926 0 : alglib_impl::ae_state_init(&_state);
6927 0 : if( setjmp(_break_jump) )
6928 : {
6929 : #if !defined(AE_NO_EXCEPTIONS)
6930 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
6931 : #else
6932 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
6933 : return *this;
6934 : #endif
6935 : }
6936 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
6937 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minlpreport assignment constructor failure (destination is not initialized)", &_state);
6938 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlpreport assignment constructor failure (source is not initialized)", &_state);
6939 0 : alglib_impl::_minlpreport_destroy(p_struct);
6940 0 : memset(p_struct, 0, sizeof(alglib_impl::minlpreport));
6941 0 : alglib_impl::_minlpreport_init_copy(p_struct, const_cast<alglib_impl::minlpreport*>(rhs.p_struct), &_state, ae_false);
6942 0 : ae_state_clear(&_state);
6943 0 : return *this;
6944 : }
6945 :
6946 0 : _minlpreport_owner::~_minlpreport_owner()
6947 : {
6948 0 : if( p_struct!=NULL )
6949 : {
6950 0 : alglib_impl::_minlpreport_destroy(p_struct);
6951 0 : ae_free(p_struct);
6952 : }
6953 0 : }
6954 :
6955 0 : alglib_impl::minlpreport* _minlpreport_owner::c_ptr()
6956 : {
6957 0 : return p_struct;
6958 : }
6959 :
6960 0 : alglib_impl::minlpreport* _minlpreport_owner::c_ptr() const
6961 : {
6962 0 : return const_cast<alglib_impl::minlpreport*>(p_struct);
6963 : }
6964 0 : minlpreport::minlpreport() : _minlpreport_owner() ,f(p_struct->f),lagbc(&p_struct->lagbc),laglc(&p_struct->laglc),y(&p_struct->y),stats(&p_struct->stats),primalerror(p_struct->primalerror),dualerror(p_struct->dualerror),slackerror(p_struct->slackerror),iterationscount(p_struct->iterationscount),terminationtype(p_struct->terminationtype)
6965 : {
6966 0 : }
6967 :
6968 0 : minlpreport::minlpreport(const minlpreport &rhs):_minlpreport_owner(rhs) ,f(p_struct->f),lagbc(&p_struct->lagbc),laglc(&p_struct->laglc),y(&p_struct->y),stats(&p_struct->stats),primalerror(p_struct->primalerror),dualerror(p_struct->dualerror),slackerror(p_struct->slackerror),iterationscount(p_struct->iterationscount),terminationtype(p_struct->terminationtype)
6969 : {
6970 0 : }
6971 :
6972 0 : minlpreport& minlpreport::operator=(const minlpreport &rhs)
6973 : {
6974 0 : if( this==&rhs )
6975 0 : return *this;
6976 0 : _minlpreport_owner::operator=(rhs);
6977 0 : return *this;
6978 : }
6979 :
6980 0 : minlpreport::~minlpreport()
6981 : {
6982 0 : }
6983 :
6984 : /*************************************************************************
6985 : LINEAR PROGRAMMING
6986 :
6987 : The subroutine creates LP solver. After initial creation it contains
6988 : default optimization problem with zero cost vector and all variables being
6989 : fixed to zero values and no constraints.
6990 :
6991 : In order to actually solve something you should:
6992 : * set cost vector with minlpsetcost()
6993 : * set variable bounds with minlpsetbc() or minlpsetbcall()
6994 : * specify constraint matrix with one of the following functions:
6995 : [*] minlpsetlc() for dense one-sided constraints
6996 : [*] minlpsetlc2dense() for dense two-sided constraints
6997 : [*] minlpsetlc2() for sparse two-sided constraints
6998 : [*] minlpaddlc2dense() to add one dense row to constraint matrix
6999 : [*] minlpaddlc2() to add one row to constraint matrix (compressed format)
7000 : * call minlpoptimize() to run the solver and minlpresults() to get the
7001 : solution vector and additional information.
7002 :
7003 : By default, LP solver uses best algorithm available. As of ALGLIB 3.17,
7004 : sparse interior point (barrier) solver is used. Future releases of ALGLIB
7005 : may introduce other solvers.
7006 :
7007 : User may choose specific LP algorithm by calling:
7008 : * minlpsetalgodss() for revised dual simplex method with DSE pricing and
7009 : bounds flipping ratio test (aka long dual step). Large-scale sparse LU
7010 : solverwith Forest-Tomlin update is used internally as linear algebra
7011 : driver.
7012 : * minlpsetalgoipm() for sparse interior point method
7013 :
7014 : INPUT PARAMETERS:
7015 : N - problem size
7016 :
7017 : OUTPUT PARAMETERS:
7018 : State - optimizer in the default state
7019 :
7020 : -- ALGLIB --
7021 : Copyright 19.07.2018 by Bochkanov Sergey
7022 : *************************************************************************/
7023 0 : void minlpcreate(const ae_int_t n, minlpstate &state, const xparams _xparams)
7024 : {
7025 : jmp_buf _break_jump;
7026 : alglib_impl::ae_state _alglib_env_state;
7027 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7028 0 : if( setjmp(_break_jump) )
7029 : {
7030 : #if !defined(AE_NO_EXCEPTIONS)
7031 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7032 : #else
7033 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7034 : return;
7035 : #endif
7036 : }
7037 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7038 0 : if( _xparams.flags!=0x0 )
7039 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7040 0 : alglib_impl::minlpcreate(n, const_cast<alglib_impl::minlpstate*>(state.c_ptr()), &_alglib_env_state);
7041 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7042 0 : return;
7043 : }
7044 :
7045 : /*************************************************************************
7046 : This function sets LP algorithm to revised dual simplex method.
7047 :
7048 : ALGLIB implementation of dual simplex method supports advanced performance
7049 : and stability improvements like DSE pricing , bounds flipping ratio test
7050 : (aka long dual step), Forest-Tomlin update, shifting.
7051 :
7052 : INPUT PARAMETERS:
7053 : State - optimizer
7054 : Eps - stopping condition, Eps>=0:
7055 : * should be small number about 1E-6 or 1E-7.
7056 : * zero value means that solver automatically selects good
7057 : value (can be different in different ALGLIB versions)
7058 : * default value is zero
7059 : Algorithm stops when relative error is less than Eps.
7060 :
7061 : ===== TRACING DSS SOLVER =================================================
7062 :
7063 : DSS solver supports advanced tracing capabilities. You can trace algorithm
7064 : output by specifying following trace symbols (case-insensitive) by means
7065 : of trace_file() call:
7066 : * 'DSS' - for basic trace of algorithm steps and decisions. Only
7067 : short scalars (function values and deltas) are printed.
7068 : N-dimensional quantities like search directions are NOT
7069 : printed.
7070 : * 'DSS.DETAILED'- for output of points being visited and search directions
7071 : This symbol also implicitly defines 'DSS'. You can
7072 : control output format by additionally specifying:
7073 : * nothing to output in 6-digit exponential format
7074 : * 'PREC.E15' to output in 15-digit exponential format
7075 : * 'PREC.F6' to output in 6-digit fixed-point format
7076 :
7077 : By default trace is disabled and adds no overhead to the optimization
7078 : process. However, specifying any of the symbols adds some formatting and
7079 : output-related overhead.
7080 :
7081 : You may specify multiple symbols by separating them with commas:
7082 : >
7083 : > alglib::trace_file("DSS,PREC.F6", "path/to/trace.log")
7084 : >
7085 :
7086 : -- ALGLIB --
7087 : Copyright 08.11.2020 by Bochkanov Sergey
7088 : *************************************************************************/
7089 0 : void minlpsetalgodss(const minlpstate &state, const double eps, const xparams _xparams)
7090 : {
7091 : jmp_buf _break_jump;
7092 : alglib_impl::ae_state _alglib_env_state;
7093 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7094 0 : if( setjmp(_break_jump) )
7095 : {
7096 : #if !defined(AE_NO_EXCEPTIONS)
7097 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7098 : #else
7099 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7100 : return;
7101 : #endif
7102 : }
7103 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7104 0 : if( _xparams.flags!=0x0 )
7105 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7106 0 : alglib_impl::minlpsetalgodss(const_cast<alglib_impl::minlpstate*>(state.c_ptr()), eps, &_alglib_env_state);
7107 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7108 0 : return;
7109 : }
7110 :
7111 : /*************************************************************************
7112 : This function sets LP algorithm to sparse interior point method.
7113 :
7114 : ALGORITHM INFORMATION:
7115 :
7116 : * this algorithm is our implementation of interior point method as
7117 : formulated by R.J.Vanderbei, with minor modifications to the algorithm
7118 : (damped Newton directions are extensively used)
7119 : * like all interior point methods, this algorithm tends to converge in
7120 : roughly same number of iterations (between 15 and 50) independently from
7121 : the problem dimensionality
7122 :
7123 : INPUT PARAMETERS:
7124 : State - optimizer
7125 : Eps - stopping condition, Eps>=0:
7126 : * should be small number about 1E-7 or 1E-8.
7127 : * zero value means that solver automatically selects good
7128 : value (can be different in different ALGLIB versions)
7129 : * default value is zero
7130 : Algorithm stops when primal error AND dual error AND
7131 : duality gap are less than Eps.
7132 :
7133 : ===== TRACING IPM SOLVER =================================================
7134 :
7135 : IPM solver supports advanced tracing capabilities. You can trace algorithm
7136 : output by specifying following trace symbols (case-insensitive) by means
7137 : of trace_file() call:
7138 : * 'IPM' - for basic trace of algorithm steps and decisions. Only
7139 : short scalars (function values and deltas) are printed.
7140 : N-dimensional quantities like search directions are NOT
7141 : printed.
7142 : * 'IPM.DETAILED'- for output of points being visited and search directions
7143 : This symbol also implicitly defines 'IPM'. You can
7144 : control output format by additionally specifying:
7145 : * nothing to output in 6-digit exponential format
7146 : * 'PREC.E15' to output in 15-digit exponential format
7147 : * 'PREC.F6' to output in 6-digit fixed-point format
7148 :
7149 : By default trace is disabled and adds no overhead to the optimization
7150 : process. However, specifying any of the symbols adds some formatting and
7151 : output-related overhead.
7152 :
7153 : You may specify multiple symbols by separating them with commas:
7154 : >
7155 : > alglib::trace_file("IPM,PREC.F6", "path/to/trace.log")
7156 : >
7157 :
7158 : -- ALGLIB --
7159 : Copyright 08.11.2020 by Bochkanov Sergey
7160 : *************************************************************************/
7161 0 : void minlpsetalgoipm(const minlpstate &state, const double eps, const xparams _xparams)
7162 : {
7163 : jmp_buf _break_jump;
7164 : alglib_impl::ae_state _alglib_env_state;
7165 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7166 0 : if( setjmp(_break_jump) )
7167 : {
7168 : #if !defined(AE_NO_EXCEPTIONS)
7169 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7170 : #else
7171 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7172 : return;
7173 : #endif
7174 : }
7175 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7176 0 : if( _xparams.flags!=0x0 )
7177 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7178 0 : alglib_impl::minlpsetalgoipm(const_cast<alglib_impl::minlpstate*>(state.c_ptr()), eps, &_alglib_env_state);
7179 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7180 0 : return;
7181 : }
7182 :
7183 : /*************************************************************************
7184 : This function sets LP algorithm to sparse interior point method.
7185 :
7186 : ALGORITHM INFORMATION:
7187 :
7188 : * this algorithm is our implementation of interior point method as
7189 : formulated by R.J.Vanderbei, with minor modifications to the algorithm
7190 : (damped Newton directions are extensively used)
7191 : * like all interior point methods, this algorithm tends to converge in
7192 : roughly same number of iterations (between 15 and 50) independently from
7193 : the problem dimensionality
7194 :
7195 : INPUT PARAMETERS:
7196 : State - optimizer
7197 : Eps - stopping condition, Eps>=0:
7198 : * should be small number about 1E-7 or 1E-8.
7199 : * zero value means that solver automatically selects good
7200 : value (can be different in different ALGLIB versions)
7201 : * default value is zero
7202 : Algorithm stops when primal error AND dual error AND
7203 : duality gap are less than Eps.
7204 :
7205 : ===== TRACING IPM SOLVER =================================================
7206 :
7207 : IPM solver supports advanced tracing capabilities. You can trace algorithm
7208 : output by specifying following trace symbols (case-insensitive) by means
7209 : of trace_file() call:
7210 : * 'IPM' - for basic trace of algorithm steps and decisions. Only
7211 : short scalars (function values and deltas) are printed.
7212 : N-dimensional quantities like search directions are NOT
7213 : printed.
7214 : * 'IPM.DETAILED'- for output of points being visited and search directions
7215 : This symbol also implicitly defines 'IPM'. You can
7216 : control output format by additionally specifying:
7217 : * nothing to output in 6-digit exponential format
7218 : * 'PREC.E15' to output in 15-digit exponential format
7219 : * 'PREC.F6' to output in 6-digit fixed-point format
7220 :
7221 : By default trace is disabled and adds no overhead to the optimization
7222 : process. However, specifying any of the symbols adds some formatting and
7223 : output-related overhead.
7224 :
7225 : You may specify multiple symbols by separating them with commas:
7226 : >
7227 : > alglib::trace_file("IPM,PREC.F6", "path/to/trace.log")
7228 : >
7229 :
7230 : -- ALGLIB --
7231 : Copyright 08.11.2020 by Bochkanov Sergey
7232 : *************************************************************************/
7233 : #if !defined(AE_NO_EXCEPTIONS)
7234 0 : void minlpsetalgoipm(const minlpstate &state, const xparams _xparams)
7235 : {
7236 : jmp_buf _break_jump;
7237 : alglib_impl::ae_state _alglib_env_state;
7238 : double eps;
7239 :
7240 0 : eps = 0;
7241 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7242 0 : if( setjmp(_break_jump) )
7243 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7244 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7245 0 : if( _xparams.flags!=0x0 )
7246 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7247 0 : alglib_impl::minlpsetalgoipm(const_cast<alglib_impl::minlpstate*>(state.c_ptr()), eps, &_alglib_env_state);
7248 :
7249 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7250 0 : return;
7251 : }
7252 : #endif
7253 :
7254 : /*************************************************************************
7255 : This function sets cost term for LP solver.
7256 :
7257 : By default, cost term is zero.
7258 :
7259 : INPUT PARAMETERS:
7260 : State - structure which stores algorithm state
7261 : C - cost term, array[N].
7262 :
7263 : -- ALGLIB --
7264 : Copyright 19.07.2018 by Bochkanov Sergey
7265 : *************************************************************************/
7266 0 : void minlpsetcost(const minlpstate &state, const real_1d_array &c, const xparams _xparams)
7267 : {
7268 : jmp_buf _break_jump;
7269 : alglib_impl::ae_state _alglib_env_state;
7270 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7271 0 : if( setjmp(_break_jump) )
7272 : {
7273 : #if !defined(AE_NO_EXCEPTIONS)
7274 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7275 : #else
7276 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7277 : return;
7278 : #endif
7279 : }
7280 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7281 0 : if( _xparams.flags!=0x0 )
7282 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7283 0 : alglib_impl::minlpsetcost(const_cast<alglib_impl::minlpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(c.c_ptr()), &_alglib_env_state);
7284 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7285 0 : return;
7286 : }
7287 :
7288 : /*************************************************************************
7289 : This function sets scaling coefficients.
7290 :
7291 : ALGLIB optimizers use scaling matrices to test stopping conditions and as
7292 : preconditioner.
7293 :
7294 : Scale of the I-th variable is a translation invariant measure of:
7295 : a) "how large" the variable is
7296 : b) how large the step should be to make significant changes in the
7297 : function
7298 :
7299 : INPUT PARAMETERS:
7300 : State - structure stores algorithm state
7301 : S - array[N], non-zero scaling coefficients
7302 : S[i] may be negative, sign doesn't matter.
7303 :
7304 : -- ALGLIB --
7305 : Copyright 19.07.2018 by Bochkanov Sergey
7306 : *************************************************************************/
7307 0 : void minlpsetscale(const minlpstate &state, const real_1d_array &s, const xparams _xparams)
7308 : {
7309 : jmp_buf _break_jump;
7310 : alglib_impl::ae_state _alglib_env_state;
7311 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7312 0 : if( setjmp(_break_jump) )
7313 : {
7314 : #if !defined(AE_NO_EXCEPTIONS)
7315 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7316 : #else
7317 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7318 : return;
7319 : #endif
7320 : }
7321 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7322 0 : if( _xparams.flags!=0x0 )
7323 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7324 0 : alglib_impl::minlpsetscale(const_cast<alglib_impl::minlpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(s.c_ptr()), &_alglib_env_state);
7325 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7326 0 : return;
7327 : }
7328 :
7329 : /*************************************************************************
7330 : This function sets box constraints for LP solver (all variables at once,
7331 : different constraints for different variables).
7332 :
7333 : The default state of constraints is to have all variables fixed at zero.
7334 : You have to overwrite it by your own constraint vector. Constraint status
7335 : is preserved until constraints are explicitly overwritten with another
7336 : minlpsetbc() call, overwritten with minlpsetbcall(), or partially
7337 : overwritten with minlmsetbci() call.
7338 :
7339 : Following types of constraints are supported:
7340 :
7341 : DESCRIPTION CONSTRAINT HOW TO SPECIFY
7342 : fixed variable x[i]=Bnd[i] BndL[i]=BndU[i]
7343 : lower bound BndL[i]<=x[i] BndU[i]=+INF
7344 : upper bound x[i]<=BndU[i] BndL[i]=-INF
7345 : range BndL[i]<=x[i]<=BndU[i] ...
7346 : free variable - BndL[I]=-INF, BndU[I]+INF
7347 :
7348 : INPUT PARAMETERS:
7349 : State - structure stores algorithm state
7350 : BndL - lower bounds, array[N].
7351 : BndU - upper bounds, array[N].
7352 :
7353 : NOTE: infinite values can be specified by means of Double.PositiveInfinity
7354 : and Double.NegativeInfinity (in C#) and alglib::fp_posinf and
7355 : alglib::fp_neginf (in C++).
7356 :
7357 : NOTE: you may replace infinities by very small/very large values, but it
7358 : is not recommended because large numbers may introduce large numerical
7359 : errors in the algorithm.
7360 :
7361 : NOTE: if constraints for all variables are same you may use minlpsetbcall()
7362 : which allows to specify constraints without using arrays.
7363 :
7364 : NOTE: BndL>BndU will result in LP problem being recognized as infeasible.
7365 :
7366 : -- ALGLIB --
7367 : Copyright 19.07.2018 by Bochkanov Sergey
7368 : *************************************************************************/
7369 0 : void minlpsetbc(const minlpstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams)
7370 : {
7371 : jmp_buf _break_jump;
7372 : alglib_impl::ae_state _alglib_env_state;
7373 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7374 0 : if( setjmp(_break_jump) )
7375 : {
7376 : #if !defined(AE_NO_EXCEPTIONS)
7377 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7378 : #else
7379 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7380 : return;
7381 : #endif
7382 : }
7383 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7384 0 : if( _xparams.flags!=0x0 )
7385 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7386 0 : alglib_impl::minlpsetbc(const_cast<alglib_impl::minlpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(bndl.c_ptr()), const_cast<alglib_impl::ae_vector*>(bndu.c_ptr()), &_alglib_env_state);
7387 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7388 0 : return;
7389 : }
7390 :
7391 : /*************************************************************************
7392 : This function sets box constraints for LP solver (all variables at once,
7393 : same constraints for all variables)
7394 :
7395 : The default state of constraints is to have all variables fixed at zero.
7396 : You have to overwrite it by your own constraint vector. Constraint status
7397 : is preserved until constraints are explicitly overwritten with another
7398 : minlpsetbc() call or partially overwritten with minlpsetbcall().
7399 :
7400 : Following types of constraints are supported:
7401 :
7402 : DESCRIPTION CONSTRAINT HOW TO SPECIFY
7403 : fixed variable x[i]=Bnd[i] BndL[i]=BndU[i]
7404 : lower bound BndL[i]<=x[i] BndU[i]=+INF
7405 : upper bound x[i]<=BndU[i] BndL[i]=-INF
7406 : range BndL[i]<=x[i]<=BndU[i] ...
7407 : free variable - BndL[I]=-INF, BndU[I]+INF
7408 :
7409 : INPUT PARAMETERS:
7410 : State - structure stores algorithm state
7411 : BndL - lower bound, same for all variables
7412 : BndU - upper bound, same for all variables
7413 :
7414 : NOTE: infinite values can be specified by means of Double.PositiveInfinity
7415 : and Double.NegativeInfinity (in C#) and alglib::fp_posinf and
7416 : alglib::fp_neginf (in C++).
7417 :
7418 : NOTE: you may replace infinities by very small/very large values, but it
7419 : is not recommended because large numbers may introduce large numerical
7420 : errors in the algorithm.
7421 :
7422 : NOTE: minlpsetbc() can be used to specify different constraints for
7423 : different variables.
7424 :
7425 : NOTE: BndL>BndU will result in LP problem being recognized as infeasible.
7426 :
7427 : -- ALGLIB --
7428 : Copyright 19.07.2018 by Bochkanov Sergey
7429 : *************************************************************************/
7430 0 : void minlpsetbcall(const minlpstate &state, const double bndl, const double bndu, const xparams _xparams)
7431 : {
7432 : jmp_buf _break_jump;
7433 : alglib_impl::ae_state _alglib_env_state;
7434 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7435 0 : if( setjmp(_break_jump) )
7436 : {
7437 : #if !defined(AE_NO_EXCEPTIONS)
7438 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7439 : #else
7440 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7441 : return;
7442 : #endif
7443 : }
7444 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7445 0 : if( _xparams.flags!=0x0 )
7446 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7447 0 : alglib_impl::minlpsetbcall(const_cast<alglib_impl::minlpstate*>(state.c_ptr()), bndl, bndu, &_alglib_env_state);
7448 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7449 0 : return;
7450 : }
7451 :
7452 : /*************************************************************************
7453 : This function sets box constraints for I-th variable (other variables are
7454 : not modified).
7455 :
7456 : The default state of constraints is to have all variables fixed at zero.
7457 : You have to overwrite it by your own constraint vector.
7458 :
7459 : Following types of constraints are supported:
7460 :
7461 : DESCRIPTION CONSTRAINT HOW TO SPECIFY
7462 : fixed variable x[i]=Bnd[i] BndL[i]=BndU[i]
7463 : lower bound BndL[i]<=x[i] BndU[i]=+INF
7464 : upper bound x[i]<=BndU[i] BndL[i]=-INF
7465 : range BndL[i]<=x[i]<=BndU[i] ...
7466 : free variable - BndL[I]=-INF, BndU[I]+INF
7467 :
7468 : INPUT PARAMETERS:
7469 : State - structure stores algorithm state
7470 : I - variable index, in [0,N)
7471 : BndL - lower bound for I-th variable
7472 : BndU - upper bound for I-th variable
7473 :
7474 : NOTE: infinite values can be specified by means of Double.PositiveInfinity
7475 : and Double.NegativeInfinity (in C#) and alglib::fp_posinf and
7476 : alglib::fp_neginf (in C++).
7477 :
7478 : NOTE: you may replace infinities by very small/very large values, but it
7479 : is not recommended because large numbers may introduce large numerical
7480 : errors in the algorithm.
7481 :
7482 : NOTE: minlpsetbc() can be used to specify different constraints for
7483 : different variables.
7484 :
7485 : NOTE: BndL>BndU will result in LP problem being recognized as infeasible.
7486 :
7487 : -- ALGLIB --
7488 : Copyright 19.07.2018 by Bochkanov Sergey
7489 : *************************************************************************/
7490 0 : void minlpsetbci(const minlpstate &state, const ae_int_t i, const double bndl, const double bndu, const xparams _xparams)
7491 : {
7492 : jmp_buf _break_jump;
7493 : alglib_impl::ae_state _alglib_env_state;
7494 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7495 0 : if( setjmp(_break_jump) )
7496 : {
7497 : #if !defined(AE_NO_EXCEPTIONS)
7498 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7499 : #else
7500 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7501 : return;
7502 : #endif
7503 : }
7504 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7505 0 : if( _xparams.flags!=0x0 )
7506 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7507 0 : alglib_impl::minlpsetbci(const_cast<alglib_impl::minlpstate*>(state.c_ptr()), i, bndl, bndu, &_alglib_env_state);
7508 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7509 0 : return;
7510 : }
7511 :
7512 : /*************************************************************************
7513 : This function sets one-sided linear constraints A*x ~ AU, where "~" can be
7514 : a mix of "<=", "=" and ">=".
7515 :
7516 : IMPORTANT: this function is provided here for compatibility with the rest
7517 : of ALGLIB optimizers which accept constraints in format like
7518 : this one. Many real-life problems feature two-sided constraints
7519 : like a0 <= a*x <= a1. It is really inefficient to add them as a
7520 : pair of one-sided constraints.
7521 :
7522 : Use minlpsetlc2dense(), minlpsetlc2(), minlpaddlc2() (or its
7523 : sparse version) wherever possible.
7524 :
7525 : INPUT PARAMETERS:
7526 : State - structure previously allocated with minlpcreate() call.
7527 : A - linear constraints, array[K,N+1]. Each row of A represents
7528 : one constraint, with first N elements being linear coefficients,
7529 : and last element being right side.
7530 : CT - constraint types, array[K]:
7531 : * if CT[i]>0, then I-th constraint is A[i,*]*x >= A[i,n]
7532 : * if CT[i]=0, then I-th constraint is A[i,*]*x = A[i,n]
7533 : * if CT[i]<0, then I-th constraint is A[i,*]*x <= A[i,n]
7534 : K - number of equality/inequality constraints, K>=0; if not
7535 : given, inferred from sizes of A and CT.
7536 :
7537 : -- ALGLIB --
7538 : Copyright 19.07.2018 by Bochkanov Sergey
7539 : *************************************************************************/
7540 0 : void minlpsetlc(const minlpstate &state, const real_2d_array &a, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams)
7541 : {
7542 : jmp_buf _break_jump;
7543 : alglib_impl::ae_state _alglib_env_state;
7544 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7545 0 : if( setjmp(_break_jump) )
7546 : {
7547 : #if !defined(AE_NO_EXCEPTIONS)
7548 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7549 : #else
7550 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7551 : return;
7552 : #endif
7553 : }
7554 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7555 0 : if( _xparams.flags!=0x0 )
7556 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7557 0 : alglib_impl::minlpsetlc(const_cast<alglib_impl::minlpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), const_cast<alglib_impl::ae_vector*>(ct.c_ptr()), k, &_alglib_env_state);
7558 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7559 0 : return;
7560 : }
7561 :
7562 : /*************************************************************************
7563 : This function sets one-sided linear constraints A*x ~ AU, where "~" can be
7564 : a mix of "<=", "=" and ">=".
7565 :
7566 : IMPORTANT: this function is provided here for compatibility with the rest
7567 : of ALGLIB optimizers which accept constraints in format like
7568 : this one. Many real-life problems feature two-sided constraints
7569 : like a0 <= a*x <= a1. It is really inefficient to add them as a
7570 : pair of one-sided constraints.
7571 :
7572 : Use minlpsetlc2dense(), minlpsetlc2(), minlpaddlc2() (or its
7573 : sparse version) wherever possible.
7574 :
7575 : INPUT PARAMETERS:
7576 : State - structure previously allocated with minlpcreate() call.
7577 : A - linear constraints, array[K,N+1]. Each row of A represents
7578 : one constraint, with first N elements being linear coefficients,
7579 : and last element being right side.
7580 : CT - constraint types, array[K]:
7581 : * if CT[i]>0, then I-th constraint is A[i,*]*x >= A[i,n]
7582 : * if CT[i]=0, then I-th constraint is A[i,*]*x = A[i,n]
7583 : * if CT[i]<0, then I-th constraint is A[i,*]*x <= A[i,n]
7584 : K - number of equality/inequality constraints, K>=0; if not
7585 : given, inferred from sizes of A and CT.
7586 :
7587 : -- ALGLIB --
7588 : Copyright 19.07.2018 by Bochkanov Sergey
7589 : *************************************************************************/
7590 : #if !defined(AE_NO_EXCEPTIONS)
7591 0 : void minlpsetlc(const minlpstate &state, const real_2d_array &a, const integer_1d_array &ct, const xparams _xparams)
7592 : {
7593 : jmp_buf _break_jump;
7594 : alglib_impl::ae_state _alglib_env_state;
7595 : ae_int_t k;
7596 0 : if( (a.rows()!=ct.length()))
7597 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'minlpsetlc': looks like one of arguments has wrong size");
7598 0 : k = a.rows();
7599 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7600 0 : if( setjmp(_break_jump) )
7601 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7602 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7603 0 : if( _xparams.flags!=0x0 )
7604 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7605 0 : alglib_impl::minlpsetlc(const_cast<alglib_impl::minlpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), const_cast<alglib_impl::ae_vector*>(ct.c_ptr()), k, &_alglib_env_state);
7606 :
7607 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7608 0 : return;
7609 : }
7610 : #endif
7611 :
7612 : /*************************************************************************
7613 : This function sets two-sided linear constraints AL <= A*x <= AU.
7614 :
7615 : This version accepts dense matrix as input; internally LP solver uses
7616 : sparse storage anyway (most LP problems are sparse), but for your
7617 : convenience it may accept dense inputs. This function overwrites linear
7618 : constraints set by previous calls (if such calls were made).
7619 :
7620 : We recommend you to use sparse version of this function unless you solve
7621 : small-scale LP problem (less than few hundreds of variables).
7622 :
7623 : NOTE: there also exist several versions of this function:
7624 : * one-sided dense version which accepts constraints in the same
7625 : format as one used by QP and NLP solvers
7626 : * two-sided sparse version which accepts sparse matrix
7627 : * two-sided dense version which allows you to add constraints row by row
7628 : * two-sided sparse version which allows you to add constraints row by row
7629 :
7630 : INPUT PARAMETERS:
7631 : State - structure previously allocated with minlpcreate() call.
7632 : A - linear constraints, array[K,N]. Each row of A represents
7633 : one constraint. One-sided inequality constraints, two-
7634 : sided inequality constraints, equality constraints are
7635 : supported (see below)
7636 : AL, AU - lower and upper bounds, array[K];
7637 : * AL[i]=AU[i] => equality constraint Ai*x
7638 : * AL[i]<AU[i] => two-sided constraint AL[i]<=Ai*x<=AU[i]
7639 : * AL[i]=-INF => one-sided constraint Ai*x<=AU[i]
7640 : * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x
7641 : * AL[i]=-INF, AU[i]=+INF => constraint is ignored
7642 : K - number of equality/inequality constraints, K>=0; if not
7643 : given, inferred from sizes of A, AL, AU.
7644 :
7645 : -- ALGLIB --
7646 : Copyright 19.07.2018 by Bochkanov Sergey
7647 : *************************************************************************/
7648 0 : void minlpsetlc2dense(const minlpstate &state, const real_2d_array &a, const real_1d_array &al, const real_1d_array &au, const ae_int_t k, const xparams _xparams)
7649 : {
7650 : jmp_buf _break_jump;
7651 : alglib_impl::ae_state _alglib_env_state;
7652 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7653 0 : if( setjmp(_break_jump) )
7654 : {
7655 : #if !defined(AE_NO_EXCEPTIONS)
7656 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7657 : #else
7658 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7659 : return;
7660 : #endif
7661 : }
7662 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7663 0 : if( _xparams.flags!=0x0 )
7664 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7665 0 : alglib_impl::minlpsetlc2dense(const_cast<alglib_impl::minlpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), const_cast<alglib_impl::ae_vector*>(al.c_ptr()), const_cast<alglib_impl::ae_vector*>(au.c_ptr()), k, &_alglib_env_state);
7666 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7667 0 : return;
7668 : }
7669 :
7670 : /*************************************************************************
7671 : This function sets two-sided linear constraints AL <= A*x <= AU.
7672 :
7673 : This version accepts dense matrix as input; internally LP solver uses
7674 : sparse storage anyway (most LP problems are sparse), but for your
7675 : convenience it may accept dense inputs. This function overwrites linear
7676 : constraints set by previous calls (if such calls were made).
7677 :
7678 : We recommend you to use sparse version of this function unless you solve
7679 : small-scale LP problem (less than few hundreds of variables).
7680 :
7681 : NOTE: there also exist several versions of this function:
7682 : * one-sided dense version which accepts constraints in the same
7683 : format as one used by QP and NLP solvers
7684 : * two-sided sparse version which accepts sparse matrix
7685 : * two-sided dense version which allows you to add constraints row by row
7686 : * two-sided sparse version which allows you to add constraints row by row
7687 :
7688 : INPUT PARAMETERS:
7689 : State - structure previously allocated with minlpcreate() call.
7690 : A - linear constraints, array[K,N]. Each row of A represents
7691 : one constraint. One-sided inequality constraints, two-
7692 : sided inequality constraints, equality constraints are
7693 : supported (see below)
7694 : AL, AU - lower and upper bounds, array[K];
7695 : * AL[i]=AU[i] => equality constraint Ai*x
7696 : * AL[i]<AU[i] => two-sided constraint AL[i]<=Ai*x<=AU[i]
7697 : * AL[i]=-INF => one-sided constraint Ai*x<=AU[i]
7698 : * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x
7699 : * AL[i]=-INF, AU[i]=+INF => constraint is ignored
7700 : K - number of equality/inequality constraints, K>=0; if not
7701 : given, inferred from sizes of A, AL, AU.
7702 :
7703 : -- ALGLIB --
7704 : Copyright 19.07.2018 by Bochkanov Sergey
7705 : *************************************************************************/
7706 : #if !defined(AE_NO_EXCEPTIONS)
7707 0 : void minlpsetlc2dense(const minlpstate &state, const real_2d_array &a, const real_1d_array &al, const real_1d_array &au, const xparams _xparams)
7708 : {
7709 : jmp_buf _break_jump;
7710 : alglib_impl::ae_state _alglib_env_state;
7711 : ae_int_t k;
7712 0 : if( (a.rows()!=al.length()) || (a.rows()!=au.length()))
7713 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'minlpsetlc2dense': looks like one of arguments has wrong size");
7714 0 : k = a.rows();
7715 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7716 0 : if( setjmp(_break_jump) )
7717 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7718 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7719 0 : if( _xparams.flags!=0x0 )
7720 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7721 0 : alglib_impl::minlpsetlc2dense(const_cast<alglib_impl::minlpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), const_cast<alglib_impl::ae_vector*>(al.c_ptr()), const_cast<alglib_impl::ae_vector*>(au.c_ptr()), k, &_alglib_env_state);
7722 :
7723 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7724 0 : return;
7725 : }
7726 : #endif
7727 :
7728 : /*************************************************************************
7729 : This function sets two-sided linear constraints AL <= A*x <= AU with
7730 : sparse constraining matrix A. Recommended for large-scale problems.
7731 :
7732 : This function overwrites linear (non-box) constraints set by previous
7733 : calls (if such calls were made).
7734 :
7735 : INPUT PARAMETERS:
7736 : State - structure previously allocated with minlpcreate() call.
7737 : A - sparse matrix with size [K,N] (exactly!).
7738 : Each row of A represents one general linear constraint.
7739 : A can be stored in any sparse storage format.
7740 : AL, AU - lower and upper bounds, array[K];
7741 : * AL[i]=AU[i] => equality constraint Ai*x
7742 : * AL[i]<AU[i] => two-sided constraint AL[i]<=Ai*x<=AU[i]
7743 : * AL[i]=-INF => one-sided constraint Ai*x<=AU[i]
7744 : * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x
7745 : * AL[i]=-INF, AU[i]=+INF => constraint is ignored
7746 : K - number of equality/inequality constraints, K>=0. If K=0
7747 : is specified, A, AL, AU are ignored.
7748 :
7749 : -- ALGLIB --
7750 : Copyright 19.07.2018 by Bochkanov Sergey
7751 : *************************************************************************/
7752 0 : void minlpsetlc2(const minlpstate &state, const sparsematrix &a, const real_1d_array &al, const real_1d_array &au, const ae_int_t k, const xparams _xparams)
7753 : {
7754 : jmp_buf _break_jump;
7755 : alglib_impl::ae_state _alglib_env_state;
7756 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7757 0 : if( setjmp(_break_jump) )
7758 : {
7759 : #if !defined(AE_NO_EXCEPTIONS)
7760 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7761 : #else
7762 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7763 : return;
7764 : #endif
7765 : }
7766 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7767 0 : if( _xparams.flags!=0x0 )
7768 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7769 0 : alglib_impl::minlpsetlc2(const_cast<alglib_impl::minlpstate*>(state.c_ptr()), const_cast<alglib_impl::sparsematrix*>(a.c_ptr()), const_cast<alglib_impl::ae_vector*>(al.c_ptr()), const_cast<alglib_impl::ae_vector*>(au.c_ptr()), k, &_alglib_env_state);
7770 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7771 0 : return;
7772 : }
7773 :
7774 : /*************************************************************************
7775 : This function appends two-sided linear constraint AL <= A*x <= AU to the
7776 : list of currently present constraints.
7777 :
7778 : This version accepts dense constraint vector as input, but sparsifies it
7779 : for internal storage and processing. Thus, time to add one constraint in
7780 : is O(N) - we have to scan entire array of length N. Sparse version of this
7781 : function is order of magnitude faster for constraints with just a few
7782 : nonzeros per row.
7783 :
7784 : INPUT PARAMETERS:
7785 : State - structure previously allocated with minlpcreate() call.
7786 : A - linear constraint coefficient, array[N], right side is NOT
7787 : included.
7788 : AL, AU - lower and upper bounds;
7789 : * AL=AU => equality constraint Ai*x
7790 : * AL<AU => two-sided constraint AL<=A*x<=AU
7791 : * AL=-INF => one-sided constraint Ai*x<=AU
7792 : * AU=+INF => one-sided constraint AL<=Ai*x
7793 : * AL=-INF, AU=+INF => constraint is ignored
7794 :
7795 : -- ALGLIB --
7796 : Copyright 19.07.2018 by Bochkanov Sergey
7797 : *************************************************************************/
7798 0 : void minlpaddlc2dense(const minlpstate &state, const real_1d_array &a, const double al, const double au, const xparams _xparams)
7799 : {
7800 : jmp_buf _break_jump;
7801 : alglib_impl::ae_state _alglib_env_state;
7802 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7803 0 : if( setjmp(_break_jump) )
7804 : {
7805 : #if !defined(AE_NO_EXCEPTIONS)
7806 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7807 : #else
7808 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7809 : return;
7810 : #endif
7811 : }
7812 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7813 0 : if( _xparams.flags!=0x0 )
7814 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7815 0 : alglib_impl::minlpaddlc2dense(const_cast<alglib_impl::minlpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(a.c_ptr()), al, au, &_alglib_env_state);
7816 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7817 0 : return;
7818 : }
7819 :
7820 : /*************************************************************************
7821 : This function appends two-sided linear constraint AL <= A*x <= AU to the
7822 : list of currently present constraints.
7823 :
7824 : Constraint is passed in compressed format: as list of non-zero entries of
7825 : coefficient vector A. Such approach is more efficient than dense storage
7826 : for highly sparse constraint vectors.
7827 :
7828 : INPUT PARAMETERS:
7829 : State - structure previously allocated with minlpcreate() call.
7830 : IdxA - array[NNZ], indexes of non-zero elements of A:
7831 : * can be unsorted
7832 : * can include duplicate indexes (corresponding entries of
7833 : ValA[] will be summed)
7834 : ValA - array[NNZ], values of non-zero elements of A
7835 : NNZ - number of non-zero coefficients in A
7836 : AL, AU - lower and upper bounds;
7837 : * AL=AU => equality constraint A*x
7838 : * AL<AU => two-sided constraint AL<=A*x<=AU
7839 : * AL=-INF => one-sided constraint A*x<=AU
7840 : * AU=+INF => one-sided constraint AL<=A*x
7841 : * AL=-INF, AU=+INF => constraint is ignored
7842 :
7843 : -- ALGLIB --
7844 : Copyright 19.07.2018 by Bochkanov Sergey
7845 : *************************************************************************/
7846 0 : void minlpaddlc2(const minlpstate &state, const integer_1d_array &idxa, const real_1d_array &vala, const ae_int_t nnz, const double al, const double au, const xparams _xparams)
7847 : {
7848 : jmp_buf _break_jump;
7849 : alglib_impl::ae_state _alglib_env_state;
7850 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7851 0 : if( setjmp(_break_jump) )
7852 : {
7853 : #if !defined(AE_NO_EXCEPTIONS)
7854 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7855 : #else
7856 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7857 : return;
7858 : #endif
7859 : }
7860 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7861 0 : if( _xparams.flags!=0x0 )
7862 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7863 0 : alglib_impl::minlpaddlc2(const_cast<alglib_impl::minlpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(idxa.c_ptr()), const_cast<alglib_impl::ae_vector*>(vala.c_ptr()), nnz, al, au, &_alglib_env_state);
7864 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7865 0 : return;
7866 : }
7867 :
7868 : /*************************************************************************
7869 : This function solves LP problem.
7870 :
7871 : INPUT PARAMETERS:
7872 : State - algorithm state
7873 :
7874 : You should use minlpresults() function to access results after calls to
7875 : this function.
7876 :
7877 : -- ALGLIB --
7878 : Copyright 19.07.2018 by Bochkanov Sergey.
7879 : *************************************************************************/
7880 0 : void minlpoptimize(const minlpstate &state, const xparams _xparams)
7881 : {
7882 : jmp_buf _break_jump;
7883 : alglib_impl::ae_state _alglib_env_state;
7884 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7885 0 : if( setjmp(_break_jump) )
7886 : {
7887 : #if !defined(AE_NO_EXCEPTIONS)
7888 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7889 : #else
7890 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7891 : return;
7892 : #endif
7893 : }
7894 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7895 0 : if( _xparams.flags!=0x0 )
7896 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7897 0 : alglib_impl::minlpoptimize(const_cast<alglib_impl::minlpstate*>(state.c_ptr()), &_alglib_env_state);
7898 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7899 0 : return;
7900 : }
7901 :
7902 : /*************************************************************************
7903 : LP solver results
7904 :
7905 : INPUT PARAMETERS:
7906 : State - algorithm state
7907 :
7908 : OUTPUT PARAMETERS:
7909 : X - array[N], solution (on failure: last trial point)
7910 : Rep - optimization report. You should check Rep.TerminationType,
7911 : which contains completion code, and you may check another
7912 : fields which contain another information about algorithm
7913 : functioning.
7914 :
7915 : Failure codes returned by algorithm are:
7916 : * -4 LP problem is primal unbounded (dual infeasible)
7917 : * -3 LP problem is primal infeasible (dual unbounded)
7918 : * -2 IPM solver detected that problem is either
7919 : infeasible or unbounded
7920 :
7921 : Success codes:
7922 : * 1..4 successful completion
7923 : * 5 MaxIts steps was taken
7924 :
7925 : -- ALGLIB --
7926 : Copyright 11.01.2011 by Bochkanov Sergey
7927 : *************************************************************************/
7928 0 : void minlpresults(const minlpstate &state, real_1d_array &x, minlpreport &rep, const xparams _xparams)
7929 : {
7930 : jmp_buf _break_jump;
7931 : alglib_impl::ae_state _alglib_env_state;
7932 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7933 0 : if( setjmp(_break_jump) )
7934 : {
7935 : #if !defined(AE_NO_EXCEPTIONS)
7936 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7937 : #else
7938 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7939 : return;
7940 : #endif
7941 : }
7942 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7943 0 : if( _xparams.flags!=0x0 )
7944 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7945 0 : alglib_impl::minlpresults(const_cast<alglib_impl::minlpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minlpreport*>(rep.c_ptr()), &_alglib_env_state);
7946 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7947 0 : return;
7948 : }
7949 :
7950 : /*************************************************************************
7951 : LP results
7952 :
7953 : Buffered implementation of MinLPResults() which uses pre-allocated buffer
7954 : to store X[]. If buffer size is too small, it resizes buffer. It is
7955 : intended to be used in the inner cycles of performance critical algorithms
7956 : where array reallocation penalty is too large to be ignored.
7957 :
7958 : -- ALGLIB --
7959 : Copyright 11.01.2011 by Bochkanov Sergey
7960 : *************************************************************************/
7961 0 : void minlpresultsbuf(const minlpstate &state, real_1d_array &x, minlpreport &rep, const xparams _xparams)
7962 : {
7963 : jmp_buf _break_jump;
7964 : alglib_impl::ae_state _alglib_env_state;
7965 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7966 0 : if( setjmp(_break_jump) )
7967 : {
7968 : #if !defined(AE_NO_EXCEPTIONS)
7969 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7970 : #else
7971 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7972 : return;
7973 : #endif
7974 : }
7975 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7976 0 : if( _xparams.flags!=0x0 )
7977 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7978 0 : alglib_impl::minlpresultsbuf(const_cast<alglib_impl::minlpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minlpreport*>(rep.c_ptr()), &_alglib_env_state);
7979 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7980 0 : return;
7981 : }
7982 : #endif
7983 :
7984 : #if defined(AE_COMPILE_NLCSLP) || !defined(AE_PARTIAL_BUILD)
7985 :
7986 : #endif
7987 :
7988 : #if defined(AE_COMPILE_MINNLC) || !defined(AE_PARTIAL_BUILD)
7989 : /*************************************************************************
7990 : This object stores nonlinear optimizer state.
7991 : You should use functions provided by MinNLC subpackage to work with this
7992 : object
7993 : *************************************************************************/
7994 0 : _minnlcstate_owner::_minnlcstate_owner()
7995 : {
7996 : jmp_buf _break_jump;
7997 : alglib_impl::ae_state _state;
7998 :
7999 0 : alglib_impl::ae_state_init(&_state);
8000 0 : if( setjmp(_break_jump) )
8001 : {
8002 0 : if( p_struct!=NULL )
8003 : {
8004 0 : alglib_impl::_minnlcstate_destroy(p_struct);
8005 0 : alglib_impl::ae_free(p_struct);
8006 : }
8007 0 : p_struct = NULL;
8008 : #if !defined(AE_NO_EXCEPTIONS)
8009 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
8010 : #else
8011 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
8012 : return;
8013 : #endif
8014 : }
8015 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
8016 0 : p_struct = NULL;
8017 0 : p_struct = (alglib_impl::minnlcstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minnlcstate), &_state);
8018 0 : memset(p_struct, 0, sizeof(alglib_impl::minnlcstate));
8019 0 : alglib_impl::_minnlcstate_init(p_struct, &_state, ae_false);
8020 0 : ae_state_clear(&_state);
8021 0 : }
8022 :
8023 0 : _minnlcstate_owner::_minnlcstate_owner(const _minnlcstate_owner &rhs)
8024 : {
8025 : jmp_buf _break_jump;
8026 : alglib_impl::ae_state _state;
8027 :
8028 0 : alglib_impl::ae_state_init(&_state);
8029 0 : if( setjmp(_break_jump) )
8030 : {
8031 0 : if( p_struct!=NULL )
8032 : {
8033 0 : alglib_impl::_minnlcstate_destroy(p_struct);
8034 0 : alglib_impl::ae_free(p_struct);
8035 : }
8036 0 : p_struct = NULL;
8037 : #if !defined(AE_NO_EXCEPTIONS)
8038 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
8039 : #else
8040 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
8041 : return;
8042 : #endif
8043 : }
8044 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
8045 0 : p_struct = NULL;
8046 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minnlcstate copy constructor failure (source is not initialized)", &_state);
8047 0 : p_struct = (alglib_impl::minnlcstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minnlcstate), &_state);
8048 0 : memset(p_struct, 0, sizeof(alglib_impl::minnlcstate));
8049 0 : alglib_impl::_minnlcstate_init_copy(p_struct, const_cast<alglib_impl::minnlcstate*>(rhs.p_struct), &_state, ae_false);
8050 0 : ae_state_clear(&_state);
8051 0 : }
8052 :
8053 0 : _minnlcstate_owner& _minnlcstate_owner::operator=(const _minnlcstate_owner &rhs)
8054 : {
8055 0 : if( this==&rhs )
8056 0 : return *this;
8057 : jmp_buf _break_jump;
8058 : alglib_impl::ae_state _state;
8059 :
8060 0 : alglib_impl::ae_state_init(&_state);
8061 0 : if( setjmp(_break_jump) )
8062 : {
8063 : #if !defined(AE_NO_EXCEPTIONS)
8064 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
8065 : #else
8066 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
8067 : return *this;
8068 : #endif
8069 : }
8070 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
8071 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minnlcstate assignment constructor failure (destination is not initialized)", &_state);
8072 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minnlcstate assignment constructor failure (source is not initialized)", &_state);
8073 0 : alglib_impl::_minnlcstate_destroy(p_struct);
8074 0 : memset(p_struct, 0, sizeof(alglib_impl::minnlcstate));
8075 0 : alglib_impl::_minnlcstate_init_copy(p_struct, const_cast<alglib_impl::minnlcstate*>(rhs.p_struct), &_state, ae_false);
8076 0 : ae_state_clear(&_state);
8077 0 : return *this;
8078 : }
8079 :
8080 0 : _minnlcstate_owner::~_minnlcstate_owner()
8081 : {
8082 0 : if( p_struct!=NULL )
8083 : {
8084 0 : alglib_impl::_minnlcstate_destroy(p_struct);
8085 0 : ae_free(p_struct);
8086 : }
8087 0 : }
8088 :
8089 0 : alglib_impl::minnlcstate* _minnlcstate_owner::c_ptr()
8090 : {
8091 0 : return p_struct;
8092 : }
8093 :
8094 0 : alglib_impl::minnlcstate* _minnlcstate_owner::c_ptr() const
8095 : {
8096 0 : return const_cast<alglib_impl::minnlcstate*>(p_struct);
8097 : }
8098 0 : minnlcstate::minnlcstate() : _minnlcstate_owner() ,needfi(p_struct->needfi),needfij(p_struct->needfij),xupdated(p_struct->xupdated),f(p_struct->f),fi(&p_struct->fi),j(&p_struct->j),x(&p_struct->x)
8099 : {
8100 0 : }
8101 :
8102 0 : minnlcstate::minnlcstate(const minnlcstate &rhs):_minnlcstate_owner(rhs) ,needfi(p_struct->needfi),needfij(p_struct->needfij),xupdated(p_struct->xupdated),f(p_struct->f),fi(&p_struct->fi),j(&p_struct->j),x(&p_struct->x)
8103 : {
8104 0 : }
8105 :
8106 0 : minnlcstate& minnlcstate::operator=(const minnlcstate &rhs)
8107 : {
8108 0 : if( this==&rhs )
8109 0 : return *this;
8110 0 : _minnlcstate_owner::operator=(rhs);
8111 0 : return *this;
8112 : }
8113 :
8114 0 : minnlcstate::~minnlcstate()
8115 : {
8116 0 : }
8117 :
8118 :
8119 : /*************************************************************************
8120 : These fields store optimization report:
8121 : * iterationscount total number of inner iterations
8122 : * nfev number of gradient evaluations
8123 : * terminationtype termination type (see below)
8124 :
8125 : Scaled constraint violations are reported:
8126 : * bcerr maximum violation of the box constraints
8127 : * bcidx index of the most violated box constraint (or
8128 : -1, if all box constraints are satisfied or
8129 : there is no box constraint)
8130 : * lcerr maximum violation of the linear constraints,
8131 : computed as maximum scaled distance between
8132 : final point and constraint boundary.
8133 : * lcidx index of the most violated linear constraint
8134 : (or -1, if all constraints are satisfied or
8135 : there is no general linear constraints)
8136 : * nlcerr maximum violation of the nonlinear constraints
8137 : * nlcidx index of the most violated nonlinear constraint
8138 : (or -1, if all constraints are satisfied or
8139 : there is no nonlinear constraints)
8140 :
8141 : Violations of box constraints are scaled on per-component basis according
8142 : to the scale vector s[] as specified by minnlcsetscale(). Violations of
8143 : the general linear constraints are also computed using user-supplied
8144 : variable scaling. Violations of nonlinear constraints are computed "as is"
8145 :
8146 : TERMINATION CODES
8147 :
8148 : TerminationType field contains completion code, which can be either:
8149 :
8150 : === FAILURE CODE ===
8151 : -8 internal integrity control detected infinite or NAN values in
8152 : function/gradient. Abnormal termination signaled.
8153 : -3 box constraints are infeasible. Note: infeasibility of non-box
8154 : constraints does NOT trigger emergency completion; you have to
8155 : examine bcerr/lcerr/nlcerr to detect possibly inconsistent
8156 : constraints.
8157 :
8158 : === SUCCESS CODE ===
8159 : 2 relative step is no more than EpsX.
8160 : 5 MaxIts steps was taken
8161 : 7 stopping conditions are too stringent,
8162 : further improvement is impossible,
8163 : X contains best point found so far.
8164 : 8 user requested algorithm termination via minnlcrequesttermination(),
8165 : last accepted point is returned
8166 :
8167 : Other fields of this structure are not documented and should not be used!
8168 : *************************************************************************/
8169 0 : _minnlcreport_owner::_minnlcreport_owner()
8170 : {
8171 : jmp_buf _break_jump;
8172 : alglib_impl::ae_state _state;
8173 :
8174 0 : alglib_impl::ae_state_init(&_state);
8175 0 : if( setjmp(_break_jump) )
8176 : {
8177 0 : if( p_struct!=NULL )
8178 : {
8179 0 : alglib_impl::_minnlcreport_destroy(p_struct);
8180 0 : alglib_impl::ae_free(p_struct);
8181 : }
8182 0 : p_struct = NULL;
8183 : #if !defined(AE_NO_EXCEPTIONS)
8184 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
8185 : #else
8186 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
8187 : return;
8188 : #endif
8189 : }
8190 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
8191 0 : p_struct = NULL;
8192 0 : p_struct = (alglib_impl::minnlcreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minnlcreport), &_state);
8193 0 : memset(p_struct, 0, sizeof(alglib_impl::minnlcreport));
8194 0 : alglib_impl::_minnlcreport_init(p_struct, &_state, ae_false);
8195 0 : ae_state_clear(&_state);
8196 0 : }
8197 :
8198 0 : _minnlcreport_owner::_minnlcreport_owner(const _minnlcreport_owner &rhs)
8199 : {
8200 : jmp_buf _break_jump;
8201 : alglib_impl::ae_state _state;
8202 :
8203 0 : alglib_impl::ae_state_init(&_state);
8204 0 : if( setjmp(_break_jump) )
8205 : {
8206 0 : if( p_struct!=NULL )
8207 : {
8208 0 : alglib_impl::_minnlcreport_destroy(p_struct);
8209 0 : alglib_impl::ae_free(p_struct);
8210 : }
8211 0 : p_struct = NULL;
8212 : #if !defined(AE_NO_EXCEPTIONS)
8213 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
8214 : #else
8215 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
8216 : return;
8217 : #endif
8218 : }
8219 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
8220 0 : p_struct = NULL;
8221 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minnlcreport copy constructor failure (source is not initialized)", &_state);
8222 0 : p_struct = (alglib_impl::minnlcreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minnlcreport), &_state);
8223 0 : memset(p_struct, 0, sizeof(alglib_impl::minnlcreport));
8224 0 : alglib_impl::_minnlcreport_init_copy(p_struct, const_cast<alglib_impl::minnlcreport*>(rhs.p_struct), &_state, ae_false);
8225 0 : ae_state_clear(&_state);
8226 0 : }
8227 :
8228 0 : _minnlcreport_owner& _minnlcreport_owner::operator=(const _minnlcreport_owner &rhs)
8229 : {
8230 0 : if( this==&rhs )
8231 0 : return *this;
8232 : jmp_buf _break_jump;
8233 : alglib_impl::ae_state _state;
8234 :
8235 0 : alglib_impl::ae_state_init(&_state);
8236 0 : if( setjmp(_break_jump) )
8237 : {
8238 : #if !defined(AE_NO_EXCEPTIONS)
8239 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
8240 : #else
8241 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
8242 : return *this;
8243 : #endif
8244 : }
8245 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
8246 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minnlcreport assignment constructor failure (destination is not initialized)", &_state);
8247 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minnlcreport assignment constructor failure (source is not initialized)", &_state);
8248 0 : alglib_impl::_minnlcreport_destroy(p_struct);
8249 0 : memset(p_struct, 0, sizeof(alglib_impl::minnlcreport));
8250 0 : alglib_impl::_minnlcreport_init_copy(p_struct, const_cast<alglib_impl::minnlcreport*>(rhs.p_struct), &_state, ae_false);
8251 0 : ae_state_clear(&_state);
8252 0 : return *this;
8253 : }
8254 :
8255 0 : _minnlcreport_owner::~_minnlcreport_owner()
8256 : {
8257 0 : if( p_struct!=NULL )
8258 : {
8259 0 : alglib_impl::_minnlcreport_destroy(p_struct);
8260 0 : ae_free(p_struct);
8261 : }
8262 0 : }
8263 :
8264 0 : alglib_impl::minnlcreport* _minnlcreport_owner::c_ptr()
8265 : {
8266 0 : return p_struct;
8267 : }
8268 :
8269 0 : alglib_impl::minnlcreport* _minnlcreport_owner::c_ptr() const
8270 : {
8271 0 : return const_cast<alglib_impl::minnlcreport*>(p_struct);
8272 : }
8273 0 : minnlcreport::minnlcreport() : _minnlcreport_owner() ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),terminationtype(p_struct->terminationtype),bcerr(p_struct->bcerr),bcidx(p_struct->bcidx),lcerr(p_struct->lcerr),lcidx(p_struct->lcidx),nlcerr(p_struct->nlcerr),nlcidx(p_struct->nlcidx),dbgphase0its(p_struct->dbgphase0its)
8274 : {
8275 0 : }
8276 :
8277 0 : minnlcreport::minnlcreport(const minnlcreport &rhs):_minnlcreport_owner(rhs) ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),terminationtype(p_struct->terminationtype),bcerr(p_struct->bcerr),bcidx(p_struct->bcidx),lcerr(p_struct->lcerr),lcidx(p_struct->lcidx),nlcerr(p_struct->nlcerr),nlcidx(p_struct->nlcidx),dbgphase0its(p_struct->dbgphase0its)
8278 : {
8279 0 : }
8280 :
8281 0 : minnlcreport& minnlcreport::operator=(const minnlcreport &rhs)
8282 : {
8283 0 : if( this==&rhs )
8284 0 : return *this;
8285 0 : _minnlcreport_owner::operator=(rhs);
8286 0 : return *this;
8287 : }
8288 :
8289 0 : minnlcreport::~minnlcreport()
8290 : {
8291 0 : }
8292 :
8293 : /*************************************************************************
8294 : NONLINEARLY CONSTRAINED OPTIMIZATION
8295 : WITH PRECONDITIONED AUGMENTED LAGRANGIAN ALGORITHM
8296 :
8297 : DESCRIPTION:
8298 : The subroutine minimizes function F(x) of N arguments subject to any
8299 : combination of:
8300 : * bound constraints
8301 : * linear inequality constraints
8302 : * linear equality constraints
8303 : * nonlinear equality constraints Gi(x)=0
8304 : * nonlinear inequality constraints Hi(x)<=0
8305 :
8306 : REQUIREMENTS:
8307 : * user must provide function value and gradient for F(), H(), G()
8308 : * starting point X0 must be feasible or not too far away from the feasible
8309 : set
8310 : * F(), G(), H() are continuously differentiable on the feasible set and
8311 : its neighborhood
8312 : * nonlinear constraints G() and H() must have non-zero gradient at G(x)=0
8313 : and at H(x)=0. Say, constraint like x^2>=1 is supported, but x^2>=0 is
8314 : NOT supported.
8315 :
8316 : USAGE:
8317 :
8318 : Constrained optimization if far more complex than the unconstrained one.
8319 : Nonlinearly constrained optimization is one of the most esoteric numerical
8320 : procedures.
8321 :
8322 : Here we give very brief outline of the MinNLC optimizer. We strongly
8323 : recommend you to study examples in the ALGLIB Reference Manual and to read
8324 : ALGLIB User Guide on optimization, which is available at
8325 : http://www.alglib.net/optimization/
8326 :
8327 : 1. User initializes algorithm state with MinNLCCreate() call and chooses
8328 : what NLC solver to use. There is some solver which is used by default,
8329 : with default settings, but you should NOT rely on default choice. It
8330 : may change in future releases of ALGLIB without notice, and no one can
8331 : guarantee that new solver will be able to solve your problem with
8332 : default settings.
8333 :
8334 : From the other side, if you choose solver explicitly, you can be pretty
8335 : sure that it will work with new ALGLIB releases.
8336 :
8337 : In the current release following solvers can be used:
8338 : * SQP solver, recommended for medium-scale problems (less than thousand
8339 : of variables) with hard-to-evaluate target functions. Requires less
8340 : function evaluations than other solvers but each step involves
8341 : solution of QP subproblem, so running time may be higher than that of
8342 : AUL (another recommended option). Activated with minnlcsetalgosqp()
8343 : function.
8344 : * AUL solver with dense preconditioner, recommended for large-scale
8345 : problems or for problems with cheap target function. Needs more
8346 : function evaluations that SQP (about 5x-10x times more), but its
8347 : iterations are much cheaper that that of SQP. Activated with
8348 : minnlcsetalgoaul() function.
8349 : * SLP solver, successive linear programming. The slowest one, requires
8350 : more target function evaluations that SQP and AUL. However, it is
8351 : somewhat more robust in tricky cases, so it can be used as a backup
8352 : plan. Activated with minnlcsetalgoslp() function.
8353 :
8354 : 2. [optional] user activates OptGuard integrity checker which tries to
8355 : detect possible errors in the user-supplied callbacks:
8356 : * discontinuity/nonsmoothness of the target/nonlinear constraints
8357 : * errors in the analytic gradient provided by user
8358 : This feature is essential for early prototyping stages because it helps
8359 : to catch common coding and problem statement errors.
8360 : OptGuard can be activated with following functions (one per each check
8361 : performed):
8362 : * minnlcoptguardsmoothness()
8363 : * minnlcoptguardgradient()
8364 :
8365 : 3. User adds boundary and/or linear and/or nonlinear constraints by means
8366 : of calling one of the following functions:
8367 : a) minnlcsetbc() for boundary constraints
8368 : b) minnlcsetlc() for linear constraints
8369 : c) minnlcsetnlc() for nonlinear constraints
8370 : You may combine (a), (b) and (c) in one optimization problem.
8371 :
8372 : 4. User sets scale of the variables with minnlcsetscale() function. It is
8373 : VERY important to set scale of the variables, because nonlinearly
8374 : constrained problems are hard to solve when variables are badly scaled.
8375 :
8376 : 5. User sets stopping conditions with minnlcsetcond(). If NLC solver
8377 : uses inner/outer iteration layout, this function sets stopping
8378 : conditions for INNER iterations.
8379 :
8380 : 6. Finally, user calls minnlcoptimize() function which takes algorithm
8381 : state and pointer (delegate, etc.) to callback function which calculates
8382 : F/G/H.
8383 :
8384 : 7. User calls minnlcresults() to get solution; additionally you can
8385 : retrieve OptGuard report with minnlcoptguardresults(), and get detailed
8386 : report about purported errors in the target function with:
8387 : * minnlcoptguardnonc1test0results()
8388 : * minnlcoptguardnonc1test1results()
8389 :
8390 : 8. Optionally user may call minnlcrestartfrom() to solve another problem
8391 : with same N but another starting point. minnlcrestartfrom() allows to
8392 : reuse already initialized structure.
8393 :
8394 :
8395 : INPUT PARAMETERS:
8396 : N - problem dimension, N>0:
8397 : * if given, only leading N elements of X are used
8398 : * if not given, automatically determined from size ofX
8399 : X - starting point, array[N]:
8400 : * it is better to set X to a feasible point
8401 : * but X can be infeasible, in which case algorithm will try
8402 : to find feasible point first, using X as initial
8403 : approximation.
8404 :
8405 : OUTPUT PARAMETERS:
8406 : State - structure stores algorithm state
8407 :
8408 : -- ALGLIB --
8409 : Copyright 06.06.2014 by Bochkanov Sergey
8410 : *************************************************************************/
8411 0 : void minnlccreate(const ae_int_t n, const real_1d_array &x, minnlcstate &state, const xparams _xparams)
8412 : {
8413 : jmp_buf _break_jump;
8414 : alglib_impl::ae_state _alglib_env_state;
8415 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8416 0 : if( setjmp(_break_jump) )
8417 : {
8418 : #if !defined(AE_NO_EXCEPTIONS)
8419 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8420 : #else
8421 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8422 : return;
8423 : #endif
8424 : }
8425 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8426 0 : if( _xparams.flags!=0x0 )
8427 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8428 0 : alglib_impl::minnlccreate(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), &_alglib_env_state);
8429 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8430 0 : return;
8431 : }
8432 :
8433 : /*************************************************************************
8434 : NONLINEARLY CONSTRAINED OPTIMIZATION
8435 : WITH PRECONDITIONED AUGMENTED LAGRANGIAN ALGORITHM
8436 :
8437 : DESCRIPTION:
8438 : The subroutine minimizes function F(x) of N arguments subject to any
8439 : combination of:
8440 : * bound constraints
8441 : * linear inequality constraints
8442 : * linear equality constraints
8443 : * nonlinear equality constraints Gi(x)=0
8444 : * nonlinear inequality constraints Hi(x)<=0
8445 :
8446 : REQUIREMENTS:
8447 : * user must provide function value and gradient for F(), H(), G()
8448 : * starting point X0 must be feasible or not too far away from the feasible
8449 : set
8450 : * F(), G(), H() are continuously differentiable on the feasible set and
8451 : its neighborhood
8452 : * nonlinear constraints G() and H() must have non-zero gradient at G(x)=0
8453 : and at H(x)=0. Say, constraint like x^2>=1 is supported, but x^2>=0 is
8454 : NOT supported.
8455 :
8456 : USAGE:
8457 :
8458 : Constrained optimization if far more complex than the unconstrained one.
8459 : Nonlinearly constrained optimization is one of the most esoteric numerical
8460 : procedures.
8461 :
8462 : Here we give very brief outline of the MinNLC optimizer. We strongly
8463 : recommend you to study examples in the ALGLIB Reference Manual and to read
8464 : ALGLIB User Guide on optimization, which is available at
8465 : http://www.alglib.net/optimization/
8466 :
8467 : 1. User initializes algorithm state with MinNLCCreate() call and chooses
8468 : what NLC solver to use. There is some solver which is used by default,
8469 : with default settings, but you should NOT rely on default choice. It
8470 : may change in future releases of ALGLIB without notice, and no one can
8471 : guarantee that new solver will be able to solve your problem with
8472 : default settings.
8473 :
8474 : From the other side, if you choose solver explicitly, you can be pretty
8475 : sure that it will work with new ALGLIB releases.
8476 :
8477 : In the current release following solvers can be used:
8478 : * SQP solver, recommended for medium-scale problems (less than thousand
8479 : of variables) with hard-to-evaluate target functions. Requires less
8480 : function evaluations than other solvers but each step involves
8481 : solution of QP subproblem, so running time may be higher than that of
8482 : AUL (another recommended option). Activated with minnlcsetalgosqp()
8483 : function.
8484 : * AUL solver with dense preconditioner, recommended for large-scale
8485 : problems or for problems with cheap target function. Needs more
8486 : function evaluations that SQP (about 5x-10x times more), but its
8487 : iterations are much cheaper that that of SQP. Activated with
8488 : minnlcsetalgoaul() function.
8489 : * SLP solver, successive linear programming. The slowest one, requires
8490 : more target function evaluations that SQP and AUL. However, it is
8491 : somewhat more robust in tricky cases, so it can be used as a backup
8492 : plan. Activated with minnlcsetalgoslp() function.
8493 :
8494 : 2. [optional] user activates OptGuard integrity checker which tries to
8495 : detect possible errors in the user-supplied callbacks:
8496 : * discontinuity/nonsmoothness of the target/nonlinear constraints
8497 : * errors in the analytic gradient provided by user
8498 : This feature is essential for early prototyping stages because it helps
8499 : to catch common coding and problem statement errors.
8500 : OptGuard can be activated with following functions (one per each check
8501 : performed):
8502 : * minnlcoptguardsmoothness()
8503 : * minnlcoptguardgradient()
8504 :
8505 : 3. User adds boundary and/or linear and/or nonlinear constraints by means
8506 : of calling one of the following functions:
8507 : a) minnlcsetbc() for boundary constraints
8508 : b) minnlcsetlc() for linear constraints
8509 : c) minnlcsetnlc() for nonlinear constraints
8510 : You may combine (a), (b) and (c) in one optimization problem.
8511 :
8512 : 4. User sets scale of the variables with minnlcsetscale() function. It is
8513 : VERY important to set scale of the variables, because nonlinearly
8514 : constrained problems are hard to solve when variables are badly scaled.
8515 :
8516 : 5. User sets stopping conditions with minnlcsetcond(). If NLC solver
8517 : uses inner/outer iteration layout, this function sets stopping
8518 : conditions for INNER iterations.
8519 :
8520 : 6. Finally, user calls minnlcoptimize() function which takes algorithm
8521 : state and pointer (delegate, etc.) to callback function which calculates
8522 : F/G/H.
8523 :
8524 : 7. User calls minnlcresults() to get solution; additionally you can
8525 : retrieve OptGuard report with minnlcoptguardresults(), and get detailed
8526 : report about purported errors in the target function with:
8527 : * minnlcoptguardnonc1test0results()
8528 : * minnlcoptguardnonc1test1results()
8529 :
8530 : 8. Optionally user may call minnlcrestartfrom() to solve another problem
8531 : with same N but another starting point. minnlcrestartfrom() allows to
8532 : reuse already initialized structure.
8533 :
8534 :
8535 : INPUT PARAMETERS:
8536 : N - problem dimension, N>0:
8537 : * if given, only leading N elements of X are used
8538 : * if not given, automatically determined from size ofX
8539 : X - starting point, array[N]:
8540 : * it is better to set X to a feasible point
8541 : * but X can be infeasible, in which case algorithm will try
8542 : to find feasible point first, using X as initial
8543 : approximation.
8544 :
8545 : OUTPUT PARAMETERS:
8546 : State - structure stores algorithm state
8547 :
8548 : -- ALGLIB --
8549 : Copyright 06.06.2014 by Bochkanov Sergey
8550 : *************************************************************************/
8551 : #if !defined(AE_NO_EXCEPTIONS)
8552 0 : void minnlccreate(const real_1d_array &x, minnlcstate &state, const xparams _xparams)
8553 : {
8554 : jmp_buf _break_jump;
8555 : alglib_impl::ae_state _alglib_env_state;
8556 : ae_int_t n;
8557 :
8558 0 : n = x.length();
8559 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8560 0 : if( setjmp(_break_jump) )
8561 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8562 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8563 0 : if( _xparams.flags!=0x0 )
8564 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8565 0 : alglib_impl::minnlccreate(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), &_alglib_env_state);
8566 :
8567 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8568 0 : return;
8569 : }
8570 : #endif
8571 :
8572 : /*************************************************************************
8573 : This subroutine is a finite difference variant of MinNLCCreate(). It uses
8574 : finite differences in order to differentiate target function.
8575 :
8576 : Description below contains information which is specific to this function
8577 : only. We recommend to read comments on MinNLCCreate() in order to get more
8578 : information about creation of NLC optimizer.
8579 :
8580 : INPUT PARAMETERS:
8581 : N - problem dimension, N>0:
8582 : * if given, only leading N elements of X are used
8583 : * if not given, automatically determined from size ofX
8584 : X - starting point, array[N]:
8585 : * it is better to set X to a feasible point
8586 : * but X can be infeasible, in which case algorithm will try
8587 : to find feasible point first, using X as initial
8588 : approximation.
8589 : DiffStep- differentiation step, >0
8590 :
8591 : OUTPUT PARAMETERS:
8592 : State - structure stores algorithm state
8593 :
8594 : NOTES:
8595 : 1. algorithm uses 4-point central formula for differentiation.
8596 : 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
8597 : S[] is scaling vector which can be set by MinNLCSetScale() call.
8598 : 3. we recommend you to use moderate values of differentiation step. Too
8599 : large step will result in too large TRUNCATION errors, while too small
8600 : step will result in too large NUMERICAL errors. 1.0E-4 can be good
8601 : value to start from.
8602 : 4. Numerical differentiation is very inefficient - one gradient
8603 : calculation needs 4*N function evaluations. This function will work for
8604 : any N - either small (1...10), moderate (10...100) or large (100...).
8605 : However, performance penalty will be too severe for any N's except for
8606 : small ones.
8607 : We should also say that code which relies on numerical differentiation
8608 : is less robust and precise. Imprecise gradient may slow down
8609 : convergence, especially on highly nonlinear problems.
8610 : Thus we recommend to use this function for fast prototyping on small-
8611 : dimensional problems only, and to implement analytical gradient as soon
8612 : as possible.
8613 :
8614 : -- ALGLIB --
8615 : Copyright 06.06.2014 by Bochkanov Sergey
8616 : *************************************************************************/
8617 0 : void minnlccreatef(const ae_int_t n, const real_1d_array &x, const double diffstep, minnlcstate &state, const xparams _xparams)
8618 : {
8619 : jmp_buf _break_jump;
8620 : alglib_impl::ae_state _alglib_env_state;
8621 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8622 0 : if( setjmp(_break_jump) )
8623 : {
8624 : #if !defined(AE_NO_EXCEPTIONS)
8625 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8626 : #else
8627 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8628 : return;
8629 : #endif
8630 : }
8631 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8632 0 : if( _xparams.flags!=0x0 )
8633 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8634 0 : alglib_impl::minnlccreatef(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), diffstep, const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), &_alglib_env_state);
8635 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8636 0 : return;
8637 : }
8638 :
8639 : /*************************************************************************
8640 : This subroutine is a finite difference variant of MinNLCCreate(). It uses
8641 : finite differences in order to differentiate target function.
8642 :
8643 : Description below contains information which is specific to this function
8644 : only. We recommend to read comments on MinNLCCreate() in order to get more
8645 : information about creation of NLC optimizer.
8646 :
8647 : INPUT PARAMETERS:
8648 : N - problem dimension, N>0:
8649 : * if given, only leading N elements of X are used
8650 : * if not given, automatically determined from size ofX
8651 : X - starting point, array[N]:
8652 : * it is better to set X to a feasible point
8653 : * but X can be infeasible, in which case algorithm will try
8654 : to find feasible point first, using X as initial
8655 : approximation.
8656 : DiffStep- differentiation step, >0
8657 :
8658 : OUTPUT PARAMETERS:
8659 : State - structure stores algorithm state
8660 :
8661 : NOTES:
8662 : 1. algorithm uses 4-point central formula for differentiation.
8663 : 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
8664 : S[] is scaling vector which can be set by MinNLCSetScale() call.
8665 : 3. we recommend you to use moderate values of differentiation step. Too
8666 : large step will result in too large TRUNCATION errors, while too small
8667 : step will result in too large NUMERICAL errors. 1.0E-4 can be good
8668 : value to start from.
8669 : 4. Numerical differentiation is very inefficient - one gradient
8670 : calculation needs 4*N function evaluations. This function will work for
8671 : any N - either small (1...10), moderate (10...100) or large (100...).
8672 : However, performance penalty will be too severe for any N's except for
8673 : small ones.
8674 : We should also say that code which relies on numerical differentiation
8675 : is less robust and precise. Imprecise gradient may slow down
8676 : convergence, especially on highly nonlinear problems.
8677 : Thus we recommend to use this function for fast prototyping on small-
8678 : dimensional problems only, and to implement analytical gradient as soon
8679 : as possible.
8680 :
8681 : -- ALGLIB --
8682 : Copyright 06.06.2014 by Bochkanov Sergey
8683 : *************************************************************************/
8684 : #if !defined(AE_NO_EXCEPTIONS)
8685 0 : void minnlccreatef(const real_1d_array &x, const double diffstep, minnlcstate &state, const xparams _xparams)
8686 : {
8687 : jmp_buf _break_jump;
8688 : alglib_impl::ae_state _alglib_env_state;
8689 : ae_int_t n;
8690 :
8691 0 : n = x.length();
8692 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8693 0 : if( setjmp(_break_jump) )
8694 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8695 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8696 0 : if( _xparams.flags!=0x0 )
8697 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8698 0 : alglib_impl::minnlccreatef(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), diffstep, const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), &_alglib_env_state);
8699 :
8700 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8701 0 : return;
8702 : }
8703 : #endif
8704 :
8705 : /*************************************************************************
8706 : This function sets boundary constraints for NLC optimizer.
8707 :
8708 : Boundary constraints are inactive by default (after initial creation).
8709 : They are preserved after algorithm restart with MinNLCRestartFrom().
8710 :
8711 : You may combine boundary constraints with general linear ones - and with
8712 : nonlinear ones! Boundary constraints are handled more efficiently than
8713 : other types. Thus, if your problem has mixed constraints, you may
8714 : explicitly specify some of them as boundary and save some time/space.
8715 :
8716 : INPUT PARAMETERS:
8717 : State - structure stores algorithm state
8718 : BndL - lower bounds, array[N].
8719 : If some (all) variables are unbounded, you may specify
8720 : very small number or -INF.
8721 : BndU - upper bounds, array[N].
8722 : If some (all) variables are unbounded, you may specify
8723 : very large number or +INF.
8724 :
8725 : NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th
8726 : variable will be "frozen" at X[i]=BndL[i]=BndU[i].
8727 :
8728 : NOTE 2: when you solve your problem with augmented Lagrangian solver,
8729 : boundary constraints are satisfied only approximately! It is
8730 : possible that algorithm will evaluate function outside of
8731 : feasible area!
8732 :
8733 : -- ALGLIB --
8734 : Copyright 06.06.2014 by Bochkanov Sergey
8735 : *************************************************************************/
8736 0 : void minnlcsetbc(const minnlcstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams)
8737 : {
8738 : jmp_buf _break_jump;
8739 : alglib_impl::ae_state _alglib_env_state;
8740 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8741 0 : if( setjmp(_break_jump) )
8742 : {
8743 : #if !defined(AE_NO_EXCEPTIONS)
8744 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8745 : #else
8746 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8747 : return;
8748 : #endif
8749 : }
8750 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8751 0 : if( _xparams.flags!=0x0 )
8752 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8753 0 : alglib_impl::minnlcsetbc(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(bndl.c_ptr()), const_cast<alglib_impl::ae_vector*>(bndu.c_ptr()), &_alglib_env_state);
8754 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8755 0 : return;
8756 : }
8757 :
8758 : /*************************************************************************
8759 : This function sets linear constraints for MinNLC optimizer.
8760 :
8761 : Linear constraints are inactive by default (after initial creation). They
8762 : are preserved after algorithm restart with MinNLCRestartFrom().
8763 :
8764 : You may combine linear constraints with boundary ones - and with nonlinear
8765 : ones! If your problem has mixed constraints, you may explicitly specify
8766 : some of them as linear. It may help optimizer to handle them more
8767 : efficiently.
8768 :
8769 : INPUT PARAMETERS:
8770 : State - structure previously allocated with MinNLCCreate call.
8771 : C - linear constraints, array[K,N+1].
8772 : Each row of C represents one constraint, either equality
8773 : or inequality (see below):
8774 : * first N elements correspond to coefficients,
8775 : * last element corresponds to the right part.
8776 : All elements of C (including right part) must be finite.
8777 : CT - type of constraints, array[K]:
8778 : * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
8779 : * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
8780 : * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
8781 : K - number of equality/inequality constraints, K>=0:
8782 : * if given, only leading K elements of C/CT are used
8783 : * if not given, automatically determined from sizes of C/CT
8784 :
8785 : NOTE 1: when you solve your problem with augmented Lagrangian solver,
8786 : linear constraints are satisfied only approximately! It is
8787 : possible that algorithm will evaluate function outside of
8788 : feasible area!
8789 :
8790 : -- ALGLIB --
8791 : Copyright 06.06.2014 by Bochkanov Sergey
8792 : *************************************************************************/
8793 0 : void minnlcsetlc(const minnlcstate &state, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams)
8794 : {
8795 : jmp_buf _break_jump;
8796 : alglib_impl::ae_state _alglib_env_state;
8797 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8798 0 : if( setjmp(_break_jump) )
8799 : {
8800 : #if !defined(AE_NO_EXCEPTIONS)
8801 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8802 : #else
8803 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8804 : return;
8805 : #endif
8806 : }
8807 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8808 0 : if( _xparams.flags!=0x0 )
8809 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8810 0 : alglib_impl::minnlcsetlc(const_cast<alglib_impl::minnlcstate*>(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);
8811 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8812 0 : return;
8813 : }
8814 :
8815 : /*************************************************************************
8816 : This function sets linear constraints for MinNLC optimizer.
8817 :
8818 : Linear constraints are inactive by default (after initial creation). They
8819 : are preserved after algorithm restart with MinNLCRestartFrom().
8820 :
8821 : You may combine linear constraints with boundary ones - and with nonlinear
8822 : ones! If your problem has mixed constraints, you may explicitly specify
8823 : some of them as linear. It may help optimizer to handle them more
8824 : efficiently.
8825 :
8826 : INPUT PARAMETERS:
8827 : State - structure previously allocated with MinNLCCreate call.
8828 : C - linear constraints, array[K,N+1].
8829 : Each row of C represents one constraint, either equality
8830 : or inequality (see below):
8831 : * first N elements correspond to coefficients,
8832 : * last element corresponds to the right part.
8833 : All elements of C (including right part) must be finite.
8834 : CT - type of constraints, array[K]:
8835 : * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
8836 : * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
8837 : * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
8838 : K - number of equality/inequality constraints, K>=0:
8839 : * if given, only leading K elements of C/CT are used
8840 : * if not given, automatically determined from sizes of C/CT
8841 :
8842 : NOTE 1: when you solve your problem with augmented Lagrangian solver,
8843 : linear constraints are satisfied only approximately! It is
8844 : possible that algorithm will evaluate function outside of
8845 : feasible area!
8846 :
8847 : -- ALGLIB --
8848 : Copyright 06.06.2014 by Bochkanov Sergey
8849 : *************************************************************************/
8850 : #if !defined(AE_NO_EXCEPTIONS)
8851 0 : void minnlcsetlc(const minnlcstate &state, const real_2d_array &c, const integer_1d_array &ct, const xparams _xparams)
8852 : {
8853 : jmp_buf _break_jump;
8854 : alglib_impl::ae_state _alglib_env_state;
8855 : ae_int_t k;
8856 0 : if( (c.rows()!=ct.length()))
8857 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'minnlcsetlc': looks like one of arguments has wrong size");
8858 0 : k = c.rows();
8859 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8860 0 : if( setjmp(_break_jump) )
8861 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8862 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8863 0 : if( _xparams.flags!=0x0 )
8864 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8865 0 : alglib_impl::minnlcsetlc(const_cast<alglib_impl::minnlcstate*>(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);
8866 :
8867 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8868 0 : return;
8869 : }
8870 : #endif
8871 :
8872 : /*************************************************************************
8873 : This function sets nonlinear constraints for MinNLC optimizer.
8874 :
8875 : In fact, this function sets NUMBER of nonlinear constraints. Constraints
8876 : itself (constraint functions) are passed to MinNLCOptimize() method. This
8877 : method requires user-defined vector function F[] and its Jacobian J[],
8878 : where:
8879 : * first component of F[] and first row of Jacobian J[] corresponds to
8880 : function being minimized
8881 : * next NLEC components of F[] (and rows of J) correspond to nonlinear
8882 : equality constraints G_i(x)=0
8883 : * next NLIC components of F[] (and rows of J) correspond to nonlinear
8884 : inequality constraints H_i(x)<=0
8885 :
8886 : NOTE: you may combine nonlinear constraints with linear/boundary ones. If
8887 : your problem has mixed constraints, you may explicitly specify some
8888 : of them as linear ones. It may help optimizer to handle them more
8889 : efficiently.
8890 :
8891 : INPUT PARAMETERS:
8892 : State - structure previously allocated with MinNLCCreate call.
8893 : NLEC - number of Non-Linear Equality Constraints (NLEC), >=0
8894 : NLIC - number of Non-Linear Inquality Constraints (NLIC), >=0
8895 :
8896 : NOTE 1: when you solve your problem with augmented Lagrangian solver,
8897 : nonlinear constraints are satisfied only approximately! It is
8898 : possible that algorithm will evaluate function outside of
8899 : feasible area!
8900 :
8901 : NOTE 2: algorithm scales variables according to scale specified by
8902 : MinNLCSetScale() function, so it can handle problems with badly
8903 : scaled variables (as long as we KNOW their scales).
8904 :
8905 : However, there is no way to automatically scale nonlinear
8906 : constraints Gi(x) and Hi(x). Inappropriate scaling of Gi/Hi may
8907 : ruin convergence. Solving problem with constraint "1000*G0(x)=0"
8908 : is NOT same as solving it with constraint "0.001*G0(x)=0".
8909 :
8910 : It means that YOU are the one who is responsible for correct
8911 : scaling of nonlinear constraints Gi(x) and Hi(x). We recommend you
8912 : to scale nonlinear constraints in such way that I-th component of
8913 : dG/dX (or dH/dx) has approximately unit magnitude (for problems
8914 : with unit scale) or has magnitude approximately equal to 1/S[i]
8915 : (where S is a scale set by MinNLCSetScale() function).
8916 :
8917 :
8918 : -- ALGLIB --
8919 : Copyright 06.06.2014 by Bochkanov Sergey
8920 : *************************************************************************/
8921 0 : void minnlcsetnlc(const minnlcstate &state, const ae_int_t nlec, const ae_int_t nlic, const xparams _xparams)
8922 : {
8923 : jmp_buf _break_jump;
8924 : alglib_impl::ae_state _alglib_env_state;
8925 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8926 0 : if( setjmp(_break_jump) )
8927 : {
8928 : #if !defined(AE_NO_EXCEPTIONS)
8929 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8930 : #else
8931 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8932 : return;
8933 : #endif
8934 : }
8935 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8936 0 : if( _xparams.flags!=0x0 )
8937 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8938 0 : alglib_impl::minnlcsetnlc(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), nlec, nlic, &_alglib_env_state);
8939 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8940 0 : return;
8941 : }
8942 :
8943 : /*************************************************************************
8944 : This function sets stopping conditions for inner iterations of optimizer.
8945 :
8946 : INPUT PARAMETERS:
8947 : State - structure which stores algorithm state
8948 : EpsX - >=0
8949 : The subroutine finishes its work if on k+1-th iteration
8950 : the condition |v|<=EpsX is fulfilled, where:
8951 : * |.| means Euclidian norm
8952 : * v - scaled step vector, v[i]=dx[i]/s[i]
8953 : * dx - step vector, dx=X(k+1)-X(k)
8954 : * s - scaling coefficients set by MinNLCSetScale()
8955 : MaxIts - maximum number of iterations. If MaxIts=0, the number of
8956 : iterations is unlimited.
8957 :
8958 : Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic
8959 : selection of the stopping condition.
8960 :
8961 : -- ALGLIB --
8962 : Copyright 06.06.2014 by Bochkanov Sergey
8963 : *************************************************************************/
8964 0 : void minnlcsetcond(const minnlcstate &state, const double epsx, const ae_int_t maxits, const xparams _xparams)
8965 : {
8966 : jmp_buf _break_jump;
8967 : alglib_impl::ae_state _alglib_env_state;
8968 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8969 0 : if( setjmp(_break_jump) )
8970 : {
8971 : #if !defined(AE_NO_EXCEPTIONS)
8972 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8973 : #else
8974 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8975 : return;
8976 : #endif
8977 : }
8978 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8979 0 : if( _xparams.flags!=0x0 )
8980 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8981 0 : alglib_impl::minnlcsetcond(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), epsx, maxits, &_alglib_env_state);
8982 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8983 0 : return;
8984 : }
8985 :
8986 : /*************************************************************************
8987 : This function sets scaling coefficients for NLC optimizer.
8988 :
8989 : ALGLIB optimizers use scaling matrices to test stopping conditions (step
8990 : size and gradient are scaled before comparison with tolerances). Scale of
8991 : the I-th variable is a translation invariant measure of:
8992 : a) "how large" the variable is
8993 : b) how large the step should be to make significant changes in the function
8994 :
8995 : Scaling is also used by finite difference variant of the optimizer - step
8996 : along I-th axis is equal to DiffStep*S[I].
8997 :
8998 : INPUT PARAMETERS:
8999 : State - structure stores algorithm state
9000 : S - array[N], non-zero scaling coefficients
9001 : S[i] may be negative, sign doesn't matter.
9002 :
9003 : -- ALGLIB --
9004 : Copyright 06.06.2014 by Bochkanov Sergey
9005 : *************************************************************************/
9006 0 : void minnlcsetscale(const minnlcstate &state, const real_1d_array &s, const xparams _xparams)
9007 : {
9008 : jmp_buf _break_jump;
9009 : alglib_impl::ae_state _alglib_env_state;
9010 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9011 0 : if( setjmp(_break_jump) )
9012 : {
9013 : #if !defined(AE_NO_EXCEPTIONS)
9014 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9015 : #else
9016 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9017 : return;
9018 : #endif
9019 : }
9020 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9021 0 : if( _xparams.flags!=0x0 )
9022 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9023 0 : alglib_impl::minnlcsetscale(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(s.c_ptr()), &_alglib_env_state);
9024 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9025 0 : return;
9026 : }
9027 :
9028 : /*************************************************************************
9029 : This function sets preconditioner to "inexact LBFGS-based" mode.
9030 :
9031 : Preconditioning is very important for convergence of Augmented Lagrangian
9032 : algorithm because presence of penalty term makes problem ill-conditioned.
9033 : Difference between performance of preconditioned and unpreconditioned
9034 : methods can be as large as 100x!
9035 :
9036 : MinNLC optimizer may use following preconditioners, each with its own
9037 : benefits and drawbacks:
9038 : a) inexact LBFGS-based, with O(N*K) evaluation time
9039 : b) exact low rank one, with O(N*K^2) evaluation time
9040 : c) exact robust one, with O(N^3+K*N^2) evaluation time
9041 : where K is a total number of general linear and nonlinear constraints (box
9042 : ones are not counted).
9043 :
9044 : Inexact LBFGS-based preconditioner uses L-BFGS formula combined with
9045 : orthogonality assumption to perform very fast updates. For a N-dimensional
9046 : problem with K general linear or nonlinear constraints (boundary ones are
9047 : not counted) it has O(N*K) cost per iteration. This preconditioner has
9048 : best quality (less iterations) when general linear and nonlinear
9049 : constraints are orthogonal to each other (orthogonality with respect to
9050 : boundary constraints is not required). Number of iterations increases when
9051 : constraints are non-orthogonal, because algorithm assumes orthogonality,
9052 : but still it is better than no preconditioner at all.
9053 :
9054 : INPUT PARAMETERS:
9055 : State - structure stores algorithm state
9056 :
9057 : -- ALGLIB --
9058 : Copyright 26.09.2014 by Bochkanov Sergey
9059 : *************************************************************************/
9060 0 : void minnlcsetprecinexact(const minnlcstate &state, const xparams _xparams)
9061 : {
9062 : jmp_buf _break_jump;
9063 : alglib_impl::ae_state _alglib_env_state;
9064 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9065 0 : if( setjmp(_break_jump) )
9066 : {
9067 : #if !defined(AE_NO_EXCEPTIONS)
9068 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9069 : #else
9070 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9071 : return;
9072 : #endif
9073 : }
9074 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9075 0 : if( _xparams.flags!=0x0 )
9076 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9077 0 : alglib_impl::minnlcsetprecinexact(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), &_alglib_env_state);
9078 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9079 0 : return;
9080 : }
9081 :
9082 : /*************************************************************************
9083 : This function sets preconditioner to "exact low rank" mode.
9084 :
9085 : Preconditioning is very important for convergence of Augmented Lagrangian
9086 : algorithm because presence of penalty term makes problem ill-conditioned.
9087 : Difference between performance of preconditioned and unpreconditioned
9088 : methods can be as large as 100x!
9089 :
9090 : MinNLC optimizer may use following preconditioners, each with its own
9091 : benefits and drawbacks:
9092 : a) inexact LBFGS-based, with O(N*K) evaluation time
9093 : b) exact low rank one, with O(N*K^2) evaluation time
9094 : c) exact robust one, with O(N^3+K*N^2) evaluation time
9095 : where K is a total number of general linear and nonlinear constraints (box
9096 : ones are not counted).
9097 :
9098 : It also provides special unpreconditioned mode of operation which can be
9099 : used for test purposes. Comments below discuss low rank preconditioner.
9100 :
9101 : Exact low-rank preconditioner uses Woodbury matrix identity to build
9102 : quadratic model of the penalized function. It has following features:
9103 : * no special assumptions about orthogonality of constraints
9104 : * preconditioner evaluation is optimized for K<<N. Its cost is O(N*K^2),
9105 : so it may become prohibitively slow for K>=N.
9106 : * finally, stability of the process is guaranteed only for K<<N. Woodbury
9107 : update often fail for K>=N due to degeneracy of intermediate matrices.
9108 : That's why we recommend to use "exact robust" preconditioner for such
9109 : cases.
9110 :
9111 : RECOMMENDATIONS
9112 :
9113 : We recommend to choose between "exact low rank" and "exact robust"
9114 : preconditioners, with "low rank" version being chosen when you know in
9115 : advance that total count of non-box constraints won't exceed N, and "robust"
9116 : version being chosen when you need bulletproof solution.
9117 :
9118 : INPUT PARAMETERS:
9119 : State - structure stores algorithm state
9120 : UpdateFreq- update frequency. Preconditioner is rebuilt after every
9121 : UpdateFreq iterations. Recommended value: 10 or higher.
9122 : Zero value means that good default value will be used.
9123 :
9124 : -- ALGLIB --
9125 : Copyright 26.09.2014 by Bochkanov Sergey
9126 : *************************************************************************/
9127 0 : void minnlcsetprecexactlowrank(const minnlcstate &state, const ae_int_t updatefreq, const xparams _xparams)
9128 : {
9129 : jmp_buf _break_jump;
9130 : alglib_impl::ae_state _alglib_env_state;
9131 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9132 0 : if( setjmp(_break_jump) )
9133 : {
9134 : #if !defined(AE_NO_EXCEPTIONS)
9135 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9136 : #else
9137 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9138 : return;
9139 : #endif
9140 : }
9141 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9142 0 : if( _xparams.flags!=0x0 )
9143 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9144 0 : alglib_impl::minnlcsetprecexactlowrank(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), updatefreq, &_alglib_env_state);
9145 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9146 0 : return;
9147 : }
9148 :
9149 : /*************************************************************************
9150 : This function sets preconditioner to "exact robust" mode.
9151 :
9152 : Preconditioning is very important for convergence of Augmented Lagrangian
9153 : algorithm because presence of penalty term makes problem ill-conditioned.
9154 : Difference between performance of preconditioned and unpreconditioned
9155 : methods can be as large as 100x!
9156 :
9157 : MinNLC optimizer may use following preconditioners, each with its own
9158 : benefits and drawbacks:
9159 : a) inexact LBFGS-based, with O(N*K) evaluation time
9160 : b) exact low rank one, with O(N*K^2) evaluation time
9161 : c) exact robust one, with O(N^3+K*N^2) evaluation time
9162 : where K is a total number of general linear and nonlinear constraints (box
9163 : ones are not counted).
9164 :
9165 : It also provides special unpreconditioned mode of operation which can be
9166 : used for test purposes. Comments below discuss robust preconditioner.
9167 :
9168 : Exact robust preconditioner uses Cholesky decomposition to invert
9169 : approximate Hessian matrix H=D+W'*C*W (where D stands for diagonal terms
9170 : of Hessian, combined result of initial scaling matrix and penalty from box
9171 : constraints; W stands for general linear constraints and linearization of
9172 : nonlinear ones; C stands for diagonal matrix of penalty coefficients).
9173 :
9174 : This preconditioner has following features:
9175 : * no special assumptions about constraint structure
9176 : * preconditioner is optimized for stability; unlike "exact low rank"
9177 : version which fails for K>=N, this one works well for any value of K.
9178 : * the only drawback is that is takes O(N^3+K*N^2) time to build it. No
9179 : economical Woodbury update is applied even when it makes sense, thus
9180 : there are exist situations (K<<N) when "exact low rank" preconditioner
9181 : outperforms this one.
9182 :
9183 : RECOMMENDATIONS
9184 :
9185 : We recommend to choose between "exact low rank" and "exact robust"
9186 : preconditioners, with "low rank" version being chosen when you know in
9187 : advance that total count of non-box constraints won't exceed N, and "robust"
9188 : version being chosen when you need bulletproof solution.
9189 :
9190 : INPUT PARAMETERS:
9191 : State - structure stores algorithm state
9192 : UpdateFreq- update frequency. Preconditioner is rebuilt after every
9193 : UpdateFreq iterations. Recommended value: 10 or higher.
9194 : Zero value means that good default value will be used.
9195 :
9196 : -- ALGLIB --
9197 : Copyright 26.09.2014 by Bochkanov Sergey
9198 : *************************************************************************/
9199 0 : void minnlcsetprecexactrobust(const minnlcstate &state, const ae_int_t updatefreq, const xparams _xparams)
9200 : {
9201 : jmp_buf _break_jump;
9202 : alglib_impl::ae_state _alglib_env_state;
9203 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9204 0 : if( setjmp(_break_jump) )
9205 : {
9206 : #if !defined(AE_NO_EXCEPTIONS)
9207 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9208 : #else
9209 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9210 : return;
9211 : #endif
9212 : }
9213 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9214 0 : if( _xparams.flags!=0x0 )
9215 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9216 0 : alglib_impl::minnlcsetprecexactrobust(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), updatefreq, &_alglib_env_state);
9217 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9218 0 : return;
9219 : }
9220 :
9221 : /*************************************************************************
9222 : This function sets preconditioner to "turned off" mode.
9223 :
9224 : Preconditioning is very important for convergence of Augmented Lagrangian
9225 : algorithm because presence of penalty term makes problem ill-conditioned.
9226 : Difference between performance of preconditioned and unpreconditioned
9227 : methods can be as large as 100x!
9228 :
9229 : MinNLC optimizer may utilize two preconditioners, each with its own
9230 : benefits and drawbacks: a) inexact LBFGS-based, and b) exact low rank one.
9231 : It also provides special unpreconditioned mode of operation which can be
9232 : used for test purposes.
9233 :
9234 : This function activates this test mode. Do not use it in production code
9235 : to solve real-life problems.
9236 :
9237 : INPUT PARAMETERS:
9238 : State - structure stores algorithm state
9239 :
9240 : -- ALGLIB --
9241 : Copyright 26.09.2014 by Bochkanov Sergey
9242 : *************************************************************************/
9243 0 : void minnlcsetprecnone(const minnlcstate &state, const xparams _xparams)
9244 : {
9245 : jmp_buf _break_jump;
9246 : alglib_impl::ae_state _alglib_env_state;
9247 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9248 0 : if( setjmp(_break_jump) )
9249 : {
9250 : #if !defined(AE_NO_EXCEPTIONS)
9251 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9252 : #else
9253 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9254 : return;
9255 : #endif
9256 : }
9257 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9258 0 : if( _xparams.flags!=0x0 )
9259 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9260 0 : alglib_impl::minnlcsetprecnone(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), &_alglib_env_state);
9261 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9262 0 : return;
9263 : }
9264 :
9265 : /*************************************************************************
9266 : This function sets maximum step length (after scaling of step vector with
9267 : respect to variable scales specified by minnlcsetscale() call).
9268 :
9269 : INPUT PARAMETERS:
9270 : State - structure which stores algorithm state
9271 : StpMax - maximum step length, >=0. Set StpMax to 0.0 (default), if
9272 : you don't want to limit step length.
9273 :
9274 : Use this subroutine when you optimize target function which contains exp()
9275 : or other fast growing functions, and optimization algorithm makes too
9276 : large steps which leads to overflow. This function allows us to reject
9277 : steps that are too large (and therefore expose us to the possible
9278 : overflow) without actually calculating function value at the x+stp*d.
9279 :
9280 : NOTE: different solvers employed by MinNLC optimizer use different norms
9281 : for step; AUL solver uses 2-norm, whilst SLP solver uses INF-norm.
9282 :
9283 : -- ALGLIB --
9284 : Copyright 02.04.2010 by Bochkanov Sergey
9285 : *************************************************************************/
9286 0 : void minnlcsetstpmax(const minnlcstate &state, const double stpmax, const xparams _xparams)
9287 : {
9288 : jmp_buf _break_jump;
9289 : alglib_impl::ae_state _alglib_env_state;
9290 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9291 0 : if( setjmp(_break_jump) )
9292 : {
9293 : #if !defined(AE_NO_EXCEPTIONS)
9294 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9295 : #else
9296 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9297 : return;
9298 : #endif
9299 : }
9300 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9301 0 : if( _xparams.flags!=0x0 )
9302 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9303 0 : alglib_impl::minnlcsetstpmax(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), stpmax, &_alglib_env_state);
9304 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9305 0 : return;
9306 : }
9307 :
9308 : /*************************************************************************
9309 : This function tells MinNLC unit to use Augmented Lagrangian algorithm
9310 : for nonlinearly constrained optimization. This algorithm is a slight
9311 : modification of one described in "A Modified Barrier-Augmented Lagrangian
9312 : Method for Constrained Minimization (1999)" by D.GOLDFARB, R.POLYAK,
9313 : K. SCHEINBERG, I.YUZEFOVICH.
9314 :
9315 : AUL solver can be significantly faster than SQP on easy problems due to
9316 : cheaper iterations, although it needs more function evaluations.
9317 :
9318 : Augmented Lagrangian algorithm works by converting problem of minimizing
9319 : F(x) subject to equality/inequality constraints to unconstrained problem
9320 : of the form
9321 :
9322 : min[ f(x) +
9323 : + Rho*PENALTY_EQ(x) + SHIFT_EQ(x,Nu1) +
9324 : + Rho*PENALTY_INEQ(x) + SHIFT_INEQ(x,Nu2) ]
9325 :
9326 : where:
9327 : * Rho is a fixed penalization coefficient
9328 : * PENALTY_EQ(x) is a penalty term, which is used to APPROXIMATELY enforce
9329 : equality constraints
9330 : * SHIFT_EQ(x) is a special "shift" term which is used to "fine-tune"
9331 : equality constraints, greatly increasing precision
9332 : * PENALTY_INEQ(x) is a penalty term which is used to approximately enforce
9333 : inequality constraints
9334 : * SHIFT_INEQ(x) is a special "shift" term which is used to "fine-tune"
9335 : inequality constraints, greatly increasing precision
9336 : * Nu1/Nu2 are vectors of Lagrange coefficients which are fine-tuned during
9337 : outer iterations of algorithm
9338 :
9339 : This version of AUL algorithm uses preconditioner, which greatly
9340 : accelerates convergence. Because this algorithm is similar to penalty
9341 : methods, it may perform steps into infeasible area. All kinds of
9342 : constraints (boundary, linear and nonlinear ones) may be violated in
9343 : intermediate points - and in the solution. However, properly configured
9344 : AUL method is significantly better at handling constraints than barrier
9345 : and/or penalty methods.
9346 :
9347 : The very basic outline of algorithm is given below:
9348 : 1) first outer iteration is performed with "default" values of Lagrange
9349 : multipliers Nu1/Nu2. Solution quality is low (candidate point can be
9350 : too far away from true solution; large violation of constraints is
9351 : possible) and is comparable with that of penalty methods.
9352 : 2) subsequent outer iterations refine Lagrange multipliers and improve
9353 : quality of the solution.
9354 :
9355 : INPUT PARAMETERS:
9356 : State - structure which stores algorithm state
9357 : Rho - penalty coefficient, Rho>0:
9358 : * large enough that algorithm converges with desired
9359 : precision. Minimum value is 10*max(S'*diag(H)*S), where
9360 : S is a scale matrix (set by MinNLCSetScale) and H is a
9361 : Hessian of the function being minimized. If you can not
9362 : easily estimate Hessian norm, see our recommendations
9363 : below.
9364 : * not TOO large to prevent ill-conditioning
9365 : * for unit-scale problems (variables and Hessian have unit
9366 : magnitude), Rho=100 or Rho=1000 can be used.
9367 : * it is important to note that Rho is internally multiplied
9368 : by scaling matrix, i.e. optimum value of Rho depends on
9369 : scale of variables specified by MinNLCSetScale().
9370 : ItsCnt - number of outer iterations:
9371 : * ItsCnt=0 means that small number of outer iterations is
9372 : automatically chosen (10 iterations in current version).
9373 : * ItsCnt=1 means that AUL algorithm performs just as usual
9374 : barrier method.
9375 : * ItsCnt>1 means that AUL algorithm performs specified
9376 : number of outer iterations
9377 :
9378 : HOW TO CHOOSE PARAMETERS
9379 :
9380 : Nonlinear optimization is a tricky area and Augmented Lagrangian algorithm
9381 : is sometimes hard to tune. Good values of Rho and ItsCnt are problem-
9382 : specific. In order to help you we prepared following set of
9383 : recommendations:
9384 :
9385 : * for unit-scale problems (variables and Hessian have unit magnitude),
9386 : Rho=100 or Rho=1000 can be used.
9387 :
9388 : * start from some small value of Rho and solve problem with just one
9389 : outer iteration (ItcCnt=1). In this case algorithm behaves like penalty
9390 : method. Increase Rho in 2x or 10x steps until you see that one outer
9391 : iteration returns point which is "rough approximation to solution".
9392 :
9393 : It is very important to have Rho so large that penalty term becomes
9394 : constraining i.e. modified function becomes highly convex in constrained
9395 : directions.
9396 :
9397 : From the other side, too large Rho may prevent you from converging to
9398 : the solution. You can diagnose it by studying number of inner iterations
9399 : performed by algorithm: too few (5-10 on 1000-dimensional problem) or
9400 : too many (orders of magnitude more than dimensionality) usually means
9401 : that Rho is too large.
9402 :
9403 : * with just one outer iteration you usually have low-quality solution.
9404 : Some constraints can be violated with very large margin, while other
9405 : ones (which are NOT violated in the true solution) can push final point
9406 : too far in the inner area of the feasible set.
9407 :
9408 : For example, if you have constraint x0>=0 and true solution x0=1, then
9409 : merely a presence of "x0>=0" will introduce a bias towards larger values
9410 : of x0. Say, algorithm may stop at x0=1.5 instead of 1.0.
9411 :
9412 : * after you found good Rho, you may increase number of outer iterations.
9413 : ItsCnt=10 is a good value. Subsequent outer iteration will refine values
9414 : of Lagrange multipliers. Constraints which were violated will be
9415 : enforced, inactive constraints will be dropped (corresponding multipliers
9416 : will be decreased). Ideally, you should see 10-1000x improvement in
9417 : constraint handling (constraint violation is reduced).
9418 :
9419 : * if you see that algorithm converges to vicinity of solution, but
9420 : additional outer iterations do not refine solution, it may mean that
9421 : algorithm is unstable - it wanders around true solution, but can not
9422 : approach it. Sometimes algorithm may be stabilized by increasing Rho one
9423 : more time, making it 5x or 10x larger.
9424 :
9425 : SCALING OF CONSTRAINTS [IMPORTANT]
9426 :
9427 : AUL optimizer scales variables according to scale specified by
9428 : MinNLCSetScale() function, so it can handle problems with badly scaled
9429 : variables (as long as we KNOW their scales). However, because function
9430 : being optimized is a mix of original function and constraint-dependent
9431 : penalty functions, it is important to rescale both variables AND
9432 : constraints.
9433 :
9434 : Say, if you minimize f(x)=x^2 subject to 1000000*x>=0, then you have
9435 : constraint whose scale is different from that of target function (another
9436 : example is 0.000001*x>=0). It is also possible to have constraints whose
9437 : scales are misaligned: 1000000*x0>=0, 0.000001*x1<=0. Inappropriate
9438 : scaling may ruin convergence because minimizing x^2 subject to x>=0 is NOT
9439 : same as minimizing it subject to 1000000*x>=0.
9440 :
9441 : Because we know coefficients of boundary/linear constraints, we can
9442 : automatically rescale and normalize them. However, there is no way to
9443 : automatically rescale nonlinear constraints Gi(x) and Hi(x) - they are
9444 : black boxes.
9445 :
9446 : It means that YOU are the one who is responsible for correct scaling of
9447 : nonlinear constraints Gi(x) and Hi(x). We recommend you to rescale
9448 : nonlinear constraints in such way that I-th component of dG/dX (or dH/dx)
9449 : has magnitude approximately equal to 1/S[i] (where S is a scale set by
9450 : MinNLCSetScale() function).
9451 :
9452 : WHAT IF IT DOES NOT CONVERGE?
9453 :
9454 : It is possible that AUL algorithm fails to converge to precise values of
9455 : Lagrange multipliers. It stops somewhere around true solution, but candidate
9456 : point is still too far from solution, and some constraints are violated.
9457 : Such kind of failure is specific for Lagrangian algorithms - technically,
9458 : they stop at some point, but this point is not constrained solution.
9459 :
9460 : There are exist several reasons why algorithm may fail to converge:
9461 : a) too loose stopping criteria for inner iteration
9462 : b) degenerate, redundant constraints
9463 : c) target function has unconstrained extremum exactly at the boundary of
9464 : some constraint
9465 : d) numerical noise in the target function
9466 :
9467 : In all these cases algorithm is unstable - each outer iteration results in
9468 : large and almost random step which improves handling of some constraints,
9469 : but violates other ones (ideally outer iterations should form a sequence
9470 : of progressively decreasing steps towards solution).
9471 :
9472 : First reason possible is that too loose stopping criteria for inner
9473 : iteration were specified. Augmented Lagrangian algorithm solves a sequence
9474 : of intermediate problems, and requries each of them to be solved with high
9475 : precision. Insufficient precision results in incorrect update of Lagrange
9476 : multipliers.
9477 :
9478 : Another reason is that you may have specified degenerate constraints: say,
9479 : some constraint was repeated twice. In most cases AUL algorithm gracefully
9480 : handles such situations, but sometimes it may spend too much time figuring
9481 : out subtle degeneracies in constraint matrix.
9482 :
9483 : Third reason is tricky and hard to diagnose. Consider situation when you
9484 : minimize f=x^2 subject to constraint x>=0. Unconstrained extremum is
9485 : located exactly at the boundary of constrained area. In this case
9486 : algorithm will tend to oscillate between negative and positive x. Each
9487 : time it stops at x<0 it "reinforces" constraint x>=0, and each time it is
9488 : bounced to x>0 it "relaxes" constraint (and is attracted to x<0).
9489 :
9490 : Such situation sometimes happens in problems with hidden symetries.
9491 : Algorithm is got caught in a loop with Lagrange multipliers being
9492 : continuously increased/decreased. Luckily, such loop forms after at least
9493 : three iterations, so this problem can be solved by DECREASING number of
9494 : outer iterations down to 1-2 and increasing penalty coefficient Rho as
9495 : much as possible.
9496 :
9497 : Final reason is numerical noise. AUL algorithm is robust against moderate
9498 : noise (more robust than, say, active set methods), but large noise may
9499 : destabilize algorithm.
9500 :
9501 : -- ALGLIB --
9502 : Copyright 06.06.2014 by Bochkanov Sergey
9503 : *************************************************************************/
9504 0 : void minnlcsetalgoaul(const minnlcstate &state, const double rho, const ae_int_t itscnt, const xparams _xparams)
9505 : {
9506 : jmp_buf _break_jump;
9507 : alglib_impl::ae_state _alglib_env_state;
9508 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9509 0 : if( setjmp(_break_jump) )
9510 : {
9511 : #if !defined(AE_NO_EXCEPTIONS)
9512 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9513 : #else
9514 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9515 : return;
9516 : #endif
9517 : }
9518 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9519 0 : if( _xparams.flags!=0x0 )
9520 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9521 0 : alglib_impl::minnlcsetalgoaul(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), rho, itscnt, &_alglib_env_state);
9522 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9523 0 : return;
9524 : }
9525 :
9526 : /*************************************************************************
9527 : This function tells MinNLC optimizer to use SLP (Successive Linear
9528 : Programming) algorithm for nonlinearly constrained optimization. This
9529 : algorithm is a slight modification of one described in "A Linear
9530 : programming-based optimization algorithm for solving nonlinear programming
9531 : problems" (2010) by Claus Still and Tapio Westerlund.
9532 :
9533 : This solver is the slowest one in ALGLIB, it requires more target function
9534 : evaluations that SQP and AUL. However it is somewhat more robust in tricky
9535 : cases, so it can be used as a backup plan. We recommend to use this algo
9536 : when SQP/AUL do not work (does not return the solution you expect). If
9537 : trying different approach gives same results, then MAYBE something is
9538 : wrong with your optimization problem.
9539 :
9540 : Despite its name ("linear" = "first order method") this algorithm performs
9541 : steps similar to that of conjugate gradients method; internally it uses
9542 : orthogonality/conjugacy requirement for subsequent steps which makes it
9543 : closer to second order methods in terms of convergence speed.
9544 :
9545 : Convergence is proved for the following case:
9546 : * function and constraints are continuously differentiable (C1 class)
9547 : * extended Mangasarian–Fromovitz constraint qualification (EMFCQ) holds;
9548 : in the context of this algorithm EMFCQ means that one can, for any
9549 : infeasible point, find a search direction such that the constraint
9550 : infeasibilities are reduced.
9551 :
9552 : This algorithm has following nice properties:
9553 : * no parameters to tune
9554 : * no convexity requirements for target function or constraints
9555 : * initial point can be infeasible
9556 : * algorithm respects box constraints in all intermediate points (it does
9557 : not even evaluate function outside of box constrained area)
9558 : * once linear constraints are enforced, algorithm will not violate them
9559 : * no such guarantees can be provided for nonlinear constraints, but once
9560 : nonlinear constraints are enforced, algorithm will try to respect them
9561 : as much as possible
9562 : * numerical differentiation does not violate box constraints (although
9563 : general linear and nonlinear ones can be violated during differentiation)
9564 : * from our experience, this algorithm is somewhat more robust in really
9565 : difficult cases
9566 :
9567 : INPUT PARAMETERS:
9568 : State - structure which stores algorithm state
9569 :
9570 : ===== TRACING SLP SOLVER =================================================
9571 :
9572 : SLP solver supports advanced tracing capabilities. You can trace algorithm
9573 : output by specifying following trace symbols (case-insensitive) by means
9574 : of trace_file() call:
9575 : * 'SLP' - for basic trace of algorithm steps and decisions. Only
9576 : short scalars (function values and deltas) are printed.
9577 : N-dimensional quantities like search directions are NOT
9578 : printed.
9579 : It also prints OptGuard integrity checker report when
9580 : nonsmoothness of target/constraints is suspected.
9581 : * 'SLP.DETAILED'- for output of points being visited and search directions
9582 : This symbol also implicitly defines 'SLP'. You can
9583 : control output format by additionally specifying:
9584 : * nothing to output in 6-digit exponential format
9585 : * 'PREC.E15' to output in 15-digit exponential format
9586 : * 'PREC.F6' to output in 6-digit fixed-point format
9587 : * 'SLP.PROBING' - to let algorithm insert additional function evaluations
9588 : before line search in order to build human-readable
9589 : chart of the raw Lagrangian (~40 additional function
9590 : evaluations is performed for each line search). This
9591 : symbol also implicitly defines 'SLP'.
9592 : * 'OPTGUARD' - for report of smoothness/continuity violations in target
9593 : and/or constraints. This kind of reporting is included
9594 : in 'SLP', but it comes with lots of additional info. If
9595 : you need just smoothness monitoring, specify this
9596 : setting.
9597 :
9598 : NOTE: this tag merely directs OptGuard output to log
9599 : file. Even if you specify it, you still have to
9600 : configure OptGuard by calling minnlcoptguard...()
9601 : family of functions.
9602 :
9603 : By default trace is disabled and adds no overhead to the optimization
9604 : process. However, specifying any of the symbols adds some formatting and
9605 : output-related overhead. Specifying 'SLP.PROBING' adds even larger
9606 : overhead due to additional function evaluations being performed.
9607 :
9608 : You may specify multiple symbols by separating them with commas:
9609 : >
9610 : > alglib::trace_file("SLP,SLP.PROBING,PREC.F6", "path/to/trace.log")
9611 : >
9612 :
9613 : -- ALGLIB --
9614 : Copyright 02.04.2018 by Bochkanov Sergey
9615 : *************************************************************************/
9616 0 : void minnlcsetalgoslp(const minnlcstate &state, const xparams _xparams)
9617 : {
9618 : jmp_buf _break_jump;
9619 : alglib_impl::ae_state _alglib_env_state;
9620 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9621 0 : if( setjmp(_break_jump) )
9622 : {
9623 : #if !defined(AE_NO_EXCEPTIONS)
9624 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9625 : #else
9626 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9627 : return;
9628 : #endif
9629 : }
9630 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9631 0 : if( _xparams.flags!=0x0 )
9632 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9633 0 : alglib_impl::minnlcsetalgoslp(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), &_alglib_env_state);
9634 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9635 0 : return;
9636 : }
9637 :
9638 : /*************************************************************************
9639 : This function tells MinNLC optimizer to use SQP (Successive Quadratic
9640 : Programming) algorithm for nonlinearly constrained optimization.
9641 :
9642 : This algorithm needs order of magnitude (5x-10x) less function evaluations
9643 : than AUL solver, but has higher overhead because each iteration involves
9644 : solution of quadratic programming problem.
9645 :
9646 : Convergence is proved for the following case:
9647 : * function and constraints are continuously differentiable (C1 class)
9648 :
9649 : This algorithm has following nice properties:
9650 : * no parameters to tune
9651 : * no convexity requirements for target function or constraints
9652 : * initial point can be infeasible
9653 : * algorithm respects box constraints in all intermediate points (it does
9654 : not even evaluate function outside of box constrained area)
9655 : * once linear constraints are enforced, algorithm will not violate them
9656 : * no such guarantees can be provided for nonlinear constraints, but once
9657 : nonlinear constraints are enforced, algorithm will try to respect them
9658 : as much as possible
9659 : * numerical differentiation does not violate box constraints (although
9660 : general linear and nonlinear ones can be violated during differentiation)
9661 :
9662 : We recommend this algorithm as a default option for medium-scale problems
9663 : (less than thousand of variables) or problems with target function being
9664 : hard to evaluate.
9665 :
9666 : For large-scale problems or ones with very cheap target function
9667 : AUL solver can be better option.
9668 :
9669 : INPUT PARAMETERS:
9670 : State - structure which stores algorithm state
9671 :
9672 : ===== INTERACTION WITH OPTGUARD ==========================================
9673 :
9674 : OptGuard integrity checker allows us to catch problems like errors in
9675 : gradients and discontinuity/nonsmoothness of the target/constraints.
9676 : Latter kind of problems can be detected by looking upon line searches
9677 : performed during optimization and searching for signs of nonsmoothness.
9678 :
9679 : The problem with SQP is that it is too good for OptGuard to work - it does
9680 : not perform line searches. It typically needs 1-2 function evaluations
9681 : per step, and it is not enough for OptGuard to detect nonsmoothness.
9682 :
9683 : So, if you suspect that your problem is nonsmooth, we recommend you to use
9684 : AUL or SLP solvers.
9685 :
9686 : ===== TRACING SQP SOLVER =================================================
9687 :
9688 : SQP solver supports advanced tracing capabilities. You can trace algorithm
9689 : output by specifying following trace symbols (case-insensitive) by means
9690 : of trace_file() call:
9691 : * 'SQP' - for basic trace of algorithm steps and decisions. Only
9692 : short scalars (function values and deltas) are printed.
9693 : N-dimensional quantities like search directions are NOT
9694 : printed.
9695 : It also prints OptGuard integrity checker report when
9696 : nonsmoothness of target/constraints is suspected.
9697 : * 'SQP.DETAILED'- for output of points being visited and search directions
9698 : This symbol also implicitly defines 'SQP'. You can
9699 : control output format by additionally specifying:
9700 : * nothing to output in 6-digit exponential format
9701 : * 'PREC.E15' to output in 15-digit exponential format
9702 : * 'PREC.F6' to output in 6-digit fixed-point format
9703 : * 'SQP.PROBING' - to let algorithm insert additional function evaluations
9704 : before line search in order to build human-readable
9705 : chart of the raw Lagrangian (~40 additional function
9706 : evaluations is performed for each line search). This
9707 : symbol also implicitly defines 'SQP' and activates
9708 : OptGuard integrity checker which detects continuity and
9709 : smoothness violations. An OptGuard log is printed at the
9710 : end of the file.
9711 :
9712 : By default trace is disabled and adds no overhead to the optimization
9713 : process. However, specifying any of the symbols adds some formatting and
9714 : output-related overhead. Specifying 'SQP.PROBING' adds even larger
9715 : overhead due to additional function evaluations being performed.
9716 :
9717 : You may specify multiple symbols by separating them with commas:
9718 : >
9719 : > alglib::trace_file("SQP,SQP.PROBING,PREC.F6", "path/to/trace.log")
9720 : >
9721 :
9722 : -- ALGLIB --
9723 : Copyright 02.12.2019 by Bochkanov Sergey
9724 : *************************************************************************/
9725 0 : void minnlcsetalgosqp(const minnlcstate &state, const xparams _xparams)
9726 : {
9727 : jmp_buf _break_jump;
9728 : alglib_impl::ae_state _alglib_env_state;
9729 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9730 0 : if( setjmp(_break_jump) )
9731 : {
9732 : #if !defined(AE_NO_EXCEPTIONS)
9733 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9734 : #else
9735 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9736 : return;
9737 : #endif
9738 : }
9739 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9740 0 : if( _xparams.flags!=0x0 )
9741 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9742 0 : alglib_impl::minnlcsetalgosqp(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), &_alglib_env_state);
9743 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9744 0 : return;
9745 : }
9746 :
9747 : /*************************************************************************
9748 : This function turns on/off reporting.
9749 :
9750 : INPUT PARAMETERS:
9751 : State - structure which stores algorithm state
9752 : NeedXRep- whether iteration reports are needed or not
9753 :
9754 : If NeedXRep is True, algorithm will call rep() callback function if it is
9755 : provided to MinNLCOptimize().
9756 :
9757 : NOTE: algorithm passes two parameters to rep() callback - current point
9758 : and penalized function value at current point. Important - function
9759 : value which is returned is NOT function being minimized. It is sum
9760 : of the value of the function being minimized - and penalty term.
9761 :
9762 : -- ALGLIB --
9763 : Copyright 28.11.2010 by Bochkanov Sergey
9764 : *************************************************************************/
9765 0 : void minnlcsetxrep(const minnlcstate &state, const bool needxrep, const xparams _xparams)
9766 : {
9767 : jmp_buf _break_jump;
9768 : alglib_impl::ae_state _alglib_env_state;
9769 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9770 0 : if( setjmp(_break_jump) )
9771 : {
9772 : #if !defined(AE_NO_EXCEPTIONS)
9773 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9774 : #else
9775 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9776 : return;
9777 : #endif
9778 : }
9779 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9780 0 : if( _xparams.flags!=0x0 )
9781 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9782 0 : alglib_impl::minnlcsetxrep(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), needxrep, &_alglib_env_state);
9783 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9784 0 : return;
9785 : }
9786 :
9787 : /*************************************************************************
9788 : This function provides reverse communication interface
9789 : Reverse communication interface is not documented or recommended to use.
9790 : See below for functions which provide better documented API
9791 : *************************************************************************/
9792 0 : bool minnlciteration(const minnlcstate &state, const xparams _xparams)
9793 : {
9794 : jmp_buf _break_jump;
9795 : alglib_impl::ae_state _alglib_env_state;
9796 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9797 0 : if( setjmp(_break_jump) )
9798 : {
9799 : #if !defined(AE_NO_EXCEPTIONS)
9800 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9801 : #else
9802 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9803 : return 0;
9804 : #endif
9805 : }
9806 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9807 0 : if( _xparams.flags!=0x0 )
9808 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9809 0 : ae_bool result = alglib_impl::minnlciteration(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), &_alglib_env_state);
9810 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9811 0 : return *(reinterpret_cast<bool*>(&result));
9812 : }
9813 :
9814 :
9815 0 : void minnlcoptimize(minnlcstate &state,
9816 : void (*fvec)(const real_1d_array &x, real_1d_array &fi, void *ptr),
9817 : void (*rep)(const real_1d_array &x, double func, void *ptr),
9818 : void *ptr,
9819 : const xparams _xparams)
9820 : {
9821 : jmp_buf _break_jump;
9822 : alglib_impl::ae_state _alglib_env_state;
9823 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9824 0 : if( setjmp(_break_jump) )
9825 : {
9826 : #if !defined(AE_NO_EXCEPTIONS)
9827 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9828 : #else
9829 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9830 : return;
9831 : #endif
9832 : }
9833 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9834 0 : if( _xparams.flags!=0x0 )
9835 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9836 0 : alglib_impl::ae_assert(fvec!=NULL, "ALGLIB: error in 'minnlcoptimize()' (fvec is NULL)", &_alglib_env_state);
9837 0 : while( alglib_impl::minnlciteration(state.c_ptr(), &_alglib_env_state) )
9838 : {
9839 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN
9840 0 : if( state.needfi )
9841 : {
9842 0 : fvec(state.x, state.fi, ptr);
9843 0 : continue;
9844 : }
9845 0 : if( state.xupdated )
9846 : {
9847 0 : if( rep!=NULL )
9848 0 : rep(state.x, state.f, ptr);
9849 0 : continue;
9850 : }
9851 0 : goto lbl_no_callback;
9852 0 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_END
9853 0 : lbl_no_callback:
9854 0 : alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minnlcoptimize' (some derivatives were not provided?)", &_alglib_env_state);
9855 : }
9856 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9857 0 : }
9858 :
9859 :
9860 0 : void minnlcoptimize(minnlcstate &state,
9861 : void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr),
9862 : void (*rep)(const real_1d_array &x, double func, void *ptr),
9863 : void *ptr,
9864 : const xparams _xparams)
9865 : {
9866 : jmp_buf _break_jump;
9867 : alglib_impl::ae_state _alglib_env_state;
9868 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9869 0 : if( setjmp(_break_jump) )
9870 : {
9871 : #if !defined(AE_NO_EXCEPTIONS)
9872 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9873 : #else
9874 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9875 : return;
9876 : #endif
9877 : }
9878 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9879 0 : if( _xparams.flags!=0x0 )
9880 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9881 0 : alglib_impl::ae_assert(jac!=NULL, "ALGLIB: error in 'minnlcoptimize()' (jac is NULL)", &_alglib_env_state);
9882 0 : while( alglib_impl::minnlciteration(state.c_ptr(), &_alglib_env_state) )
9883 : {
9884 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN
9885 0 : if( state.needfij )
9886 : {
9887 0 : jac(state.x, state.fi, state.j, ptr);
9888 0 : continue;
9889 : }
9890 0 : if( state.xupdated )
9891 : {
9892 0 : if( rep!=NULL )
9893 0 : rep(state.x, state.f, ptr);
9894 0 : continue;
9895 : }
9896 0 : goto lbl_no_callback;
9897 0 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_END
9898 0 : lbl_no_callback:
9899 0 : alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minnlcoptimize' (some derivatives were not provided?)", &_alglib_env_state);
9900 : }
9901 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9902 0 : }
9903 :
9904 :
9905 :
9906 : /*************************************************************************
9907 : This function activates/deactivates verification of the user-supplied
9908 : analytic gradient/Jacobian.
9909 :
9910 : Upon activation of this option OptGuard integrity checker performs
9911 : numerical differentiation of your target function (constraints) at the
9912 : initial point (note: future versions may also perform check at the final
9913 : point) and compares numerical gradient/Jacobian with analytic one provided
9914 : by you.
9915 :
9916 : If difference is too large, an error flag is set and optimization session
9917 : continues. After optimization session is over, you can retrieve the report
9918 : which stores both gradients/Jacobians, and specific components highlighted
9919 : as suspicious by the OptGuard.
9920 :
9921 : The primary OptGuard report can be retrieved with minnlcoptguardresults().
9922 :
9923 : IMPORTANT: gradient check is a high-overhead option which will cost you
9924 : about 3*N additional function evaluations. In many cases it may
9925 : cost as much as the rest of the optimization session.
9926 :
9927 : YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO
9928 : CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY.
9929 :
9930 : NOTE: unlike previous incarnation of the gradient checking code, OptGuard
9931 : does NOT interrupt optimization even if it discovers bad gradient.
9932 :
9933 : INPUT PARAMETERS:
9934 : State - structure used to store algorithm state
9935 : TestStep - verification step used for numerical differentiation:
9936 : * TestStep=0 turns verification off
9937 : * TestStep>0 activates verification
9938 : You should carefully choose TestStep. Value which is
9939 : too large (so large that function behavior is non-
9940 : cubic at this scale) will lead to false alarms. Too
9941 : short step will result in rounding errors dominating
9942 : numerical derivative.
9943 :
9944 : You may use different step for different parameters by
9945 : means of setting scale with minnlcsetscale().
9946 :
9947 : === EXPLANATION ==========================================================
9948 :
9949 : In order to verify gradient algorithm performs following steps:
9950 : * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i],
9951 : where X[i] is i-th component of the initial point and S[i] is a scale
9952 : of i-th parameter
9953 : * F(X) is evaluated at these trial points
9954 : * we perform one more evaluation in the middle point of the interval
9955 : * we build cubic model using function values and derivatives at trial
9956 : points and we compare its prediction with actual value in the middle
9957 : point
9958 :
9959 : -- ALGLIB --
9960 : Copyright 15.06.2014 by Bochkanov Sergey
9961 : *************************************************************************/
9962 0 : void minnlcoptguardgradient(const minnlcstate &state, const double teststep, const xparams _xparams)
9963 : {
9964 : jmp_buf _break_jump;
9965 : alglib_impl::ae_state _alglib_env_state;
9966 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9967 0 : if( setjmp(_break_jump) )
9968 : {
9969 : #if !defined(AE_NO_EXCEPTIONS)
9970 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9971 : #else
9972 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9973 : return;
9974 : #endif
9975 : }
9976 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9977 0 : if( _xparams.flags!=0x0 )
9978 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9979 0 : alglib_impl::minnlcoptguardgradient(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), teststep, &_alglib_env_state);
9980 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9981 0 : return;
9982 : }
9983 :
9984 : /*************************************************************************
9985 : This function activates/deactivates nonsmoothness monitoring option of
9986 : the OptGuard integrity checker. Smoothness monitor silently observes
9987 : solution process and tries to detect ill-posed problems, i.e. ones with:
9988 : a) discontinuous target function (non-C0) and/or constraints
9989 : b) nonsmooth target function (non-C1) and/or constraints
9990 :
9991 : Smoothness monitoring does NOT interrupt optimization even if it suspects
9992 : that your problem is nonsmooth. It just sets corresponding flags in the
9993 : OptGuard report which can be retrieved after optimization is over.
9994 :
9995 : Smoothness monitoring is a moderate overhead option which often adds less
9996 : than 1% to the optimizer running time. Thus, you can use it even for large
9997 : scale problems.
9998 :
9999 : NOTE: OptGuard does NOT guarantee that it will always detect C0/C1
10000 : continuity violations.
10001 :
10002 : First, minor errors are hard to catch - say, a 0.0001 difference in
10003 : the model values at two sides of the gap may be due to discontinuity
10004 : of the model - or simply because the model has changed.
10005 :
10006 : Second, C1-violations are especially difficult to detect in a
10007 : noninvasive way. The optimizer usually performs very short steps
10008 : near the nonsmoothness, and differentiation usually introduces a
10009 : lot of numerical noise. It is hard to tell whether some tiny
10010 : discontinuity in the slope is due to real nonsmoothness or just due
10011 : to numerical noise alone.
10012 :
10013 : Our top priority was to avoid false positives, so in some rare cases
10014 : minor errors may went unnoticed (however, in most cases they can be
10015 : spotted with restart from different initial point).
10016 :
10017 : INPUT PARAMETERS:
10018 : state - algorithm state
10019 : level - monitoring level:
10020 : * 0 - monitoring is disabled
10021 : * 1 - noninvasive low-overhead monitoring; function values
10022 : and/or gradients are recorded, but OptGuard does not
10023 : try to perform additional evaluations in order to
10024 : get more information about suspicious locations.
10025 : This kind of monitoring does not work well with SQP
10026 : because SQP solver needs just 1-2 function evaluations
10027 : per step, which is not enough for OptGuard to make
10028 : any conclusions.
10029 :
10030 : === EXPLANATION ==========================================================
10031 :
10032 : One major source of headache during optimization is the possibility of
10033 : the coding errors in the target function/constraints (or their gradients).
10034 : Such errors most often manifest themselves as discontinuity or
10035 : nonsmoothness of the target/constraints.
10036 :
10037 : Another frequent situation is when you try to optimize something involving
10038 : lots of min() and max() operations, i.e. nonsmooth target. Although not a
10039 : coding error, it is nonsmoothness anyway - and smooth optimizers usually
10040 : stop right after encountering nonsmoothness, well before reaching solution.
10041 :
10042 : OptGuard integrity checker helps you to catch such situations: it monitors
10043 : function values/gradients being passed to the optimizer and tries to
10044 : errors. Upon discovering suspicious pair of points it raises appropriate
10045 : flag (and allows you to continue optimization). When optimization is done,
10046 : you can study OptGuard result.
10047 :
10048 : -- ALGLIB --
10049 : Copyright 21.11.2018 by Bochkanov Sergey
10050 : *************************************************************************/
10051 0 : void minnlcoptguardsmoothness(const minnlcstate &state, const ae_int_t level, const xparams _xparams)
10052 : {
10053 : jmp_buf _break_jump;
10054 : alglib_impl::ae_state _alglib_env_state;
10055 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10056 0 : if( setjmp(_break_jump) )
10057 : {
10058 : #if !defined(AE_NO_EXCEPTIONS)
10059 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10060 : #else
10061 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10062 : return;
10063 : #endif
10064 : }
10065 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10066 0 : if( _xparams.flags!=0x0 )
10067 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10068 0 : alglib_impl::minnlcoptguardsmoothness(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), level, &_alglib_env_state);
10069 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10070 0 : return;
10071 : }
10072 :
10073 : /*************************************************************************
10074 : This function activates/deactivates nonsmoothness monitoring option of
10075 : the OptGuard integrity checker. Smoothness monitor silently observes
10076 : solution process and tries to detect ill-posed problems, i.e. ones with:
10077 : a) discontinuous target function (non-C0) and/or constraints
10078 : b) nonsmooth target function (non-C1) and/or constraints
10079 :
10080 : Smoothness monitoring does NOT interrupt optimization even if it suspects
10081 : that your problem is nonsmooth. It just sets corresponding flags in the
10082 : OptGuard report which can be retrieved after optimization is over.
10083 :
10084 : Smoothness monitoring is a moderate overhead option which often adds less
10085 : than 1% to the optimizer running time. Thus, you can use it even for large
10086 : scale problems.
10087 :
10088 : NOTE: OptGuard does NOT guarantee that it will always detect C0/C1
10089 : continuity violations.
10090 :
10091 : First, minor errors are hard to catch - say, a 0.0001 difference in
10092 : the model values at two sides of the gap may be due to discontinuity
10093 : of the model - or simply because the model has changed.
10094 :
10095 : Second, C1-violations are especially difficult to detect in a
10096 : noninvasive way. The optimizer usually performs very short steps
10097 : near the nonsmoothness, and differentiation usually introduces a
10098 : lot of numerical noise. It is hard to tell whether some tiny
10099 : discontinuity in the slope is due to real nonsmoothness or just due
10100 : to numerical noise alone.
10101 :
10102 : Our top priority was to avoid false positives, so in some rare cases
10103 : minor errors may went unnoticed (however, in most cases they can be
10104 : spotted with restart from different initial point).
10105 :
10106 : INPUT PARAMETERS:
10107 : state - algorithm state
10108 : level - monitoring level:
10109 : * 0 - monitoring is disabled
10110 : * 1 - noninvasive low-overhead monitoring; function values
10111 : and/or gradients are recorded, but OptGuard does not
10112 : try to perform additional evaluations in order to
10113 : get more information about suspicious locations.
10114 : This kind of monitoring does not work well with SQP
10115 : because SQP solver needs just 1-2 function evaluations
10116 : per step, which is not enough for OptGuard to make
10117 : any conclusions.
10118 :
10119 : === EXPLANATION ==========================================================
10120 :
10121 : One major source of headache during optimization is the possibility of
10122 : the coding errors in the target function/constraints (or their gradients).
10123 : Such errors most often manifest themselves as discontinuity or
10124 : nonsmoothness of the target/constraints.
10125 :
10126 : Another frequent situation is when you try to optimize something involving
10127 : lots of min() and max() operations, i.e. nonsmooth target. Although not a
10128 : coding error, it is nonsmoothness anyway - and smooth optimizers usually
10129 : stop right after encountering nonsmoothness, well before reaching solution.
10130 :
10131 : OptGuard integrity checker helps you to catch such situations: it monitors
10132 : function values/gradients being passed to the optimizer and tries to
10133 : errors. Upon discovering suspicious pair of points it raises appropriate
10134 : flag (and allows you to continue optimization). When optimization is done,
10135 : you can study OptGuard result.
10136 :
10137 : -- ALGLIB --
10138 : Copyright 21.11.2018 by Bochkanov Sergey
10139 : *************************************************************************/
10140 : #if !defined(AE_NO_EXCEPTIONS)
10141 0 : void minnlcoptguardsmoothness(const minnlcstate &state, const xparams _xparams)
10142 : {
10143 : jmp_buf _break_jump;
10144 : alglib_impl::ae_state _alglib_env_state;
10145 : ae_int_t level;
10146 :
10147 0 : level = 1;
10148 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10149 0 : if( setjmp(_break_jump) )
10150 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10151 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10152 0 : if( _xparams.flags!=0x0 )
10153 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10154 0 : alglib_impl::minnlcoptguardsmoothness(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), level, &_alglib_env_state);
10155 :
10156 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10157 0 : return;
10158 : }
10159 : #endif
10160 :
10161 : /*************************************************************************
10162 : Results of OptGuard integrity check, should be called after optimization
10163 : session is over.
10164 :
10165 : === PRIMARY REPORT =======================================================
10166 :
10167 : OptGuard performs several checks which are intended to catch common errors
10168 : in the implementation of nonlinear function/gradient:
10169 : * incorrect analytic gradient
10170 : * discontinuous (non-C0) target functions (constraints)
10171 : * nonsmooth (non-C1) target functions (constraints)
10172 :
10173 : Each of these checks is activated with appropriate function:
10174 : * minnlcoptguardgradient() for gradient verification
10175 : * minnlcoptguardsmoothness() for C0/C1 checks
10176 :
10177 : Following flags are set when these errors are suspected:
10178 : * rep.badgradsuspected, and additionally:
10179 : * rep.badgradfidx for specific function (Jacobian row) suspected
10180 : * rep.badgradvidx for specific variable (Jacobian column) suspected
10181 : * rep.badgradxbase, a point where gradient/Jacobian is tested
10182 : * rep.badgraduser, user-provided gradient/Jacobian
10183 : * rep.badgradnum, reference gradient/Jacobian obtained via numerical
10184 : differentiation
10185 : * rep.nonc0suspected, and additionally:
10186 : * rep.nonc0fidx - an index of specific function violating C0 continuity
10187 : * rep.nonc1suspected, and additionally
10188 : * rep.nonc1fidx - an index of specific function violating C1 continuity
10189 : Here function index 0 means target function, index 1 or higher denotes
10190 : nonlinear constraints.
10191 :
10192 : === ADDITIONAL REPORTS/LOGS ==============================================
10193 :
10194 : Several different tests are performed to catch C0/C1 errors, you can find
10195 : out specific test signaled error by looking to:
10196 : * rep.nonc0test0positive, for non-C0 test #0
10197 : * rep.nonc1test0positive, for non-C1 test #0
10198 : * rep.nonc1test1positive, for non-C1 test #1
10199 :
10200 : Additional information (including line search logs) can be obtained by
10201 : means of:
10202 : * minnlcoptguardnonc1test0results()
10203 : * minnlcoptguardnonc1test1results()
10204 : which return detailed error reports, specific points where discontinuities
10205 : were found, and so on.
10206 :
10207 : ==========================================================================
10208 :
10209 : INPUT PARAMETERS:
10210 : state - algorithm state
10211 :
10212 : OUTPUT PARAMETERS:
10213 : rep - generic OptGuard report; more detailed reports can be
10214 : retrieved with other functions.
10215 :
10216 : NOTE: false negatives (nonsmooth problems are not identified as nonsmooth
10217 : ones) are possible although unlikely.
10218 :
10219 : The reason is that you need to make several evaluations around
10220 : nonsmoothness in order to accumulate enough information about
10221 : function curvature. Say, if you start right from the nonsmooth point,
10222 : optimizer simply won't get enough data to understand what is going
10223 : wrong before it terminates due to abrupt changes in the derivative.
10224 : It is also possible that "unlucky" step will move us to the
10225 : termination too quickly.
10226 :
10227 : Our current approach is to have less than 0.1% false negatives in
10228 : our test examples (measured with multiple restarts from random
10229 : points), and to have exactly 0% false positives.
10230 :
10231 : -- ALGLIB --
10232 : Copyright 21.11.2018 by Bochkanov Sergey
10233 : *************************************************************************/
10234 0 : void minnlcoptguardresults(const minnlcstate &state, optguardreport &rep, const xparams _xparams)
10235 : {
10236 : jmp_buf _break_jump;
10237 : alglib_impl::ae_state _alglib_env_state;
10238 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10239 0 : if( setjmp(_break_jump) )
10240 : {
10241 : #if !defined(AE_NO_EXCEPTIONS)
10242 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10243 : #else
10244 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10245 : return;
10246 : #endif
10247 : }
10248 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10249 0 : if( _xparams.flags!=0x0 )
10250 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10251 0 : alglib_impl::minnlcoptguardresults(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), const_cast<alglib_impl::optguardreport*>(rep.c_ptr()), &_alglib_env_state);
10252 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10253 0 : return;
10254 : }
10255 :
10256 : /*************************************************************************
10257 : Detailed results of the OptGuard integrity check for nonsmoothness test #0
10258 :
10259 : Nonsmoothness (non-C1) test #0 studies function values (not gradient!)
10260 : obtained during line searches and monitors behavior of the directional
10261 : derivative estimate.
10262 :
10263 : This test is less powerful than test #1, but it does not depend on the
10264 : gradient values and thus it is more robust against artifacts introduced by
10265 : numerical differentiation.
10266 :
10267 : Two reports are returned:
10268 : * a "strongest" one, corresponding to line search which had highest
10269 : value of the nonsmoothness indicator
10270 : * a "longest" one, corresponding to line search which had more function
10271 : evaluations, and thus is more detailed
10272 :
10273 : In both cases following fields are returned:
10274 :
10275 : * positive - is TRUE when test flagged suspicious point; FALSE if test
10276 : did not notice anything (in the latter cases fields below are empty).
10277 : * fidx - is an index of the function (0 for target function, 1 or higher
10278 : for nonlinear constraints) which is suspected of being "non-C1"
10279 : * x0[], d[] - arrays of length N which store initial point and direction
10280 : for line search (d[] can be normalized, but does not have to)
10281 : * stp[], f[] - arrays of length CNT which store step lengths and function
10282 : values at these points; f[i] is evaluated in x0+stp[i]*d.
10283 : * stpidxa, stpidxb - we suspect that function violates C1 continuity
10284 : between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3,
10285 : with most likely position of the violation between stpidxa+1 and
10286 : stpidxa+2.
10287 :
10288 : ==========================================================================
10289 : = SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will
10290 : = see where C1 continuity is violated.
10291 : ==========================================================================
10292 :
10293 : INPUT PARAMETERS:
10294 : state - algorithm state
10295 :
10296 : OUTPUT PARAMETERS:
10297 : strrep - C1 test #0 "strong" report
10298 : lngrep - C1 test #0 "long" report
10299 :
10300 : -- ALGLIB --
10301 : Copyright 21.11.2018 by Bochkanov Sergey
10302 : *************************************************************************/
10303 0 : void minnlcoptguardnonc1test0results(const minnlcstate &state, optguardnonc1test0report &strrep, optguardnonc1test0report &lngrep, const xparams _xparams)
10304 : {
10305 : jmp_buf _break_jump;
10306 : alglib_impl::ae_state _alglib_env_state;
10307 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10308 0 : if( setjmp(_break_jump) )
10309 : {
10310 : #if !defined(AE_NO_EXCEPTIONS)
10311 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10312 : #else
10313 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10314 : return;
10315 : #endif
10316 : }
10317 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10318 0 : if( _xparams.flags!=0x0 )
10319 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10320 0 : alglib_impl::minnlcoptguardnonc1test0results(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), const_cast<alglib_impl::optguardnonc1test0report*>(strrep.c_ptr()), const_cast<alglib_impl::optguardnonc1test0report*>(lngrep.c_ptr()), &_alglib_env_state);
10321 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10322 0 : return;
10323 : }
10324 :
10325 : /*************************************************************************
10326 : Detailed results of the OptGuard integrity check for nonsmoothness test #1
10327 :
10328 : Nonsmoothness (non-C1) test #1 studies individual components of the
10329 : gradient computed during line search.
10330 :
10331 : When precise analytic gradient is provided this test is more powerful than
10332 : test #0 which works with function values and ignores user-provided
10333 : gradient. However, test #0 becomes more powerful when numerical
10334 : differentiation is employed (in such cases test #1 detects higher levels
10335 : of numerical noise and becomes too conservative).
10336 :
10337 : This test also tells specific components of the gradient which violate C1
10338 : continuity, which makes it more informative than #0, which just tells that
10339 : continuity is violated.
10340 :
10341 : Two reports are returned:
10342 : * a "strongest" one, corresponding to line search which had highest
10343 : value of the nonsmoothness indicator
10344 : * a "longest" one, corresponding to line search which had more function
10345 : evaluations, and thus is more detailed
10346 :
10347 : In both cases following fields are returned:
10348 :
10349 : * positive - is TRUE when test flagged suspicious point; FALSE if test
10350 : did not notice anything (in the latter cases fields below are empty).
10351 : * fidx - is an index of the function (0 for target function, 1 or higher
10352 : for nonlinear constraints) which is suspected of being "non-C1"
10353 : * vidx - is an index of the variable in [0,N) with nonsmooth derivative
10354 : * x0[], d[] - arrays of length N which store initial point and direction
10355 : for line search (d[] can be normalized, but does not have to)
10356 : * stp[], g[] - arrays of length CNT which store step lengths and gradient
10357 : values at these points; g[i] is evaluated in x0+stp[i]*d and contains
10358 : vidx-th component of the gradient.
10359 : * stpidxa, stpidxb - we suspect that function violates C1 continuity
10360 : between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3,
10361 : with most likely position of the violation between stpidxa+1 and
10362 : stpidxa+2.
10363 :
10364 : ==========================================================================
10365 : = SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will
10366 : = see where C1 continuity is violated.
10367 : ==========================================================================
10368 :
10369 : INPUT PARAMETERS:
10370 : state - algorithm state
10371 :
10372 : OUTPUT PARAMETERS:
10373 : strrep - C1 test #1 "strong" report
10374 : lngrep - C1 test #1 "long" report
10375 :
10376 : -- ALGLIB --
10377 : Copyright 21.11.2018 by Bochkanov Sergey
10378 : *************************************************************************/
10379 0 : void minnlcoptguardnonc1test1results(const minnlcstate &state, optguardnonc1test1report &strrep, optguardnonc1test1report &lngrep, const xparams _xparams)
10380 : {
10381 : jmp_buf _break_jump;
10382 : alglib_impl::ae_state _alglib_env_state;
10383 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10384 0 : if( setjmp(_break_jump) )
10385 : {
10386 : #if !defined(AE_NO_EXCEPTIONS)
10387 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10388 : #else
10389 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10390 : return;
10391 : #endif
10392 : }
10393 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10394 0 : if( _xparams.flags!=0x0 )
10395 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10396 0 : alglib_impl::minnlcoptguardnonc1test1results(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), const_cast<alglib_impl::optguardnonc1test1report*>(strrep.c_ptr()), const_cast<alglib_impl::optguardnonc1test1report*>(lngrep.c_ptr()), &_alglib_env_state);
10397 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10398 0 : return;
10399 : }
10400 :
10401 : /*************************************************************************
10402 : MinNLC results: the solution found, completion codes and additional
10403 : information.
10404 :
10405 : If you activated OptGuard integrity checking functionality and want to get
10406 : OptGuard report, it can be retrieved with:
10407 : * minnlcoptguardresults() - for a primary report about (a) suspected C0/C1
10408 : continuity violations and (b) errors in the analytic gradient.
10409 : * minnlcoptguardnonc1test0results() - for C1 continuity violation test #0,
10410 : detailed line search log
10411 : * minnlcoptguardnonc1test1results() - for C1 continuity violation test #1,
10412 : detailed line search log
10413 :
10414 : INPUT PARAMETERS:
10415 : State - algorithm state
10416 :
10417 : OUTPUT PARAMETERS:
10418 : X - array[0..N-1], solution
10419 : Rep - optimization report, contains information about completion
10420 : code, constraint violation at the solution and so on.
10421 :
10422 : You should check rep.terminationtype in order to
10423 : distinguish successful termination from unsuccessful one:
10424 :
10425 : === FAILURE CODES ===
10426 : * -8 internal integrity control detected infinite or
10427 : NAN values in function/gradient. Abnormal
10428 : termination signalled.
10429 : * -3 box constraints are infeasible.
10430 : Note: infeasibility of non-box constraints does
10431 : NOT trigger emergency completion; you have
10432 : to examine rep.bcerr/rep.lcerr/rep.nlcerr to
10433 : detect possibly inconsistent constraints.
10434 :
10435 : === SUCCESS CODES ===
10436 : * 2 scaled step is no more than EpsX.
10437 : * 5 MaxIts steps were taken.
10438 : * 8 user requested algorithm termination via
10439 : minnlcrequesttermination(), last accepted point is
10440 : returned.
10441 :
10442 : More information about fields of this structure can be
10443 : found in the comments on minnlcreport datatype.
10444 :
10445 : -- ALGLIB --
10446 : Copyright 06.06.2014 by Bochkanov Sergey
10447 : *************************************************************************/
10448 0 : void minnlcresults(const minnlcstate &state, real_1d_array &x, minnlcreport &rep, const xparams _xparams)
10449 : {
10450 : jmp_buf _break_jump;
10451 : alglib_impl::ae_state _alglib_env_state;
10452 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10453 0 : if( setjmp(_break_jump) )
10454 : {
10455 : #if !defined(AE_NO_EXCEPTIONS)
10456 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10457 : #else
10458 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10459 : return;
10460 : #endif
10461 : }
10462 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10463 0 : if( _xparams.flags!=0x0 )
10464 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10465 0 : alglib_impl::minnlcresults(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minnlcreport*>(rep.c_ptr()), &_alglib_env_state);
10466 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10467 0 : return;
10468 : }
10469 :
10470 : /*************************************************************************
10471 : NLC results
10472 :
10473 : Buffered implementation of MinNLCResults() which uses pre-allocated buffer
10474 : to store X[]. If buffer size is too small, it resizes buffer. It is
10475 : intended to be used in the inner cycles of performance critical algorithms
10476 : where array reallocation penalty is too large to be ignored.
10477 :
10478 : -- ALGLIB --
10479 : Copyright 28.11.2010 by Bochkanov Sergey
10480 : *************************************************************************/
10481 0 : void minnlcresultsbuf(const minnlcstate &state, real_1d_array &x, minnlcreport &rep, const xparams _xparams)
10482 : {
10483 : jmp_buf _break_jump;
10484 : alglib_impl::ae_state _alglib_env_state;
10485 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10486 0 : if( setjmp(_break_jump) )
10487 : {
10488 : #if !defined(AE_NO_EXCEPTIONS)
10489 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10490 : #else
10491 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10492 : return;
10493 : #endif
10494 : }
10495 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10496 0 : if( _xparams.flags!=0x0 )
10497 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10498 0 : alglib_impl::minnlcresultsbuf(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minnlcreport*>(rep.c_ptr()), &_alglib_env_state);
10499 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10500 0 : return;
10501 : }
10502 :
10503 : /*************************************************************************
10504 : This subroutine submits request for termination of running optimizer. It
10505 : should be called from user-supplied callback when user decides that it is
10506 : time to "smoothly" terminate optimization process. As result, optimizer
10507 : stops at point which was "current accepted" when termination request was
10508 : submitted and returns error code 8 (successful termination).
10509 :
10510 : INPUT PARAMETERS:
10511 : State - optimizer structure
10512 :
10513 : NOTE: after request for termination optimizer may perform several
10514 : additional calls to user-supplied callbacks. It does NOT guarantee
10515 : to stop immediately - it just guarantees that these additional calls
10516 : will be discarded later.
10517 :
10518 : NOTE: calling this function on optimizer which is NOT running will have no
10519 : effect.
10520 :
10521 : NOTE: multiple calls to this function are possible. First call is counted,
10522 : subsequent calls are silently ignored.
10523 :
10524 : -- ALGLIB --
10525 : Copyright 08.10.2014 by Bochkanov Sergey
10526 : *************************************************************************/
10527 0 : void minnlcrequesttermination(const minnlcstate &state, const xparams _xparams)
10528 : {
10529 : jmp_buf _break_jump;
10530 : alglib_impl::ae_state _alglib_env_state;
10531 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10532 0 : if( setjmp(_break_jump) )
10533 : {
10534 : #if !defined(AE_NO_EXCEPTIONS)
10535 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10536 : #else
10537 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10538 : return;
10539 : #endif
10540 : }
10541 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10542 0 : if( _xparams.flags!=0x0 )
10543 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10544 0 : alglib_impl::minnlcrequesttermination(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), &_alglib_env_state);
10545 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10546 0 : return;
10547 : }
10548 :
10549 : /*************************************************************************
10550 : This subroutine restarts algorithm from new point.
10551 : All optimization parameters (including constraints) are left unchanged.
10552 :
10553 : This function allows to solve multiple optimization problems (which
10554 : must have same number of dimensions) without object reallocation penalty.
10555 :
10556 : INPUT PARAMETERS:
10557 : State - structure previously allocated with MinNLCCreate call.
10558 : X - new starting point.
10559 :
10560 : -- ALGLIB --
10561 : Copyright 28.11.2010 by Bochkanov Sergey
10562 : *************************************************************************/
10563 0 : void minnlcrestartfrom(const minnlcstate &state, const real_1d_array &x, const xparams _xparams)
10564 : {
10565 : jmp_buf _break_jump;
10566 : alglib_impl::ae_state _alglib_env_state;
10567 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10568 0 : if( setjmp(_break_jump) )
10569 : {
10570 : #if !defined(AE_NO_EXCEPTIONS)
10571 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10572 : #else
10573 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10574 : return;
10575 : #endif
10576 : }
10577 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10578 0 : if( _xparams.flags!=0x0 )
10579 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10580 0 : alglib_impl::minnlcrestartfrom(const_cast<alglib_impl::minnlcstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
10581 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10582 0 : return;
10583 : }
10584 : #endif
10585 :
10586 : #if defined(AE_COMPILE_MINBC) || !defined(AE_PARTIAL_BUILD)
10587 : /*************************************************************************
10588 : This object stores nonlinear optimizer state.
10589 : You should use functions provided by MinBC subpackage to work with this
10590 : object
10591 : *************************************************************************/
10592 0 : _minbcstate_owner::_minbcstate_owner()
10593 : {
10594 : jmp_buf _break_jump;
10595 : alglib_impl::ae_state _state;
10596 :
10597 0 : alglib_impl::ae_state_init(&_state);
10598 0 : if( setjmp(_break_jump) )
10599 : {
10600 0 : if( p_struct!=NULL )
10601 : {
10602 0 : alglib_impl::_minbcstate_destroy(p_struct);
10603 0 : alglib_impl::ae_free(p_struct);
10604 : }
10605 0 : p_struct = NULL;
10606 : #if !defined(AE_NO_EXCEPTIONS)
10607 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
10608 : #else
10609 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
10610 : return;
10611 : #endif
10612 : }
10613 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
10614 0 : p_struct = NULL;
10615 0 : p_struct = (alglib_impl::minbcstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minbcstate), &_state);
10616 0 : memset(p_struct, 0, sizeof(alglib_impl::minbcstate));
10617 0 : alglib_impl::_minbcstate_init(p_struct, &_state, ae_false);
10618 0 : ae_state_clear(&_state);
10619 0 : }
10620 :
10621 0 : _minbcstate_owner::_minbcstate_owner(const _minbcstate_owner &rhs)
10622 : {
10623 : jmp_buf _break_jump;
10624 : alglib_impl::ae_state _state;
10625 :
10626 0 : alglib_impl::ae_state_init(&_state);
10627 0 : if( setjmp(_break_jump) )
10628 : {
10629 0 : if( p_struct!=NULL )
10630 : {
10631 0 : alglib_impl::_minbcstate_destroy(p_struct);
10632 0 : alglib_impl::ae_free(p_struct);
10633 : }
10634 0 : p_struct = NULL;
10635 : #if !defined(AE_NO_EXCEPTIONS)
10636 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
10637 : #else
10638 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
10639 : return;
10640 : #endif
10641 : }
10642 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
10643 0 : p_struct = NULL;
10644 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minbcstate copy constructor failure (source is not initialized)", &_state);
10645 0 : p_struct = (alglib_impl::minbcstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minbcstate), &_state);
10646 0 : memset(p_struct, 0, sizeof(alglib_impl::minbcstate));
10647 0 : alglib_impl::_minbcstate_init_copy(p_struct, const_cast<alglib_impl::minbcstate*>(rhs.p_struct), &_state, ae_false);
10648 0 : ae_state_clear(&_state);
10649 0 : }
10650 :
10651 0 : _minbcstate_owner& _minbcstate_owner::operator=(const _minbcstate_owner &rhs)
10652 : {
10653 0 : if( this==&rhs )
10654 0 : return *this;
10655 : jmp_buf _break_jump;
10656 : alglib_impl::ae_state _state;
10657 :
10658 0 : alglib_impl::ae_state_init(&_state);
10659 0 : if( setjmp(_break_jump) )
10660 : {
10661 : #if !defined(AE_NO_EXCEPTIONS)
10662 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
10663 : #else
10664 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
10665 : return *this;
10666 : #endif
10667 : }
10668 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
10669 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minbcstate assignment constructor failure (destination is not initialized)", &_state);
10670 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minbcstate assignment constructor failure (source is not initialized)", &_state);
10671 0 : alglib_impl::_minbcstate_destroy(p_struct);
10672 0 : memset(p_struct, 0, sizeof(alglib_impl::minbcstate));
10673 0 : alglib_impl::_minbcstate_init_copy(p_struct, const_cast<alglib_impl::minbcstate*>(rhs.p_struct), &_state, ae_false);
10674 0 : ae_state_clear(&_state);
10675 0 : return *this;
10676 : }
10677 :
10678 0 : _minbcstate_owner::~_minbcstate_owner()
10679 : {
10680 0 : if( p_struct!=NULL )
10681 : {
10682 0 : alglib_impl::_minbcstate_destroy(p_struct);
10683 0 : ae_free(p_struct);
10684 : }
10685 0 : }
10686 :
10687 0 : alglib_impl::minbcstate* _minbcstate_owner::c_ptr()
10688 : {
10689 0 : return p_struct;
10690 : }
10691 :
10692 0 : alglib_impl::minbcstate* _minbcstate_owner::c_ptr() const
10693 : {
10694 0 : return const_cast<alglib_impl::minbcstate*>(p_struct);
10695 : }
10696 0 : minbcstate::minbcstate() : _minbcstate_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)
10697 : {
10698 0 : }
10699 :
10700 0 : minbcstate::minbcstate(const minbcstate &rhs):_minbcstate_owner(rhs) ,needf(p_struct->needf),needfg(p_struct->needfg),xupdated(p_struct->xupdated),f(p_struct->f),g(&p_struct->g),x(&p_struct->x)
10701 : {
10702 0 : }
10703 :
10704 0 : minbcstate& minbcstate::operator=(const minbcstate &rhs)
10705 : {
10706 0 : if( this==&rhs )
10707 0 : return *this;
10708 0 : _minbcstate_owner::operator=(rhs);
10709 0 : return *this;
10710 : }
10711 :
10712 0 : minbcstate::~minbcstate()
10713 : {
10714 0 : }
10715 :
10716 :
10717 : /*************************************************************************
10718 : This structure stores optimization report:
10719 : * iterationscount number of iterations
10720 : * nfev number of gradient evaluations
10721 : * terminationtype termination type (see below)
10722 :
10723 : TERMINATION CODES
10724 :
10725 : terminationtype field contains completion code, which can be:
10726 : -8 internal integrity control detected infinite or NAN values in
10727 : function/gradient. Abnormal termination signalled.
10728 : -3 inconsistent constraints.
10729 : 1 relative function improvement is no more than EpsF.
10730 : 2 relative step is no more than EpsX.
10731 : 4 gradient norm is no more than EpsG
10732 : 5 MaxIts steps was taken
10733 : 7 stopping conditions are too stringent,
10734 : further improvement is impossible,
10735 : X contains best point found so far.
10736 : 8 terminated by user who called minbcrequesttermination(). X contains
10737 : point which was "current accepted" when termination request was
10738 : submitted.
10739 : *************************************************************************/
10740 0 : _minbcreport_owner::_minbcreport_owner()
10741 : {
10742 : jmp_buf _break_jump;
10743 : alglib_impl::ae_state _state;
10744 :
10745 0 : alglib_impl::ae_state_init(&_state);
10746 0 : if( setjmp(_break_jump) )
10747 : {
10748 0 : if( p_struct!=NULL )
10749 : {
10750 0 : alglib_impl::_minbcreport_destroy(p_struct);
10751 0 : alglib_impl::ae_free(p_struct);
10752 : }
10753 0 : p_struct = NULL;
10754 : #if !defined(AE_NO_EXCEPTIONS)
10755 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
10756 : #else
10757 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
10758 : return;
10759 : #endif
10760 : }
10761 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
10762 0 : p_struct = NULL;
10763 0 : p_struct = (alglib_impl::minbcreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minbcreport), &_state);
10764 0 : memset(p_struct, 0, sizeof(alglib_impl::minbcreport));
10765 0 : alglib_impl::_minbcreport_init(p_struct, &_state, ae_false);
10766 0 : ae_state_clear(&_state);
10767 0 : }
10768 :
10769 0 : _minbcreport_owner::_minbcreport_owner(const _minbcreport_owner &rhs)
10770 : {
10771 : jmp_buf _break_jump;
10772 : alglib_impl::ae_state _state;
10773 :
10774 0 : alglib_impl::ae_state_init(&_state);
10775 0 : if( setjmp(_break_jump) )
10776 : {
10777 0 : if( p_struct!=NULL )
10778 : {
10779 0 : alglib_impl::_minbcreport_destroy(p_struct);
10780 0 : alglib_impl::ae_free(p_struct);
10781 : }
10782 0 : p_struct = NULL;
10783 : #if !defined(AE_NO_EXCEPTIONS)
10784 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
10785 : #else
10786 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
10787 : return;
10788 : #endif
10789 : }
10790 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
10791 0 : p_struct = NULL;
10792 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minbcreport copy constructor failure (source is not initialized)", &_state);
10793 0 : p_struct = (alglib_impl::minbcreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minbcreport), &_state);
10794 0 : memset(p_struct, 0, sizeof(alglib_impl::minbcreport));
10795 0 : alglib_impl::_minbcreport_init_copy(p_struct, const_cast<alglib_impl::minbcreport*>(rhs.p_struct), &_state, ae_false);
10796 0 : ae_state_clear(&_state);
10797 0 : }
10798 :
10799 0 : _minbcreport_owner& _minbcreport_owner::operator=(const _minbcreport_owner &rhs)
10800 : {
10801 0 : if( this==&rhs )
10802 0 : return *this;
10803 : jmp_buf _break_jump;
10804 : alglib_impl::ae_state _state;
10805 :
10806 0 : alglib_impl::ae_state_init(&_state);
10807 0 : if( setjmp(_break_jump) )
10808 : {
10809 : #if !defined(AE_NO_EXCEPTIONS)
10810 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
10811 : #else
10812 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
10813 : return *this;
10814 : #endif
10815 : }
10816 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
10817 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minbcreport assignment constructor failure (destination is not initialized)", &_state);
10818 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minbcreport assignment constructor failure (source is not initialized)", &_state);
10819 0 : alglib_impl::_minbcreport_destroy(p_struct);
10820 0 : memset(p_struct, 0, sizeof(alglib_impl::minbcreport));
10821 0 : alglib_impl::_minbcreport_init_copy(p_struct, const_cast<alglib_impl::minbcreport*>(rhs.p_struct), &_state, ae_false);
10822 0 : ae_state_clear(&_state);
10823 0 : return *this;
10824 : }
10825 :
10826 0 : _minbcreport_owner::~_minbcreport_owner()
10827 : {
10828 0 : if( p_struct!=NULL )
10829 : {
10830 0 : alglib_impl::_minbcreport_destroy(p_struct);
10831 0 : ae_free(p_struct);
10832 : }
10833 0 : }
10834 :
10835 0 : alglib_impl::minbcreport* _minbcreport_owner::c_ptr()
10836 : {
10837 0 : return p_struct;
10838 : }
10839 :
10840 0 : alglib_impl::minbcreport* _minbcreport_owner::c_ptr() const
10841 : {
10842 0 : return const_cast<alglib_impl::minbcreport*>(p_struct);
10843 : }
10844 0 : minbcreport::minbcreport() : _minbcreport_owner() ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),varidx(p_struct->varidx),terminationtype(p_struct->terminationtype)
10845 : {
10846 0 : }
10847 :
10848 0 : minbcreport::minbcreport(const minbcreport &rhs):_minbcreport_owner(rhs) ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),varidx(p_struct->varidx),terminationtype(p_struct->terminationtype)
10849 : {
10850 0 : }
10851 :
10852 0 : minbcreport& minbcreport::operator=(const minbcreport &rhs)
10853 : {
10854 0 : if( this==&rhs )
10855 0 : return *this;
10856 0 : _minbcreport_owner::operator=(rhs);
10857 0 : return *this;
10858 : }
10859 :
10860 0 : minbcreport::~minbcreport()
10861 : {
10862 0 : }
10863 :
10864 : /*************************************************************************
10865 : BOX CONSTRAINED OPTIMIZATION
10866 : WITH FAST ACTIVATION OF MULTIPLE BOX CONSTRAINTS
10867 :
10868 : DESCRIPTION:
10869 : The subroutine minimizes function F(x) of N arguments subject to box
10870 : constraints (with some of box constraints actually being equality ones).
10871 :
10872 : This optimizer uses algorithm similar to that of MinBLEIC (optimizer with
10873 : general linear constraints), but presence of box-only constraints allows
10874 : us to use faster constraint activation strategies. On large-scale problems,
10875 : with multiple constraints active at the solution, this optimizer can be
10876 : several times faster than BLEIC.
10877 :
10878 : REQUIREMENTS:
10879 : * user must provide function value and gradient
10880 : * starting point X0 must be feasible or
10881 : not too far away from the feasible set
10882 : * grad(f) must be Lipschitz continuous on a level set:
10883 : L = { x : f(x)<=f(x0) }
10884 : * function must be defined everywhere on the feasible set F
10885 :
10886 : USAGE:
10887 :
10888 : Constrained optimization if far more complex than the unconstrained one.
10889 : Here we give very brief outline of the BC optimizer. We strongly recommend
10890 : you to read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide
10891 : on optimization, which is available at http://www.alglib.net/optimization/
10892 :
10893 : 1. User initializes algorithm state with MinBCCreate() call
10894 :
10895 : 2. USer adds box constraints by calling MinBCSetBC() function.
10896 :
10897 : 3. User sets stopping conditions with MinBCSetCond().
10898 :
10899 : 4. User calls MinBCOptimize() function which takes algorithm state and
10900 : pointer (delegate, etc.) to callback function which calculates F/G.
10901 :
10902 : 5. User calls MinBCResults() to get solution
10903 :
10904 : 6. Optionally user may call MinBCRestartFrom() to solve another problem
10905 : with same N but another starting point.
10906 : MinBCRestartFrom() allows to reuse already initialized structure.
10907 :
10908 :
10909 : INPUT PARAMETERS:
10910 : N - problem dimension, N>0:
10911 : * if given, only leading N elements of X are used
10912 : * if not given, automatically determined from size ofX
10913 : X - starting point, array[N]:
10914 : * it is better to set X to a feasible point
10915 : * but X can be infeasible, in which case algorithm will try
10916 : to find feasible point first, using X as initial
10917 : approximation.
10918 :
10919 : OUTPUT PARAMETERS:
10920 : State - structure stores algorithm state
10921 :
10922 : -- ALGLIB --
10923 : Copyright 28.11.2010 by Bochkanov Sergey
10924 : *************************************************************************/
10925 0 : void minbccreate(const ae_int_t n, const real_1d_array &x, minbcstate &state, const xparams _xparams)
10926 : {
10927 : jmp_buf _break_jump;
10928 : alglib_impl::ae_state _alglib_env_state;
10929 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10930 0 : if( setjmp(_break_jump) )
10931 : {
10932 : #if !defined(AE_NO_EXCEPTIONS)
10933 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10934 : #else
10935 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10936 : return;
10937 : #endif
10938 : }
10939 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10940 0 : if( _xparams.flags!=0x0 )
10941 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10942 0 : alglib_impl::minbccreate(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minbcstate*>(state.c_ptr()), &_alglib_env_state);
10943 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10944 0 : return;
10945 : }
10946 :
10947 : /*************************************************************************
10948 : BOX CONSTRAINED OPTIMIZATION
10949 : WITH FAST ACTIVATION OF MULTIPLE BOX CONSTRAINTS
10950 :
10951 : DESCRIPTION:
10952 : The subroutine minimizes function F(x) of N arguments subject to box
10953 : constraints (with some of box constraints actually being equality ones).
10954 :
10955 : This optimizer uses algorithm similar to that of MinBLEIC (optimizer with
10956 : general linear constraints), but presence of box-only constraints allows
10957 : us to use faster constraint activation strategies. On large-scale problems,
10958 : with multiple constraints active at the solution, this optimizer can be
10959 : several times faster than BLEIC.
10960 :
10961 : REQUIREMENTS:
10962 : * user must provide function value and gradient
10963 : * starting point X0 must be feasible or
10964 : not too far away from the feasible set
10965 : * grad(f) must be Lipschitz continuous on a level set:
10966 : L = { x : f(x)<=f(x0) }
10967 : * function must be defined everywhere on the feasible set F
10968 :
10969 : USAGE:
10970 :
10971 : Constrained optimization if far more complex than the unconstrained one.
10972 : Here we give very brief outline of the BC optimizer. We strongly recommend
10973 : you to read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide
10974 : on optimization, which is available at http://www.alglib.net/optimization/
10975 :
10976 : 1. User initializes algorithm state with MinBCCreate() call
10977 :
10978 : 2. USer adds box constraints by calling MinBCSetBC() function.
10979 :
10980 : 3. User sets stopping conditions with MinBCSetCond().
10981 :
10982 : 4. User calls MinBCOptimize() function which takes algorithm state and
10983 : pointer (delegate, etc.) to callback function which calculates F/G.
10984 :
10985 : 5. User calls MinBCResults() to get solution
10986 :
10987 : 6. Optionally user may call MinBCRestartFrom() to solve another problem
10988 : with same N but another starting point.
10989 : MinBCRestartFrom() allows to reuse already initialized structure.
10990 :
10991 :
10992 : INPUT PARAMETERS:
10993 : N - problem dimension, N>0:
10994 : * if given, only leading N elements of X are used
10995 : * if not given, automatically determined from size ofX
10996 : X - starting point, array[N]:
10997 : * it is better to set X to a feasible point
10998 : * but X can be infeasible, in which case algorithm will try
10999 : to find feasible point first, using X as initial
11000 : approximation.
11001 :
11002 : OUTPUT PARAMETERS:
11003 : State - structure stores algorithm state
11004 :
11005 : -- ALGLIB --
11006 : Copyright 28.11.2010 by Bochkanov Sergey
11007 : *************************************************************************/
11008 : #if !defined(AE_NO_EXCEPTIONS)
11009 0 : void minbccreate(const real_1d_array &x, minbcstate &state, const xparams _xparams)
11010 : {
11011 : jmp_buf _break_jump;
11012 : alglib_impl::ae_state _alglib_env_state;
11013 : ae_int_t n;
11014 :
11015 0 : n = x.length();
11016 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11017 0 : if( setjmp(_break_jump) )
11018 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11019 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11020 0 : if( _xparams.flags!=0x0 )
11021 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11022 0 : alglib_impl::minbccreate(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minbcstate*>(state.c_ptr()), &_alglib_env_state);
11023 :
11024 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11025 0 : return;
11026 : }
11027 : #endif
11028 :
11029 : /*************************************************************************
11030 : The subroutine is finite difference variant of MinBCCreate(). It uses
11031 : finite differences in order to differentiate target function.
11032 :
11033 : Description below contains information which is specific to this function
11034 : only. We recommend to read comments on MinBCCreate() in order to get
11035 : more information about creation of BC optimizer.
11036 :
11037 : INPUT PARAMETERS:
11038 : N - problem dimension, N>0:
11039 : * if given, only leading N elements of X are used
11040 : * if not given, automatically determined from size of X
11041 : X - starting point, array[0..N-1].
11042 : DiffStep- differentiation step, >0
11043 :
11044 : OUTPUT PARAMETERS:
11045 : State - structure which stores algorithm state
11046 :
11047 : NOTES:
11048 : 1. algorithm uses 4-point central formula for differentiation.
11049 : 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
11050 : S[] is scaling vector which can be set by MinBCSetScale() call.
11051 : 3. we recommend you to use moderate values of differentiation step. Too
11052 : large step will result in too large truncation errors, while too small
11053 : step will result in too large numerical errors. 1.0E-6 can be good
11054 : value to start with.
11055 : 4. Numerical differentiation is very inefficient - one gradient
11056 : calculation needs 4*N function evaluations. This function will work for
11057 : any N - either small (1...10), moderate (10...100) or large (100...).
11058 : However, performance penalty will be too severe for any N's except for
11059 : small ones.
11060 : We should also say that code which relies on numerical differentiation
11061 : is less robust and precise. CG needs exact gradient values. Imprecise
11062 : gradient may slow down convergence, especially on highly nonlinear
11063 : problems.
11064 : Thus we recommend to use this function for fast prototyping on small-
11065 : dimensional problems only, and to implement analytical gradient as soon
11066 : as possible.
11067 :
11068 : -- ALGLIB --
11069 : Copyright 16.05.2011 by Bochkanov Sergey
11070 : *************************************************************************/
11071 0 : void minbccreatef(const ae_int_t n, const real_1d_array &x, const double diffstep, minbcstate &state, const xparams _xparams)
11072 : {
11073 : jmp_buf _break_jump;
11074 : alglib_impl::ae_state _alglib_env_state;
11075 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11076 0 : if( setjmp(_break_jump) )
11077 : {
11078 : #if !defined(AE_NO_EXCEPTIONS)
11079 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11080 : #else
11081 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11082 : return;
11083 : #endif
11084 : }
11085 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11086 0 : if( _xparams.flags!=0x0 )
11087 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11088 0 : alglib_impl::minbccreatef(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), diffstep, const_cast<alglib_impl::minbcstate*>(state.c_ptr()), &_alglib_env_state);
11089 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11090 0 : return;
11091 : }
11092 :
11093 : /*************************************************************************
11094 : The subroutine is finite difference variant of MinBCCreate(). It uses
11095 : finite differences in order to differentiate target function.
11096 :
11097 : Description below contains information which is specific to this function
11098 : only. We recommend to read comments on MinBCCreate() in order to get
11099 : more information about creation of BC optimizer.
11100 :
11101 : INPUT PARAMETERS:
11102 : N - problem dimension, N>0:
11103 : * if given, only leading N elements of X are used
11104 : * if not given, automatically determined from size of X
11105 : X - starting point, array[0..N-1].
11106 : DiffStep- differentiation step, >0
11107 :
11108 : OUTPUT PARAMETERS:
11109 : State - structure which stores algorithm state
11110 :
11111 : NOTES:
11112 : 1. algorithm uses 4-point central formula for differentiation.
11113 : 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
11114 : S[] is scaling vector which can be set by MinBCSetScale() call.
11115 : 3. we recommend you to use moderate values of differentiation step. Too
11116 : large step will result in too large truncation errors, while too small
11117 : step will result in too large numerical errors. 1.0E-6 can be good
11118 : value to start with.
11119 : 4. Numerical differentiation is very inefficient - one gradient
11120 : calculation needs 4*N function evaluations. This function will work for
11121 : any N - either small (1...10), moderate (10...100) or large (100...).
11122 : However, performance penalty will be too severe for any N's except for
11123 : small ones.
11124 : We should also say that code which relies on numerical differentiation
11125 : is less robust and precise. CG needs exact gradient values. Imprecise
11126 : gradient may slow down convergence, especially on highly nonlinear
11127 : problems.
11128 : Thus we recommend to use this function for fast prototyping on small-
11129 : dimensional problems only, and to implement analytical gradient as soon
11130 : as possible.
11131 :
11132 : -- ALGLIB --
11133 : Copyright 16.05.2011 by Bochkanov Sergey
11134 : *************************************************************************/
11135 : #if !defined(AE_NO_EXCEPTIONS)
11136 0 : void minbccreatef(const real_1d_array &x, const double diffstep, minbcstate &state, const xparams _xparams)
11137 : {
11138 : jmp_buf _break_jump;
11139 : alglib_impl::ae_state _alglib_env_state;
11140 : ae_int_t n;
11141 :
11142 0 : n = x.length();
11143 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11144 0 : if( setjmp(_break_jump) )
11145 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11146 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11147 0 : if( _xparams.flags!=0x0 )
11148 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11149 0 : alglib_impl::minbccreatef(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), diffstep, const_cast<alglib_impl::minbcstate*>(state.c_ptr()), &_alglib_env_state);
11150 :
11151 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11152 0 : return;
11153 : }
11154 : #endif
11155 :
11156 : /*************************************************************************
11157 : This function sets boundary constraints for BC optimizer.
11158 :
11159 : Boundary constraints are inactive by default (after initial creation).
11160 : They are preserved after algorithm restart with MinBCRestartFrom().
11161 :
11162 : INPUT PARAMETERS:
11163 : State - structure stores algorithm state
11164 : BndL - lower bounds, array[N].
11165 : If some (all) variables are unbounded, you may specify
11166 : very small number or -INF.
11167 : BndU - upper bounds, array[N].
11168 : If some (all) variables are unbounded, you may specify
11169 : very large number or +INF.
11170 :
11171 : NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th
11172 : variable will be "frozen" at X[i]=BndL[i]=BndU[i].
11173 :
11174 : NOTE 2: this solver has following useful properties:
11175 : * bound constraints are always satisfied exactly
11176 : * function is evaluated only INSIDE area specified by bound constraints,
11177 : even when numerical differentiation is used (algorithm adjusts nodes
11178 : according to boundary constraints)
11179 :
11180 : -- ALGLIB --
11181 : Copyright 28.11.2010 by Bochkanov Sergey
11182 : *************************************************************************/
11183 0 : void minbcsetbc(const minbcstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams)
11184 : {
11185 : jmp_buf _break_jump;
11186 : alglib_impl::ae_state _alglib_env_state;
11187 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11188 0 : if( setjmp(_break_jump) )
11189 : {
11190 : #if !defined(AE_NO_EXCEPTIONS)
11191 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11192 : #else
11193 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11194 : return;
11195 : #endif
11196 : }
11197 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11198 0 : if( _xparams.flags!=0x0 )
11199 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11200 0 : alglib_impl::minbcsetbc(const_cast<alglib_impl::minbcstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(bndl.c_ptr()), const_cast<alglib_impl::ae_vector*>(bndu.c_ptr()), &_alglib_env_state);
11201 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11202 0 : return;
11203 : }
11204 :
11205 : /*************************************************************************
11206 : This function sets stopping conditions for the optimizer.
11207 :
11208 : INPUT PARAMETERS:
11209 : State - structure which stores algorithm state
11210 : EpsG - >=0
11211 : The subroutine finishes its work if the condition
11212 : |v|<EpsG is satisfied, where:
11213 : * |.| means Euclidian norm
11214 : * v - scaled gradient vector, v[i]=g[i]*s[i]
11215 : * g - gradient
11216 : * s - scaling coefficients set by MinBCSetScale()
11217 : EpsF - >=0
11218 : The subroutine finishes its work if on k+1-th iteration
11219 : the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
11220 : is satisfied.
11221 : EpsX - >=0
11222 : The subroutine finishes its work if on k+1-th iteration
11223 : the condition |v|<=EpsX is fulfilled, where:
11224 : * |.| means Euclidian norm
11225 : * v - scaled step vector, v[i]=dx[i]/s[i]
11226 : * dx - step vector, dx=X(k+1)-X(k)
11227 : * s - scaling coefficients set by MinBCSetScale()
11228 : MaxIts - maximum number of iterations. If MaxIts=0, the number of
11229 : iterations is unlimited.
11230 :
11231 : Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead
11232 : to automatic stopping criterion selection.
11233 :
11234 : NOTE: when SetCond() called with non-zero MaxIts, BC solver may perform
11235 : slightly more than MaxIts iterations. I.e., MaxIts sets non-strict
11236 : limit on iterations count.
11237 :
11238 : -- ALGLIB --
11239 : Copyright 28.11.2010 by Bochkanov Sergey
11240 : *************************************************************************/
11241 0 : void minbcsetcond(const minbcstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits, const xparams _xparams)
11242 : {
11243 : jmp_buf _break_jump;
11244 : alglib_impl::ae_state _alglib_env_state;
11245 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11246 0 : if( setjmp(_break_jump) )
11247 : {
11248 : #if !defined(AE_NO_EXCEPTIONS)
11249 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11250 : #else
11251 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11252 : return;
11253 : #endif
11254 : }
11255 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11256 0 : if( _xparams.flags!=0x0 )
11257 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11258 0 : alglib_impl::minbcsetcond(const_cast<alglib_impl::minbcstate*>(state.c_ptr()), epsg, epsf, epsx, maxits, &_alglib_env_state);
11259 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11260 0 : return;
11261 : }
11262 :
11263 : /*************************************************************************
11264 : This function sets scaling coefficients for BC optimizer.
11265 :
11266 : ALGLIB optimizers use scaling matrices to test stopping conditions (step
11267 : size and gradient are scaled before comparison with tolerances). Scale of
11268 : the I-th variable is a translation invariant measure of:
11269 : a) "how large" the variable is
11270 : b) how large the step should be to make significant changes in the function
11271 :
11272 : Scaling is also used by finite difference variant of the optimizer - step
11273 : along I-th axis is equal to DiffStep*S[I].
11274 :
11275 : In most optimizers (and in the BC too) scaling is NOT a form of
11276 : preconditioning. It just affects stopping conditions. You should set
11277 : preconditioner by separate call to one of the MinBCSetPrec...()
11278 : functions.
11279 :
11280 : There is a special preconditioning mode, however, which uses scaling
11281 : coefficients to form diagonal preconditioning matrix. You can turn this
11282 : mode on, if you want. But you should understand that scaling is not the
11283 : same thing as preconditioning - these are two different, although related
11284 : forms of tuning solver.
11285 :
11286 : INPUT PARAMETERS:
11287 : State - structure stores algorithm state
11288 : S - array[N], non-zero scaling coefficients
11289 : S[i] may be negative, sign doesn't matter.
11290 :
11291 : -- ALGLIB --
11292 : Copyright 14.01.2011 by Bochkanov Sergey
11293 : *************************************************************************/
11294 0 : void minbcsetscale(const minbcstate &state, const real_1d_array &s, const xparams _xparams)
11295 : {
11296 : jmp_buf _break_jump;
11297 : alglib_impl::ae_state _alglib_env_state;
11298 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11299 0 : if( setjmp(_break_jump) )
11300 : {
11301 : #if !defined(AE_NO_EXCEPTIONS)
11302 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11303 : #else
11304 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11305 : return;
11306 : #endif
11307 : }
11308 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11309 0 : if( _xparams.flags!=0x0 )
11310 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11311 0 : alglib_impl::minbcsetscale(const_cast<alglib_impl::minbcstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(s.c_ptr()), &_alglib_env_state);
11312 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11313 0 : return;
11314 : }
11315 :
11316 : /*************************************************************************
11317 : Modification of the preconditioner: preconditioning is turned off.
11318 :
11319 : INPUT PARAMETERS:
11320 : State - structure which stores algorithm state
11321 :
11322 : -- ALGLIB --
11323 : Copyright 13.10.2010 by Bochkanov Sergey
11324 : *************************************************************************/
11325 0 : void minbcsetprecdefault(const minbcstate &state, const xparams _xparams)
11326 : {
11327 : jmp_buf _break_jump;
11328 : alglib_impl::ae_state _alglib_env_state;
11329 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11330 0 : if( setjmp(_break_jump) )
11331 : {
11332 : #if !defined(AE_NO_EXCEPTIONS)
11333 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11334 : #else
11335 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11336 : return;
11337 : #endif
11338 : }
11339 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11340 0 : if( _xparams.flags!=0x0 )
11341 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11342 0 : alglib_impl::minbcsetprecdefault(const_cast<alglib_impl::minbcstate*>(state.c_ptr()), &_alglib_env_state);
11343 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11344 0 : return;
11345 : }
11346 :
11347 : /*************************************************************************
11348 : Modification of the preconditioner: diagonal of approximate Hessian is
11349 : used.
11350 :
11351 : INPUT PARAMETERS:
11352 : State - structure which stores algorithm state
11353 : D - diagonal of the approximate Hessian, array[0..N-1],
11354 : (if larger, only leading N elements are used).
11355 :
11356 : NOTE 1: D[i] should be positive. Exception will be thrown otherwise.
11357 :
11358 : NOTE 2: you should pass diagonal of approximate Hessian - NOT ITS INVERSE.
11359 :
11360 : -- ALGLIB --
11361 : Copyright 13.10.2010 by Bochkanov Sergey
11362 : *************************************************************************/
11363 0 : void minbcsetprecdiag(const minbcstate &state, const real_1d_array &d, const xparams _xparams)
11364 : {
11365 : jmp_buf _break_jump;
11366 : alglib_impl::ae_state _alglib_env_state;
11367 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11368 0 : if( setjmp(_break_jump) )
11369 : {
11370 : #if !defined(AE_NO_EXCEPTIONS)
11371 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11372 : #else
11373 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11374 : return;
11375 : #endif
11376 : }
11377 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11378 0 : if( _xparams.flags!=0x0 )
11379 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11380 0 : alglib_impl::minbcsetprecdiag(const_cast<alglib_impl::minbcstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(d.c_ptr()), &_alglib_env_state);
11381 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11382 0 : return;
11383 : }
11384 :
11385 : /*************************************************************************
11386 : Modification of the preconditioner: scale-based diagonal preconditioning.
11387 :
11388 : This preconditioning mode can be useful when you don't have approximate
11389 : diagonal of Hessian, but you know that your variables are badly scaled
11390 : (for example, one variable is in [1,10], and another in [1000,100000]),
11391 : and most part of the ill-conditioning comes from different scales of vars.
11392 :
11393 : In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2),
11394 : can greatly improve convergence.
11395 :
11396 : IMPRTANT: you should set scale of your variables with MinBCSetScale()
11397 : call (before or after MinBCSetPrecScale() call). Without knowledge of
11398 : the scale of your variables scale-based preconditioner will be just unit
11399 : matrix.
11400 :
11401 : INPUT PARAMETERS:
11402 : State - structure which stores algorithm state
11403 :
11404 : -- ALGLIB --
11405 : Copyright 13.10.2010 by Bochkanov Sergey
11406 : *************************************************************************/
11407 0 : void minbcsetprecscale(const minbcstate &state, const xparams _xparams)
11408 : {
11409 : jmp_buf _break_jump;
11410 : alglib_impl::ae_state _alglib_env_state;
11411 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11412 0 : if( setjmp(_break_jump) )
11413 : {
11414 : #if !defined(AE_NO_EXCEPTIONS)
11415 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11416 : #else
11417 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11418 : return;
11419 : #endif
11420 : }
11421 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11422 0 : if( _xparams.flags!=0x0 )
11423 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11424 0 : alglib_impl::minbcsetprecscale(const_cast<alglib_impl::minbcstate*>(state.c_ptr()), &_alglib_env_state);
11425 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11426 0 : return;
11427 : }
11428 :
11429 : /*************************************************************************
11430 : This function turns on/off reporting.
11431 :
11432 : INPUT PARAMETERS:
11433 : State - structure which stores algorithm state
11434 : NeedXRep- whether iteration reports are needed or not
11435 :
11436 : If NeedXRep is True, algorithm will call rep() callback function if it is
11437 : provided to MinBCOptimize().
11438 :
11439 : -- ALGLIB --
11440 : Copyright 28.11.2010 by Bochkanov Sergey
11441 : *************************************************************************/
11442 0 : void minbcsetxrep(const minbcstate &state, const bool needxrep, const xparams _xparams)
11443 : {
11444 : jmp_buf _break_jump;
11445 : alglib_impl::ae_state _alglib_env_state;
11446 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11447 0 : if( setjmp(_break_jump) )
11448 : {
11449 : #if !defined(AE_NO_EXCEPTIONS)
11450 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11451 : #else
11452 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11453 : return;
11454 : #endif
11455 : }
11456 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11457 0 : if( _xparams.flags!=0x0 )
11458 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11459 0 : alglib_impl::minbcsetxrep(const_cast<alglib_impl::minbcstate*>(state.c_ptr()), needxrep, &_alglib_env_state);
11460 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11461 0 : return;
11462 : }
11463 :
11464 : /*************************************************************************
11465 : This function sets maximum step length
11466 :
11467 : INPUT PARAMETERS:
11468 : State - structure which stores algorithm state
11469 : StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't
11470 : want to limit step length.
11471 :
11472 : Use this subroutine when you optimize target function which contains exp()
11473 : or other fast growing functions, and optimization algorithm makes too
11474 : large steps which lead to overflow. This function allows us to reject
11475 : steps that are too large (and therefore expose us to the possible
11476 : overflow) without actually calculating function value at the x+stp*d.
11477 :
11478 : -- ALGLIB --
11479 : Copyright 02.04.2010 by Bochkanov Sergey
11480 : *************************************************************************/
11481 0 : void minbcsetstpmax(const minbcstate &state, const double stpmax, const xparams _xparams)
11482 : {
11483 : jmp_buf _break_jump;
11484 : alglib_impl::ae_state _alglib_env_state;
11485 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11486 0 : if( setjmp(_break_jump) )
11487 : {
11488 : #if !defined(AE_NO_EXCEPTIONS)
11489 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11490 : #else
11491 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11492 : return;
11493 : #endif
11494 : }
11495 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11496 0 : if( _xparams.flags!=0x0 )
11497 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11498 0 : alglib_impl::minbcsetstpmax(const_cast<alglib_impl::minbcstate*>(state.c_ptr()), stpmax, &_alglib_env_state);
11499 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11500 0 : return;
11501 : }
11502 :
11503 : /*************************************************************************
11504 : This function provides reverse communication interface
11505 : Reverse communication interface is not documented or recommended to use.
11506 : See below for functions which provide better documented API
11507 : *************************************************************************/
11508 0 : bool minbciteration(const minbcstate &state, const xparams _xparams)
11509 : {
11510 : jmp_buf _break_jump;
11511 : alglib_impl::ae_state _alglib_env_state;
11512 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11513 0 : if( setjmp(_break_jump) )
11514 : {
11515 : #if !defined(AE_NO_EXCEPTIONS)
11516 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11517 : #else
11518 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11519 : return 0;
11520 : #endif
11521 : }
11522 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11523 0 : if( _xparams.flags!=0x0 )
11524 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11525 0 : ae_bool result = alglib_impl::minbciteration(const_cast<alglib_impl::minbcstate*>(state.c_ptr()), &_alglib_env_state);
11526 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11527 0 : return *(reinterpret_cast<bool*>(&result));
11528 : }
11529 :
11530 :
11531 0 : void minbcoptimize(minbcstate &state,
11532 : void (*func)(const real_1d_array &x, double &func, void *ptr),
11533 : void (*rep)(const real_1d_array &x, double func, void *ptr),
11534 : void *ptr,
11535 : const xparams _xparams)
11536 : {
11537 : jmp_buf _break_jump;
11538 : alglib_impl::ae_state _alglib_env_state;
11539 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11540 0 : if( setjmp(_break_jump) )
11541 : {
11542 : #if !defined(AE_NO_EXCEPTIONS)
11543 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11544 : #else
11545 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11546 : return;
11547 : #endif
11548 : }
11549 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11550 0 : if( _xparams.flags!=0x0 )
11551 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11552 0 : alglib_impl::ae_assert(func!=NULL, "ALGLIB: error in 'minbcoptimize()' (func is NULL)", &_alglib_env_state);
11553 0 : while( alglib_impl::minbciteration(state.c_ptr(), &_alglib_env_state) )
11554 : {
11555 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN
11556 0 : if( state.needf )
11557 : {
11558 0 : func(state.x, state.f, ptr);
11559 0 : continue;
11560 : }
11561 0 : if( state.xupdated )
11562 : {
11563 0 : if( rep!=NULL )
11564 0 : rep(state.x, state.f, ptr);
11565 0 : continue;
11566 : }
11567 0 : goto lbl_no_callback;
11568 0 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_END
11569 0 : lbl_no_callback:
11570 0 : alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minbcoptimize' (some derivatives were not provided?)", &_alglib_env_state);
11571 : }
11572 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11573 0 : }
11574 :
11575 :
11576 0 : void minbcoptimize(minbcstate &state,
11577 : void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr),
11578 : void (*rep)(const real_1d_array &x, double func, void *ptr),
11579 : void *ptr,
11580 : const xparams _xparams)
11581 : {
11582 : jmp_buf _break_jump;
11583 : alglib_impl::ae_state _alglib_env_state;
11584 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11585 0 : if( setjmp(_break_jump) )
11586 : {
11587 : #if !defined(AE_NO_EXCEPTIONS)
11588 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11589 : #else
11590 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11591 : return;
11592 : #endif
11593 : }
11594 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11595 0 : if( _xparams.flags!=0x0 )
11596 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11597 0 : alglib_impl::ae_assert(grad!=NULL, "ALGLIB: error in 'minbcoptimize()' (grad is NULL)", &_alglib_env_state);
11598 0 : while( alglib_impl::minbciteration(state.c_ptr(), &_alglib_env_state) )
11599 : {
11600 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN
11601 0 : if( state.needfg )
11602 : {
11603 0 : grad(state.x, state.f, state.g, ptr);
11604 0 : continue;
11605 : }
11606 0 : if( state.xupdated )
11607 : {
11608 0 : if( rep!=NULL )
11609 0 : rep(state.x, state.f, ptr);
11610 0 : continue;
11611 : }
11612 0 : goto lbl_no_callback;
11613 0 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_END
11614 0 : lbl_no_callback:
11615 0 : alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minbcoptimize' (some derivatives were not provided?)", &_alglib_env_state);
11616 : }
11617 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11618 0 : }
11619 :
11620 :
11621 :
11622 : /*************************************************************************
11623 : This function activates/deactivates verification of the user-supplied
11624 : analytic gradient.
11625 :
11626 : Upon activation of this option OptGuard integrity checker performs
11627 : numerical differentiation of your target function at the initial point
11628 : (note: future versions may also perform check at the final point) and
11629 : compares numerical gradient with analytic one provided by you.
11630 :
11631 : If difference is too large, an error flag is set and optimization session
11632 : continues. After optimization session is over, you can retrieve the report
11633 : which stores both gradients and specific components highlighted as
11634 : suspicious by the OptGuard.
11635 :
11636 : The primary OptGuard report can be retrieved with minbcoptguardresults().
11637 :
11638 : IMPORTANT: gradient check is a high-overhead option which will cost you
11639 : about 3*N additional function evaluations. In many cases it may
11640 : cost as much as the rest of the optimization session.
11641 :
11642 : YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO
11643 : CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY.
11644 :
11645 : NOTE: unlike previous incarnation of the gradient checking code, OptGuard
11646 : does NOT interrupt optimization even if it discovers bad gradient.
11647 :
11648 : INPUT PARAMETERS:
11649 : State - structure used to store algorithm state
11650 : TestStep - verification step used for numerical differentiation:
11651 : * TestStep=0 turns verification off
11652 : * TestStep>0 activates verification
11653 : You should carefully choose TestStep. Value which is
11654 : too large (so large that function behavior is non-
11655 : cubic at this scale) will lead to false alarms. Too
11656 : short step will result in rounding errors dominating
11657 : numerical derivative.
11658 :
11659 : You may use different step for different parameters by
11660 : means of setting scale with minbcsetscale().
11661 :
11662 : === EXPLANATION ==========================================================
11663 :
11664 : In order to verify gradient algorithm performs following steps:
11665 : * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i],
11666 : where X[i] is i-th component of the initial point and S[i] is a scale
11667 : of i-th parameter
11668 : * F(X) is evaluated at these trial points
11669 : * we perform one more evaluation in the middle point of the interval
11670 : * we build cubic model using function values and derivatives at trial
11671 : points and we compare its prediction with actual value in the middle
11672 : point
11673 :
11674 : -- ALGLIB --
11675 : Copyright 15.06.2014 by Bochkanov Sergey
11676 : *************************************************************************/
11677 0 : void minbcoptguardgradient(const minbcstate &state, const double teststep, const xparams _xparams)
11678 : {
11679 : jmp_buf _break_jump;
11680 : alglib_impl::ae_state _alglib_env_state;
11681 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11682 0 : if( setjmp(_break_jump) )
11683 : {
11684 : #if !defined(AE_NO_EXCEPTIONS)
11685 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11686 : #else
11687 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11688 : return;
11689 : #endif
11690 : }
11691 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11692 0 : if( _xparams.flags!=0x0 )
11693 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11694 0 : alglib_impl::minbcoptguardgradient(const_cast<alglib_impl::minbcstate*>(state.c_ptr()), teststep, &_alglib_env_state);
11695 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11696 0 : return;
11697 : }
11698 :
11699 : /*************************************************************************
11700 : This function activates/deactivates nonsmoothness monitoring option of
11701 : the OptGuard integrity checker. Smoothness monitor silently observes
11702 : solution process and tries to detect ill-posed problems, i.e. ones with:
11703 : a) discontinuous target function (non-C0)
11704 : b) nonsmooth target function (non-C1)
11705 :
11706 : Smoothness monitoring does NOT interrupt optimization even if it suspects
11707 : that your problem is nonsmooth. It just sets corresponding flags in the
11708 : OptGuard report which can be retrieved after optimization is over.
11709 :
11710 : Smoothness monitoring is a moderate overhead option which often adds less
11711 : than 1% to the optimizer running time. Thus, you can use it even for large
11712 : scale problems.
11713 :
11714 : NOTE: OptGuard does NOT guarantee that it will always detect C0/C1
11715 : continuity violations.
11716 :
11717 : First, minor errors are hard to catch - say, a 0.0001 difference in
11718 : the model values at two sides of the gap may be due to discontinuity
11719 : of the model - or simply because the model has changed.
11720 :
11721 : Second, C1-violations are especially difficult to detect in a
11722 : noninvasive way. The optimizer usually performs very short steps
11723 : near the nonsmoothness, and differentiation usually introduces a
11724 : lot of numerical noise. It is hard to tell whether some tiny
11725 : discontinuity in the slope is due to real nonsmoothness or just due
11726 : to numerical noise alone.
11727 :
11728 : Our top priority was to avoid false positives, so in some rare cases
11729 : minor errors may went unnoticed (however, in most cases they can be
11730 : spotted with restart from different initial point).
11731 :
11732 : INPUT PARAMETERS:
11733 : state - algorithm state
11734 : level - monitoring level:
11735 : * 0 - monitoring is disabled
11736 : * 1 - noninvasive low-overhead monitoring; function values
11737 : and/or gradients are recorded, but OptGuard does not
11738 : try to perform additional evaluations in order to
11739 : get more information about suspicious locations.
11740 :
11741 : === EXPLANATION ==========================================================
11742 :
11743 : One major source of headache during optimization is the possibility of
11744 : the coding errors in the target function/constraints (or their gradients).
11745 : Such errors most often manifest themselves as discontinuity or
11746 : nonsmoothness of the target/constraints.
11747 :
11748 : Another frequent situation is when you try to optimize something involving
11749 : lots of min() and max() operations, i.e. nonsmooth target. Although not a
11750 : coding error, it is nonsmoothness anyway - and smooth optimizers usually
11751 : stop right after encountering nonsmoothness, well before reaching solution.
11752 :
11753 : OptGuard integrity checker helps you to catch such situations: it monitors
11754 : function values/gradients being passed to the optimizer and tries to
11755 : errors. Upon discovering suspicious pair of points it raises appropriate
11756 : flag (and allows you to continue optimization). When optimization is done,
11757 : you can study OptGuard result.
11758 :
11759 : -- ALGLIB --
11760 : Copyright 21.11.2018 by Bochkanov Sergey
11761 : *************************************************************************/
11762 0 : void minbcoptguardsmoothness(const minbcstate &state, const ae_int_t level, const xparams _xparams)
11763 : {
11764 : jmp_buf _break_jump;
11765 : alglib_impl::ae_state _alglib_env_state;
11766 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11767 0 : if( setjmp(_break_jump) )
11768 : {
11769 : #if !defined(AE_NO_EXCEPTIONS)
11770 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11771 : #else
11772 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11773 : return;
11774 : #endif
11775 : }
11776 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11777 0 : if( _xparams.flags!=0x0 )
11778 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11779 0 : alglib_impl::minbcoptguardsmoothness(const_cast<alglib_impl::minbcstate*>(state.c_ptr()), level, &_alglib_env_state);
11780 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11781 0 : return;
11782 : }
11783 :
11784 : /*************************************************************************
11785 : This function activates/deactivates nonsmoothness monitoring option of
11786 : the OptGuard integrity checker. Smoothness monitor silently observes
11787 : solution process and tries to detect ill-posed problems, i.e. ones with:
11788 : a) discontinuous target function (non-C0)
11789 : b) nonsmooth target function (non-C1)
11790 :
11791 : Smoothness monitoring does NOT interrupt optimization even if it suspects
11792 : that your problem is nonsmooth. It just sets corresponding flags in the
11793 : OptGuard report which can be retrieved after optimization is over.
11794 :
11795 : Smoothness monitoring is a moderate overhead option which often adds less
11796 : than 1% to the optimizer running time. Thus, you can use it even for large
11797 : scale problems.
11798 :
11799 : NOTE: OptGuard does NOT guarantee that it will always detect C0/C1
11800 : continuity violations.
11801 :
11802 : First, minor errors are hard to catch - say, a 0.0001 difference in
11803 : the model values at two sides of the gap may be due to discontinuity
11804 : of the model - or simply because the model has changed.
11805 :
11806 : Second, C1-violations are especially difficult to detect in a
11807 : noninvasive way. The optimizer usually performs very short steps
11808 : near the nonsmoothness, and differentiation usually introduces a
11809 : lot of numerical noise. It is hard to tell whether some tiny
11810 : discontinuity in the slope is due to real nonsmoothness or just due
11811 : to numerical noise alone.
11812 :
11813 : Our top priority was to avoid false positives, so in some rare cases
11814 : minor errors may went unnoticed (however, in most cases they can be
11815 : spotted with restart from different initial point).
11816 :
11817 : INPUT PARAMETERS:
11818 : state - algorithm state
11819 : level - monitoring level:
11820 : * 0 - monitoring is disabled
11821 : * 1 - noninvasive low-overhead monitoring; function values
11822 : and/or gradients are recorded, but OptGuard does not
11823 : try to perform additional evaluations in order to
11824 : get more information about suspicious locations.
11825 :
11826 : === EXPLANATION ==========================================================
11827 :
11828 : One major source of headache during optimization is the possibility of
11829 : the coding errors in the target function/constraints (or their gradients).
11830 : Such errors most often manifest themselves as discontinuity or
11831 : nonsmoothness of the target/constraints.
11832 :
11833 : Another frequent situation is when you try to optimize something involving
11834 : lots of min() and max() operations, i.e. nonsmooth target. Although not a
11835 : coding error, it is nonsmoothness anyway - and smooth optimizers usually
11836 : stop right after encountering nonsmoothness, well before reaching solution.
11837 :
11838 : OptGuard integrity checker helps you to catch such situations: it monitors
11839 : function values/gradients being passed to the optimizer and tries to
11840 : errors. Upon discovering suspicious pair of points it raises appropriate
11841 : flag (and allows you to continue optimization). When optimization is done,
11842 : you can study OptGuard result.
11843 :
11844 : -- ALGLIB --
11845 : Copyright 21.11.2018 by Bochkanov Sergey
11846 : *************************************************************************/
11847 : #if !defined(AE_NO_EXCEPTIONS)
11848 0 : void minbcoptguardsmoothness(const minbcstate &state, const xparams _xparams)
11849 : {
11850 : jmp_buf _break_jump;
11851 : alglib_impl::ae_state _alglib_env_state;
11852 : ae_int_t level;
11853 :
11854 0 : level = 1;
11855 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11856 0 : if( setjmp(_break_jump) )
11857 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11858 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11859 0 : if( _xparams.flags!=0x0 )
11860 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11861 0 : alglib_impl::minbcoptguardsmoothness(const_cast<alglib_impl::minbcstate*>(state.c_ptr()), level, &_alglib_env_state);
11862 :
11863 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11864 0 : return;
11865 : }
11866 : #endif
11867 :
11868 : /*************************************************************************
11869 : Results of OptGuard integrity check, should be called after optimization
11870 : session is over.
11871 :
11872 : === PRIMARY REPORT =======================================================
11873 :
11874 : OptGuard performs several checks which are intended to catch common errors
11875 : in the implementation of nonlinear function/gradient:
11876 : * incorrect analytic gradient
11877 : * discontinuous (non-C0) target functions (constraints)
11878 : * nonsmooth (non-C1) target functions (constraints)
11879 :
11880 : Each of these checks is activated with appropriate function:
11881 : * minbcoptguardgradient() for gradient verification
11882 : * minbcoptguardsmoothness() for C0/C1 checks
11883 :
11884 : Following flags are set when these errors are suspected:
11885 : * rep.badgradsuspected, and additionally:
11886 : * rep.badgradvidx for specific variable (gradient element) suspected
11887 : * rep.badgradxbase, a point where gradient is tested
11888 : * rep.badgraduser, user-provided gradient (stored as 2D matrix with
11889 : single row in order to make report structure compatible with more
11890 : complex optimizers like MinNLC or MinLM)
11891 : * rep.badgradnum, reference gradient obtained via numerical
11892 : differentiation (stored as 2D matrix with single row in order to make
11893 : report structure compatible with more complex optimizers like MinNLC
11894 : or MinLM)
11895 : * rep.nonc0suspected
11896 : * rep.nonc1suspected
11897 :
11898 : === ADDITIONAL REPORTS/LOGS ==============================================
11899 :
11900 : Several different tests are performed to catch C0/C1 errors, you can find
11901 : out specific test signaled error by looking to:
11902 : * rep.nonc0test0positive, for non-C0 test #0
11903 : * rep.nonc1test0positive, for non-C1 test #0
11904 : * rep.nonc1test1positive, for non-C1 test #1
11905 :
11906 : Additional information (including line search logs) can be obtained by
11907 : means of:
11908 : * minbcoptguardnonc1test0results()
11909 : * minbcoptguardnonc1test1results()
11910 : which return detailed error reports, specific points where discontinuities
11911 : were found, and so on.
11912 :
11913 : ==========================================================================
11914 :
11915 : INPUT PARAMETERS:
11916 : state - algorithm state
11917 :
11918 : OUTPUT PARAMETERS:
11919 : rep - generic OptGuard report; more detailed reports can be
11920 : retrieved with other functions.
11921 :
11922 : NOTE: false negatives (nonsmooth problems are not identified as nonsmooth
11923 : ones) are possible although unlikely.
11924 :
11925 : The reason is that you need to make several evaluations around
11926 : nonsmoothness in order to accumulate enough information about
11927 : function curvature. Say, if you start right from the nonsmooth point,
11928 : optimizer simply won't get enough data to understand what is going
11929 : wrong before it terminates due to abrupt changes in the derivative.
11930 : It is also possible that "unlucky" step will move us to the
11931 : termination too quickly.
11932 :
11933 : Our current approach is to have less than 0.1% false negatives in
11934 : our test examples (measured with multiple restarts from random
11935 : points), and to have exactly 0% false positives.
11936 :
11937 : -- ALGLIB --
11938 : Copyright 21.11.2018 by Bochkanov Sergey
11939 : *************************************************************************/
11940 0 : void minbcoptguardresults(const minbcstate &state, optguardreport &rep, const xparams _xparams)
11941 : {
11942 : jmp_buf _break_jump;
11943 : alglib_impl::ae_state _alglib_env_state;
11944 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11945 0 : if( setjmp(_break_jump) )
11946 : {
11947 : #if !defined(AE_NO_EXCEPTIONS)
11948 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11949 : #else
11950 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11951 : return;
11952 : #endif
11953 : }
11954 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11955 0 : if( _xparams.flags!=0x0 )
11956 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11957 0 : alglib_impl::minbcoptguardresults(const_cast<alglib_impl::minbcstate*>(state.c_ptr()), const_cast<alglib_impl::optguardreport*>(rep.c_ptr()), &_alglib_env_state);
11958 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11959 0 : return;
11960 : }
11961 :
11962 : /*************************************************************************
11963 : Detailed results of the OptGuard integrity check for nonsmoothness test #0
11964 :
11965 : Nonsmoothness (non-C1) test #0 studies function values (not gradient!)
11966 : obtained during line searches and monitors behavior of the directional
11967 : derivative estimate.
11968 :
11969 : This test is less powerful than test #1, but it does not depend on the
11970 : gradient values and thus it is more robust against artifacts introduced by
11971 : numerical differentiation.
11972 :
11973 : Two reports are returned:
11974 : * a "strongest" one, corresponding to line search which had highest
11975 : value of the nonsmoothness indicator
11976 : * a "longest" one, corresponding to line search which had more function
11977 : evaluations, and thus is more detailed
11978 :
11979 : In both cases following fields are returned:
11980 :
11981 : * positive - is TRUE when test flagged suspicious point; FALSE if test
11982 : did not notice anything (in the latter cases fields below are empty).
11983 : * x0[], d[] - arrays of length N which store initial point and direction
11984 : for line search (d[] can be normalized, but does not have to)
11985 : * stp[], f[] - arrays of length CNT which store step lengths and function
11986 : values at these points; f[i] is evaluated in x0+stp[i]*d.
11987 : * stpidxa, stpidxb - we suspect that function violates C1 continuity
11988 : between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3,
11989 : with most likely position of the violation between stpidxa+1 and
11990 : stpidxa+2.
11991 :
11992 : ==========================================================================
11993 : = SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will
11994 : = see where C1 continuity is violated.
11995 : ==========================================================================
11996 :
11997 : INPUT PARAMETERS:
11998 : state - algorithm state
11999 :
12000 : OUTPUT PARAMETERS:
12001 : strrep - C1 test #0 "strong" report
12002 : lngrep - C1 test #0 "long" report
12003 :
12004 : -- ALGLIB --
12005 : Copyright 21.11.2018 by Bochkanov Sergey
12006 : *************************************************************************/
12007 0 : void minbcoptguardnonc1test0results(const minbcstate &state, optguardnonc1test0report &strrep, optguardnonc1test0report &lngrep, const xparams _xparams)
12008 : {
12009 : jmp_buf _break_jump;
12010 : alglib_impl::ae_state _alglib_env_state;
12011 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12012 0 : if( setjmp(_break_jump) )
12013 : {
12014 : #if !defined(AE_NO_EXCEPTIONS)
12015 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12016 : #else
12017 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12018 : return;
12019 : #endif
12020 : }
12021 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12022 0 : if( _xparams.flags!=0x0 )
12023 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12024 0 : alglib_impl::minbcoptguardnonc1test0results(const_cast<alglib_impl::minbcstate*>(state.c_ptr()), const_cast<alglib_impl::optguardnonc1test0report*>(strrep.c_ptr()), const_cast<alglib_impl::optguardnonc1test0report*>(lngrep.c_ptr()), &_alglib_env_state);
12025 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12026 0 : return;
12027 : }
12028 :
12029 : /*************************************************************************
12030 : Detailed results of the OptGuard integrity check for nonsmoothness test #1
12031 :
12032 : Nonsmoothness (non-C1) test #1 studies individual components of the
12033 : gradient computed during line search.
12034 :
12035 : When precise analytic gradient is provided this test is more powerful than
12036 : test #0 which works with function values and ignores user-provided
12037 : gradient. However, test #0 becomes more powerful when numerical
12038 : differentiation is employed (in such cases test #1 detects higher levels
12039 : of numerical noise and becomes too conservative).
12040 :
12041 : This test also tells specific components of the gradient which violate C1
12042 : continuity, which makes it more informative than #0, which just tells that
12043 : continuity is violated.
12044 :
12045 : Two reports are returned:
12046 : * a "strongest" one, corresponding to line search which had highest
12047 : value of the nonsmoothness indicator
12048 : * a "longest" one, corresponding to line search which had more function
12049 : evaluations, and thus is more detailed
12050 :
12051 : In both cases following fields are returned:
12052 :
12053 : * positive - is TRUE when test flagged suspicious point; FALSE if test
12054 : did not notice anything (in the latter cases fields below are empty).
12055 : * vidx - is an index of the variable in [0,N) with nonsmooth derivative
12056 : * x0[], d[] - arrays of length N which store initial point and direction
12057 : for line search (d[] can be normalized, but does not have to)
12058 : * stp[], g[] - arrays of length CNT which store step lengths and gradient
12059 : values at these points; g[i] is evaluated in x0+stp[i]*d and contains
12060 : vidx-th component of the gradient.
12061 : * stpidxa, stpidxb - we suspect that function violates C1 continuity
12062 : between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3,
12063 : with most likely position of the violation between stpidxa+1 and
12064 : stpidxa+2.
12065 :
12066 : ==========================================================================
12067 : = SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will
12068 : = see where C1 continuity is violated.
12069 : ==========================================================================
12070 :
12071 : INPUT PARAMETERS:
12072 : state - algorithm state
12073 :
12074 : OUTPUT PARAMETERS:
12075 : strrep - C1 test #1 "strong" report
12076 : lngrep - C1 test #1 "long" report
12077 :
12078 : -- ALGLIB --
12079 : Copyright 21.11.2018 by Bochkanov Sergey
12080 : *************************************************************************/
12081 0 : void minbcoptguardnonc1test1results(const minbcstate &state, optguardnonc1test1report &strrep, optguardnonc1test1report &lngrep, const xparams _xparams)
12082 : {
12083 : jmp_buf _break_jump;
12084 : alglib_impl::ae_state _alglib_env_state;
12085 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12086 0 : if( setjmp(_break_jump) )
12087 : {
12088 : #if !defined(AE_NO_EXCEPTIONS)
12089 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12090 : #else
12091 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12092 : return;
12093 : #endif
12094 : }
12095 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12096 0 : if( _xparams.flags!=0x0 )
12097 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12098 0 : alglib_impl::minbcoptguardnonc1test1results(const_cast<alglib_impl::minbcstate*>(state.c_ptr()), const_cast<alglib_impl::optguardnonc1test1report*>(strrep.c_ptr()), const_cast<alglib_impl::optguardnonc1test1report*>(lngrep.c_ptr()), &_alglib_env_state);
12099 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12100 0 : return;
12101 : }
12102 :
12103 : /*************************************************************************
12104 : BC results
12105 :
12106 : INPUT PARAMETERS:
12107 : State - algorithm state
12108 :
12109 : OUTPUT PARAMETERS:
12110 : X - array[0..N-1], solution
12111 : Rep - optimization report. You should check Rep.TerminationType
12112 : in order to distinguish successful termination from
12113 : unsuccessful one:
12114 : * -8 internal integrity control detected infinite or
12115 : NAN values in function/gradient. Abnormal
12116 : termination signalled.
12117 : * -3 inconsistent constraints.
12118 : * 1 relative function improvement is no more than EpsF.
12119 : * 2 scaled step is no more than EpsX.
12120 : * 4 scaled gradient norm is no more than EpsG.
12121 : * 5 MaxIts steps was taken
12122 : * 8 terminated by user who called minbcrequesttermination().
12123 : X contains point which was "current accepted" when
12124 : termination request was submitted.
12125 : More information about fields of this structure can be
12126 : found in the comments on MinBCReport datatype.
12127 :
12128 : -- ALGLIB --
12129 : Copyright 28.11.2010 by Bochkanov Sergey
12130 : *************************************************************************/
12131 0 : void minbcresults(const minbcstate &state, real_1d_array &x, minbcreport &rep, const xparams _xparams)
12132 : {
12133 : jmp_buf _break_jump;
12134 : alglib_impl::ae_state _alglib_env_state;
12135 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12136 0 : if( setjmp(_break_jump) )
12137 : {
12138 : #if !defined(AE_NO_EXCEPTIONS)
12139 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12140 : #else
12141 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12142 : return;
12143 : #endif
12144 : }
12145 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12146 0 : if( _xparams.flags!=0x0 )
12147 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12148 0 : alglib_impl::minbcresults(const_cast<alglib_impl::minbcstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minbcreport*>(rep.c_ptr()), &_alglib_env_state);
12149 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12150 0 : return;
12151 : }
12152 :
12153 : /*************************************************************************
12154 : BC results
12155 :
12156 : Buffered implementation of MinBCResults() which uses pre-allocated buffer
12157 : to store X[]. If buffer size is too small, it resizes buffer. It is
12158 : intended to be used in the inner cycles of performance critical algorithms
12159 : where array reallocation penalty is too large to be ignored.
12160 :
12161 : -- ALGLIB --
12162 : Copyright 28.11.2010 by Bochkanov Sergey
12163 : *************************************************************************/
12164 0 : void minbcresultsbuf(const minbcstate &state, real_1d_array &x, minbcreport &rep, const xparams _xparams)
12165 : {
12166 : jmp_buf _break_jump;
12167 : alglib_impl::ae_state _alglib_env_state;
12168 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12169 0 : if( setjmp(_break_jump) )
12170 : {
12171 : #if !defined(AE_NO_EXCEPTIONS)
12172 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12173 : #else
12174 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12175 : return;
12176 : #endif
12177 : }
12178 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12179 0 : if( _xparams.flags!=0x0 )
12180 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12181 0 : alglib_impl::minbcresultsbuf(const_cast<alglib_impl::minbcstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minbcreport*>(rep.c_ptr()), &_alglib_env_state);
12182 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12183 0 : return;
12184 : }
12185 :
12186 : /*************************************************************************
12187 : This subroutine restarts algorithm from new point.
12188 : All optimization parameters (including constraints) are left unchanged.
12189 :
12190 : This function allows to solve multiple optimization problems (which
12191 : must have same number of dimensions) without object reallocation penalty.
12192 :
12193 : INPUT PARAMETERS:
12194 : State - structure previously allocated with MinBCCreate call.
12195 : X - new starting point.
12196 :
12197 : -- ALGLIB --
12198 : Copyright 28.11.2010 by Bochkanov Sergey
12199 : *************************************************************************/
12200 0 : void minbcrestartfrom(const minbcstate &state, const real_1d_array &x, const xparams _xparams)
12201 : {
12202 : jmp_buf _break_jump;
12203 : alglib_impl::ae_state _alglib_env_state;
12204 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12205 0 : if( setjmp(_break_jump) )
12206 : {
12207 : #if !defined(AE_NO_EXCEPTIONS)
12208 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12209 : #else
12210 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12211 : return;
12212 : #endif
12213 : }
12214 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12215 0 : if( _xparams.flags!=0x0 )
12216 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12217 0 : alglib_impl::minbcrestartfrom(const_cast<alglib_impl::minbcstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
12218 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12219 0 : return;
12220 : }
12221 :
12222 : /*************************************************************************
12223 : This subroutine submits request for termination of running optimizer. It
12224 : should be called from user-supplied callback when user decides that it is
12225 : time to "smoothly" terminate optimization process. As result, optimizer
12226 : stops at point which was "current accepted" when termination request was
12227 : submitted and returns error code 8 (successful termination).
12228 :
12229 : INPUT PARAMETERS:
12230 : State - optimizer structure
12231 :
12232 : NOTE: after request for termination optimizer may perform several
12233 : additional calls to user-supplied callbacks. It does NOT guarantee
12234 : to stop immediately - it just guarantees that these additional calls
12235 : will be discarded later.
12236 :
12237 : NOTE: calling this function on optimizer which is NOT running will have no
12238 : effect.
12239 :
12240 : NOTE: multiple calls to this function are possible. First call is counted,
12241 : subsequent calls are silently ignored.
12242 :
12243 : -- ALGLIB --
12244 : Copyright 08.10.2014 by Bochkanov Sergey
12245 : *************************************************************************/
12246 0 : void minbcrequesttermination(const minbcstate &state, const xparams _xparams)
12247 : {
12248 : jmp_buf _break_jump;
12249 : alglib_impl::ae_state _alglib_env_state;
12250 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12251 0 : if( setjmp(_break_jump) )
12252 : {
12253 : #if !defined(AE_NO_EXCEPTIONS)
12254 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12255 : #else
12256 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12257 : return;
12258 : #endif
12259 : }
12260 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12261 0 : if( _xparams.flags!=0x0 )
12262 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12263 0 : alglib_impl::minbcrequesttermination(const_cast<alglib_impl::minbcstate*>(state.c_ptr()), &_alglib_env_state);
12264 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12265 0 : return;
12266 : }
12267 : #endif
12268 :
12269 : #if defined(AE_COMPILE_MINNS) || !defined(AE_PARTIAL_BUILD)
12270 : /*************************************************************************
12271 : This object stores nonlinear optimizer state.
12272 : You should use functions provided by MinNS subpackage to work with this
12273 : object
12274 : *************************************************************************/
12275 0 : _minnsstate_owner::_minnsstate_owner()
12276 : {
12277 : jmp_buf _break_jump;
12278 : alglib_impl::ae_state _state;
12279 :
12280 0 : alglib_impl::ae_state_init(&_state);
12281 0 : if( setjmp(_break_jump) )
12282 : {
12283 0 : if( p_struct!=NULL )
12284 : {
12285 0 : alglib_impl::_minnsstate_destroy(p_struct);
12286 0 : alglib_impl::ae_free(p_struct);
12287 : }
12288 0 : p_struct = NULL;
12289 : #if !defined(AE_NO_EXCEPTIONS)
12290 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
12291 : #else
12292 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
12293 : return;
12294 : #endif
12295 : }
12296 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
12297 0 : p_struct = NULL;
12298 0 : p_struct = (alglib_impl::minnsstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minnsstate), &_state);
12299 0 : memset(p_struct, 0, sizeof(alglib_impl::minnsstate));
12300 0 : alglib_impl::_minnsstate_init(p_struct, &_state, ae_false);
12301 0 : ae_state_clear(&_state);
12302 0 : }
12303 :
12304 0 : _minnsstate_owner::_minnsstate_owner(const _minnsstate_owner &rhs)
12305 : {
12306 : jmp_buf _break_jump;
12307 : alglib_impl::ae_state _state;
12308 :
12309 0 : alglib_impl::ae_state_init(&_state);
12310 0 : if( setjmp(_break_jump) )
12311 : {
12312 0 : if( p_struct!=NULL )
12313 : {
12314 0 : alglib_impl::_minnsstate_destroy(p_struct);
12315 0 : alglib_impl::ae_free(p_struct);
12316 : }
12317 0 : p_struct = NULL;
12318 : #if !defined(AE_NO_EXCEPTIONS)
12319 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
12320 : #else
12321 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
12322 : return;
12323 : #endif
12324 : }
12325 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
12326 0 : p_struct = NULL;
12327 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minnsstate copy constructor failure (source is not initialized)", &_state);
12328 0 : p_struct = (alglib_impl::minnsstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minnsstate), &_state);
12329 0 : memset(p_struct, 0, sizeof(alglib_impl::minnsstate));
12330 0 : alglib_impl::_minnsstate_init_copy(p_struct, const_cast<alglib_impl::minnsstate*>(rhs.p_struct), &_state, ae_false);
12331 0 : ae_state_clear(&_state);
12332 0 : }
12333 :
12334 0 : _minnsstate_owner& _minnsstate_owner::operator=(const _minnsstate_owner &rhs)
12335 : {
12336 0 : if( this==&rhs )
12337 0 : return *this;
12338 : jmp_buf _break_jump;
12339 : alglib_impl::ae_state _state;
12340 :
12341 0 : alglib_impl::ae_state_init(&_state);
12342 0 : if( setjmp(_break_jump) )
12343 : {
12344 : #if !defined(AE_NO_EXCEPTIONS)
12345 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
12346 : #else
12347 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
12348 : return *this;
12349 : #endif
12350 : }
12351 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
12352 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minnsstate assignment constructor failure (destination is not initialized)", &_state);
12353 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minnsstate assignment constructor failure (source is not initialized)", &_state);
12354 0 : alglib_impl::_minnsstate_destroy(p_struct);
12355 0 : memset(p_struct, 0, sizeof(alglib_impl::minnsstate));
12356 0 : alglib_impl::_minnsstate_init_copy(p_struct, const_cast<alglib_impl::minnsstate*>(rhs.p_struct), &_state, ae_false);
12357 0 : ae_state_clear(&_state);
12358 0 : return *this;
12359 : }
12360 :
12361 0 : _minnsstate_owner::~_minnsstate_owner()
12362 : {
12363 0 : if( p_struct!=NULL )
12364 : {
12365 0 : alglib_impl::_minnsstate_destroy(p_struct);
12366 0 : ae_free(p_struct);
12367 : }
12368 0 : }
12369 :
12370 0 : alglib_impl::minnsstate* _minnsstate_owner::c_ptr()
12371 : {
12372 0 : return p_struct;
12373 : }
12374 :
12375 0 : alglib_impl::minnsstate* _minnsstate_owner::c_ptr() const
12376 : {
12377 0 : return const_cast<alglib_impl::minnsstate*>(p_struct);
12378 : }
12379 0 : minnsstate::minnsstate() : _minnsstate_owner() ,needfi(p_struct->needfi),needfij(p_struct->needfij),xupdated(p_struct->xupdated),f(p_struct->f),fi(&p_struct->fi),j(&p_struct->j),x(&p_struct->x)
12380 : {
12381 0 : }
12382 :
12383 0 : minnsstate::minnsstate(const minnsstate &rhs):_minnsstate_owner(rhs) ,needfi(p_struct->needfi),needfij(p_struct->needfij),xupdated(p_struct->xupdated),f(p_struct->f),fi(&p_struct->fi),j(&p_struct->j),x(&p_struct->x)
12384 : {
12385 0 : }
12386 :
12387 0 : minnsstate& minnsstate::operator=(const minnsstate &rhs)
12388 : {
12389 0 : if( this==&rhs )
12390 0 : return *this;
12391 0 : _minnsstate_owner::operator=(rhs);
12392 0 : return *this;
12393 : }
12394 :
12395 0 : minnsstate::~minnsstate()
12396 : {
12397 0 : }
12398 :
12399 :
12400 : /*************************************************************************
12401 : This structure stores optimization report:
12402 : * IterationsCount total number of inner iterations
12403 : * NFEV number of gradient evaluations
12404 : * TerminationType termination type (see below)
12405 : * CErr maximum violation of all types of constraints
12406 : * LCErr maximum violation of linear constraints
12407 : * NLCErr maximum violation of nonlinear constraints
12408 :
12409 : TERMINATION CODES
12410 :
12411 : TerminationType field contains completion code, which can be:
12412 : -8 internal integrity control detected infinite or NAN values in
12413 : function/gradient. Abnormal termination signalled.
12414 : -3 box constraints are inconsistent
12415 : -1 inconsistent parameters were passed:
12416 : * penalty parameter for minnssetalgoags() is zero,
12417 : but we have nonlinear constraints set by minnssetnlc()
12418 : 2 sampling radius decreased below epsx
12419 : 5 MaxIts steps was taken
12420 : 7 stopping conditions are too stringent,
12421 : further improvement is impossible,
12422 : X contains best point found so far.
12423 : 8 User requested termination via MinNSRequestTermination()
12424 :
12425 : Other fields of this structure are not documented and should not be used!
12426 : *************************************************************************/
12427 0 : _minnsreport_owner::_minnsreport_owner()
12428 : {
12429 : jmp_buf _break_jump;
12430 : alglib_impl::ae_state _state;
12431 :
12432 0 : alglib_impl::ae_state_init(&_state);
12433 0 : if( setjmp(_break_jump) )
12434 : {
12435 0 : if( p_struct!=NULL )
12436 : {
12437 0 : alglib_impl::_minnsreport_destroy(p_struct);
12438 0 : alglib_impl::ae_free(p_struct);
12439 : }
12440 0 : p_struct = NULL;
12441 : #if !defined(AE_NO_EXCEPTIONS)
12442 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
12443 : #else
12444 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
12445 : return;
12446 : #endif
12447 : }
12448 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
12449 0 : p_struct = NULL;
12450 0 : p_struct = (alglib_impl::minnsreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minnsreport), &_state);
12451 0 : memset(p_struct, 0, sizeof(alglib_impl::minnsreport));
12452 0 : alglib_impl::_minnsreport_init(p_struct, &_state, ae_false);
12453 0 : ae_state_clear(&_state);
12454 0 : }
12455 :
12456 0 : _minnsreport_owner::_minnsreport_owner(const _minnsreport_owner &rhs)
12457 : {
12458 : jmp_buf _break_jump;
12459 : alglib_impl::ae_state _state;
12460 :
12461 0 : alglib_impl::ae_state_init(&_state);
12462 0 : if( setjmp(_break_jump) )
12463 : {
12464 0 : if( p_struct!=NULL )
12465 : {
12466 0 : alglib_impl::_minnsreport_destroy(p_struct);
12467 0 : alglib_impl::ae_free(p_struct);
12468 : }
12469 0 : p_struct = NULL;
12470 : #if !defined(AE_NO_EXCEPTIONS)
12471 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
12472 : #else
12473 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
12474 : return;
12475 : #endif
12476 : }
12477 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
12478 0 : p_struct = NULL;
12479 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minnsreport copy constructor failure (source is not initialized)", &_state);
12480 0 : p_struct = (alglib_impl::minnsreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minnsreport), &_state);
12481 0 : memset(p_struct, 0, sizeof(alglib_impl::minnsreport));
12482 0 : alglib_impl::_minnsreport_init_copy(p_struct, const_cast<alglib_impl::minnsreport*>(rhs.p_struct), &_state, ae_false);
12483 0 : ae_state_clear(&_state);
12484 0 : }
12485 :
12486 0 : _minnsreport_owner& _minnsreport_owner::operator=(const _minnsreport_owner &rhs)
12487 : {
12488 0 : if( this==&rhs )
12489 0 : return *this;
12490 : jmp_buf _break_jump;
12491 : alglib_impl::ae_state _state;
12492 :
12493 0 : alglib_impl::ae_state_init(&_state);
12494 0 : if( setjmp(_break_jump) )
12495 : {
12496 : #if !defined(AE_NO_EXCEPTIONS)
12497 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
12498 : #else
12499 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
12500 : return *this;
12501 : #endif
12502 : }
12503 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
12504 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minnsreport assignment constructor failure (destination is not initialized)", &_state);
12505 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minnsreport assignment constructor failure (source is not initialized)", &_state);
12506 0 : alglib_impl::_minnsreport_destroy(p_struct);
12507 0 : memset(p_struct, 0, sizeof(alglib_impl::minnsreport));
12508 0 : alglib_impl::_minnsreport_init_copy(p_struct, const_cast<alglib_impl::minnsreport*>(rhs.p_struct), &_state, ae_false);
12509 0 : ae_state_clear(&_state);
12510 0 : return *this;
12511 : }
12512 :
12513 0 : _minnsreport_owner::~_minnsreport_owner()
12514 : {
12515 0 : if( p_struct!=NULL )
12516 : {
12517 0 : alglib_impl::_minnsreport_destroy(p_struct);
12518 0 : ae_free(p_struct);
12519 : }
12520 0 : }
12521 :
12522 0 : alglib_impl::minnsreport* _minnsreport_owner::c_ptr()
12523 : {
12524 0 : return p_struct;
12525 : }
12526 :
12527 0 : alglib_impl::minnsreport* _minnsreport_owner::c_ptr() const
12528 : {
12529 0 : return const_cast<alglib_impl::minnsreport*>(p_struct);
12530 : }
12531 0 : minnsreport::minnsreport() : _minnsreport_owner() ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),cerr(p_struct->cerr),lcerr(p_struct->lcerr),nlcerr(p_struct->nlcerr),terminationtype(p_struct->terminationtype),varidx(p_struct->varidx),funcidx(p_struct->funcidx)
12532 : {
12533 0 : }
12534 :
12535 0 : minnsreport::minnsreport(const minnsreport &rhs):_minnsreport_owner(rhs) ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),cerr(p_struct->cerr),lcerr(p_struct->lcerr),nlcerr(p_struct->nlcerr),terminationtype(p_struct->terminationtype),varidx(p_struct->varidx),funcidx(p_struct->funcidx)
12536 : {
12537 0 : }
12538 :
12539 0 : minnsreport& minnsreport::operator=(const minnsreport &rhs)
12540 : {
12541 0 : if( this==&rhs )
12542 0 : return *this;
12543 0 : _minnsreport_owner::operator=(rhs);
12544 0 : return *this;
12545 : }
12546 :
12547 0 : minnsreport::~minnsreport()
12548 : {
12549 0 : }
12550 :
12551 : /*************************************************************************
12552 : NONSMOOTH NONCONVEX OPTIMIZATION
12553 : SUBJECT TO BOX/LINEAR/NONLINEAR-NONSMOOTH CONSTRAINTS
12554 :
12555 : DESCRIPTION:
12556 :
12557 : The subroutine minimizes function F(x) of N arguments subject to any
12558 : combination of:
12559 : * bound constraints
12560 : * linear inequality constraints
12561 : * linear equality constraints
12562 : * nonlinear equality constraints Gi(x)=0
12563 : * nonlinear inequality constraints Hi(x)<=0
12564 :
12565 : IMPORTANT: see MinNSSetAlgoAGS for important information on performance
12566 : restrictions of AGS solver.
12567 :
12568 : REQUIREMENTS:
12569 : * starting point X0 must be feasible or not too far away from the feasible
12570 : set
12571 : * F(), G(), H() are continuous, locally Lipschitz and continuously (but
12572 : not necessarily twice) differentiable in an open dense subset of R^N.
12573 : Functions F(), G() and H() may be nonsmooth and non-convex.
12574 : Informally speaking, it means that functions are composed of large
12575 : differentiable "patches" with nonsmoothness having place only at the
12576 : boundaries between these "patches".
12577 : Most real-life nonsmooth functions satisfy these requirements. Say,
12578 : anything which involves finite number of abs(), min() and max() is very
12579 : likely to pass the test.
12580 : Say, it is possible to optimize anything of the following:
12581 : * f=abs(x0)+2*abs(x1)
12582 : * f=max(x0,x1)
12583 : * f=sin(max(x0,x1)+abs(x2))
12584 : * for nonlinearly constrained problems: F() must be bounded from below
12585 : without nonlinear constraints (this requirement is due to the fact that,
12586 : contrary to box and linear constraints, nonlinear ones require special
12587 : handling).
12588 : * user must provide function value and gradient for F(), H(), G() at all
12589 : points where function/gradient can be calculated. If optimizer requires
12590 : value exactly at the boundary between "patches" (say, at x=0 for f=abs(x)),
12591 : where gradient is not defined, user may resolve tie arbitrarily (in our
12592 : case - return +1 or -1 at its discretion).
12593 : * NS solver supports numerical differentiation, i.e. it may differentiate
12594 : your function for you, but it results in 2N increase of function
12595 : evaluations. Not recommended unless you solve really small problems. See
12596 : minnscreatef() for more information on this functionality.
12597 :
12598 : USAGE:
12599 :
12600 : 1. User initializes algorithm state with MinNSCreate() call and chooses
12601 : what NLC solver to use. There is some solver which is used by default,
12602 : with default settings, but you should NOT rely on default choice. It
12603 : may change in future releases of ALGLIB without notice, and no one can
12604 : guarantee that new solver will be able to solve your problem with
12605 : default settings.
12606 :
12607 : From the other side, if you choose solver explicitly, you can be pretty
12608 : sure that it will work with new ALGLIB releases.
12609 :
12610 : In the current release following solvers can be used:
12611 : * AGS solver (activated with MinNSSetAlgoAGS() function)
12612 :
12613 : 2. User adds boundary and/or linear and/or nonlinear constraints by means
12614 : of calling one of the following functions:
12615 : a) MinNSSetBC() for boundary constraints
12616 : b) MinNSSetLC() for linear constraints
12617 : c) MinNSSetNLC() for nonlinear constraints
12618 : You may combine (a), (b) and (c) in one optimization problem.
12619 :
12620 : 3. User sets scale of the variables with MinNSSetScale() function. It is
12621 : VERY important to set scale of the variables, because nonlinearly
12622 : constrained problems are hard to solve when variables are badly scaled.
12623 :
12624 : 4. User sets stopping conditions with MinNSSetCond().
12625 :
12626 : 5. Finally, user calls MinNSOptimize() function which takes algorithm
12627 : state and pointer (delegate, etc) to callback function which calculates
12628 : F/G/H.
12629 :
12630 : 7. User calls MinNSResults() to get solution
12631 :
12632 : 8. Optionally user may call MinNSRestartFrom() to solve another problem
12633 : with same N but another starting point. MinNSRestartFrom() allows to
12634 : reuse already initialized structure.
12635 :
12636 :
12637 : INPUT PARAMETERS:
12638 : N - problem dimension, N>0:
12639 : * if given, only leading N elements of X are used
12640 : * if not given, automatically determined from size of X
12641 : X - starting point, array[N]:
12642 : * it is better to set X to a feasible point
12643 : * but X can be infeasible, in which case algorithm will try
12644 : to find feasible point first, using X as initial
12645 : approximation.
12646 :
12647 : OUTPUT PARAMETERS:
12648 : State - structure stores algorithm state
12649 :
12650 : NOTE: minnscreatef() function may be used if you do not have analytic
12651 : gradient. This function creates solver which uses numerical
12652 : differentiation with user-specified step.
12653 :
12654 : -- ALGLIB --
12655 : Copyright 18.05.2015 by Bochkanov Sergey
12656 : *************************************************************************/
12657 0 : void minnscreate(const ae_int_t n, const real_1d_array &x, minnsstate &state, const xparams _xparams)
12658 : {
12659 : jmp_buf _break_jump;
12660 : alglib_impl::ae_state _alglib_env_state;
12661 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12662 0 : if( setjmp(_break_jump) )
12663 : {
12664 : #if !defined(AE_NO_EXCEPTIONS)
12665 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12666 : #else
12667 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12668 : return;
12669 : #endif
12670 : }
12671 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12672 0 : if( _xparams.flags!=0x0 )
12673 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12674 0 : alglib_impl::minnscreate(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minnsstate*>(state.c_ptr()), &_alglib_env_state);
12675 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12676 0 : return;
12677 : }
12678 :
12679 : /*************************************************************************
12680 : NONSMOOTH NONCONVEX OPTIMIZATION
12681 : SUBJECT TO BOX/LINEAR/NONLINEAR-NONSMOOTH CONSTRAINTS
12682 :
12683 : DESCRIPTION:
12684 :
12685 : The subroutine minimizes function F(x) of N arguments subject to any
12686 : combination of:
12687 : * bound constraints
12688 : * linear inequality constraints
12689 : * linear equality constraints
12690 : * nonlinear equality constraints Gi(x)=0
12691 : * nonlinear inequality constraints Hi(x)<=0
12692 :
12693 : IMPORTANT: see MinNSSetAlgoAGS for important information on performance
12694 : restrictions of AGS solver.
12695 :
12696 : REQUIREMENTS:
12697 : * starting point X0 must be feasible or not too far away from the feasible
12698 : set
12699 : * F(), G(), H() are continuous, locally Lipschitz and continuously (but
12700 : not necessarily twice) differentiable in an open dense subset of R^N.
12701 : Functions F(), G() and H() may be nonsmooth and non-convex.
12702 : Informally speaking, it means that functions are composed of large
12703 : differentiable "patches" with nonsmoothness having place only at the
12704 : boundaries between these "patches".
12705 : Most real-life nonsmooth functions satisfy these requirements. Say,
12706 : anything which involves finite number of abs(), min() and max() is very
12707 : likely to pass the test.
12708 : Say, it is possible to optimize anything of the following:
12709 : * f=abs(x0)+2*abs(x1)
12710 : * f=max(x0,x1)
12711 : * f=sin(max(x0,x1)+abs(x2))
12712 : * for nonlinearly constrained problems: F() must be bounded from below
12713 : without nonlinear constraints (this requirement is due to the fact that,
12714 : contrary to box and linear constraints, nonlinear ones require special
12715 : handling).
12716 : * user must provide function value and gradient for F(), H(), G() at all
12717 : points where function/gradient can be calculated. If optimizer requires
12718 : value exactly at the boundary between "patches" (say, at x=0 for f=abs(x)),
12719 : where gradient is not defined, user may resolve tie arbitrarily (in our
12720 : case - return +1 or -1 at its discretion).
12721 : * NS solver supports numerical differentiation, i.e. it may differentiate
12722 : your function for you, but it results in 2N increase of function
12723 : evaluations. Not recommended unless you solve really small problems. See
12724 : minnscreatef() for more information on this functionality.
12725 :
12726 : USAGE:
12727 :
12728 : 1. User initializes algorithm state with MinNSCreate() call and chooses
12729 : what NLC solver to use. There is some solver which is used by default,
12730 : with default settings, but you should NOT rely on default choice. It
12731 : may change in future releases of ALGLIB without notice, and no one can
12732 : guarantee that new solver will be able to solve your problem with
12733 : default settings.
12734 :
12735 : From the other side, if you choose solver explicitly, you can be pretty
12736 : sure that it will work with new ALGLIB releases.
12737 :
12738 : In the current release following solvers can be used:
12739 : * AGS solver (activated with MinNSSetAlgoAGS() function)
12740 :
12741 : 2. User adds boundary and/or linear and/or nonlinear constraints by means
12742 : of calling one of the following functions:
12743 : a) MinNSSetBC() for boundary constraints
12744 : b) MinNSSetLC() for linear constraints
12745 : c) MinNSSetNLC() for nonlinear constraints
12746 : You may combine (a), (b) and (c) in one optimization problem.
12747 :
12748 : 3. User sets scale of the variables with MinNSSetScale() function. It is
12749 : VERY important to set scale of the variables, because nonlinearly
12750 : constrained problems are hard to solve when variables are badly scaled.
12751 :
12752 : 4. User sets stopping conditions with MinNSSetCond().
12753 :
12754 : 5. Finally, user calls MinNSOptimize() function which takes algorithm
12755 : state and pointer (delegate, etc) to callback function which calculates
12756 : F/G/H.
12757 :
12758 : 7. User calls MinNSResults() to get solution
12759 :
12760 : 8. Optionally user may call MinNSRestartFrom() to solve another problem
12761 : with same N but another starting point. MinNSRestartFrom() allows to
12762 : reuse already initialized structure.
12763 :
12764 :
12765 : INPUT PARAMETERS:
12766 : N - problem dimension, N>0:
12767 : * if given, only leading N elements of X are used
12768 : * if not given, automatically determined from size of X
12769 : X - starting point, array[N]:
12770 : * it is better to set X to a feasible point
12771 : * but X can be infeasible, in which case algorithm will try
12772 : to find feasible point first, using X as initial
12773 : approximation.
12774 :
12775 : OUTPUT PARAMETERS:
12776 : State - structure stores algorithm state
12777 :
12778 : NOTE: minnscreatef() function may be used if you do not have analytic
12779 : gradient. This function creates solver which uses numerical
12780 : differentiation with user-specified step.
12781 :
12782 : -- ALGLIB --
12783 : Copyright 18.05.2015 by Bochkanov Sergey
12784 : *************************************************************************/
12785 : #if !defined(AE_NO_EXCEPTIONS)
12786 0 : void minnscreate(const real_1d_array &x, minnsstate &state, const xparams _xparams)
12787 : {
12788 : jmp_buf _break_jump;
12789 : alglib_impl::ae_state _alglib_env_state;
12790 : ae_int_t n;
12791 :
12792 0 : n = x.length();
12793 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12794 0 : if( setjmp(_break_jump) )
12795 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12796 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12797 0 : if( _xparams.flags!=0x0 )
12798 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12799 0 : alglib_impl::minnscreate(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minnsstate*>(state.c_ptr()), &_alglib_env_state);
12800 :
12801 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12802 0 : return;
12803 : }
12804 : #endif
12805 :
12806 : /*************************************************************************
12807 : Version of minnscreatef() which uses numerical differentiation. I.e., you
12808 : do not have to calculate derivatives yourself. However, this version needs
12809 : 2N times more function evaluations.
12810 :
12811 : 2-point differentiation formula is used, because more precise 4-point
12812 : formula is unstable when used on non-smooth functions.
12813 :
12814 : INPUT PARAMETERS:
12815 : N - problem dimension, N>0:
12816 : * if given, only leading N elements of X are used
12817 : * if not given, automatically determined from size of X
12818 : X - starting point, array[N]:
12819 : * it is better to set X to a feasible point
12820 : * but X can be infeasible, in which case algorithm will try
12821 : to find feasible point first, using X as initial
12822 : approximation.
12823 : DiffStep- differentiation step, DiffStep>0. Algorithm performs
12824 : numerical differentiation with step for I-th variable
12825 : being equal to DiffStep*S[I] (here S[] is a scale vector,
12826 : set by minnssetscale() function).
12827 : Do not use too small steps, because it may lead to
12828 : catastrophic cancellation during intermediate calculations.
12829 :
12830 : OUTPUT PARAMETERS:
12831 : State - structure stores algorithm state
12832 :
12833 : -- ALGLIB --
12834 : Copyright 18.05.2015 by Bochkanov Sergey
12835 : *************************************************************************/
12836 0 : void minnscreatef(const ae_int_t n, const real_1d_array &x, const double diffstep, minnsstate &state, const xparams _xparams)
12837 : {
12838 : jmp_buf _break_jump;
12839 : alglib_impl::ae_state _alglib_env_state;
12840 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12841 0 : if( setjmp(_break_jump) )
12842 : {
12843 : #if !defined(AE_NO_EXCEPTIONS)
12844 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12845 : #else
12846 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12847 : return;
12848 : #endif
12849 : }
12850 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12851 0 : if( _xparams.flags!=0x0 )
12852 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12853 0 : alglib_impl::minnscreatef(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), diffstep, const_cast<alglib_impl::minnsstate*>(state.c_ptr()), &_alglib_env_state);
12854 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12855 0 : return;
12856 : }
12857 :
12858 : /*************************************************************************
12859 : Version of minnscreatef() which uses numerical differentiation. I.e., you
12860 : do not have to calculate derivatives yourself. However, this version needs
12861 : 2N times more function evaluations.
12862 :
12863 : 2-point differentiation formula is used, because more precise 4-point
12864 : formula is unstable when used on non-smooth functions.
12865 :
12866 : INPUT PARAMETERS:
12867 : N - problem dimension, N>0:
12868 : * if given, only leading N elements of X are used
12869 : * if not given, automatically determined from size of X
12870 : X - starting point, array[N]:
12871 : * it is better to set X to a feasible point
12872 : * but X can be infeasible, in which case algorithm will try
12873 : to find feasible point first, using X as initial
12874 : approximation.
12875 : DiffStep- differentiation step, DiffStep>0. Algorithm performs
12876 : numerical differentiation with step for I-th variable
12877 : being equal to DiffStep*S[I] (here S[] is a scale vector,
12878 : set by minnssetscale() function).
12879 : Do not use too small steps, because it may lead to
12880 : catastrophic cancellation during intermediate calculations.
12881 :
12882 : OUTPUT PARAMETERS:
12883 : State - structure stores algorithm state
12884 :
12885 : -- ALGLIB --
12886 : Copyright 18.05.2015 by Bochkanov Sergey
12887 : *************************************************************************/
12888 : #if !defined(AE_NO_EXCEPTIONS)
12889 0 : void minnscreatef(const real_1d_array &x, const double diffstep, minnsstate &state, const xparams _xparams)
12890 : {
12891 : jmp_buf _break_jump;
12892 : alglib_impl::ae_state _alglib_env_state;
12893 : ae_int_t n;
12894 :
12895 0 : n = x.length();
12896 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12897 0 : if( setjmp(_break_jump) )
12898 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12899 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12900 0 : if( _xparams.flags!=0x0 )
12901 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12902 0 : alglib_impl::minnscreatef(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), diffstep, const_cast<alglib_impl::minnsstate*>(state.c_ptr()), &_alglib_env_state);
12903 :
12904 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12905 0 : return;
12906 : }
12907 : #endif
12908 :
12909 : /*************************************************************************
12910 : This function sets boundary constraints.
12911 :
12912 : Boundary constraints are inactive by default (after initial creation).
12913 : They are preserved after algorithm restart with minnsrestartfrom().
12914 :
12915 : INPUT PARAMETERS:
12916 : State - structure stores algorithm state
12917 : BndL - lower bounds, array[N].
12918 : If some (all) variables are unbounded, you may specify
12919 : very small number or -INF.
12920 : BndU - upper bounds, array[N].
12921 : If some (all) variables are unbounded, you may specify
12922 : very large number or +INF.
12923 :
12924 : NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th
12925 : variable will be "frozen" at X[i]=BndL[i]=BndU[i].
12926 :
12927 : NOTE 2: AGS solver has following useful properties:
12928 : * bound constraints are always satisfied exactly
12929 : * function is evaluated only INSIDE area specified by bound constraints,
12930 : even when numerical differentiation is used (algorithm adjusts nodes
12931 : according to boundary constraints)
12932 :
12933 : -- ALGLIB --
12934 : Copyright 18.05.2015 by Bochkanov Sergey
12935 : *************************************************************************/
12936 0 : void minnssetbc(const minnsstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams)
12937 : {
12938 : jmp_buf _break_jump;
12939 : alglib_impl::ae_state _alglib_env_state;
12940 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12941 0 : if( setjmp(_break_jump) )
12942 : {
12943 : #if !defined(AE_NO_EXCEPTIONS)
12944 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12945 : #else
12946 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12947 : return;
12948 : #endif
12949 : }
12950 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12951 0 : if( _xparams.flags!=0x0 )
12952 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12953 0 : alglib_impl::minnssetbc(const_cast<alglib_impl::minnsstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(bndl.c_ptr()), const_cast<alglib_impl::ae_vector*>(bndu.c_ptr()), &_alglib_env_state);
12954 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12955 0 : return;
12956 : }
12957 :
12958 : /*************************************************************************
12959 : This function sets linear constraints.
12960 :
12961 : Linear constraints are inactive by default (after initial creation).
12962 : They are preserved after algorithm restart with minnsrestartfrom().
12963 :
12964 : INPUT PARAMETERS:
12965 : State - structure previously allocated with minnscreate() call.
12966 : C - linear constraints, array[K,N+1].
12967 : Each row of C represents one constraint, either equality
12968 : or inequality (see below):
12969 : * first N elements correspond to coefficients,
12970 : * last element corresponds to the right part.
12971 : All elements of C (including right part) must be finite.
12972 : CT - type of constraints, array[K]:
12973 : * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
12974 : * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
12975 : * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
12976 : K - number of equality/inequality constraints, K>=0:
12977 : * if given, only leading K elements of C/CT are used
12978 : * if not given, automatically determined from sizes of C/CT
12979 :
12980 : NOTE: linear (non-bound) constraints are satisfied only approximately:
12981 :
12982 : * there always exists some minor violation (about current sampling radius
12983 : in magnitude during optimization, about EpsX in the solution) due to use
12984 : of penalty method to handle constraints.
12985 : * numerical differentiation, if used, may lead to function evaluations
12986 : outside of the feasible area, because algorithm does NOT change
12987 : numerical differentiation formula according to linear constraints.
12988 :
12989 : If you want constraints to be satisfied exactly, try to reformulate your
12990 : problem in such manner that all constraints will become boundary ones
12991 : (this kind of constraints is always satisfied exactly, both in the final
12992 : solution and in all intermediate points).
12993 :
12994 : -- ALGLIB --
12995 : Copyright 18.05.2015 by Bochkanov Sergey
12996 : *************************************************************************/
12997 0 : void minnssetlc(const minnsstate &state, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams)
12998 : {
12999 : jmp_buf _break_jump;
13000 : alglib_impl::ae_state _alglib_env_state;
13001 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13002 0 : if( setjmp(_break_jump) )
13003 : {
13004 : #if !defined(AE_NO_EXCEPTIONS)
13005 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13006 : #else
13007 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13008 : return;
13009 : #endif
13010 : }
13011 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13012 0 : if( _xparams.flags!=0x0 )
13013 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13014 0 : alglib_impl::minnssetlc(const_cast<alglib_impl::minnsstate*>(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);
13015 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13016 0 : return;
13017 : }
13018 :
13019 : /*************************************************************************
13020 : This function sets linear constraints.
13021 :
13022 : Linear constraints are inactive by default (after initial creation).
13023 : They are preserved after algorithm restart with minnsrestartfrom().
13024 :
13025 : INPUT PARAMETERS:
13026 : State - structure previously allocated with minnscreate() call.
13027 : C - linear constraints, array[K,N+1].
13028 : Each row of C represents one constraint, either equality
13029 : or inequality (see below):
13030 : * first N elements correspond to coefficients,
13031 : * last element corresponds to the right part.
13032 : All elements of C (including right part) must be finite.
13033 : CT - type of constraints, array[K]:
13034 : * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
13035 : * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
13036 : * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
13037 : K - number of equality/inequality constraints, K>=0:
13038 : * if given, only leading K elements of C/CT are used
13039 : * if not given, automatically determined from sizes of C/CT
13040 :
13041 : NOTE: linear (non-bound) constraints are satisfied only approximately:
13042 :
13043 : * there always exists some minor violation (about current sampling radius
13044 : in magnitude during optimization, about EpsX in the solution) due to use
13045 : of penalty method to handle constraints.
13046 : * numerical differentiation, if used, may lead to function evaluations
13047 : outside of the feasible area, because algorithm does NOT change
13048 : numerical differentiation formula according to linear constraints.
13049 :
13050 : If you want constraints to be satisfied exactly, try to reformulate your
13051 : problem in such manner that all constraints will become boundary ones
13052 : (this kind of constraints is always satisfied exactly, both in the final
13053 : solution and in all intermediate points).
13054 :
13055 : -- ALGLIB --
13056 : Copyright 18.05.2015 by Bochkanov Sergey
13057 : *************************************************************************/
13058 : #if !defined(AE_NO_EXCEPTIONS)
13059 0 : void minnssetlc(const minnsstate &state, const real_2d_array &c, const integer_1d_array &ct, const xparams _xparams)
13060 : {
13061 : jmp_buf _break_jump;
13062 : alglib_impl::ae_state _alglib_env_state;
13063 : ae_int_t k;
13064 0 : if( (c.rows()!=ct.length()))
13065 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'minnssetlc': looks like one of arguments has wrong size");
13066 0 : k = c.rows();
13067 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13068 0 : if( setjmp(_break_jump) )
13069 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13070 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13071 0 : if( _xparams.flags!=0x0 )
13072 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13073 0 : alglib_impl::minnssetlc(const_cast<alglib_impl::minnsstate*>(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);
13074 :
13075 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13076 0 : return;
13077 : }
13078 : #endif
13079 :
13080 : /*************************************************************************
13081 : This function sets nonlinear constraints.
13082 :
13083 : In fact, this function sets NUMBER of nonlinear constraints. Constraints
13084 : itself (constraint functions) are passed to minnsoptimize() method. This
13085 : method requires user-defined vector function F[] and its Jacobian J[],
13086 : where:
13087 : * first component of F[] and first row of Jacobian J[] correspond to
13088 : function being minimized
13089 : * next NLEC components of F[] (and rows of J) correspond to nonlinear
13090 : equality constraints G_i(x)=0
13091 : * next NLIC components of F[] (and rows of J) correspond to nonlinear
13092 : inequality constraints H_i(x)<=0
13093 :
13094 : NOTE: you may combine nonlinear constraints with linear/boundary ones. If
13095 : your problem has mixed constraints, you may explicitly specify some
13096 : of them as linear ones. It may help optimizer to handle them more
13097 : efficiently.
13098 :
13099 : INPUT PARAMETERS:
13100 : State - structure previously allocated with minnscreate() call.
13101 : NLEC - number of Non-Linear Equality Constraints (NLEC), >=0
13102 : NLIC - number of Non-Linear Inquality Constraints (NLIC), >=0
13103 :
13104 : NOTE 1: nonlinear constraints are satisfied only approximately! It is
13105 : possible that algorithm will evaluate function outside of
13106 : the feasible area!
13107 :
13108 : NOTE 2: algorithm scales variables according to scale specified by
13109 : minnssetscale() function, so it can handle problems with badly
13110 : scaled variables (as long as we KNOW their scales).
13111 :
13112 : However, there is no way to automatically scale nonlinear
13113 : constraints Gi(x) and Hi(x). Inappropriate scaling of Gi/Hi may
13114 : ruin convergence. Solving problem with constraint "1000*G0(x)=0"
13115 : is NOT same as solving it with constraint "0.001*G0(x)=0".
13116 :
13117 : It means that YOU are the one who is responsible for correct
13118 : scaling of nonlinear constraints Gi(x) and Hi(x). We recommend you
13119 : to scale nonlinear constraints in such way that I-th component of
13120 : dG/dX (or dH/dx) has approximately unit magnitude (for problems
13121 : with unit scale) or has magnitude approximately equal to 1/S[i]
13122 : (where S is a scale set by minnssetscale() function).
13123 :
13124 : NOTE 3: nonlinear constraints are always hard to handle, no matter what
13125 : algorithm you try to use. Even basic box/linear constraints modify
13126 : function curvature by adding valleys and ridges. However,
13127 : nonlinear constraints add valleys which are very hard to follow
13128 : due to their "curved" nature.
13129 :
13130 : It means that optimization with single nonlinear constraint may be
13131 : significantly slower than optimization with multiple linear ones.
13132 : It is normal situation, and we recommend you to carefully choose
13133 : Rho parameter of minnssetalgoags(), because too large value may
13134 : slow down convergence.
13135 :
13136 :
13137 : -- ALGLIB --
13138 : Copyright 18.05.2015 by Bochkanov Sergey
13139 : *************************************************************************/
13140 0 : void minnssetnlc(const minnsstate &state, const ae_int_t nlec, const ae_int_t nlic, const xparams _xparams)
13141 : {
13142 : jmp_buf _break_jump;
13143 : alglib_impl::ae_state _alglib_env_state;
13144 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13145 0 : if( setjmp(_break_jump) )
13146 : {
13147 : #if !defined(AE_NO_EXCEPTIONS)
13148 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13149 : #else
13150 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13151 : return;
13152 : #endif
13153 : }
13154 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13155 0 : if( _xparams.flags!=0x0 )
13156 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13157 0 : alglib_impl::minnssetnlc(const_cast<alglib_impl::minnsstate*>(state.c_ptr()), nlec, nlic, &_alglib_env_state);
13158 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13159 0 : return;
13160 : }
13161 :
13162 : /*************************************************************************
13163 : This function sets stopping conditions for iterations of optimizer.
13164 :
13165 : INPUT PARAMETERS:
13166 : State - structure which stores algorithm state
13167 : EpsX - >=0
13168 : The AGS solver finishes its work if on k+1-th iteration
13169 : sampling radius decreases below EpsX.
13170 : MaxIts - maximum number of iterations. If MaxIts=0, the number of
13171 : iterations is unlimited.
13172 :
13173 : Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic
13174 : stopping criterion selection. We do not recommend you to rely on default
13175 : choice in production code.
13176 :
13177 : -- ALGLIB --
13178 : Copyright 18.05.2015 by Bochkanov Sergey
13179 : *************************************************************************/
13180 0 : void minnssetcond(const minnsstate &state, const double epsx, const ae_int_t maxits, const xparams _xparams)
13181 : {
13182 : jmp_buf _break_jump;
13183 : alglib_impl::ae_state _alglib_env_state;
13184 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13185 0 : if( setjmp(_break_jump) )
13186 : {
13187 : #if !defined(AE_NO_EXCEPTIONS)
13188 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13189 : #else
13190 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13191 : return;
13192 : #endif
13193 : }
13194 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13195 0 : if( _xparams.flags!=0x0 )
13196 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13197 0 : alglib_impl::minnssetcond(const_cast<alglib_impl::minnsstate*>(state.c_ptr()), epsx, maxits, &_alglib_env_state);
13198 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13199 0 : return;
13200 : }
13201 :
13202 : /*************************************************************************
13203 : This function sets scaling coefficients for NLC optimizer.
13204 :
13205 : ALGLIB optimizers use scaling matrices to test stopping conditions (step
13206 : size and gradient are scaled before comparison with tolerances). Scale of
13207 : the I-th variable is a translation invariant measure of:
13208 : a) "how large" the variable is
13209 : b) how large the step should be to make significant changes in the function
13210 :
13211 : Scaling is also used by finite difference variant of the optimizer - step
13212 : along I-th axis is equal to DiffStep*S[I].
13213 :
13214 : INPUT PARAMETERS:
13215 : State - structure stores algorithm state
13216 : S - array[N], non-zero scaling coefficients
13217 : S[i] may be negative, sign doesn't matter.
13218 :
13219 : -- ALGLIB --
13220 : Copyright 18.05.2015 by Bochkanov Sergey
13221 : *************************************************************************/
13222 0 : void minnssetscale(const minnsstate &state, const real_1d_array &s, const xparams _xparams)
13223 : {
13224 : jmp_buf _break_jump;
13225 : alglib_impl::ae_state _alglib_env_state;
13226 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13227 0 : if( setjmp(_break_jump) )
13228 : {
13229 : #if !defined(AE_NO_EXCEPTIONS)
13230 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13231 : #else
13232 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13233 : return;
13234 : #endif
13235 : }
13236 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13237 0 : if( _xparams.flags!=0x0 )
13238 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13239 0 : alglib_impl::minnssetscale(const_cast<alglib_impl::minnsstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(s.c_ptr()), &_alglib_env_state);
13240 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13241 0 : return;
13242 : }
13243 :
13244 : /*************************************************************************
13245 : This function tells MinNS unit to use AGS (adaptive gradient sampling)
13246 : algorithm for nonsmooth constrained optimization. This algorithm is a
13247 : slight modification of one described in "An Adaptive Gradient Sampling
13248 : Algorithm for Nonsmooth Optimization" by Frank E. Curtisy and Xiaocun Quez.
13249 :
13250 : This optimizer has following benefits and drawbacks:
13251 : + robustness; it can be used with nonsmooth and nonconvex functions.
13252 : + relatively easy tuning; most of the metaparameters are easy to select.
13253 : - it has convergence of steepest descent, slower than CG/LBFGS.
13254 : - each iteration involves evaluation of ~2N gradient values and solution
13255 : of 2Nx2N quadratic programming problem, which limits applicability of
13256 : algorithm by small-scale problems (up to 50-100).
13257 :
13258 : IMPORTANT: this algorithm has convergence guarantees, i.e. it will
13259 : steadily move towards some stationary point of the function.
13260 :
13261 : However, "stationary point" does not always mean "solution".
13262 : Nonsmooth problems often have "flat spots", i.e. areas where
13263 : function do not change at all. Such "flat spots" are stationary
13264 : points by definition, and algorithm may be caught here.
13265 :
13266 : Nonsmooth CONVEX tasks are not prone to this problem. Say, if
13267 : your function has form f()=MAX(f0,f1,...), and f_i are convex,
13268 : then f() is convex too and you have guaranteed convergence to
13269 : solution.
13270 :
13271 : INPUT PARAMETERS:
13272 : State - structure which stores algorithm state
13273 : Radius - initial sampling radius, >=0.
13274 :
13275 : Internally multiplied by vector of per-variable scales
13276 : specified by minnssetscale()).
13277 :
13278 : You should select relatively large sampling radius, roughly
13279 : proportional to scaled length of the first steps of the
13280 : algorithm. Something close to 0.1 in magnitude should be
13281 : good for most problems.
13282 :
13283 : AGS solver can automatically decrease radius, so too large
13284 : radius is not a problem (assuming that you won't choose
13285 : so large radius that algorithm will sample function in
13286 : too far away points, where gradient value is irrelevant).
13287 :
13288 : Too small radius won't cause algorithm to fail, but it may
13289 : slow down algorithm (it may have to perform too short
13290 : steps).
13291 : Penalty - penalty coefficient for nonlinear constraints:
13292 : * for problem with nonlinear constraints should be some
13293 : problem-specific positive value, large enough that
13294 : penalty term changes shape of the function.
13295 : Starting from some problem-specific value penalty
13296 : coefficient becomes large enough to exactly enforce
13297 : nonlinear constraints; larger values do not improve
13298 : precision.
13299 : Increasing it too much may slow down convergence, so you
13300 : should choose it carefully.
13301 : * can be zero for problems WITHOUT nonlinear constraints
13302 : (i.e. for unconstrained ones or ones with just box or
13303 : linear constraints)
13304 : * if you specify zero value for problem with at least one
13305 : nonlinear constraint, algorithm will terminate with
13306 : error code -1.
13307 :
13308 : ALGORITHM OUTLINE
13309 :
13310 : The very basic outline of unconstrained AGS algorithm is given below:
13311 :
13312 : 0. If sampling radius is below EpsX or we performed more then MaxIts
13313 : iterations - STOP.
13314 : 1. sample O(N) gradient values at random locations around current point;
13315 : informally speaking, this sample is an implicit piecewise linear model
13316 : of the function, although algorithm formulation does not mention that
13317 : explicitly
13318 : 2. solve quadratic programming problem in order to find descent direction
13319 : 3. if QP solver tells us that we are near solution, decrease sampling
13320 : radius and move to (0)
13321 : 4. perform backtracking line search
13322 : 5. after moving to new point, goto (0)
13323 :
13324 : As for the constraints:
13325 : * box constraints are handled exactly by modification of the function
13326 : being minimized
13327 : * linear/nonlinear constraints are handled by adding L1 penalty. Because
13328 : our solver can handle nonsmoothness, we can use L1 penalty function,
13329 : which is an exact one (i.e. exact solution is returned under such
13330 : penalty).
13331 : * penalty coefficient for linear constraints is chosen automatically;
13332 : however, penalty coefficient for nonlinear constraints must be specified
13333 : by user.
13334 :
13335 : -- ALGLIB --
13336 : Copyright 18.05.2015 by Bochkanov Sergey
13337 : *************************************************************************/
13338 0 : void minnssetalgoags(const minnsstate &state, const double radius, const double penalty, const xparams _xparams)
13339 : {
13340 : jmp_buf _break_jump;
13341 : alglib_impl::ae_state _alglib_env_state;
13342 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13343 0 : if( setjmp(_break_jump) )
13344 : {
13345 : #if !defined(AE_NO_EXCEPTIONS)
13346 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13347 : #else
13348 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13349 : return;
13350 : #endif
13351 : }
13352 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13353 0 : if( _xparams.flags!=0x0 )
13354 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13355 0 : alglib_impl::minnssetalgoags(const_cast<alglib_impl::minnsstate*>(state.c_ptr()), radius, penalty, &_alglib_env_state);
13356 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13357 0 : return;
13358 : }
13359 :
13360 : /*************************************************************************
13361 : This function turns on/off reporting.
13362 :
13363 : INPUT PARAMETERS:
13364 : State - structure which stores algorithm state
13365 : NeedXRep- whether iteration reports are needed or not
13366 :
13367 : If NeedXRep is True, algorithm will call rep() callback function if it is
13368 : provided to minnsoptimize().
13369 :
13370 : -- ALGLIB --
13371 : Copyright 28.11.2010 by Bochkanov Sergey
13372 : *************************************************************************/
13373 0 : void minnssetxrep(const minnsstate &state, const bool needxrep, const xparams _xparams)
13374 : {
13375 : jmp_buf _break_jump;
13376 : alglib_impl::ae_state _alglib_env_state;
13377 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13378 0 : if( setjmp(_break_jump) )
13379 : {
13380 : #if !defined(AE_NO_EXCEPTIONS)
13381 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13382 : #else
13383 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13384 : return;
13385 : #endif
13386 : }
13387 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13388 0 : if( _xparams.flags!=0x0 )
13389 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13390 0 : alglib_impl::minnssetxrep(const_cast<alglib_impl::minnsstate*>(state.c_ptr()), needxrep, &_alglib_env_state);
13391 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13392 0 : return;
13393 : }
13394 :
13395 : /*************************************************************************
13396 : This subroutine submits request for termination of running optimizer. It
13397 : should be called from user-supplied callback when user decides that it is
13398 : time to "smoothly" terminate optimization process. As result, optimizer
13399 : stops at point which was "current accepted" when termination request was
13400 : submitted and returns error code 8 (successful termination).
13401 :
13402 : INPUT PARAMETERS:
13403 : State - optimizer structure
13404 :
13405 : NOTE: after request for termination optimizer may perform several
13406 : additional calls to user-supplied callbacks. It does NOT guarantee
13407 : to stop immediately - it just guarantees that these additional calls
13408 : will be discarded later.
13409 :
13410 : NOTE: calling this function on optimizer which is NOT running will have no
13411 : effect.
13412 :
13413 : NOTE: multiple calls to this function are possible. First call is counted,
13414 : subsequent calls are silently ignored.
13415 :
13416 : -- ALGLIB --
13417 : Copyright 18.05.2015 by Bochkanov Sergey
13418 : *************************************************************************/
13419 0 : void minnsrequesttermination(const minnsstate &state, const xparams _xparams)
13420 : {
13421 : jmp_buf _break_jump;
13422 : alglib_impl::ae_state _alglib_env_state;
13423 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13424 0 : if( setjmp(_break_jump) )
13425 : {
13426 : #if !defined(AE_NO_EXCEPTIONS)
13427 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13428 : #else
13429 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13430 : return;
13431 : #endif
13432 : }
13433 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13434 0 : if( _xparams.flags!=0x0 )
13435 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13436 0 : alglib_impl::minnsrequesttermination(const_cast<alglib_impl::minnsstate*>(state.c_ptr()), &_alglib_env_state);
13437 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13438 0 : return;
13439 : }
13440 :
13441 : /*************************************************************************
13442 : This function provides reverse communication interface
13443 : Reverse communication interface is not documented or recommended to use.
13444 : See below for functions which provide better documented API
13445 : *************************************************************************/
13446 0 : bool minnsiteration(const minnsstate &state, const xparams _xparams)
13447 : {
13448 : jmp_buf _break_jump;
13449 : alglib_impl::ae_state _alglib_env_state;
13450 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13451 0 : if( setjmp(_break_jump) )
13452 : {
13453 : #if !defined(AE_NO_EXCEPTIONS)
13454 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13455 : #else
13456 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13457 : return 0;
13458 : #endif
13459 : }
13460 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13461 0 : if( _xparams.flags!=0x0 )
13462 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13463 0 : ae_bool result = alglib_impl::minnsiteration(const_cast<alglib_impl::minnsstate*>(state.c_ptr()), &_alglib_env_state);
13464 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13465 0 : return *(reinterpret_cast<bool*>(&result));
13466 : }
13467 :
13468 :
13469 0 : void minnsoptimize(minnsstate &state,
13470 : void (*fvec)(const real_1d_array &x, real_1d_array &fi, void *ptr),
13471 : void (*rep)(const real_1d_array &x, double func, void *ptr),
13472 : void *ptr,
13473 : const xparams _xparams)
13474 : {
13475 : jmp_buf _break_jump;
13476 : alglib_impl::ae_state _alglib_env_state;
13477 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13478 0 : if( setjmp(_break_jump) )
13479 : {
13480 : #if !defined(AE_NO_EXCEPTIONS)
13481 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13482 : #else
13483 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13484 : return;
13485 : #endif
13486 : }
13487 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13488 0 : if( _xparams.flags!=0x0 )
13489 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13490 0 : alglib_impl::ae_assert(fvec!=NULL, "ALGLIB: error in 'minnsoptimize()' (fvec is NULL)", &_alglib_env_state);
13491 0 : while( alglib_impl::minnsiteration(state.c_ptr(), &_alglib_env_state) )
13492 : {
13493 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN
13494 0 : if( state.needfi )
13495 : {
13496 0 : fvec(state.x, state.fi, ptr);
13497 0 : continue;
13498 : }
13499 0 : if( state.xupdated )
13500 : {
13501 0 : if( rep!=NULL )
13502 0 : rep(state.x, state.f, ptr);
13503 0 : continue;
13504 : }
13505 0 : goto lbl_no_callback;
13506 0 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_END
13507 0 : lbl_no_callback:
13508 0 : alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minnsoptimize' (some derivatives were not provided?)", &_alglib_env_state);
13509 : }
13510 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13511 0 : }
13512 :
13513 :
13514 0 : void minnsoptimize(minnsstate &state,
13515 : void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr),
13516 : void (*rep)(const real_1d_array &x, double func, void *ptr),
13517 : void *ptr,
13518 : const xparams _xparams)
13519 : {
13520 : jmp_buf _break_jump;
13521 : alglib_impl::ae_state _alglib_env_state;
13522 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13523 0 : if( setjmp(_break_jump) )
13524 : {
13525 : #if !defined(AE_NO_EXCEPTIONS)
13526 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13527 : #else
13528 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13529 : return;
13530 : #endif
13531 : }
13532 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13533 0 : if( _xparams.flags!=0x0 )
13534 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13535 0 : alglib_impl::ae_assert(jac!=NULL, "ALGLIB: error in 'minnsoptimize()' (jac is NULL)", &_alglib_env_state);
13536 0 : while( alglib_impl::minnsiteration(state.c_ptr(), &_alglib_env_state) )
13537 : {
13538 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN
13539 0 : if( state.needfij )
13540 : {
13541 0 : jac(state.x, state.fi, state.j, ptr);
13542 0 : continue;
13543 : }
13544 0 : if( state.xupdated )
13545 : {
13546 0 : if( rep!=NULL )
13547 0 : rep(state.x, state.f, ptr);
13548 0 : continue;
13549 : }
13550 0 : goto lbl_no_callback;
13551 0 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_END
13552 0 : lbl_no_callback:
13553 0 : alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minnsoptimize' (some derivatives were not provided?)", &_alglib_env_state);
13554 : }
13555 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13556 0 : }
13557 :
13558 :
13559 :
13560 : /*************************************************************************
13561 : MinNS results
13562 :
13563 : INPUT PARAMETERS:
13564 : State - algorithm state
13565 :
13566 : OUTPUT PARAMETERS:
13567 : X - array[0..N-1], solution
13568 : Rep - optimization report. You should check Rep.TerminationType
13569 : in order to distinguish successful termination from
13570 : unsuccessful one:
13571 : * -8 internal integrity control detected infinite or
13572 : NAN values in function/gradient. Abnormal
13573 : termination signalled.
13574 : * -3 box constraints are inconsistent
13575 : * -1 inconsistent parameters were passed:
13576 : * penalty parameter for minnssetalgoags() is zero,
13577 : but we have nonlinear constraints set by minnssetnlc()
13578 : * 2 sampling radius decreased below epsx
13579 : * 7 stopping conditions are too stringent,
13580 : further improvement is impossible,
13581 : X contains best point found so far.
13582 : * 8 User requested termination via minnsrequesttermination()
13583 :
13584 : -- ALGLIB --
13585 : Copyright 18.05.2015 by Bochkanov Sergey
13586 : *************************************************************************/
13587 0 : void minnsresults(const minnsstate &state, real_1d_array &x, minnsreport &rep, const xparams _xparams)
13588 : {
13589 : jmp_buf _break_jump;
13590 : alglib_impl::ae_state _alglib_env_state;
13591 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13592 0 : if( setjmp(_break_jump) )
13593 : {
13594 : #if !defined(AE_NO_EXCEPTIONS)
13595 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13596 : #else
13597 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13598 : return;
13599 : #endif
13600 : }
13601 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13602 0 : if( _xparams.flags!=0x0 )
13603 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13604 0 : alglib_impl::minnsresults(const_cast<alglib_impl::minnsstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minnsreport*>(rep.c_ptr()), &_alglib_env_state);
13605 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13606 0 : return;
13607 : }
13608 :
13609 : /*************************************************************************
13610 :
13611 : Buffered implementation of minnsresults() which uses pre-allocated buffer
13612 : to store X[]. If buffer size is too small, it resizes buffer. It is
13613 : intended to be used in the inner cycles of performance critical algorithms
13614 : where array reallocation penalty is too large to be ignored.
13615 :
13616 : -- ALGLIB --
13617 : Copyright 18.05.2015 by Bochkanov Sergey
13618 : *************************************************************************/
13619 0 : void minnsresultsbuf(const minnsstate &state, real_1d_array &x, minnsreport &rep, const xparams _xparams)
13620 : {
13621 : jmp_buf _break_jump;
13622 : alglib_impl::ae_state _alglib_env_state;
13623 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13624 0 : if( setjmp(_break_jump) )
13625 : {
13626 : #if !defined(AE_NO_EXCEPTIONS)
13627 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13628 : #else
13629 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13630 : return;
13631 : #endif
13632 : }
13633 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13634 0 : if( _xparams.flags!=0x0 )
13635 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13636 0 : alglib_impl::minnsresultsbuf(const_cast<alglib_impl::minnsstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minnsreport*>(rep.c_ptr()), &_alglib_env_state);
13637 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13638 0 : return;
13639 : }
13640 :
13641 : /*************************************************************************
13642 : This subroutine restarts algorithm from new point.
13643 : All optimization parameters (including constraints) are left unchanged.
13644 :
13645 : This function allows to solve multiple optimization problems (which
13646 : must have same number of dimensions) without object reallocation penalty.
13647 :
13648 : INPUT PARAMETERS:
13649 : State - structure previously allocated with minnscreate() call.
13650 : X - new starting point.
13651 :
13652 : -- ALGLIB --
13653 : Copyright 18.05.2015 by Bochkanov Sergey
13654 : *************************************************************************/
13655 0 : void minnsrestartfrom(const minnsstate &state, const real_1d_array &x, const xparams _xparams)
13656 : {
13657 : jmp_buf _break_jump;
13658 : alglib_impl::ae_state _alglib_env_state;
13659 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13660 0 : if( setjmp(_break_jump) )
13661 : {
13662 : #if !defined(AE_NO_EXCEPTIONS)
13663 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13664 : #else
13665 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13666 : return;
13667 : #endif
13668 : }
13669 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13670 0 : if( _xparams.flags!=0x0 )
13671 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13672 0 : alglib_impl::minnsrestartfrom(const_cast<alglib_impl::minnsstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
13673 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13674 0 : return;
13675 : }
13676 : #endif
13677 :
13678 : #if defined(AE_COMPILE_MINCOMP) || !defined(AE_PARTIAL_BUILD)
13679 : /*************************************************************************
13680 :
13681 : *************************************************************************/
13682 0 : _minasastate_owner::_minasastate_owner()
13683 : {
13684 : jmp_buf _break_jump;
13685 : alglib_impl::ae_state _state;
13686 :
13687 0 : alglib_impl::ae_state_init(&_state);
13688 0 : if( setjmp(_break_jump) )
13689 : {
13690 0 : if( p_struct!=NULL )
13691 : {
13692 0 : alglib_impl::_minasastate_destroy(p_struct);
13693 0 : alglib_impl::ae_free(p_struct);
13694 : }
13695 0 : p_struct = NULL;
13696 : #if !defined(AE_NO_EXCEPTIONS)
13697 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
13698 : #else
13699 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
13700 : return;
13701 : #endif
13702 : }
13703 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
13704 0 : p_struct = NULL;
13705 0 : p_struct = (alglib_impl::minasastate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minasastate), &_state);
13706 0 : memset(p_struct, 0, sizeof(alglib_impl::minasastate));
13707 0 : alglib_impl::_minasastate_init(p_struct, &_state, ae_false);
13708 0 : ae_state_clear(&_state);
13709 0 : }
13710 :
13711 0 : _minasastate_owner::_minasastate_owner(const _minasastate_owner &rhs)
13712 : {
13713 : jmp_buf _break_jump;
13714 : alglib_impl::ae_state _state;
13715 :
13716 0 : alglib_impl::ae_state_init(&_state);
13717 0 : if( setjmp(_break_jump) )
13718 : {
13719 0 : if( p_struct!=NULL )
13720 : {
13721 0 : alglib_impl::_minasastate_destroy(p_struct);
13722 0 : alglib_impl::ae_free(p_struct);
13723 : }
13724 0 : p_struct = NULL;
13725 : #if !defined(AE_NO_EXCEPTIONS)
13726 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
13727 : #else
13728 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
13729 : return;
13730 : #endif
13731 : }
13732 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
13733 0 : p_struct = NULL;
13734 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minasastate copy constructor failure (source is not initialized)", &_state);
13735 0 : p_struct = (alglib_impl::minasastate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minasastate), &_state);
13736 0 : memset(p_struct, 0, sizeof(alglib_impl::minasastate));
13737 0 : alglib_impl::_minasastate_init_copy(p_struct, const_cast<alglib_impl::minasastate*>(rhs.p_struct), &_state, ae_false);
13738 0 : ae_state_clear(&_state);
13739 0 : }
13740 :
13741 0 : _minasastate_owner& _minasastate_owner::operator=(const _minasastate_owner &rhs)
13742 : {
13743 0 : if( this==&rhs )
13744 0 : return *this;
13745 : jmp_buf _break_jump;
13746 : alglib_impl::ae_state _state;
13747 :
13748 0 : alglib_impl::ae_state_init(&_state);
13749 0 : if( setjmp(_break_jump) )
13750 : {
13751 : #if !defined(AE_NO_EXCEPTIONS)
13752 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
13753 : #else
13754 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
13755 : return *this;
13756 : #endif
13757 : }
13758 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
13759 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minasastate assignment constructor failure (destination is not initialized)", &_state);
13760 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minasastate assignment constructor failure (source is not initialized)", &_state);
13761 0 : alglib_impl::_minasastate_destroy(p_struct);
13762 0 : memset(p_struct, 0, sizeof(alglib_impl::minasastate));
13763 0 : alglib_impl::_minasastate_init_copy(p_struct, const_cast<alglib_impl::minasastate*>(rhs.p_struct), &_state, ae_false);
13764 0 : ae_state_clear(&_state);
13765 0 : return *this;
13766 : }
13767 :
13768 0 : _minasastate_owner::~_minasastate_owner()
13769 : {
13770 0 : if( p_struct!=NULL )
13771 : {
13772 0 : alglib_impl::_minasastate_destroy(p_struct);
13773 0 : ae_free(p_struct);
13774 : }
13775 0 : }
13776 :
13777 0 : alglib_impl::minasastate* _minasastate_owner::c_ptr()
13778 : {
13779 0 : return p_struct;
13780 : }
13781 :
13782 0 : alglib_impl::minasastate* _minasastate_owner::c_ptr() const
13783 : {
13784 0 : return const_cast<alglib_impl::minasastate*>(p_struct);
13785 : }
13786 0 : minasastate::minasastate() : _minasastate_owner() ,needfg(p_struct->needfg),xupdated(p_struct->xupdated),f(p_struct->f),g(&p_struct->g),x(&p_struct->x)
13787 : {
13788 0 : }
13789 :
13790 0 : minasastate::minasastate(const minasastate &rhs):_minasastate_owner(rhs) ,needfg(p_struct->needfg),xupdated(p_struct->xupdated),f(p_struct->f),g(&p_struct->g),x(&p_struct->x)
13791 : {
13792 0 : }
13793 :
13794 0 : minasastate& minasastate::operator=(const minasastate &rhs)
13795 : {
13796 0 : if( this==&rhs )
13797 0 : return *this;
13798 0 : _minasastate_owner::operator=(rhs);
13799 0 : return *this;
13800 : }
13801 :
13802 0 : minasastate::~minasastate()
13803 : {
13804 0 : }
13805 :
13806 :
13807 : /*************************************************************************
13808 :
13809 : *************************************************************************/
13810 0 : _minasareport_owner::_minasareport_owner()
13811 : {
13812 : jmp_buf _break_jump;
13813 : alglib_impl::ae_state _state;
13814 :
13815 0 : alglib_impl::ae_state_init(&_state);
13816 0 : if( setjmp(_break_jump) )
13817 : {
13818 0 : if( p_struct!=NULL )
13819 : {
13820 0 : alglib_impl::_minasareport_destroy(p_struct);
13821 0 : alglib_impl::ae_free(p_struct);
13822 : }
13823 0 : p_struct = NULL;
13824 : #if !defined(AE_NO_EXCEPTIONS)
13825 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
13826 : #else
13827 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
13828 : return;
13829 : #endif
13830 : }
13831 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
13832 0 : p_struct = NULL;
13833 0 : p_struct = (alglib_impl::minasareport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minasareport), &_state);
13834 0 : memset(p_struct, 0, sizeof(alglib_impl::minasareport));
13835 0 : alglib_impl::_minasareport_init(p_struct, &_state, ae_false);
13836 0 : ae_state_clear(&_state);
13837 0 : }
13838 :
13839 0 : _minasareport_owner::_minasareport_owner(const _minasareport_owner &rhs)
13840 : {
13841 : jmp_buf _break_jump;
13842 : alglib_impl::ae_state _state;
13843 :
13844 0 : alglib_impl::ae_state_init(&_state);
13845 0 : if( setjmp(_break_jump) )
13846 : {
13847 0 : if( p_struct!=NULL )
13848 : {
13849 0 : alglib_impl::_minasareport_destroy(p_struct);
13850 0 : alglib_impl::ae_free(p_struct);
13851 : }
13852 0 : p_struct = NULL;
13853 : #if !defined(AE_NO_EXCEPTIONS)
13854 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
13855 : #else
13856 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
13857 : return;
13858 : #endif
13859 : }
13860 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
13861 0 : p_struct = NULL;
13862 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minasareport copy constructor failure (source is not initialized)", &_state);
13863 0 : p_struct = (alglib_impl::minasareport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minasareport), &_state);
13864 0 : memset(p_struct, 0, sizeof(alglib_impl::minasareport));
13865 0 : alglib_impl::_minasareport_init_copy(p_struct, const_cast<alglib_impl::minasareport*>(rhs.p_struct), &_state, ae_false);
13866 0 : ae_state_clear(&_state);
13867 0 : }
13868 :
13869 0 : _minasareport_owner& _minasareport_owner::operator=(const _minasareport_owner &rhs)
13870 : {
13871 0 : if( this==&rhs )
13872 0 : return *this;
13873 : jmp_buf _break_jump;
13874 : alglib_impl::ae_state _state;
13875 :
13876 0 : alglib_impl::ae_state_init(&_state);
13877 0 : if( setjmp(_break_jump) )
13878 : {
13879 : #if !defined(AE_NO_EXCEPTIONS)
13880 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
13881 : #else
13882 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
13883 : return *this;
13884 : #endif
13885 : }
13886 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
13887 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minasareport assignment constructor failure (destination is not initialized)", &_state);
13888 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minasareport assignment constructor failure (source is not initialized)", &_state);
13889 0 : alglib_impl::_minasareport_destroy(p_struct);
13890 0 : memset(p_struct, 0, sizeof(alglib_impl::minasareport));
13891 0 : alglib_impl::_minasareport_init_copy(p_struct, const_cast<alglib_impl::minasareport*>(rhs.p_struct), &_state, ae_false);
13892 0 : ae_state_clear(&_state);
13893 0 : return *this;
13894 : }
13895 :
13896 0 : _minasareport_owner::~_minasareport_owner()
13897 : {
13898 0 : if( p_struct!=NULL )
13899 : {
13900 0 : alglib_impl::_minasareport_destroy(p_struct);
13901 0 : ae_free(p_struct);
13902 : }
13903 0 : }
13904 :
13905 0 : alglib_impl::minasareport* _minasareport_owner::c_ptr()
13906 : {
13907 0 : return p_struct;
13908 : }
13909 :
13910 0 : alglib_impl::minasareport* _minasareport_owner::c_ptr() const
13911 : {
13912 0 : return const_cast<alglib_impl::minasareport*>(p_struct);
13913 : }
13914 0 : minasareport::minasareport() : _minasareport_owner() ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),terminationtype(p_struct->terminationtype),activeconstraints(p_struct->activeconstraints)
13915 : {
13916 0 : }
13917 :
13918 0 : minasareport::minasareport(const minasareport &rhs):_minasareport_owner(rhs) ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),terminationtype(p_struct->terminationtype),activeconstraints(p_struct->activeconstraints)
13919 : {
13920 0 : }
13921 :
13922 0 : minasareport& minasareport::operator=(const minasareport &rhs)
13923 : {
13924 0 : if( this==&rhs )
13925 0 : return *this;
13926 0 : _minasareport_owner::operator=(rhs);
13927 0 : return *this;
13928 : }
13929 :
13930 0 : minasareport::~minasareport()
13931 : {
13932 0 : }
13933 :
13934 : /*************************************************************************
13935 : Obsolete function, use MinLBFGSSetPrecDefault() instead.
13936 :
13937 : -- ALGLIB --
13938 : Copyright 13.10.2010 by Bochkanov Sergey
13939 : *************************************************************************/
13940 0 : void minlbfgssetdefaultpreconditioner(const minlbfgsstate &state, const xparams _xparams)
13941 : {
13942 : jmp_buf _break_jump;
13943 : alglib_impl::ae_state _alglib_env_state;
13944 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13945 0 : if( setjmp(_break_jump) )
13946 : {
13947 : #if !defined(AE_NO_EXCEPTIONS)
13948 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13949 : #else
13950 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13951 : return;
13952 : #endif
13953 : }
13954 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13955 0 : if( _xparams.flags!=0x0 )
13956 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13957 0 : alglib_impl::minlbfgssetdefaultpreconditioner(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), &_alglib_env_state);
13958 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13959 0 : return;
13960 : }
13961 :
13962 : /*************************************************************************
13963 : Obsolete function, use MinLBFGSSetCholeskyPreconditioner() instead.
13964 :
13965 : -- ALGLIB --
13966 : Copyright 13.10.2010 by Bochkanov Sergey
13967 : *************************************************************************/
13968 0 : void minlbfgssetcholeskypreconditioner(const minlbfgsstate &state, const real_2d_array &p, const bool isupper, const xparams _xparams)
13969 : {
13970 : jmp_buf _break_jump;
13971 : alglib_impl::ae_state _alglib_env_state;
13972 0 : alglib_impl::ae_state_init(&_alglib_env_state);
13973 0 : if( setjmp(_break_jump) )
13974 : {
13975 : #if !defined(AE_NO_EXCEPTIONS)
13976 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
13977 : #else
13978 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
13979 : return;
13980 : #endif
13981 : }
13982 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
13983 0 : if( _xparams.flags!=0x0 )
13984 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
13985 0 : alglib_impl::minlbfgssetcholeskypreconditioner(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(p.c_ptr()), isupper, &_alglib_env_state);
13986 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
13987 0 : return;
13988 : }
13989 :
13990 : /*************************************************************************
13991 : This is obsolete function which was used by previous version of the BLEIC
13992 : optimizer. It does nothing in the current version of BLEIC.
13993 :
13994 : -- ALGLIB --
13995 : Copyright 28.11.2010 by Bochkanov Sergey
13996 : *************************************************************************/
13997 0 : void minbleicsetbarrierwidth(const minbleicstate &state, const double mu, const xparams _xparams)
13998 : {
13999 : jmp_buf _break_jump;
14000 : alglib_impl::ae_state _alglib_env_state;
14001 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14002 0 : if( setjmp(_break_jump) )
14003 : {
14004 : #if !defined(AE_NO_EXCEPTIONS)
14005 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14006 : #else
14007 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
14008 : return;
14009 : #endif
14010 : }
14011 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14012 0 : if( _xparams.flags!=0x0 )
14013 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14014 0 : alglib_impl::minbleicsetbarrierwidth(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), mu, &_alglib_env_state);
14015 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14016 0 : return;
14017 : }
14018 :
14019 : /*************************************************************************
14020 : This is obsolete function which was used by previous version of the BLEIC
14021 : optimizer. It does nothing in the current version of BLEIC.
14022 :
14023 : -- ALGLIB --
14024 : Copyright 28.11.2010 by Bochkanov Sergey
14025 : *************************************************************************/
14026 0 : void minbleicsetbarrierdecay(const minbleicstate &state, const double mudecay, const xparams _xparams)
14027 : {
14028 : jmp_buf _break_jump;
14029 : alglib_impl::ae_state _alglib_env_state;
14030 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14031 0 : if( setjmp(_break_jump) )
14032 : {
14033 : #if !defined(AE_NO_EXCEPTIONS)
14034 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14035 : #else
14036 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
14037 : return;
14038 : #endif
14039 : }
14040 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14041 0 : if( _xparams.flags!=0x0 )
14042 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14043 0 : alglib_impl::minbleicsetbarrierdecay(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), mudecay, &_alglib_env_state);
14044 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14045 0 : return;
14046 : }
14047 :
14048 : /*************************************************************************
14049 : Obsolete optimization algorithm.
14050 : Was replaced by MinBLEIC subpackage.
14051 :
14052 : -- ALGLIB --
14053 : Copyright 25.03.2010 by Bochkanov Sergey
14054 : *************************************************************************/
14055 0 : void minasacreate(const ae_int_t n, const real_1d_array &x, const real_1d_array &bndl, const real_1d_array &bndu, minasastate &state, const xparams _xparams)
14056 : {
14057 : jmp_buf _break_jump;
14058 : alglib_impl::ae_state _alglib_env_state;
14059 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14060 0 : if( setjmp(_break_jump) )
14061 : {
14062 : #if !defined(AE_NO_EXCEPTIONS)
14063 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14064 : #else
14065 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
14066 : return;
14067 : #endif
14068 : }
14069 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14070 0 : if( _xparams.flags!=0x0 )
14071 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14072 0 : 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);
14073 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14074 0 : return;
14075 : }
14076 :
14077 : /*************************************************************************
14078 : Obsolete optimization algorithm.
14079 : Was replaced by MinBLEIC subpackage.
14080 :
14081 : -- ALGLIB --
14082 : Copyright 25.03.2010 by Bochkanov Sergey
14083 : *************************************************************************/
14084 : #if !defined(AE_NO_EXCEPTIONS)
14085 0 : void minasacreate(const real_1d_array &x, const real_1d_array &bndl, const real_1d_array &bndu, minasastate &state, const xparams _xparams)
14086 : {
14087 : jmp_buf _break_jump;
14088 : alglib_impl::ae_state _alglib_env_state;
14089 : ae_int_t n;
14090 0 : if( (x.length()!=bndl.length()) || (x.length()!=bndu.length()))
14091 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'minasacreate': looks like one of arguments has wrong size");
14092 0 : n = x.length();
14093 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14094 0 : if( setjmp(_break_jump) )
14095 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14096 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14097 0 : if( _xparams.flags!=0x0 )
14098 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14099 0 : 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);
14100 :
14101 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14102 0 : return;
14103 : }
14104 : #endif
14105 :
14106 : /*************************************************************************
14107 : Obsolete optimization algorithm.
14108 : Was replaced by MinBLEIC subpackage.
14109 :
14110 : -- ALGLIB --
14111 : Copyright 02.04.2010 by Bochkanov Sergey
14112 : *************************************************************************/
14113 0 : void minasasetcond(const minasastate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits, const xparams _xparams)
14114 : {
14115 : jmp_buf _break_jump;
14116 : alglib_impl::ae_state _alglib_env_state;
14117 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14118 0 : if( setjmp(_break_jump) )
14119 : {
14120 : #if !defined(AE_NO_EXCEPTIONS)
14121 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14122 : #else
14123 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
14124 : return;
14125 : #endif
14126 : }
14127 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14128 0 : if( _xparams.flags!=0x0 )
14129 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14130 0 : alglib_impl::minasasetcond(const_cast<alglib_impl::minasastate*>(state.c_ptr()), epsg, epsf, epsx, maxits, &_alglib_env_state);
14131 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14132 0 : return;
14133 : }
14134 :
14135 : /*************************************************************************
14136 : Obsolete optimization algorithm.
14137 : Was replaced by MinBLEIC subpackage.
14138 :
14139 : -- ALGLIB --
14140 : Copyright 02.04.2010 by Bochkanov Sergey
14141 : *************************************************************************/
14142 0 : void minasasetxrep(const minasastate &state, const bool needxrep, const xparams _xparams)
14143 : {
14144 : jmp_buf _break_jump;
14145 : alglib_impl::ae_state _alglib_env_state;
14146 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14147 0 : if( setjmp(_break_jump) )
14148 : {
14149 : #if !defined(AE_NO_EXCEPTIONS)
14150 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14151 : #else
14152 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
14153 : return;
14154 : #endif
14155 : }
14156 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14157 0 : if( _xparams.flags!=0x0 )
14158 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14159 0 : alglib_impl::minasasetxrep(const_cast<alglib_impl::minasastate*>(state.c_ptr()), needxrep, &_alglib_env_state);
14160 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14161 0 : return;
14162 : }
14163 :
14164 : /*************************************************************************
14165 : Obsolete optimization algorithm.
14166 : Was replaced by MinBLEIC subpackage.
14167 :
14168 : -- ALGLIB --
14169 : Copyright 02.04.2010 by Bochkanov Sergey
14170 : *************************************************************************/
14171 0 : void minasasetalgorithm(const minasastate &state, const ae_int_t algotype, const xparams _xparams)
14172 : {
14173 : jmp_buf _break_jump;
14174 : alglib_impl::ae_state _alglib_env_state;
14175 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14176 0 : if( setjmp(_break_jump) )
14177 : {
14178 : #if !defined(AE_NO_EXCEPTIONS)
14179 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14180 : #else
14181 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
14182 : return;
14183 : #endif
14184 : }
14185 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14186 0 : if( _xparams.flags!=0x0 )
14187 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14188 0 : alglib_impl::minasasetalgorithm(const_cast<alglib_impl::minasastate*>(state.c_ptr()), algotype, &_alglib_env_state);
14189 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14190 0 : return;
14191 : }
14192 :
14193 : /*************************************************************************
14194 : Obsolete optimization algorithm.
14195 : Was replaced by MinBLEIC subpackage.
14196 :
14197 : -- ALGLIB --
14198 : Copyright 02.04.2010 by Bochkanov Sergey
14199 : *************************************************************************/
14200 0 : void minasasetstpmax(const minasastate &state, const double stpmax, const xparams _xparams)
14201 : {
14202 : jmp_buf _break_jump;
14203 : alglib_impl::ae_state _alglib_env_state;
14204 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14205 0 : if( setjmp(_break_jump) )
14206 : {
14207 : #if !defined(AE_NO_EXCEPTIONS)
14208 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14209 : #else
14210 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
14211 : return;
14212 : #endif
14213 : }
14214 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14215 0 : if( _xparams.flags!=0x0 )
14216 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14217 0 : alglib_impl::minasasetstpmax(const_cast<alglib_impl::minasastate*>(state.c_ptr()), stpmax, &_alglib_env_state);
14218 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14219 0 : return;
14220 : }
14221 :
14222 : /*************************************************************************
14223 : This function provides reverse communication interface
14224 : Reverse communication interface is not documented or recommended to use.
14225 : See below for functions which provide better documented API
14226 : *************************************************************************/
14227 0 : bool minasaiteration(const minasastate &state, const xparams _xparams)
14228 : {
14229 : jmp_buf _break_jump;
14230 : alglib_impl::ae_state _alglib_env_state;
14231 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14232 0 : if( setjmp(_break_jump) )
14233 : {
14234 : #if !defined(AE_NO_EXCEPTIONS)
14235 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14236 : #else
14237 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
14238 : return 0;
14239 : #endif
14240 : }
14241 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14242 0 : if( _xparams.flags!=0x0 )
14243 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14244 0 : ae_bool result = alglib_impl::minasaiteration(const_cast<alglib_impl::minasastate*>(state.c_ptr()), &_alglib_env_state);
14245 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14246 0 : return *(reinterpret_cast<bool*>(&result));
14247 : }
14248 :
14249 :
14250 0 : void minasaoptimize(minasastate &state,
14251 : void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr),
14252 : void (*rep)(const real_1d_array &x, double func, void *ptr),
14253 : void *ptr,
14254 : const xparams _xparams)
14255 : {
14256 : jmp_buf _break_jump;
14257 : alglib_impl::ae_state _alglib_env_state;
14258 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14259 0 : if( setjmp(_break_jump) )
14260 : {
14261 : #if !defined(AE_NO_EXCEPTIONS)
14262 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14263 : #else
14264 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
14265 : return;
14266 : #endif
14267 : }
14268 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14269 0 : if( _xparams.flags!=0x0 )
14270 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14271 0 : alglib_impl::ae_assert(grad!=NULL, "ALGLIB: error in 'minasaoptimize()' (grad is NULL)", &_alglib_env_state);
14272 0 : while( alglib_impl::minasaiteration(state.c_ptr(), &_alglib_env_state) )
14273 : {
14274 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN
14275 0 : if( state.needfg )
14276 : {
14277 0 : grad(state.x, state.f, state.g, ptr);
14278 0 : continue;
14279 : }
14280 0 : if( state.xupdated )
14281 : {
14282 0 : if( rep!=NULL )
14283 0 : rep(state.x, state.f, ptr);
14284 0 : continue;
14285 : }
14286 0 : goto lbl_no_callback;
14287 0 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_END
14288 0 : lbl_no_callback:
14289 0 : alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minasaoptimize' (some derivatives were not provided?)", &_alglib_env_state);
14290 : }
14291 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14292 0 : }
14293 :
14294 :
14295 :
14296 : /*************************************************************************
14297 : Obsolete optimization algorithm.
14298 : Was replaced by MinBLEIC subpackage.
14299 :
14300 : -- ALGLIB --
14301 : Copyright 20.03.2009 by Bochkanov Sergey
14302 : *************************************************************************/
14303 0 : void minasaresults(const minasastate &state, real_1d_array &x, minasareport &rep, const xparams _xparams)
14304 : {
14305 : jmp_buf _break_jump;
14306 : alglib_impl::ae_state _alglib_env_state;
14307 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14308 0 : if( setjmp(_break_jump) )
14309 : {
14310 : #if !defined(AE_NO_EXCEPTIONS)
14311 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14312 : #else
14313 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
14314 : return;
14315 : #endif
14316 : }
14317 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14318 0 : if( _xparams.flags!=0x0 )
14319 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14320 0 : 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);
14321 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14322 0 : return;
14323 : }
14324 :
14325 : /*************************************************************************
14326 : Obsolete optimization algorithm.
14327 : Was replaced by MinBLEIC subpackage.
14328 :
14329 : -- ALGLIB --
14330 : Copyright 20.03.2009 by Bochkanov Sergey
14331 : *************************************************************************/
14332 0 : void minasaresultsbuf(const minasastate &state, real_1d_array &x, minasareport &rep, const xparams _xparams)
14333 : {
14334 : jmp_buf _break_jump;
14335 : alglib_impl::ae_state _alglib_env_state;
14336 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14337 0 : if( setjmp(_break_jump) )
14338 : {
14339 : #if !defined(AE_NO_EXCEPTIONS)
14340 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14341 : #else
14342 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
14343 : return;
14344 : #endif
14345 : }
14346 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14347 0 : if( _xparams.flags!=0x0 )
14348 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14349 0 : 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);
14350 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14351 0 : return;
14352 : }
14353 :
14354 : /*************************************************************************
14355 : Obsolete optimization algorithm.
14356 : Was replaced by MinBLEIC subpackage.
14357 :
14358 : -- ALGLIB --
14359 : Copyright 30.07.2010 by Bochkanov Sergey
14360 : *************************************************************************/
14361 0 : void minasarestartfrom(const minasastate &state, const real_1d_array &x, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams)
14362 : {
14363 : jmp_buf _break_jump;
14364 : alglib_impl::ae_state _alglib_env_state;
14365 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14366 0 : if( setjmp(_break_jump) )
14367 : {
14368 : #if !defined(AE_NO_EXCEPTIONS)
14369 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14370 : #else
14371 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
14372 : return;
14373 : #endif
14374 : }
14375 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14376 0 : if( _xparams.flags!=0x0 )
14377 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14378 0 : 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);
14379 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14380 0 : return;
14381 : }
14382 : #endif
14383 :
14384 : #if defined(AE_COMPILE_MINCG) || !defined(AE_PARTIAL_BUILD)
14385 : /*************************************************************************
14386 : This object stores state of the nonlinear CG optimizer.
14387 :
14388 : You should use ALGLIB functions to work with this object.
14389 : *************************************************************************/
14390 0 : _mincgstate_owner::_mincgstate_owner()
14391 : {
14392 : jmp_buf _break_jump;
14393 : alglib_impl::ae_state _state;
14394 :
14395 0 : alglib_impl::ae_state_init(&_state);
14396 0 : if( setjmp(_break_jump) )
14397 : {
14398 0 : if( p_struct!=NULL )
14399 : {
14400 0 : alglib_impl::_mincgstate_destroy(p_struct);
14401 0 : alglib_impl::ae_free(p_struct);
14402 : }
14403 0 : p_struct = NULL;
14404 : #if !defined(AE_NO_EXCEPTIONS)
14405 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
14406 : #else
14407 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
14408 : return;
14409 : #endif
14410 : }
14411 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
14412 0 : p_struct = NULL;
14413 0 : p_struct = (alglib_impl::mincgstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::mincgstate), &_state);
14414 0 : memset(p_struct, 0, sizeof(alglib_impl::mincgstate));
14415 0 : alglib_impl::_mincgstate_init(p_struct, &_state, ae_false);
14416 0 : ae_state_clear(&_state);
14417 0 : }
14418 :
14419 0 : _mincgstate_owner::_mincgstate_owner(const _mincgstate_owner &rhs)
14420 : {
14421 : jmp_buf _break_jump;
14422 : alglib_impl::ae_state _state;
14423 :
14424 0 : alglib_impl::ae_state_init(&_state);
14425 0 : if( setjmp(_break_jump) )
14426 : {
14427 0 : if( p_struct!=NULL )
14428 : {
14429 0 : alglib_impl::_mincgstate_destroy(p_struct);
14430 0 : alglib_impl::ae_free(p_struct);
14431 : }
14432 0 : p_struct = NULL;
14433 : #if !defined(AE_NO_EXCEPTIONS)
14434 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
14435 : #else
14436 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
14437 : return;
14438 : #endif
14439 : }
14440 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
14441 0 : p_struct = NULL;
14442 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: mincgstate copy constructor failure (source is not initialized)", &_state);
14443 0 : p_struct = (alglib_impl::mincgstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::mincgstate), &_state);
14444 0 : memset(p_struct, 0, sizeof(alglib_impl::mincgstate));
14445 0 : alglib_impl::_mincgstate_init_copy(p_struct, const_cast<alglib_impl::mincgstate*>(rhs.p_struct), &_state, ae_false);
14446 0 : ae_state_clear(&_state);
14447 0 : }
14448 :
14449 0 : _mincgstate_owner& _mincgstate_owner::operator=(const _mincgstate_owner &rhs)
14450 : {
14451 0 : if( this==&rhs )
14452 0 : return *this;
14453 : jmp_buf _break_jump;
14454 : alglib_impl::ae_state _state;
14455 :
14456 0 : alglib_impl::ae_state_init(&_state);
14457 0 : if( setjmp(_break_jump) )
14458 : {
14459 : #if !defined(AE_NO_EXCEPTIONS)
14460 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
14461 : #else
14462 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
14463 : return *this;
14464 : #endif
14465 : }
14466 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
14467 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: mincgstate assignment constructor failure (destination is not initialized)", &_state);
14468 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: mincgstate assignment constructor failure (source is not initialized)", &_state);
14469 0 : alglib_impl::_mincgstate_destroy(p_struct);
14470 0 : memset(p_struct, 0, sizeof(alglib_impl::mincgstate));
14471 0 : alglib_impl::_mincgstate_init_copy(p_struct, const_cast<alglib_impl::mincgstate*>(rhs.p_struct), &_state, ae_false);
14472 0 : ae_state_clear(&_state);
14473 0 : return *this;
14474 : }
14475 :
14476 0 : _mincgstate_owner::~_mincgstate_owner()
14477 : {
14478 0 : if( p_struct!=NULL )
14479 : {
14480 0 : alglib_impl::_mincgstate_destroy(p_struct);
14481 0 : ae_free(p_struct);
14482 : }
14483 0 : }
14484 :
14485 0 : alglib_impl::mincgstate* _mincgstate_owner::c_ptr()
14486 : {
14487 0 : return p_struct;
14488 : }
14489 :
14490 0 : alglib_impl::mincgstate* _mincgstate_owner::c_ptr() const
14491 : {
14492 0 : return const_cast<alglib_impl::mincgstate*>(p_struct);
14493 : }
14494 0 : 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)
14495 : {
14496 0 : }
14497 :
14498 0 : mincgstate::mincgstate(const mincgstate &rhs):_mincgstate_owner(rhs) ,needf(p_struct->needf),needfg(p_struct->needfg),xupdated(p_struct->xupdated),f(p_struct->f),g(&p_struct->g),x(&p_struct->x)
14499 : {
14500 0 : }
14501 :
14502 0 : mincgstate& mincgstate::operator=(const mincgstate &rhs)
14503 : {
14504 0 : if( this==&rhs )
14505 0 : return *this;
14506 0 : _mincgstate_owner::operator=(rhs);
14507 0 : return *this;
14508 : }
14509 :
14510 0 : mincgstate::~mincgstate()
14511 : {
14512 0 : }
14513 :
14514 :
14515 : /*************************************************************************
14516 : This structure stores optimization report:
14517 : * IterationsCount total number of inner iterations
14518 : * NFEV number of gradient evaluations
14519 : * TerminationType termination type (see below)
14520 :
14521 : TERMINATION CODES
14522 :
14523 : TerminationType field contains completion code, which can be:
14524 : -8 internal integrity control detected infinite or NAN values in
14525 : function/gradient. Abnormal termination signalled.
14526 : 1 relative function improvement is no more than EpsF.
14527 : 2 relative step is no more than EpsX.
14528 : 4 gradient norm is no more than EpsG
14529 : 5 MaxIts steps was taken
14530 : 7 stopping conditions are too stringent,
14531 : further improvement is impossible,
14532 : X contains best point found so far.
14533 : 8 terminated by user who called mincgrequesttermination(). X contains
14534 : point which was "current accepted" when termination request was
14535 : submitted.
14536 :
14537 : Other fields of this structure are not documented and should not be used!
14538 : *************************************************************************/
14539 0 : _mincgreport_owner::_mincgreport_owner()
14540 : {
14541 : jmp_buf _break_jump;
14542 : alglib_impl::ae_state _state;
14543 :
14544 0 : alglib_impl::ae_state_init(&_state);
14545 0 : if( setjmp(_break_jump) )
14546 : {
14547 0 : if( p_struct!=NULL )
14548 : {
14549 0 : alglib_impl::_mincgreport_destroy(p_struct);
14550 0 : alglib_impl::ae_free(p_struct);
14551 : }
14552 0 : p_struct = NULL;
14553 : #if !defined(AE_NO_EXCEPTIONS)
14554 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
14555 : #else
14556 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
14557 : return;
14558 : #endif
14559 : }
14560 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
14561 0 : p_struct = NULL;
14562 0 : p_struct = (alglib_impl::mincgreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::mincgreport), &_state);
14563 0 : memset(p_struct, 0, sizeof(alglib_impl::mincgreport));
14564 0 : alglib_impl::_mincgreport_init(p_struct, &_state, ae_false);
14565 0 : ae_state_clear(&_state);
14566 0 : }
14567 :
14568 0 : _mincgreport_owner::_mincgreport_owner(const _mincgreport_owner &rhs)
14569 : {
14570 : jmp_buf _break_jump;
14571 : alglib_impl::ae_state _state;
14572 :
14573 0 : alglib_impl::ae_state_init(&_state);
14574 0 : if( setjmp(_break_jump) )
14575 : {
14576 0 : if( p_struct!=NULL )
14577 : {
14578 0 : alglib_impl::_mincgreport_destroy(p_struct);
14579 0 : alglib_impl::ae_free(p_struct);
14580 : }
14581 0 : p_struct = NULL;
14582 : #if !defined(AE_NO_EXCEPTIONS)
14583 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
14584 : #else
14585 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
14586 : return;
14587 : #endif
14588 : }
14589 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
14590 0 : p_struct = NULL;
14591 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: mincgreport copy constructor failure (source is not initialized)", &_state);
14592 0 : p_struct = (alglib_impl::mincgreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::mincgreport), &_state);
14593 0 : memset(p_struct, 0, sizeof(alglib_impl::mincgreport));
14594 0 : alglib_impl::_mincgreport_init_copy(p_struct, const_cast<alglib_impl::mincgreport*>(rhs.p_struct), &_state, ae_false);
14595 0 : ae_state_clear(&_state);
14596 0 : }
14597 :
14598 0 : _mincgreport_owner& _mincgreport_owner::operator=(const _mincgreport_owner &rhs)
14599 : {
14600 0 : if( this==&rhs )
14601 0 : return *this;
14602 : jmp_buf _break_jump;
14603 : alglib_impl::ae_state _state;
14604 :
14605 0 : alglib_impl::ae_state_init(&_state);
14606 0 : if( setjmp(_break_jump) )
14607 : {
14608 : #if !defined(AE_NO_EXCEPTIONS)
14609 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
14610 : #else
14611 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
14612 : return *this;
14613 : #endif
14614 : }
14615 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
14616 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: mincgreport assignment constructor failure (destination is not initialized)", &_state);
14617 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: mincgreport assignment constructor failure (source is not initialized)", &_state);
14618 0 : alglib_impl::_mincgreport_destroy(p_struct);
14619 0 : memset(p_struct, 0, sizeof(alglib_impl::mincgreport));
14620 0 : alglib_impl::_mincgreport_init_copy(p_struct, const_cast<alglib_impl::mincgreport*>(rhs.p_struct), &_state, ae_false);
14621 0 : ae_state_clear(&_state);
14622 0 : return *this;
14623 : }
14624 :
14625 0 : _mincgreport_owner::~_mincgreport_owner()
14626 : {
14627 0 : if( p_struct!=NULL )
14628 : {
14629 0 : alglib_impl::_mincgreport_destroy(p_struct);
14630 0 : ae_free(p_struct);
14631 : }
14632 0 : }
14633 :
14634 0 : alglib_impl::mincgreport* _mincgreport_owner::c_ptr()
14635 : {
14636 0 : return p_struct;
14637 : }
14638 :
14639 0 : alglib_impl::mincgreport* _mincgreport_owner::c_ptr() const
14640 : {
14641 0 : return const_cast<alglib_impl::mincgreport*>(p_struct);
14642 : }
14643 0 : mincgreport::mincgreport() : _mincgreport_owner() ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),terminationtype(p_struct->terminationtype)
14644 : {
14645 0 : }
14646 :
14647 0 : mincgreport::mincgreport(const mincgreport &rhs):_mincgreport_owner(rhs) ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),terminationtype(p_struct->terminationtype)
14648 : {
14649 0 : }
14650 :
14651 0 : mincgreport& mincgreport::operator=(const mincgreport &rhs)
14652 : {
14653 0 : if( this==&rhs )
14654 0 : return *this;
14655 0 : _mincgreport_owner::operator=(rhs);
14656 0 : return *this;
14657 : }
14658 :
14659 0 : mincgreport::~mincgreport()
14660 : {
14661 0 : }
14662 :
14663 : /*************************************************************************
14664 : NONLINEAR CONJUGATE GRADIENT METHOD
14665 :
14666 : DESCRIPTION:
14667 : The subroutine minimizes function F(x) of N arguments by using one of the
14668 : nonlinear conjugate gradient methods.
14669 :
14670 : These CG methods are globally convergent (even on non-convex functions) as
14671 : long as grad(f) is Lipschitz continuous in a some neighborhood of the
14672 : L = { x : f(x)<=f(x0) }.
14673 :
14674 :
14675 : REQUIREMENTS:
14676 : Algorithm will request following information during its operation:
14677 : * function value F and its gradient G (simultaneously) at given point X
14678 :
14679 :
14680 : USAGE:
14681 : 1. User initializes algorithm state with MinCGCreate() call
14682 : 2. User tunes solver parameters with MinCGSetCond(), MinCGSetStpMax() and
14683 : other functions
14684 : 3. User calls MinCGOptimize() function which takes algorithm state and
14685 : pointer (delegate, etc.) to callback function which calculates F/G.
14686 : 4. User calls MinCGResults() to get solution
14687 : 5. Optionally, user may call MinCGRestartFrom() to solve another problem
14688 : with same N but another starting point and/or another function.
14689 : MinCGRestartFrom() allows to reuse already initialized structure.
14690 :
14691 :
14692 : INPUT PARAMETERS:
14693 : N - problem dimension, N>0:
14694 : * if given, only leading N elements of X are used
14695 : * if not given, automatically determined from size of X
14696 : X - starting point, array[0..N-1].
14697 :
14698 : OUTPUT PARAMETERS:
14699 : State - structure which stores algorithm state
14700 :
14701 : -- ALGLIB --
14702 : Copyright 25.03.2010 by Bochkanov Sergey
14703 : *************************************************************************/
14704 0 : void mincgcreate(const ae_int_t n, const real_1d_array &x, mincgstate &state, const xparams _xparams)
14705 : {
14706 : jmp_buf _break_jump;
14707 : alglib_impl::ae_state _alglib_env_state;
14708 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14709 0 : if( setjmp(_break_jump) )
14710 : {
14711 : #if !defined(AE_NO_EXCEPTIONS)
14712 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14713 : #else
14714 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
14715 : return;
14716 : #endif
14717 : }
14718 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14719 0 : if( _xparams.flags!=0x0 )
14720 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14721 0 : alglib_impl::mincgcreate(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::mincgstate*>(state.c_ptr()), &_alglib_env_state);
14722 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14723 0 : return;
14724 : }
14725 :
14726 : /*************************************************************************
14727 : NONLINEAR CONJUGATE GRADIENT METHOD
14728 :
14729 : DESCRIPTION:
14730 : The subroutine minimizes function F(x) of N arguments by using one of the
14731 : nonlinear conjugate gradient methods.
14732 :
14733 : These CG methods are globally convergent (even on non-convex functions) as
14734 : long as grad(f) is Lipschitz continuous in a some neighborhood of the
14735 : L = { x : f(x)<=f(x0) }.
14736 :
14737 :
14738 : REQUIREMENTS:
14739 : Algorithm will request following information during its operation:
14740 : * function value F and its gradient G (simultaneously) at given point X
14741 :
14742 :
14743 : USAGE:
14744 : 1. User initializes algorithm state with MinCGCreate() call
14745 : 2. User tunes solver parameters with MinCGSetCond(), MinCGSetStpMax() and
14746 : other functions
14747 : 3. User calls MinCGOptimize() function which takes algorithm state and
14748 : pointer (delegate, etc.) to callback function which calculates F/G.
14749 : 4. User calls MinCGResults() to get solution
14750 : 5. Optionally, user may call MinCGRestartFrom() to solve another problem
14751 : with same N but another starting point and/or another function.
14752 : MinCGRestartFrom() allows to reuse already initialized structure.
14753 :
14754 :
14755 : INPUT PARAMETERS:
14756 : N - problem dimension, N>0:
14757 : * if given, only leading N elements of X are used
14758 : * if not given, automatically determined from size of X
14759 : X - starting point, array[0..N-1].
14760 :
14761 : OUTPUT PARAMETERS:
14762 : State - structure which stores algorithm state
14763 :
14764 : -- ALGLIB --
14765 : Copyright 25.03.2010 by Bochkanov Sergey
14766 : *************************************************************************/
14767 : #if !defined(AE_NO_EXCEPTIONS)
14768 0 : void mincgcreate(const real_1d_array &x, mincgstate &state, const xparams _xparams)
14769 : {
14770 : jmp_buf _break_jump;
14771 : alglib_impl::ae_state _alglib_env_state;
14772 : ae_int_t n;
14773 :
14774 0 : n = x.length();
14775 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14776 0 : if( setjmp(_break_jump) )
14777 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14778 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14779 0 : if( _xparams.flags!=0x0 )
14780 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14781 0 : alglib_impl::mincgcreate(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::mincgstate*>(state.c_ptr()), &_alglib_env_state);
14782 :
14783 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14784 0 : return;
14785 : }
14786 : #endif
14787 :
14788 : /*************************************************************************
14789 : The subroutine is finite difference variant of MinCGCreate(). It uses
14790 : finite differences in order to differentiate target function.
14791 :
14792 : Description below contains information which is specific to this function
14793 : only. We recommend to read comments on MinCGCreate() in order to get more
14794 : information about creation of CG optimizer.
14795 :
14796 : INPUT PARAMETERS:
14797 : N - problem dimension, N>0:
14798 : * if given, only leading N elements of X are used
14799 : * if not given, automatically determined from size of X
14800 : X - starting point, array[0..N-1].
14801 : DiffStep- differentiation step, >0
14802 :
14803 : OUTPUT PARAMETERS:
14804 : State - structure which stores algorithm state
14805 :
14806 : NOTES:
14807 : 1. algorithm uses 4-point central formula for differentiation.
14808 : 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
14809 : S[] is scaling vector which can be set by MinCGSetScale() call.
14810 : 3. we recommend you to use moderate values of differentiation step. Too
14811 : large step will result in too large truncation errors, while too small
14812 : step will result in too large numerical errors. 1.0E-6 can be good
14813 : value to start with.
14814 : 4. Numerical differentiation is very inefficient - one gradient
14815 : calculation needs 4*N function evaluations. This function will work for
14816 : any N - either small (1...10), moderate (10...100) or large (100...).
14817 : However, performance penalty will be too severe for any N's except for
14818 : small ones.
14819 : We should also say that code which relies on numerical differentiation
14820 : is less robust and precise. L-BFGS needs exact gradient values.
14821 : Imprecise gradient may slow down convergence, especially on highly
14822 : nonlinear problems.
14823 : Thus we recommend to use this function for fast prototyping on small-
14824 : dimensional problems only, and to implement analytical gradient as soon
14825 : as possible.
14826 :
14827 : -- ALGLIB --
14828 : Copyright 16.05.2011 by Bochkanov Sergey
14829 : *************************************************************************/
14830 0 : void mincgcreatef(const ae_int_t n, const real_1d_array &x, const double diffstep, mincgstate &state, const xparams _xparams)
14831 : {
14832 : jmp_buf _break_jump;
14833 : alglib_impl::ae_state _alglib_env_state;
14834 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14835 0 : if( setjmp(_break_jump) )
14836 : {
14837 : #if !defined(AE_NO_EXCEPTIONS)
14838 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14839 : #else
14840 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
14841 : return;
14842 : #endif
14843 : }
14844 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14845 0 : if( _xparams.flags!=0x0 )
14846 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14847 0 : 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);
14848 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14849 0 : return;
14850 : }
14851 :
14852 : /*************************************************************************
14853 : The subroutine is finite difference variant of MinCGCreate(). It uses
14854 : finite differences in order to differentiate target function.
14855 :
14856 : Description below contains information which is specific to this function
14857 : only. We recommend to read comments on MinCGCreate() in order to get more
14858 : information about creation of CG optimizer.
14859 :
14860 : INPUT PARAMETERS:
14861 : N - problem dimension, N>0:
14862 : * if given, only leading N elements of X are used
14863 : * if not given, automatically determined from size of X
14864 : X - starting point, array[0..N-1].
14865 : DiffStep- differentiation step, >0
14866 :
14867 : OUTPUT PARAMETERS:
14868 : State - structure which stores algorithm state
14869 :
14870 : NOTES:
14871 : 1. algorithm uses 4-point central formula for differentiation.
14872 : 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
14873 : S[] is scaling vector which can be set by MinCGSetScale() call.
14874 : 3. we recommend you to use moderate values of differentiation step. Too
14875 : large step will result in too large truncation errors, while too small
14876 : step will result in too large numerical errors. 1.0E-6 can be good
14877 : value to start with.
14878 : 4. Numerical differentiation is very inefficient - one gradient
14879 : calculation needs 4*N function evaluations. This function will work for
14880 : any N - either small (1...10), moderate (10...100) or large (100...).
14881 : However, performance penalty will be too severe for any N's except for
14882 : small ones.
14883 : We should also say that code which relies on numerical differentiation
14884 : is less robust and precise. L-BFGS needs exact gradient values.
14885 : Imprecise gradient may slow down convergence, especially on highly
14886 : nonlinear problems.
14887 : Thus we recommend to use this function for fast prototyping on small-
14888 : dimensional problems only, and to implement analytical gradient as soon
14889 : as possible.
14890 :
14891 : -- ALGLIB --
14892 : Copyright 16.05.2011 by Bochkanov Sergey
14893 : *************************************************************************/
14894 : #if !defined(AE_NO_EXCEPTIONS)
14895 0 : void mincgcreatef(const real_1d_array &x, const double diffstep, mincgstate &state, const xparams _xparams)
14896 : {
14897 : jmp_buf _break_jump;
14898 : alglib_impl::ae_state _alglib_env_state;
14899 : ae_int_t n;
14900 :
14901 0 : n = x.length();
14902 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14903 0 : if( setjmp(_break_jump) )
14904 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14905 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14906 0 : if( _xparams.flags!=0x0 )
14907 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14908 0 : 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);
14909 :
14910 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14911 0 : return;
14912 : }
14913 : #endif
14914 :
14915 : /*************************************************************************
14916 : This function sets stopping conditions for CG optimization algorithm.
14917 :
14918 : INPUT PARAMETERS:
14919 : State - structure which stores algorithm state
14920 : EpsG - >=0
14921 : The subroutine finishes its work if the condition
14922 : |v|<EpsG is satisfied, where:
14923 : * |.| means Euclidian norm
14924 : * v - scaled gradient vector, v[i]=g[i]*s[i]
14925 : * g - gradient
14926 : * s - scaling coefficients set by MinCGSetScale()
14927 : EpsF - >=0
14928 : The subroutine finishes its work if on k+1-th iteration
14929 : the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
14930 : is satisfied.
14931 : EpsX - >=0
14932 : The subroutine finishes its work if on k+1-th iteration
14933 : the condition |v|<=EpsX is fulfilled, where:
14934 : * |.| means Euclidian norm
14935 : * v - scaled step vector, v[i]=dx[i]/s[i]
14936 : * dx - ste pvector, dx=X(k+1)-X(k)
14937 : * s - scaling coefficients set by MinCGSetScale()
14938 : MaxIts - maximum number of iterations. If MaxIts=0, the number of
14939 : iterations is unlimited.
14940 :
14941 : Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to
14942 : automatic stopping criterion selection (small EpsX).
14943 :
14944 : -- ALGLIB --
14945 : Copyright 02.04.2010 by Bochkanov Sergey
14946 : *************************************************************************/
14947 0 : void mincgsetcond(const mincgstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits, const xparams _xparams)
14948 : {
14949 : jmp_buf _break_jump;
14950 : alglib_impl::ae_state _alglib_env_state;
14951 0 : alglib_impl::ae_state_init(&_alglib_env_state);
14952 0 : if( setjmp(_break_jump) )
14953 : {
14954 : #if !defined(AE_NO_EXCEPTIONS)
14955 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
14956 : #else
14957 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
14958 : return;
14959 : #endif
14960 : }
14961 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
14962 0 : if( _xparams.flags!=0x0 )
14963 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
14964 0 : alglib_impl::mincgsetcond(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), epsg, epsf, epsx, maxits, &_alglib_env_state);
14965 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
14966 0 : return;
14967 : }
14968 :
14969 : /*************************************************************************
14970 : This function sets scaling coefficients for CG optimizer.
14971 :
14972 : ALGLIB optimizers use scaling matrices to test stopping conditions (step
14973 : size and gradient are scaled before comparison with tolerances). Scale of
14974 : the I-th variable is a translation invariant measure of:
14975 : a) "how large" the variable is
14976 : b) how large the step should be to make significant changes in the function
14977 :
14978 : Scaling is also used by finite difference variant of CG optimizer - step
14979 : along I-th axis is equal to DiffStep*S[I].
14980 :
14981 : In most optimizers (and in the CG too) scaling is NOT a form of
14982 : preconditioning. It just affects stopping conditions. You should set
14983 : preconditioner by separate call to one of the MinCGSetPrec...() functions.
14984 :
14985 : There is special preconditioning mode, however, which uses scaling
14986 : coefficients to form diagonal preconditioning matrix. You can turn this
14987 : mode on, if you want. But you should understand that scaling is not the
14988 : same thing as preconditioning - these are two different, although related
14989 : forms of tuning solver.
14990 :
14991 : INPUT PARAMETERS:
14992 : State - structure stores algorithm state
14993 : S - array[N], non-zero scaling coefficients
14994 : S[i] may be negative, sign doesn't matter.
14995 :
14996 : -- ALGLIB --
14997 : Copyright 14.01.2011 by Bochkanov Sergey
14998 : *************************************************************************/
14999 0 : void mincgsetscale(const mincgstate &state, const real_1d_array &s, const xparams _xparams)
15000 : {
15001 : jmp_buf _break_jump;
15002 : alglib_impl::ae_state _alglib_env_state;
15003 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15004 0 : if( setjmp(_break_jump) )
15005 : {
15006 : #if !defined(AE_NO_EXCEPTIONS)
15007 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15008 : #else
15009 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15010 : return;
15011 : #endif
15012 : }
15013 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15014 0 : if( _xparams.flags!=0x0 )
15015 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15016 0 : alglib_impl::mincgsetscale(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(s.c_ptr()), &_alglib_env_state);
15017 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15018 0 : return;
15019 : }
15020 :
15021 : /*************************************************************************
15022 : This function turns on/off reporting.
15023 :
15024 : INPUT PARAMETERS:
15025 : State - structure which stores algorithm state
15026 : NeedXRep- whether iteration reports are needed or not
15027 :
15028 : If NeedXRep is True, algorithm will call rep() callback function if it is
15029 : provided to MinCGOptimize().
15030 :
15031 : -- ALGLIB --
15032 : Copyright 02.04.2010 by Bochkanov Sergey
15033 : *************************************************************************/
15034 0 : void mincgsetxrep(const mincgstate &state, const bool needxrep, const xparams _xparams)
15035 : {
15036 : jmp_buf _break_jump;
15037 : alglib_impl::ae_state _alglib_env_state;
15038 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15039 0 : if( setjmp(_break_jump) )
15040 : {
15041 : #if !defined(AE_NO_EXCEPTIONS)
15042 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15043 : #else
15044 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15045 : return;
15046 : #endif
15047 : }
15048 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15049 0 : if( _xparams.flags!=0x0 )
15050 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15051 0 : alglib_impl::mincgsetxrep(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), needxrep, &_alglib_env_state);
15052 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15053 0 : return;
15054 : }
15055 :
15056 : /*************************************************************************
15057 : This function sets CG algorithm.
15058 :
15059 : INPUT PARAMETERS:
15060 : State - structure which stores algorithm state
15061 : CGType - algorithm type:
15062 : * -1 automatic selection of the best algorithm
15063 : * 0 DY (Dai and Yuan) algorithm
15064 : * 1 Hybrid DY-HS algorithm
15065 :
15066 : -- ALGLIB --
15067 : Copyright 02.04.2010 by Bochkanov Sergey
15068 : *************************************************************************/
15069 0 : void mincgsetcgtype(const mincgstate &state, const ae_int_t cgtype, const xparams _xparams)
15070 : {
15071 : jmp_buf _break_jump;
15072 : alglib_impl::ae_state _alglib_env_state;
15073 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15074 0 : if( setjmp(_break_jump) )
15075 : {
15076 : #if !defined(AE_NO_EXCEPTIONS)
15077 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15078 : #else
15079 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15080 : return;
15081 : #endif
15082 : }
15083 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15084 0 : if( _xparams.flags!=0x0 )
15085 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15086 0 : alglib_impl::mincgsetcgtype(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), cgtype, &_alglib_env_state);
15087 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15088 0 : return;
15089 : }
15090 :
15091 : /*************************************************************************
15092 : This function sets maximum step length
15093 :
15094 : INPUT PARAMETERS:
15095 : State - structure which stores algorithm state
15096 : StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't
15097 : want to limit step length.
15098 :
15099 : Use this subroutine when you optimize target function which contains exp()
15100 : or other fast growing functions, and optimization algorithm makes too
15101 : large steps which leads to overflow. This function allows us to reject
15102 : steps that are too large (and therefore expose us to the possible
15103 : overflow) without actually calculating function value at the x+stp*d.
15104 :
15105 : -- ALGLIB --
15106 : Copyright 02.04.2010 by Bochkanov Sergey
15107 : *************************************************************************/
15108 0 : void mincgsetstpmax(const mincgstate &state, const double stpmax, const xparams _xparams)
15109 : {
15110 : jmp_buf _break_jump;
15111 : alglib_impl::ae_state _alglib_env_state;
15112 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15113 0 : if( setjmp(_break_jump) )
15114 : {
15115 : #if !defined(AE_NO_EXCEPTIONS)
15116 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15117 : #else
15118 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15119 : return;
15120 : #endif
15121 : }
15122 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15123 0 : if( _xparams.flags!=0x0 )
15124 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15125 0 : alglib_impl::mincgsetstpmax(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), stpmax, &_alglib_env_state);
15126 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15127 0 : return;
15128 : }
15129 :
15130 : /*************************************************************************
15131 : This function allows to suggest initial step length to the CG algorithm.
15132 :
15133 : Suggested step length is used as starting point for the line search. It
15134 : can be useful when you have badly scaled problem, i.e. when ||grad||
15135 : (which is used as initial estimate for the first step) is many orders of
15136 : magnitude different from the desired step.
15137 :
15138 : Line search may fail on such problems without good estimate of initial
15139 : step length. Imagine, for example, problem with ||grad||=10^50 and desired
15140 : step equal to 0.1 Line search function will use 10^50 as initial step,
15141 : then it will decrease step length by 2 (up to 20 attempts) and will get
15142 : 10^44, which is still too large.
15143 :
15144 : This function allows us to tell than line search should be started from
15145 : some moderate step length, like 1.0, so algorithm will be able to detect
15146 : desired step length in a several searches.
15147 :
15148 : Default behavior (when no step is suggested) is to use preconditioner, if
15149 : it is available, to generate initial estimate of step length.
15150 :
15151 : This function influences only first iteration of algorithm. It should be
15152 : called between MinCGCreate/MinCGRestartFrom() call and MinCGOptimize call.
15153 : Suggested step is ignored if you have preconditioner.
15154 :
15155 : INPUT PARAMETERS:
15156 : State - structure used to store algorithm state.
15157 : Stp - initial estimate of the step length.
15158 : Can be zero (no estimate).
15159 :
15160 : -- ALGLIB --
15161 : Copyright 30.07.2010 by Bochkanov Sergey
15162 : *************************************************************************/
15163 0 : void mincgsuggeststep(const mincgstate &state, const double stp, const xparams _xparams)
15164 : {
15165 : jmp_buf _break_jump;
15166 : alglib_impl::ae_state _alglib_env_state;
15167 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15168 0 : if( setjmp(_break_jump) )
15169 : {
15170 : #if !defined(AE_NO_EXCEPTIONS)
15171 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15172 : #else
15173 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15174 : return;
15175 : #endif
15176 : }
15177 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15178 0 : if( _xparams.flags!=0x0 )
15179 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15180 0 : alglib_impl::mincgsuggeststep(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), stp, &_alglib_env_state);
15181 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15182 0 : return;
15183 : }
15184 :
15185 : /*************************************************************************
15186 : Modification of the preconditioner: preconditioning is turned off.
15187 :
15188 : INPUT PARAMETERS:
15189 : State - structure which stores algorithm state
15190 :
15191 : NOTE: you can change preconditioner "on the fly", during algorithm
15192 : iterations.
15193 :
15194 : -- ALGLIB --
15195 : Copyright 13.10.2010 by Bochkanov Sergey
15196 : *************************************************************************/
15197 0 : void mincgsetprecdefault(const mincgstate &state, const xparams _xparams)
15198 : {
15199 : jmp_buf _break_jump;
15200 : alglib_impl::ae_state _alglib_env_state;
15201 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15202 0 : if( setjmp(_break_jump) )
15203 : {
15204 : #if !defined(AE_NO_EXCEPTIONS)
15205 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15206 : #else
15207 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15208 : return;
15209 : #endif
15210 : }
15211 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15212 0 : if( _xparams.flags!=0x0 )
15213 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15214 0 : alglib_impl::mincgsetprecdefault(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), &_alglib_env_state);
15215 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15216 0 : return;
15217 : }
15218 :
15219 : /*************************************************************************
15220 : Modification of the preconditioner: diagonal of approximate Hessian is
15221 : used.
15222 :
15223 : INPUT PARAMETERS:
15224 : State - structure which stores algorithm state
15225 : D - diagonal of the approximate Hessian, array[0..N-1],
15226 : (if larger, only leading N elements are used).
15227 :
15228 : NOTE: you can change preconditioner "on the fly", during algorithm
15229 : iterations.
15230 :
15231 : NOTE 2: D[i] should be positive. Exception will be thrown otherwise.
15232 :
15233 : NOTE 3: you should pass diagonal of approximate Hessian - NOT ITS INVERSE.
15234 :
15235 : -- ALGLIB --
15236 : Copyright 13.10.2010 by Bochkanov Sergey
15237 : *************************************************************************/
15238 0 : void mincgsetprecdiag(const mincgstate &state, const real_1d_array &d, const xparams _xparams)
15239 : {
15240 : jmp_buf _break_jump;
15241 : alglib_impl::ae_state _alglib_env_state;
15242 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15243 0 : if( setjmp(_break_jump) )
15244 : {
15245 : #if !defined(AE_NO_EXCEPTIONS)
15246 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15247 : #else
15248 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15249 : return;
15250 : #endif
15251 : }
15252 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15253 0 : if( _xparams.flags!=0x0 )
15254 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15255 0 : alglib_impl::mincgsetprecdiag(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(d.c_ptr()), &_alglib_env_state);
15256 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15257 0 : return;
15258 : }
15259 :
15260 : /*************************************************************************
15261 : Modification of the preconditioner: scale-based diagonal preconditioning.
15262 :
15263 : This preconditioning mode can be useful when you don't have approximate
15264 : diagonal of Hessian, but you know that your variables are badly scaled
15265 : (for example, one variable is in [1,10], and another in [1000,100000]),
15266 : and most part of the ill-conditioning comes from different scales of vars.
15267 :
15268 : In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2),
15269 : can greatly improve convergence.
15270 :
15271 : IMPRTANT: you should set scale of your variables with MinCGSetScale() call
15272 : (before or after MinCGSetPrecScale() call). Without knowledge of the scale
15273 : of your variables scale-based preconditioner will be just unit matrix.
15274 :
15275 : INPUT PARAMETERS:
15276 : State - structure which stores algorithm state
15277 :
15278 : NOTE: you can change preconditioner "on the fly", during algorithm
15279 : iterations.
15280 :
15281 : -- ALGLIB --
15282 : Copyright 13.10.2010 by Bochkanov Sergey
15283 : *************************************************************************/
15284 0 : void mincgsetprecscale(const mincgstate &state, const xparams _xparams)
15285 : {
15286 : jmp_buf _break_jump;
15287 : alglib_impl::ae_state _alglib_env_state;
15288 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15289 0 : if( setjmp(_break_jump) )
15290 : {
15291 : #if !defined(AE_NO_EXCEPTIONS)
15292 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15293 : #else
15294 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15295 : return;
15296 : #endif
15297 : }
15298 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15299 0 : if( _xparams.flags!=0x0 )
15300 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15301 0 : alglib_impl::mincgsetprecscale(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), &_alglib_env_state);
15302 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15303 0 : return;
15304 : }
15305 :
15306 : /*************************************************************************
15307 : This function provides reverse communication interface
15308 : Reverse communication interface is not documented or recommended to use.
15309 : See below for functions which provide better documented API
15310 : *************************************************************************/
15311 0 : bool mincgiteration(const mincgstate &state, const xparams _xparams)
15312 : {
15313 : jmp_buf _break_jump;
15314 : alglib_impl::ae_state _alglib_env_state;
15315 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15316 0 : if( setjmp(_break_jump) )
15317 : {
15318 : #if !defined(AE_NO_EXCEPTIONS)
15319 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15320 : #else
15321 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15322 : return 0;
15323 : #endif
15324 : }
15325 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15326 0 : if( _xparams.flags!=0x0 )
15327 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15328 0 : ae_bool result = alglib_impl::mincgiteration(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), &_alglib_env_state);
15329 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15330 0 : return *(reinterpret_cast<bool*>(&result));
15331 : }
15332 :
15333 :
15334 0 : void mincgoptimize(mincgstate &state,
15335 : void (*func)(const real_1d_array &x, double &func, void *ptr),
15336 : void (*rep)(const real_1d_array &x, double func, void *ptr),
15337 : void *ptr,
15338 : const xparams _xparams)
15339 : {
15340 : jmp_buf _break_jump;
15341 : alglib_impl::ae_state _alglib_env_state;
15342 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15343 0 : if( setjmp(_break_jump) )
15344 : {
15345 : #if !defined(AE_NO_EXCEPTIONS)
15346 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15347 : #else
15348 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15349 : return;
15350 : #endif
15351 : }
15352 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15353 0 : if( _xparams.flags!=0x0 )
15354 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15355 0 : alglib_impl::ae_assert(func!=NULL, "ALGLIB: error in 'mincgoptimize()' (func is NULL)", &_alglib_env_state);
15356 0 : while( alglib_impl::mincgiteration(state.c_ptr(), &_alglib_env_state) )
15357 : {
15358 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN
15359 0 : if( state.needf )
15360 : {
15361 0 : func(state.x, state.f, ptr);
15362 0 : continue;
15363 : }
15364 0 : if( state.xupdated )
15365 : {
15366 0 : if( rep!=NULL )
15367 0 : rep(state.x, state.f, ptr);
15368 0 : continue;
15369 : }
15370 0 : goto lbl_no_callback;
15371 0 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_END
15372 0 : lbl_no_callback:
15373 0 : alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'mincgoptimize' (some derivatives were not provided?)", &_alglib_env_state);
15374 : }
15375 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15376 0 : }
15377 :
15378 :
15379 0 : void mincgoptimize(mincgstate &state,
15380 : void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr),
15381 : void (*rep)(const real_1d_array &x, double func, void *ptr),
15382 : void *ptr,
15383 : const xparams _xparams)
15384 : {
15385 : jmp_buf _break_jump;
15386 : alglib_impl::ae_state _alglib_env_state;
15387 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15388 0 : if( setjmp(_break_jump) )
15389 : {
15390 : #if !defined(AE_NO_EXCEPTIONS)
15391 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15392 : #else
15393 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15394 : return;
15395 : #endif
15396 : }
15397 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15398 0 : if( _xparams.flags!=0x0 )
15399 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15400 0 : alglib_impl::ae_assert(grad!=NULL, "ALGLIB: error in 'mincgoptimize()' (grad is NULL)", &_alglib_env_state);
15401 0 : while( alglib_impl::mincgiteration(state.c_ptr(), &_alglib_env_state) )
15402 : {
15403 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN
15404 0 : if( state.needfg )
15405 : {
15406 0 : grad(state.x, state.f, state.g, ptr);
15407 0 : continue;
15408 : }
15409 0 : if( state.xupdated )
15410 : {
15411 0 : if( rep!=NULL )
15412 0 : rep(state.x, state.f, ptr);
15413 0 : continue;
15414 : }
15415 0 : goto lbl_no_callback;
15416 0 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_END
15417 0 : lbl_no_callback:
15418 0 : alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'mincgoptimize' (some derivatives were not provided?)", &_alglib_env_state);
15419 : }
15420 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15421 0 : }
15422 :
15423 :
15424 :
15425 : /*************************************************************************
15426 : This function activates/deactivates verification of the user-supplied
15427 : analytic gradient.
15428 :
15429 : Upon activation of this option OptGuard integrity checker performs
15430 : numerical differentiation of your target function at the initial point
15431 : (note: future versions may also perform check at the final point) and
15432 : compares numerical gradient with analytic one provided by you.
15433 :
15434 : If difference is too large, an error flag is set and optimization session
15435 : continues. After optimization session is over, you can retrieve the report
15436 : which stores both gradients and specific components highlighted as
15437 : suspicious by the OptGuard.
15438 :
15439 : The primary OptGuard report can be retrieved with mincgoptguardresults().
15440 :
15441 : IMPORTANT: gradient check is a high-overhead option which will cost you
15442 : about 3*N additional function evaluations. In many cases it may
15443 : cost as much as the rest of the optimization session.
15444 :
15445 : YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO
15446 : CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY.
15447 :
15448 : NOTE: unlike previous incarnation of the gradient checking code, OptGuard
15449 : does NOT interrupt optimization even if it discovers bad gradient.
15450 :
15451 : INPUT PARAMETERS:
15452 : State - structure used to store algorithm state
15453 : TestStep - verification step used for numerical differentiation:
15454 : * TestStep=0 turns verification off
15455 : * TestStep>0 activates verification
15456 : You should carefully choose TestStep. Value which is
15457 : too large (so large that function behavior is non-
15458 : cubic at this scale) will lead to false alarms. Too
15459 : short step will result in rounding errors dominating
15460 : numerical derivative.
15461 :
15462 : You may use different step for different parameters by
15463 : means of setting scale with mincgsetscale().
15464 :
15465 : === EXPLANATION ==========================================================
15466 :
15467 : In order to verify gradient algorithm performs following steps:
15468 : * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i],
15469 : where X[i] is i-th component of the initial point and S[i] is a scale
15470 : of i-th parameter
15471 : * F(X) is evaluated at these trial points
15472 : * we perform one more evaluation in the middle point of the interval
15473 : * we build cubic model using function values and derivatives at trial
15474 : points and we compare its prediction with actual value in the middle
15475 : point
15476 :
15477 : -- ALGLIB --
15478 : Copyright 15.06.2014 by Bochkanov Sergey
15479 : *************************************************************************/
15480 0 : void mincgoptguardgradient(const mincgstate &state, const double teststep, const xparams _xparams)
15481 : {
15482 : jmp_buf _break_jump;
15483 : alglib_impl::ae_state _alglib_env_state;
15484 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15485 0 : if( setjmp(_break_jump) )
15486 : {
15487 : #if !defined(AE_NO_EXCEPTIONS)
15488 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15489 : #else
15490 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15491 : return;
15492 : #endif
15493 : }
15494 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15495 0 : if( _xparams.flags!=0x0 )
15496 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15497 0 : alglib_impl::mincgoptguardgradient(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), teststep, &_alglib_env_state);
15498 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15499 0 : return;
15500 : }
15501 :
15502 : /*************************************************************************
15503 : This function activates/deactivates nonsmoothness monitoring option of
15504 : the OptGuard integrity checker. Smoothness monitor silently observes
15505 : solution process and tries to detect ill-posed problems, i.e. ones with:
15506 : a) discontinuous target function (non-C0)
15507 : b) nonsmooth target function (non-C1)
15508 :
15509 : Smoothness monitoring does NOT interrupt optimization even if it suspects
15510 : that your problem is nonsmooth. It just sets corresponding flags in the
15511 : OptGuard report which can be retrieved after optimization is over.
15512 :
15513 : Smoothness monitoring is a moderate overhead option which often adds less
15514 : than 1% to the optimizer running time. Thus, you can use it even for large
15515 : scale problems.
15516 :
15517 : NOTE: OptGuard does NOT guarantee that it will always detect C0/C1
15518 : continuity violations.
15519 :
15520 : First, minor errors are hard to catch - say, a 0.0001 difference in
15521 : the model values at two sides of the gap may be due to discontinuity
15522 : of the model - or simply because the model has changed.
15523 :
15524 : Second, C1-violations are especially difficult to detect in a
15525 : noninvasive way. The optimizer usually performs very short steps
15526 : near the nonsmoothness, and differentiation usually introduces a
15527 : lot of numerical noise. It is hard to tell whether some tiny
15528 : discontinuity in the slope is due to real nonsmoothness or just due
15529 : to numerical noise alone.
15530 :
15531 : Our top priority was to avoid false positives, so in some rare cases
15532 : minor errors may went unnoticed (however, in most cases they can be
15533 : spotted with restart from different initial point).
15534 :
15535 : INPUT PARAMETERS:
15536 : state - algorithm state
15537 : level - monitoring level:
15538 : * 0 - monitoring is disabled
15539 : * 1 - noninvasive low-overhead monitoring; function values
15540 : and/or gradients are recorded, but OptGuard does not
15541 : try to perform additional evaluations in order to
15542 : get more information about suspicious locations.
15543 :
15544 : === EXPLANATION ==========================================================
15545 :
15546 : One major source of headache during optimization is the possibility of
15547 : the coding errors in the target function/constraints (or their gradients).
15548 : Such errors most often manifest themselves as discontinuity or
15549 : nonsmoothness of the target/constraints.
15550 :
15551 : Another frequent situation is when you try to optimize something involving
15552 : lots of min() and max() operations, i.e. nonsmooth target. Although not a
15553 : coding error, it is nonsmoothness anyway - and smooth optimizers usually
15554 : stop right after encountering nonsmoothness, well before reaching solution.
15555 :
15556 : OptGuard integrity checker helps you to catch such situations: it monitors
15557 : function values/gradients being passed to the optimizer and tries to
15558 : errors. Upon discovering suspicious pair of points it raises appropriate
15559 : flag (and allows you to continue optimization). When optimization is done,
15560 : you can study OptGuard result.
15561 :
15562 : -- ALGLIB --
15563 : Copyright 21.11.2018 by Bochkanov Sergey
15564 : *************************************************************************/
15565 0 : void mincgoptguardsmoothness(const mincgstate &state, const ae_int_t level, const xparams _xparams)
15566 : {
15567 : jmp_buf _break_jump;
15568 : alglib_impl::ae_state _alglib_env_state;
15569 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15570 0 : if( setjmp(_break_jump) )
15571 : {
15572 : #if !defined(AE_NO_EXCEPTIONS)
15573 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15574 : #else
15575 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15576 : return;
15577 : #endif
15578 : }
15579 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15580 0 : if( _xparams.flags!=0x0 )
15581 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15582 0 : alglib_impl::mincgoptguardsmoothness(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), level, &_alglib_env_state);
15583 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15584 0 : return;
15585 : }
15586 :
15587 : /*************************************************************************
15588 : This function activates/deactivates nonsmoothness monitoring option of
15589 : the OptGuard integrity checker. Smoothness monitor silently observes
15590 : solution process and tries to detect ill-posed problems, i.e. ones with:
15591 : a) discontinuous target function (non-C0)
15592 : b) nonsmooth target function (non-C1)
15593 :
15594 : Smoothness monitoring does NOT interrupt optimization even if it suspects
15595 : that your problem is nonsmooth. It just sets corresponding flags in the
15596 : OptGuard report which can be retrieved after optimization is over.
15597 :
15598 : Smoothness monitoring is a moderate overhead option which often adds less
15599 : than 1% to the optimizer running time. Thus, you can use it even for large
15600 : scale problems.
15601 :
15602 : NOTE: OptGuard does NOT guarantee that it will always detect C0/C1
15603 : continuity violations.
15604 :
15605 : First, minor errors are hard to catch - say, a 0.0001 difference in
15606 : the model values at two sides of the gap may be due to discontinuity
15607 : of the model - or simply because the model has changed.
15608 :
15609 : Second, C1-violations are especially difficult to detect in a
15610 : noninvasive way. The optimizer usually performs very short steps
15611 : near the nonsmoothness, and differentiation usually introduces a
15612 : lot of numerical noise. It is hard to tell whether some tiny
15613 : discontinuity in the slope is due to real nonsmoothness or just due
15614 : to numerical noise alone.
15615 :
15616 : Our top priority was to avoid false positives, so in some rare cases
15617 : minor errors may went unnoticed (however, in most cases they can be
15618 : spotted with restart from different initial point).
15619 :
15620 : INPUT PARAMETERS:
15621 : state - algorithm state
15622 : level - monitoring level:
15623 : * 0 - monitoring is disabled
15624 : * 1 - noninvasive low-overhead monitoring; function values
15625 : and/or gradients are recorded, but OptGuard does not
15626 : try to perform additional evaluations in order to
15627 : get more information about suspicious locations.
15628 :
15629 : === EXPLANATION ==========================================================
15630 :
15631 : One major source of headache during optimization is the possibility of
15632 : the coding errors in the target function/constraints (or their gradients).
15633 : Such errors most often manifest themselves as discontinuity or
15634 : nonsmoothness of the target/constraints.
15635 :
15636 : Another frequent situation is when you try to optimize something involving
15637 : lots of min() and max() operations, i.e. nonsmooth target. Although not a
15638 : coding error, it is nonsmoothness anyway - and smooth optimizers usually
15639 : stop right after encountering nonsmoothness, well before reaching solution.
15640 :
15641 : OptGuard integrity checker helps you to catch such situations: it monitors
15642 : function values/gradients being passed to the optimizer and tries to
15643 : errors. Upon discovering suspicious pair of points it raises appropriate
15644 : flag (and allows you to continue optimization). When optimization is done,
15645 : you can study OptGuard result.
15646 :
15647 : -- ALGLIB --
15648 : Copyright 21.11.2018 by Bochkanov Sergey
15649 : *************************************************************************/
15650 : #if !defined(AE_NO_EXCEPTIONS)
15651 0 : void mincgoptguardsmoothness(const mincgstate &state, const xparams _xparams)
15652 : {
15653 : jmp_buf _break_jump;
15654 : alglib_impl::ae_state _alglib_env_state;
15655 : ae_int_t level;
15656 :
15657 0 : level = 1;
15658 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15659 0 : if( setjmp(_break_jump) )
15660 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15661 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15662 0 : if( _xparams.flags!=0x0 )
15663 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15664 0 : alglib_impl::mincgoptguardsmoothness(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), level, &_alglib_env_state);
15665 :
15666 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15667 0 : return;
15668 : }
15669 : #endif
15670 :
15671 : /*************************************************************************
15672 : Results of OptGuard integrity check, should be called after optimization
15673 : session is over.
15674 :
15675 : === PRIMARY REPORT =======================================================
15676 :
15677 : OptGuard performs several checks which are intended to catch common errors
15678 : in the implementation of nonlinear function/gradient:
15679 : * incorrect analytic gradient
15680 : * discontinuous (non-C0) target functions (constraints)
15681 : * nonsmooth (non-C1) target functions (constraints)
15682 :
15683 : Each of these checks is activated with appropriate function:
15684 : * mincgoptguardgradient() for gradient verification
15685 : * mincgoptguardsmoothness() for C0/C1 checks
15686 :
15687 : Following flags are set when these errors are suspected:
15688 : * rep.badgradsuspected, and additionally:
15689 : * rep.badgradvidx for specific variable (gradient element) suspected
15690 : * rep.badgradxbase, a point where gradient is tested
15691 : * rep.badgraduser, user-provided gradient (stored as 2D matrix with
15692 : single row in order to make report structure compatible with more
15693 : complex optimizers like MinNLC or MinLM)
15694 : * rep.badgradnum, reference gradient obtained via numerical
15695 : differentiation (stored as 2D matrix with single row in order to make
15696 : report structure compatible with more complex optimizers like MinNLC
15697 : or MinLM)
15698 : * rep.nonc0suspected
15699 : * rep.nonc1suspected
15700 :
15701 : === ADDITIONAL REPORTS/LOGS ==============================================
15702 :
15703 : Several different tests are performed to catch C0/C1 errors, you can find
15704 : out specific test signaled error by looking to:
15705 : * rep.nonc0test0positive, for non-C0 test #0
15706 : * rep.nonc1test0positive, for non-C1 test #0
15707 : * rep.nonc1test1positive, for non-C1 test #1
15708 :
15709 : Additional information (including line search logs) can be obtained by
15710 : means of:
15711 : * mincgoptguardnonc1test0results()
15712 : * mincgoptguardnonc1test1results()
15713 : which return detailed error reports, specific points where discontinuities
15714 : were found, and so on.
15715 :
15716 : ==========================================================================
15717 :
15718 : INPUT PARAMETERS:
15719 : state - algorithm state
15720 :
15721 : OUTPUT PARAMETERS:
15722 : rep - generic OptGuard report; more detailed reports can be
15723 : retrieved with other functions.
15724 :
15725 : NOTE: false negatives (nonsmooth problems are not identified as nonsmooth
15726 : ones) are possible although unlikely.
15727 :
15728 : The reason is that you need to make several evaluations around
15729 : nonsmoothness in order to accumulate enough information about
15730 : function curvature. Say, if you start right from the nonsmooth point,
15731 : optimizer simply won't get enough data to understand what is going
15732 : wrong before it terminates due to abrupt changes in the derivative.
15733 : It is also possible that "unlucky" step will move us to the
15734 : termination too quickly.
15735 :
15736 : Our current approach is to have less than 0.1% false negatives in
15737 : our test examples (measured with multiple restarts from random
15738 : points), and to have exactly 0% false positives.
15739 :
15740 : -- ALGLIB --
15741 : Copyright 21.11.2018 by Bochkanov Sergey
15742 : *************************************************************************/
15743 0 : void mincgoptguardresults(const mincgstate &state, optguardreport &rep, const xparams _xparams)
15744 : {
15745 : jmp_buf _break_jump;
15746 : alglib_impl::ae_state _alglib_env_state;
15747 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15748 0 : if( setjmp(_break_jump) )
15749 : {
15750 : #if !defined(AE_NO_EXCEPTIONS)
15751 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15752 : #else
15753 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15754 : return;
15755 : #endif
15756 : }
15757 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15758 0 : if( _xparams.flags!=0x0 )
15759 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15760 0 : alglib_impl::mincgoptguardresults(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), const_cast<alglib_impl::optguardreport*>(rep.c_ptr()), &_alglib_env_state);
15761 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15762 0 : return;
15763 : }
15764 :
15765 : /*************************************************************************
15766 : Detailed results of the OptGuard integrity check for nonsmoothness test #0
15767 :
15768 : Nonsmoothness (non-C1) test #0 studies function values (not gradient!)
15769 : obtained during line searches and monitors behavior of the directional
15770 : derivative estimate.
15771 :
15772 : This test is less powerful than test #1, but it does not depend on the
15773 : gradient values and thus it is more robust against artifacts introduced by
15774 : numerical differentiation.
15775 :
15776 : Two reports are returned:
15777 : * a "strongest" one, corresponding to line search which had highest
15778 : value of the nonsmoothness indicator
15779 : * a "longest" one, corresponding to line search which had more function
15780 : evaluations, and thus is more detailed
15781 :
15782 : In both cases following fields are returned:
15783 :
15784 : * positive - is TRUE when test flagged suspicious point; FALSE if test
15785 : did not notice anything (in the latter cases fields below are empty).
15786 : * x0[], d[] - arrays of length N which store initial point and direction
15787 : for line search (d[] can be normalized, but does not have to)
15788 : * stp[], f[] - arrays of length CNT which store step lengths and function
15789 : values at these points; f[i] is evaluated in x0+stp[i]*d.
15790 : * stpidxa, stpidxb - we suspect that function violates C1 continuity
15791 : between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3,
15792 : with most likely position of the violation between stpidxa+1 and
15793 : stpidxa+2.
15794 :
15795 : ==========================================================================
15796 : = SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will
15797 : = see where C1 continuity is violated.
15798 : ==========================================================================
15799 :
15800 : INPUT PARAMETERS:
15801 : state - algorithm state
15802 :
15803 : OUTPUT PARAMETERS:
15804 : strrep - C1 test #0 "strong" report
15805 : lngrep - C1 test #0 "long" report
15806 :
15807 : -- ALGLIB --
15808 : Copyright 21.11.2018 by Bochkanov Sergey
15809 : *************************************************************************/
15810 0 : void mincgoptguardnonc1test0results(const mincgstate &state, optguardnonc1test0report &strrep, optguardnonc1test0report &lngrep, const xparams _xparams)
15811 : {
15812 : jmp_buf _break_jump;
15813 : alglib_impl::ae_state _alglib_env_state;
15814 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15815 0 : if( setjmp(_break_jump) )
15816 : {
15817 : #if !defined(AE_NO_EXCEPTIONS)
15818 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15819 : #else
15820 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15821 : return;
15822 : #endif
15823 : }
15824 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15825 0 : if( _xparams.flags!=0x0 )
15826 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15827 0 : alglib_impl::mincgoptguardnonc1test0results(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), const_cast<alglib_impl::optguardnonc1test0report*>(strrep.c_ptr()), const_cast<alglib_impl::optguardnonc1test0report*>(lngrep.c_ptr()), &_alglib_env_state);
15828 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15829 0 : return;
15830 : }
15831 :
15832 : /*************************************************************************
15833 : Detailed results of the OptGuard integrity check for nonsmoothness test #1
15834 :
15835 : Nonsmoothness (non-C1) test #1 studies individual components of the
15836 : gradient computed during line search.
15837 :
15838 : When precise analytic gradient is provided this test is more powerful than
15839 : test #0 which works with function values and ignores user-provided
15840 : gradient. However, test #0 becomes more powerful when numerical
15841 : differentiation is employed (in such cases test #1 detects higher levels
15842 : of numerical noise and becomes too conservative).
15843 :
15844 : This test also tells specific components of the gradient which violate C1
15845 : continuity, which makes it more informative than #0, which just tells that
15846 : continuity is violated.
15847 :
15848 : Two reports are returned:
15849 : * a "strongest" one, corresponding to line search which had highest
15850 : value of the nonsmoothness indicator
15851 : * a "longest" one, corresponding to line search which had more function
15852 : evaluations, and thus is more detailed
15853 :
15854 : In both cases following fields are returned:
15855 :
15856 : * positive - is TRUE when test flagged suspicious point; FALSE if test
15857 : did not notice anything (in the latter cases fields below are empty).
15858 : * vidx - is an index of the variable in [0,N) with nonsmooth derivative
15859 : * x0[], d[] - arrays of length N which store initial point and direction
15860 : for line search (d[] can be normalized, but does not have to)
15861 : * stp[], g[] - arrays of length CNT which store step lengths and gradient
15862 : values at these points; g[i] is evaluated in x0+stp[i]*d and contains
15863 : vidx-th component of the gradient.
15864 : * stpidxa, stpidxb - we suspect that function violates C1 continuity
15865 : between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3,
15866 : with most likely position of the violation between stpidxa+1 and
15867 : stpidxa+2.
15868 :
15869 : ==========================================================================
15870 : = SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will
15871 : = see where C1 continuity is violated.
15872 : ==========================================================================
15873 :
15874 : INPUT PARAMETERS:
15875 : state - algorithm state
15876 :
15877 : OUTPUT PARAMETERS:
15878 : strrep - C1 test #1 "strong" report
15879 : lngrep - C1 test #1 "long" report
15880 :
15881 : -- ALGLIB --
15882 : Copyright 21.11.2018 by Bochkanov Sergey
15883 : *************************************************************************/
15884 0 : void mincgoptguardnonc1test1results(const mincgstate &state, optguardnonc1test1report &strrep, optguardnonc1test1report &lngrep, const xparams _xparams)
15885 : {
15886 : jmp_buf _break_jump;
15887 : alglib_impl::ae_state _alglib_env_state;
15888 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15889 0 : if( setjmp(_break_jump) )
15890 : {
15891 : #if !defined(AE_NO_EXCEPTIONS)
15892 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15893 : #else
15894 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15895 : return;
15896 : #endif
15897 : }
15898 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15899 0 : if( _xparams.flags!=0x0 )
15900 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15901 0 : alglib_impl::mincgoptguardnonc1test1results(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), const_cast<alglib_impl::optguardnonc1test1report*>(strrep.c_ptr()), const_cast<alglib_impl::optguardnonc1test1report*>(lngrep.c_ptr()), &_alglib_env_state);
15902 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15903 0 : return;
15904 : }
15905 :
15906 : /*************************************************************************
15907 : Conjugate gradient results
15908 :
15909 : INPUT PARAMETERS:
15910 : State - algorithm state
15911 :
15912 : OUTPUT PARAMETERS:
15913 : X - array[0..N-1], solution
15914 : Rep - optimization report:
15915 : * Rep.TerminationType completetion code:
15916 : * -8 internal integrity control detected infinite
15917 : or NAN values in function/gradient. Abnormal
15918 : termination signalled.
15919 : * -7 gradient verification failed.
15920 : See MinCGSetGradientCheck() for more information.
15921 : * 1 relative function improvement is no more than
15922 : EpsF.
15923 : * 2 relative step is no more than EpsX.
15924 : * 4 gradient norm is no more than EpsG
15925 : * 5 MaxIts steps was taken
15926 : * 7 stopping conditions are too stringent,
15927 : further improvement is impossible,
15928 : we return best X found so far
15929 : * 8 terminated by user
15930 : * Rep.IterationsCount contains iterations count
15931 : * NFEV countains number of function calculations
15932 :
15933 : -- ALGLIB --
15934 : Copyright 20.04.2009 by Bochkanov Sergey
15935 : *************************************************************************/
15936 0 : void mincgresults(const mincgstate &state, real_1d_array &x, mincgreport &rep, const xparams _xparams)
15937 : {
15938 : jmp_buf _break_jump;
15939 : alglib_impl::ae_state _alglib_env_state;
15940 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15941 0 : if( setjmp(_break_jump) )
15942 : {
15943 : #if !defined(AE_NO_EXCEPTIONS)
15944 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15945 : #else
15946 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15947 : return;
15948 : #endif
15949 : }
15950 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15951 0 : if( _xparams.flags!=0x0 )
15952 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15953 0 : 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);
15954 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15955 0 : return;
15956 : }
15957 :
15958 : /*************************************************************************
15959 : Conjugate gradient results
15960 :
15961 : Buffered implementation of MinCGResults(), which uses pre-allocated buffer
15962 : to store X[]. If buffer size is too small, it resizes buffer. It is
15963 : intended to be used in the inner cycles of performance critical algorithms
15964 : where array reallocation penalty is too large to be ignored.
15965 :
15966 : -- ALGLIB --
15967 : Copyright 20.04.2009 by Bochkanov Sergey
15968 : *************************************************************************/
15969 0 : void mincgresultsbuf(const mincgstate &state, real_1d_array &x, mincgreport &rep, const xparams _xparams)
15970 : {
15971 : jmp_buf _break_jump;
15972 : alglib_impl::ae_state _alglib_env_state;
15973 0 : alglib_impl::ae_state_init(&_alglib_env_state);
15974 0 : if( setjmp(_break_jump) )
15975 : {
15976 : #if !defined(AE_NO_EXCEPTIONS)
15977 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
15978 : #else
15979 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
15980 : return;
15981 : #endif
15982 : }
15983 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
15984 0 : if( _xparams.flags!=0x0 )
15985 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
15986 0 : 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);
15987 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
15988 0 : return;
15989 : }
15990 :
15991 : /*************************************************************************
15992 : This subroutine restarts CG algorithm from new point. All optimization
15993 : parameters are left unchanged.
15994 :
15995 : This function allows to solve multiple optimization problems (which
15996 : must have same number of dimensions) without object reallocation penalty.
15997 :
15998 : INPUT PARAMETERS:
15999 : State - structure used to store algorithm state.
16000 : X - new starting point.
16001 :
16002 : -- ALGLIB --
16003 : Copyright 30.07.2010 by Bochkanov Sergey
16004 : *************************************************************************/
16005 0 : void mincgrestartfrom(const mincgstate &state, const real_1d_array &x, const xparams _xparams)
16006 : {
16007 : jmp_buf _break_jump;
16008 : alglib_impl::ae_state _alglib_env_state;
16009 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16010 0 : if( setjmp(_break_jump) )
16011 : {
16012 : #if !defined(AE_NO_EXCEPTIONS)
16013 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16014 : #else
16015 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16016 : return;
16017 : #endif
16018 : }
16019 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16020 0 : if( _xparams.flags!=0x0 )
16021 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16022 0 : alglib_impl::mincgrestartfrom(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
16023 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16024 0 : return;
16025 : }
16026 :
16027 : /*************************************************************************
16028 : This subroutine submits request for termination of running optimizer. It
16029 : should be called from user-supplied callback when user decides that it is
16030 : time to "smoothly" terminate optimization process. As result, optimizer
16031 : stops at point which was "current accepted" when termination request was
16032 : submitted and returns error code 8 (successful termination).
16033 :
16034 : INPUT PARAMETERS:
16035 : State - optimizer structure
16036 :
16037 : NOTE: after request for termination optimizer may perform several
16038 : additional calls to user-supplied callbacks. It does NOT guarantee
16039 : to stop immediately - it just guarantees that these additional calls
16040 : will be discarded later.
16041 :
16042 : NOTE: calling this function on optimizer which is NOT running will have no
16043 : effect.
16044 :
16045 : NOTE: multiple calls to this function are possible. First call is counted,
16046 : subsequent calls are silently ignored.
16047 :
16048 : -- ALGLIB --
16049 : Copyright 08.10.2014 by Bochkanov Sergey
16050 : *************************************************************************/
16051 0 : void mincgrequesttermination(const mincgstate &state, const xparams _xparams)
16052 : {
16053 : jmp_buf _break_jump;
16054 : alglib_impl::ae_state _alglib_env_state;
16055 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16056 0 : if( setjmp(_break_jump) )
16057 : {
16058 : #if !defined(AE_NO_EXCEPTIONS)
16059 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16060 : #else
16061 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16062 : return;
16063 : #endif
16064 : }
16065 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16066 0 : if( _xparams.flags!=0x0 )
16067 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16068 0 : alglib_impl::mincgrequesttermination(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), &_alglib_env_state);
16069 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16070 0 : return;
16071 : }
16072 : #endif
16073 :
16074 : #if defined(AE_COMPILE_MINLM) || !defined(AE_PARTIAL_BUILD)
16075 : /*************************************************************************
16076 : Levenberg-Marquardt optimizer.
16077 :
16078 : This structure should be created using one of the MinLMCreate???()
16079 : functions. You should not access its fields directly; use ALGLIB functions
16080 : to work with it.
16081 : *************************************************************************/
16082 0 : _minlmstate_owner::_minlmstate_owner()
16083 : {
16084 : jmp_buf _break_jump;
16085 : alglib_impl::ae_state _state;
16086 :
16087 0 : alglib_impl::ae_state_init(&_state);
16088 0 : if( setjmp(_break_jump) )
16089 : {
16090 0 : if( p_struct!=NULL )
16091 : {
16092 0 : alglib_impl::_minlmstate_destroy(p_struct);
16093 0 : alglib_impl::ae_free(p_struct);
16094 : }
16095 0 : p_struct = NULL;
16096 : #if !defined(AE_NO_EXCEPTIONS)
16097 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
16098 : #else
16099 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
16100 : return;
16101 : #endif
16102 : }
16103 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
16104 0 : p_struct = NULL;
16105 0 : p_struct = (alglib_impl::minlmstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlmstate), &_state);
16106 0 : memset(p_struct, 0, sizeof(alglib_impl::minlmstate));
16107 0 : alglib_impl::_minlmstate_init(p_struct, &_state, ae_false);
16108 0 : ae_state_clear(&_state);
16109 0 : }
16110 :
16111 0 : _minlmstate_owner::_minlmstate_owner(const _minlmstate_owner &rhs)
16112 : {
16113 : jmp_buf _break_jump;
16114 : alglib_impl::ae_state _state;
16115 :
16116 0 : alglib_impl::ae_state_init(&_state);
16117 0 : if( setjmp(_break_jump) )
16118 : {
16119 0 : if( p_struct!=NULL )
16120 : {
16121 0 : alglib_impl::_minlmstate_destroy(p_struct);
16122 0 : alglib_impl::ae_free(p_struct);
16123 : }
16124 0 : p_struct = NULL;
16125 : #if !defined(AE_NO_EXCEPTIONS)
16126 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
16127 : #else
16128 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
16129 : return;
16130 : #endif
16131 : }
16132 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
16133 0 : p_struct = NULL;
16134 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlmstate copy constructor failure (source is not initialized)", &_state);
16135 0 : p_struct = (alglib_impl::minlmstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlmstate), &_state);
16136 0 : memset(p_struct, 0, sizeof(alglib_impl::minlmstate));
16137 0 : alglib_impl::_minlmstate_init_copy(p_struct, const_cast<alglib_impl::minlmstate*>(rhs.p_struct), &_state, ae_false);
16138 0 : ae_state_clear(&_state);
16139 0 : }
16140 :
16141 0 : _minlmstate_owner& _minlmstate_owner::operator=(const _minlmstate_owner &rhs)
16142 : {
16143 0 : if( this==&rhs )
16144 0 : return *this;
16145 : jmp_buf _break_jump;
16146 : alglib_impl::ae_state _state;
16147 :
16148 0 : alglib_impl::ae_state_init(&_state);
16149 0 : if( setjmp(_break_jump) )
16150 : {
16151 : #if !defined(AE_NO_EXCEPTIONS)
16152 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
16153 : #else
16154 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
16155 : return *this;
16156 : #endif
16157 : }
16158 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
16159 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minlmstate assignment constructor failure (destination is not initialized)", &_state);
16160 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlmstate assignment constructor failure (source is not initialized)", &_state);
16161 0 : alglib_impl::_minlmstate_destroy(p_struct);
16162 0 : memset(p_struct, 0, sizeof(alglib_impl::minlmstate));
16163 0 : alglib_impl::_minlmstate_init_copy(p_struct, const_cast<alglib_impl::minlmstate*>(rhs.p_struct), &_state, ae_false);
16164 0 : ae_state_clear(&_state);
16165 0 : return *this;
16166 : }
16167 :
16168 0 : _minlmstate_owner::~_minlmstate_owner()
16169 : {
16170 0 : if( p_struct!=NULL )
16171 : {
16172 0 : alglib_impl::_minlmstate_destroy(p_struct);
16173 0 : ae_free(p_struct);
16174 : }
16175 0 : }
16176 :
16177 0 : alglib_impl::minlmstate* _minlmstate_owner::c_ptr()
16178 : {
16179 0 : return p_struct;
16180 : }
16181 :
16182 0 : alglib_impl::minlmstate* _minlmstate_owner::c_ptr() const
16183 : {
16184 0 : return const_cast<alglib_impl::minlmstate*>(p_struct);
16185 : }
16186 0 : 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)
16187 : {
16188 0 : }
16189 :
16190 0 : minlmstate::minlmstate(const minlmstate &rhs):_minlmstate_owner(rhs) ,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)
16191 : {
16192 0 : }
16193 :
16194 0 : minlmstate& minlmstate::operator=(const minlmstate &rhs)
16195 : {
16196 0 : if( this==&rhs )
16197 0 : return *this;
16198 0 : _minlmstate_owner::operator=(rhs);
16199 0 : return *this;
16200 : }
16201 :
16202 0 : minlmstate::~minlmstate()
16203 : {
16204 0 : }
16205 :
16206 :
16207 : /*************************************************************************
16208 : Optimization report, filled by MinLMResults() function
16209 :
16210 : FIELDS:
16211 : * TerminationType, completetion code:
16212 : * -8 optimizer detected NAN/INF values either in the function itself,
16213 : or in its Jacobian
16214 : * -5 inappropriate solver was used:
16215 : * solver created with minlmcreatefgh() used on problem with
16216 : general linear constraints (set with minlmsetlc() call).
16217 : * -3 constraints are inconsistent
16218 : * 2 relative step is no more than EpsX.
16219 : * 5 MaxIts steps was taken
16220 : * 7 stopping conditions are too stringent,
16221 : further improvement is impossible
16222 : * 8 terminated by user who called MinLMRequestTermination().
16223 : X contains point which was "current accepted" when termination
16224 : request was submitted.
16225 : * IterationsCount, contains iterations count
16226 : * NFunc, number of function calculations
16227 : * NJac, number of Jacobi matrix calculations
16228 : * NGrad, number of gradient calculations
16229 : * NHess, number of Hessian calculations
16230 : * NCholesky, number of Cholesky decomposition calculations
16231 : *************************************************************************/
16232 0 : _minlmreport_owner::_minlmreport_owner()
16233 : {
16234 : jmp_buf _break_jump;
16235 : alglib_impl::ae_state _state;
16236 :
16237 0 : alglib_impl::ae_state_init(&_state);
16238 0 : if( setjmp(_break_jump) )
16239 : {
16240 0 : if( p_struct!=NULL )
16241 : {
16242 0 : alglib_impl::_minlmreport_destroy(p_struct);
16243 0 : alglib_impl::ae_free(p_struct);
16244 : }
16245 0 : p_struct = NULL;
16246 : #if !defined(AE_NO_EXCEPTIONS)
16247 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
16248 : #else
16249 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
16250 : return;
16251 : #endif
16252 : }
16253 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
16254 0 : p_struct = NULL;
16255 0 : p_struct = (alglib_impl::minlmreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlmreport), &_state);
16256 0 : memset(p_struct, 0, sizeof(alglib_impl::minlmreport));
16257 0 : alglib_impl::_minlmreport_init(p_struct, &_state, ae_false);
16258 0 : ae_state_clear(&_state);
16259 0 : }
16260 :
16261 0 : _minlmreport_owner::_minlmreport_owner(const _minlmreport_owner &rhs)
16262 : {
16263 : jmp_buf _break_jump;
16264 : alglib_impl::ae_state _state;
16265 :
16266 0 : alglib_impl::ae_state_init(&_state);
16267 0 : if( setjmp(_break_jump) )
16268 : {
16269 0 : if( p_struct!=NULL )
16270 : {
16271 0 : alglib_impl::_minlmreport_destroy(p_struct);
16272 0 : alglib_impl::ae_free(p_struct);
16273 : }
16274 0 : p_struct = NULL;
16275 : #if !defined(AE_NO_EXCEPTIONS)
16276 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
16277 : #else
16278 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
16279 : return;
16280 : #endif
16281 : }
16282 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
16283 0 : p_struct = NULL;
16284 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlmreport copy constructor failure (source is not initialized)", &_state);
16285 0 : p_struct = (alglib_impl::minlmreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::minlmreport), &_state);
16286 0 : memset(p_struct, 0, sizeof(alglib_impl::minlmreport));
16287 0 : alglib_impl::_minlmreport_init_copy(p_struct, const_cast<alglib_impl::minlmreport*>(rhs.p_struct), &_state, ae_false);
16288 0 : ae_state_clear(&_state);
16289 0 : }
16290 :
16291 0 : _minlmreport_owner& _minlmreport_owner::operator=(const _minlmreport_owner &rhs)
16292 : {
16293 0 : if( this==&rhs )
16294 0 : return *this;
16295 : jmp_buf _break_jump;
16296 : alglib_impl::ae_state _state;
16297 :
16298 0 : alglib_impl::ae_state_init(&_state);
16299 0 : if( setjmp(_break_jump) )
16300 : {
16301 : #if !defined(AE_NO_EXCEPTIONS)
16302 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
16303 : #else
16304 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
16305 : return *this;
16306 : #endif
16307 : }
16308 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
16309 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: minlmreport assignment constructor failure (destination is not initialized)", &_state);
16310 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: minlmreport assignment constructor failure (source is not initialized)", &_state);
16311 0 : alglib_impl::_minlmreport_destroy(p_struct);
16312 0 : memset(p_struct, 0, sizeof(alglib_impl::minlmreport));
16313 0 : alglib_impl::_minlmreport_init_copy(p_struct, const_cast<alglib_impl::minlmreport*>(rhs.p_struct), &_state, ae_false);
16314 0 : ae_state_clear(&_state);
16315 0 : return *this;
16316 : }
16317 :
16318 0 : _minlmreport_owner::~_minlmreport_owner()
16319 : {
16320 0 : if( p_struct!=NULL )
16321 : {
16322 0 : alglib_impl::_minlmreport_destroy(p_struct);
16323 0 : ae_free(p_struct);
16324 : }
16325 0 : }
16326 :
16327 0 : alglib_impl::minlmreport* _minlmreport_owner::c_ptr()
16328 : {
16329 0 : return p_struct;
16330 : }
16331 :
16332 0 : alglib_impl::minlmreport* _minlmreport_owner::c_ptr() const
16333 : {
16334 0 : return const_cast<alglib_impl::minlmreport*>(p_struct);
16335 : }
16336 0 : minlmreport::minlmreport() : _minlmreport_owner() ,iterationscount(p_struct->iterationscount),terminationtype(p_struct->terminationtype),nfunc(p_struct->nfunc),njac(p_struct->njac),ngrad(p_struct->ngrad),nhess(p_struct->nhess),ncholesky(p_struct->ncholesky)
16337 : {
16338 0 : }
16339 :
16340 0 : minlmreport::minlmreport(const minlmreport &rhs):_minlmreport_owner(rhs) ,iterationscount(p_struct->iterationscount),terminationtype(p_struct->terminationtype),nfunc(p_struct->nfunc),njac(p_struct->njac),ngrad(p_struct->ngrad),nhess(p_struct->nhess),ncholesky(p_struct->ncholesky)
16341 : {
16342 0 : }
16343 :
16344 0 : minlmreport& minlmreport::operator=(const minlmreport &rhs)
16345 : {
16346 0 : if( this==&rhs )
16347 0 : return *this;
16348 0 : _minlmreport_owner::operator=(rhs);
16349 0 : return *this;
16350 : }
16351 :
16352 0 : minlmreport::~minlmreport()
16353 : {
16354 0 : }
16355 :
16356 : /*************************************************************************
16357 : IMPROVED LEVENBERG-MARQUARDT METHOD FOR
16358 : NON-LINEAR LEAST SQUARES OPTIMIZATION
16359 :
16360 : DESCRIPTION:
16361 : This function is used to find minimum of function which is represented as
16362 : sum of squares:
16363 : F(x) = f[0]^2(x[0],...,x[n-1]) + ... + f[m-1]^2(x[0],...,x[n-1])
16364 : using value of function vector f[] and Jacobian of f[].
16365 :
16366 :
16367 : REQUIREMENTS:
16368 : This algorithm will request following information during its operation:
16369 :
16370 : * function vector f[] at given point X
16371 : * function vector f[] and Jacobian of f[] (simultaneously) at given point
16372 :
16373 : There are several overloaded versions of MinLMOptimize() function which
16374 : correspond to different LM-like optimization algorithms provided by this
16375 : unit. You should choose version which accepts fvec() and jac() callbacks.
16376 : First one is used to calculate f[] at given point, second one calculates
16377 : f[] and Jacobian df[i]/dx[j].
16378 :
16379 : You can try to initialize MinLMState structure with VJ function and then
16380 : use incorrect version of MinLMOptimize() (for example, version which
16381 : works with general form function and does not provide Jacobian), but it
16382 : will lead to exception being thrown after first attempt to calculate
16383 : Jacobian.
16384 :
16385 :
16386 : USAGE:
16387 : 1. User initializes algorithm state with MinLMCreateVJ() call
16388 : 2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and
16389 : other functions
16390 : 3. User calls MinLMOptimize() function which takes algorithm state and
16391 : callback functions.
16392 : 4. User calls MinLMResults() to get solution
16393 : 5. Optionally, user may call MinLMRestartFrom() to solve another problem
16394 : with same N/M but another starting point and/or another function.
16395 : MinLMRestartFrom() allows to reuse already initialized structure.
16396 :
16397 :
16398 : INPUT PARAMETERS:
16399 : N - dimension, N>1
16400 : * if given, only leading N elements of X are used
16401 : * if not given, automatically determined from size of X
16402 : M - number of functions f[i]
16403 : X - initial solution, array[0..N-1]
16404 :
16405 : OUTPUT PARAMETERS:
16406 : State - structure which stores algorithm state
16407 :
16408 : NOTES:
16409 : 1. you may tune stopping conditions with MinLMSetCond() function
16410 : 2. if target function contains exp() or other fast growing functions, and
16411 : optimization algorithm makes too large steps which leads to overflow,
16412 : use MinLMSetStpMax() function to bound algorithm's steps.
16413 :
16414 : -- ALGLIB --
16415 : Copyright 30.03.2009 by Bochkanov Sergey
16416 : *************************************************************************/
16417 0 : void minlmcreatevj(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams)
16418 : {
16419 : jmp_buf _break_jump;
16420 : alglib_impl::ae_state _alglib_env_state;
16421 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16422 0 : if( setjmp(_break_jump) )
16423 : {
16424 : #if !defined(AE_NO_EXCEPTIONS)
16425 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16426 : #else
16427 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16428 : return;
16429 : #endif
16430 : }
16431 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16432 0 : if( _xparams.flags!=0x0 )
16433 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16434 0 : 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);
16435 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16436 0 : return;
16437 : }
16438 :
16439 : /*************************************************************************
16440 : IMPROVED LEVENBERG-MARQUARDT METHOD FOR
16441 : NON-LINEAR LEAST SQUARES OPTIMIZATION
16442 :
16443 : DESCRIPTION:
16444 : This function is used to find minimum of function which is represented as
16445 : sum of squares:
16446 : F(x) = f[0]^2(x[0],...,x[n-1]) + ... + f[m-1]^2(x[0],...,x[n-1])
16447 : using value of function vector f[] and Jacobian of f[].
16448 :
16449 :
16450 : REQUIREMENTS:
16451 : This algorithm will request following information during its operation:
16452 :
16453 : * function vector f[] at given point X
16454 : * function vector f[] and Jacobian of f[] (simultaneously) at given point
16455 :
16456 : There are several overloaded versions of MinLMOptimize() function which
16457 : correspond to different LM-like optimization algorithms provided by this
16458 : unit. You should choose version which accepts fvec() and jac() callbacks.
16459 : First one is used to calculate f[] at given point, second one calculates
16460 : f[] and Jacobian df[i]/dx[j].
16461 :
16462 : You can try to initialize MinLMState structure with VJ function and then
16463 : use incorrect version of MinLMOptimize() (for example, version which
16464 : works with general form function and does not provide Jacobian), but it
16465 : will lead to exception being thrown after first attempt to calculate
16466 : Jacobian.
16467 :
16468 :
16469 : USAGE:
16470 : 1. User initializes algorithm state with MinLMCreateVJ() call
16471 : 2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and
16472 : other functions
16473 : 3. User calls MinLMOptimize() function which takes algorithm state and
16474 : callback functions.
16475 : 4. User calls MinLMResults() to get solution
16476 : 5. Optionally, user may call MinLMRestartFrom() to solve another problem
16477 : with same N/M but another starting point and/or another function.
16478 : MinLMRestartFrom() allows to reuse already initialized structure.
16479 :
16480 :
16481 : INPUT PARAMETERS:
16482 : N - dimension, N>1
16483 : * if given, only leading N elements of X are used
16484 : * if not given, automatically determined from size of X
16485 : M - number of functions f[i]
16486 : X - initial solution, array[0..N-1]
16487 :
16488 : OUTPUT PARAMETERS:
16489 : State - structure which stores algorithm state
16490 :
16491 : NOTES:
16492 : 1. you may tune stopping conditions with MinLMSetCond() function
16493 : 2. if target function contains exp() or other fast growing functions, and
16494 : optimization algorithm makes too large steps which leads to overflow,
16495 : use MinLMSetStpMax() function to bound algorithm's steps.
16496 :
16497 : -- ALGLIB --
16498 : Copyright 30.03.2009 by Bochkanov Sergey
16499 : *************************************************************************/
16500 : #if !defined(AE_NO_EXCEPTIONS)
16501 0 : void minlmcreatevj(const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams)
16502 : {
16503 : jmp_buf _break_jump;
16504 : alglib_impl::ae_state _alglib_env_state;
16505 : ae_int_t n;
16506 :
16507 0 : n = x.length();
16508 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16509 0 : if( setjmp(_break_jump) )
16510 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16511 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16512 0 : if( _xparams.flags!=0x0 )
16513 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16514 0 : 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);
16515 :
16516 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16517 0 : return;
16518 : }
16519 : #endif
16520 :
16521 : /*************************************************************************
16522 : IMPROVED LEVENBERG-MARQUARDT METHOD FOR
16523 : NON-LINEAR LEAST SQUARES OPTIMIZATION
16524 :
16525 : DESCRIPTION:
16526 : This function is used to find minimum of function which is represented as
16527 : sum of squares:
16528 : F(x) = f[0]^2(x[0],...,x[n-1]) + ... + f[m-1]^2(x[0],...,x[n-1])
16529 : using value of function vector f[] only. Finite differences are used to
16530 : calculate Jacobian.
16531 :
16532 :
16533 : REQUIREMENTS:
16534 : This algorithm will request following information during its operation:
16535 : * function vector f[] at given point X
16536 :
16537 : There are several overloaded versions of MinLMOptimize() function which
16538 : correspond to different LM-like optimization algorithms provided by this
16539 : unit. You should choose version which accepts fvec() callback.
16540 :
16541 : You can try to initialize MinLMState structure with VJ function and then
16542 : use incorrect version of MinLMOptimize() (for example, version which
16543 : works with general form function and does not accept function vector), but
16544 : it will lead to exception being thrown after first attempt to calculate
16545 : Jacobian.
16546 :
16547 :
16548 : USAGE:
16549 : 1. User initializes algorithm state with MinLMCreateV() call
16550 : 2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and
16551 : other functions
16552 : 3. User calls MinLMOptimize() function which takes algorithm state and
16553 : callback functions.
16554 : 4. User calls MinLMResults() to get solution
16555 : 5. Optionally, user may call MinLMRestartFrom() to solve another problem
16556 : with same N/M but another starting point and/or another function.
16557 : MinLMRestartFrom() allows to reuse already initialized structure.
16558 :
16559 :
16560 : INPUT PARAMETERS:
16561 : N - dimension, N>1
16562 : * if given, only leading N elements of X are used
16563 : * if not given, automatically determined from size of X
16564 : M - number of functions f[i]
16565 : X - initial solution, array[0..N-1]
16566 : DiffStep- differentiation step, >0
16567 :
16568 : OUTPUT PARAMETERS:
16569 : State - structure which stores algorithm state
16570 :
16571 : See also MinLMIteration, MinLMResults.
16572 :
16573 : NOTES:
16574 : 1. you may tune stopping conditions with MinLMSetCond() function
16575 : 2. if target function contains exp() or other fast growing functions, and
16576 : optimization algorithm makes too large steps which leads to overflow,
16577 : use MinLMSetStpMax() function to bound algorithm's steps.
16578 :
16579 : -- ALGLIB --
16580 : Copyright 30.03.2009 by Bochkanov Sergey
16581 : *************************************************************************/
16582 0 : void minlmcreatev(const ae_int_t n, const ae_int_t m, const real_1d_array &x, const double diffstep, minlmstate &state, const xparams _xparams)
16583 : {
16584 : jmp_buf _break_jump;
16585 : alglib_impl::ae_state _alglib_env_state;
16586 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16587 0 : if( setjmp(_break_jump) )
16588 : {
16589 : #if !defined(AE_NO_EXCEPTIONS)
16590 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16591 : #else
16592 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16593 : return;
16594 : #endif
16595 : }
16596 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16597 0 : if( _xparams.flags!=0x0 )
16598 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16599 0 : 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);
16600 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16601 0 : return;
16602 : }
16603 :
16604 : /*************************************************************************
16605 : IMPROVED LEVENBERG-MARQUARDT METHOD FOR
16606 : NON-LINEAR LEAST SQUARES OPTIMIZATION
16607 :
16608 : DESCRIPTION:
16609 : This function is used to find minimum of function which is represented as
16610 : sum of squares:
16611 : F(x) = f[0]^2(x[0],...,x[n-1]) + ... + f[m-1]^2(x[0],...,x[n-1])
16612 : using value of function vector f[] only. Finite differences are used to
16613 : calculate Jacobian.
16614 :
16615 :
16616 : REQUIREMENTS:
16617 : This algorithm will request following information during its operation:
16618 : * function vector f[] at given point X
16619 :
16620 : There are several overloaded versions of MinLMOptimize() function which
16621 : correspond to different LM-like optimization algorithms provided by this
16622 : unit. You should choose version which accepts fvec() callback.
16623 :
16624 : You can try to initialize MinLMState structure with VJ function and then
16625 : use incorrect version of MinLMOptimize() (for example, version which
16626 : works with general form function and does not accept function vector), but
16627 : it will lead to exception being thrown after first attempt to calculate
16628 : Jacobian.
16629 :
16630 :
16631 : USAGE:
16632 : 1. User initializes algorithm state with MinLMCreateV() call
16633 : 2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and
16634 : other functions
16635 : 3. User calls MinLMOptimize() function which takes algorithm state and
16636 : callback functions.
16637 : 4. User calls MinLMResults() to get solution
16638 : 5. Optionally, user may call MinLMRestartFrom() to solve another problem
16639 : with same N/M but another starting point and/or another function.
16640 : MinLMRestartFrom() allows to reuse already initialized structure.
16641 :
16642 :
16643 : INPUT PARAMETERS:
16644 : N - dimension, N>1
16645 : * if given, only leading N elements of X are used
16646 : * if not given, automatically determined from size of X
16647 : M - number of functions f[i]
16648 : X - initial solution, array[0..N-1]
16649 : DiffStep- differentiation step, >0
16650 :
16651 : OUTPUT PARAMETERS:
16652 : State - structure which stores algorithm state
16653 :
16654 : See also MinLMIteration, MinLMResults.
16655 :
16656 : NOTES:
16657 : 1. you may tune stopping conditions with MinLMSetCond() function
16658 : 2. if target function contains exp() or other fast growing functions, and
16659 : optimization algorithm makes too large steps which leads to overflow,
16660 : use MinLMSetStpMax() function to bound algorithm's steps.
16661 :
16662 : -- ALGLIB --
16663 : Copyright 30.03.2009 by Bochkanov Sergey
16664 : *************************************************************************/
16665 : #if !defined(AE_NO_EXCEPTIONS)
16666 0 : void minlmcreatev(const ae_int_t m, const real_1d_array &x, const double diffstep, minlmstate &state, const xparams _xparams)
16667 : {
16668 : jmp_buf _break_jump;
16669 : alglib_impl::ae_state _alglib_env_state;
16670 : ae_int_t n;
16671 :
16672 0 : n = x.length();
16673 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16674 0 : if( setjmp(_break_jump) )
16675 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16676 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16677 0 : if( _xparams.flags!=0x0 )
16678 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16679 0 : 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);
16680 :
16681 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16682 0 : return;
16683 : }
16684 : #endif
16685 :
16686 : /*************************************************************************
16687 : LEVENBERG-MARQUARDT-LIKE METHOD FOR NON-LINEAR OPTIMIZATION
16688 :
16689 : DESCRIPTION:
16690 : This function is used to find minimum of general form (not "sum-of-
16691 : -squares") function
16692 : F = F(x[0], ..., x[n-1])
16693 : using its gradient and Hessian. Levenberg-Marquardt modification with
16694 : L-BFGS pre-optimization and internal pre-conditioned L-BFGS optimization
16695 : after each Levenberg-Marquardt step is used.
16696 :
16697 :
16698 : REQUIREMENTS:
16699 : This algorithm will request following information during its operation:
16700 :
16701 : * function value F at given point X
16702 : * F and gradient G (simultaneously) at given point X
16703 : * F, G and Hessian H (simultaneously) at given point X
16704 :
16705 : There are several overloaded versions of MinLMOptimize() function which
16706 : correspond to different LM-like optimization algorithms provided by this
16707 : unit. You should choose version which accepts func(), grad() and hess()
16708 : function pointers. First pointer is used to calculate F at given point,
16709 : second one calculates F(x) and grad F(x), third one calculates F(x),
16710 : grad F(x), hess F(x).
16711 :
16712 : You can try to initialize MinLMState structure with FGH-function and then
16713 : use incorrect version of MinLMOptimize() (for example, version which does
16714 : not provide Hessian matrix), but it will lead to exception being thrown
16715 : after first attempt to calculate Hessian.
16716 :
16717 :
16718 : USAGE:
16719 : 1. User initializes algorithm state with MinLMCreateFGH() call
16720 : 2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and
16721 : other functions
16722 : 3. User calls MinLMOptimize() function which takes algorithm state and
16723 : pointers (delegates, etc.) to callback functions.
16724 : 4. User calls MinLMResults() to get solution
16725 : 5. Optionally, user may call MinLMRestartFrom() to solve another problem
16726 : with same N but another starting point and/or another function.
16727 : MinLMRestartFrom() allows to reuse already initialized structure.
16728 :
16729 :
16730 : INPUT PARAMETERS:
16731 : N - dimension, N>1
16732 : * if given, only leading N elements of X are used
16733 : * if not given, automatically determined from size of X
16734 : X - initial solution, array[0..N-1]
16735 :
16736 : OUTPUT PARAMETERS:
16737 : State - structure which stores algorithm state
16738 :
16739 : NOTES:
16740 : 1. you may tune stopping conditions with MinLMSetCond() function
16741 : 2. if target function contains exp() or other fast growing functions, and
16742 : optimization algorithm makes too large steps which leads to overflow,
16743 : use MinLMSetStpMax() function to bound algorithm's steps.
16744 :
16745 : -- ALGLIB --
16746 : Copyright 30.03.2009 by Bochkanov Sergey
16747 : *************************************************************************/
16748 0 : void minlmcreatefgh(const ae_int_t n, const real_1d_array &x, minlmstate &state, const xparams _xparams)
16749 : {
16750 : jmp_buf _break_jump;
16751 : alglib_impl::ae_state _alglib_env_state;
16752 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16753 0 : if( setjmp(_break_jump) )
16754 : {
16755 : #if !defined(AE_NO_EXCEPTIONS)
16756 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16757 : #else
16758 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16759 : return;
16760 : #endif
16761 : }
16762 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16763 0 : if( _xparams.flags!=0x0 )
16764 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16765 0 : alglib_impl::minlmcreatefgh(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minlmstate*>(state.c_ptr()), &_alglib_env_state);
16766 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16767 0 : return;
16768 : }
16769 :
16770 : /*************************************************************************
16771 : LEVENBERG-MARQUARDT-LIKE METHOD FOR NON-LINEAR OPTIMIZATION
16772 :
16773 : DESCRIPTION:
16774 : This function is used to find minimum of general form (not "sum-of-
16775 : -squares") function
16776 : F = F(x[0], ..., x[n-1])
16777 : using its gradient and Hessian. Levenberg-Marquardt modification with
16778 : L-BFGS pre-optimization and internal pre-conditioned L-BFGS optimization
16779 : after each Levenberg-Marquardt step is used.
16780 :
16781 :
16782 : REQUIREMENTS:
16783 : This algorithm will request following information during its operation:
16784 :
16785 : * function value F at given point X
16786 : * F and gradient G (simultaneously) at given point X
16787 : * F, G and Hessian H (simultaneously) at given point X
16788 :
16789 : There are several overloaded versions of MinLMOptimize() function which
16790 : correspond to different LM-like optimization algorithms provided by this
16791 : unit. You should choose version which accepts func(), grad() and hess()
16792 : function pointers. First pointer is used to calculate F at given point,
16793 : second one calculates F(x) and grad F(x), third one calculates F(x),
16794 : grad F(x), hess F(x).
16795 :
16796 : You can try to initialize MinLMState structure with FGH-function and then
16797 : use incorrect version of MinLMOptimize() (for example, version which does
16798 : not provide Hessian matrix), but it will lead to exception being thrown
16799 : after first attempt to calculate Hessian.
16800 :
16801 :
16802 : USAGE:
16803 : 1. User initializes algorithm state with MinLMCreateFGH() call
16804 : 2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and
16805 : other functions
16806 : 3. User calls MinLMOptimize() function which takes algorithm state and
16807 : pointers (delegates, etc.) to callback functions.
16808 : 4. User calls MinLMResults() to get solution
16809 : 5. Optionally, user may call MinLMRestartFrom() to solve another problem
16810 : with same N but another starting point and/or another function.
16811 : MinLMRestartFrom() allows to reuse already initialized structure.
16812 :
16813 :
16814 : INPUT PARAMETERS:
16815 : N - dimension, N>1
16816 : * if given, only leading N elements of X are used
16817 : * if not given, automatically determined from size of X
16818 : X - initial solution, array[0..N-1]
16819 :
16820 : OUTPUT PARAMETERS:
16821 : State - structure which stores algorithm state
16822 :
16823 : NOTES:
16824 : 1. you may tune stopping conditions with MinLMSetCond() function
16825 : 2. if target function contains exp() or other fast growing functions, and
16826 : optimization algorithm makes too large steps which leads to overflow,
16827 : use MinLMSetStpMax() function to bound algorithm's steps.
16828 :
16829 : -- ALGLIB --
16830 : Copyright 30.03.2009 by Bochkanov Sergey
16831 : *************************************************************************/
16832 : #if !defined(AE_NO_EXCEPTIONS)
16833 0 : void minlmcreatefgh(const real_1d_array &x, minlmstate &state, const xparams _xparams)
16834 : {
16835 : jmp_buf _break_jump;
16836 : alglib_impl::ae_state _alglib_env_state;
16837 : ae_int_t n;
16838 :
16839 0 : n = x.length();
16840 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16841 0 : if( setjmp(_break_jump) )
16842 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16843 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16844 0 : if( _xparams.flags!=0x0 )
16845 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16846 0 : alglib_impl::minlmcreatefgh(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minlmstate*>(state.c_ptr()), &_alglib_env_state);
16847 :
16848 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16849 0 : return;
16850 : }
16851 : #endif
16852 :
16853 : /*************************************************************************
16854 : This function sets stopping conditions for Levenberg-Marquardt optimization
16855 : algorithm.
16856 :
16857 : INPUT PARAMETERS:
16858 : State - structure which stores algorithm state
16859 : EpsX - >=0
16860 : The subroutine finishes its work if on k+1-th iteration
16861 : the condition |v|<=EpsX is fulfilled, where:
16862 : * |.| means Euclidian norm
16863 : * v - scaled step vector, v[i]=dx[i]/s[i]
16864 : * dx - ste pvector, dx=X(k+1)-X(k)
16865 : * s - scaling coefficients set by MinLMSetScale()
16866 : Recommended values: 1E-9 ... 1E-12.
16867 : MaxIts - maximum number of iterations. If MaxIts=0, the number of
16868 : iterations is unlimited. Only Levenberg-Marquardt
16869 : iterations are counted (L-BFGS/CG iterations are NOT
16870 : counted because their cost is very low compared to that of
16871 : LM).
16872 :
16873 : Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic
16874 : stopping criterion selection (small EpsX).
16875 :
16876 : NOTE: it is not recommended to set large EpsX (say, 0.001). Because LM is
16877 : a second-order method, it performs very precise steps anyway.
16878 :
16879 : -- ALGLIB --
16880 : Copyright 02.04.2010 by Bochkanov Sergey
16881 : *************************************************************************/
16882 0 : void minlmsetcond(const minlmstate &state, const double epsx, const ae_int_t maxits, const xparams _xparams)
16883 : {
16884 : jmp_buf _break_jump;
16885 : alglib_impl::ae_state _alglib_env_state;
16886 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16887 0 : if( setjmp(_break_jump) )
16888 : {
16889 : #if !defined(AE_NO_EXCEPTIONS)
16890 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16891 : #else
16892 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16893 : return;
16894 : #endif
16895 : }
16896 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16897 0 : if( _xparams.flags!=0x0 )
16898 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16899 0 : alglib_impl::minlmsetcond(const_cast<alglib_impl::minlmstate*>(state.c_ptr()), epsx, maxits, &_alglib_env_state);
16900 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16901 0 : return;
16902 : }
16903 :
16904 : /*************************************************************************
16905 : This function turns on/off reporting.
16906 :
16907 : INPUT PARAMETERS:
16908 : State - structure which stores algorithm state
16909 : NeedXRep- whether iteration reports are needed or not
16910 :
16911 : If NeedXRep is True, algorithm will call rep() callback function if it is
16912 : provided to MinLMOptimize(). Both Levenberg-Marquardt and internal L-BFGS
16913 : iterations are reported.
16914 :
16915 : -- ALGLIB --
16916 : Copyright 02.04.2010 by Bochkanov Sergey
16917 : *************************************************************************/
16918 0 : void minlmsetxrep(const minlmstate &state, const bool needxrep, const xparams _xparams)
16919 : {
16920 : jmp_buf _break_jump;
16921 : alglib_impl::ae_state _alglib_env_state;
16922 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16923 0 : if( setjmp(_break_jump) )
16924 : {
16925 : #if !defined(AE_NO_EXCEPTIONS)
16926 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16927 : #else
16928 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16929 : return;
16930 : #endif
16931 : }
16932 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16933 0 : if( _xparams.flags!=0x0 )
16934 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16935 0 : alglib_impl::minlmsetxrep(const_cast<alglib_impl::minlmstate*>(state.c_ptr()), needxrep, &_alglib_env_state);
16936 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16937 0 : return;
16938 : }
16939 :
16940 : /*************************************************************************
16941 : This function sets maximum step length
16942 :
16943 : INPUT PARAMETERS:
16944 : State - structure which stores algorithm state
16945 : StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't
16946 : want to limit step length.
16947 :
16948 : Use this subroutine when you optimize target function which contains exp()
16949 : or other fast growing functions, and optimization algorithm makes too
16950 : large steps which leads to overflow. This function allows us to reject
16951 : steps that are too large (and therefore expose us to the possible
16952 : overflow) without actually calculating function value at the x+stp*d.
16953 :
16954 : NOTE: non-zero StpMax leads to moderate performance degradation because
16955 : intermediate step of preconditioned L-BFGS optimization is incompatible
16956 : with limits on step size.
16957 :
16958 : -- ALGLIB --
16959 : Copyright 02.04.2010 by Bochkanov Sergey
16960 : *************************************************************************/
16961 0 : void minlmsetstpmax(const minlmstate &state, const double stpmax, const xparams _xparams)
16962 : {
16963 : jmp_buf _break_jump;
16964 : alglib_impl::ae_state _alglib_env_state;
16965 0 : alglib_impl::ae_state_init(&_alglib_env_state);
16966 0 : if( setjmp(_break_jump) )
16967 : {
16968 : #if !defined(AE_NO_EXCEPTIONS)
16969 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
16970 : #else
16971 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
16972 : return;
16973 : #endif
16974 : }
16975 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
16976 0 : if( _xparams.flags!=0x0 )
16977 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
16978 0 : alglib_impl::minlmsetstpmax(const_cast<alglib_impl::minlmstate*>(state.c_ptr()), stpmax, &_alglib_env_state);
16979 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
16980 0 : return;
16981 : }
16982 :
16983 : /*************************************************************************
16984 : This function sets scaling coefficients for LM optimizer.
16985 :
16986 : ALGLIB optimizers use scaling matrices to test stopping conditions (step
16987 : size and gradient are scaled before comparison with tolerances). Scale of
16988 : the I-th variable is a translation invariant measure of:
16989 : a) "how large" the variable is
16990 : b) how large the step should be to make significant changes in the function
16991 :
16992 : Generally, scale is NOT considered to be a form of preconditioner. But LM
16993 : optimizer is unique in that it uses scaling matrix both in the stopping
16994 : condition tests and as Marquardt damping factor.
16995 :
16996 : Proper scaling is very important for the algorithm performance. It is less
16997 : important for the quality of results, but still has some influence (it is
16998 : easier to converge when variables are properly scaled, so premature
16999 : stopping is possible when very badly scalled variables are combined with
17000 : relaxed stopping conditions).
17001 :
17002 : INPUT PARAMETERS:
17003 : State - structure stores algorithm state
17004 : S - array[N], non-zero scaling coefficients
17005 : S[i] may be negative, sign doesn't matter.
17006 :
17007 : -- ALGLIB --
17008 : Copyright 14.01.2011 by Bochkanov Sergey
17009 : *************************************************************************/
17010 0 : void minlmsetscale(const minlmstate &state, const real_1d_array &s, const xparams _xparams)
17011 : {
17012 : jmp_buf _break_jump;
17013 : alglib_impl::ae_state _alglib_env_state;
17014 0 : alglib_impl::ae_state_init(&_alglib_env_state);
17015 0 : if( setjmp(_break_jump) )
17016 : {
17017 : #if !defined(AE_NO_EXCEPTIONS)
17018 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
17019 : #else
17020 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
17021 : return;
17022 : #endif
17023 : }
17024 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
17025 0 : if( _xparams.flags!=0x0 )
17026 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
17027 0 : alglib_impl::minlmsetscale(const_cast<alglib_impl::minlmstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(s.c_ptr()), &_alglib_env_state);
17028 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
17029 0 : return;
17030 : }
17031 :
17032 : /*************************************************************************
17033 : This function sets boundary constraints for LM optimizer
17034 :
17035 : Boundary constraints are inactive by default (after initial creation).
17036 : They are preserved until explicitly turned off with another SetBC() call.
17037 :
17038 : INPUT PARAMETERS:
17039 : State - structure stores algorithm state
17040 : BndL - lower bounds, array[N].
17041 : If some (all) variables are unbounded, you may specify
17042 : very small number or -INF (latter is recommended because
17043 : it will allow solver to use better algorithm).
17044 : BndU - upper bounds, array[N].
17045 : If some (all) variables are unbounded, you may specify
17046 : very large number or +INF (latter is recommended because
17047 : it will allow solver to use better algorithm).
17048 :
17049 : NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th
17050 : variable will be "frozen" at X[i]=BndL[i]=BndU[i].
17051 :
17052 : NOTE 2: this solver has following useful properties:
17053 : * bound constraints are always satisfied exactly
17054 : * function is evaluated only INSIDE area specified by bound constraints
17055 : or at its boundary
17056 :
17057 : -- ALGLIB --
17058 : Copyright 14.01.2011 by Bochkanov Sergey
17059 : *************************************************************************/
17060 0 : void minlmsetbc(const minlmstate &state, const real_1d_array &bndl, const real_1d_array &bndu, const xparams _xparams)
17061 : {
17062 : jmp_buf _break_jump;
17063 : alglib_impl::ae_state _alglib_env_state;
17064 0 : alglib_impl::ae_state_init(&_alglib_env_state);
17065 0 : if( setjmp(_break_jump) )
17066 : {
17067 : #if !defined(AE_NO_EXCEPTIONS)
17068 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
17069 : #else
17070 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
17071 : return;
17072 : #endif
17073 : }
17074 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
17075 0 : if( _xparams.flags!=0x0 )
17076 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
17077 0 : 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);
17078 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
17079 0 : return;
17080 : }
17081 :
17082 : /*************************************************************************
17083 : This function sets general linear constraints for LM optimizer
17084 :
17085 : Linear constraints are inactive by default (after initial creation). They
17086 : are preserved until explicitly turned off with another minlmsetlc() call.
17087 :
17088 : INPUT PARAMETERS:
17089 : State - structure stores algorithm state
17090 : C - linear constraints, array[K,N+1].
17091 : Each row of C represents one constraint, either equality
17092 : or inequality (see below):
17093 : * first N elements correspond to coefficients,
17094 : * last element corresponds to the right part.
17095 : All elements of C (including right part) must be finite.
17096 : CT - type of constraints, array[K]:
17097 : * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
17098 : * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
17099 : * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
17100 : K - number of equality/inequality constraints, K>=0:
17101 : * if given, only leading K elements of C/CT are used
17102 : * if not given, automatically determined from sizes of C/CT
17103 :
17104 : IMPORTANT: if you have linear constraints, it is strongly recommended to
17105 : set scale of variables with minlmsetscale(). QP solver which is
17106 : used to calculate linearly constrained steps heavily relies on
17107 : good scaling of input problems.
17108 :
17109 : IMPORTANT: solvers created with minlmcreatefgh() do not support linear
17110 : constraints.
17111 :
17112 : NOTE: linear (non-bound) constraints are satisfied only approximately -
17113 : there always exists some violation due to numerical errors and
17114 : algorithmic limitations.
17115 :
17116 : NOTE: general linear constraints add significant overhead to solution
17117 : process. Although solver performs roughly same amount of iterations
17118 : (when compared with similar box-only constrained problem), each
17119 : iteration now involves solution of linearly constrained QP
17120 : subproblem, which requires ~3-5 times more Cholesky decompositions.
17121 : Thus, if you can reformulate your problem in such way this it has
17122 : only box constraints, it may be beneficial to do so.
17123 :
17124 : -- ALGLIB --
17125 : Copyright 14.01.2011 by Bochkanov Sergey
17126 : *************************************************************************/
17127 0 : void minlmsetlc(const minlmstate &state, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k, const xparams _xparams)
17128 : {
17129 : jmp_buf _break_jump;
17130 : alglib_impl::ae_state _alglib_env_state;
17131 0 : alglib_impl::ae_state_init(&_alglib_env_state);
17132 0 : if( setjmp(_break_jump) )
17133 : {
17134 : #if !defined(AE_NO_EXCEPTIONS)
17135 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
17136 : #else
17137 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
17138 : return;
17139 : #endif
17140 : }
17141 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
17142 0 : if( _xparams.flags!=0x0 )
17143 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
17144 0 : alglib_impl::minlmsetlc(const_cast<alglib_impl::minlmstate*>(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);
17145 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
17146 0 : return;
17147 : }
17148 :
17149 : /*************************************************************************
17150 : This function sets general linear constraints for LM optimizer
17151 :
17152 : Linear constraints are inactive by default (after initial creation). They
17153 : are preserved until explicitly turned off with another minlmsetlc() call.
17154 :
17155 : INPUT PARAMETERS:
17156 : State - structure stores algorithm state
17157 : C - linear constraints, array[K,N+1].
17158 : Each row of C represents one constraint, either equality
17159 : or inequality (see below):
17160 : * first N elements correspond to coefficients,
17161 : * last element corresponds to the right part.
17162 : All elements of C (including right part) must be finite.
17163 : CT - type of constraints, array[K]:
17164 : * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
17165 : * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
17166 : * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
17167 : K - number of equality/inequality constraints, K>=0:
17168 : * if given, only leading K elements of C/CT are used
17169 : * if not given, automatically determined from sizes of C/CT
17170 :
17171 : IMPORTANT: if you have linear constraints, it is strongly recommended to
17172 : set scale of variables with minlmsetscale(). QP solver which is
17173 : used to calculate linearly constrained steps heavily relies on
17174 : good scaling of input problems.
17175 :
17176 : IMPORTANT: solvers created with minlmcreatefgh() do not support linear
17177 : constraints.
17178 :
17179 : NOTE: linear (non-bound) constraints are satisfied only approximately -
17180 : there always exists some violation due to numerical errors and
17181 : algorithmic limitations.
17182 :
17183 : NOTE: general linear constraints add significant overhead to solution
17184 : process. Although solver performs roughly same amount of iterations
17185 : (when compared with similar box-only constrained problem), each
17186 : iteration now involves solution of linearly constrained QP
17187 : subproblem, which requires ~3-5 times more Cholesky decompositions.
17188 : Thus, if you can reformulate your problem in such way this it has
17189 : only box constraints, it may be beneficial to do so.
17190 :
17191 : -- ALGLIB --
17192 : Copyright 14.01.2011 by Bochkanov Sergey
17193 : *************************************************************************/
17194 : #if !defined(AE_NO_EXCEPTIONS)
17195 0 : void minlmsetlc(const minlmstate &state, const real_2d_array &c, const integer_1d_array &ct, const xparams _xparams)
17196 : {
17197 : jmp_buf _break_jump;
17198 : alglib_impl::ae_state _alglib_env_state;
17199 : ae_int_t k;
17200 0 : if( (c.rows()!=ct.length()))
17201 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'minlmsetlc': looks like one of arguments has wrong size");
17202 0 : k = c.rows();
17203 0 : alglib_impl::ae_state_init(&_alglib_env_state);
17204 0 : if( setjmp(_break_jump) )
17205 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
17206 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
17207 0 : if( _xparams.flags!=0x0 )
17208 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
17209 0 : alglib_impl::minlmsetlc(const_cast<alglib_impl::minlmstate*>(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);
17210 :
17211 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
17212 0 : return;
17213 : }
17214 : #endif
17215 :
17216 : /*************************************************************************
17217 : This function is used to change acceleration settings
17218 :
17219 : You can choose between three acceleration strategies:
17220 : * AccType=0, no acceleration.
17221 : * AccType=1, secant updates are used to update quadratic model after each
17222 : iteration. After fixed number of iterations (or after model breakdown)
17223 : we recalculate quadratic model using analytic Jacobian or finite
17224 : differences. Number of secant-based iterations depends on optimization
17225 : settings: about 3 iterations - when we have analytic Jacobian, up to 2*N
17226 : iterations - when we use finite differences to calculate Jacobian.
17227 :
17228 : AccType=1 is recommended when Jacobian calculation cost is prohibitively
17229 : high (several Mx1 function vector calculations followed by several NxN
17230 : Cholesky factorizations are faster than calculation of one M*N Jacobian).
17231 : It should also be used when we have no Jacobian, because finite difference
17232 : approximation takes too much time to compute.
17233 :
17234 : Table below list optimization protocols (XYZ protocol corresponds to
17235 : MinLMCreateXYZ) and acceleration types they support (and use by default).
17236 :
17237 : ACCELERATION TYPES SUPPORTED BY OPTIMIZATION PROTOCOLS:
17238 :
17239 : protocol 0 1 comment
17240 : V + +
17241 : VJ + +
17242 : FGH +
17243 :
17244 : DEFAULT VALUES:
17245 :
17246 : protocol 0 1 comment
17247 : V x without acceleration it is so slooooooooow
17248 : VJ x
17249 : FGH x
17250 :
17251 : NOTE: this function should be called before optimization. Attempt to call
17252 : it during algorithm iterations may result in unexpected behavior.
17253 :
17254 : NOTE: attempt to call this function with unsupported protocol/acceleration
17255 : combination will result in exception being thrown.
17256 :
17257 : -- ALGLIB --
17258 : Copyright 14.10.2010 by Bochkanov Sergey
17259 : *************************************************************************/
17260 0 : void minlmsetacctype(const minlmstate &state, const ae_int_t acctype, const xparams _xparams)
17261 : {
17262 : jmp_buf _break_jump;
17263 : alglib_impl::ae_state _alglib_env_state;
17264 0 : alglib_impl::ae_state_init(&_alglib_env_state);
17265 0 : if( setjmp(_break_jump) )
17266 : {
17267 : #if !defined(AE_NO_EXCEPTIONS)
17268 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
17269 : #else
17270 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
17271 : return;
17272 : #endif
17273 : }
17274 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
17275 0 : if( _xparams.flags!=0x0 )
17276 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
17277 0 : alglib_impl::minlmsetacctype(const_cast<alglib_impl::minlmstate*>(state.c_ptr()), acctype, &_alglib_env_state);
17278 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
17279 0 : return;
17280 : }
17281 :
17282 : /*************************************************************************
17283 : This function provides reverse communication interface
17284 : Reverse communication interface is not documented or recommended to use.
17285 : See below for functions which provide better documented API
17286 : *************************************************************************/
17287 0 : bool minlmiteration(const minlmstate &state, const xparams _xparams)
17288 : {
17289 : jmp_buf _break_jump;
17290 : alglib_impl::ae_state _alglib_env_state;
17291 0 : alglib_impl::ae_state_init(&_alglib_env_state);
17292 0 : if( setjmp(_break_jump) )
17293 : {
17294 : #if !defined(AE_NO_EXCEPTIONS)
17295 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
17296 : #else
17297 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
17298 : return 0;
17299 : #endif
17300 : }
17301 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
17302 0 : if( _xparams.flags!=0x0 )
17303 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
17304 0 : ae_bool result = alglib_impl::minlmiteration(const_cast<alglib_impl::minlmstate*>(state.c_ptr()), &_alglib_env_state);
17305 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
17306 0 : return *(reinterpret_cast<bool*>(&result));
17307 : }
17308 :
17309 :
17310 0 : void minlmoptimize(minlmstate &state,
17311 : void (*fvec)(const real_1d_array &x, real_1d_array &fi, void *ptr),
17312 : void (*rep)(const real_1d_array &x, double func, void *ptr),
17313 : void *ptr,
17314 : const xparams _xparams)
17315 : {
17316 : jmp_buf _break_jump;
17317 : alglib_impl::ae_state _alglib_env_state;
17318 0 : alglib_impl::ae_state_init(&_alglib_env_state);
17319 0 : if( setjmp(_break_jump) )
17320 : {
17321 : #if !defined(AE_NO_EXCEPTIONS)
17322 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
17323 : #else
17324 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
17325 : return;
17326 : #endif
17327 : }
17328 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
17329 0 : if( _xparams.flags!=0x0 )
17330 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
17331 0 : alglib_impl::ae_assert(fvec!=NULL, "ALGLIB: error in 'minlmoptimize()' (fvec is NULL)", &_alglib_env_state);
17332 0 : while( alglib_impl::minlmiteration(state.c_ptr(), &_alglib_env_state) )
17333 : {
17334 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN
17335 0 : if( state.needfi )
17336 : {
17337 0 : fvec(state.x, state.fi, ptr);
17338 0 : continue;
17339 : }
17340 0 : if( state.xupdated )
17341 : {
17342 0 : if( rep!=NULL )
17343 0 : rep(state.x, state.f, ptr);
17344 0 : continue;
17345 : }
17346 0 : goto lbl_no_callback;
17347 0 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_END
17348 0 : lbl_no_callback:
17349 0 : alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)", &_alglib_env_state);
17350 : }
17351 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
17352 0 : }
17353 :
17354 :
17355 0 : void minlmoptimize(minlmstate &state,
17356 : void (*fvec)(const real_1d_array &x, real_1d_array &fi, void *ptr),
17357 : void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr),
17358 : void (*rep)(const real_1d_array &x, double func, void *ptr),
17359 : void *ptr,
17360 : const xparams _xparams)
17361 : {
17362 : jmp_buf _break_jump;
17363 : alglib_impl::ae_state _alglib_env_state;
17364 0 : alglib_impl::ae_state_init(&_alglib_env_state);
17365 0 : if( setjmp(_break_jump) )
17366 : {
17367 : #if !defined(AE_NO_EXCEPTIONS)
17368 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
17369 : #else
17370 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
17371 : return;
17372 : #endif
17373 : }
17374 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
17375 0 : if( _xparams.flags!=0x0 )
17376 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
17377 0 : alglib_impl::ae_assert(fvec!=NULL, "ALGLIB: error in 'minlmoptimize()' (fvec is NULL)", &_alglib_env_state);
17378 0 : alglib_impl::ae_assert(jac!=NULL, "ALGLIB: error in 'minlmoptimize()' (jac is NULL)", &_alglib_env_state);
17379 0 : while( alglib_impl::minlmiteration(state.c_ptr(), &_alglib_env_state) )
17380 : {
17381 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN
17382 0 : if( state.needfi )
17383 : {
17384 0 : fvec(state.x, state.fi, ptr);
17385 0 : continue;
17386 : }
17387 0 : if( state.needfij )
17388 : {
17389 0 : jac(state.x, state.fi, state.j, ptr);
17390 0 : continue;
17391 : }
17392 0 : if( state.xupdated )
17393 : {
17394 0 : if( rep!=NULL )
17395 0 : rep(state.x, state.f, ptr);
17396 0 : continue;
17397 : }
17398 0 : goto lbl_no_callback;
17399 0 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_END
17400 0 : lbl_no_callback:
17401 0 : alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)", &_alglib_env_state);
17402 : }
17403 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
17404 0 : }
17405 :
17406 :
17407 0 : void minlmoptimize(minlmstate &state,
17408 : void (*func)(const real_1d_array &x, double &func, void *ptr),
17409 : void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr),
17410 : void (*hess)(const real_1d_array &x, double &func, real_1d_array &grad, real_2d_array &hess, void *ptr),
17411 : void (*rep)(const real_1d_array &x, double func, void *ptr),
17412 : void *ptr,
17413 : const xparams _xparams)
17414 : {
17415 : jmp_buf _break_jump;
17416 : alglib_impl::ae_state _alglib_env_state;
17417 0 : alglib_impl::ae_state_init(&_alglib_env_state);
17418 0 : if( setjmp(_break_jump) )
17419 : {
17420 : #if !defined(AE_NO_EXCEPTIONS)
17421 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
17422 : #else
17423 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
17424 : return;
17425 : #endif
17426 : }
17427 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
17428 0 : if( _xparams.flags!=0x0 )
17429 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
17430 0 : alglib_impl::ae_assert(func!=NULL, "ALGLIB: error in 'minlmoptimize()' (func is NULL)", &_alglib_env_state);
17431 0 : alglib_impl::ae_assert(grad!=NULL, "ALGLIB: error in 'minlmoptimize()' (grad is NULL)", &_alglib_env_state);
17432 0 : alglib_impl::ae_assert(hess!=NULL, "ALGLIB: error in 'minlmoptimize()' (hess is NULL)", &_alglib_env_state);
17433 0 : while( alglib_impl::minlmiteration(state.c_ptr(), &_alglib_env_state) )
17434 : {
17435 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN
17436 0 : if( state.needf )
17437 : {
17438 0 : func(state.x, state.f, ptr);
17439 0 : continue;
17440 : }
17441 0 : if( state.needfg )
17442 : {
17443 0 : grad(state.x, state.f, state.g, ptr);
17444 0 : continue;
17445 : }
17446 0 : if( state.needfgh )
17447 : {
17448 0 : hess(state.x, state.f, state.g, state.h, ptr);
17449 0 : continue;
17450 : }
17451 0 : if( state.xupdated )
17452 : {
17453 0 : if( rep!=NULL )
17454 0 : rep(state.x, state.f, ptr);
17455 0 : continue;
17456 : }
17457 0 : goto lbl_no_callback;
17458 0 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_END
17459 0 : lbl_no_callback:
17460 0 : alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)", &_alglib_env_state);
17461 : }
17462 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
17463 0 : }
17464 :
17465 :
17466 0 : void minlmoptimize(minlmstate &state,
17467 : void (*func)(const real_1d_array &x, double &func, void *ptr),
17468 : void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr),
17469 : void (*rep)(const real_1d_array &x, double func, void *ptr),
17470 : void *ptr,
17471 : const xparams _xparams)
17472 : {
17473 : jmp_buf _break_jump;
17474 : alglib_impl::ae_state _alglib_env_state;
17475 0 : alglib_impl::ae_state_init(&_alglib_env_state);
17476 0 : if( setjmp(_break_jump) )
17477 : {
17478 : #if !defined(AE_NO_EXCEPTIONS)
17479 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
17480 : #else
17481 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
17482 : return;
17483 : #endif
17484 : }
17485 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
17486 0 : if( _xparams.flags!=0x0 )
17487 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
17488 0 : alglib_impl::ae_assert(func!=NULL, "ALGLIB: error in 'minlmoptimize()' (func is NULL)", &_alglib_env_state);
17489 0 : alglib_impl::ae_assert(jac!=NULL, "ALGLIB: error in 'minlmoptimize()' (jac is NULL)", &_alglib_env_state);
17490 0 : while( alglib_impl::minlmiteration(state.c_ptr(), &_alglib_env_state) )
17491 : {
17492 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN
17493 0 : if( state.needf )
17494 : {
17495 0 : func(state.x, state.f, ptr);
17496 0 : continue;
17497 : }
17498 0 : if( state.needfij )
17499 : {
17500 0 : jac(state.x, state.fi, state.j, ptr);
17501 0 : continue;
17502 : }
17503 0 : if( state.xupdated )
17504 : {
17505 0 : if( rep!=NULL )
17506 0 : rep(state.x, state.f, ptr);
17507 0 : continue;
17508 : }
17509 0 : goto lbl_no_callback;
17510 0 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_END
17511 0 : lbl_no_callback:
17512 0 : alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)", &_alglib_env_state);
17513 : }
17514 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
17515 0 : }
17516 :
17517 :
17518 0 : void minlmoptimize(minlmstate &state,
17519 : void (*func)(const real_1d_array &x, double &func, void *ptr),
17520 : void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr),
17521 : void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr),
17522 : void (*rep)(const real_1d_array &x, double func, void *ptr),
17523 : void *ptr,
17524 : const xparams _xparams)
17525 : {
17526 : jmp_buf _break_jump;
17527 : alglib_impl::ae_state _alglib_env_state;
17528 0 : alglib_impl::ae_state_init(&_alglib_env_state);
17529 0 : if( setjmp(_break_jump) )
17530 : {
17531 : #if !defined(AE_NO_EXCEPTIONS)
17532 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
17533 : #else
17534 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
17535 : return;
17536 : #endif
17537 : }
17538 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
17539 0 : if( _xparams.flags!=0x0 )
17540 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
17541 0 : alglib_impl::ae_assert(func!=NULL, "ALGLIB: error in 'minlmoptimize()' (func is NULL)", &_alglib_env_state);
17542 0 : alglib_impl::ae_assert(grad!=NULL, "ALGLIB: error in 'minlmoptimize()' (grad is NULL)", &_alglib_env_state);
17543 0 : alglib_impl::ae_assert(jac!=NULL, "ALGLIB: error in 'minlmoptimize()' (jac is NULL)", &_alglib_env_state);
17544 0 : while( alglib_impl::minlmiteration(state.c_ptr(), &_alglib_env_state) )
17545 : {
17546 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_BEGIN
17547 0 : if( state.needf )
17548 : {
17549 0 : func(state.x, state.f, ptr);
17550 0 : continue;
17551 : }
17552 0 : if( state.needfg )
17553 : {
17554 0 : grad(state.x, state.f, state.g, ptr);
17555 0 : continue;
17556 : }
17557 0 : if( state.needfij )
17558 : {
17559 0 : jac(state.x, state.fi, state.j, ptr);
17560 0 : continue;
17561 : }
17562 0 : if( state.xupdated )
17563 : {
17564 0 : if( rep!=NULL )
17565 0 : rep(state.x, state.f, ptr);
17566 0 : continue;
17567 : }
17568 0 : goto lbl_no_callback;
17569 0 : _ALGLIB_CALLBACK_EXCEPTION_GUARD_END
17570 0 : lbl_no_callback:
17571 0 : alglib_impl::ae_assert(ae_false, "ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)", &_alglib_env_state);
17572 : }
17573 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
17574 0 : }
17575 :
17576 :
17577 :
17578 : /*************************************************************************
17579 : This function activates/deactivates verification of the user-supplied
17580 : analytic Jacobian.
17581 :
17582 : Upon activation of this option OptGuard integrity checker performs
17583 : numerical differentiation of your target function vector at the initial
17584 : point (note: future versions may also perform check at the final point)
17585 : and compares numerical Jacobian with analytic one provided by you.
17586 :
17587 : If difference is too large, an error flag is set and optimization session
17588 : continues. After optimization session is over, you can retrieve the report
17589 : which stores both Jacobians, and specific components highlighted as
17590 : suspicious by the OptGuard.
17591 :
17592 : The OptGuard report can be retrieved with minlmoptguardresults().
17593 :
17594 : IMPORTANT: gradient check is a high-overhead option which will cost you
17595 : about 3*N additional function evaluations. In many cases it may
17596 : cost as much as the rest of the optimization session.
17597 :
17598 : YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO
17599 : CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY.
17600 :
17601 : NOTE: unlike previous incarnation of the gradient checking code, OptGuard
17602 : does NOT interrupt optimization even if it discovers bad gradient.
17603 :
17604 : INPUT PARAMETERS:
17605 : State - structure used to store algorithm state
17606 : TestStep - verification step used for numerical differentiation:
17607 : * TestStep=0 turns verification off
17608 : * TestStep>0 activates verification
17609 : You should carefully choose TestStep. Value which is
17610 : too large (so large that function behavior is non-
17611 : cubic at this scale) will lead to false alarms. Too
17612 : short step will result in rounding errors dominating
17613 : numerical derivative.
17614 :
17615 : You may use different step for different parameters by
17616 : means of setting scale with minlmsetscale().
17617 :
17618 : === EXPLANATION ==========================================================
17619 :
17620 : In order to verify gradient algorithm performs following steps:
17621 : * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i],
17622 : where X[i] is i-th component of the initial point and S[i] is a scale
17623 : of i-th parameter
17624 : * F(X) is evaluated at these trial points
17625 : * we perform one more evaluation in the middle point of the interval
17626 : * we build cubic model using function values and derivatives at trial
17627 : points and we compare its prediction with actual value in the middle
17628 : point
17629 :
17630 : -- ALGLIB --
17631 : Copyright 15.06.2014 by Bochkanov Sergey
17632 : *************************************************************************/
17633 0 : void minlmoptguardgradient(const minlmstate &state, const double teststep, const xparams _xparams)
17634 : {
17635 : jmp_buf _break_jump;
17636 : alglib_impl::ae_state _alglib_env_state;
17637 0 : alglib_impl::ae_state_init(&_alglib_env_state);
17638 0 : if( setjmp(_break_jump) )
17639 : {
17640 : #if !defined(AE_NO_EXCEPTIONS)
17641 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
17642 : #else
17643 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
17644 : return;
17645 : #endif
17646 : }
17647 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
17648 0 : if( _xparams.flags!=0x0 )
17649 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
17650 0 : alglib_impl::minlmoptguardgradient(const_cast<alglib_impl::minlmstate*>(state.c_ptr()), teststep, &_alglib_env_state);
17651 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
17652 0 : return;
17653 : }
17654 :
17655 : /*************************************************************************
17656 : Results of OptGuard integrity check, should be called after optimization
17657 : session is over.
17658 :
17659 : OptGuard checks analytic Jacobian against reference value obtained by
17660 : numerical differentiation with user-specified step.
17661 :
17662 : NOTE: other optimizers perform additional OptGuard checks for things like
17663 : C0/C1-continuity violations. However, LM optimizer can check only
17664 : for incorrect Jacobian.
17665 :
17666 : The reason is that unlike line search methods LM optimizer does not
17667 : perform extensive evaluations along the line. Thus, we simply do not
17668 : have enough data to catch C0/C1-violations.
17669 :
17670 : This check is activated with minlmoptguardgradient() function.
17671 :
17672 : Following flags are set when these errors are suspected:
17673 : * rep.badgradsuspected, and additionally:
17674 : * rep.badgradfidx for specific function (Jacobian row) suspected
17675 : * rep.badgradvidx for specific variable (Jacobian column) suspected
17676 : * rep.badgradxbase, a point where gradient/Jacobian is tested
17677 : * rep.badgraduser, user-provided gradient/Jacobian
17678 : * rep.badgradnum, reference gradient/Jacobian obtained via numerical
17679 : differentiation
17680 :
17681 : INPUT PARAMETERS:
17682 : state - algorithm state
17683 :
17684 : OUTPUT PARAMETERS:
17685 : rep - OptGuard report
17686 :
17687 : -- ALGLIB --
17688 : Copyright 21.11.2018 by Bochkanov Sergey
17689 : *************************************************************************/
17690 0 : void minlmoptguardresults(const minlmstate &state, optguardreport &rep, const xparams _xparams)
17691 : {
17692 : jmp_buf _break_jump;
17693 : alglib_impl::ae_state _alglib_env_state;
17694 0 : alglib_impl::ae_state_init(&_alglib_env_state);
17695 0 : if( setjmp(_break_jump) )
17696 : {
17697 : #if !defined(AE_NO_EXCEPTIONS)
17698 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
17699 : #else
17700 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
17701 : return;
17702 : #endif
17703 : }
17704 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
17705 0 : if( _xparams.flags!=0x0 )
17706 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
17707 0 : alglib_impl::minlmoptguardresults(const_cast<alglib_impl::minlmstate*>(state.c_ptr()), const_cast<alglib_impl::optguardreport*>(rep.c_ptr()), &_alglib_env_state);
17708 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
17709 0 : return;
17710 : }
17711 :
17712 : /*************************************************************************
17713 : Levenberg-Marquardt algorithm results
17714 :
17715 : NOTE: if you activated OptGuard integrity checking functionality and want
17716 : to get OptGuard report, it can be retrieved with the help of
17717 : minlmoptguardresults() function.
17718 :
17719 : INPUT PARAMETERS:
17720 : State - algorithm state
17721 :
17722 : OUTPUT PARAMETERS:
17723 : X - array[0..N-1], solution
17724 : Rep - optimization report; includes termination codes and
17725 : additional information. Termination codes are listed below,
17726 : see comments for this structure for more info.
17727 : Termination code is stored in rep.terminationtype field:
17728 : * -8 optimizer detected NAN/INF values either in the
17729 : function itself, or in its Jacobian
17730 : * -3 constraints are inconsistent
17731 : * 2 relative step is no more than EpsX.
17732 : * 5 MaxIts steps was taken
17733 : * 7 stopping conditions are too stringent,
17734 : further improvement is impossible
17735 : * 8 terminated by user who called minlmrequesttermination().
17736 : X contains point which was "current accepted" when
17737 : termination request was submitted.
17738 :
17739 : -- ALGLIB --
17740 : Copyright 10.03.2009 by Bochkanov Sergey
17741 : *************************************************************************/
17742 0 : void minlmresults(const minlmstate &state, real_1d_array &x, minlmreport &rep, const xparams _xparams)
17743 : {
17744 : jmp_buf _break_jump;
17745 : alglib_impl::ae_state _alglib_env_state;
17746 0 : alglib_impl::ae_state_init(&_alglib_env_state);
17747 0 : if( setjmp(_break_jump) )
17748 : {
17749 : #if !defined(AE_NO_EXCEPTIONS)
17750 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
17751 : #else
17752 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
17753 : return;
17754 : #endif
17755 : }
17756 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
17757 0 : if( _xparams.flags!=0x0 )
17758 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
17759 0 : 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);
17760 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
17761 0 : return;
17762 : }
17763 :
17764 : /*************************************************************************
17765 : Levenberg-Marquardt algorithm results
17766 :
17767 : Buffered implementation of MinLMResults(), which uses pre-allocated buffer
17768 : to store X[]. If buffer size is too small, it resizes buffer. It is
17769 : intended to be used in the inner cycles of performance critical algorithms
17770 : where array reallocation penalty is too large to be ignored.
17771 :
17772 : -- ALGLIB --
17773 : Copyright 10.03.2009 by Bochkanov Sergey
17774 : *************************************************************************/
17775 0 : void minlmresultsbuf(const minlmstate &state, real_1d_array &x, minlmreport &rep, const xparams _xparams)
17776 : {
17777 : jmp_buf _break_jump;
17778 : alglib_impl::ae_state _alglib_env_state;
17779 0 : alglib_impl::ae_state_init(&_alglib_env_state);
17780 0 : if( setjmp(_break_jump) )
17781 : {
17782 : #if !defined(AE_NO_EXCEPTIONS)
17783 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
17784 : #else
17785 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
17786 : return;
17787 : #endif
17788 : }
17789 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
17790 0 : if( _xparams.flags!=0x0 )
17791 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
17792 0 : 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);
17793 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
17794 0 : return;
17795 : }
17796 :
17797 : /*************************************************************************
17798 : This subroutine restarts LM algorithm from new point. All optimization
17799 : parameters are left unchanged.
17800 :
17801 : This function allows to solve multiple optimization problems (which
17802 : must have same number of dimensions) without object reallocation penalty.
17803 :
17804 : INPUT PARAMETERS:
17805 : State - structure used for reverse communication previously
17806 : allocated with MinLMCreateXXX call.
17807 : X - new starting point.
17808 :
17809 : -- ALGLIB --
17810 : Copyright 30.07.2010 by Bochkanov Sergey
17811 : *************************************************************************/
17812 0 : void minlmrestartfrom(const minlmstate &state, const real_1d_array &x, const xparams _xparams)
17813 : {
17814 : jmp_buf _break_jump;
17815 : alglib_impl::ae_state _alglib_env_state;
17816 0 : alglib_impl::ae_state_init(&_alglib_env_state);
17817 0 : if( setjmp(_break_jump) )
17818 : {
17819 : #if !defined(AE_NO_EXCEPTIONS)
17820 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
17821 : #else
17822 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
17823 : return;
17824 : #endif
17825 : }
17826 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
17827 0 : if( _xparams.flags!=0x0 )
17828 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
17829 0 : alglib_impl::minlmrestartfrom(const_cast<alglib_impl::minlmstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
17830 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
17831 0 : return;
17832 : }
17833 :
17834 : /*************************************************************************
17835 : This subroutine submits request for termination of running optimizer. It
17836 : should be called from user-supplied callback when user decides that it is
17837 : time to "smoothly" terminate optimization process. As result, optimizer
17838 : stops at point which was "current accepted" when termination request was
17839 : submitted and returns error code 8 (successful termination).
17840 :
17841 : INPUT PARAMETERS:
17842 : State - optimizer structure
17843 :
17844 : NOTE: after request for termination optimizer may perform several
17845 : additional calls to user-supplied callbacks. It does NOT guarantee
17846 : to stop immediately - it just guarantees that these additional calls
17847 : will be discarded later.
17848 :
17849 : NOTE: calling this function on optimizer which is NOT running will have no
17850 : effect.
17851 :
17852 : NOTE: multiple calls to this function are possible. First call is counted,
17853 : subsequent calls are silently ignored.
17854 :
17855 : -- ALGLIB --
17856 : Copyright 08.10.2014 by Bochkanov Sergey
17857 : *************************************************************************/
17858 0 : void minlmrequesttermination(const minlmstate &state, const xparams _xparams)
17859 : {
17860 : jmp_buf _break_jump;
17861 : alglib_impl::ae_state _alglib_env_state;
17862 0 : alglib_impl::ae_state_init(&_alglib_env_state);
17863 0 : if( setjmp(_break_jump) )
17864 : {
17865 : #if !defined(AE_NO_EXCEPTIONS)
17866 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
17867 : #else
17868 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
17869 : return;
17870 : #endif
17871 : }
17872 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
17873 0 : if( _xparams.flags!=0x0 )
17874 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
17875 0 : alglib_impl::minlmrequesttermination(const_cast<alglib_impl::minlmstate*>(state.c_ptr()), &_alglib_env_state);
17876 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
17877 0 : return;
17878 : }
17879 :
17880 : /*************************************************************************
17881 : This is obsolete function.
17882 :
17883 : Since ALGLIB 3.3 it is equivalent to MinLMCreateVJ().
17884 :
17885 : -- ALGLIB --
17886 : Copyright 30.03.2009 by Bochkanov Sergey
17887 : *************************************************************************/
17888 0 : void minlmcreatevgj(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams)
17889 : {
17890 : jmp_buf _break_jump;
17891 : alglib_impl::ae_state _alglib_env_state;
17892 0 : alglib_impl::ae_state_init(&_alglib_env_state);
17893 0 : if( setjmp(_break_jump) )
17894 : {
17895 : #if !defined(AE_NO_EXCEPTIONS)
17896 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
17897 : #else
17898 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
17899 : return;
17900 : #endif
17901 : }
17902 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
17903 0 : if( _xparams.flags!=0x0 )
17904 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
17905 0 : 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);
17906 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
17907 0 : return;
17908 : }
17909 :
17910 : /*************************************************************************
17911 : This is obsolete function.
17912 :
17913 : Since ALGLIB 3.3 it is equivalent to MinLMCreateVJ().
17914 :
17915 : -- ALGLIB --
17916 : Copyright 30.03.2009 by Bochkanov Sergey
17917 : *************************************************************************/
17918 : #if !defined(AE_NO_EXCEPTIONS)
17919 0 : void minlmcreatevgj(const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams)
17920 : {
17921 : jmp_buf _break_jump;
17922 : alglib_impl::ae_state _alglib_env_state;
17923 : ae_int_t n;
17924 :
17925 0 : n = x.length();
17926 0 : alglib_impl::ae_state_init(&_alglib_env_state);
17927 0 : if( setjmp(_break_jump) )
17928 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
17929 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
17930 0 : if( _xparams.flags!=0x0 )
17931 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
17932 0 : 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);
17933 :
17934 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
17935 0 : return;
17936 : }
17937 : #endif
17938 :
17939 : /*************************************************************************
17940 : This is obsolete function.
17941 :
17942 : Since ALGLIB 3.3 it is equivalent to MinLMCreateFJ().
17943 :
17944 : -- ALGLIB --
17945 : Copyright 30.03.2009 by Bochkanov Sergey
17946 : *************************************************************************/
17947 0 : void minlmcreatefgj(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams)
17948 : {
17949 : jmp_buf _break_jump;
17950 : alglib_impl::ae_state _alglib_env_state;
17951 0 : alglib_impl::ae_state_init(&_alglib_env_state);
17952 0 : if( setjmp(_break_jump) )
17953 : {
17954 : #if !defined(AE_NO_EXCEPTIONS)
17955 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
17956 : #else
17957 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
17958 : return;
17959 : #endif
17960 : }
17961 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
17962 0 : if( _xparams.flags!=0x0 )
17963 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
17964 0 : 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);
17965 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
17966 0 : return;
17967 : }
17968 :
17969 : /*************************************************************************
17970 : This is obsolete function.
17971 :
17972 : Since ALGLIB 3.3 it is equivalent to MinLMCreateFJ().
17973 :
17974 : -- ALGLIB --
17975 : Copyright 30.03.2009 by Bochkanov Sergey
17976 : *************************************************************************/
17977 : #if !defined(AE_NO_EXCEPTIONS)
17978 0 : void minlmcreatefgj(const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams)
17979 : {
17980 : jmp_buf _break_jump;
17981 : alglib_impl::ae_state _alglib_env_state;
17982 : ae_int_t n;
17983 :
17984 0 : n = x.length();
17985 0 : alglib_impl::ae_state_init(&_alglib_env_state);
17986 0 : if( setjmp(_break_jump) )
17987 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
17988 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
17989 0 : if( _xparams.flags!=0x0 )
17990 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
17991 0 : 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);
17992 :
17993 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
17994 0 : return;
17995 : }
17996 : #endif
17997 :
17998 : /*************************************************************************
17999 : This function is considered obsolete since ALGLIB 3.1.0 and is present for
18000 : backward compatibility only. We recommend to use MinLMCreateVJ, which
18001 : provides similar, but more consistent and feature-rich interface.
18002 :
18003 : -- ALGLIB --
18004 : Copyright 30.03.2009 by Bochkanov Sergey
18005 : *************************************************************************/
18006 0 : void minlmcreatefj(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams)
18007 : {
18008 : jmp_buf _break_jump;
18009 : alglib_impl::ae_state _alglib_env_state;
18010 0 : alglib_impl::ae_state_init(&_alglib_env_state);
18011 0 : if( setjmp(_break_jump) )
18012 : {
18013 : #if !defined(AE_NO_EXCEPTIONS)
18014 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
18015 : #else
18016 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
18017 : return;
18018 : #endif
18019 : }
18020 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
18021 0 : if( _xparams.flags!=0x0 )
18022 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
18023 0 : 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);
18024 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
18025 0 : return;
18026 : }
18027 :
18028 : /*************************************************************************
18029 : This function is considered obsolete since ALGLIB 3.1.0 and is present for
18030 : backward compatibility only. We recommend to use MinLMCreateVJ, which
18031 : provides similar, but more consistent and feature-rich interface.
18032 :
18033 : -- ALGLIB --
18034 : Copyright 30.03.2009 by Bochkanov Sergey
18035 : *************************************************************************/
18036 : #if !defined(AE_NO_EXCEPTIONS)
18037 0 : void minlmcreatefj(const ae_int_t m, const real_1d_array &x, minlmstate &state, const xparams _xparams)
18038 : {
18039 : jmp_buf _break_jump;
18040 : alglib_impl::ae_state _alglib_env_state;
18041 : ae_int_t n;
18042 :
18043 0 : n = x.length();
18044 0 : alglib_impl::ae_state_init(&_alglib_env_state);
18045 0 : if( setjmp(_break_jump) )
18046 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
18047 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
18048 0 : if( _xparams.flags!=0x0 )
18049 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
18050 0 : 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);
18051 :
18052 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
18053 0 : return;
18054 : }
18055 : #endif
18056 : #endif
18057 : }
18058 :
18059 : /////////////////////////////////////////////////////////////////////////
18060 : //
18061 : // THIS SECTION CONTAINS IMPLEMENTATION OF COMPUTATIONAL CORE
18062 : //
18063 : /////////////////////////////////////////////////////////////////////////
18064 : namespace alglib_impl
18065 : {
18066 : #if defined(AE_COMPILE_CQMODELS) || !defined(AE_PARTIAL_BUILD)
18067 : static ae_int_t cqmodels_newtonrefinementits = 3;
18068 : static ae_bool cqmodels_cqmrebuild(convexquadraticmodel* s,
18069 : ae_state *_state);
18070 : static void cqmodels_cqmsolveea(convexquadraticmodel* s,
18071 : /* Real */ ae_vector* x,
18072 : /* Real */ ae_vector* tmp,
18073 : ae_state *_state);
18074 :
18075 :
18076 : #endif
18077 : #if defined(AE_COMPILE_OPTGUARDAPI) || !defined(AE_PARTIAL_BUILD)
18078 :
18079 :
18080 : #endif
18081 : #if defined(AE_COMPILE_OPTSERV) || !defined(AE_PARTIAL_BUILD)
18082 : static double optserv_ognoiselevelf = 1.0E2*ae_machineepsilon;
18083 : static double optserv_ognoiselevelg = 1.0E4*ae_machineepsilon;
18084 : static double optserv_ogminrating0 = 50.0;
18085 : static double optserv_ogminrating1 = 50.0;
18086 : static double optserv_feasibilityerror(/* Real */ ae_matrix* ce,
18087 : /* Real */ ae_vector* x,
18088 : ae_int_t nmain,
18089 : ae_int_t nslack,
18090 : ae_int_t k,
18091 : /* Real */ ae_vector* tmp0,
18092 : ae_state *_state);
18093 : static void optserv_feasibilityerrorgrad(/* Real */ ae_matrix* ce,
18094 : /* Real */ ae_vector* x,
18095 : ae_int_t nmain,
18096 : ae_int_t nslack,
18097 : ae_int_t k,
18098 : double* err,
18099 : /* Real */ ae_vector* grad,
18100 : /* Real */ ae_vector* tmp0,
18101 : ae_state *_state);
18102 : static void optserv_testc0continuity(double f0,
18103 : double f1,
18104 : double f2,
18105 : double f3,
18106 : double noise0,
18107 : double noise1,
18108 : double noise2,
18109 : double noise3,
18110 : double delta0,
18111 : double delta1,
18112 : double delta2,
18113 : ae_bool applyspecialcorrection,
18114 : double* rating,
18115 : double* lipschitz,
18116 : ae_state *_state);
18117 : static void optserv_c1continuitytest0(smoothnessmonitor* monitor,
18118 : ae_int_t funcidx,
18119 : ae_int_t stpidx,
18120 : ae_int_t sortedcnt,
18121 : ae_state *_state);
18122 : static void optserv_c1continuitytest1(smoothnessmonitor* monitor,
18123 : ae_int_t funcidx,
18124 : ae_int_t stpidx,
18125 : ae_int_t sortedcnt,
18126 : ae_state *_state);
18127 :
18128 :
18129 : #endif
18130 : #if defined(AE_COMPILE_SNNLS) || !defined(AE_PARTIAL_BUILD)
18131 : static void snnls_funcgradu(snnlssolver* s,
18132 : /* Real */ ae_vector* x,
18133 : /* Real */ ae_vector* r,
18134 : /* Real */ ae_vector* g,
18135 : double* f,
18136 : ae_state *_state);
18137 : static void snnls_func(snnlssolver* s,
18138 : /* Real */ ae_vector* x,
18139 : double* f,
18140 : ae_state *_state);
18141 : static void snnls_trdprepare(snnlssolver* s,
18142 : /* Real */ ae_vector* x,
18143 : /* Real */ ae_vector* diag,
18144 : double lambdav,
18145 : /* Real */ ae_vector* trdd,
18146 : /* Real */ ae_matrix* trda,
18147 : /* Real */ ae_vector* tmp0,
18148 : /* Real */ ae_vector* tmp1,
18149 : /* Real */ ae_vector* tmp2,
18150 : /* Real */ ae_matrix* tmplq,
18151 : ae_state *_state);
18152 : static void snnls_trdsolve(/* Real */ ae_vector* trdd,
18153 : /* Real */ ae_matrix* trda,
18154 : ae_int_t ns,
18155 : ae_int_t nd,
18156 : /* Real */ ae_vector* d,
18157 : ae_state *_state);
18158 : static void snnls_trdfixvariable(/* Real */ ae_vector* trdd,
18159 : /* Real */ ae_matrix* trda,
18160 : ae_int_t ns,
18161 : ae_int_t nd,
18162 : ae_int_t idx,
18163 : /* Real */ ae_vector* tmp,
18164 : ae_state *_state);
18165 :
18166 :
18167 : #endif
18168 : #if defined(AE_COMPILE_SACTIVESETS) || !defined(AE_PARTIAL_BUILD)
18169 : static ae_int_t sactivesets_maxbasisage = 5;
18170 : static double sactivesets_maxbasisdecay = 0.01;
18171 : static double sactivesets_minnormseparation = 0.25;
18172 : static void sactivesets_constraineddescent(sactiveset* state,
18173 : /* Real */ ae_vector* g,
18174 : /* Real */ ae_vector* h,
18175 : /* Real */ ae_matrix* ha,
18176 : ae_bool normalize,
18177 : /* Real */ ae_vector* d,
18178 : ae_state *_state);
18179 : static void sactivesets_reactivateconstraints(sactiveset* state,
18180 : /* Real */ ae_vector* gc,
18181 : /* Real */ ae_vector* h,
18182 : ae_state *_state);
18183 :
18184 :
18185 : #endif
18186 : #if defined(AE_COMPILE_QQPSOLVER) || !defined(AE_PARTIAL_BUILD)
18187 : static ae_int_t qqpsolver_quickqprestartcg = 50;
18188 : static double qqpsolver_regz = 1.0E-9;
18189 : static double qqpsolver_projectedtargetfunction(qqpbuffers* sstate,
18190 : /* Real */ ae_vector* x,
18191 : /* Real */ ae_vector* d,
18192 : double stp,
18193 : /* Real */ ae_vector* tmp0,
18194 : /* Real */ ae_vector* tmp1,
18195 : ae_state *_state);
18196 : static void qqpsolver_targetgradient(qqpbuffers* sstate,
18197 : /* Real */ ae_vector* x,
18198 : /* Real */ ae_vector* g,
18199 : ae_state *_state);
18200 : static void qqpsolver_quadraticmodel(qqpbuffers* sstate,
18201 : /* Real */ ae_vector* x,
18202 : /* Real */ ae_vector* d,
18203 : /* Real */ ae_vector* g,
18204 : double* d1,
18205 : ae_int_t* d1est,
18206 : double* d2,
18207 : ae_int_t* d2est,
18208 : /* Real */ ae_vector* tmp0,
18209 : ae_state *_state);
18210 : static void qqpsolver_findbeststepandmove(qqpbuffers* sstate,
18211 : sactiveset* sas,
18212 : /* Real */ ae_vector* d,
18213 : double stp,
18214 : ae_bool needact,
18215 : ae_int_t cidx,
18216 : double cval,
18217 : /* Real */ ae_vector* addsteps,
18218 : ae_int_t addstepscnt,
18219 : /* Boolean */ ae_vector* activated,
18220 : /* Real */ ae_vector* tmp0,
18221 : /* Real */ ae_vector* tmp1,
18222 : ae_state *_state);
18223 : static ae_bool qqpsolver_cnewtonbuild(qqpbuffers* sstate,
18224 : ae_int_t sparsesolver,
18225 : ae_int_t* ncholesky,
18226 : ae_state *_state);
18227 : static ae_bool qqpsolver_cnewtonupdate(qqpbuffers* sstate,
18228 : qqpsettings* settings,
18229 : ae_int_t* ncupdates,
18230 : ae_state *_state);
18231 : static ae_bool qqpsolver_cnewtonstep(qqpbuffers* sstate,
18232 : qqpsettings* settings,
18233 : /* Real */ ae_vector* gc,
18234 : ae_state *_state);
18235 :
18236 :
18237 : #endif
18238 : #if defined(AE_COMPILE_MINLBFGS) || !defined(AE_PARTIAL_BUILD)
18239 : static double minlbfgs_gtol = 0.4;
18240 : static void minlbfgs_clearrequestfields(minlbfgsstate* state,
18241 : ae_state *_state);
18242 :
18243 :
18244 : #endif
18245 : #if defined(AE_COMPILE_LPQPSERV) || !defined(AE_PARTIAL_BUILD)
18246 :
18247 :
18248 : #endif
18249 : #if defined(AE_COMPILE_VIPMSOLVER) || !defined(AE_PARTIAL_BUILD)
18250 : static ae_int_t vipmsolver_maxipmits = 200;
18251 : static double vipmsolver_initslackval = 100.0;
18252 : static double vipmsolver_steplengthdecay = 0.95;
18253 : static double vipmsolver_stagnationdelta = 0.99999;
18254 : static double vipmsolver_primalinfeasible1 = 1.0E-3;
18255 : static double vipmsolver_dualinfeasible1 = 1.0E-3;
18256 : static double vipmsolver_bigy = 1.0E8;
18257 : static double vipmsolver_ygrowth = 1.0E6;
18258 : static ae_int_t vipmsolver_itersfortoostringentcond = 25;
18259 : static ae_int_t vipmsolver_minitersbeforedroppingbounds = 3;
18260 : static ae_int_t vipmsolver_minitersbeforeinfeasible = 3;
18261 : static ae_int_t vipmsolver_minitersbeforestagnation = 5;
18262 : static ae_int_t vipmsolver_minitersbeforeeworststagnation = 50;
18263 : static ae_int_t vipmsolver_primalstagnationlen = 5;
18264 : static ae_int_t vipmsolver_dualstagnationlen = 7;
18265 : static double vipmsolver_bigconstrxtol = 1.0E-5;
18266 : static double vipmsolver_bigconstrmag = 1.0E3;
18267 : static double vipmsolver_minitersbeforesafeguards = 5;
18268 : static double vipmsolver_badsteplength = 1.0E-3;
18269 : static void vipmsolver_varsinitbyzero(vipmvars* vstate,
18270 : ae_int_t n,
18271 : ae_int_t m,
18272 : ae_state *_state);
18273 : static void vipmsolver_varsinitfrom(vipmvars* vstate,
18274 : vipmvars* vsrc,
18275 : ae_state *_state);
18276 : static void vipmsolver_varsaddstep(vipmvars* vstate,
18277 : vipmvars* vdir,
18278 : double stpp,
18279 : double stpd,
18280 : ae_state *_state);
18281 : static double vipmsolver_varscomputecomplementaritygap(vipmvars* vstate,
18282 : ae_state *_state);
18283 : static double vipmsolver_varscomputemu(vipmvars* vstate, ae_state *_state);
18284 : static void vipmsolver_vipminit(vipmstate* state,
18285 : /* Real */ ae_vector* s,
18286 : /* Real */ ae_vector* xorigin,
18287 : ae_int_t n,
18288 : ae_int_t nmain,
18289 : ae_int_t ftype,
18290 : ae_state *_state);
18291 : static double vipmsolver_vipmtarget(vipmstate* state,
18292 : /* Real */ ae_vector* x,
18293 : ae_state *_state);
18294 : static void vipmsolver_multiplygeax(vipmstate* state,
18295 : double alpha,
18296 : /* Real */ ae_vector* x,
18297 : ae_int_t offsx,
18298 : double beta,
18299 : /* Real */ ae_vector* y,
18300 : ae_int_t offsax,
18301 : ae_state *_state);
18302 : static void vipmsolver_multiplygeatx(vipmstate* state,
18303 : double alpha,
18304 : /* Real */ ae_vector* x,
18305 : ae_int_t offsx,
18306 : double beta,
18307 : /* Real */ ae_vector* y,
18308 : ae_int_t offsy,
18309 : ae_state *_state);
18310 : static void vipmsolver_multiplyhx(vipmstate* state,
18311 : /* Real */ ae_vector* x,
18312 : /* Real */ ae_vector* hx,
18313 : ae_state *_state);
18314 : static void vipmsolver_vipmmultiply(vipmstate* state,
18315 : /* Real */ ae_vector* x,
18316 : /* Real */ ae_vector* y,
18317 : /* Real */ ae_vector* hx,
18318 : /* Real */ ae_vector* ax,
18319 : /* Real */ ae_vector* aty,
18320 : ae_state *_state);
18321 : static void vipmsolver_vipmpowerup(vipmstate* state,
18322 : double regfree,
18323 : ae_state *_state);
18324 : static ae_bool vipmsolver_vipmfactorize(vipmstate* state,
18325 : double alpha0,
18326 : /* Real */ ae_vector* d,
18327 : double beta0,
18328 : /* Real */ ae_vector* e,
18329 : double alpha11,
18330 : double beta11,
18331 : double modeps,
18332 : double dampeps,
18333 : ae_state *_state);
18334 : static void vipmsolver_solvereducedkktsystem(vipmstate* state,
18335 : /* Real */ ae_vector* deltaxy,
18336 : ae_state *_state);
18337 : static ae_bool vipmsolver_vipmprecomputenewtonfactorization(vipmstate* state,
18338 : vipmvars* v0,
18339 : double regeps,
18340 : double modeps,
18341 : double dampeps,
18342 : double dampfree,
18343 : ae_state *_state);
18344 : static void vipmsolver_solvekktsystem(vipmstate* state,
18345 : vipmrighthandside* rhs,
18346 : vipmvars* sol,
18347 : ae_state *_state);
18348 : static ae_bool vipmsolver_vipmcomputestepdirection(vipmstate* state,
18349 : vipmvars* v0,
18350 : double muestimate,
18351 : vipmvars* vdestimate,
18352 : vipmvars* vdresult,
18353 : double reg,
18354 : ae_bool isdampepslarge,
18355 : ae_state *_state);
18356 : static void vipmsolver_vipmcomputesteplength(vipmstate* state,
18357 : vipmvars* v0,
18358 : vipmvars* vs,
18359 : double stepdecay,
18360 : double* alphap,
18361 : double* alphad,
18362 : ae_state *_state);
18363 : static void vipmsolver_vipmperformstep(vipmstate* state,
18364 : double alphap,
18365 : double alphad,
18366 : ae_state *_state);
18367 : static void vipmsolver_computeerrors(vipmstate* state,
18368 : double* errp2,
18369 : double* errd2,
18370 : double* errpinf,
18371 : double* errdinf,
18372 : double* egap,
18373 : ae_state *_state);
18374 : static void vipmsolver_runintegritychecks(vipmstate* state,
18375 : vipmvars* v0,
18376 : vipmvars* vd,
18377 : double alphap,
18378 : double alphad,
18379 : ae_state *_state);
18380 : static void vipmsolver_traceprogress(vipmstate* state,
18381 : double mu,
18382 : double muaff,
18383 : double sigma,
18384 : double alphap,
18385 : double alphad,
18386 : ae_state *_state);
18387 : static void vipmsolver_rhscompute(vipmstate* state,
18388 : vipmvars* v0,
18389 : double muestimate,
18390 : vipmvars* direstimate,
18391 : vipmrighthandside* rhs,
18392 : double reg,
18393 : ae_state *_state);
18394 : static void vipmsolver_rhssubtract(vipmstate* state,
18395 : vipmrighthandside* rhs,
18396 : vipmvars* v0,
18397 : vipmvars* vdcandidate,
18398 : double reg,
18399 : ae_state *_state);
18400 : static double vipmsolver_rhsprimal2(vipmrighthandside* rhs,
18401 : ae_int_t n,
18402 : ae_int_t m,
18403 : ae_state *_state);
18404 : static double vipmsolver_rhsdual2(vipmrighthandside* rhs,
18405 : ae_int_t n,
18406 : ae_int_t m,
18407 : ae_state *_state);
18408 : static double vipmsolver_rhsprimalinf(vipmrighthandside* rhs,
18409 : ae_int_t n,
18410 : ae_int_t m,
18411 : ae_state *_state);
18412 : static double vipmsolver_rhsdualinf(vipmrighthandside* rhs,
18413 : ae_int_t n,
18414 : ae_int_t m,
18415 : ae_state *_state);
18416 : static double vipmsolver_rhscompl2(vipmrighthandside* rhs,
18417 : ae_int_t n,
18418 : ae_int_t m,
18419 : ae_state *_state);
18420 : static double vipmsolver_minnz(/* Real */ ae_vector* x,
18421 : ae_int_t n,
18422 : ae_state *_state);
18423 : static double vipmsolver_minprodnz(/* Real */ ae_vector* x,
18424 : /* Real */ ae_vector* y,
18425 : ae_int_t n,
18426 : ae_state *_state);
18427 : static double vipmsolver_maxprodnz(/* Real */ ae_vector* x,
18428 : /* Real */ ae_vector* y,
18429 : ae_int_t n,
18430 : ae_state *_state);
18431 :
18432 :
18433 : #endif
18434 : #if defined(AE_COMPILE_NLCSQP) || !defined(AE_PARTIAL_BUILD)
18435 : static double nlcsqp_sqpdeltadecrease = 0.20;
18436 : static double nlcsqp_sqpdeltaincrease = 0.80;
18437 : static double nlcsqp_maxtrustraddecay = 0.1;
18438 : static double nlcsqp_maxtrustradgrowth = 1.333;
18439 : static double nlcsqp_maxbigc = 1.0E5;
18440 : static double nlcsqp_meritfunctionbase = 0.0;
18441 : static double nlcsqp_meritfunctiongain = 2.0;
18442 : static double nlcsqp_augmentationfactor = 10.0;
18443 : static double nlcsqp_inittrustrad = 0.1;
18444 : static double nlcsqp_stagnationepsf = 1.0E-12;
18445 : static ae_int_t nlcsqp_fstagnationlimit = 20;
18446 : static ae_int_t nlcsqp_trustradstagnationlimit = 10;
18447 : static double nlcsqp_sqpbigscale = 5.0;
18448 : static double nlcsqp_sqpsmallscale = 0.2;
18449 : static ae_int_t nlcsqp_penaltymemlen = 5;
18450 : static void nlcsqp_initqpsubsolver(minsqpstate* sstate,
18451 : minsqpsubsolver* subsolver,
18452 : ae_state *_state);
18453 : static void nlcsqp_qpsubsolversetalgoipm(minsqpsubsolver* subsolver,
18454 : ae_state *_state);
18455 : static ae_bool nlcsqp_qpsubproblemupdatehessian(minsqpstate* sstate,
18456 : minsqpsubsolver* subsolver,
18457 : /* Real */ ae_vector* x0,
18458 : /* Real */ ae_vector* g0,
18459 : /* Real */ ae_vector* x1,
18460 : /* Real */ ae_vector* g1,
18461 : ae_state *_state);
18462 : static void nlcsqp_fassolve(minsqpsubsolver* subsolver,
18463 : /* Real */ ae_vector* d0,
18464 : /* Real */ ae_matrix* h,
18465 : ae_int_t nq,
18466 : /* Real */ ae_vector* b,
18467 : ae_int_t n,
18468 : /* Real */ ae_vector* bndl,
18469 : /* Real */ ae_vector* bndu,
18470 : sparsematrix* a,
18471 : ae_int_t m,
18472 : /* Real */ ae_vector* al,
18473 : /* Real */ ae_vector* au,
18474 : double trustrad,
18475 : ae_int_t* terminationtype,
18476 : /* Real */ ae_vector* d,
18477 : /* Real */ ae_vector* lagmult,
18478 : ae_state *_state);
18479 : static ae_bool nlcsqp_qpsubproblemsolve(minsqpstate* state,
18480 : minsqpsubsolver* subsolver,
18481 : /* Real */ ae_vector* x,
18482 : /* Real */ ae_vector* fi,
18483 : /* Real */ ae_matrix* jac,
18484 : /* Real */ ae_vector* d,
18485 : /* Real */ ae_vector* lagmult,
18486 : ae_int_t* terminationtype,
18487 : ae_state *_state);
18488 : static void nlcsqp_meritphaseinit(minsqpmeritphasestate* meritstate,
18489 : /* Real */ ae_vector* curx,
18490 : /* Real */ ae_vector* curfi,
18491 : /* Real */ ae_matrix* curj,
18492 : ae_int_t n,
18493 : ae_int_t nec,
18494 : ae_int_t nic,
18495 : ae_int_t nlec,
18496 : ae_int_t nlic,
18497 : /* Real */ ae_matrix* abslagmemory,
18498 : ae_int_t memlen,
18499 : ae_state *_state);
18500 : static ae_bool nlcsqp_meritphaseiteration(minsqpstate* state,
18501 : minsqpmeritphasestate* meritstate,
18502 : smoothnessmonitor* smonitor,
18503 : ae_bool userterminationneeded,
18504 : ae_state *_state);
18505 : static void nlcsqp_meritphaseresults(minsqpmeritphasestate* meritstate,
18506 : /* Real */ ae_vector* curx,
18507 : /* Real */ ae_vector* curfi,
18508 : /* Real */ ae_matrix* curj,
18509 : /* Real */ ae_vector* lagmult,
18510 : ae_bool* increasebigc,
18511 : ae_int_t* status,
18512 : ae_state *_state);
18513 : static void nlcsqp_sqpsendx(minsqpstate* state,
18514 : /* Real */ ae_vector* xs,
18515 : ae_state *_state);
18516 : static ae_bool nlcsqp_sqpretrievefij(minsqpstate* state,
18517 : /* Real */ ae_vector* fis,
18518 : /* Real */ ae_matrix* js,
18519 : ae_state *_state);
18520 : static void nlcsqp_sqpcopystate(minsqpstate* state,
18521 : /* Real */ ae_vector* x0,
18522 : /* Real */ ae_vector* fi0,
18523 : /* Real */ ae_matrix* j0,
18524 : /* Real */ ae_vector* x1,
18525 : /* Real */ ae_vector* fi1,
18526 : /* Real */ ae_matrix* j1,
18527 : ae_state *_state);
18528 : static void nlcsqp_lagrangianfg(minsqpstate* state,
18529 : /* Real */ ae_vector* x,
18530 : double trustrad,
18531 : /* Real */ ae_vector* fi,
18532 : /* Real */ ae_matrix* j,
18533 : /* Real */ ae_vector* lagmult,
18534 : minsqptmplagrangian* tmp,
18535 : double* f,
18536 : /* Real */ ae_vector* g,
18537 : ae_state *_state);
18538 : static double nlcsqp_meritfunction(minsqpstate* state,
18539 : /* Real */ ae_vector* x,
18540 : /* Real */ ae_vector* fi,
18541 : /* Real */ ae_vector* lagmult,
18542 : /* Real */ ae_vector* penalties,
18543 : minsqptmpmerit* tmp,
18544 : ae_state *_state);
18545 : static double nlcsqp_rawlagrangian(minsqpstate* state,
18546 : /* Real */ ae_vector* x,
18547 : /* Real */ ae_vector* fi,
18548 : /* Real */ ae_vector* lagmult,
18549 : /* Real */ ae_vector* penalties,
18550 : minsqptmpmerit* tmp,
18551 : ae_state *_state);
18552 : static void nlcsqp_meritfunctionandrawlagrangian(minsqpstate* state,
18553 : /* Real */ ae_vector* x,
18554 : /* Real */ ae_vector* fi,
18555 : /* Real */ ae_vector* lagmult,
18556 : /* Real */ ae_vector* penalties,
18557 : minsqptmpmerit* tmp,
18558 : double* meritf,
18559 : double* rawlag,
18560 : ae_state *_state);
18561 :
18562 :
18563 : #endif
18564 : #if defined(AE_COMPILE_QPDENSEAULSOLVER) || !defined(AE_PARTIAL_BUILD)
18565 : static double qpdenseaulsolver_evictionlevel = -0.01;
18566 : static double qpdenseaulsolver_expansionratio = 0.20;
18567 : static void qpdenseaulsolver_generateexmodel(/* Real */ ae_matrix* sclsfta,
18568 : /* Real */ ae_vector* sclsftb,
18569 : ae_int_t nmain,
18570 : /* Real */ ae_vector* sclsftbndl,
18571 : /* Boolean */ ae_vector* sclsfthasbndl,
18572 : /* Real */ ae_vector* sclsftbndu,
18573 : /* Boolean */ ae_vector* sclsfthasbndu,
18574 : /* Real */ ae_matrix* sclsftcleic,
18575 : ae_int_t sclsftnec,
18576 : ae_int_t sclsftnic,
18577 : /* Real */ ae_vector* nulc,
18578 : double rho,
18579 : /* Real */ ae_matrix* exa,
18580 : /* Real */ ae_vector* exb,
18581 : /* Real */ ae_vector* exbndl,
18582 : /* Real */ ae_vector* exbndu,
18583 : /* Real */ ae_matrix* tmp2,
18584 : ae_state *_state);
18585 : static void qpdenseaulsolver_generateexinitialpoint(/* Real */ ae_vector* sclsftxc,
18586 : ae_int_t nmain,
18587 : ae_int_t nslack,
18588 : /* Real */ ae_vector* exxc,
18589 : ae_state *_state);
18590 : static void qpdenseaulsolver_updatelagrangemultipliers(/* Real */ ae_matrix* sclsfta,
18591 : /* Real */ ae_vector* sclsftb,
18592 : ae_int_t nmain,
18593 : /* Real */ ae_vector* sclsftbndl,
18594 : /* Boolean */ ae_vector* sclsfthasbndl,
18595 : /* Real */ ae_vector* sclsftbndu,
18596 : /* Boolean */ ae_vector* sclsfthasbndu,
18597 : /* Real */ ae_matrix* sclsftcleic,
18598 : ae_int_t sclsftnec,
18599 : ae_int_t sclsftnic,
18600 : /* Real */ ae_vector* exxc,
18601 : /* Real */ ae_vector* nulcest,
18602 : qpdenseaulbuffers* buffers,
18603 : ae_state *_state);
18604 : static void qpdenseaulsolver_scaleshiftoriginalproblem(convexquadraticmodel* a,
18605 : sparsematrix* sparsea,
18606 : ae_int_t akind,
18607 : ae_bool sparseaupper,
18608 : /* Real */ ae_vector* b,
18609 : /* Real */ ae_vector* bndl,
18610 : /* Real */ ae_vector* bndu,
18611 : /* Real */ ae_vector* s,
18612 : /* Real */ ae_vector* xorigin,
18613 : ae_int_t nmain,
18614 : /* Real */ ae_matrix* cleic,
18615 : ae_int_t dnec,
18616 : ae_int_t dnic,
18617 : sparsematrix* scleic,
18618 : ae_int_t snec,
18619 : ae_int_t snic,
18620 : ae_bool renormlc,
18621 : qpdenseaulbuffers* state,
18622 : /* Real */ ae_vector* xs,
18623 : ae_state *_state);
18624 : static double qpdenseaulsolver_normalizequadraticterm(/* Real */ ae_matrix* a,
18625 : /* Real */ ae_vector* b,
18626 : ae_int_t n,
18627 : /* Real */ ae_matrix* cleic,
18628 : ae_int_t nec,
18629 : ae_int_t nic,
18630 : ae_bool usecleic,
18631 : /* Real */ ae_matrix* tmp2,
18632 : ae_state *_state);
18633 : static void qpdenseaulsolver_selectinitialworkingset(/* Real */ ae_matrix* a,
18634 : ae_int_t nmain,
18635 : /* Real */ ae_matrix* cleic,
18636 : ae_int_t nec,
18637 : ae_int_t nic,
18638 : /* Real */ ae_vector* tmp0,
18639 : /* Real */ ae_matrix* tmp2,
18640 : ae_int_t* nicwork,
18641 : ae_bool* allowwseviction,
18642 : ae_state *_state);
18643 :
18644 :
18645 : #endif
18646 : #if defined(AE_COMPILE_MINBLEIC) || !defined(AE_PARTIAL_BUILD)
18647 : static double minbleic_gtol = 0.4;
18648 : static double minbleic_maxnonmonotoniclen = 1.0E-7;
18649 : static double minbleic_nmstol = 1.0E2;
18650 : static double minbleic_initialdecay = 0.5;
18651 : static double minbleic_mindecay = 0.1;
18652 : static double minbleic_decaycorrection = 0.8;
18653 : static double minbleic_penaltyfactor = 100;
18654 : static void minbleic_clearrequestfields(minbleicstate* state,
18655 : ae_state *_state);
18656 : static void minbleic_minbleicinitinternal(ae_int_t n,
18657 : /* Real */ ae_vector* x,
18658 : double diffstep,
18659 : minbleicstate* state,
18660 : ae_state *_state);
18661 : static void minbleic_updateestimateofgoodstep(double* estimate,
18662 : double newstep,
18663 : ae_state *_state);
18664 : static double minbleic_feasibilityerror(/* Real */ ae_vector* x,
18665 : /* Real */ ae_vector* s,
18666 : ae_int_t n,
18667 : /* Real */ ae_matrix* cleic,
18668 : ae_int_t nec,
18669 : ae_int_t nic,
18670 : ae_state *_state);
18671 :
18672 :
18673 : #endif
18674 : #if defined(AE_COMPILE_QPBLEICSOLVER) || !defined(AE_PARTIAL_BUILD)
18675 :
18676 :
18677 : #endif
18678 : #if defined(AE_COMPILE_MINQP) || !defined(AE_PARTIAL_BUILD)
18679 :
18680 :
18681 : #endif
18682 : #if defined(AE_COMPILE_LPQPPRESOLVE) || !defined(AE_PARTIAL_BUILD)
18683 :
18684 :
18685 : #endif
18686 : #if defined(AE_COMPILE_REVISEDDUALSIMPLEX) || !defined(AE_PARTIAL_BUILD)
18687 : static ae_int_t reviseddualsimplex_maxforcedrestarts = 1;
18688 : static ae_int_t reviseddualsimplex_safetrfage = 5;
18689 : static ae_int_t reviseddualsimplex_defaultmaxtrfage = 100;
18690 : static double reviseddualsimplex_minbeta = 1.0E-4;
18691 : static double reviseddualsimplex_maxudecay = 0.001;
18692 : static double reviseddualsimplex_shiftlen = 1.0E-12;
18693 : static double reviseddualsimplex_alphatrigger = 1.0E8*ae_machineepsilon;
18694 : static double reviseddualsimplex_alphatrigger2 = 0.001;
18695 : static ae_int_t reviseddualsimplex_ssinvalid = 0;
18696 : static ae_int_t reviseddualsimplex_ssvalidxn = 1;
18697 : static ae_int_t reviseddualsimplex_ssvalid = 2;
18698 : static ae_int_t reviseddualsimplex_ccfixed = 0;
18699 : static ae_int_t reviseddualsimplex_cclower = 1;
18700 : static ae_int_t reviseddualsimplex_ccupper = 2;
18701 : static ae_int_t reviseddualsimplex_ccrange = 3;
18702 : static ae_int_t reviseddualsimplex_ccfree = 4;
18703 : static ae_int_t reviseddualsimplex_ccinfeasible = 5;
18704 : static void reviseddualsimplex_subprobleminit(ae_int_t n,
18705 : dualsimplexsubproblem* s,
18706 : ae_state *_state);
18707 : static void reviseddualsimplex_subprobleminitphase1(dualsimplexsubproblem* s0,
18708 : dualsimplexbasis* basis,
18709 : dualsimplexsubproblem* s1,
18710 : ae_state *_state);
18711 : static void reviseddualsimplex_subprobleminitphase3(dualsimplexsubproblem* s0,
18712 : dualsimplexsubproblem* s1,
18713 : ae_state *_state);
18714 : static void reviseddualsimplex_subprobleminferinitialxn(dualsimplexstate* state,
18715 : dualsimplexsubproblem* s,
18716 : ae_state *_state);
18717 : static void reviseddualsimplex_subproblemhandlexnupdate(dualsimplexstate* state,
18718 : dualsimplexsubproblem* s,
18719 : ae_state *_state);
18720 : static double reviseddualsimplex_initialdualfeasibilitycorrection(dualsimplexstate* state,
18721 : dualsimplexsubproblem* s,
18722 : dualsimplexsettings* settings,
18723 : ae_state *_state);
18724 : static void reviseddualsimplex_shifting(dualsimplexstate* state,
18725 : dualsimplexsubproblem* s,
18726 : dssvector* alphar,
18727 : double delta,
18728 : ae_int_t q,
18729 : double alpharpiv,
18730 : double* thetad,
18731 : dualsimplexsettings* settings,
18732 : ae_state *_state);
18733 : static void reviseddualsimplex_pricingstep(dualsimplexstate* state,
18734 : dualsimplexsubproblem* s,
18735 : ae_bool phase1pricing,
18736 : ae_int_t* p,
18737 : ae_int_t* r,
18738 : double* delta,
18739 : dualsimplexsettings* settings,
18740 : ae_state *_state);
18741 : static void reviseddualsimplex_btranstep(dualsimplexstate* state,
18742 : dualsimplexsubproblem* s,
18743 : ae_int_t r,
18744 : dssvector* rhor,
18745 : dualsimplexsettings* settings,
18746 : ae_state *_state);
18747 : static void reviseddualsimplex_pivotrowstep(dualsimplexstate* state,
18748 : dualsimplexsubproblem* s,
18749 : dssvector* rhor,
18750 : dssvector* alphar,
18751 : dualsimplexsettings* settings,
18752 : ae_state *_state);
18753 : static void reviseddualsimplex_ftranstep(dualsimplexstate* state,
18754 : dualsimplexsubproblem* s,
18755 : dssvector* rhor,
18756 : ae_int_t q,
18757 : /* Real */ ae_vector* alphaq,
18758 : /* Real */ ae_vector* alphaqim,
18759 : /* Real */ ae_vector* tau,
18760 : dualsimplexsettings* settings,
18761 : ae_state *_state);
18762 : static void reviseddualsimplex_ratiotest(dualsimplexstate* state,
18763 : dualsimplexsubproblem* s,
18764 : dssvector* alphar,
18765 : double delta,
18766 : ae_int_t p,
18767 : ae_int_t* q,
18768 : double* alpharpiv,
18769 : double* thetad,
18770 : /* Integer */ ae_vector* possibleflips,
18771 : ae_int_t* possibleflipscnt,
18772 : dualsimplexsettings* settings,
18773 : ae_state *_state);
18774 : static void reviseddualsimplex_updatestep(dualsimplexstate* state,
18775 : dualsimplexsubproblem* s,
18776 : ae_int_t p,
18777 : ae_int_t q,
18778 : ae_int_t r,
18779 : double delta,
18780 : double alphapiv,
18781 : double thetap,
18782 : double thetad,
18783 : /* Real */ ae_vector* alphaq,
18784 : /* Real */ ae_vector* alphaqim,
18785 : dssvector* alphar,
18786 : /* Real */ ae_vector* tau,
18787 : /* Integer */ ae_vector* possiblealpharflips,
18788 : ae_int_t possiblealpharflipscnt,
18789 : dualsimplexsettings* settings,
18790 : ae_state *_state);
18791 : static ae_bool reviseddualsimplex_refactorizationrequired(dualsimplexstate* state,
18792 : dualsimplexsubproblem* s,
18793 : ae_int_t q,
18794 : double alpharpiv,
18795 : ae_int_t r,
18796 : double alphaqpiv,
18797 : ae_state *_state);
18798 : static void reviseddualsimplex_cacheboundinfo(dualsimplexsubproblem* s,
18799 : ae_int_t i,
18800 : ae_int_t k,
18801 : dualsimplexsettings* settings,
18802 : ae_state *_state);
18803 : static void reviseddualsimplex_solvesubproblemdual(dualsimplexstate* state,
18804 : dualsimplexsubproblem* s,
18805 : ae_bool isphase1,
18806 : dualsimplexsettings* settings,
18807 : ae_int_t* info,
18808 : ae_state *_state);
18809 : static void reviseddualsimplex_solvesubproblemprimal(dualsimplexstate* state,
18810 : dualsimplexsubproblem* s,
18811 : dualsimplexsettings* settings,
18812 : ae_int_t* info,
18813 : ae_state *_state);
18814 : static void reviseddualsimplex_invokephase1(dualsimplexstate* state,
18815 : dualsimplexsettings* settings,
18816 : ae_state *_state);
18817 : static void reviseddualsimplex_dssoptimizewrk(dualsimplexstate* state,
18818 : dualsimplexsettings* settings,
18819 : ae_state *_state);
18820 : static void reviseddualsimplex_solveboxonly(dualsimplexstate* state,
18821 : ae_state *_state);
18822 : static void reviseddualsimplex_setzeroxystats(dualsimplexstate* state,
18823 : ae_state *_state);
18824 : static void reviseddualsimplex_basisinit(ae_int_t ns,
18825 : ae_int_t m,
18826 : dualsimplexbasis* s,
18827 : ae_state *_state);
18828 : static void reviseddualsimplex_basisclearstats(dualsimplexbasis* s,
18829 : ae_state *_state);
18830 : static ae_bool reviseddualsimplex_basistryresize(dualsimplexbasis* s,
18831 : ae_int_t newm,
18832 : sparsematrix* at,
18833 : dualsimplexsettings* settings,
18834 : ae_state *_state);
18835 : static double reviseddualsimplex_basisminimumdiagonalelement(dualsimplexbasis* s,
18836 : ae_state *_state);
18837 : static void reviseddualsimplex_basisexportto(dualsimplexbasis* s0,
18838 : dualsimplexbasis* s1,
18839 : ae_state *_state);
18840 : static ae_bool reviseddualsimplex_basistryimportfrom(dualsimplexbasis* s0,
18841 : dualsimplexbasis* s1,
18842 : sparsematrix* at,
18843 : dualsimplexsettings* settings,
18844 : ae_state *_state);
18845 : static void reviseddualsimplex_basisfreshtrf(dualsimplexbasis* s,
18846 : sparsematrix* at,
18847 : dualsimplexsettings* settings,
18848 : ae_state *_state);
18849 : static double reviseddualsimplex_basisfreshtrfunsafe(dualsimplexbasis* s,
18850 : sparsematrix* at,
18851 : dualsimplexsettings* settings,
18852 : ae_state *_state);
18853 : static void reviseddualsimplex_basisrequestweights(dualsimplexbasis* s,
18854 : dualsimplexsettings* settings,
18855 : ae_state *_state);
18856 : static void reviseddualsimplex_basisupdatetrf(dualsimplexbasis* s,
18857 : sparsematrix* at,
18858 : ae_int_t p,
18859 : ae_int_t q,
18860 : /* Real */ ae_vector* alphaq,
18861 : /* Real */ ae_vector* alphaqim,
18862 : ae_int_t r,
18863 : /* Real */ ae_vector* tau,
18864 : dualsimplexsettings* settings,
18865 : ae_state *_state);
18866 : static void reviseddualsimplex_basissolve(dualsimplexbasis* s,
18867 : /* Real */ ae_vector* r,
18868 : /* Real */ ae_vector* x,
18869 : /* Real */ ae_vector* tmpx,
18870 : ae_state *_state);
18871 : static void reviseddualsimplex_basissolvex(dualsimplexbasis* s,
18872 : /* Real */ ae_vector* r,
18873 : /* Real */ ae_vector* x,
18874 : /* Real */ ae_vector* xim,
18875 : ae_bool needintermediate,
18876 : /* Real */ ae_vector* tx,
18877 : ae_state *_state);
18878 : static void reviseddualsimplex_basissolvet(dualsimplexbasis* s,
18879 : /* Real */ ae_vector* r,
18880 : /* Real */ ae_vector* x,
18881 : /* Real */ ae_vector* tx,
18882 : ae_state *_state);
18883 : static void reviseddualsimplex_computeanxn(dualsimplexstate* state,
18884 : dualsimplexsubproblem* subproblem,
18885 : /* Real */ ae_vector* x,
18886 : /* Real */ ae_vector* y,
18887 : ae_state *_state);
18888 : static void reviseddualsimplex_computeantv(dualsimplexstate* state,
18889 : /* Real */ ae_vector* y,
18890 : /* Real */ ae_vector* r,
18891 : ae_state *_state);
18892 : static ae_bool reviseddualsimplex_hasbndl(dualsimplexsubproblem* subproblem,
18893 : ae_int_t i,
18894 : ae_state *_state);
18895 : static ae_bool reviseddualsimplex_hasbndu(dualsimplexsubproblem* subproblem,
18896 : ae_int_t i,
18897 : ae_state *_state);
18898 : static ae_bool reviseddualsimplex_isfree(dualsimplexsubproblem* subproblem,
18899 : ae_int_t i,
18900 : ae_state *_state);
18901 : static void reviseddualsimplex_downgradestate(dualsimplexsubproblem* subproblem,
18902 : ae_int_t s,
18903 : ae_state *_state);
18904 : static double reviseddualsimplex_dualfeasibilityerror(dualsimplexstate* state,
18905 : dualsimplexsubproblem* s,
18906 : ae_state *_state);
18907 : static ae_bool reviseddualsimplex_isdualfeasible(dualsimplexstate* state,
18908 : dualsimplexsubproblem* s,
18909 : dualsimplexsettings* settings,
18910 : ae_state *_state);
18911 : static void reviseddualsimplex_pivottobwd(/* Integer */ ae_vector* p,
18912 : ae_int_t m,
18913 : /* Integer */ ae_vector* bwd,
18914 : ae_state *_state);
18915 : static void reviseddualsimplex_inversecyclicpermutation(/* Integer */ ae_vector* bwd,
18916 : ae_int_t m,
18917 : ae_int_t d,
18918 : /* Integer */ ae_vector* tmpi,
18919 : ae_state *_state);
18920 : static void reviseddualsimplex_offloadbasiccomponents(dualsimplexsubproblem* s,
18921 : dualsimplexbasis* basis,
18922 : dualsimplexsettings* settings,
18923 : ae_state *_state);
18924 : static void reviseddualsimplex_recombinebasicnonbasicx(dualsimplexsubproblem* s,
18925 : dualsimplexbasis* basis,
18926 : ae_state *_state);
18927 : static void reviseddualsimplex_setxydstats(dualsimplexstate* state,
18928 : dualsimplexsubproblem* s,
18929 : dualsimplexbasis* basis,
18930 : apbuffers* buffers,
18931 : /* Real */ ae_vector* x,
18932 : /* Real */ ae_vector* lagbc,
18933 : /* Real */ ae_vector* laglc,
18934 : /* Integer */ ae_vector* stats,
18935 : ae_state *_state);
18936 : static void reviseddualsimplex_dvalloc(dssvector* x,
18937 : ae_int_t n,
18938 : ae_state *_state);
18939 : static void reviseddualsimplex_dvinit(dssvector* x,
18940 : ae_int_t n,
18941 : ae_state *_state);
18942 : static void reviseddualsimplex_dvdensetosparse(dssvector* x,
18943 : ae_state *_state);
18944 : static void reviseddualsimplex_dvsparsetodense(dssvector* x,
18945 : ae_state *_state);
18946 : static double reviseddualsimplex_sparsityof(/* Real */ ae_vector* x,
18947 : ae_int_t n,
18948 : ae_state *_state);
18949 : static void reviseddualsimplex_updateavgcounter(double v,
18950 : double* acc,
18951 : ae_int_t* cnt,
18952 : ae_state *_state);
18953 :
18954 :
18955 : #endif
18956 : #if defined(AE_COMPILE_MINLP) || !defined(AE_PARTIAL_BUILD)
18957 : static ae_int_t minlp_alllogicalsbasis = 0;
18958 : static void minlp_clearreportfields(minlpstate* state, ae_state *_state);
18959 :
18960 :
18961 : #endif
18962 : #if defined(AE_COMPILE_NLCSLP) || !defined(AE_PARTIAL_BUILD)
18963 : static double nlcslp_slpstpclosetozero = 0.001;
18964 : static double nlcslp_slpdeltadecrease = 0.20;
18965 : static double nlcslp_slpdeltaincrease = 0.80;
18966 : static double nlcslp_slpstpclosetoone = 0.95;
18967 : static double nlcslp_maxtrustraddecay = 0.1;
18968 : static double nlcslp_maxtrustradgrowth = 1.333;
18969 : static double nlcslp_slpgtol = 0.4;
18970 : static double nlcslp_bigc = 500.0;
18971 : static double nlcslp_bfgstol = 1.0E-5;
18972 : static double nlcslp_meritfunctionbase = 0.0;
18973 : static double nlcslp_meritfunctiongain = 2.0;
18974 : static double nlcslp_inequalitydampingfactor = 10.0;
18975 : static double nlcslp_augmentationfactor = 10.0;
18976 : static double nlcslp_inittrustrad = 0.1;
18977 : static double nlcslp_stagnationepsf = 1.0E-12;
18978 : static ae_int_t nlcslp_lpfailureslimit = 20;
18979 : static ae_int_t nlcslp_fstagnationlimit = 20;
18980 : static ae_int_t nlcslp_nondescentlimit = 99999;
18981 : static ae_int_t nlcslp_nonmonotonicphase2limit = 5;
18982 : static double nlcslp_slpbigscale = 5.0;
18983 : static double nlcslp_slpsmallscale = 0.2;
18984 : static void nlcslp_initlpsubsolver(minslpstate* sstate,
18985 : minslpsubsolver* subsolver,
18986 : ae_int_t hessiantype,
18987 : ae_state *_state);
18988 : static void nlcslp_lpsubproblemrestart(minslpstate* sstate,
18989 : minslpsubsolver* subsolver,
18990 : ae_state *_state);
18991 : static void nlcslp_lpsubproblemupdatehessian(minslpstate* sstate,
18992 : minslpsubsolver* subsolver,
18993 : /* Real */ ae_vector* x0,
18994 : /* Real */ ae_vector* g0,
18995 : /* Real */ ae_vector* x1,
18996 : /* Real */ ae_vector* g1,
18997 : ae_state *_state);
18998 : static ae_bool nlcslp_lpsubproblemsolve(minslpstate* state,
18999 : minslpsubsolver* subsolver,
19000 : /* Real */ ae_vector* x,
19001 : /* Real */ ae_vector* fi,
19002 : /* Real */ ae_matrix* jac,
19003 : ae_int_t innerk,
19004 : /* Real */ ae_vector* d,
19005 : /* Real */ ae_vector* lagmult,
19006 : ae_state *_state);
19007 : static void nlcslp_lpsubproblemappendconjugacyconstraint(minslpstate* state,
19008 : minslpsubsolver* subsolver,
19009 : /* Real */ ae_vector* d,
19010 : ae_state *_state);
19011 : static void nlcslp_phase13init(minslpphase13state* state13,
19012 : ae_int_t n,
19013 : ae_int_t nec,
19014 : ae_int_t nic,
19015 : ae_int_t nlec,
19016 : ae_int_t nlic,
19017 : ae_bool usecorrection,
19018 : ae_state *_state);
19019 : static ae_bool nlcslp_phase13iteration(minslpstate* state,
19020 : minslpphase13state* state13,
19021 : smoothnessmonitor* smonitor,
19022 : ae_bool userterminationneeded,
19023 : /* Real */ ae_vector* curx,
19024 : /* Real */ ae_vector* curfi,
19025 : /* Real */ ae_matrix* curj,
19026 : /* Real */ ae_vector* lagmult,
19027 : ae_int_t* status,
19028 : double* stp,
19029 : ae_state *_state);
19030 : static void nlcslp_phase2init(minslpphase2state* state2,
19031 : ae_int_t n,
19032 : ae_int_t nec,
19033 : ae_int_t nic,
19034 : ae_int_t nlec,
19035 : ae_int_t nlic,
19036 : /* Real */ ae_vector* meritlagmult,
19037 : ae_state *_state);
19038 : static ae_bool nlcslp_phase2iteration(minslpstate* state,
19039 : minslpphase2state* state2,
19040 : smoothnessmonitor* smonitor,
19041 : ae_bool userterminationneeded,
19042 : /* Real */ ae_vector* curx,
19043 : /* Real */ ae_vector* curfi,
19044 : /* Real */ ae_matrix* curj,
19045 : /* Real */ ae_vector* lagmult,
19046 : double* gammamax,
19047 : ae_int_t* status,
19048 : ae_state *_state);
19049 : static void nlcslp_slpsendx(minslpstate* state,
19050 : /* Real */ ae_vector* xs,
19051 : ae_state *_state);
19052 : static ae_bool nlcslp_slpretrievefij(minslpstate* state,
19053 : /* Real */ ae_vector* fis,
19054 : /* Real */ ae_matrix* js,
19055 : ae_state *_state);
19056 : static void nlcslp_slpcopystate(minslpstate* state,
19057 : /* Real */ ae_vector* x0,
19058 : /* Real */ ae_vector* fi0,
19059 : /* Real */ ae_matrix* j0,
19060 : /* Real */ ae_vector* x1,
19061 : /* Real */ ae_vector* fi1,
19062 : /* Real */ ae_matrix* j1,
19063 : ae_state *_state);
19064 : static void nlcslp_lagrangianfg(minslpstate* state,
19065 : /* Real */ ae_vector* x,
19066 : double trustrad,
19067 : /* Real */ ae_vector* fi,
19068 : /* Real */ ae_matrix* j,
19069 : /* Real */ ae_vector* lagmult,
19070 : minslptmplagrangian* tmp,
19071 : double* f,
19072 : /* Real */ ae_vector* g,
19073 : double* lcerr,
19074 : ae_int_t* lcidx,
19075 : double* nlcerr,
19076 : ae_int_t* nlcidx,
19077 : ae_state *_state);
19078 : static double nlcslp_meritfunction(minslpstate* state,
19079 : /* Real */ ae_vector* x,
19080 : /* Real */ ae_vector* fi,
19081 : /* Real */ ae_vector* lagmult,
19082 : minslptmpmerit* tmp,
19083 : ae_state *_state);
19084 : static double nlcslp_rawlagrangian(minslpstate* state,
19085 : /* Real */ ae_vector* x,
19086 : /* Real */ ae_vector* fi,
19087 : /* Real */ ae_vector* lagmult,
19088 : minslptmpmerit* tmp,
19089 : ae_state *_state);
19090 : static void nlcslp_meritfunctionandrawlagrangian(minslpstate* state,
19091 : /* Real */ ae_vector* x,
19092 : /* Real */ ae_vector* fi,
19093 : /* Real */ ae_vector* lagmult,
19094 : minslptmpmerit* tmp,
19095 : double* meritf,
19096 : double* rawlag,
19097 : ae_state *_state);
19098 :
19099 :
19100 : #endif
19101 : #if defined(AE_COMPILE_MINNLC) || !defined(AE_PARTIAL_BUILD)
19102 : static double minnlc_aulmaxgrowth = 10.0;
19103 : static double minnlc_maxlagmult = 1.0E7;
19104 : static ae_int_t minnlc_lbfgsfactor = 10;
19105 : static double minnlc_hessesttol = 1.0E-6;
19106 : static double minnlc_initgamma = 1.0E-6;
19107 : static double minnlc_regprec = 1.0E-6;
19108 : static void minnlc_clearrequestfields(minnlcstate* state,
19109 : ae_state *_state);
19110 : static void minnlc_minnlcinitinternal(ae_int_t n,
19111 : /* Real */ ae_vector* x,
19112 : double diffstep,
19113 : minnlcstate* state,
19114 : ae_state *_state);
19115 : static void minnlc_clearpreconditioner(minlbfgsstate* auloptimizer,
19116 : ae_state *_state);
19117 : static void minnlc_updatepreconditioner(ae_int_t prectype,
19118 : ae_int_t updatefreq,
19119 : ae_int_t* preccounter,
19120 : minlbfgsstate* auloptimizer,
19121 : /* Real */ ae_vector* x,
19122 : double rho,
19123 : double gammak,
19124 : /* Real */ ae_vector* bndl,
19125 : /* Boolean */ ae_vector* hasbndl,
19126 : /* Real */ ae_vector* bndu,
19127 : /* Boolean */ ae_vector* hasbndu,
19128 : /* Real */ ae_vector* nubc,
19129 : /* Real */ ae_matrix* cleic,
19130 : /* Real */ ae_vector* nulc,
19131 : /* Real */ ae_vector* fi,
19132 : /* Real */ ae_matrix* jac,
19133 : /* Real */ ae_vector* nunlc,
19134 : /* Real */ ae_vector* bufd,
19135 : /* Real */ ae_vector* bufc,
19136 : /* Real */ ae_matrix* bufw,
19137 : /* Real */ ae_matrix* bufz,
19138 : /* Real */ ae_vector* tmp0,
19139 : ae_int_t n,
19140 : ae_int_t nec,
19141 : ae_int_t nic,
19142 : ae_int_t ng,
19143 : ae_int_t nh,
19144 : ae_state *_state);
19145 : static void minnlc_penaltybc(/* Real */ ae_vector* x,
19146 : /* Real */ ae_vector* bndl,
19147 : /* Boolean */ ae_vector* hasbndl,
19148 : /* Real */ ae_vector* bndu,
19149 : /* Boolean */ ae_vector* hasbndu,
19150 : /* Real */ ae_vector* nubc,
19151 : ae_int_t n,
19152 : double rho,
19153 : double stabilizingpoint,
19154 : double* f,
19155 : /* Real */ ae_vector* g,
19156 : ae_state *_state);
19157 : static void minnlc_penaltylc(/* Real */ ae_vector* x,
19158 : /* Real */ ae_matrix* cleic,
19159 : /* Real */ ae_vector* nulc,
19160 : ae_int_t n,
19161 : ae_int_t nec,
19162 : ae_int_t nic,
19163 : double rho,
19164 : double stabilizingpoint,
19165 : double* f,
19166 : /* Real */ ae_vector* g,
19167 : ae_state *_state);
19168 : static void minnlc_penaltynlc(/* Real */ ae_vector* fi,
19169 : /* Real */ ae_matrix* j,
19170 : /* Real */ ae_vector* nunlc,
19171 : ae_int_t n,
19172 : ae_int_t ng,
19173 : ae_int_t nh,
19174 : double rho,
19175 : double stabilizingpoint,
19176 : double* f,
19177 : /* Real */ ae_vector* g,
19178 : ae_state *_state);
19179 : static ae_bool minnlc_auliteration(minnlcstate* state,
19180 : smoothnessmonitor* smonitor,
19181 : ae_state *_state);
19182 : static void minnlc_unscale(minnlcstate* state,
19183 : /* Real */ ae_vector* xs,
19184 : /* Real */ ae_vector* scaledbndl,
19185 : /* Real */ ae_vector* scaledbndu,
19186 : /* Real */ ae_vector* xu,
19187 : ae_state *_state);
19188 :
19189 :
19190 : #endif
19191 : #if defined(AE_COMPILE_MINBC) || !defined(AE_PARTIAL_BUILD)
19192 : static double minbc_gtol = 0.4;
19193 : static double minbc_maxnonmonotoniclen = 1.0E-5;
19194 : static double minbc_initialdecay = 0.5;
19195 : static double minbc_mindecay = 0.1;
19196 : static double minbc_decaycorrection = 0.8;
19197 : static void minbc_clearrequestfields(minbcstate* state, ae_state *_state);
19198 : static void minbc_minbcinitinternal(ae_int_t n,
19199 : /* Real */ ae_vector* x,
19200 : double diffstep,
19201 : minbcstate* state,
19202 : ae_state *_state);
19203 : static void minbc_updateestimateofgoodstep(double* estimate,
19204 : double newstep,
19205 : ae_state *_state);
19206 :
19207 :
19208 : #endif
19209 : #if defined(AE_COMPILE_MINNS) || !defined(AE_PARTIAL_BUILD)
19210 : static void minns_clearrequestfields(minnsstate* state, ae_state *_state);
19211 : static void minns_minnsinitinternal(ae_int_t n,
19212 : /* Real */ ae_vector* x,
19213 : double diffstep,
19214 : minnsstate* state,
19215 : ae_state *_state);
19216 : static ae_bool minns_agsiteration(minnsstate* state, ae_state *_state);
19217 : static void minns_generatemeritfunction(minnsstate* state,
19218 : ae_int_t sampleidx,
19219 : ae_state *_state);
19220 : static void minns_unscalepointbc(minnsstate* state,
19221 : /* Real */ ae_vector* x,
19222 : ae_state *_state);
19223 : static void minns_solveqp(/* Real */ ae_matrix* sampleg,
19224 : /* Real */ ae_vector* diagh,
19225 : ae_int_t nsample,
19226 : ae_int_t nvars,
19227 : /* Real */ ae_vector* coeffs,
19228 : ae_int_t* dbgncholesky,
19229 : minnsqp* state,
19230 : ae_state *_state);
19231 : static void minns_qpcalculategradfunc(/* Real */ ae_matrix* sampleg,
19232 : /* Real */ ae_vector* diagh,
19233 : ae_int_t nsample,
19234 : ae_int_t nvars,
19235 : /* Real */ ae_vector* coeffs,
19236 : /* Real */ ae_vector* g,
19237 : double* f,
19238 : /* Real */ ae_vector* tmp,
19239 : ae_state *_state);
19240 : static void minns_qpcalculatefunc(/* Real */ ae_matrix* sampleg,
19241 : /* Real */ ae_vector* diagh,
19242 : ae_int_t nsample,
19243 : ae_int_t nvars,
19244 : /* Real */ ae_vector* coeffs,
19245 : double* f,
19246 : /* Real */ ae_vector* tmp,
19247 : ae_state *_state);
19248 : static void minns_qpsolveu(/* Real */ ae_matrix* a,
19249 : ae_int_t n,
19250 : /* Real */ ae_vector* x,
19251 : ae_state *_state);
19252 : static void minns_qpsolveut(/* Real */ ae_matrix* a,
19253 : ae_int_t n,
19254 : /* Real */ ae_vector* x,
19255 : ae_state *_state);
19256 :
19257 :
19258 : #endif
19259 : #if defined(AE_COMPILE_MINCOMP) || !defined(AE_PARTIAL_BUILD)
19260 : static ae_int_t mincomp_n1 = 2;
19261 : static ae_int_t mincomp_n2 = 2;
19262 : static double mincomp_stpmin = 1.0E-300;
19263 : static double mincomp_gtol = 0.3;
19264 : static double mincomp_gpaftol = 0.0001;
19265 : static double mincomp_gpadecay = 0.5;
19266 : static double mincomp_asarho = 0.5;
19267 : static double mincomp_asaboundedantigradnorm(minasastate* state,
19268 : ae_state *_state);
19269 : static double mincomp_asaginorm(minasastate* state, ae_state *_state);
19270 : static double mincomp_asad1norm(minasastate* state, ae_state *_state);
19271 : static ae_bool mincomp_asauisempty(minasastate* state, ae_state *_state);
19272 : static void mincomp_clearrequestfields(minasastate* state,
19273 : ae_state *_state);
19274 :
19275 :
19276 : #endif
19277 : #if defined(AE_COMPILE_MINCG) || !defined(AE_PARTIAL_BUILD)
19278 : static ae_int_t mincg_rscountdownlen = 10;
19279 : static double mincg_gtol = 0.3;
19280 : static void mincg_clearrequestfields(mincgstate* state, ae_state *_state);
19281 : static void mincg_preconditionedmultiply(mincgstate* state,
19282 : /* Real */ ae_vector* x,
19283 : /* Real */ ae_vector* work0,
19284 : /* Real */ ae_vector* work1,
19285 : ae_state *_state);
19286 : static double mincg_preconditionedmultiply2(mincgstate* state,
19287 : /* Real */ ae_vector* x,
19288 : /* Real */ ae_vector* y,
19289 : /* Real */ ae_vector* work0,
19290 : /* Real */ ae_vector* work1,
19291 : ae_state *_state);
19292 : static void mincg_mincginitinternal(ae_int_t n,
19293 : double diffstep,
19294 : mincgstate* state,
19295 : ae_state *_state);
19296 :
19297 :
19298 : #endif
19299 : #if defined(AE_COMPILE_MINLM) || !defined(AE_PARTIAL_BUILD)
19300 : static double minlm_lambdaup = 2.0;
19301 : static double minlm_lambdadown = 0.33;
19302 : static double minlm_suspiciousnu = 16;
19303 : static ae_int_t minlm_smallmodelage = 3;
19304 : static ae_int_t minlm_additers = 5;
19305 : static void minlm_lmprepare(ae_int_t n,
19306 : ae_int_t m,
19307 : ae_bool havegrad,
19308 : minlmstate* state,
19309 : ae_state *_state);
19310 : static void minlm_clearrequestfields(minlmstate* state, ae_state *_state);
19311 : static ae_bool minlm_increaselambda(double* lambdav,
19312 : double* nu,
19313 : ae_state *_state);
19314 : static void minlm_decreaselambda(double* lambdav,
19315 : double* nu,
19316 : ae_state *_state);
19317 : static ae_int_t minlm_checkdecrease(/* Real */ ae_matrix* quadraticmodel,
19318 : /* Real */ ae_vector* gbase,
19319 : double fbase,
19320 : ae_int_t n,
19321 : /* Real */ ae_vector* deltax,
19322 : double fnew,
19323 : double* lambdav,
19324 : double* nu,
19325 : ae_state *_state);
19326 : static ae_bool minlm_minlmstepfinderinit(minlmstepfinder* state,
19327 : ae_int_t n,
19328 : ae_int_t m,
19329 : ae_int_t maxmodelage,
19330 : ae_bool hasfi,
19331 : /* Real */ ae_vector* xbase,
19332 : /* Real */ ae_vector* bndl,
19333 : /* Real */ ae_vector* bndu,
19334 : /* Real */ ae_matrix* cleic,
19335 : ae_int_t nec,
19336 : ae_int_t nic,
19337 : /* Real */ ae_vector* s,
19338 : double stpmax,
19339 : double epsx,
19340 : ae_state *_state);
19341 : static void minlm_minlmstepfinderstart(minlmstepfinder* state,
19342 : /* Real */ ae_matrix* quadraticmodel,
19343 : /* Real */ ae_vector* gbase,
19344 : double fbase,
19345 : /* Real */ ae_vector* xbase,
19346 : /* Real */ ae_vector* fibase,
19347 : ae_int_t modelage,
19348 : ae_state *_state);
19349 : static ae_bool minlm_minlmstepfinderiteration(minlmstepfinder* state,
19350 : double* lambdav,
19351 : double* nu,
19352 : /* Real */ ae_vector* xnew,
19353 : /* Real */ ae_vector* deltax,
19354 : ae_bool* deltaxready,
19355 : /* Real */ ae_vector* deltaf,
19356 : ae_bool* deltafready,
19357 : ae_int_t* iflag,
19358 : double* fnew,
19359 : ae_int_t* ncholesky,
19360 : ae_state *_state);
19361 :
19362 :
19363 : #endif
19364 :
19365 : #if defined(AE_COMPILE_CQMODELS) || !defined(AE_PARTIAL_BUILD)
19366 :
19367 :
19368 : /*************************************************************************
19369 : This subroutine is used to initialize CQM. By default, empty NxN model is
19370 : generated, with Alpha=Lambda=Theta=0.0 and zero b.
19371 :
19372 : Previously allocated buffer variables are reused as much as possible.
19373 :
19374 : -- ALGLIB --
19375 : Copyright 12.06.2012 by Bochkanov Sergey
19376 : *************************************************************************/
19377 0 : void cqminit(ae_int_t n, convexquadraticmodel* s, ae_state *_state)
19378 : {
19379 : ae_int_t i;
19380 :
19381 :
19382 0 : s->n = n;
19383 0 : s->k = 0;
19384 0 : s->nfree = n;
19385 0 : s->ecakind = -1;
19386 0 : s->alpha = 0.0;
19387 0 : s->tau = 0.0;
19388 0 : s->theta = 0.0;
19389 0 : s->ismaintermchanged = ae_true;
19390 0 : s->issecondarytermchanged = ae_true;
19391 0 : s->islineartermchanged = ae_true;
19392 0 : s->isactivesetchanged = ae_true;
19393 0 : bvectorsetlengthatleast(&s->activeset, n, _state);
19394 0 : rvectorsetlengthatleast(&s->xc, n, _state);
19395 0 : rvectorsetlengthatleast(&s->eb, n, _state);
19396 0 : rvectorsetlengthatleast(&s->tq1, n, _state);
19397 0 : rvectorsetlengthatleast(&s->txc, n, _state);
19398 0 : rvectorsetlengthatleast(&s->tb, n, _state);
19399 0 : rvectorsetlengthatleast(&s->b, s->n, _state);
19400 0 : rvectorsetlengthatleast(&s->tk1, s->n, _state);
19401 0 : for(i=0; i<=n-1; i++)
19402 : {
19403 0 : s->activeset.ptr.p_bool[i] = ae_false;
19404 0 : s->xc.ptr.p_double[i] = 0.0;
19405 0 : s->b.ptr.p_double[i] = 0.0;
19406 : }
19407 0 : }
19408 :
19409 :
19410 : /*************************************************************************
19411 : This subroutine changes main quadratic term of the model.
19412 :
19413 : INPUT PARAMETERS:
19414 : S - model
19415 : A - NxN matrix, only upper or lower triangle is referenced
19416 : IsUpper - True, when matrix is stored in upper triangle
19417 : Alpha - multiplier; when Alpha=0, A is not referenced at all
19418 :
19419 : -- ALGLIB --
19420 : Copyright 12.06.2012 by Bochkanov Sergey
19421 : *************************************************************************/
19422 0 : void cqmseta(convexquadraticmodel* s,
19423 : /* Real */ ae_matrix* a,
19424 : ae_bool isupper,
19425 : double alpha,
19426 : ae_state *_state)
19427 : {
19428 : ae_int_t i;
19429 : ae_int_t j;
19430 : double v;
19431 :
19432 :
19433 0 : ae_assert(ae_isfinite(alpha, _state)&&ae_fp_greater_eq(alpha,(double)(0)), "CQMSetA: Alpha<0 or is not finite number", _state);
19434 0 : ae_assert(ae_fp_eq(alpha,(double)(0))||isfinitertrmatrix(a, s->n, isupper, _state), "CQMSetA: A is not finite NxN matrix", _state);
19435 0 : s->alpha = alpha;
19436 0 : if( ae_fp_greater(alpha,(double)(0)) )
19437 : {
19438 0 : rmatrixsetlengthatleast(&s->a, s->n, s->n, _state);
19439 0 : rmatrixsetlengthatleast(&s->ecadense, s->n, s->n, _state);
19440 0 : rmatrixsetlengthatleast(&s->tq2dense, s->n, s->n, _state);
19441 0 : for(i=0; i<=s->n-1; i++)
19442 : {
19443 0 : for(j=i; j<=s->n-1; j++)
19444 : {
19445 0 : if( isupper )
19446 : {
19447 0 : v = a->ptr.pp_double[i][j];
19448 : }
19449 : else
19450 : {
19451 0 : v = a->ptr.pp_double[j][i];
19452 : }
19453 0 : s->a.ptr.pp_double[i][j] = v;
19454 0 : s->a.ptr.pp_double[j][i] = v;
19455 : }
19456 : }
19457 : }
19458 0 : s->ismaintermchanged = ae_true;
19459 0 : }
19460 :
19461 :
19462 : /*************************************************************************
19463 : This subroutine changes main quadratic term of the model.
19464 :
19465 : INPUT PARAMETERS:
19466 : S - model
19467 : A - possibly preallocated buffer
19468 :
19469 : OUTPUT PARAMETERS:
19470 : A - NxN matrix, full matrix is returned.
19471 : Zero matrix is returned if model is empty.
19472 :
19473 : -- ALGLIB --
19474 : Copyright 12.06.2012 by Bochkanov Sergey
19475 : *************************************************************************/
19476 0 : void cqmgeta(convexquadraticmodel* s,
19477 : /* Real */ ae_matrix* a,
19478 : ae_state *_state)
19479 : {
19480 : ae_int_t i;
19481 : ae_int_t j;
19482 : double v;
19483 : ae_int_t n;
19484 :
19485 :
19486 0 : n = s->n;
19487 0 : rmatrixsetlengthatleast(a, n, n, _state);
19488 0 : if( ae_fp_greater(s->alpha,(double)(0)) )
19489 : {
19490 0 : v = s->alpha;
19491 0 : for(i=0; i<=n-1; i++)
19492 : {
19493 0 : for(j=0; j<=n-1; j++)
19494 : {
19495 0 : a->ptr.pp_double[i][j] = v*s->a.ptr.pp_double[i][j];
19496 : }
19497 : }
19498 : }
19499 : else
19500 : {
19501 0 : for(i=0; i<=n-1; i++)
19502 : {
19503 0 : for(j=0; j<=n-1; j++)
19504 : {
19505 0 : a->ptr.pp_double[i][j] = 0.0;
19506 : }
19507 : }
19508 : }
19509 0 : }
19510 :
19511 :
19512 : /*************************************************************************
19513 : This subroutine rewrites diagonal of the main quadratic term of the model
19514 : (dense A) by vector Z/Alpha (current value of the Alpha coefficient is
19515 : used).
19516 :
19517 : IMPORTANT: in case model has no dense quadratic term, this function
19518 : allocates N*N dense matrix of zeros, and fills its diagonal by
19519 : non-zero values.
19520 :
19521 : INPUT PARAMETERS:
19522 : S - model
19523 : Z - new diagonal, array[N]
19524 :
19525 : -- ALGLIB --
19526 : Copyright 12.06.2012 by Bochkanov Sergey
19527 : *************************************************************************/
19528 0 : void cqmrewritedensediagonal(convexquadraticmodel* s,
19529 : /* Real */ ae_vector* z,
19530 : ae_state *_state)
19531 : {
19532 : ae_int_t n;
19533 : ae_int_t i;
19534 : ae_int_t j;
19535 :
19536 :
19537 0 : n = s->n;
19538 0 : if( ae_fp_eq(s->alpha,(double)(0)) )
19539 : {
19540 0 : rmatrixsetlengthatleast(&s->a, s->n, s->n, _state);
19541 0 : rmatrixsetlengthatleast(&s->ecadense, s->n, s->n, _state);
19542 0 : rmatrixsetlengthatleast(&s->tq2dense, s->n, s->n, _state);
19543 0 : for(i=0; i<=n-1; i++)
19544 : {
19545 0 : for(j=0; j<=n-1; j++)
19546 : {
19547 0 : s->a.ptr.pp_double[i][j] = 0.0;
19548 : }
19549 : }
19550 0 : s->alpha = 1.0;
19551 : }
19552 0 : for(i=0; i<=s->n-1; i++)
19553 : {
19554 0 : s->a.ptr.pp_double[i][i] = z->ptr.p_double[i]/s->alpha;
19555 : }
19556 0 : s->ismaintermchanged = ae_true;
19557 0 : }
19558 :
19559 :
19560 : /*************************************************************************
19561 : This subroutine changes diagonal quadratic term of the model.
19562 :
19563 : INPUT PARAMETERS:
19564 : S - model
19565 : D - array[N], semidefinite diagonal matrix
19566 : Tau - multiplier; when Tau=0, D is not referenced at all
19567 :
19568 : -- ALGLIB --
19569 : Copyright 12.06.2012 by Bochkanov Sergey
19570 : *************************************************************************/
19571 0 : void cqmsetd(convexquadraticmodel* s,
19572 : /* Real */ ae_vector* d,
19573 : double tau,
19574 : ae_state *_state)
19575 : {
19576 : ae_int_t i;
19577 :
19578 :
19579 0 : ae_assert(ae_isfinite(tau, _state)&&ae_fp_greater_eq(tau,(double)(0)), "CQMSetD: Tau<0 or is not finite number", _state);
19580 0 : ae_assert(ae_fp_eq(tau,(double)(0))||isfinitevector(d, s->n, _state), "CQMSetD: D is not finite Nx1 vector", _state);
19581 0 : s->tau = tau;
19582 0 : if( ae_fp_greater(tau,(double)(0)) )
19583 : {
19584 0 : rvectorsetlengthatleast(&s->d, s->n, _state);
19585 0 : rvectorsetlengthatleast(&s->ecadiag, s->n, _state);
19586 0 : rvectorsetlengthatleast(&s->tq2diag, s->n, _state);
19587 0 : for(i=0; i<=s->n-1; i++)
19588 : {
19589 0 : ae_assert(ae_fp_greater_eq(d->ptr.p_double[i],(double)(0)), "CQMSetD: D[i]<0", _state);
19590 0 : s->d.ptr.p_double[i] = d->ptr.p_double[i];
19591 : }
19592 : }
19593 0 : s->ismaintermchanged = ae_true;
19594 0 : }
19595 :
19596 :
19597 : /*************************************************************************
19598 : This subroutine drops main quadratic term A from the model. It is same as
19599 : call to CQMSetA() with zero A, but gives better performance because
19600 : algorithm knows that matrix is zero and can optimize subsequent
19601 : calculations.
19602 :
19603 : INPUT PARAMETERS:
19604 : S - model
19605 :
19606 : -- ALGLIB --
19607 : Copyright 12.06.2012 by Bochkanov Sergey
19608 : *************************************************************************/
19609 0 : void cqmdropa(convexquadraticmodel* s, ae_state *_state)
19610 : {
19611 :
19612 :
19613 0 : s->alpha = 0.0;
19614 0 : s->ismaintermchanged = ae_true;
19615 0 : }
19616 :
19617 :
19618 : /*************************************************************************
19619 : This subroutine changes linear term of the model
19620 :
19621 : -- ALGLIB --
19622 : Copyright 12.06.2012 by Bochkanov Sergey
19623 : *************************************************************************/
19624 0 : void cqmsetb(convexquadraticmodel* s,
19625 : /* Real */ ae_vector* b,
19626 : ae_state *_state)
19627 : {
19628 : ae_int_t i;
19629 :
19630 :
19631 0 : ae_assert(isfinitevector(b, s->n, _state), "CQMSetB: B is not finite vector", _state);
19632 0 : rvectorsetlengthatleast(&s->b, s->n, _state);
19633 0 : for(i=0; i<=s->n-1; i++)
19634 : {
19635 0 : s->b.ptr.p_double[i] = b->ptr.p_double[i];
19636 : }
19637 0 : s->islineartermchanged = ae_true;
19638 0 : }
19639 :
19640 :
19641 : /*************************************************************************
19642 : This subroutine changes linear term of the model
19643 :
19644 : -- ALGLIB --
19645 : Copyright 12.06.2012 by Bochkanov Sergey
19646 : *************************************************************************/
19647 0 : void cqmsetq(convexquadraticmodel* s,
19648 : /* Real */ ae_matrix* q,
19649 : /* Real */ ae_vector* r,
19650 : ae_int_t k,
19651 : double theta,
19652 : ae_state *_state)
19653 : {
19654 : ae_int_t i;
19655 : ae_int_t j;
19656 :
19657 :
19658 0 : ae_assert(k>=0, "CQMSetQ: K<0", _state);
19659 0 : ae_assert((k==0||ae_fp_eq(theta,(double)(0)))||apservisfinitematrix(q, k, s->n, _state), "CQMSetQ: Q is not finite matrix", _state);
19660 0 : ae_assert((k==0||ae_fp_eq(theta,(double)(0)))||isfinitevector(r, k, _state), "CQMSetQ: R is not finite vector", _state);
19661 0 : ae_assert(ae_isfinite(theta, _state)&&ae_fp_greater_eq(theta,(double)(0)), "CQMSetQ: Theta<0 or is not finite number", _state);
19662 :
19663 : /*
19664 : * degenerate case: K=0 or Theta=0
19665 : */
19666 0 : if( k==0||ae_fp_eq(theta,(double)(0)) )
19667 : {
19668 0 : s->k = 0;
19669 0 : s->theta = (double)(0);
19670 0 : s->issecondarytermchanged = ae_true;
19671 0 : return;
19672 : }
19673 :
19674 : /*
19675 : * General case: both Theta>0 and K>0
19676 : */
19677 0 : s->k = k;
19678 0 : s->theta = theta;
19679 0 : rmatrixsetlengthatleast(&s->q, s->k, s->n, _state);
19680 0 : rvectorsetlengthatleast(&s->r, s->k, _state);
19681 0 : rmatrixsetlengthatleast(&s->eq, s->k, s->n, _state);
19682 0 : rmatrixsetlengthatleast(&s->eccm, s->k, s->k, _state);
19683 0 : rmatrixsetlengthatleast(&s->tk2, s->k, s->n, _state);
19684 0 : for(i=0; i<=s->k-1; i++)
19685 : {
19686 0 : for(j=0; j<=s->n-1; j++)
19687 : {
19688 0 : s->q.ptr.pp_double[i][j] = q->ptr.pp_double[i][j];
19689 : }
19690 0 : s->r.ptr.p_double[i] = r->ptr.p_double[i];
19691 : }
19692 0 : s->issecondarytermchanged = ae_true;
19693 : }
19694 :
19695 :
19696 : /*************************************************************************
19697 : This subroutine changes active set
19698 :
19699 : INPUT PARAMETERS
19700 : S - model
19701 : X - array[N], constraint values
19702 : ActiveSet- array[N], active set. If ActiveSet[I]=True, then I-th
19703 : variables is constrained to X[I].
19704 :
19705 : -- ALGLIB --
19706 : Copyright 12.06.2012 by Bochkanov Sergey
19707 : *************************************************************************/
19708 0 : void cqmsetactiveset(convexquadraticmodel* s,
19709 : /* Real */ ae_vector* x,
19710 : /* Boolean */ ae_vector* activeset,
19711 : ae_state *_state)
19712 : {
19713 : ae_int_t i;
19714 :
19715 :
19716 0 : ae_assert(x->cnt>=s->n, "CQMSetActiveSet: Length(X)<N", _state);
19717 0 : ae_assert(activeset->cnt>=s->n, "CQMSetActiveSet: Length(ActiveSet)<N", _state);
19718 0 : for(i=0; i<=s->n-1; i++)
19719 : {
19720 0 : s->isactivesetchanged = s->isactivesetchanged||(s->activeset.ptr.p_bool[i]&&!activeset->ptr.p_bool[i]);
19721 0 : s->isactivesetchanged = s->isactivesetchanged||(activeset->ptr.p_bool[i]&&!s->activeset.ptr.p_bool[i]);
19722 0 : s->activeset.ptr.p_bool[i] = activeset->ptr.p_bool[i];
19723 0 : if( activeset->ptr.p_bool[i] )
19724 : {
19725 0 : ae_assert(ae_isfinite(x->ptr.p_double[i], _state), "CQMSetActiveSet: X[] contains infinite constraints", _state);
19726 0 : s->isactivesetchanged = s->isactivesetchanged||ae_fp_neq(s->xc.ptr.p_double[i],x->ptr.p_double[i]);
19727 0 : s->xc.ptr.p_double[i] = x->ptr.p_double[i];
19728 : }
19729 : }
19730 0 : }
19731 :
19732 :
19733 : /*************************************************************************
19734 : This subroutine evaluates model at X. Active constraints are ignored.
19735 :
19736 : -- ALGLIB --
19737 : Copyright 12.06.2012 by Bochkanov Sergey
19738 : *************************************************************************/
19739 0 : double cqmeval(convexquadraticmodel* s,
19740 : /* Real */ ae_vector* x,
19741 : ae_state *_state)
19742 : {
19743 : ae_int_t n;
19744 : ae_int_t i;
19745 : ae_int_t j;
19746 : double v;
19747 : double result;
19748 :
19749 :
19750 0 : n = s->n;
19751 0 : ae_assert(isfinitevector(x, n, _state), "CQMEval: X is not finite vector", _state);
19752 0 : result = 0.0;
19753 :
19754 : /*
19755 : * main quadratic term
19756 : */
19757 0 : if( ae_fp_greater(s->alpha,(double)(0)) )
19758 : {
19759 0 : for(i=0; i<=n-1; i++)
19760 : {
19761 0 : for(j=0; j<=n-1; j++)
19762 : {
19763 0 : result = result+s->alpha*0.5*x->ptr.p_double[i]*s->a.ptr.pp_double[i][j]*x->ptr.p_double[j];
19764 : }
19765 : }
19766 : }
19767 0 : if( ae_fp_greater(s->tau,(double)(0)) )
19768 : {
19769 0 : for(i=0; i<=n-1; i++)
19770 : {
19771 0 : result = result+0.5*ae_sqr(x->ptr.p_double[i], _state)*s->tau*s->d.ptr.p_double[i];
19772 : }
19773 : }
19774 :
19775 : /*
19776 : * secondary quadratic term
19777 : */
19778 0 : if( ae_fp_greater(s->theta,(double)(0)) )
19779 : {
19780 0 : for(i=0; i<=s->k-1; i++)
19781 : {
19782 0 : v = ae_v_dotproduct(&s->q.ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
19783 0 : result = result+0.5*s->theta*ae_sqr(v-s->r.ptr.p_double[i], _state);
19784 : }
19785 : }
19786 :
19787 : /*
19788 : * linear term
19789 : */
19790 0 : for(i=0; i<=s->n-1; i++)
19791 : {
19792 0 : result = result+x->ptr.p_double[i]*s->b.ptr.p_double[i];
19793 : }
19794 0 : return result;
19795 : }
19796 :
19797 :
19798 : /*************************************************************************
19799 : This subroutine evaluates model at X. Active constraints are ignored.
19800 : It returns:
19801 : R - model value
19802 : Noise- estimate of the numerical noise in data
19803 :
19804 : -- ALGLIB --
19805 : Copyright 12.06.2012 by Bochkanov Sergey
19806 : *************************************************************************/
19807 0 : void cqmevalx(convexquadraticmodel* s,
19808 : /* Real */ ae_vector* x,
19809 : double* r,
19810 : double* noise,
19811 : ae_state *_state)
19812 : {
19813 : ae_int_t n;
19814 : ae_int_t i;
19815 : ae_int_t j;
19816 : double v;
19817 : double v2;
19818 : double mxq;
19819 : double eps;
19820 :
19821 0 : *r = 0;
19822 0 : *noise = 0;
19823 :
19824 0 : n = s->n;
19825 0 : ae_assert(isfinitevector(x, n, _state), "CQMEval: X is not finite vector", _state);
19826 0 : *r = 0.0;
19827 0 : *noise = 0.0;
19828 0 : eps = 2*ae_machineepsilon;
19829 0 : mxq = 0.0;
19830 :
19831 : /*
19832 : * Main quadratic term.
19833 : *
19834 : * Noise from the main quadratic term is equal to the
19835 : * maximum summand in the term.
19836 : */
19837 0 : if( ae_fp_greater(s->alpha,(double)(0)) )
19838 : {
19839 0 : for(i=0; i<=n-1; i++)
19840 : {
19841 0 : for(j=0; j<=n-1; j++)
19842 : {
19843 0 : v = s->alpha*0.5*x->ptr.p_double[i]*s->a.ptr.pp_double[i][j]*x->ptr.p_double[j];
19844 0 : *r = *r+v;
19845 0 : *noise = ae_maxreal(*noise, eps*ae_fabs(v, _state), _state);
19846 : }
19847 : }
19848 : }
19849 0 : if( ae_fp_greater(s->tau,(double)(0)) )
19850 : {
19851 0 : for(i=0; i<=n-1; i++)
19852 : {
19853 0 : v = 0.5*ae_sqr(x->ptr.p_double[i], _state)*s->tau*s->d.ptr.p_double[i];
19854 0 : *r = *r+v;
19855 0 : *noise = ae_maxreal(*noise, eps*ae_fabs(v, _state), _state);
19856 : }
19857 : }
19858 :
19859 : /*
19860 : * secondary quadratic term
19861 : *
19862 : * Noise from the secondary quadratic term is estimated as follows:
19863 : * * noise in qi*x-r[i] is estimated as
19864 : * Eps*MXQ = Eps*max(|r[i]|, |q[i,j]*x[j]|)
19865 : * * noise in (qi*x-r[i])^2 is estimated as
19866 : * NOISE = (|qi*x-r[i]|+Eps*MXQ)^2-(|qi*x-r[i]|)^2
19867 : * = Eps*MXQ*(2*|qi*x-r[i]|+Eps*MXQ)
19868 : */
19869 0 : if( ae_fp_greater(s->theta,(double)(0)) )
19870 : {
19871 0 : for(i=0; i<=s->k-1; i++)
19872 : {
19873 0 : v = 0.0;
19874 0 : mxq = ae_fabs(s->r.ptr.p_double[i], _state);
19875 0 : for(j=0; j<=n-1; j++)
19876 : {
19877 0 : v2 = s->q.ptr.pp_double[i][j]*x->ptr.p_double[j];
19878 0 : v = v+v2;
19879 0 : mxq = ae_maxreal(mxq, ae_fabs(v2, _state), _state);
19880 : }
19881 0 : *r = *r+0.5*s->theta*ae_sqr(v-s->r.ptr.p_double[i], _state);
19882 0 : *noise = ae_maxreal(*noise, eps*mxq*(2*ae_fabs(v-s->r.ptr.p_double[i], _state)+eps*mxq), _state);
19883 : }
19884 : }
19885 :
19886 : /*
19887 : * linear term
19888 : */
19889 0 : for(i=0; i<=s->n-1; i++)
19890 : {
19891 0 : *r = *r+x->ptr.p_double[i]*s->b.ptr.p_double[i];
19892 0 : *noise = ae_maxreal(*noise, eps*ae_fabs(x->ptr.p_double[i]*s->b.ptr.p_double[i], _state), _state);
19893 : }
19894 :
19895 : /*
19896 : * Final update of the noise
19897 : */
19898 0 : *noise = n*(*noise);
19899 0 : }
19900 :
19901 :
19902 : /*************************************************************************
19903 : This subroutine evaluates gradient of the model; active constraints are
19904 : ignored.
19905 :
19906 : INPUT PARAMETERS:
19907 : S - convex model
19908 : X - point, array[N]
19909 : G - possibly preallocated buffer; resized, if too small
19910 :
19911 : -- ALGLIB --
19912 : Copyright 12.06.2012 by Bochkanov Sergey
19913 : *************************************************************************/
19914 0 : void cqmgradunconstrained(convexquadraticmodel* s,
19915 : /* Real */ ae_vector* x,
19916 : /* Real */ ae_vector* g,
19917 : ae_state *_state)
19918 : {
19919 : ae_int_t n;
19920 : ae_int_t i;
19921 : ae_int_t j;
19922 : double v;
19923 :
19924 :
19925 0 : n = s->n;
19926 0 : ae_assert(isfinitevector(x, n, _state), "CQMEvalGradUnconstrained: X is not finite vector", _state);
19927 0 : rvectorsetlengthatleast(g, n, _state);
19928 0 : for(i=0; i<=n-1; i++)
19929 : {
19930 0 : g->ptr.p_double[i] = (double)(0);
19931 : }
19932 :
19933 : /*
19934 : * main quadratic term
19935 : */
19936 0 : if( ae_fp_greater(s->alpha,(double)(0)) )
19937 : {
19938 0 : for(i=0; i<=n-1; i++)
19939 : {
19940 0 : v = 0.0;
19941 0 : for(j=0; j<=n-1; j++)
19942 : {
19943 0 : v = v+s->alpha*s->a.ptr.pp_double[i][j]*x->ptr.p_double[j];
19944 : }
19945 0 : g->ptr.p_double[i] = g->ptr.p_double[i]+v;
19946 : }
19947 : }
19948 0 : if( ae_fp_greater(s->tau,(double)(0)) )
19949 : {
19950 0 : for(i=0; i<=n-1; i++)
19951 : {
19952 0 : g->ptr.p_double[i] = g->ptr.p_double[i]+x->ptr.p_double[i]*s->tau*s->d.ptr.p_double[i];
19953 : }
19954 : }
19955 :
19956 : /*
19957 : * secondary quadratic term
19958 : */
19959 0 : if( ae_fp_greater(s->theta,(double)(0)) )
19960 : {
19961 0 : for(i=0; i<=s->k-1; i++)
19962 : {
19963 0 : v = ae_v_dotproduct(&s->q.ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
19964 0 : v = s->theta*(v-s->r.ptr.p_double[i]);
19965 0 : ae_v_addd(&g->ptr.p_double[0], 1, &s->q.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v);
19966 : }
19967 : }
19968 :
19969 : /*
19970 : * linear term
19971 : */
19972 0 : for(i=0; i<=n-1; i++)
19973 : {
19974 0 : g->ptr.p_double[i] = g->ptr.p_double[i]+s->b.ptr.p_double[i];
19975 : }
19976 0 : }
19977 :
19978 :
19979 : /*************************************************************************
19980 : This subroutine evaluates x'*(0.5*alpha*A+tau*D)*x
19981 :
19982 : NOTE: Tmp[] must be preallocated array whose length is at least N
19983 :
19984 : -- ALGLIB --
19985 : Copyright 12.06.2012 by Bochkanov Sergey
19986 : *************************************************************************/
19987 0 : double cqmxtadx2(convexquadraticmodel* s,
19988 : /* Real */ ae_vector* x,
19989 : /* Real */ ae_vector* tmp,
19990 : ae_state *_state)
19991 : {
19992 : ae_int_t n;
19993 : ae_int_t i;
19994 : double result;
19995 :
19996 :
19997 0 : n = s->n;
19998 0 : ae_assert(isfinitevector(x, n, _state), "CQMXTADX2: X is not finite vector", _state);
19999 0 : ae_assert(tmp->cnt>=n, "CQMXTADX2: Length(Tmp)<N", _state);
20000 0 : result = 0.0;
20001 :
20002 : /*
20003 : * main quadratic term
20004 : */
20005 0 : if( ae_fp_greater(s->alpha,(double)(0)) )
20006 : {
20007 0 : result = result+s->alpha*0.5*rmatrixsyvmv(n, &s->a, 0, 0, ae_true, x, 0, tmp, _state);
20008 : }
20009 0 : if( ae_fp_greater(s->tau,(double)(0)) )
20010 : {
20011 0 : for(i=0; i<=n-1; i++)
20012 : {
20013 0 : result = result+0.5*ae_sqr(x->ptr.p_double[i], _state)*s->tau*s->d.ptr.p_double[i];
20014 : }
20015 : }
20016 0 : return result;
20017 : }
20018 :
20019 :
20020 : /*************************************************************************
20021 : This subroutine evaluates (0.5*alpha*A+tau*D)*x
20022 :
20023 : Y is automatically resized if needed
20024 :
20025 : -- ALGLIB --
20026 : Copyright 12.06.2012 by Bochkanov Sergey
20027 : *************************************************************************/
20028 0 : void cqmadx(convexquadraticmodel* s,
20029 : /* Real */ ae_vector* x,
20030 : /* Real */ ae_vector* y,
20031 : ae_state *_state)
20032 : {
20033 : ae_int_t n;
20034 : ae_int_t i;
20035 :
20036 :
20037 0 : n = s->n;
20038 0 : ae_assert(isfinitevector(x, n, _state), "CQMEval: X is not finite vector", _state);
20039 0 : rvectorsetlengthatleast(y, n, _state);
20040 :
20041 : /*
20042 : * main quadratic term
20043 : */
20044 0 : for(i=0; i<=n-1; i++)
20045 : {
20046 0 : y->ptr.p_double[i] = (double)(0);
20047 : }
20048 0 : if( ae_fp_greater(s->alpha,(double)(0)) )
20049 : {
20050 0 : rmatrixsymv(n, s->alpha, &s->a, 0, 0, ae_true, x, 0, 1.0, y, 0, _state);
20051 : }
20052 0 : if( ae_fp_greater(s->tau,(double)(0)) )
20053 : {
20054 0 : for(i=0; i<=n-1; i++)
20055 : {
20056 0 : y->ptr.p_double[i] = y->ptr.p_double[i]+x->ptr.p_double[i]*s->tau*s->d.ptr.p_double[i];
20057 : }
20058 : }
20059 0 : }
20060 :
20061 :
20062 : /*************************************************************************
20063 : This subroutine finds optimum of the model. It returns False on failure
20064 : (indefinite/semidefinite matrix). Optimum is found subject to active
20065 : constraints.
20066 :
20067 : INPUT PARAMETERS
20068 : S - model
20069 : X - possibly preallocated buffer; automatically resized, if
20070 : too small enough.
20071 :
20072 : -- ALGLIB --
20073 : Copyright 12.06.2012 by Bochkanov Sergey
20074 : *************************************************************************/
20075 0 : ae_bool cqmconstrainedoptimum(convexquadraticmodel* s,
20076 : /* Real */ ae_vector* x,
20077 : ae_state *_state)
20078 : {
20079 : ae_int_t n;
20080 : ae_int_t nfree;
20081 : ae_int_t k;
20082 : ae_int_t i;
20083 : double v;
20084 : ae_int_t cidx0;
20085 : ae_int_t itidx;
20086 : ae_bool result;
20087 :
20088 :
20089 :
20090 : /*
20091 : * Rebuild internal structures
20092 : */
20093 0 : if( !cqmodels_cqmrebuild(s, _state) )
20094 : {
20095 0 : result = ae_false;
20096 0 : return result;
20097 : }
20098 0 : n = s->n;
20099 0 : k = s->k;
20100 0 : nfree = s->nfree;
20101 0 : result = ae_true;
20102 :
20103 : /*
20104 : * Calculate initial point for the iterative refinement:
20105 : * * free components are set to zero
20106 : * * constrained components are set to their constrained values
20107 : */
20108 0 : rvectorsetlengthatleast(x, n, _state);
20109 0 : for(i=0; i<=n-1; i++)
20110 : {
20111 0 : if( s->activeset.ptr.p_bool[i] )
20112 : {
20113 0 : x->ptr.p_double[i] = s->xc.ptr.p_double[i];
20114 : }
20115 : else
20116 : {
20117 0 : x->ptr.p_double[i] = (double)(0);
20118 : }
20119 : }
20120 :
20121 : /*
20122 : * Iterative refinement.
20123 : *
20124 : * In an ideal world without numerical errors it would be enough
20125 : * to make just one Newton step from initial point:
20126 : * x_new = -H^(-1)*grad(x=0)
20127 : * However, roundoff errors can significantly deteriorate quality
20128 : * of the solution. So we have to recalculate gradient and to
20129 : * perform Newton steps several times.
20130 : *
20131 : * Below we perform fixed number of Newton iterations.
20132 : */
20133 0 : for(itidx=0; itidx<=cqmodels_newtonrefinementits-1; itidx++)
20134 : {
20135 :
20136 : /*
20137 : * Calculate gradient at the current point.
20138 : * Move free components of the gradient in the beginning.
20139 : */
20140 0 : cqmgradunconstrained(s, x, &s->tmpg, _state);
20141 0 : cidx0 = 0;
20142 0 : for(i=0; i<=n-1; i++)
20143 : {
20144 0 : if( !s->activeset.ptr.p_bool[i] )
20145 : {
20146 0 : s->tmpg.ptr.p_double[cidx0] = s->tmpg.ptr.p_double[i];
20147 0 : cidx0 = cidx0+1;
20148 : }
20149 : }
20150 :
20151 : /*
20152 : * Free components of the extrema are calculated in the first NFree elements of TXC.
20153 : *
20154 : * First, we have to calculate original Newton step, without rank-K perturbations
20155 : */
20156 0 : ae_v_moveneg(&s->txc.ptr.p_double[0], 1, &s->tmpg.ptr.p_double[0], 1, ae_v_len(0,nfree-1));
20157 0 : cqmodels_cqmsolveea(s, &s->txc, &s->tmp0, _state);
20158 :
20159 : /*
20160 : * Then, we account for rank-K correction.
20161 : * Woodbury matrix identity is used.
20162 : */
20163 0 : if( s->k>0&&ae_fp_greater(s->theta,(double)(0)) )
20164 : {
20165 0 : rvectorsetlengthatleast(&s->tmp0, ae_maxint(nfree, k, _state), _state);
20166 0 : rvectorsetlengthatleast(&s->tmp1, ae_maxint(nfree, k, _state), _state);
20167 0 : ae_v_moveneg(&s->tmp1.ptr.p_double[0], 1, &s->tmpg.ptr.p_double[0], 1, ae_v_len(0,nfree-1));
20168 0 : cqmodels_cqmsolveea(s, &s->tmp1, &s->tmp0, _state);
20169 0 : for(i=0; i<=k-1; i++)
20170 : {
20171 0 : 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));
20172 0 : s->tmp0.ptr.p_double[i] = v;
20173 : }
20174 0 : fblscholeskysolve(&s->eccm, 1.0, k, ae_true, &s->tmp0, &s->tmp1, _state);
20175 0 : for(i=0; i<=nfree-1; i++)
20176 : {
20177 0 : s->tmp1.ptr.p_double[i] = 0.0;
20178 : }
20179 0 : for(i=0; i<=k-1; i++)
20180 : {
20181 0 : v = s->tmp0.ptr.p_double[i];
20182 0 : 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);
20183 : }
20184 0 : cqmodels_cqmsolveea(s, &s->tmp1, &s->tmp0, _state);
20185 0 : ae_v_sub(&s->txc.ptr.p_double[0], 1, &s->tmp1.ptr.p_double[0], 1, ae_v_len(0,nfree-1));
20186 : }
20187 :
20188 : /*
20189 : * Unpack components from TXC into X. We pass through all
20190 : * free components of X and add our step.
20191 : */
20192 0 : cidx0 = 0;
20193 0 : for(i=0; i<=n-1; i++)
20194 : {
20195 0 : if( !s->activeset.ptr.p_bool[i] )
20196 : {
20197 0 : x->ptr.p_double[i] = x->ptr.p_double[i]+s->txc.ptr.p_double[cidx0];
20198 0 : cidx0 = cidx0+1;
20199 : }
20200 : }
20201 : }
20202 0 : return result;
20203 : }
20204 :
20205 :
20206 : /*************************************************************************
20207 : This function scales vector by multiplying it by inverse of the diagonal
20208 : of the Hessian matrix. It should be used to accelerate steepest descent
20209 : phase of the QP solver.
20210 :
20211 : Although it is called "scale-grad", it can be called for any vector,
20212 : whether it is gradient, anti-gradient, or just some vector.
20213 :
20214 : This function does NOT takes into account current set of constraints, it
20215 : just performs matrix-vector multiplication without taking into account
20216 : constraints.
20217 :
20218 : INPUT PARAMETERS:
20219 : S - model
20220 : X - vector to scale
20221 :
20222 : OUTPUT PARAMETERS:
20223 : X - scaled vector
20224 :
20225 : NOTE:
20226 : when called for non-SPD matrices, it silently skips components of X
20227 : which correspond to zero or negative diagonal elements.
20228 :
20229 : NOTE:
20230 : this function uses diagonals of A and D; it ignores Q - rank-K term of
20231 : the quadratic model.
20232 :
20233 : -- ALGLIB --
20234 : Copyright 12.06.2012 by Bochkanov Sergey
20235 : *************************************************************************/
20236 0 : void cqmscalevector(convexquadraticmodel* s,
20237 : /* Real */ ae_vector* x,
20238 : ae_state *_state)
20239 : {
20240 : ae_int_t n;
20241 : ae_int_t i;
20242 : double v;
20243 :
20244 :
20245 0 : n = s->n;
20246 0 : for(i=0; i<=n-1; i++)
20247 : {
20248 0 : v = 0.0;
20249 0 : if( ae_fp_greater(s->alpha,(double)(0)) )
20250 : {
20251 0 : v = v+s->a.ptr.pp_double[i][i];
20252 : }
20253 0 : if( ae_fp_greater(s->tau,(double)(0)) )
20254 : {
20255 0 : v = v+s->d.ptr.p_double[i];
20256 : }
20257 0 : if( ae_fp_greater(v,(double)(0)) )
20258 : {
20259 0 : x->ptr.p_double[i] = x->ptr.p_double[i]/v;
20260 : }
20261 : }
20262 0 : }
20263 :
20264 :
20265 : /*************************************************************************
20266 : This function returns diagonal of the A-term.
20267 :
20268 : INPUT PARAMETERS:
20269 : S - model
20270 :
20271 : OUTPUT PARAMETERS:
20272 : D - diagonal of the A (or zero)
20273 :
20274 : -- ALGLIB --
20275 : Copyright 26.12.2017 by Bochkanov Sergey
20276 : *************************************************************************/
20277 0 : void cqmgetdiaga(convexquadraticmodel* s,
20278 : /* Real */ ae_vector* x,
20279 : ae_state *_state)
20280 : {
20281 : ae_int_t n;
20282 : ae_int_t i;
20283 :
20284 :
20285 0 : n = s->n;
20286 0 : rvectorsetlengthatleast(x, n, _state);
20287 0 : for(i=0; i<=n-1; i++)
20288 : {
20289 0 : if( ae_fp_greater(s->alpha,(double)(0)) )
20290 : {
20291 0 : x->ptr.p_double[i] = s->a.ptr.pp_double[i][i];
20292 : }
20293 : else
20294 : {
20295 0 : x->ptr.p_double[i] = (double)(0);
20296 : }
20297 : }
20298 0 : }
20299 :
20300 :
20301 : /*************************************************************************
20302 : This subroutine calls CQMRebuild() and evaluates model at X subject to
20303 : active constraints.
20304 :
20305 : It is intended for debug purposes only, because it evaluates model by
20306 : means of temporaries, which were calculated by CQMRebuild(). The only
20307 : purpose of this function is to check correctness of CQMRebuild() by
20308 : comparing results of this function with ones obtained by CQMEval(), which
20309 : is used as reference point. The idea is that significant deviation in
20310 : results of these two functions is evidence of some error in the
20311 : CQMRebuild().
20312 :
20313 : NOTE: suffix T denotes that temporaries marked by T-prefix are used. There
20314 : is one more variant of this function, which uses "effective" model
20315 : built by CQMRebuild().
20316 :
20317 : NOTE2: in case CQMRebuild() fails (due to model non-convexity), this
20318 : function returns NAN.
20319 :
20320 : -- ALGLIB --
20321 : Copyright 12.06.2012 by Bochkanov Sergey
20322 : *************************************************************************/
20323 0 : double cqmdebugconstrainedevalt(convexquadraticmodel* s,
20324 : /* Real */ ae_vector* x,
20325 : ae_state *_state)
20326 : {
20327 : ae_int_t n;
20328 : ae_int_t nfree;
20329 : ae_int_t i;
20330 : ae_int_t j;
20331 : double v;
20332 : double result;
20333 :
20334 :
20335 0 : n = s->n;
20336 0 : ae_assert(isfinitevector(x, n, _state), "CQMDebugConstrainedEvalT: X is not finite vector", _state);
20337 0 : if( !cqmodels_cqmrebuild(s, _state) )
20338 : {
20339 0 : result = _state->v_nan;
20340 0 : return result;
20341 : }
20342 0 : result = 0.0;
20343 0 : nfree = s->nfree;
20344 :
20345 : /*
20346 : * Reorder variables
20347 : */
20348 0 : j = 0;
20349 0 : for(i=0; i<=n-1; i++)
20350 : {
20351 0 : if( !s->activeset.ptr.p_bool[i] )
20352 : {
20353 0 : ae_assert(j<nfree, "CQMDebugConstrainedEvalT: internal error", _state);
20354 0 : s->txc.ptr.p_double[j] = x->ptr.p_double[i];
20355 0 : j = j+1;
20356 : }
20357 : }
20358 :
20359 : /*
20360 : * TQ2, TQ1, TQ0
20361 : *
20362 : */
20363 0 : if( ae_fp_greater(s->alpha,(double)(0)) )
20364 : {
20365 :
20366 : /*
20367 : * Dense TQ2
20368 : */
20369 0 : for(i=0; i<=nfree-1; i++)
20370 : {
20371 0 : for(j=0; j<=nfree-1; j++)
20372 : {
20373 0 : result = result+0.5*s->txc.ptr.p_double[i]*s->tq2dense.ptr.pp_double[i][j]*s->txc.ptr.p_double[j];
20374 : }
20375 : }
20376 : }
20377 : else
20378 : {
20379 :
20380 : /*
20381 : * Diagonal TQ2
20382 : */
20383 0 : for(i=0; i<=nfree-1; i++)
20384 : {
20385 0 : result = result+0.5*s->tq2diag.ptr.p_double[i]*ae_sqr(s->txc.ptr.p_double[i], _state);
20386 : }
20387 : }
20388 0 : for(i=0; i<=nfree-1; i++)
20389 : {
20390 0 : result = result+s->tq1.ptr.p_double[i]*s->txc.ptr.p_double[i];
20391 : }
20392 0 : result = result+s->tq0;
20393 :
20394 : /*
20395 : * TK2, TK1, TK0
20396 : */
20397 0 : if( s->k>0&&ae_fp_greater(s->theta,(double)(0)) )
20398 : {
20399 0 : for(i=0; i<=s->k-1; i++)
20400 : {
20401 0 : v = (double)(0);
20402 0 : for(j=0; j<=nfree-1; j++)
20403 : {
20404 0 : v = v+s->tk2.ptr.pp_double[i][j]*s->txc.ptr.p_double[j];
20405 : }
20406 0 : result = result+0.5*ae_sqr(v, _state);
20407 : }
20408 0 : for(i=0; i<=nfree-1; i++)
20409 : {
20410 0 : result = result+s->tk1.ptr.p_double[i]*s->txc.ptr.p_double[i];
20411 : }
20412 0 : result = result+s->tk0;
20413 : }
20414 :
20415 : /*
20416 : * TB (Bf and Bc parts)
20417 : */
20418 0 : for(i=0; i<=n-1; i++)
20419 : {
20420 0 : result = result+s->tb.ptr.p_double[i]*s->txc.ptr.p_double[i];
20421 : }
20422 0 : return result;
20423 : }
20424 :
20425 :
20426 : /*************************************************************************
20427 : This subroutine calls CQMRebuild() and evaluates model at X subject to
20428 : active constraints.
20429 :
20430 : It is intended for debug purposes only, because it evaluates model by
20431 : means of "effective" matrices built by CQMRebuild(). The only purpose of
20432 : this function is to check correctness of CQMRebuild() by comparing results
20433 : of this function with ones obtained by CQMEval(), which is used as
20434 : reference point. The idea is that significant deviation in results of
20435 : these two functions is evidence of some error in the CQMRebuild().
20436 :
20437 : NOTE: suffix E denotes that effective matrices. There is one more variant
20438 : of this function, which uses temporary matrices built by
20439 : CQMRebuild().
20440 :
20441 : NOTE2: in case CQMRebuild() fails (due to model non-convexity), this
20442 : function returns NAN.
20443 :
20444 : -- ALGLIB --
20445 : Copyright 12.06.2012 by Bochkanov Sergey
20446 : *************************************************************************/
20447 0 : double cqmdebugconstrainedevale(convexquadraticmodel* s,
20448 : /* Real */ ae_vector* x,
20449 : ae_state *_state)
20450 : {
20451 : ae_int_t n;
20452 : ae_int_t nfree;
20453 : ae_int_t i;
20454 : ae_int_t j;
20455 : double v;
20456 : double result;
20457 :
20458 :
20459 0 : n = s->n;
20460 0 : ae_assert(isfinitevector(x, n, _state), "CQMDebugConstrainedEvalE: X is not finite vector", _state);
20461 0 : if( !cqmodels_cqmrebuild(s, _state) )
20462 : {
20463 0 : result = _state->v_nan;
20464 0 : return result;
20465 : }
20466 0 : result = 0.0;
20467 0 : nfree = s->nfree;
20468 :
20469 : /*
20470 : * Reorder variables
20471 : */
20472 0 : j = 0;
20473 0 : for(i=0; i<=n-1; i++)
20474 : {
20475 0 : if( !s->activeset.ptr.p_bool[i] )
20476 : {
20477 0 : ae_assert(j<nfree, "CQMDebugConstrainedEvalE: internal error", _state);
20478 0 : s->txc.ptr.p_double[j] = x->ptr.p_double[i];
20479 0 : j = j+1;
20480 : }
20481 : }
20482 :
20483 : /*
20484 : * ECA
20485 : */
20486 0 : ae_assert((s->ecakind==0||s->ecakind==1)||(s->ecakind==-1&&nfree==0), "CQMDebugConstrainedEvalE: unexpected ECAKind", _state);
20487 0 : if( s->ecakind==0 )
20488 : {
20489 :
20490 : /*
20491 : * Dense ECA
20492 : */
20493 0 : for(i=0; i<=nfree-1; i++)
20494 : {
20495 0 : v = 0.0;
20496 0 : for(j=i; j<=nfree-1; j++)
20497 : {
20498 0 : v = v+s->ecadense.ptr.pp_double[i][j]*s->txc.ptr.p_double[j];
20499 : }
20500 0 : result = result+0.5*ae_sqr(v, _state);
20501 : }
20502 : }
20503 0 : if( s->ecakind==1 )
20504 : {
20505 :
20506 : /*
20507 : * Diagonal ECA
20508 : */
20509 0 : for(i=0; i<=nfree-1; i++)
20510 : {
20511 0 : result = result+0.5*ae_sqr(s->ecadiag.ptr.p_double[i]*s->txc.ptr.p_double[i], _state);
20512 : }
20513 : }
20514 :
20515 : /*
20516 : * EQ
20517 : */
20518 0 : for(i=0; i<=s->k-1; i++)
20519 : {
20520 0 : v = 0.0;
20521 0 : for(j=0; j<=nfree-1; j++)
20522 : {
20523 0 : v = v+s->eq.ptr.pp_double[i][j]*s->txc.ptr.p_double[j];
20524 : }
20525 0 : result = result+0.5*ae_sqr(v, _state);
20526 : }
20527 :
20528 : /*
20529 : * EB
20530 : */
20531 0 : for(i=0; i<=nfree-1; i++)
20532 : {
20533 0 : result = result+s->eb.ptr.p_double[i]*s->txc.ptr.p_double[i];
20534 : }
20535 :
20536 : /*
20537 : * EC
20538 : */
20539 0 : result = result+s->ec;
20540 0 : return result;
20541 : }
20542 :
20543 :
20544 : /*************************************************************************
20545 : Internal function, rebuilds "effective" model subject to constraints.
20546 : Returns False on failure (non-SPD main quadratic term)
20547 :
20548 : -- ALGLIB --
20549 : Copyright 10.05.2011 by Bochkanov Sergey
20550 : *************************************************************************/
20551 0 : static ae_bool cqmodels_cqmrebuild(convexquadraticmodel* s,
20552 : ae_state *_state)
20553 : {
20554 : ae_int_t n;
20555 : ae_int_t nfree;
20556 : ae_int_t k;
20557 : ae_int_t i;
20558 : ae_int_t j;
20559 : ae_int_t ridx0;
20560 : ae_int_t ridx1;
20561 : ae_int_t cidx0;
20562 : ae_int_t cidx1;
20563 : double v;
20564 : ae_bool result;
20565 :
20566 :
20567 0 : if( ae_fp_eq(s->alpha,(double)(0))&&ae_fp_eq(s->tau,(double)(0)) )
20568 : {
20569 :
20570 : /*
20571 : * Non-SPD model, quick exit
20572 : */
20573 0 : result = ae_false;
20574 0 : return result;
20575 : }
20576 0 : result = ae_true;
20577 0 : n = s->n;
20578 0 : k = s->k;
20579 :
20580 : /*
20581 : * Determine number of free variables.
20582 : * Fill TXC - array whose last N-NFree elements store constraints.
20583 : */
20584 0 : if( s->isactivesetchanged )
20585 : {
20586 0 : s->nfree = 0;
20587 0 : for(i=0; i<=n-1; i++)
20588 : {
20589 0 : if( !s->activeset.ptr.p_bool[i] )
20590 : {
20591 0 : s->nfree = s->nfree+1;
20592 : }
20593 : }
20594 0 : j = s->nfree;
20595 0 : for(i=0; i<=n-1; i++)
20596 : {
20597 0 : if( s->activeset.ptr.p_bool[i] )
20598 : {
20599 0 : s->txc.ptr.p_double[j] = s->xc.ptr.p_double[i];
20600 0 : j = j+1;
20601 : }
20602 : }
20603 : }
20604 0 : nfree = s->nfree;
20605 :
20606 : /*
20607 : * Re-evaluate TQ2/TQ1/TQ0, if needed
20608 : */
20609 0 : if( s->isactivesetchanged||s->ismaintermchanged )
20610 : {
20611 :
20612 : /*
20613 : * Handle cases Alpha>0 and Alpha=0 separately:
20614 : * * in the first case we have dense matrix
20615 : * * in the second one we have diagonal matrix, which can be
20616 : * handled more efficiently
20617 : */
20618 0 : if( ae_fp_greater(s->alpha,(double)(0)) )
20619 : {
20620 :
20621 : /*
20622 : * Alpha>0, dense QP
20623 : *
20624 : * Split variables into two groups - free (F) and constrained (C). Reorder
20625 : * variables in such way that free vars come first, constrained are last:
20626 : * x = [xf, xc].
20627 : *
20628 : * Main quadratic term x'*(alpha*A+tau*D)*x now splits into quadratic part,
20629 : * linear part and constant part:
20630 : * ( alpha*Aff+tau*Df alpha*Afc ) ( xf )
20631 : * 0.5*( xf' xc' )*( )*( ) =
20632 : * ( alpha*Acf alpha*Acc+tau*Dc ) ( xc )
20633 : *
20634 : * = 0.5*xf'*(alpha*Aff+tau*Df)*xf + (alpha*Afc*xc)'*xf + 0.5*xc'(alpha*Acc+tau*Dc)*xc
20635 : *
20636 : * We store these parts into temporary variables:
20637 : * * alpha*Aff+tau*Df, alpha*Afc, alpha*Acc+tau*Dc are stored into upper
20638 : * triangle of TQ2
20639 : * * alpha*Afc*xc is stored into TQ1
20640 : * * 0.5*xc'(alpha*Acc+tau*Dc)*xc is stored into TQ0
20641 : *
20642 : * Below comes first part of the work - generation of TQ2:
20643 : * * we pass through rows of A and copy I-th row into upper block (Aff/Afc) or
20644 : * lower one (Acf/Acc) of TQ2, depending on presence of X[i] in the active set.
20645 : * RIdx0 variable contains current position for insertion into upper block,
20646 : * RIdx1 contains current position for insertion into lower one.
20647 : * * within each row, we copy J-th element into left half (Aff/Acf) or right
20648 : * one (Afc/Acc), depending on presence of X[j] in the active set. CIdx0
20649 : * contains current position for insertion into left block, CIdx1 contains
20650 : * position for insertion into right one.
20651 : * * during copying, we multiply elements by alpha and add diagonal matrix D.
20652 : */
20653 0 : ridx0 = 0;
20654 0 : ridx1 = s->nfree;
20655 0 : for(i=0; i<=n-1; i++)
20656 : {
20657 0 : cidx0 = 0;
20658 0 : cidx1 = s->nfree;
20659 0 : for(j=0; j<=n-1; j++)
20660 : {
20661 0 : if( !s->activeset.ptr.p_bool[i]&&!s->activeset.ptr.p_bool[j] )
20662 : {
20663 :
20664 : /*
20665 : * Element belongs to Aff
20666 : */
20667 0 : v = s->alpha*s->a.ptr.pp_double[i][j];
20668 0 : if( i==j&&ae_fp_greater(s->tau,(double)(0)) )
20669 : {
20670 0 : v = v+s->tau*s->d.ptr.p_double[i];
20671 : }
20672 0 : s->tq2dense.ptr.pp_double[ridx0][cidx0] = v;
20673 : }
20674 0 : if( !s->activeset.ptr.p_bool[i]&&s->activeset.ptr.p_bool[j] )
20675 : {
20676 :
20677 : /*
20678 : * Element belongs to Afc
20679 : */
20680 0 : s->tq2dense.ptr.pp_double[ridx0][cidx1] = s->alpha*s->a.ptr.pp_double[i][j];
20681 : }
20682 0 : if( s->activeset.ptr.p_bool[i]&&!s->activeset.ptr.p_bool[j] )
20683 : {
20684 :
20685 : /*
20686 : * Element belongs to Acf
20687 : */
20688 0 : s->tq2dense.ptr.pp_double[ridx1][cidx0] = s->alpha*s->a.ptr.pp_double[i][j];
20689 : }
20690 0 : if( s->activeset.ptr.p_bool[i]&&s->activeset.ptr.p_bool[j] )
20691 : {
20692 :
20693 : /*
20694 : * Element belongs to Acc
20695 : */
20696 0 : v = s->alpha*s->a.ptr.pp_double[i][j];
20697 0 : if( i==j&&ae_fp_greater(s->tau,(double)(0)) )
20698 : {
20699 0 : v = v+s->tau*s->d.ptr.p_double[i];
20700 : }
20701 0 : s->tq2dense.ptr.pp_double[ridx1][cidx1] = v;
20702 : }
20703 0 : if( s->activeset.ptr.p_bool[j] )
20704 : {
20705 0 : cidx1 = cidx1+1;
20706 : }
20707 : else
20708 : {
20709 0 : cidx0 = cidx0+1;
20710 : }
20711 : }
20712 0 : if( s->activeset.ptr.p_bool[i] )
20713 : {
20714 0 : ridx1 = ridx1+1;
20715 : }
20716 : else
20717 : {
20718 0 : ridx0 = ridx0+1;
20719 : }
20720 : }
20721 :
20722 : /*
20723 : * Now we have TQ2, and we can evaluate TQ1.
20724 : * In the special case when we have Alpha=0, NFree=0 or NFree=N,
20725 : * TQ1 is filled by zeros.
20726 : */
20727 0 : for(i=0; i<=n-1; i++)
20728 : {
20729 0 : s->tq1.ptr.p_double[i] = 0.0;
20730 : }
20731 0 : if( s->nfree>0&&s->nfree<n )
20732 : {
20733 0 : rmatrixmv(s->nfree, n-s->nfree, &s->tq2dense, 0, s->nfree, 0, &s->txc, s->nfree, &s->tq1, 0, _state);
20734 : }
20735 :
20736 : /*
20737 : * And finally, we evaluate TQ0.
20738 : */
20739 0 : v = 0.0;
20740 0 : for(i=s->nfree; i<=n-1; i++)
20741 : {
20742 0 : for(j=s->nfree; j<=n-1; j++)
20743 : {
20744 0 : v = v+0.5*s->txc.ptr.p_double[i]*s->tq2dense.ptr.pp_double[i][j]*s->txc.ptr.p_double[j];
20745 : }
20746 : }
20747 0 : s->tq0 = v;
20748 : }
20749 : else
20750 : {
20751 :
20752 : /*
20753 : * Alpha=0, diagonal QP
20754 : *
20755 : * Split variables into two groups - free (F) and constrained (C). Reorder
20756 : * variables in such way that free vars come first, constrained are last:
20757 : * x = [xf, xc].
20758 : *
20759 : * Main quadratic term x'*(tau*D)*x now splits into quadratic and constant
20760 : * parts:
20761 : * ( tau*Df ) ( xf )
20762 : * 0.5*( xf' xc' )*( )*( ) =
20763 : * ( tau*Dc ) ( xc )
20764 : *
20765 : * = 0.5*xf'*(tau*Df)*xf + 0.5*xc'(tau*Dc)*xc
20766 : *
20767 : * We store these parts into temporary variables:
20768 : * * tau*Df is stored in TQ2Diag
20769 : * * 0.5*xc'(tau*Dc)*xc is stored into TQ0
20770 : */
20771 0 : s->tq0 = 0.0;
20772 0 : ridx0 = 0;
20773 0 : for(i=0; i<=n-1; i++)
20774 : {
20775 0 : if( !s->activeset.ptr.p_bool[i] )
20776 : {
20777 0 : s->tq2diag.ptr.p_double[ridx0] = s->tau*s->d.ptr.p_double[i];
20778 0 : ridx0 = ridx0+1;
20779 : }
20780 : else
20781 : {
20782 0 : s->tq0 = s->tq0+0.5*s->tau*s->d.ptr.p_double[i]*ae_sqr(s->xc.ptr.p_double[i], _state);
20783 : }
20784 : }
20785 0 : for(i=0; i<=n-1; i++)
20786 : {
20787 0 : s->tq1.ptr.p_double[i] = 0.0;
20788 : }
20789 : }
20790 : }
20791 :
20792 : /*
20793 : * Re-evaluate TK2/TK1/TK0, if needed
20794 : */
20795 0 : if( s->isactivesetchanged||s->issecondarytermchanged )
20796 : {
20797 :
20798 : /*
20799 : * Split variables into two groups - free (F) and constrained (C). Reorder
20800 : * variables in such way that free vars come first, constrained are last:
20801 : * x = [xf, xc].
20802 : *
20803 : * Secondary term theta*(Q*x-r)'*(Q*x-r) now splits into quadratic part,
20804 : * linear part and constant part:
20805 : * ( ( xf ) )' ( ( xf ) )
20806 : * 0.5*theta*( (Qf Qc)'*( ) - r ) * ( (Qf Qc)'*( ) - r ) =
20807 : * ( ( xc ) ) ( ( xc ) )
20808 : *
20809 : * = 0.5*theta*xf'*(Qf'*Qf)*xf + theta*((Qc*xc-r)'*Qf)*xf +
20810 : * + theta*(-r'*(Qc*xc-r)-0.5*r'*r+0.5*xc'*Qc'*Qc*xc)
20811 : *
20812 : * We store these parts into temporary variables:
20813 : * * sqrt(theta)*Qf is stored into TK2
20814 : * * theta*((Qc*xc-r)'*Qf) is stored into TK1
20815 : * * theta*(-r'*(Qc*xc-r)-0.5*r'*r+0.5*xc'*Qc'*Qc*xc) is stored into TK0
20816 : *
20817 : * We use several other temporaries to store intermediate results:
20818 : * * Tmp0 - to store Qc*xc-r
20819 : * * Tmp1 - to store Qc*xc
20820 : *
20821 : * Generation of TK2/TK1/TK0 is performed as follows:
20822 : * * we fill TK2/TK1/TK0 (to handle K=0 or Theta=0)
20823 : * * other steps are performed only for K>0 and Theta>0
20824 : * * we pass through columns of Q and copy I-th column into left block (Qf) or
20825 : * right one (Qc) of TK2, depending on presence of X[i] in the active set.
20826 : * CIdx0 variable contains current position for insertion into upper block,
20827 : * CIdx1 contains current position for insertion into lower one.
20828 : * * we calculate Qc*xc-r and store it into Tmp0
20829 : * * we calculate TK0 and TK1
20830 : * * we multiply leading part of TK2 which stores Qf by sqrt(theta)
20831 : * it is important to perform this step AFTER calculation of TK0 and TK1,
20832 : * because we need original (non-modified) Qf to calculate TK0 and TK1.
20833 : */
20834 0 : for(j=0; j<=n-1; j++)
20835 : {
20836 0 : for(i=0; i<=k-1; i++)
20837 : {
20838 0 : s->tk2.ptr.pp_double[i][j] = 0.0;
20839 : }
20840 0 : s->tk1.ptr.p_double[j] = 0.0;
20841 : }
20842 0 : s->tk0 = 0.0;
20843 0 : if( s->k>0&&ae_fp_greater(s->theta,(double)(0)) )
20844 : {
20845 :
20846 : /*
20847 : * Split Q into Qf and Qc
20848 : * Calculate Qc*xc-r, store in Tmp0
20849 : */
20850 0 : rvectorsetlengthatleast(&s->tmp0, k, _state);
20851 0 : rvectorsetlengthatleast(&s->tmp1, k, _state);
20852 0 : cidx0 = 0;
20853 0 : cidx1 = nfree;
20854 0 : for(i=0; i<=k-1; i++)
20855 : {
20856 0 : s->tmp1.ptr.p_double[i] = 0.0;
20857 : }
20858 0 : for(j=0; j<=n-1; j++)
20859 : {
20860 0 : if( s->activeset.ptr.p_bool[j] )
20861 : {
20862 0 : for(i=0; i<=k-1; i++)
20863 : {
20864 0 : s->tk2.ptr.pp_double[i][cidx1] = s->q.ptr.pp_double[i][j];
20865 0 : 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];
20866 : }
20867 0 : cidx1 = cidx1+1;
20868 : }
20869 : else
20870 : {
20871 0 : for(i=0; i<=k-1; i++)
20872 : {
20873 0 : s->tk2.ptr.pp_double[i][cidx0] = s->q.ptr.pp_double[i][j];
20874 : }
20875 0 : cidx0 = cidx0+1;
20876 : }
20877 : }
20878 0 : for(i=0; i<=k-1; i++)
20879 : {
20880 0 : s->tmp0.ptr.p_double[i] = s->tmp1.ptr.p_double[i]-s->r.ptr.p_double[i];
20881 : }
20882 :
20883 : /*
20884 : * Calculate TK0
20885 : */
20886 0 : v = 0.0;
20887 0 : for(i=0; i<=k-1; i++)
20888 : {
20889 0 : 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));
20890 : }
20891 0 : s->tk0 = v;
20892 :
20893 : /*
20894 : * Calculate TK1
20895 : */
20896 0 : if( nfree>0 )
20897 : {
20898 0 : for(i=0; i<=k-1; i++)
20899 : {
20900 0 : v = s->theta*s->tmp0.ptr.p_double[i];
20901 0 : 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);
20902 : }
20903 : }
20904 :
20905 : /*
20906 : * Calculate TK2
20907 : */
20908 0 : if( nfree>0 )
20909 : {
20910 0 : v = ae_sqrt(s->theta, _state);
20911 0 : for(i=0; i<=k-1; i++)
20912 : {
20913 0 : ae_v_muld(&s->tk2.ptr.pp_double[i][0], 1, ae_v_len(0,nfree-1), v);
20914 : }
20915 : }
20916 : }
20917 : }
20918 :
20919 : /*
20920 : * Re-evaluate TB
20921 : */
20922 0 : if( s->isactivesetchanged||s->islineartermchanged )
20923 : {
20924 0 : ridx0 = 0;
20925 0 : ridx1 = nfree;
20926 0 : for(i=0; i<=n-1; i++)
20927 : {
20928 0 : if( s->activeset.ptr.p_bool[i] )
20929 : {
20930 0 : s->tb.ptr.p_double[ridx1] = s->b.ptr.p_double[i];
20931 0 : ridx1 = ridx1+1;
20932 : }
20933 : else
20934 : {
20935 0 : s->tb.ptr.p_double[ridx0] = s->b.ptr.p_double[i];
20936 0 : ridx0 = ridx0+1;
20937 : }
20938 : }
20939 : }
20940 :
20941 : /*
20942 : * Compose ECA: either dense ECA or diagonal ECA
20943 : */
20944 0 : if( (s->isactivesetchanged||s->ismaintermchanged)&&nfree>0 )
20945 : {
20946 0 : if( ae_fp_greater(s->alpha,(double)(0)) )
20947 : {
20948 :
20949 : /*
20950 : * Dense ECA
20951 : */
20952 0 : s->ecakind = 0;
20953 0 : for(i=0; i<=nfree-1; i++)
20954 : {
20955 0 : for(j=i; j<=nfree-1; j++)
20956 : {
20957 0 : s->ecadense.ptr.pp_double[i][j] = s->tq2dense.ptr.pp_double[i][j];
20958 : }
20959 : }
20960 0 : if( !spdmatrixcholeskyrec(&s->ecadense, 0, nfree, ae_true, &s->tmp0, _state) )
20961 : {
20962 0 : result = ae_false;
20963 0 : return result;
20964 : }
20965 : }
20966 : else
20967 : {
20968 :
20969 : /*
20970 : * Diagonal ECA
20971 : */
20972 0 : s->ecakind = 1;
20973 0 : for(i=0; i<=nfree-1; i++)
20974 : {
20975 0 : if( ae_fp_less(s->tq2diag.ptr.p_double[i],(double)(0)) )
20976 : {
20977 0 : result = ae_false;
20978 0 : return result;
20979 : }
20980 0 : s->ecadiag.ptr.p_double[i] = ae_sqrt(s->tq2diag.ptr.p_double[i], _state);
20981 : }
20982 : }
20983 : }
20984 :
20985 : /*
20986 : * Compose EQ
20987 : */
20988 0 : if( s->isactivesetchanged||s->issecondarytermchanged )
20989 : {
20990 0 : for(i=0; i<=k-1; i++)
20991 : {
20992 0 : for(j=0; j<=nfree-1; j++)
20993 : {
20994 0 : s->eq.ptr.pp_double[i][j] = s->tk2.ptr.pp_double[i][j];
20995 : }
20996 : }
20997 : }
20998 :
20999 : /*
21000 : * Calculate ECCM
21001 : */
21002 0 : if( ((((s->isactivesetchanged||s->ismaintermchanged)||s->issecondarytermchanged)&&s->k>0)&&ae_fp_greater(s->theta,(double)(0)))&&nfree>0 )
21003 : {
21004 :
21005 : /*
21006 : * Calculate ECCM - Cholesky factor of the "effective" capacitance
21007 : * matrix CM = I + EQ*inv(EffectiveA)*EQ'.
21008 : *
21009 : * We calculate CM as follows:
21010 : * CM = I + EQ*inv(EffectiveA)*EQ'
21011 : * = I + EQ*ECA^(-1)*ECA^(-T)*EQ'
21012 : * = I + (EQ*ECA^(-1))*(EQ*ECA^(-1))'
21013 : *
21014 : * Then we perform Cholesky decomposition of CM.
21015 : */
21016 0 : rmatrixsetlengthatleast(&s->tmp2, k, n, _state);
21017 0 : rmatrixcopy(k, nfree, &s->eq, 0, 0, &s->tmp2, 0, 0, _state);
21018 0 : ae_assert(s->ecakind==0||s->ecakind==1, "CQMRebuild: unexpected ECAKind", _state);
21019 0 : if( s->ecakind==0 )
21020 : {
21021 0 : rmatrixrighttrsm(k, nfree, &s->ecadense, 0, 0, ae_true, ae_false, 0, &s->tmp2, 0, 0, _state);
21022 : }
21023 0 : if( s->ecakind==1 )
21024 : {
21025 0 : for(i=0; i<=k-1; i++)
21026 : {
21027 0 : for(j=0; j<=nfree-1; j++)
21028 : {
21029 0 : s->tmp2.ptr.pp_double[i][j] = s->tmp2.ptr.pp_double[i][j]/s->ecadiag.ptr.p_double[j];
21030 : }
21031 : }
21032 : }
21033 0 : for(i=0; i<=k-1; i++)
21034 : {
21035 0 : for(j=0; j<=k-1; j++)
21036 : {
21037 0 : s->eccm.ptr.pp_double[i][j] = 0.0;
21038 : }
21039 0 : s->eccm.ptr.pp_double[i][i] = 1.0;
21040 : }
21041 0 : rmatrixsyrk(k, nfree, 1.0, &s->tmp2, 0, 0, 0, 1.0, &s->eccm, 0, 0, ae_true, _state);
21042 0 : if( !spdmatrixcholeskyrec(&s->eccm, 0, k, ae_true, &s->tmp0, _state) )
21043 : {
21044 0 : result = ae_false;
21045 0 : return result;
21046 : }
21047 : }
21048 :
21049 : /*
21050 : * Compose EB and EC
21051 : *
21052 : * NOTE: because these quantities are cheap to compute, we do not
21053 : * use caching here.
21054 : */
21055 0 : for(i=0; i<=nfree-1; i++)
21056 : {
21057 0 : s->eb.ptr.p_double[i] = s->tq1.ptr.p_double[i]+s->tk1.ptr.p_double[i]+s->tb.ptr.p_double[i];
21058 : }
21059 0 : s->ec = s->tq0+s->tk0;
21060 0 : for(i=nfree; i<=n-1; i++)
21061 : {
21062 0 : s->ec = s->ec+s->tb.ptr.p_double[i]*s->txc.ptr.p_double[i];
21063 : }
21064 :
21065 : /*
21066 : * Change cache status - everything is cached
21067 : */
21068 0 : s->ismaintermchanged = ae_false;
21069 0 : s->issecondarytermchanged = ae_false;
21070 0 : s->islineartermchanged = ae_false;
21071 0 : s->isactivesetchanged = ae_false;
21072 0 : return result;
21073 : }
21074 :
21075 :
21076 : /*************************************************************************
21077 : Internal function, solves system Effective_A*x = b.
21078 : It should be called after successful completion of CQMRebuild().
21079 :
21080 : INPUT PARAMETERS:
21081 : S - quadratic model, after call to CQMRebuild()
21082 : X - right part B, array[S.NFree]
21083 : Tmp - temporary array, automatically reallocated if needed
21084 :
21085 : OUTPUT PARAMETERS:
21086 : X - solution, array[S.NFree]
21087 :
21088 : NOTE: when called with zero S.NFree, returns silently
21089 : NOTE: this function assumes that EA is non-degenerate
21090 :
21091 : -- ALGLIB --
21092 : Copyright 10.05.2011 by Bochkanov Sergey
21093 : *************************************************************************/
21094 0 : static void cqmodels_cqmsolveea(convexquadraticmodel* s,
21095 : /* Real */ ae_vector* x,
21096 : /* Real */ ae_vector* tmp,
21097 : ae_state *_state)
21098 : {
21099 : ae_int_t i;
21100 :
21101 :
21102 0 : ae_assert((s->ecakind==0||s->ecakind==1)||(s->ecakind==-1&&s->nfree==0), "CQMSolveEA: unexpected ECAKind", _state);
21103 0 : if( s->ecakind==0 )
21104 : {
21105 :
21106 : /*
21107 : * Dense ECA, use FBLSCholeskySolve() dense solver.
21108 : */
21109 0 : fblscholeskysolve(&s->ecadense, 1.0, s->nfree, ae_true, x, tmp, _state);
21110 : }
21111 0 : if( s->ecakind==1 )
21112 : {
21113 :
21114 : /*
21115 : * Diagonal ECA
21116 : */
21117 0 : for(i=0; i<=s->nfree-1; i++)
21118 : {
21119 0 : x->ptr.p_double[i] = x->ptr.p_double[i]/ae_sqr(s->ecadiag.ptr.p_double[i], _state);
21120 : }
21121 : }
21122 0 : }
21123 :
21124 :
21125 0 : void _convexquadraticmodel_init(void* _p, ae_state *_state, ae_bool make_automatic)
21126 : {
21127 0 : convexquadraticmodel *p = (convexquadraticmodel*)_p;
21128 0 : ae_touch_ptr((void*)p);
21129 0 : ae_matrix_init(&p->a, 0, 0, DT_REAL, _state, make_automatic);
21130 0 : ae_matrix_init(&p->q, 0, 0, DT_REAL, _state, make_automatic);
21131 0 : ae_vector_init(&p->b, 0, DT_REAL, _state, make_automatic);
21132 0 : ae_vector_init(&p->r, 0, DT_REAL, _state, make_automatic);
21133 0 : ae_vector_init(&p->xc, 0, DT_REAL, _state, make_automatic);
21134 0 : ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic);
21135 0 : ae_vector_init(&p->activeset, 0, DT_BOOL, _state, make_automatic);
21136 0 : ae_matrix_init(&p->tq2dense, 0, 0, DT_REAL, _state, make_automatic);
21137 0 : ae_matrix_init(&p->tk2, 0, 0, DT_REAL, _state, make_automatic);
21138 0 : ae_vector_init(&p->tq2diag, 0, DT_REAL, _state, make_automatic);
21139 0 : ae_vector_init(&p->tq1, 0, DT_REAL, _state, make_automatic);
21140 0 : ae_vector_init(&p->tk1, 0, DT_REAL, _state, make_automatic);
21141 0 : ae_vector_init(&p->txc, 0, DT_REAL, _state, make_automatic);
21142 0 : ae_vector_init(&p->tb, 0, DT_REAL, _state, make_automatic);
21143 0 : ae_matrix_init(&p->ecadense, 0, 0, DT_REAL, _state, make_automatic);
21144 0 : ae_matrix_init(&p->eq, 0, 0, DT_REAL, _state, make_automatic);
21145 0 : ae_matrix_init(&p->eccm, 0, 0, DT_REAL, _state, make_automatic);
21146 0 : ae_vector_init(&p->ecadiag, 0, DT_REAL, _state, make_automatic);
21147 0 : ae_vector_init(&p->eb, 0, DT_REAL, _state, make_automatic);
21148 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
21149 0 : ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic);
21150 0 : ae_vector_init(&p->tmpg, 0, DT_REAL, _state, make_automatic);
21151 0 : ae_matrix_init(&p->tmp2, 0, 0, DT_REAL, _state, make_automatic);
21152 0 : }
21153 :
21154 :
21155 0 : void _convexquadraticmodel_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
21156 : {
21157 0 : convexquadraticmodel *dst = (convexquadraticmodel*)_dst;
21158 0 : convexquadraticmodel *src = (convexquadraticmodel*)_src;
21159 0 : dst->n = src->n;
21160 0 : dst->k = src->k;
21161 0 : dst->alpha = src->alpha;
21162 0 : dst->tau = src->tau;
21163 0 : dst->theta = src->theta;
21164 0 : ae_matrix_init_copy(&dst->a, &src->a, _state, make_automatic);
21165 0 : ae_matrix_init_copy(&dst->q, &src->q, _state, make_automatic);
21166 0 : ae_vector_init_copy(&dst->b, &src->b, _state, make_automatic);
21167 0 : ae_vector_init_copy(&dst->r, &src->r, _state, make_automatic);
21168 0 : ae_vector_init_copy(&dst->xc, &src->xc, _state, make_automatic);
21169 0 : ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic);
21170 0 : ae_vector_init_copy(&dst->activeset, &src->activeset, _state, make_automatic);
21171 0 : ae_matrix_init_copy(&dst->tq2dense, &src->tq2dense, _state, make_automatic);
21172 0 : ae_matrix_init_copy(&dst->tk2, &src->tk2, _state, make_automatic);
21173 0 : ae_vector_init_copy(&dst->tq2diag, &src->tq2diag, _state, make_automatic);
21174 0 : ae_vector_init_copy(&dst->tq1, &src->tq1, _state, make_automatic);
21175 0 : ae_vector_init_copy(&dst->tk1, &src->tk1, _state, make_automatic);
21176 0 : dst->tq0 = src->tq0;
21177 0 : dst->tk0 = src->tk0;
21178 0 : ae_vector_init_copy(&dst->txc, &src->txc, _state, make_automatic);
21179 0 : ae_vector_init_copy(&dst->tb, &src->tb, _state, make_automatic);
21180 0 : dst->nfree = src->nfree;
21181 0 : dst->ecakind = src->ecakind;
21182 0 : ae_matrix_init_copy(&dst->ecadense, &src->ecadense, _state, make_automatic);
21183 0 : ae_matrix_init_copy(&dst->eq, &src->eq, _state, make_automatic);
21184 0 : ae_matrix_init_copy(&dst->eccm, &src->eccm, _state, make_automatic);
21185 0 : ae_vector_init_copy(&dst->ecadiag, &src->ecadiag, _state, make_automatic);
21186 0 : ae_vector_init_copy(&dst->eb, &src->eb, _state, make_automatic);
21187 0 : dst->ec = src->ec;
21188 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
21189 0 : ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic);
21190 0 : ae_vector_init_copy(&dst->tmpg, &src->tmpg, _state, make_automatic);
21191 0 : ae_matrix_init_copy(&dst->tmp2, &src->tmp2, _state, make_automatic);
21192 0 : dst->ismaintermchanged = src->ismaintermchanged;
21193 0 : dst->issecondarytermchanged = src->issecondarytermchanged;
21194 0 : dst->islineartermchanged = src->islineartermchanged;
21195 0 : dst->isactivesetchanged = src->isactivesetchanged;
21196 0 : }
21197 :
21198 :
21199 0 : void _convexquadraticmodel_clear(void* _p)
21200 : {
21201 0 : convexquadraticmodel *p = (convexquadraticmodel*)_p;
21202 0 : ae_touch_ptr((void*)p);
21203 0 : ae_matrix_clear(&p->a);
21204 0 : ae_matrix_clear(&p->q);
21205 0 : ae_vector_clear(&p->b);
21206 0 : ae_vector_clear(&p->r);
21207 0 : ae_vector_clear(&p->xc);
21208 0 : ae_vector_clear(&p->d);
21209 0 : ae_vector_clear(&p->activeset);
21210 0 : ae_matrix_clear(&p->tq2dense);
21211 0 : ae_matrix_clear(&p->tk2);
21212 0 : ae_vector_clear(&p->tq2diag);
21213 0 : ae_vector_clear(&p->tq1);
21214 0 : ae_vector_clear(&p->tk1);
21215 0 : ae_vector_clear(&p->txc);
21216 0 : ae_vector_clear(&p->tb);
21217 0 : ae_matrix_clear(&p->ecadense);
21218 0 : ae_matrix_clear(&p->eq);
21219 0 : ae_matrix_clear(&p->eccm);
21220 0 : ae_vector_clear(&p->ecadiag);
21221 0 : ae_vector_clear(&p->eb);
21222 0 : ae_vector_clear(&p->tmp0);
21223 0 : ae_vector_clear(&p->tmp1);
21224 0 : ae_vector_clear(&p->tmpg);
21225 0 : ae_matrix_clear(&p->tmp2);
21226 0 : }
21227 :
21228 :
21229 0 : void _convexquadraticmodel_destroy(void* _p)
21230 : {
21231 0 : convexquadraticmodel *p = (convexquadraticmodel*)_p;
21232 0 : ae_touch_ptr((void*)p);
21233 0 : ae_matrix_destroy(&p->a);
21234 0 : ae_matrix_destroy(&p->q);
21235 0 : ae_vector_destroy(&p->b);
21236 0 : ae_vector_destroy(&p->r);
21237 0 : ae_vector_destroy(&p->xc);
21238 0 : ae_vector_destroy(&p->d);
21239 0 : ae_vector_destroy(&p->activeset);
21240 0 : ae_matrix_destroy(&p->tq2dense);
21241 0 : ae_matrix_destroy(&p->tk2);
21242 0 : ae_vector_destroy(&p->tq2diag);
21243 0 : ae_vector_destroy(&p->tq1);
21244 0 : ae_vector_destroy(&p->tk1);
21245 0 : ae_vector_destroy(&p->txc);
21246 0 : ae_vector_destroy(&p->tb);
21247 0 : ae_matrix_destroy(&p->ecadense);
21248 0 : ae_matrix_destroy(&p->eq);
21249 0 : ae_matrix_destroy(&p->eccm);
21250 0 : ae_vector_destroy(&p->ecadiag);
21251 0 : ae_vector_destroy(&p->eb);
21252 0 : ae_vector_destroy(&p->tmp0);
21253 0 : ae_vector_destroy(&p->tmp1);
21254 0 : ae_vector_destroy(&p->tmpg);
21255 0 : ae_matrix_destroy(&p->tmp2);
21256 0 : }
21257 :
21258 :
21259 : #endif
21260 : #if defined(AE_COMPILE_OPTGUARDAPI) || !defined(AE_PARTIAL_BUILD)
21261 :
21262 :
21263 : /*************************************************************************
21264 : This subroutine initializes "internal" OptGuard report, i.e. one intended
21265 : for internal use by optimizers.
21266 :
21267 : -- ALGLIB --
21268 : Copyright 19.11.2018 by Bochkanov Sergey
21269 : *************************************************************************/
21270 996 : void optguardinitinternal(optguardreport* rep,
21271 : ae_int_t n,
21272 : ae_int_t k,
21273 : ae_state *_state)
21274 : {
21275 :
21276 :
21277 996 : rep->nonc0suspected = ae_false;
21278 996 : rep->nonc0test0positive = ae_false;
21279 996 : rep->nonc0lipschitzc = (double)(0);
21280 996 : rep->nonc0fidx = -1;
21281 996 : rep->nonc1suspected = ae_false;
21282 996 : rep->nonc1test0positive = ae_false;
21283 996 : rep->nonc1test1positive = ae_false;
21284 996 : rep->nonc1lipschitzc = (double)(0);
21285 996 : rep->nonc1fidx = -1;
21286 996 : rep->badgradsuspected = ae_false;
21287 996 : rep->badgradfidx = -1;
21288 996 : rep->badgradvidx = -1;
21289 996 : }
21290 :
21291 :
21292 : /*************************************************************************
21293 : This subroutine exports report to user-readable representation (all arrays
21294 : are forced to have exactly same size as needed; unused arrays are set to
21295 : zero length).
21296 :
21297 : -- ALGLIB --
21298 : Copyright 19.11.2018 by Bochkanov Sergey
21299 : *************************************************************************/
21300 0 : void optguardexportreport(optguardreport* srcrep,
21301 : ae_int_t n,
21302 : ae_int_t k,
21303 : ae_bool badgradhasxj,
21304 : optguardreport* dstrep,
21305 : ae_state *_state)
21306 : {
21307 : ae_int_t i;
21308 : ae_int_t j;
21309 :
21310 :
21311 0 : dstrep->nonc0suspected = srcrep->nonc0suspected;
21312 0 : dstrep->nonc0test0positive = srcrep->nonc0test0positive;
21313 0 : if( srcrep->nonc0suspected )
21314 : {
21315 0 : dstrep->nonc0lipschitzc = srcrep->nonc0lipschitzc;
21316 0 : dstrep->nonc0fidx = srcrep->nonc0fidx;
21317 : }
21318 : else
21319 : {
21320 0 : dstrep->nonc0lipschitzc = (double)(0);
21321 0 : dstrep->nonc0fidx = -1;
21322 : }
21323 0 : dstrep->nonc1suspected = srcrep->nonc1suspected;
21324 0 : dstrep->nonc1test0positive = srcrep->nonc1test0positive;
21325 0 : dstrep->nonc1test1positive = srcrep->nonc1test1positive;
21326 0 : if( srcrep->nonc1suspected )
21327 : {
21328 0 : dstrep->nonc1lipschitzc = srcrep->nonc1lipschitzc;
21329 0 : dstrep->nonc1fidx = srcrep->nonc1fidx;
21330 : }
21331 : else
21332 : {
21333 0 : dstrep->nonc1lipschitzc = (double)(0);
21334 0 : dstrep->nonc1fidx = -1;
21335 : }
21336 0 : dstrep->badgradsuspected = srcrep->badgradsuspected;
21337 0 : if( srcrep->badgradsuspected )
21338 : {
21339 0 : dstrep->badgradfidx = srcrep->badgradfidx;
21340 0 : dstrep->badgradvidx = srcrep->badgradvidx;
21341 : }
21342 : else
21343 : {
21344 0 : dstrep->badgradfidx = -1;
21345 0 : dstrep->badgradvidx = -1;
21346 : }
21347 0 : if( badgradhasxj )
21348 : {
21349 0 : ae_vector_set_length(&dstrep->badgradxbase, n, _state);
21350 0 : for(j=0; j<=n-1; j++)
21351 : {
21352 0 : dstrep->badgradxbase.ptr.p_double[j] = srcrep->badgradxbase.ptr.p_double[j];
21353 : }
21354 0 : ae_matrix_set_length(&dstrep->badgraduser, k, n, _state);
21355 0 : ae_matrix_set_length(&dstrep->badgradnum, k, n, _state);
21356 0 : for(i=0; i<=k-1; i++)
21357 : {
21358 0 : for(j=0; j<=n-1; j++)
21359 : {
21360 0 : dstrep->badgraduser.ptr.pp_double[i][j] = srcrep->badgraduser.ptr.pp_double[i][j];
21361 0 : dstrep->badgradnum.ptr.pp_double[i][j] = srcrep->badgradnum.ptr.pp_double[i][j];
21362 : }
21363 : }
21364 : }
21365 : else
21366 : {
21367 0 : ae_vector_set_length(&dstrep->badgradxbase, 0, _state);
21368 0 : ae_matrix_set_length(&dstrep->badgraduser, 0, 0, _state);
21369 0 : ae_matrix_set_length(&dstrep->badgradnum, 0, 0, _state);
21370 : }
21371 0 : }
21372 :
21373 :
21374 : /*************************************************************************
21375 : This subroutine exports report to user-readable representation (all arrays
21376 : are forced to have exactly same size as needed; unused arrays are set to
21377 : zero length).
21378 :
21379 : NOTE: we assume that SrcRep contains scaled X0[] and D[], i.e. explicit
21380 : variable scaling was applied. We need to rescale them during export,
21381 : that's why we need S[] parameter.
21382 :
21383 : -- ALGLIB --
21384 : Copyright 19.11.2018 by Bochkanov Sergey
21385 : *************************************************************************/
21386 0 : void smoothnessmonitorexportc1test0report(optguardnonc1test0report* srcrep,
21387 : /* Real */ ae_vector* s,
21388 : optguardnonc1test0report* dstrep,
21389 : ae_state *_state)
21390 : {
21391 : ae_int_t i;
21392 :
21393 :
21394 0 : dstrep->positive = srcrep->positive;
21395 0 : if( srcrep->positive )
21396 : {
21397 0 : dstrep->stpidxa = srcrep->stpidxa;
21398 0 : dstrep->stpidxb = srcrep->stpidxb;
21399 0 : dstrep->fidx = srcrep->fidx;
21400 0 : dstrep->cnt = srcrep->cnt;
21401 0 : dstrep->n = srcrep->n;
21402 0 : ae_vector_set_length(&dstrep->x0, srcrep->n, _state);
21403 0 : ae_vector_set_length(&dstrep->d, srcrep->n, _state);
21404 0 : for(i=0; i<=srcrep->n-1; i++)
21405 : {
21406 0 : dstrep->x0.ptr.p_double[i] = srcrep->x0.ptr.p_double[i]*s->ptr.p_double[i];
21407 0 : dstrep->d.ptr.p_double[i] = srcrep->d.ptr.p_double[i]*s->ptr.p_double[i];
21408 : }
21409 0 : ae_vector_set_length(&dstrep->stp, srcrep->cnt, _state);
21410 0 : ae_vector_set_length(&dstrep->f, srcrep->cnt, _state);
21411 0 : for(i=0; i<=srcrep->cnt-1; i++)
21412 : {
21413 0 : dstrep->stp.ptr.p_double[i] = srcrep->stp.ptr.p_double[i];
21414 0 : dstrep->f.ptr.p_double[i] = srcrep->f.ptr.p_double[i];
21415 : }
21416 : }
21417 : else
21418 : {
21419 0 : dstrep->stpidxa = -1;
21420 0 : dstrep->stpidxb = -1;
21421 0 : dstrep->fidx = -1;
21422 0 : dstrep->cnt = 0;
21423 0 : dstrep->n = 0;
21424 0 : ae_vector_set_length(&dstrep->x0, 0, _state);
21425 0 : ae_vector_set_length(&dstrep->d, 0, _state);
21426 0 : ae_vector_set_length(&dstrep->stp, 0, _state);
21427 0 : ae_vector_set_length(&dstrep->f, 0, _state);
21428 : }
21429 0 : }
21430 :
21431 :
21432 : /*************************************************************************
21433 : This subroutine exports report to user-readable representation (all arrays
21434 : are forced to have exactly same size as needed; unused arrays are set to
21435 : zero length).
21436 :
21437 : NOTE: we assume that SrcRep contains scaled X0[], D[] and G[], i.e. explicit
21438 : variable scaling was applied. We need to rescale them during export,
21439 : that's why we need S[] parameter.
21440 :
21441 : -- ALGLIB --
21442 : Copyright 19.11.2018 by Bochkanov Sergey
21443 : *************************************************************************/
21444 0 : void smoothnessmonitorexportc1test1report(optguardnonc1test1report* srcrep,
21445 : /* Real */ ae_vector* s,
21446 : optguardnonc1test1report* dstrep,
21447 : ae_state *_state)
21448 : {
21449 : ae_int_t i;
21450 :
21451 :
21452 0 : dstrep->positive = srcrep->positive;
21453 0 : if( srcrep->positive )
21454 : {
21455 0 : ae_assert(srcrep->vidx>=0&&srcrep->vidx<srcrep->n, "SmoothnessMonitorExportC1Test1Report: integrity check failed", _state);
21456 0 : dstrep->stpidxa = srcrep->stpidxa;
21457 0 : dstrep->stpidxb = srcrep->stpidxb;
21458 0 : dstrep->fidx = srcrep->fidx;
21459 0 : dstrep->vidx = srcrep->vidx;
21460 0 : dstrep->cnt = srcrep->cnt;
21461 0 : dstrep->n = srcrep->n;
21462 0 : ae_vector_set_length(&dstrep->x0, srcrep->n, _state);
21463 0 : ae_vector_set_length(&dstrep->d, srcrep->n, _state);
21464 0 : for(i=0; i<=srcrep->n-1; i++)
21465 : {
21466 0 : dstrep->x0.ptr.p_double[i] = srcrep->x0.ptr.p_double[i]*s->ptr.p_double[i];
21467 0 : dstrep->d.ptr.p_double[i] = srcrep->d.ptr.p_double[i]*s->ptr.p_double[i];
21468 : }
21469 0 : ae_vector_set_length(&dstrep->stp, srcrep->cnt, _state);
21470 0 : ae_vector_set_length(&dstrep->g, srcrep->cnt, _state);
21471 0 : for(i=0; i<=srcrep->cnt-1; i++)
21472 : {
21473 0 : dstrep->stp.ptr.p_double[i] = srcrep->stp.ptr.p_double[i];
21474 0 : dstrep->g.ptr.p_double[i] = srcrep->g.ptr.p_double[i]/s->ptr.p_double[srcrep->vidx];
21475 : }
21476 : }
21477 : else
21478 : {
21479 0 : dstrep->stpidxa = -1;
21480 0 : dstrep->stpidxb = -1;
21481 0 : dstrep->fidx = -1;
21482 0 : dstrep->vidx = -1;
21483 0 : dstrep->cnt = 0;
21484 0 : dstrep->n = 0;
21485 0 : ae_vector_set_length(&dstrep->x0, 0, _state);
21486 0 : ae_vector_set_length(&dstrep->d, 0, _state);
21487 0 : ae_vector_set_length(&dstrep->stp, 0, _state);
21488 0 : ae_vector_set_length(&dstrep->g, 0, _state);
21489 : }
21490 0 : }
21491 :
21492 :
21493 : /*************************************************************************
21494 : Returns True when all flags are clear. Intended for easy coding of unit
21495 : tests.
21496 :
21497 : -- ALGLIB --
21498 : Copyright 19.11.2018 by Bochkanov Sergey
21499 : *************************************************************************/
21500 0 : ae_bool optguardallclear(optguardreport* rep, ae_state *_state)
21501 : {
21502 : ae_bool result;
21503 :
21504 :
21505 0 : result = !((rep->badgradsuspected||rep->nonc0suspected)||rep->nonc1suspected);
21506 0 : return result;
21507 : }
21508 :
21509 :
21510 498 : void _optguardreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
21511 : {
21512 498 : optguardreport *p = (optguardreport*)_p;
21513 498 : ae_touch_ptr((void*)p);
21514 498 : ae_vector_init(&p->badgradxbase, 0, DT_REAL, _state, make_automatic);
21515 498 : ae_matrix_init(&p->badgraduser, 0, 0, DT_REAL, _state, make_automatic);
21516 498 : ae_matrix_init(&p->badgradnum, 0, 0, DT_REAL, _state, make_automatic);
21517 498 : }
21518 :
21519 :
21520 0 : void _optguardreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
21521 : {
21522 0 : optguardreport *dst = (optguardreport*)_dst;
21523 0 : optguardreport *src = (optguardreport*)_src;
21524 0 : dst->nonc0suspected = src->nonc0suspected;
21525 0 : dst->nonc0test0positive = src->nonc0test0positive;
21526 0 : dst->nonc0fidx = src->nonc0fidx;
21527 0 : dst->nonc0lipschitzc = src->nonc0lipschitzc;
21528 0 : dst->nonc1suspected = src->nonc1suspected;
21529 0 : dst->nonc1test0positive = src->nonc1test0positive;
21530 0 : dst->nonc1test1positive = src->nonc1test1positive;
21531 0 : dst->nonc1fidx = src->nonc1fidx;
21532 0 : dst->nonc1lipschitzc = src->nonc1lipschitzc;
21533 0 : dst->badgradsuspected = src->badgradsuspected;
21534 0 : dst->badgradfidx = src->badgradfidx;
21535 0 : dst->badgradvidx = src->badgradvidx;
21536 0 : ae_vector_init_copy(&dst->badgradxbase, &src->badgradxbase, _state, make_automatic);
21537 0 : ae_matrix_init_copy(&dst->badgraduser, &src->badgraduser, _state, make_automatic);
21538 0 : ae_matrix_init_copy(&dst->badgradnum, &src->badgradnum, _state, make_automatic);
21539 0 : }
21540 :
21541 :
21542 498 : void _optguardreport_clear(void* _p)
21543 : {
21544 498 : optguardreport *p = (optguardreport*)_p;
21545 498 : ae_touch_ptr((void*)p);
21546 498 : ae_vector_clear(&p->badgradxbase);
21547 498 : ae_matrix_clear(&p->badgraduser);
21548 498 : ae_matrix_clear(&p->badgradnum);
21549 498 : }
21550 :
21551 :
21552 498 : void _optguardreport_destroy(void* _p)
21553 : {
21554 498 : optguardreport *p = (optguardreport*)_p;
21555 498 : ae_touch_ptr((void*)p);
21556 498 : ae_vector_destroy(&p->badgradxbase);
21557 498 : ae_matrix_destroy(&p->badgraduser);
21558 498 : ae_matrix_destroy(&p->badgradnum);
21559 498 : }
21560 :
21561 :
21562 996 : void _optguardnonc0report_init(void* _p, ae_state *_state, ae_bool make_automatic)
21563 : {
21564 996 : optguardnonc0report *p = (optguardnonc0report*)_p;
21565 996 : ae_touch_ptr((void*)p);
21566 996 : ae_vector_init(&p->x0, 0, DT_REAL, _state, make_automatic);
21567 996 : ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic);
21568 996 : ae_vector_init(&p->stp, 0, DT_REAL, _state, make_automatic);
21569 996 : ae_vector_init(&p->f, 0, DT_REAL, _state, make_automatic);
21570 996 : }
21571 :
21572 :
21573 0 : void _optguardnonc0report_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
21574 : {
21575 0 : optguardnonc0report *dst = (optguardnonc0report*)_dst;
21576 0 : optguardnonc0report *src = (optguardnonc0report*)_src;
21577 0 : dst->positive = src->positive;
21578 0 : dst->fidx = src->fidx;
21579 0 : ae_vector_init_copy(&dst->x0, &src->x0, _state, make_automatic);
21580 0 : ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic);
21581 0 : dst->n = src->n;
21582 0 : ae_vector_init_copy(&dst->stp, &src->stp, _state, make_automatic);
21583 0 : ae_vector_init_copy(&dst->f, &src->f, _state, make_automatic);
21584 0 : dst->cnt = src->cnt;
21585 0 : dst->stpidxa = src->stpidxa;
21586 0 : dst->stpidxb = src->stpidxb;
21587 0 : }
21588 :
21589 :
21590 996 : void _optguardnonc0report_clear(void* _p)
21591 : {
21592 996 : optguardnonc0report *p = (optguardnonc0report*)_p;
21593 996 : ae_touch_ptr((void*)p);
21594 996 : ae_vector_clear(&p->x0);
21595 996 : ae_vector_clear(&p->d);
21596 996 : ae_vector_clear(&p->stp);
21597 996 : ae_vector_clear(&p->f);
21598 996 : }
21599 :
21600 :
21601 996 : void _optguardnonc0report_destroy(void* _p)
21602 : {
21603 996 : optguardnonc0report *p = (optguardnonc0report*)_p;
21604 996 : ae_touch_ptr((void*)p);
21605 996 : ae_vector_destroy(&p->x0);
21606 996 : ae_vector_destroy(&p->d);
21607 996 : ae_vector_destroy(&p->stp);
21608 996 : ae_vector_destroy(&p->f);
21609 996 : }
21610 :
21611 :
21612 996 : void _optguardnonc1test0report_init(void* _p, ae_state *_state, ae_bool make_automatic)
21613 : {
21614 996 : optguardnonc1test0report *p = (optguardnonc1test0report*)_p;
21615 996 : ae_touch_ptr((void*)p);
21616 996 : ae_vector_init(&p->x0, 0, DT_REAL, _state, make_automatic);
21617 996 : ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic);
21618 996 : ae_vector_init(&p->stp, 0, DT_REAL, _state, make_automatic);
21619 996 : ae_vector_init(&p->f, 0, DT_REAL, _state, make_automatic);
21620 996 : }
21621 :
21622 :
21623 0 : void _optguardnonc1test0report_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
21624 : {
21625 0 : optguardnonc1test0report *dst = (optguardnonc1test0report*)_dst;
21626 0 : optguardnonc1test0report *src = (optguardnonc1test0report*)_src;
21627 0 : dst->positive = src->positive;
21628 0 : dst->fidx = src->fidx;
21629 0 : ae_vector_init_copy(&dst->x0, &src->x0, _state, make_automatic);
21630 0 : ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic);
21631 0 : dst->n = src->n;
21632 0 : ae_vector_init_copy(&dst->stp, &src->stp, _state, make_automatic);
21633 0 : ae_vector_init_copy(&dst->f, &src->f, _state, make_automatic);
21634 0 : dst->cnt = src->cnt;
21635 0 : dst->stpidxa = src->stpidxa;
21636 0 : dst->stpidxb = src->stpidxb;
21637 0 : }
21638 :
21639 :
21640 996 : void _optguardnonc1test0report_clear(void* _p)
21641 : {
21642 996 : optguardnonc1test0report *p = (optguardnonc1test0report*)_p;
21643 996 : ae_touch_ptr((void*)p);
21644 996 : ae_vector_clear(&p->x0);
21645 996 : ae_vector_clear(&p->d);
21646 996 : ae_vector_clear(&p->stp);
21647 996 : ae_vector_clear(&p->f);
21648 996 : }
21649 :
21650 :
21651 996 : void _optguardnonc1test0report_destroy(void* _p)
21652 : {
21653 996 : optguardnonc1test0report *p = (optguardnonc1test0report*)_p;
21654 996 : ae_touch_ptr((void*)p);
21655 996 : ae_vector_destroy(&p->x0);
21656 996 : ae_vector_destroy(&p->d);
21657 996 : ae_vector_destroy(&p->stp);
21658 996 : ae_vector_destroy(&p->f);
21659 996 : }
21660 :
21661 :
21662 996 : void _optguardnonc1test1report_init(void* _p, ae_state *_state, ae_bool make_automatic)
21663 : {
21664 996 : optguardnonc1test1report *p = (optguardnonc1test1report*)_p;
21665 996 : ae_touch_ptr((void*)p);
21666 996 : ae_vector_init(&p->x0, 0, DT_REAL, _state, make_automatic);
21667 996 : ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic);
21668 996 : ae_vector_init(&p->stp, 0, DT_REAL, _state, make_automatic);
21669 996 : ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic);
21670 996 : }
21671 :
21672 :
21673 0 : void _optguardnonc1test1report_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
21674 : {
21675 0 : optguardnonc1test1report *dst = (optguardnonc1test1report*)_dst;
21676 0 : optguardnonc1test1report *src = (optguardnonc1test1report*)_src;
21677 0 : dst->positive = src->positive;
21678 0 : dst->fidx = src->fidx;
21679 0 : dst->vidx = src->vidx;
21680 0 : ae_vector_init_copy(&dst->x0, &src->x0, _state, make_automatic);
21681 0 : ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic);
21682 0 : dst->n = src->n;
21683 0 : ae_vector_init_copy(&dst->stp, &src->stp, _state, make_automatic);
21684 0 : ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic);
21685 0 : dst->cnt = src->cnt;
21686 0 : dst->stpidxa = src->stpidxa;
21687 0 : dst->stpidxb = src->stpidxb;
21688 0 : }
21689 :
21690 :
21691 996 : void _optguardnonc1test1report_clear(void* _p)
21692 : {
21693 996 : optguardnonc1test1report *p = (optguardnonc1test1report*)_p;
21694 996 : ae_touch_ptr((void*)p);
21695 996 : ae_vector_clear(&p->x0);
21696 996 : ae_vector_clear(&p->d);
21697 996 : ae_vector_clear(&p->stp);
21698 996 : ae_vector_clear(&p->g);
21699 996 : }
21700 :
21701 :
21702 996 : void _optguardnonc1test1report_destroy(void* _p)
21703 : {
21704 996 : optguardnonc1test1report *p = (optguardnonc1test1report*)_p;
21705 996 : ae_touch_ptr((void*)p);
21706 996 : ae_vector_destroy(&p->x0);
21707 996 : ae_vector_destroy(&p->d);
21708 996 : ae_vector_destroy(&p->stp);
21709 996 : ae_vector_destroy(&p->g);
21710 996 : }
21711 :
21712 :
21713 : #endif
21714 : #if defined(AE_COMPILE_OPTSERV) || !defined(AE_PARTIAL_BUILD)
21715 :
21716 :
21717 : /*************************************************************************
21718 : This subroutine checks violation of the box constraints. On output it sets
21719 : bcerr to the maximum scaled violation, bcidx to the index of the violating
21720 : constraint.
21721 :
21722 : if bcerr=0 (say, if no constraints are violated) then bcidx=-1.
21723 :
21724 : If nonunits=false then s[] is not referenced at all (assumed unit).
21725 :
21726 : -- ALGLIB --
21727 : Copyright 7.11.2018 by Bochkanov Sergey
21728 : *************************************************************************/
21729 0 : void checkbcviolation(/* Boolean */ ae_vector* hasbndl,
21730 : /* Real */ ae_vector* bndl,
21731 : /* Boolean */ ae_vector* hasbndu,
21732 : /* Real */ ae_vector* bndu,
21733 : /* Real */ ae_vector* x,
21734 : ae_int_t n,
21735 : /* Real */ ae_vector* s,
21736 : ae_bool nonunits,
21737 : double* bcerr,
21738 : ae_int_t* bcidx,
21739 : ae_state *_state)
21740 : {
21741 : ae_int_t i;
21742 : double vs;
21743 : double ve;
21744 :
21745 0 : *bcerr = 0;
21746 0 : *bcidx = 0;
21747 :
21748 0 : *bcerr = (double)(0);
21749 0 : *bcidx = -1;
21750 0 : for(i=0; i<=n-1; i++)
21751 : {
21752 :
21753 : /*
21754 : * Fetch scale
21755 : */
21756 0 : if( nonunits )
21757 : {
21758 0 : vs = 1/s->ptr.p_double[i];
21759 : }
21760 : else
21761 : {
21762 0 : vs = (double)(1);
21763 : }
21764 :
21765 : /*
21766 : * Check lower bound
21767 : */
21768 0 : if( hasbndl->ptr.p_bool[i]&&x->ptr.p_double[i]<bndl->ptr.p_double[i] )
21769 : {
21770 0 : ve = (bndl->ptr.p_double[i]-x->ptr.p_double[i])*vs;
21771 0 : if( ve>*bcerr )
21772 : {
21773 0 : *bcerr = ve;
21774 0 : *bcidx = i;
21775 : }
21776 : }
21777 :
21778 : /*
21779 : * Check upper bound
21780 : */
21781 0 : if( hasbndu->ptr.p_bool[i]&&x->ptr.p_double[i]>bndu->ptr.p_double[i] )
21782 : {
21783 0 : ve = (x->ptr.p_double[i]-bndu->ptr.p_double[i])*vs;
21784 0 : if( ve>*bcerr )
21785 : {
21786 0 : *bcerr = ve;
21787 0 : *bcidx = i;
21788 : }
21789 : }
21790 : }
21791 0 : }
21792 :
21793 :
21794 : /*************************************************************************
21795 : This subroutine checks violation of the general linear constraints.
21796 :
21797 : Constraints are assumed to be un-normalized and stored in the format "NEC
21798 : equality ones followed by NIC inequality ones".
21799 :
21800 : On output it sets lcerr to the maximum scaled violation, lcidx to the source
21801 : index of the most violating constraint (row indexes of CLEIC are mapped to
21802 : the indexes of the "original" constraints via LCSrcIdx[] array.
21803 :
21804 : if lcerr=0 (say, if no constraints are violated) then lcidx=-1.
21805 :
21806 : If nonunits=false then s[] is not referenced at all (assumed unit).
21807 :
21808 : -- ALGLIB --
21809 : Copyright 7.11.2018 by Bochkanov Sergey
21810 : *************************************************************************/
21811 0 : void checklcviolation(/* Real */ ae_matrix* cleic,
21812 : /* Integer */ ae_vector* lcsrcidx,
21813 : ae_int_t nec,
21814 : ae_int_t nic,
21815 : /* Real */ ae_vector* x,
21816 : ae_int_t n,
21817 : double* lcerr,
21818 : ae_int_t* lcidx,
21819 : ae_state *_state)
21820 : {
21821 : ae_int_t i;
21822 : ae_int_t j;
21823 : double cx;
21824 : double cnrm;
21825 : double v;
21826 :
21827 0 : *lcerr = 0;
21828 0 : *lcidx = 0;
21829 :
21830 0 : *lcerr = (double)(0);
21831 0 : *lcidx = -1;
21832 0 : for(i=0; i<=nec+nic-1; i++)
21833 : {
21834 0 : cx = -cleic->ptr.pp_double[i][n];
21835 0 : cnrm = (double)(0);
21836 0 : for(j=0; j<=n-1; j++)
21837 : {
21838 0 : v = cleic->ptr.pp_double[i][j];
21839 0 : cx = cx+v*x->ptr.p_double[j];
21840 0 : cnrm = cnrm+v*v;
21841 : }
21842 0 : cnrm = ae_sqrt(cnrm, _state);
21843 0 : cx = cx/coalesce(cnrm, (double)(1), _state);
21844 0 : if( i<nec )
21845 : {
21846 0 : cx = ae_fabs(cx, _state);
21847 : }
21848 : else
21849 : {
21850 0 : cx = ae_maxreal(cx, (double)(0), _state);
21851 : }
21852 0 : if( cx>*lcerr )
21853 : {
21854 0 : *lcerr = cx;
21855 0 : *lcidx = lcsrcidx->ptr.p_int[i];
21856 : }
21857 : }
21858 0 : }
21859 :
21860 :
21861 : /*************************************************************************
21862 : This subroutine checks violation of the nonlinear constraints. Fi[0] is the
21863 : target value (ignored), Fi[1:NG+NH] are values of nonlinear constraints.
21864 :
21865 : On output it sets nlcerr to the scaled violation, nlcidx to the index
21866 : of the most violating constraint in [0,NG+NH-1] range.
21867 :
21868 : if nlcerr=0 (say, if no constraints are violated) then nlcidx=-1.
21869 :
21870 : If nonunits=false then s[] is not referenced at all (assumed unit).
21871 :
21872 : -- ALGLIB --
21873 : Copyright 7.11.2018 by Bochkanov Sergey
21874 : *************************************************************************/
21875 0 : void checknlcviolation(/* Real */ ae_vector* fi,
21876 : ae_int_t ng,
21877 : ae_int_t nh,
21878 : double* nlcerr,
21879 : ae_int_t* nlcidx,
21880 : ae_state *_state)
21881 : {
21882 : ae_int_t i;
21883 : double v;
21884 :
21885 0 : *nlcerr = 0;
21886 0 : *nlcidx = 0;
21887 :
21888 0 : *nlcerr = (double)(0);
21889 0 : *nlcidx = -1;
21890 0 : for(i=0; i<=ng+nh-1; i++)
21891 : {
21892 0 : v = fi->ptr.p_double[i+1];
21893 0 : if( i<ng )
21894 : {
21895 0 : v = ae_fabs(v, _state);
21896 : }
21897 : else
21898 : {
21899 0 : v = ae_maxreal(v, (double)(0), _state);
21900 : }
21901 0 : if( v>*nlcerr )
21902 : {
21903 0 : *nlcerr = v;
21904 0 : *nlcidx = i;
21905 : }
21906 : }
21907 0 : }
21908 :
21909 :
21910 : /*************************************************************************
21911 : This subroutine is same as CheckNLCViolation, but is works with scaled
21912 : constraints: it assumes that Fi[] were divided by FScales[] vector BEFORE
21913 : passing them to this function.
21914 :
21915 : The function checks scaled values, but reports unscaled errors.
21916 :
21917 : -- ALGLIB --
21918 : Copyright 7.11.2018 by Bochkanov Sergey
21919 : *************************************************************************/
21920 0 : void unscaleandchecknlcviolation(/* Real */ ae_vector* fi,
21921 : /* Real */ ae_vector* fscales,
21922 : ae_int_t ng,
21923 : ae_int_t nh,
21924 : double* nlcerr,
21925 : ae_int_t* nlcidx,
21926 : ae_state *_state)
21927 : {
21928 : ae_int_t i;
21929 : double v;
21930 :
21931 0 : *nlcerr = 0;
21932 0 : *nlcidx = 0;
21933 :
21934 0 : *nlcerr = (double)(0);
21935 0 : *nlcidx = -1;
21936 0 : for(i=0; i<=ng+nh-1; i++)
21937 : {
21938 0 : ae_assert(ae_fp_greater(fscales->ptr.p_double[i+1],(double)(0)), "UnscaleAndCheckNLCViolation: integrity check failed", _state);
21939 0 : v = fi->ptr.p_double[i+1]*fscales->ptr.p_double[i+1];
21940 0 : if( i<ng )
21941 : {
21942 0 : v = ae_fabs(v, _state);
21943 : }
21944 : else
21945 : {
21946 0 : v = ae_maxreal(v, (double)(0), _state);
21947 : }
21948 0 : if( v>*nlcerr )
21949 : {
21950 0 : *nlcerr = v;
21951 0 : *nlcidx = i;
21952 : }
21953 : }
21954 0 : }
21955 :
21956 :
21957 : /*************************************************************************
21958 : This subroutine is used to prepare threshold value which will be used for
21959 : trimming of the target function (see comments on TrimFunction() for more
21960 : information).
21961 :
21962 : This function accepts only one parameter: function value at the starting
21963 : point. It returns threshold which will be used for trimming.
21964 :
21965 : -- ALGLIB --
21966 : Copyright 10.05.2011 by Bochkanov Sergey
21967 : *************************************************************************/
21968 498 : void trimprepare(double f, double* threshold, ae_state *_state)
21969 : {
21970 :
21971 498 : *threshold = 0;
21972 :
21973 498 : *threshold = 10*(ae_fabs(f, _state)+1);
21974 498 : }
21975 :
21976 :
21977 : /*************************************************************************
21978 : This subroutine is used to "trim" target function, i.e. to do following
21979 : transformation:
21980 :
21981 : { {F,G} if F<Threshold
21982 : {F_tr, G_tr} = {
21983 : { {Threshold, 0} if F>=Threshold
21984 :
21985 : Such transformation allows us to solve problems with singularities by
21986 : redefining function in such way that it becomes bounded from above.
21987 :
21988 : -- ALGLIB --
21989 : Copyright 10.05.2011 by Bochkanov Sergey
21990 : *************************************************************************/
21991 4391 : void trimfunction(double* f,
21992 : /* Real */ ae_vector* g,
21993 : ae_int_t n,
21994 : double threshold,
21995 : ae_state *_state)
21996 : {
21997 : ae_int_t i;
21998 :
21999 :
22000 4391 : if( ae_fp_greater_eq(*f,threshold) )
22001 : {
22002 104 : *f = threshold;
22003 312 : for(i=0; i<=n-1; i++)
22004 : {
22005 208 : g->ptr.p_double[i] = 0.0;
22006 : }
22007 : }
22008 4391 : }
22009 :
22010 :
22011 : /*************************************************************************
22012 : This function enforces boundary constraints in the X.
22013 :
22014 : This function correctly (although a bit inefficient) handles BL[i] which
22015 : are -INF and BU[i] which are +INF.
22016 :
22017 : We have NMain+NSlack dimensional X, with first NMain components bounded
22018 : by BL/BU, and next NSlack ones bounded by non-negativity constraints.
22019 :
22020 : INPUT PARAMETERS
22021 : X - array[NMain+NSlack], point
22022 : BL - array[NMain], lower bounds
22023 : (may contain -INF, when bound is not present)
22024 : HaveBL - array[NMain], if HaveBL[i] is False,
22025 : then i-th bound is not present
22026 : BU - array[NMain], upper bounds
22027 : (may contain +INF, when bound is not present)
22028 : HaveBU - array[NMain], if HaveBU[i] is False,
22029 : then i-th bound is not present
22030 :
22031 : OUTPUT PARAMETERS
22032 : X - X with all constraints being enforced
22033 :
22034 : It returns True when constraints are consistent,
22035 : False - when constraints are inconsistent.
22036 :
22037 : -- ALGLIB --
22038 : Copyright 10.01.2012 by Bochkanov Sergey
22039 : *************************************************************************/
22040 0 : ae_bool enforceboundaryconstraints(/* Real */ ae_vector* x,
22041 : /* Real */ ae_vector* bl,
22042 : /* Boolean */ ae_vector* havebl,
22043 : /* Real */ ae_vector* bu,
22044 : /* Boolean */ ae_vector* havebu,
22045 : ae_int_t nmain,
22046 : ae_int_t nslack,
22047 : ae_state *_state)
22048 : {
22049 : ae_int_t i;
22050 : ae_bool result;
22051 :
22052 :
22053 0 : result = ae_false;
22054 0 : for(i=0; i<=nmain-1; i++)
22055 : {
22056 0 : if( (havebl->ptr.p_bool[i]&&havebu->ptr.p_bool[i])&&ae_fp_greater(bl->ptr.p_double[i],bu->ptr.p_double[i]) )
22057 : {
22058 0 : return result;
22059 : }
22060 0 : if( havebl->ptr.p_bool[i]&&ae_fp_less(x->ptr.p_double[i],bl->ptr.p_double[i]) )
22061 : {
22062 0 : x->ptr.p_double[i] = bl->ptr.p_double[i];
22063 : }
22064 0 : if( havebu->ptr.p_bool[i]&&ae_fp_greater(x->ptr.p_double[i],bu->ptr.p_double[i]) )
22065 : {
22066 0 : x->ptr.p_double[i] = bu->ptr.p_double[i];
22067 : }
22068 : }
22069 0 : for(i=0; i<=nslack-1; i++)
22070 : {
22071 0 : if( ae_fp_less(x->ptr.p_double[nmain+i],(double)(0)) )
22072 : {
22073 0 : x->ptr.p_double[nmain+i] = (double)(0);
22074 : }
22075 : }
22076 0 : result = ae_true;
22077 0 : return result;
22078 : }
22079 :
22080 :
22081 : /*************************************************************************
22082 : This function projects gradient into feasible area of boundary constrained
22083 : optimization problem. X can be infeasible with respect to boundary
22084 : constraints. We have NMain+NSlack dimensional X, with first NMain
22085 : components bounded by BL/BU, and next NSlack ones bounded by non-negativity
22086 : constraints.
22087 :
22088 : INPUT PARAMETERS
22089 : X - array[NMain+NSlack], point
22090 : G - array[NMain+NSlack], gradient
22091 : BL - lower bounds (may contain -INF, when bound is not present)
22092 : HaveBL - if HaveBL[i] is False, then i-th bound is not present
22093 : BU - upper bounds (may contain +INF, when bound is not present)
22094 : HaveBU - if HaveBU[i] is False, then i-th bound is not present
22095 :
22096 : OUTPUT PARAMETERS
22097 : G - projection of G. Components of G which satisfy one of the
22098 : following
22099 : (1) (X[I]<=BndL[I]) and (G[I]>0), OR
22100 : (2) (X[I]>=BndU[I]) and (G[I]<0)
22101 : are replaced by zeros.
22102 :
22103 : NOTE 1: this function assumes that constraints are feasible. It throws
22104 : exception otherwise.
22105 :
22106 : NOTE 2: in fact, projection of ANTI-gradient is calculated, because this
22107 : function trims components of -G which points outside of the feasible area.
22108 : However, working with -G is considered confusing, because all optimization
22109 : source work with G.
22110 :
22111 : -- ALGLIB --
22112 : Copyright 10.01.2012 by Bochkanov Sergey
22113 : *************************************************************************/
22114 0 : void projectgradientintobc(/* Real */ ae_vector* x,
22115 : /* Real */ ae_vector* g,
22116 : /* Real */ ae_vector* bl,
22117 : /* Boolean */ ae_vector* havebl,
22118 : /* Real */ ae_vector* bu,
22119 : /* Boolean */ ae_vector* havebu,
22120 : ae_int_t nmain,
22121 : ae_int_t nslack,
22122 : ae_state *_state)
22123 : {
22124 : ae_int_t i;
22125 :
22126 :
22127 0 : for(i=0; i<=nmain-1; i++)
22128 : {
22129 0 : 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);
22130 0 : 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],(double)(0)) )
22131 : {
22132 0 : g->ptr.p_double[i] = (double)(0);
22133 : }
22134 0 : 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],(double)(0)) )
22135 : {
22136 0 : g->ptr.p_double[i] = (double)(0);
22137 : }
22138 : }
22139 0 : for(i=0; i<=nslack-1; i++)
22140 : {
22141 0 : if( ae_fp_less_eq(x->ptr.p_double[nmain+i],(double)(0))&&ae_fp_greater(g->ptr.p_double[nmain+i],(double)(0)) )
22142 : {
22143 0 : g->ptr.p_double[nmain+i] = (double)(0);
22144 : }
22145 : }
22146 0 : }
22147 :
22148 :
22149 : /*************************************************************************
22150 : Given
22151 : a) initial point X0[NMain+NSlack]
22152 : (feasible with respect to bound constraints)
22153 : b) step vector alpha*D[NMain+NSlack]
22154 : c) boundary constraints BndL[NMain], BndU[NMain]
22155 : d) implicit non-negativity constraints for slack variables
22156 : this function calculates bound on the step length subject to boundary
22157 : constraints.
22158 :
22159 : It returns:
22160 : * MaxStepLen - such step length that X0+MaxStepLen*alpha*D is exactly
22161 : at the boundary given by constraints
22162 : * VariableToFreeze - index of the constraint to be activated,
22163 : 0 <= VariableToFreeze < NMain+NSlack
22164 : * ValueToFreeze - value of the corresponding constraint.
22165 :
22166 : Notes:
22167 : * it is possible that several constraints can be activated by the step
22168 : at once. In such cases only one constraint is returned. It is caller
22169 : responsibility to check other constraints. This function makes sure
22170 : that we activate at least one constraint, and everything else is the
22171 : responsibility of the caller.
22172 : * steps smaller than MaxStepLen still can activate constraints due to
22173 : numerical errors. Thus purpose of this function is not to guard
22174 : against accidental activation of the constraints - quite the reverse,
22175 : its purpose is to activate at least constraint upon performing step
22176 : which is too long.
22177 : * in case there is no constraints to activate, we return negative
22178 : VariableToFreeze and zero MaxStepLen and ValueToFreeze.
22179 : * this function assumes that constraints are consistent; it throws
22180 : exception otherwise.
22181 :
22182 : INPUT PARAMETERS
22183 : X - array[NMain+NSlack], point. Must be feasible with respect
22184 : to bound constraints (exception will be thrown otherwise)
22185 : D - array[NMain+NSlack], step direction
22186 : alpha - scalar multiplier before D, alpha<>0
22187 : BndL - lower bounds, array[NMain]
22188 : (may contain -INF, when bound is not present)
22189 : HaveBndL - array[NMain], if HaveBndL[i] is False,
22190 : then i-th bound is not present
22191 : BndU - array[NMain], upper bounds
22192 : (may contain +INF, when bound is not present)
22193 : HaveBndU - array[NMain], if HaveBndU[i] is False,
22194 : then i-th bound is not present
22195 : NMain - number of main variables
22196 : NSlack - number of slack variables
22197 :
22198 : OUTPUT PARAMETERS
22199 : VariableToFreeze:
22200 : * negative value = step is unbounded, ValueToFreeze=0,
22201 : MaxStepLen=0.
22202 : * non-negative value = at least one constraint, given by
22203 : this parameter, will be activated
22204 : upon performing maximum step.
22205 : ValueToFreeze- value of the variable which will be constrained
22206 : MaxStepLen - maximum length of the step. Can be zero when step vector
22207 : looks outside of the feasible area.
22208 :
22209 : -- ALGLIB --
22210 : Copyright 10.01.2012 by Bochkanov Sergey
22211 : *************************************************************************/
22212 0 : void calculatestepbound(/* Real */ ae_vector* x,
22213 : /* Real */ ae_vector* d,
22214 : double alpha,
22215 : /* Real */ ae_vector* bndl,
22216 : /* Boolean */ ae_vector* havebndl,
22217 : /* Real */ ae_vector* bndu,
22218 : /* Boolean */ ae_vector* havebndu,
22219 : ae_int_t nmain,
22220 : ae_int_t nslack,
22221 : ae_int_t* variabletofreeze,
22222 : double* valuetofreeze,
22223 : double* maxsteplen,
22224 : ae_state *_state)
22225 : {
22226 : ae_int_t i;
22227 : double prevmax;
22228 : double initval;
22229 :
22230 0 : *variabletofreeze = 0;
22231 0 : *valuetofreeze = 0;
22232 0 : *maxsteplen = 0;
22233 :
22234 0 : ae_assert(ae_fp_neq(alpha,(double)(0)), "CalculateStepBound: zero alpha", _state);
22235 0 : *variabletofreeze = -1;
22236 0 : initval = ae_maxrealnumber;
22237 0 : *maxsteplen = initval;
22238 0 : for(i=0; i<=nmain-1; i++)
22239 : {
22240 0 : if( havebndl->ptr.p_bool[i]&&ae_fp_less(alpha*d->ptr.p_double[i],(double)(0)) )
22241 : {
22242 0 : ae_assert(ae_fp_greater_eq(x->ptr.p_double[i],bndl->ptr.p_double[i]), "CalculateStepBound: infeasible X", _state);
22243 0 : prevmax = *maxsteplen;
22244 0 : *maxsteplen = safeminposrv(x->ptr.p_double[i]-bndl->ptr.p_double[i], -alpha*d->ptr.p_double[i], *maxsteplen, _state);
22245 0 : if( ae_fp_less(*maxsteplen,prevmax) )
22246 : {
22247 0 : *variabletofreeze = i;
22248 0 : *valuetofreeze = bndl->ptr.p_double[i];
22249 : }
22250 : }
22251 0 : if( havebndu->ptr.p_bool[i]&&ae_fp_greater(alpha*d->ptr.p_double[i],(double)(0)) )
22252 : {
22253 0 : ae_assert(ae_fp_less_eq(x->ptr.p_double[i],bndu->ptr.p_double[i]), "CalculateStepBound: infeasible X", _state);
22254 0 : prevmax = *maxsteplen;
22255 0 : *maxsteplen = safeminposrv(bndu->ptr.p_double[i]-x->ptr.p_double[i], alpha*d->ptr.p_double[i], *maxsteplen, _state);
22256 0 : if( ae_fp_less(*maxsteplen,prevmax) )
22257 : {
22258 0 : *variabletofreeze = i;
22259 0 : *valuetofreeze = bndu->ptr.p_double[i];
22260 : }
22261 : }
22262 : }
22263 0 : for(i=0; i<=nslack-1; i++)
22264 : {
22265 0 : if( ae_fp_less(alpha*d->ptr.p_double[nmain+i],(double)(0)) )
22266 : {
22267 0 : ae_assert(ae_fp_greater_eq(x->ptr.p_double[nmain+i],(double)(0)), "CalculateStepBound: infeasible X", _state);
22268 0 : prevmax = *maxsteplen;
22269 0 : *maxsteplen = safeminposrv(x->ptr.p_double[nmain+i], -alpha*d->ptr.p_double[nmain+i], *maxsteplen, _state);
22270 0 : if( ae_fp_less(*maxsteplen,prevmax) )
22271 : {
22272 0 : *variabletofreeze = nmain+i;
22273 0 : *valuetofreeze = (double)(0);
22274 : }
22275 : }
22276 : }
22277 0 : if( ae_fp_eq(*maxsteplen,initval) )
22278 : {
22279 0 : *valuetofreeze = (double)(0);
22280 0 : *maxsteplen = (double)(0);
22281 : }
22282 0 : }
22283 :
22284 :
22285 : /*************************************************************************
22286 : This function postprocesses bounded step by:
22287 : * analysing step length (whether it is equal to MaxStepLen) and activating
22288 : constraint given by VariableToFreeze if needed
22289 : * checking for additional bound constraints to activate
22290 :
22291 : This function uses final point of the step, quantities calculated by the
22292 : CalculateStepBound() function. As result, it returns point which is
22293 : exactly feasible with respect to boundary constraints.
22294 :
22295 : NOTE 1: this function does NOT handle and check linear equality constraints
22296 : NOTE 2: when StepTaken=MaxStepLen we always activate at least one constraint
22297 :
22298 : INPUT PARAMETERS
22299 : X - array[NMain+NSlack], final point to postprocess
22300 : XPrev - array[NMain+NSlack], initial point
22301 : BndL - lower bounds, array[NMain]
22302 : (may contain -INF, when bound is not present)
22303 : HaveBndL - array[NMain], if HaveBndL[i] is False,
22304 : then i-th bound is not present
22305 : BndU - array[NMain], upper bounds
22306 : (may contain +INF, when bound is not present)
22307 : HaveBndU - array[NMain], if HaveBndU[i] is False,
22308 : then i-th bound is not present
22309 : NMain - number of main variables
22310 : NSlack - number of slack variables
22311 : VariableToFreeze-result of CalculateStepBound()
22312 : ValueToFreeze- result of CalculateStepBound()
22313 : StepTaken - actual step length (actual step is equal to the possibly
22314 : non-unit step direction vector times this parameter).
22315 : StepTaken<=MaxStepLen.
22316 : MaxStepLen - result of CalculateStepBound()
22317 :
22318 : OUTPUT PARAMETERS
22319 : X - point bounded with respect to constraints.
22320 : components corresponding to active constraints are exactly
22321 : equal to the boundary values.
22322 :
22323 : RESULT:
22324 : number of constraints activated in addition to previously active ones.
22325 : Constraints which were DEACTIVATED are ignored (do not influence
22326 : function value).
22327 :
22328 : -- ALGLIB --
22329 : Copyright 10.01.2012 by Bochkanov Sergey
22330 : *************************************************************************/
22331 0 : ae_int_t postprocessboundedstep(/* Real */ ae_vector* x,
22332 : /* Real */ ae_vector* xprev,
22333 : /* Real */ ae_vector* bndl,
22334 : /* Boolean */ ae_vector* havebndl,
22335 : /* Real */ ae_vector* bndu,
22336 : /* Boolean */ ae_vector* havebndu,
22337 : ae_int_t nmain,
22338 : ae_int_t nslack,
22339 : ae_int_t variabletofreeze,
22340 : double valuetofreeze,
22341 : double steptaken,
22342 : double maxsteplen,
22343 : ae_state *_state)
22344 : {
22345 : ae_int_t i;
22346 : ae_bool wasactivated;
22347 : ae_int_t result;
22348 :
22349 :
22350 0 : ae_assert(variabletofreeze<0||ae_fp_less_eq(steptaken,maxsteplen), "Assertion failed", _state);
22351 :
22352 : /*
22353 : * Activate constraints
22354 : */
22355 0 : if( variabletofreeze>=0&&ae_fp_eq(steptaken,maxsteplen) )
22356 : {
22357 0 : x->ptr.p_double[variabletofreeze] = valuetofreeze;
22358 : }
22359 0 : for(i=0; i<=nmain-1; i++)
22360 : {
22361 0 : if( havebndl->ptr.p_bool[i]&&ae_fp_less(x->ptr.p_double[i],bndl->ptr.p_double[i]) )
22362 : {
22363 0 : x->ptr.p_double[i] = bndl->ptr.p_double[i];
22364 : }
22365 0 : if( havebndu->ptr.p_bool[i]&&ae_fp_greater(x->ptr.p_double[i],bndu->ptr.p_double[i]) )
22366 : {
22367 0 : x->ptr.p_double[i] = bndu->ptr.p_double[i];
22368 : }
22369 : }
22370 0 : for(i=0; i<=nslack-1; i++)
22371 : {
22372 0 : if( ae_fp_less_eq(x->ptr.p_double[nmain+i],(double)(0)) )
22373 : {
22374 0 : x->ptr.p_double[nmain+i] = (double)(0);
22375 : }
22376 : }
22377 :
22378 : /*
22379 : * Calculate number of constraints being activated
22380 : */
22381 0 : result = 0;
22382 0 : for(i=0; i<=nmain-1; i++)
22383 : {
22384 0 : 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])));
22385 0 : wasactivated = wasactivated||variabletofreeze==i;
22386 0 : if( wasactivated )
22387 : {
22388 0 : result = result+1;
22389 : }
22390 : }
22391 0 : for(i=0; i<=nslack-1; i++)
22392 : {
22393 0 : 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);
22394 0 : wasactivated = wasactivated||variabletofreeze==nmain+i;
22395 0 : if( wasactivated )
22396 : {
22397 0 : result = result+1;
22398 : }
22399 : }
22400 0 : return result;
22401 : }
22402 :
22403 :
22404 : /*************************************************************************
22405 : The purpose of this function is to prevent algorithm from "unsticking"
22406 : from the active bound constraints because of numerical noise in the
22407 : gradient or Hessian.
22408 :
22409 : It is done by zeroing some components of the search direction D. D[i] is
22410 : zeroed when both (a) and (b) are true:
22411 : a) corresponding X[i] is exactly at the boundary
22412 : b) |D[i]*S[i]| <= DropTol*Sqrt(SUM(D[i]^2*S[I]^2))
22413 :
22414 : D can be step direction , antigradient, gradient, or anything similar.
22415 : Sign of D does not matter, nor matters step length.
22416 :
22417 : NOTE 1: boundary constraints are expected to be consistent, as well as X
22418 : is expected to be feasible. Exception will be thrown otherwise.
22419 :
22420 : INPUT PARAMETERS
22421 : D - array[NMain+NSlack], direction
22422 : X - array[NMain+NSlack], current point
22423 : BndL - lower bounds, array[NMain]
22424 : (may contain -INF, when bound is not present)
22425 : HaveBndL - array[NMain], if HaveBndL[i] is False,
22426 : then i-th bound is not present
22427 : BndU - array[NMain], upper bounds
22428 : (may contain +INF, when bound is not present)
22429 : HaveBndU - array[NMain], if HaveBndU[i] is False,
22430 : then i-th bound is not present
22431 : S - array[NMain+NSlack], scaling of the variables
22432 : NMain - number of main variables
22433 : NSlack - number of slack variables
22434 : DropTol - drop tolerance, >=0
22435 :
22436 : OUTPUT PARAMETERS
22437 : X - point bounded with respect to constraints.
22438 : components corresponding to active constraints are exactly
22439 : equal to the boundary values.
22440 :
22441 : -- ALGLIB --
22442 : Copyright 10.01.2012 by Bochkanov Sergey
22443 : *************************************************************************/
22444 0 : void filterdirection(/* Real */ ae_vector* d,
22445 : /* Real */ ae_vector* x,
22446 : /* Real */ ae_vector* bndl,
22447 : /* Boolean */ ae_vector* havebndl,
22448 : /* Real */ ae_vector* bndu,
22449 : /* Boolean */ ae_vector* havebndu,
22450 : /* Real */ ae_vector* s,
22451 : ae_int_t nmain,
22452 : ae_int_t nslack,
22453 : double droptol,
22454 : ae_state *_state)
22455 : {
22456 : ae_int_t i;
22457 : double scalednorm;
22458 : ae_bool isactive;
22459 :
22460 :
22461 0 : scalednorm = 0.0;
22462 0 : for(i=0; i<=nmain+nslack-1; i++)
22463 : {
22464 0 : scalednorm = scalednorm+ae_sqr(d->ptr.p_double[i]*s->ptr.p_double[i], _state);
22465 : }
22466 0 : scalednorm = ae_sqrt(scalednorm, _state);
22467 0 : for(i=0; i<=nmain-1; i++)
22468 : {
22469 0 : 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);
22470 0 : 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);
22471 0 : 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]));
22472 0 : if( isactive&&ae_fp_less_eq(ae_fabs(d->ptr.p_double[i]*s->ptr.p_double[i], _state),droptol*scalednorm) )
22473 : {
22474 0 : d->ptr.p_double[i] = 0.0;
22475 : }
22476 : }
22477 0 : for(i=0; i<=nslack-1; i++)
22478 : {
22479 0 : ae_assert(ae_fp_greater_eq(x->ptr.p_double[nmain+i],(double)(0)), "FilterDirection: infeasible point", _state);
22480 0 : if( ae_fp_eq(x->ptr.p_double[nmain+i],(double)(0))&&ae_fp_less_eq(ae_fabs(d->ptr.p_double[nmain+i]*s->ptr.p_double[nmain+i], _state),droptol*scalednorm) )
22481 : {
22482 0 : d->ptr.p_double[nmain+i] = 0.0;
22483 : }
22484 : }
22485 0 : }
22486 :
22487 :
22488 : /*************************************************************************
22489 : This function returns number of bound constraints whose state was changed
22490 : (either activated or deactivated) when making step from XPrev to X.
22491 :
22492 : Constraints are considered:
22493 : * active - when we are exactly at the boundary
22494 : * inactive - when we are not at the boundary
22495 :
22496 : You should note that antigradient direction is NOT taken into account when
22497 : we make decions on the constraint status.
22498 :
22499 : INPUT PARAMETERS
22500 : X - array[NMain+NSlack], final point.
22501 : Must be feasible with respect to bound constraints.
22502 : XPrev - array[NMain+NSlack], initial point.
22503 : Must be feasible with respect to bound constraints.
22504 : BndL - lower bounds, array[NMain]
22505 : (may contain -INF, when bound is not present)
22506 : HaveBndL - array[NMain], if HaveBndL[i] is False,
22507 : then i-th bound is not present
22508 : BndU - array[NMain], upper bounds
22509 : (may contain +INF, when bound is not present)
22510 : HaveBndU - array[NMain], if HaveBndU[i] is False,
22511 : then i-th bound is not present
22512 : NMain - number of main variables
22513 : NSlack - number of slack variables
22514 :
22515 : RESULT:
22516 : number of constraints whose state was changed.
22517 :
22518 : -- ALGLIB --
22519 : Copyright 10.01.2012 by Bochkanov Sergey
22520 : *************************************************************************/
22521 0 : ae_int_t numberofchangedconstraints(/* Real */ ae_vector* x,
22522 : /* Real */ ae_vector* xprev,
22523 : /* Real */ ae_vector* bndl,
22524 : /* Boolean */ ae_vector* havebndl,
22525 : /* Real */ ae_vector* bndu,
22526 : /* Boolean */ ae_vector* havebndu,
22527 : ae_int_t nmain,
22528 : ae_int_t nslack,
22529 : ae_state *_state)
22530 : {
22531 : ae_int_t i;
22532 : ae_bool statuschanged;
22533 : ae_int_t result;
22534 :
22535 :
22536 0 : result = 0;
22537 0 : for(i=0; i<=nmain-1; i++)
22538 : {
22539 0 : if( ae_fp_neq(x->ptr.p_double[i],xprev->ptr.p_double[i]) )
22540 : {
22541 0 : statuschanged = ae_false;
22542 0 : 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])) )
22543 : {
22544 0 : statuschanged = ae_true;
22545 : }
22546 0 : 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])) )
22547 : {
22548 0 : statuschanged = ae_true;
22549 : }
22550 0 : if( statuschanged )
22551 : {
22552 0 : result = result+1;
22553 : }
22554 : }
22555 : }
22556 0 : for(i=0; i<=nslack-1; i++)
22557 : {
22558 0 : 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],(double)(0))||ae_fp_eq(xprev->ptr.p_double[nmain+i],(double)(0))) )
22559 : {
22560 0 : result = result+1;
22561 : }
22562 : }
22563 0 : return result;
22564 : }
22565 :
22566 :
22567 : /*************************************************************************
22568 : This function finds feasible point of (NMain+NSlack)-dimensional problem
22569 : subject to NMain explicit boundary constraints (some constraints can be
22570 : omitted), NSlack implicit non-negativity constraints, K linear equality
22571 : constraints.
22572 :
22573 : INPUT PARAMETERS
22574 : X - array[NMain+NSlack], initial point.
22575 : BndL - lower bounds, array[NMain]
22576 : (may contain -INF, when bound is not present)
22577 : HaveBndL - array[NMain], if HaveBndL[i] is False,
22578 : then i-th bound is not present
22579 : BndU - array[NMain], upper bounds
22580 : (may contain +INF, when bound is not present)
22581 : HaveBndU - array[NMain], if HaveBndU[i] is False,
22582 : then i-th bound is not present
22583 : NMain - number of main variables
22584 : NSlack - number of slack variables
22585 : CE - array[K,NMain+NSlack+1], equality constraints CE*x=b.
22586 : Rows contain constraints, first NMain+NSlack columns
22587 : contain coefficients before X[], last column contain
22588 : right part.
22589 : K - number of linear constraints
22590 : EpsI - infeasibility (error in the right part) allowed in the
22591 : solution
22592 :
22593 : OUTPUT PARAMETERS:
22594 : X - feasible point or best infeasible point found before
22595 : algorithm termination
22596 : QPIts - number of QP iterations (for debug purposes)
22597 : GPAIts - number of GPA iterations (for debug purposes)
22598 :
22599 : RESULT:
22600 : True in case X is feasible, False - if it is infeasible.
22601 :
22602 : -- ALGLIB --
22603 : Copyright 20.01.2012 by Bochkanov Sergey
22604 : *************************************************************************/
22605 0 : ae_bool findfeasiblepoint(/* Real */ ae_vector* x,
22606 : /* Real */ ae_vector* bndl,
22607 : /* Boolean */ ae_vector* havebndl,
22608 : /* Real */ ae_vector* bndu,
22609 : /* Boolean */ ae_vector* havebndu,
22610 : ae_int_t nmain,
22611 : ae_int_t nslack,
22612 : /* Real */ ae_matrix* ce,
22613 : ae_int_t k,
22614 : double epsi,
22615 : ae_int_t* qpits,
22616 : ae_int_t* gpaits,
22617 : ae_state *_state)
22618 : {
22619 : ae_frame _frame_block;
22620 : ae_matrix _ce;
22621 : ae_int_t i;
22622 : ae_int_t j;
22623 : ae_int_t idx0;
22624 : ae_int_t idx1;
22625 : ae_vector permx;
22626 : ae_vector xn;
22627 : ae_vector xa;
22628 : ae_vector newtonstep;
22629 : ae_vector g;
22630 : ae_vector pg;
22631 : ae_vector tau;
22632 : ae_vector s;
22633 : double armijostep;
22634 : double armijobeststep;
22635 : double armijobestfeas;
22636 : double v;
22637 : double vv;
22638 : double mx;
22639 : double feaserr;
22640 : double feaserr0;
22641 : double feaserr1;
22642 : double feasold;
22643 : double feasnew;
22644 : double pgnorm;
22645 : double vn;
22646 : double vd;
22647 : double stp;
22648 : ae_int_t vartofreeze;
22649 : double valtofreeze;
22650 : double maxsteplen;
22651 : ae_bool werechangesinconstraints;
22652 : ae_bool stage1isover;
22653 : ae_bool converged;
22654 : ae_vector activeconstraints;
22655 : ae_vector tmpk;
22656 : ae_vector colnorms;
22657 : ae_int_t nactive;
22658 : ae_int_t nfree;
22659 : ae_vector p1;
22660 : ae_vector p2;
22661 : apbuffers buf;
22662 : ae_int_t itscount;
22663 : ae_int_t itswithintolerance;
22664 : ae_int_t maxitswithintolerance;
22665 : ae_int_t badits;
22666 : ae_int_t maxbadits;
22667 : ae_int_t gparuns;
22668 : ae_int_t maxarmijoruns;
22669 : ae_matrix permce;
22670 : ae_matrix q;
22671 : ae_bool result;
22672 :
22673 0 : ae_frame_make(_state, &_frame_block);
22674 0 : memset(&_ce, 0, sizeof(_ce));
22675 0 : memset(&permx, 0, sizeof(permx));
22676 0 : memset(&xn, 0, sizeof(xn));
22677 0 : memset(&xa, 0, sizeof(xa));
22678 0 : memset(&newtonstep, 0, sizeof(newtonstep));
22679 0 : memset(&g, 0, sizeof(g));
22680 0 : memset(&pg, 0, sizeof(pg));
22681 0 : memset(&tau, 0, sizeof(tau));
22682 0 : memset(&s, 0, sizeof(s));
22683 0 : memset(&activeconstraints, 0, sizeof(activeconstraints));
22684 0 : memset(&tmpk, 0, sizeof(tmpk));
22685 0 : memset(&colnorms, 0, sizeof(colnorms));
22686 0 : memset(&p1, 0, sizeof(p1));
22687 0 : memset(&p2, 0, sizeof(p2));
22688 0 : memset(&buf, 0, sizeof(buf));
22689 0 : memset(&permce, 0, sizeof(permce));
22690 0 : memset(&q, 0, sizeof(q));
22691 0 : ae_matrix_init_copy(&_ce, ce, _state, ae_true);
22692 0 : ce = &_ce;
22693 0 : *qpits = 0;
22694 0 : *gpaits = 0;
22695 0 : ae_vector_init(&permx, 0, DT_REAL, _state, ae_true);
22696 0 : ae_vector_init(&xn, 0, DT_REAL, _state, ae_true);
22697 0 : ae_vector_init(&xa, 0, DT_REAL, _state, ae_true);
22698 0 : ae_vector_init(&newtonstep, 0, DT_REAL, _state, ae_true);
22699 0 : ae_vector_init(&g, 0, DT_REAL, _state, ae_true);
22700 0 : ae_vector_init(&pg, 0, DT_REAL, _state, ae_true);
22701 0 : ae_vector_init(&tau, 0, DT_REAL, _state, ae_true);
22702 0 : ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
22703 0 : ae_vector_init(&activeconstraints, 0, DT_REAL, _state, ae_true);
22704 0 : ae_vector_init(&tmpk, 0, DT_REAL, _state, ae_true);
22705 0 : ae_vector_init(&colnorms, 0, DT_REAL, _state, ae_true);
22706 0 : ae_vector_init(&p1, 0, DT_INT, _state, ae_true);
22707 0 : ae_vector_init(&p2, 0, DT_INT, _state, ae_true);
22708 0 : _apbuffers_init(&buf, _state, ae_true);
22709 0 : ae_matrix_init(&permce, 0, 0, DT_REAL, _state, ae_true);
22710 0 : ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true);
22711 :
22712 0 : maxitswithintolerance = 3;
22713 0 : maxbadits = 3;
22714 0 : maxarmijoruns = 5;
22715 0 : *qpits = 0;
22716 0 : *gpaits = 0;
22717 :
22718 : /*
22719 : * Initial enforcement of the feasibility with respect to boundary constraints
22720 : * NOTE: after this block we assume that boundary constraints are consistent.
22721 : */
22722 0 : if( !enforceboundaryconstraints(x, bndl, havebndl, bndu, havebndu, nmain, nslack, _state) )
22723 : {
22724 0 : result = ae_false;
22725 0 : ae_frame_leave(_state);
22726 0 : return result;
22727 : }
22728 0 : if( k==0 )
22729 : {
22730 :
22731 : /*
22732 : * No linear constraints, we can exit right now
22733 : */
22734 0 : result = ae_true;
22735 0 : ae_frame_leave(_state);
22736 0 : return result;
22737 : }
22738 :
22739 : /*
22740 : * Scale rows of CE in such way that max(CE[i,0..nmain+nslack-1])=1 for any i=0..k-1
22741 : */
22742 0 : for(i=0; i<=k-1; i++)
22743 : {
22744 0 : v = 0.0;
22745 0 : for(j=0; j<=nmain+nslack-1; j++)
22746 : {
22747 0 : v = ae_maxreal(v, ae_fabs(ce->ptr.pp_double[i][j], _state), _state);
22748 : }
22749 0 : if( ae_fp_neq(v,(double)(0)) )
22750 : {
22751 0 : v = 1/v;
22752 0 : ae_v_muld(&ce->ptr.pp_double[i][0], 1, ae_v_len(0,nmain+nslack), v);
22753 : }
22754 : }
22755 :
22756 : /*
22757 : * Allocate temporaries
22758 : */
22759 0 : ae_vector_set_length(&xn, nmain+nslack, _state);
22760 0 : ae_vector_set_length(&xa, nmain+nslack, _state);
22761 0 : ae_vector_set_length(&permx, nmain+nslack, _state);
22762 0 : ae_vector_set_length(&g, nmain+nslack, _state);
22763 0 : ae_vector_set_length(&pg, nmain+nslack, _state);
22764 0 : ae_vector_set_length(&tmpk, k, _state);
22765 0 : ae_matrix_set_length(&permce, k, nmain+nslack, _state);
22766 0 : ae_vector_set_length(&activeconstraints, nmain+nslack, _state);
22767 0 : ae_vector_set_length(&newtonstep, nmain+nslack, _state);
22768 0 : ae_vector_set_length(&s, nmain+nslack, _state);
22769 0 : ae_vector_set_length(&colnorms, nmain+nslack, _state);
22770 0 : for(i=0; i<=nmain+nslack-1; i++)
22771 : {
22772 0 : s.ptr.p_double[i] = 1.0;
22773 0 : colnorms.ptr.p_double[i] = 0.0;
22774 0 : for(j=0; j<=k-1; j++)
22775 : {
22776 0 : colnorms.ptr.p_double[i] = colnorms.ptr.p_double[i]+ae_sqr(ce->ptr.pp_double[j][i], _state);
22777 : }
22778 : }
22779 :
22780 : /*
22781 : * K>0, we have linear equality constraints combined with bound constraints.
22782 : *
22783 : * Try to find feasible point as minimizer of the quadratic function
22784 : * F(x) = 0.5*||CE*x-b||^2 = 0.5*x'*(CE'*CE)*x - (b'*CE)*x + 0.5*b'*b
22785 : * subject to boundary constraints given by BL, BU and non-negativity of
22786 : * the slack variables. BTW, we drop constant term because it does not
22787 : * actually influences on the solution.
22788 : *
22789 : * Below we will assume that K>0.
22790 : */
22791 0 : itswithintolerance = 0;
22792 0 : badits = 0;
22793 0 : itscount = 0;
22794 : for(;;)
22795 : {
22796 :
22797 : /*
22798 : * Stage 0: check for exact convergence
22799 : */
22800 0 : converged = ae_true;
22801 0 : feaserr = optserv_feasibilityerror(ce, x, nmain, nslack, k, &tmpk, _state);
22802 0 : for(i=0; i<=k-1; i++)
22803 : {
22804 :
22805 : /*
22806 : * Calculate MX - maximum term in the left part
22807 : *
22808 : * Terminate if error in the right part is not greater than 100*Eps*MX.
22809 : *
22810 : * IMPORTANT: we must perform check for non-strict inequality, i.e. to use <= instead of <.
22811 : * it will allow us to easily handle situations with zero rows of CE.
22812 : *
22813 : * NOTE: it is important to calculate feasibility error with dedicated
22814 : * function. Once we had a situation when usage of "inline" code
22815 : * resulted in different numerical values calculated at different
22816 : * parts of program for exactly same X. However, this value is
22817 : * essential for algorithm's ability to terminate before entering
22818 : * infinite loop, so reproducibility of numerical results is very
22819 : * important.
22820 : */
22821 0 : mx = (double)(0);
22822 0 : v = -ce->ptr.pp_double[i][nmain+nslack];
22823 0 : for(j=0; j<=nmain+nslack-1; j++)
22824 : {
22825 0 : mx = ae_maxreal(mx, ae_fabs(ce->ptr.pp_double[i][j]*x->ptr.p_double[j], _state), _state);
22826 0 : v = v+ce->ptr.pp_double[i][j]*x->ptr.p_double[j];
22827 : }
22828 0 : converged = converged&&ae_fp_less_eq(ae_fabs(v, _state),100*ae_machineepsilon*mx);
22829 : }
22830 0 : feaserr0 = feaserr;
22831 0 : if( converged )
22832 : {
22833 0 : result = ae_fp_less_eq(feaserr,epsi);
22834 0 : ae_frame_leave(_state);
22835 0 : return result;
22836 : }
22837 :
22838 : /*
22839 : * Stage 1: equality constrained quadratic programming
22840 : *
22841 : * * treat active bound constraints as equality ones (constraint is considered
22842 : * active when we are at the boundary, independently of the antigradient direction)
22843 : * * calculate unrestricted Newton step to point XM (which may be infeasible)
22844 : * calculate MaxStepLen = largest step in direction of XM which retains feasibility.
22845 : * * perform bounded step from X to XN:
22846 : * a) XN=XM (if XM is feasible)
22847 : * b) XN=X-MaxStepLen*(XM-X) (otherwise)
22848 : * * X := XN
22849 : * * if XM (Newton step subject to currently active constraints) was feasible, goto Stage 2
22850 : * * repeat Stage 1
22851 : *
22852 : * NOTE 1: in order to solve constrained qudratic subproblem we will have to reorder
22853 : * variables in such way that ones corresponding to inactive constraints will
22854 : * be first, and active ones will be last in the list. CE and X are now
22855 : * [ xi ]
22856 : * separated into two parts: CE = [CEi CEa], x = [ ], where CEi/Xi correspond
22857 : * [ xa ]
22858 : * to INACTIVE constraints, and CEa/Xa correspond to the ACTIVE ones.
22859 : *
22860 : * Now, instead of F=0.5*x'*(CE'*CE)*x - (b'*CE)*x + 0.5*b'*b, we have
22861 : * F(xi) = 0.5*(CEi*xi,CEi*xi) + (CEa*xa-b,CEi*xi) + (0.5*CEa*xa-b,CEa*xa).
22862 : * Here xa is considered constant, i.e. we optimize with respect to xi, leaving xa fixed.
22863 : *
22864 : * We can solve it by performing SVD of CEi and calculating pseudoinverse of the
22865 : * Hessian matrix. Of course, we do NOT calculate pseudoinverse explicitly - we
22866 : * just use singular vectors to perform implicit multiplication by it.
22867 : *
22868 : */
22869 : for(;;)
22870 : {
22871 :
22872 : /*
22873 : * Calculate G - gradient subject to equality constraints,
22874 : * multiply it by inverse of the Hessian diagonal to obtain initial
22875 : * step vector.
22876 : *
22877 : * Bound step subject to constraints which can be activated,
22878 : * run Armijo search with increasing step size.
22879 : * Search is terminated when feasibility error stops to decrease.
22880 : *
22881 : * NOTE: it is important to test for "stops to decrease" instead
22882 : * of "starts to increase" in order to correctly handle cases with
22883 : * zero CE.
22884 : */
22885 0 : armijobeststep = 0.0;
22886 0 : optserv_feasibilityerrorgrad(ce, x, nmain, nslack, k, &armijobestfeas, &g, &tmpk, _state);
22887 0 : for(i=0; i<=nmain-1; i++)
22888 : {
22889 0 : if( havebndl->ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],bndl->ptr.p_double[i]) )
22890 : {
22891 0 : g.ptr.p_double[i] = 0.0;
22892 : }
22893 0 : if( havebndu->ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],bndu->ptr.p_double[i]) )
22894 : {
22895 0 : g.ptr.p_double[i] = 0.0;
22896 : }
22897 : }
22898 0 : for(i=0; i<=nslack-1; i++)
22899 : {
22900 0 : if( ae_fp_eq(x->ptr.p_double[nmain+i],0.0) )
22901 : {
22902 0 : g.ptr.p_double[nmain+i] = 0.0;
22903 : }
22904 : }
22905 0 : v = 0.0;
22906 0 : for(i=0; i<=nmain+nslack-1; i++)
22907 : {
22908 0 : if( ae_fp_neq(ae_sqr(colnorms.ptr.p_double[i], _state),(double)(0)) )
22909 : {
22910 0 : newtonstep.ptr.p_double[i] = -g.ptr.p_double[i]/ae_sqr(colnorms.ptr.p_double[i], _state);
22911 : }
22912 : else
22913 : {
22914 0 : newtonstep.ptr.p_double[i] = 0.0;
22915 : }
22916 0 : v = v+ae_sqr(newtonstep.ptr.p_double[i], _state);
22917 : }
22918 0 : if( ae_fp_eq(v,(double)(0)) )
22919 : {
22920 :
22921 : /*
22922 : * Constrained gradient is zero, QP iterations are over
22923 : */
22924 0 : break;
22925 : }
22926 0 : calculatestepbound(x, &newtonstep, 1.0, bndl, havebndl, bndu, havebndu, nmain, nslack, &vartofreeze, &valtofreeze, &maxsteplen, _state);
22927 0 : if( vartofreeze>=0&&ae_fp_eq(maxsteplen,(double)(0)) )
22928 : {
22929 :
22930 : /*
22931 : * Can not perform step, QP iterations are over
22932 : */
22933 0 : break;
22934 : }
22935 0 : if( vartofreeze>=0 )
22936 : {
22937 0 : armijostep = ae_minreal(1.0, maxsteplen, _state);
22938 : }
22939 : else
22940 : {
22941 0 : armijostep = (double)(1);
22942 : }
22943 : for(;;)
22944 : {
22945 0 : ae_v_move(&xa.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
22946 0 : ae_v_addd(&xa.ptr.p_double[0], 1, &newtonstep.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1), armijostep);
22947 0 : enforceboundaryconstraints(&xa, bndl, havebndl, bndu, havebndu, nmain, nslack, _state);
22948 0 : feaserr = optserv_feasibilityerror(ce, &xa, nmain, nslack, k, &tmpk, _state);
22949 0 : if( ae_fp_greater_eq(feaserr,armijobestfeas) )
22950 : {
22951 0 : break;
22952 : }
22953 0 : armijobestfeas = feaserr;
22954 0 : armijobeststep = armijostep;
22955 0 : armijostep = 2.0*armijostep;
22956 : }
22957 0 : ae_v_addd(&x->ptr.p_double[0], 1, &newtonstep.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1), armijobeststep);
22958 0 : enforceboundaryconstraints(x, bndl, havebndl, bndu, havebndu, nmain, nslack, _state);
22959 :
22960 : /*
22961 : * Determine number of active and free constraints
22962 : */
22963 0 : nactive = 0;
22964 0 : for(i=0; i<=nmain-1; i++)
22965 : {
22966 0 : activeconstraints.ptr.p_double[i] = (double)(0);
22967 0 : if( havebndl->ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],bndl->ptr.p_double[i]) )
22968 : {
22969 0 : activeconstraints.ptr.p_double[i] = (double)(1);
22970 : }
22971 0 : if( havebndu->ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],bndu->ptr.p_double[i]) )
22972 : {
22973 0 : activeconstraints.ptr.p_double[i] = (double)(1);
22974 : }
22975 0 : if( ae_fp_greater(activeconstraints.ptr.p_double[i],(double)(0)) )
22976 : {
22977 0 : nactive = nactive+1;
22978 : }
22979 : }
22980 0 : for(i=0; i<=nslack-1; i++)
22981 : {
22982 0 : activeconstraints.ptr.p_double[nmain+i] = (double)(0);
22983 0 : if( ae_fp_eq(x->ptr.p_double[nmain+i],0.0) )
22984 : {
22985 0 : activeconstraints.ptr.p_double[nmain+i] = (double)(1);
22986 : }
22987 0 : if( ae_fp_greater(activeconstraints.ptr.p_double[nmain+i],(double)(0)) )
22988 : {
22989 0 : nactive = nactive+1;
22990 : }
22991 : }
22992 0 : nfree = nmain+nslack-nactive;
22993 0 : if( nfree==0 )
22994 : {
22995 0 : break;
22996 : }
22997 0 : *qpits = *qpits+1;
22998 :
22999 : /*
23000 : * Reorder variables: CE is reordered to PermCE, X is reordered to PermX
23001 : */
23002 0 : tagsortbuf(&activeconstraints, nmain+nslack, &p1, &p2, &buf, _state);
23003 0 : for(i=0; i<=k-1; i++)
23004 : {
23005 0 : for(j=0; j<=nmain+nslack-1; j++)
23006 : {
23007 0 : permce.ptr.pp_double[i][j] = ce->ptr.pp_double[i][j];
23008 : }
23009 : }
23010 0 : for(j=0; j<=nmain+nslack-1; j++)
23011 : {
23012 0 : permx.ptr.p_double[j] = x->ptr.p_double[j];
23013 : }
23014 0 : for(j=0; j<=nmain+nslack-1; j++)
23015 : {
23016 0 : if( p2.ptr.p_int[j]!=j )
23017 : {
23018 0 : idx0 = p2.ptr.p_int[j];
23019 0 : idx1 = j;
23020 0 : for(i=0; i<=k-1; i++)
23021 : {
23022 0 : v = permce.ptr.pp_double[i][idx0];
23023 0 : permce.ptr.pp_double[i][idx0] = permce.ptr.pp_double[i][idx1];
23024 0 : permce.ptr.pp_double[i][idx1] = v;
23025 : }
23026 0 : v = permx.ptr.p_double[idx0];
23027 0 : permx.ptr.p_double[idx0] = permx.ptr.p_double[idx1];
23028 0 : permx.ptr.p_double[idx1] = v;
23029 : }
23030 : }
23031 :
23032 : /*
23033 : * Calculate (unprojected) gradient:
23034 : * G(xi) = CEi'*(CEi*xi + CEa*xa - b)
23035 : */
23036 0 : for(i=0; i<=nfree-1; i++)
23037 : {
23038 0 : g.ptr.p_double[i] = (double)(0);
23039 : }
23040 0 : for(i=0; i<=k-1; i++)
23041 : {
23042 0 : v = ae_v_dotproduct(&permce.ptr.pp_double[i][0], 1, &permx.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
23043 0 : tmpk.ptr.p_double[i] = v-ce->ptr.pp_double[i][nmain+nslack];
23044 : }
23045 0 : for(i=0; i<=k-1; i++)
23046 : {
23047 0 : v = tmpk.ptr.p_double[i];
23048 0 : ae_v_addd(&g.ptr.p_double[0], 1, &permce.ptr.pp_double[i][0], 1, ae_v_len(0,nfree-1), v);
23049 : }
23050 :
23051 : /*
23052 : * Calculate Newton step using pseudoinverse PermCE:
23053 : * F(xi) = 0.5*xi'*H*xi + g'*xi (Taylor decomposition)
23054 : * XN = -H^(-1)*g (new point, solution of the QP subproblem)
23055 : * H = CEi'*CEi
23056 : * H^(-1) can be calculated via QR or LQ decomposition (see below)
23057 : * step = -H^(-1)*g
23058 : *
23059 : * NOTE: PermCE is destroyed after this block
23060 : */
23061 0 : for(i=0; i<=nmain+nslack-1; i++)
23062 : {
23063 0 : newtonstep.ptr.p_double[i] = (double)(0);
23064 : }
23065 0 : if( k<=nfree )
23066 : {
23067 :
23068 : /*
23069 : * CEi = L*Q
23070 : * H = Q'*L'*L*Q
23071 : * inv(H) = Q'*inv(L)*inv(L')*Q
23072 : *
23073 : * NOTE: we apply minor regularizing perturbation to diagonal of L,
23074 : * which is equal to 10*K*Eps
23075 : */
23076 0 : rmatrixlq(&permce, k, nfree, &tau, _state);
23077 0 : rmatrixlqunpackq(&permce, k, nfree, &tau, k, &q, _state);
23078 0 : v = (double)(0);
23079 0 : for(i=0; i<=k-1; i++)
23080 : {
23081 0 : v = ae_maxreal(v, ae_fabs(permce.ptr.pp_double[i][i], _state), _state);
23082 : }
23083 0 : v = coalesce(v, (double)(1), _state);
23084 0 : for(i=0; i<=k-1; i++)
23085 : {
23086 0 : permce.ptr.pp_double[i][i] = permce.ptr.pp_double[i][i]+10*k*ae_machineepsilon*v;
23087 : }
23088 0 : rmatrixgemv(k, nfree, 1.0, &q, 0, 0, 0, &g, 0, 0.0, &tmpk, 0, _state);
23089 0 : rmatrixtrsv(k, &permce, 0, 0, ae_false, ae_false, 1, &tmpk, 0, _state);
23090 0 : rmatrixtrsv(k, &permce, 0, 0, ae_false, ae_false, 0, &tmpk, 0, _state);
23091 0 : rmatrixgemv(nfree, k, -1.0, &q, 0, 0, 1, &tmpk, 0, 0.0, &newtonstep, 0, _state);
23092 : }
23093 : else
23094 : {
23095 :
23096 : /*
23097 : * CEi = Q*R
23098 : * H = R'*R
23099 : * inv(H) = inv(R)*inv(R')
23100 : *
23101 : * NOTE: we apply minor regularizing perturbation to diagonal of R,
23102 : * which is equal to 10*K*Eps
23103 : */
23104 0 : rmatrixqr(&permce, k, nfree, &tau, _state);
23105 0 : v = (double)(0);
23106 0 : for(i=0; i<=nfree-1; i++)
23107 : {
23108 0 : v = ae_maxreal(v, ae_fabs(permce.ptr.pp_double[i][i], _state), _state);
23109 : }
23110 0 : v = coalesce(v, (double)(1), _state);
23111 0 : for(i=0; i<=nfree-1; i++)
23112 : {
23113 0 : vv = 10*nfree*ae_machineepsilon*v;
23114 0 : if( ae_fp_less(permce.ptr.pp_double[i][i],(double)(0)) )
23115 : {
23116 0 : vv = -vv;
23117 : }
23118 0 : permce.ptr.pp_double[i][i] = permce.ptr.pp_double[i][i]+vv;
23119 : }
23120 0 : ae_v_moveneg(&newtonstep.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,nfree-1));
23121 0 : rmatrixtrsv(nfree, &permce, 0, 0, ae_true, ae_false, 1, &newtonstep, 0, _state);
23122 0 : rmatrixtrsv(nfree, &permce, 0, 0, ae_true, ae_false, 0, &newtonstep, 0, _state);
23123 : }
23124 :
23125 : /*
23126 : * Post-reordering of Newton step
23127 : */
23128 0 : for(j=nmain+nslack-1; j>=0; j--)
23129 : {
23130 0 : if( p2.ptr.p_int[j]!=j )
23131 : {
23132 0 : idx0 = p2.ptr.p_int[j];
23133 0 : idx1 = j;
23134 0 : v = newtonstep.ptr.p_double[idx0];
23135 0 : newtonstep.ptr.p_double[idx0] = newtonstep.ptr.p_double[idx1];
23136 0 : newtonstep.ptr.p_double[idx1] = v;
23137 : }
23138 : }
23139 :
23140 : /*
23141 : * NewtonStep contains Newton step subject to active bound constraints.
23142 : *
23143 : * Such step leads us to the minimizer of the equality constrained F,
23144 : * but such minimizer may be infeasible because some constraints which
23145 : * are inactive at the initial point can be violated at the solution.
23146 : *
23147 : * Thus, we perform optimization in two stages:
23148 : * a) perform bounded Newton step, i.e. step in the Newton direction
23149 : * until activation of the first constraint
23150 : * b) in case (MaxStepLen>0)and(MaxStepLen<1), perform additional iteration
23151 : * of the Armijo line search in the rest of the Newton direction.
23152 : */
23153 0 : calculatestepbound(x, &newtonstep, 1.0, bndl, havebndl, bndu, havebndu, nmain, nslack, &vartofreeze, &valtofreeze, &maxsteplen, _state);
23154 0 : if( vartofreeze>=0&&ae_fp_eq(maxsteplen,(double)(0)) )
23155 : {
23156 :
23157 : /*
23158 : * Activation of the constraints prevent us from performing step,
23159 : * QP iterations are over
23160 : */
23161 0 : break;
23162 : }
23163 0 : if( vartofreeze>=0 )
23164 : {
23165 0 : v = ae_minreal(1.0, maxsteplen, _state);
23166 : }
23167 : else
23168 : {
23169 0 : v = 1.0;
23170 : }
23171 0 : ae_v_moved(&xn.ptr.p_double[0], 1, &newtonstep.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1), v);
23172 0 : ae_v_add(&xn.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
23173 0 : postprocessboundedstep(&xn, x, bndl, havebndl, bndu, havebndu, nmain, nslack, vartofreeze, valtofreeze, v, maxsteplen, _state);
23174 0 : if( ae_fp_greater(maxsteplen,(double)(0))&&ae_fp_less(maxsteplen,(double)(1)) )
23175 : {
23176 :
23177 : /*
23178 : * Newton step was restricted by activation of the constraints,
23179 : * perform Armijo iteration.
23180 : *
23181 : * Initial estimate for best step is zero step. We try different
23182 : * step sizes, from the 1-MaxStepLen (residual of the full Newton
23183 : * step) to progressively smaller and smaller steps.
23184 : */
23185 0 : armijobeststep = 0.0;
23186 0 : armijobestfeas = optserv_feasibilityerror(ce, &xn, nmain, nslack, k, &tmpk, _state);
23187 0 : armijostep = 1-maxsteplen;
23188 0 : for(j=0; j<=maxarmijoruns-1; j++)
23189 : {
23190 0 : ae_v_move(&xa.ptr.p_double[0], 1, &xn.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
23191 0 : ae_v_addd(&xa.ptr.p_double[0], 1, &newtonstep.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1), armijostep);
23192 0 : enforceboundaryconstraints(&xa, bndl, havebndl, bndu, havebndu, nmain, nslack, _state);
23193 0 : feaserr = optserv_feasibilityerror(ce, &xa, nmain, nslack, k, &tmpk, _state);
23194 0 : if( ae_fp_less(feaserr,armijobestfeas) )
23195 : {
23196 0 : armijobestfeas = feaserr;
23197 0 : armijobeststep = armijostep;
23198 : }
23199 0 : armijostep = 0.5*armijostep;
23200 : }
23201 0 : ae_v_move(&xa.ptr.p_double[0], 1, &xn.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
23202 0 : ae_v_addd(&xa.ptr.p_double[0], 1, &newtonstep.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1), armijobeststep);
23203 0 : enforceboundaryconstraints(&xa, bndl, havebndl, bndu, havebndu, nmain, nslack, _state);
23204 : }
23205 : else
23206 : {
23207 :
23208 : /*
23209 : * Armijo iteration is not performed
23210 : */
23211 0 : ae_v_move(&xa.ptr.p_double[0], 1, &xn.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
23212 : }
23213 0 : stage1isover = ae_fp_greater_eq(maxsteplen,(double)(1))||ae_fp_eq(maxsteplen,(double)(0));
23214 :
23215 : /*
23216 : * Calculate feasibility errors for old and new X.
23217 : * These quantinies are used for debugging purposes only.
23218 : * However, we can leave them in release code because performance impact is insignificant.
23219 : *
23220 : * Update X. Exit if needed.
23221 : */
23222 0 : feasold = optserv_feasibilityerror(ce, x, nmain, nslack, k, &tmpk, _state);
23223 0 : feasnew = optserv_feasibilityerror(ce, &xa, nmain, nslack, k, &tmpk, _state);
23224 0 : if( ae_fp_greater_eq(feasnew,feasold) )
23225 : {
23226 0 : break;
23227 : }
23228 0 : ae_v_move(&x->ptr.p_double[0], 1, &xa.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
23229 0 : if( stage1isover )
23230 : {
23231 0 : break;
23232 : }
23233 : }
23234 :
23235 : /*
23236 : * Stage 2: gradient projection algorithm (GPA)
23237 : *
23238 : * * calculate feasibility error (with respect to linear equality constraints)
23239 : * * calculate gradient G of F, project it into feasible area (G => PG)
23240 : * * exit if norm(PG) is exactly zero or feasibility error is smaller than EpsC
23241 : * * let XM be exact minimum of F along -PG (XM may be infeasible).
23242 : * calculate MaxStepLen = largest step in direction of -PG which retains feasibility.
23243 : * * perform bounded step from X to XN:
23244 : * a) XN=XM (if XM is feasible)
23245 : * b) XN=X-MaxStepLen*PG (otherwise)
23246 : * * X := XN
23247 : * * stop after specified number of iterations or when no new constraints was activated
23248 : *
23249 : * NOTES:
23250 : * * grad(F) = (CE'*CE)*x - (b'*CE)^T
23251 : * * CE[i] denotes I-th row of CE
23252 : * * XM = X+stp*(-PG) where stp=(grad(F(X)),PG)/(CE*PG,CE*PG).
23253 : * Here PG is a projected gradient, but in fact it can be arbitrary non-zero
23254 : * direction vector - formula for minimum of F along PG still will be correct.
23255 : */
23256 0 : werechangesinconstraints = ae_false;
23257 0 : for(gparuns=1; gparuns<=k; gparuns++)
23258 : {
23259 :
23260 : /*
23261 : * calculate feasibility error and G
23262 : */
23263 0 : optserv_feasibilityerrorgrad(ce, x, nmain, nslack, k, &feaserr, &g, &tmpk, _state);
23264 :
23265 : /*
23266 : * project G, filter it (strip numerical noise)
23267 : */
23268 0 : ae_v_move(&pg.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
23269 0 : projectgradientintobc(x, &pg, bndl, havebndl, bndu, havebndu, nmain, nslack, _state);
23270 0 : filterdirection(&pg, x, bndl, havebndl, bndu, havebndu, &s, nmain, nslack, 1.0E-9, _state);
23271 0 : for(i=0; i<=nmain+nslack-1; i++)
23272 : {
23273 0 : if( ae_fp_neq(ae_sqr(colnorms.ptr.p_double[i], _state),(double)(0)) )
23274 : {
23275 0 : pg.ptr.p_double[i] = pg.ptr.p_double[i]/ae_sqr(colnorms.ptr.p_double[i], _state);
23276 : }
23277 : else
23278 : {
23279 0 : pg.ptr.p_double[i] = 0.0;
23280 : }
23281 : }
23282 :
23283 : /*
23284 : * Check GNorm and feasibility.
23285 : * Exit when GNorm is exactly zero.
23286 : */
23287 0 : pgnorm = ae_v_dotproduct(&pg.ptr.p_double[0], 1, &pg.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
23288 0 : pgnorm = ae_sqrt(pgnorm, _state);
23289 0 : if( ae_fp_eq(pgnorm,(double)(0)) )
23290 : {
23291 0 : result = ae_fp_less_eq(feaserr,epsi);
23292 0 : ae_frame_leave(_state);
23293 0 : return result;
23294 : }
23295 :
23296 : /*
23297 : * calculate planned step length
23298 : */
23299 0 : vn = ae_v_dotproduct(&g.ptr.p_double[0], 1, &pg.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
23300 0 : vd = (double)(0);
23301 0 : rmatrixgemv(k, nmain+nslack, 1.0, ce, 0, 0, 0, &pg, 0, 0.0, &tmpk, 0, _state);
23302 0 : for(i=0; i<=k-1; i++)
23303 : {
23304 0 : vd = vd+ae_sqr(tmpk.ptr.p_double[i], _state);
23305 : }
23306 0 : stp = vn/vd;
23307 :
23308 : /*
23309 : * Calculate step bound.
23310 : * Perform bounded step and post-process it
23311 : */
23312 0 : calculatestepbound(x, &pg, -1.0, bndl, havebndl, bndu, havebndu, nmain, nslack, &vartofreeze, &valtofreeze, &maxsteplen, _state);
23313 0 : if( vartofreeze>=0&&ae_fp_eq(maxsteplen,(double)(0)) )
23314 : {
23315 0 : result = ae_false;
23316 0 : ae_frame_leave(_state);
23317 0 : return result;
23318 : }
23319 0 : if( vartofreeze>=0 )
23320 : {
23321 0 : v = ae_minreal(stp, maxsteplen, _state);
23322 : }
23323 : else
23324 : {
23325 0 : v = stp;
23326 : }
23327 0 : ae_v_move(&xn.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
23328 0 : ae_v_subd(&xn.ptr.p_double[0], 1, &pg.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1), v);
23329 0 : postprocessboundedstep(&xn, x, bndl, havebndl, bndu, havebndu, nmain, nslack, vartofreeze, valtofreeze, v, maxsteplen, _state);
23330 :
23331 : /*
23332 : * update X
23333 : * check stopping criteria
23334 : */
23335 0 : werechangesinconstraints = werechangesinconstraints||numberofchangedconstraints(&xn, x, bndl, havebndl, bndu, havebndu, nmain, nslack, _state)>0;
23336 0 : ae_v_move(&x->ptr.p_double[0], 1, &xn.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
23337 0 : *gpaits = *gpaits+1;
23338 0 : if( !werechangesinconstraints )
23339 : {
23340 0 : break;
23341 : }
23342 : }
23343 :
23344 : /*
23345 : * Stage 3: decide to stop algorithm or not to stop
23346 : *
23347 : * 1. we can stop when last GPA run did NOT changed constraints status.
23348 : * It means that we've found final set of the active constraints even
23349 : * before GPA made its run. And it means that Newton step moved us to
23350 : * the minimum subject to the present constraints.
23351 : * Depending on feasibility error, True or False is returned.
23352 : */
23353 0 : feaserr = optserv_feasibilityerror(ce, x, nmain, nslack, k, &tmpk, _state);
23354 0 : feaserr1 = feaserr;
23355 0 : if( ae_fp_greater_eq(feaserr1,feaserr0*(1-1000*ae_machineepsilon)) )
23356 : {
23357 0 : inc(&badits, _state);
23358 : }
23359 : else
23360 : {
23361 0 : badits = 0;
23362 : }
23363 0 : if( ae_fp_less_eq(feaserr,epsi) )
23364 : {
23365 0 : inc(&itswithintolerance, _state);
23366 : }
23367 : else
23368 : {
23369 0 : itswithintolerance = 0;
23370 : }
23371 0 : if( (!werechangesinconstraints||itswithintolerance>=maxitswithintolerance)||badits>=maxbadits )
23372 : {
23373 0 : result = ae_fp_less_eq(feaserr,epsi);
23374 0 : ae_frame_leave(_state);
23375 0 : return result;
23376 : }
23377 0 : itscount = itscount+1;
23378 :
23379 : /*
23380 : * Block below is never executed; it is necessary just to avoid
23381 : * "unreachable code" warning about automatically generated code.
23382 : *
23383 : * We just need a way to transfer control to the end of the function,
23384 : * even a fake way which is never actually traversed.
23385 : */
23386 0 : if( alwaysfalse(_state) )
23387 : {
23388 0 : result = ae_false;
23389 0 : ae_assert(ae_false, "Assertion failed", _state);
23390 0 : break;
23391 : }
23392 : }
23393 0 : ae_frame_leave(_state);
23394 0 : return result;
23395 : }
23396 :
23397 :
23398 : /*************************************************************************
23399 : This function checks that input derivatives are right. First it scales
23400 : parameters DF0 and DF1 from segment [A;B] to [0;1]. Then it builds Hermite
23401 : spline and derivative of it in 0.5. Search scale as Max(DF0,DF1, |F0-F1|).
23402 : Right derivative has to satisfy condition:
23403 : |H-F|/S<=0,001, |H'-F'|/S<=0,001.
23404 :
23405 : INPUT PARAMETERS:
23406 : F0 - function's value in X-TestStep point;
23407 : DF0 - derivative's value in X-TestStep point;
23408 : F1 - function's value in X+TestStep point;
23409 : DF1 - derivative's value in X+TestStep point;
23410 : F - testing function's value;
23411 : DF - testing derivative's value;
23412 : Width- width of verification segment.
23413 :
23414 : RESULT:
23415 : If input derivatives is right then function returns true, else
23416 : function returns false.
23417 :
23418 : -- ALGLIB --
23419 : Copyright 29.05.2012 by Bochkanov Sergey
23420 : *************************************************************************/
23421 0 : ae_bool derivativecheck(double f0,
23422 : double df0,
23423 : double f1,
23424 : double df1,
23425 : double f,
23426 : double df,
23427 : double width,
23428 : ae_state *_state)
23429 : {
23430 : double s;
23431 : double h;
23432 : double dh;
23433 : ae_bool result;
23434 :
23435 :
23436 :
23437 : /*
23438 : * Rescale input data to [0,1]
23439 : */
23440 0 : df = width*df;
23441 0 : df0 = width*df0;
23442 0 : df1 = width*df1;
23443 :
23444 : /*
23445 : * Compute error scale, two sources are used:
23446 : * * magnitudes of derivatives and secants
23447 : * * magnitudes of input data times sqrt(machine_epsilon)
23448 : */
23449 0 : s = 0.0;
23450 0 : s = ae_maxreal(s, ae_fabs(df0, _state), _state);
23451 0 : s = ae_maxreal(s, ae_fabs(df1, _state), _state);
23452 0 : s = ae_maxreal(s, ae_fabs(f1-f0, _state), _state);
23453 0 : s = ae_maxreal(s, ae_sqrt(ae_machineepsilon, _state)*ae_fabs(f0, _state), _state);
23454 0 : s = ae_maxreal(s, ae_sqrt(ae_machineepsilon, _state)*ae_fabs(f1, _state), _state);
23455 :
23456 : /*
23457 : * Compute H and dH/dX at the middle of interval
23458 : */
23459 0 : h = 0.5*(f0+f1)+0.125*(df0-df1);
23460 0 : dh = 1.5*(f1-f0)-0.250*(df0+df1);
23461 :
23462 : /*
23463 : * Check
23464 : */
23465 0 : if( ae_fp_neq(s,(double)(0)) )
23466 : {
23467 0 : if( ae_fp_greater(ae_fabs(h-f, _state)/s,0.001)||ae_fp_greater(ae_fabs(dh-df, _state)/s,0.001) )
23468 : {
23469 0 : result = ae_false;
23470 0 : return result;
23471 : }
23472 : }
23473 : else
23474 : {
23475 0 : if( ae_fp_neq(h-f,0.0)||ae_fp_neq(dh-df,0.0) )
23476 : {
23477 0 : result = ae_false;
23478 0 : return result;
23479 : }
23480 : }
23481 0 : result = ae_true;
23482 0 : return result;
23483 : }
23484 :
23485 :
23486 : /*************************************************************************
23487 : Having quadratic target function
23488 :
23489 : f(x) = 0.5*x'*A*x + b'*x + penaltyfactor*0.5*(C*x-b)'*(C*x-b)
23490 :
23491 : and its parabolic model along direction D
23492 :
23493 : F(x0+alpha*D) = D2*alpha^2 + D1*alpha
23494 :
23495 : this function estimates numerical errors in the coefficients of the model.
23496 :
23497 : It is important that this function does NOT calculate D1/D2 - it only
23498 : estimates numerical errors introduced during evaluation and compares their
23499 : magnitudes against magnitudes of numerical errors. As result, one of three
23500 : outcomes is returned for each coefficient:
23501 : * "true" coefficient is almost surely positive
23502 : * "true" coefficient is almost surely negative
23503 : * numerical errors in coefficient are so large that it can not be
23504 : reliably distinguished from zero
23505 :
23506 : INPUT PARAMETERS:
23507 : AbsASum - SUM(|A[i,j]|)
23508 : AbsASum2- SUM(A[i,j]^2)
23509 : MB - max(|B|)
23510 : MX - max(|X|)
23511 : MD - max(|D|)
23512 : D1 - linear coefficient
23513 : D2 - quadratic coefficient
23514 :
23515 : OUTPUT PARAMETERS:
23516 : D1Est - estimate of D1 sign, accounting for possible numerical
23517 : errors:
23518 : * >0 means "almost surely positive" (D1>0 and large)
23519 : * <0 means "almost surely negative" (D1<0 and large)
23520 : * =0 means "pessimistic estimate of numerical errors
23521 : in D1 is larger than magnitude of D1 itself; it is
23522 : impossible to reliably distinguish D1 from zero".
23523 : D2Est - estimate of D2 sign, accounting for possible numerical
23524 : errors:
23525 : * >0 means "almost surely positive" (D2>0 and large)
23526 : * <0 means "almost surely negative" (D2<0 and large)
23527 : * =0 means "pessimistic estimate of numerical errors
23528 : in D2 is larger than magnitude of D2 itself; it is
23529 : impossible to reliably distinguish D2 from zero".
23530 :
23531 : -- ALGLIB --
23532 : Copyright 14.05.2014 by Bochkanov Sergey
23533 : *************************************************************************/
23534 0 : void estimateparabolicmodel(double absasum,
23535 : double absasum2,
23536 : double mx,
23537 : double mb,
23538 : double md,
23539 : double d1,
23540 : double d2,
23541 : ae_int_t* d1est,
23542 : ae_int_t* d2est,
23543 : ae_state *_state)
23544 : {
23545 : double d1esterror;
23546 : double d2esterror;
23547 : double eps;
23548 : double e1;
23549 : double e2;
23550 :
23551 0 : *d1est = 0;
23552 0 : *d2est = 0;
23553 :
23554 :
23555 : /*
23556 : * Error estimates:
23557 : *
23558 : * * error in D1=d'*(A*x+b) is estimated as
23559 : * ED1 = eps*MAX_ABS(D)*(MAX_ABS(X)*ENORM(A)+MAX_ABS(B))
23560 : * * error in D2=0.5*d'*A*d is estimated as
23561 : * ED2 = eps*MAX_ABS(D)^2*ENORM(A)
23562 : *
23563 : * Here ENORM(A) is some pseudo-norm which reflects the way numerical
23564 : * error accumulates during addition. Two ways of accumulation are
23565 : * possible - worst case (errors always increase) and mean-case (errors
23566 : * may cancel each other). We calculate geometrical average of both:
23567 : * * ENORM_WORST(A) = SUM(|A[i,j]|) error in N-term sum grows as O(N)
23568 : * * ENORM_MEAN(A) = SQRT(SUM(A[i,j]^2)) error in N-term sum grows as O(sqrt(N))
23569 : * * ENORM(A) = SQRT(ENORM_WORST(A),ENORM_MEAN(A))
23570 : */
23571 0 : eps = 4*ae_machineepsilon;
23572 0 : e1 = eps*md*(mx*absasum+mb);
23573 0 : e2 = eps*md*(mx*ae_sqrt(absasum2, _state)+mb);
23574 0 : d1esterror = ae_sqrt(e1*e2, _state);
23575 0 : if( ae_fp_less_eq(ae_fabs(d1, _state),d1esterror) )
23576 : {
23577 0 : *d1est = 0;
23578 : }
23579 : else
23580 : {
23581 0 : *d1est = ae_sign(d1, _state);
23582 : }
23583 0 : e1 = eps*md*md*absasum;
23584 0 : e2 = eps*md*md*ae_sqrt(absasum2, _state);
23585 0 : d2esterror = ae_sqrt(e1*e2, _state);
23586 0 : if( ae_fp_less_eq(ae_fabs(d2, _state),d2esterror) )
23587 : {
23588 0 : *d2est = 0;
23589 : }
23590 : else
23591 : {
23592 0 : *d2est = ae_sign(d2, _state);
23593 : }
23594 0 : }
23595 :
23596 :
23597 : /*************************************************************************
23598 : This function calculates inexact rank-K preconditioner for Hessian matrix
23599 : H=D+W'*C*W, where:
23600 : * H is a Hessian matrix, which is approximated by D/W/C
23601 : * D is a diagonal matrix with positive entries
23602 : * W is a rank-K correction
23603 : * C is a diagonal factor of rank-K correction
23604 :
23605 : This preconditioner is inexact but fast - it requires O(N*K) time to be
23606 : applied. Its main purpose - to be used in barrier/penalty/AUL methods,
23607 : where ill-conditioning is created by combination of two factors:
23608 : * simple bounds on variables => ill-conditioned D
23609 : * general barrier/penalty => correction W with large coefficient C (makes
23610 : problem ill-conditioned) but W itself is well conditioned.
23611 :
23612 : Preconditioner P is calculated by artificially constructing a set of BFGS
23613 : updates which tries to reproduce behavior of H:
23614 : * Sk = Wk (k-th row of W)
23615 : * Yk = (D+Wk'*Ck*Wk)*Sk
23616 : * Yk/Sk are reordered by ascending of C[k]*norm(Wk)^2
23617 :
23618 : Here we assume that rows of Wk are orthogonal or nearly orthogonal, which
23619 : allows us to have O(N*K+K^2) update instead of O(N*K^2) one. Reordering of
23620 : updates is essential for having good performance on non-orthogonal problems
23621 : (updates which do not add much of curvature are added first, and updates
23622 : which add very large eigenvalues are added last and override effect of the
23623 : first updates).
23624 :
23625 : On input this function takes direction S and components of H.
23626 : On output it returns inv(H)*S
23627 :
23628 : -- ALGLIB --
23629 : Copyright 30.06.2014 by Bochkanov Sergey
23630 : *************************************************************************/
23631 0 : void inexactlbfgspreconditioner(/* Real */ ae_vector* s,
23632 : ae_int_t n,
23633 : /* Real */ ae_vector* d,
23634 : /* Real */ ae_vector* c,
23635 : /* Real */ ae_matrix* w,
23636 : ae_int_t k,
23637 : precbuflbfgs* buf,
23638 : ae_state *_state)
23639 : {
23640 : ae_int_t idx;
23641 : ae_int_t i;
23642 : ae_int_t j;
23643 : double v;
23644 : double v0;
23645 : double v1;
23646 : double vx;
23647 : double vy;
23648 :
23649 :
23650 0 : rvectorsetlengthatleast(&buf->norms, k, _state);
23651 0 : rvectorsetlengthatleast(&buf->alpha, k, _state);
23652 0 : rvectorsetlengthatleast(&buf->rho, k, _state);
23653 0 : rmatrixsetlengthatleast(&buf->yk, k, n, _state);
23654 0 : ivectorsetlengthatleast(&buf->idx, k, _state);
23655 :
23656 : /*
23657 : * Check inputs
23658 : */
23659 0 : for(i=0; i<=n-1; i++)
23660 : {
23661 0 : ae_assert(ae_fp_greater(d->ptr.p_double[i],(double)(0)), "InexactLBFGSPreconditioner: D[]<=0", _state);
23662 : }
23663 0 : for(i=0; i<=k-1; i++)
23664 : {
23665 0 : ae_assert(ae_fp_greater_eq(c->ptr.p_double[i],(double)(0)), "InexactLBFGSPreconditioner: C[]<0", _state);
23666 : }
23667 :
23668 : /*
23669 : * Reorder linear terms according to increase of second derivative.
23670 : * Fill Norms[] array.
23671 : */
23672 0 : for(idx=0; idx<=k-1; idx++)
23673 : {
23674 0 : v = ae_v_dotproduct(&w->ptr.pp_double[idx][0], 1, &w->ptr.pp_double[idx][0], 1, ae_v_len(0,n-1));
23675 0 : buf->norms.ptr.p_double[idx] = v*c->ptr.p_double[idx];
23676 0 : buf->idx.ptr.p_int[idx] = idx;
23677 : }
23678 0 : tagsortfasti(&buf->norms, &buf->idx, &buf->bufa, &buf->bufb, k, _state);
23679 :
23680 : /*
23681 : * Apply updates
23682 : */
23683 0 : for(idx=0; idx<=k-1; idx++)
23684 : {
23685 :
23686 : /*
23687 : * Select update to perform (ordered by ascending of second derivative)
23688 : */
23689 0 : i = buf->idx.ptr.p_int[idx];
23690 :
23691 : /*
23692 : * Calculate YK and Rho
23693 : */
23694 0 : v = ae_v_dotproduct(&w->ptr.pp_double[i][0], 1, &w->ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
23695 0 : v = v*c->ptr.p_double[i];
23696 0 : for(j=0; j<=n-1; j++)
23697 : {
23698 0 : buf->yk.ptr.pp_double[i][j] = (d->ptr.p_double[j]+v)*w->ptr.pp_double[i][j];
23699 : }
23700 0 : v = 0.0;
23701 0 : v0 = 0.0;
23702 0 : v1 = 0.0;
23703 0 : for(j=0; j<=n-1; j++)
23704 : {
23705 0 : vx = w->ptr.pp_double[i][j];
23706 0 : vy = buf->yk.ptr.pp_double[i][j];
23707 0 : v = v+vx*vy;
23708 0 : v0 = v0+vx*vx;
23709 0 : v1 = v1+vy*vy;
23710 : }
23711 0 : if( (ae_fp_greater(v,(double)(0))&&ae_fp_greater(v0*v1,(double)(0)))&&ae_fp_greater(v/ae_sqrt(v0*v1, _state),n*10*ae_machineepsilon) )
23712 : {
23713 0 : buf->rho.ptr.p_double[i] = 1/v;
23714 : }
23715 : else
23716 : {
23717 0 : buf->rho.ptr.p_double[i] = 0.0;
23718 : }
23719 : }
23720 0 : for(idx=k-1; idx>=0; idx--)
23721 : {
23722 :
23723 : /*
23724 : * Select update to perform (ordered by ascending of second derivative)
23725 : */
23726 0 : i = buf->idx.ptr.p_int[idx];
23727 :
23728 : /*
23729 : * Calculate Alpha[] according to L-BFGS algorithm
23730 : * and update S[]
23731 : */
23732 0 : v = ae_v_dotproduct(&w->ptr.pp_double[i][0], 1, &s->ptr.p_double[0], 1, ae_v_len(0,n-1));
23733 0 : v = buf->rho.ptr.p_double[i]*v;
23734 0 : buf->alpha.ptr.p_double[i] = v;
23735 0 : ae_v_subd(&s->ptr.p_double[0], 1, &buf->yk.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v);
23736 : }
23737 0 : for(j=0; j<=n-1; j++)
23738 : {
23739 0 : s->ptr.p_double[j] = s->ptr.p_double[j]/d->ptr.p_double[j];
23740 : }
23741 0 : for(idx=0; idx<=k-1; idx++)
23742 : {
23743 :
23744 : /*
23745 : * Select update to perform (ordered by ascending of second derivative)
23746 : */
23747 0 : i = buf->idx.ptr.p_int[idx];
23748 :
23749 : /*
23750 : * Calculate Beta according to L-BFGS algorithm
23751 : * and update S[]
23752 : */
23753 0 : v = ae_v_dotproduct(&buf->yk.ptr.pp_double[i][0], 1, &s->ptr.p_double[0], 1, ae_v_len(0,n-1));
23754 0 : v = buf->alpha.ptr.p_double[i]-buf->rho.ptr.p_double[i]*v;
23755 0 : ae_v_addd(&s->ptr.p_double[0], 1, &w->ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v);
23756 : }
23757 0 : }
23758 :
23759 :
23760 : /*************************************************************************
23761 : This function prepares exact low-rank preconditioner for Hessian matrix
23762 : H=D+W'*C*W, where:
23763 : * H is a Hessian matrix, which is approximated by D/W/C
23764 : * D is a diagonal matrix with positive entries
23765 : * W is a rank-K correction
23766 : * C is a diagonal factor of rank-K correction, positive semidefinite
23767 :
23768 : This preconditioner is exact but relatively slow - it requires O(N*K^2)
23769 : time to be prepared and O(N*K) time to be applied. It is calculated with
23770 : the help of Woodbury matrix identity.
23771 :
23772 : It should be used as follows:
23773 : * PrepareLowRankPreconditioner() call PREPARES data structure
23774 : * subsequent calls to ApplyLowRankPreconditioner() APPLY preconditioner to
23775 : user-specified search direction.
23776 :
23777 : -- ALGLIB --
23778 : Copyright 30.06.2014 by Bochkanov Sergey
23779 : *************************************************************************/
23780 0 : void preparelowrankpreconditioner(/* Real */ ae_vector* d,
23781 : /* Real */ ae_vector* c,
23782 : /* Real */ ae_matrix* w,
23783 : ae_int_t n,
23784 : ae_int_t k,
23785 : precbuflowrank* buf,
23786 : ae_state *_state)
23787 : {
23788 : ae_int_t i;
23789 : ae_int_t j;
23790 : double v;
23791 : ae_bool b;
23792 :
23793 :
23794 :
23795 : /*
23796 : * Check inputs
23797 : */
23798 0 : ae_assert(n>0, "PrepareLowRankPreconditioner: N<=0", _state);
23799 0 : ae_assert(k>=0, "PrepareLowRankPreconditioner: N<=0", _state);
23800 0 : for(i=0; i<=n-1; i++)
23801 : {
23802 0 : ae_assert(ae_fp_greater(d->ptr.p_double[i],(double)(0)), "PrepareLowRankPreconditioner: D[]<=0", _state);
23803 : }
23804 0 : for(i=0; i<=k-1; i++)
23805 : {
23806 0 : ae_assert(ae_fp_greater_eq(c->ptr.p_double[i],(double)(0)), "PrepareLowRankPreconditioner: C[]<0", _state);
23807 : }
23808 :
23809 : /*
23810 : * Prepare buffer structure; skip zero entries of update.
23811 : */
23812 0 : rvectorsetlengthatleast(&buf->d, n, _state);
23813 0 : rmatrixsetlengthatleast(&buf->v, k, n, _state);
23814 0 : rvectorsetlengthatleast(&buf->bufc, k, _state);
23815 0 : rmatrixsetlengthatleast(&buf->bufw, k+1, n, _state);
23816 0 : buf->n = n;
23817 0 : buf->k = 0;
23818 0 : for(i=0; i<=k-1; i++)
23819 : {
23820 :
23821 : /*
23822 : * Estimate magnitude of update row; skip zero rows (either W or C are zero)
23823 : */
23824 0 : v = 0.0;
23825 0 : for(j=0; j<=n-1; j++)
23826 : {
23827 0 : v = v+w->ptr.pp_double[i][j]*w->ptr.pp_double[i][j];
23828 : }
23829 0 : v = v*c->ptr.p_double[i];
23830 0 : if( ae_fp_eq(v,(double)(0)) )
23831 : {
23832 0 : continue;
23833 : }
23834 0 : ae_assert(ae_fp_greater(v,(double)(0)), "PrepareLowRankPreconditioner: internal error", _state);
23835 :
23836 : /*
23837 : * Copy non-zero update to buffer
23838 : */
23839 0 : buf->bufc.ptr.p_double[buf->k] = c->ptr.p_double[i];
23840 0 : for(j=0; j<=n-1; j++)
23841 : {
23842 0 : buf->v.ptr.pp_double[buf->k][j] = w->ptr.pp_double[i][j];
23843 0 : buf->bufw.ptr.pp_double[buf->k][j] = w->ptr.pp_double[i][j];
23844 : }
23845 0 : inc(&buf->k, _state);
23846 : }
23847 :
23848 : /*
23849 : * Reset K (for convenience)
23850 : */
23851 0 : k = buf->k;
23852 :
23853 : /*
23854 : * Prepare diagonal factor; quick exit for K=0
23855 : */
23856 0 : for(i=0; i<=n-1; i++)
23857 : {
23858 0 : buf->d.ptr.p_double[i] = 1/d->ptr.p_double[i];
23859 : }
23860 0 : if( k==0 )
23861 : {
23862 0 : return;
23863 : }
23864 :
23865 : /*
23866 : * Use Woodbury matrix identity
23867 : */
23868 0 : rmatrixsetlengthatleast(&buf->bufz, k, k, _state);
23869 0 : for(i=0; i<=k-1; i++)
23870 : {
23871 0 : for(j=0; j<=k-1; j++)
23872 : {
23873 0 : buf->bufz.ptr.pp_double[i][j] = 0.0;
23874 : }
23875 : }
23876 0 : for(i=0; i<=k-1; i++)
23877 : {
23878 0 : buf->bufz.ptr.pp_double[i][i] = 1/buf->bufc.ptr.p_double[i];
23879 : }
23880 0 : for(j=0; j<=n-1; j++)
23881 : {
23882 0 : buf->bufw.ptr.pp_double[k][j] = 1/ae_sqrt(d->ptr.p_double[j], _state);
23883 : }
23884 0 : for(i=0; i<=k-1; i++)
23885 : {
23886 0 : for(j=0; j<=n-1; j++)
23887 : {
23888 0 : buf->bufw.ptr.pp_double[i][j] = buf->bufw.ptr.pp_double[i][j]*buf->bufw.ptr.pp_double[k][j];
23889 : }
23890 : }
23891 0 : rmatrixgemm(k, k, n, 1.0, &buf->bufw, 0, 0, 0, &buf->bufw, 0, 0, 1, 1.0, &buf->bufz, 0, 0, _state);
23892 0 : b = spdmatrixcholeskyrec(&buf->bufz, 0, k, ae_true, &buf->tmp, _state);
23893 0 : ae_assert(b, "PrepareLowRankPreconditioner: internal error (Cholesky failure)", _state);
23894 0 : rmatrixlefttrsm(k, n, &buf->bufz, 0, 0, ae_true, ae_false, 1, &buf->v, 0, 0, _state);
23895 0 : for(i=0; i<=k-1; i++)
23896 : {
23897 0 : for(j=0; j<=n-1; j++)
23898 : {
23899 0 : buf->v.ptr.pp_double[i][j] = buf->v.ptr.pp_double[i][j]*buf->d.ptr.p_double[j];
23900 : }
23901 : }
23902 : }
23903 :
23904 :
23905 : /*************************************************************************
23906 : This function apply exact low-rank preconditioner prepared by
23907 : PrepareLowRankPreconditioner function (see its comments for more information).
23908 :
23909 : -- ALGLIB --
23910 : Copyright 30.06.2014 by Bochkanov Sergey
23911 : *************************************************************************/
23912 0 : void applylowrankpreconditioner(/* Real */ ae_vector* s,
23913 : precbuflowrank* buf,
23914 : ae_state *_state)
23915 : {
23916 : ae_int_t n;
23917 : ae_int_t k;
23918 : ae_int_t i;
23919 : ae_int_t j;
23920 : double v;
23921 :
23922 :
23923 0 : n = buf->n;
23924 0 : k = buf->k;
23925 0 : rvectorsetlengthatleast(&buf->tmp, n, _state);
23926 0 : for(j=0; j<=n-1; j++)
23927 : {
23928 0 : buf->tmp.ptr.p_double[j] = buf->d.ptr.p_double[j]*s->ptr.p_double[j];
23929 : }
23930 0 : for(i=0; i<=k-1; i++)
23931 : {
23932 0 : v = 0.0;
23933 0 : for(j=0; j<=n-1; j++)
23934 : {
23935 0 : v = v+buf->v.ptr.pp_double[i][j]*s->ptr.p_double[j];
23936 : }
23937 0 : for(j=0; j<=n-1; j++)
23938 : {
23939 0 : buf->tmp.ptr.p_double[j] = buf->tmp.ptr.p_double[j]-v*buf->v.ptr.pp_double[i][j];
23940 : }
23941 : }
23942 0 : for(i=0; i<=n-1; i++)
23943 : {
23944 0 : s->ptr.p_double[i] = buf->tmp.ptr.p_double[i];
23945 : }
23946 0 : }
23947 :
23948 :
23949 : /*************************************************************************
23950 : This subroutine initializes smoothness monitor at the beginning of the
23951 : optimization session. It requires variable scales to be passed.
23952 :
23953 : It is possible to perform "dummy" initialization with N=K=0.
23954 :
23955 : -- ALGLIB --
23956 : Copyright 19.11.2018 by Bochkanov Sergey
23957 : *************************************************************************/
23958 996 : void smoothnessmonitorinit(smoothnessmonitor* monitor,
23959 : /* Real */ ae_vector* s,
23960 : ae_int_t n,
23961 : ae_int_t k,
23962 : ae_bool checksmoothness,
23963 : ae_state *_state)
23964 : {
23965 : ae_int_t i;
23966 :
23967 :
23968 996 : monitor->n = n;
23969 996 : monitor->k = k;
23970 996 : monitor->checksmoothness = checksmoothness;
23971 996 : monitor->linesearchspoiled = ae_false;
23972 996 : monitor->linesearchstarted = ae_false;
23973 996 : monitor->enqueuedcnt = 0;
23974 996 : monitor->sortedcnt = 0;
23975 996 : rvectorsetlengthatleast(&monitor->s, n, _state);
23976 1992 : for(i=0; i<=n-1; i++)
23977 : {
23978 996 : monitor->s.ptr.p_double[i] = s->ptr.p_double[i];
23979 : }
23980 996 : monitor->nonc0currentrating = 0.0;
23981 996 : monitor->nonc1currentrating = 0.0;
23982 996 : optguardinitinternal(&monitor->rep, n, k, _state);
23983 996 : monitor->nonc0strrating = 0.0;
23984 996 : monitor->nonc0lngrating = -ae_maxrealnumber;
23985 996 : monitor->nonc0strrep.positive = ae_false;
23986 996 : monitor->nonc0lngrep.positive = ae_false;
23987 996 : monitor->nonc1test0strrating = 0.0;
23988 996 : monitor->nonc1test0lngrating = -ae_maxrealnumber;
23989 996 : monitor->nonc1test0strrep.positive = ae_false;
23990 996 : monitor->nonc1test0lngrep.positive = ae_false;
23991 996 : monitor->nonc1test1strrating = 0.0;
23992 996 : monitor->nonc1test1lngrating = -ae_maxrealnumber;
23993 996 : monitor->nonc1test1strrep.positive = ae_false;
23994 996 : monitor->nonc1test1lngrep.positive = ae_false;
23995 996 : monitor->badgradhasxj = ae_false;
23996 996 : ae_vector_set_length(&monitor->rstateg0.ia, 4+1, _state);
23997 996 : ae_vector_set_length(&monitor->rstateg0.ra, 3+1, _state);
23998 996 : monitor->rstateg0.stage = -1;
23999 996 : }
24000 :
24001 :
24002 : /*************************************************************************
24003 : This subroutine starts line search
24004 :
24005 : -- ALGLIB --
24006 : Copyright 19.11.2018 by Bochkanov Sergey
24007 : *************************************************************************/
24008 0 : void smoothnessmonitorstartlinesearch(smoothnessmonitor* monitor,
24009 : /* Real */ ae_vector* x,
24010 : /* Real */ ae_vector* fi,
24011 : /* Real */ ae_matrix* jac,
24012 : ae_state *_state)
24013 : {
24014 : ae_int_t n;
24015 : ae_int_t k;
24016 : ae_int_t i;
24017 : ae_int_t j;
24018 : double v;
24019 :
24020 :
24021 0 : n = monitor->n;
24022 0 : k = monitor->k;
24023 :
24024 : /*
24025 : * Skip if inactive or spoiled by NAN
24026 : */
24027 0 : if( !monitor->checksmoothness )
24028 : {
24029 0 : return;
24030 : }
24031 0 : v = (double)(0);
24032 0 : for(i=0; i<=n-1; i++)
24033 : {
24034 0 : v = 0.5*v+x->ptr.p_double[i];
24035 : }
24036 0 : for(i=0; i<=k-1; i++)
24037 : {
24038 0 : v = 0.5*v+fi->ptr.p_double[i];
24039 : }
24040 0 : for(i=0; i<=k-1; i++)
24041 : {
24042 0 : for(j=0; j<=n-1; j++)
24043 : {
24044 0 : v = 0.5*v+jac->ptr.pp_double[i][j];
24045 : }
24046 : }
24047 0 : if( !ae_isfinite(v, _state) )
24048 : {
24049 0 : monitor->linesearchspoiled = ae_true;
24050 0 : return;
24051 : }
24052 :
24053 : /*
24054 : * Finalize previous line search
24055 : */
24056 0 : if( monitor->enqueuedcnt>0 )
24057 : {
24058 0 : smoothnessmonitorfinalizelinesearch(monitor, _state);
24059 : }
24060 :
24061 : /*
24062 : * Store initial point
24063 : */
24064 0 : monitor->linesearchstarted = ae_true;
24065 0 : monitor->enqueuedcnt = 1;
24066 0 : rvectorgrowto(&monitor->enqueuedstp, monitor->enqueuedcnt, _state);
24067 0 : rvectorgrowto(&monitor->enqueuedx, monitor->enqueuedcnt*n, _state);
24068 0 : rvectorgrowto(&monitor->enqueuedfunc, monitor->enqueuedcnt*k, _state);
24069 0 : rmatrixgrowrowsto(&monitor->enqueuedjac, monitor->enqueuedcnt*k, n, _state);
24070 0 : monitor->enqueuedstp.ptr.p_double[0] = 0.0;
24071 0 : for(j=0; j<=n-1; j++)
24072 : {
24073 0 : monitor->enqueuedx.ptr.p_double[j] = x->ptr.p_double[j];
24074 : }
24075 0 : for(i=0; i<=k-1; i++)
24076 : {
24077 0 : monitor->enqueuedfunc.ptr.p_double[i] = fi->ptr.p_double[i];
24078 : }
24079 0 : for(i=0; i<=k-1; i++)
24080 : {
24081 0 : for(j=0; j<=n-1; j++)
24082 : {
24083 0 : monitor->enqueuedjac.ptr.pp_double[i][j] = jac->ptr.pp_double[i][j];
24084 : }
24085 : }
24086 :
24087 : /*
24088 : * Initialize sorted representation
24089 : */
24090 0 : rvectorgrowto(&monitor->sortedstp, 1, _state);
24091 0 : ivectorgrowto(&monitor->sortedidx, 1, _state);
24092 0 : monitor->sortedstp.ptr.p_double[0] = 0.0;
24093 0 : monitor->sortedidx.ptr.p_int[0] = 0;
24094 0 : monitor->sortedcnt = 1;
24095 : }
24096 :
24097 :
24098 : /*************************************************************************
24099 : This subroutine starts line search for a scalar function - convenience
24100 : wrapper for ....StartLineSearch() with unscaled variables.
24101 :
24102 : -- ALGLIB --
24103 : Copyright 19.11.2018 by Bochkanov Sergey
24104 : *************************************************************************/
24105 1269 : void smoothnessmonitorstartlinesearch1u(smoothnessmonitor* monitor,
24106 : /* Real */ ae_vector* s,
24107 : /* Real */ ae_vector* invs,
24108 : /* Real */ ae_vector* x,
24109 : double f0,
24110 : /* Real */ ae_vector* j0,
24111 : ae_state *_state)
24112 : {
24113 : ae_int_t n;
24114 : ae_int_t k;
24115 : ae_int_t i;
24116 :
24117 :
24118 1269 : n = monitor->n;
24119 1269 : k = monitor->k;
24120 1269 : if( !monitor->checksmoothness )
24121 : {
24122 1269 : return;
24123 : }
24124 0 : ae_assert(k==1, "SmoothnessMonitorStartLineSearch1: K<>1", _state);
24125 0 : rvectorsetlengthatleast(&monitor->xu, n, _state);
24126 0 : rvectorsetlengthatleast(&monitor->f0, 1, _state);
24127 0 : rmatrixsetlengthatleast(&monitor->j0, 1, n, _state);
24128 0 : monitor->f0.ptr.p_double[0] = f0;
24129 0 : for(i=0; i<=n-1; i++)
24130 : {
24131 0 : monitor->xu.ptr.p_double[i] = x->ptr.p_double[i]*invs->ptr.p_double[i];
24132 0 : monitor->j0.ptr.pp_double[0][i] = j0->ptr.p_double[i]*s->ptr.p_double[i];
24133 : }
24134 0 : smoothnessmonitorstartlinesearch(monitor, &monitor->xu, &monitor->f0, &monitor->j0, _state);
24135 : }
24136 :
24137 :
24138 : /*************************************************************************
24139 : This subroutine enqueues one more trial point
24140 :
24141 : -- ALGLIB --
24142 : Copyright 19.11.2018 by Bochkanov Sergey
24143 : *************************************************************************/
24144 0 : void smoothnessmonitorenqueuepoint(smoothnessmonitor* monitor,
24145 : /* Real */ ae_vector* d,
24146 : double stp,
24147 : /* Real */ ae_vector* x,
24148 : /* Real */ ae_vector* fi,
24149 : /* Real */ ae_matrix* jac,
24150 : ae_state *_state)
24151 : {
24152 : ae_int_t n;
24153 : ae_int_t k;
24154 : ae_int_t i;
24155 : ae_int_t j;
24156 : double v;
24157 : ae_int_t enqueuedcnt;
24158 : ae_int_t sortedcnt;
24159 : ae_bool hasduplicates;
24160 : ae_int_t funcidx;
24161 : ae_int_t stpidx;
24162 : double f0;
24163 : double f1;
24164 : double f2;
24165 : double f3;
24166 : double f4;
24167 : double noise0;
24168 : double noise1;
24169 : double noise2;
24170 : double noise3;
24171 : double rating;
24172 : double lipschitz;
24173 : double nrm;
24174 : double lengthrating;
24175 :
24176 :
24177 0 : n = monitor->n;
24178 0 : k = monitor->k;
24179 :
24180 : /*
24181 : * Skip if inactive or spoiled by NAN
24182 : */
24183 0 : if( (!monitor->checksmoothness||monitor->linesearchspoiled)||!monitor->linesearchstarted )
24184 : {
24185 0 : return;
24186 : }
24187 0 : v = stp;
24188 0 : for(i=0; i<=n-1; i++)
24189 : {
24190 0 : v = 0.5*v+x->ptr.p_double[i];
24191 : }
24192 0 : for(i=0; i<=n-1; i++)
24193 : {
24194 0 : v = 0.5*v+d->ptr.p_double[i];
24195 : }
24196 0 : for(i=0; i<=k-1; i++)
24197 : {
24198 0 : v = 0.5*v+fi->ptr.p_double[i];
24199 : }
24200 0 : for(i=0; i<=k-1; i++)
24201 : {
24202 0 : for(j=0; j<=n-1; j++)
24203 : {
24204 0 : v = 0.5*v+jac->ptr.pp_double[i][j];
24205 : }
24206 : }
24207 0 : if( !ae_isfinite(v, _state) )
24208 : {
24209 0 : monitor->linesearchspoiled = ae_true;
24210 0 : return;
24211 : }
24212 :
24213 : /*
24214 : * Enqueue
24215 : */
24216 0 : inc(&monitor->enqueuedcnt, _state);
24217 0 : enqueuedcnt = monitor->enqueuedcnt;
24218 0 : rvectorgrowto(&monitor->dcur, n, _state);
24219 0 : rvectorgrowto(&monitor->enqueuedstp, enqueuedcnt, _state);
24220 0 : rvectorgrowto(&monitor->enqueuedx, enqueuedcnt*n, _state);
24221 0 : rvectorgrowto(&monitor->enqueuedfunc, enqueuedcnt*k, _state);
24222 0 : rmatrixgrowrowsto(&monitor->enqueuedjac, enqueuedcnt*k, n, _state);
24223 0 : monitor->enqueuedstp.ptr.p_double[enqueuedcnt-1] = stp;
24224 0 : for(j=0; j<=n-1; j++)
24225 : {
24226 0 : monitor->dcur.ptr.p_double[j] = d->ptr.p_double[j];
24227 : }
24228 0 : for(j=0; j<=n-1; j++)
24229 : {
24230 0 : monitor->enqueuedx.ptr.p_double[(enqueuedcnt-1)*n+j] = x->ptr.p_double[j];
24231 : }
24232 0 : for(i=0; i<=k-1; i++)
24233 : {
24234 0 : monitor->enqueuedfunc.ptr.p_double[(enqueuedcnt-1)*k+i] = fi->ptr.p_double[i];
24235 : }
24236 0 : for(i=0; i<=k-1; i++)
24237 : {
24238 0 : for(j=0; j<=n-1; j++)
24239 : {
24240 0 : monitor->enqueuedjac.ptr.pp_double[(enqueuedcnt-1)*k+i][j] = jac->ptr.pp_double[i][j];
24241 : }
24242 : }
24243 :
24244 : /*
24245 : * Update sorted representation: insert to the end, reorder
24246 : */
24247 0 : sortedcnt = monitor->sortedcnt;
24248 0 : hasduplicates = ae_false;
24249 0 : for(i=0; i<=sortedcnt-1; i++)
24250 : {
24251 0 : hasduplicates = hasduplicates||monitor->sortedstp.ptr.p_double[i]==stp;
24252 : }
24253 0 : if( !hasduplicates )
24254 : {
24255 0 : inc(&monitor->sortedcnt, _state);
24256 0 : sortedcnt = monitor->sortedcnt;
24257 0 : rvectorgrowto(&monitor->sortedstp, sortedcnt, _state);
24258 0 : ivectorgrowto(&monitor->sortedidx, sortedcnt, _state);
24259 0 : monitor->sortedstp.ptr.p_double[sortedcnt-1] = stp;
24260 0 : monitor->sortedidx.ptr.p_int[sortedcnt-1] = enqueuedcnt-1;
24261 0 : for(i=sortedcnt-2; i>=0; i--)
24262 : {
24263 0 : if( monitor->sortedstp.ptr.p_double[i]<=monitor->sortedstp.ptr.p_double[i+1] )
24264 : {
24265 0 : break;
24266 : }
24267 0 : v = monitor->sortedstp.ptr.p_double[i];
24268 0 : monitor->sortedstp.ptr.p_double[i] = monitor->sortedstp.ptr.p_double[i+1];
24269 0 : monitor->sortedstp.ptr.p_double[i+1] = v;
24270 0 : j = monitor->sortedidx.ptr.p_int[i];
24271 0 : monitor->sortedidx.ptr.p_int[i] = monitor->sortedidx.ptr.p_int[i+1];
24272 0 : monitor->sortedidx.ptr.p_int[i+1] = j;
24273 : }
24274 : }
24275 :
24276 : /*
24277 : * Scan sorted representation, check for C0 and C1 continuity
24278 : * violations.
24279 : */
24280 0 : rvectorsetlengthatleast(&monitor->f, sortedcnt, _state);
24281 0 : rvectorsetlengthatleast(&monitor->g, sortedcnt*n, _state);
24282 0 : for(funcidx=0; funcidx<=k-1; funcidx++)
24283 : {
24284 :
24285 : /*
24286 : * Fetch current function and its gradient to the contiguous storage
24287 : */
24288 0 : for(i=0; i<=sortedcnt-1; i++)
24289 : {
24290 0 : monitor->f.ptr.p_double[i] = monitor->enqueuedfunc.ptr.p_double[monitor->sortedidx.ptr.p_int[i]*k+funcidx];
24291 0 : for(j=0; j<=n-1; j++)
24292 : {
24293 0 : monitor->g.ptr.p_double[i*n+j] = monitor->enqueuedjac.ptr.pp_double[monitor->sortedidx.ptr.p_int[i]*k+funcidx][j];
24294 : }
24295 : }
24296 :
24297 : /*
24298 : * Check C0 continuity.
24299 : *
24300 : * The basis approach is that we find appropriate candidate point
24301 : * (either a local minimum along the line - for target; or an interval
24302 : * where function sign is changed - for constraints), calculate left
24303 : * and right estimates of the Lipschitz constant (slopes between points
24304 : * #0 and #1, #2 and #3), and then calculate slope between points #1 and
24305 : * #2 and compare it with left/right estimates.
24306 : *
24307 : * The actual approach is a bit more complex to account for different
24308 : * sources of numerical noise and different false positive scenarios.
24309 : */
24310 0 : if( funcidx==0 )
24311 : {
24312 0 : for(stpidx=0; stpidx<=sortedcnt-4; stpidx++)
24313 : {
24314 0 : f0 = monitor->f.ptr.p_double[stpidx+0];
24315 0 : f1 = monitor->f.ptr.p_double[stpidx+1];
24316 0 : f2 = monitor->f.ptr.p_double[stpidx+2];
24317 0 : f3 = monitor->f.ptr.p_double[stpidx+3];
24318 0 : noise0 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f0, _state), 1.0, _state);
24319 0 : noise1 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f1, _state), 1.0, _state);
24320 0 : noise2 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f2, _state), 1.0, _state);
24321 0 : noise3 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f3, _state), 1.0, _state);
24322 0 : if( !(f1<f0+(noise0+noise1)&&f1<f2) )
24323 : {
24324 0 : continue;
24325 : }
24326 0 : optserv_testc0continuity(f0, f1, f2, f3, noise0, noise1, noise2, noise3, monitor->sortedstp.ptr.p_double[stpidx+1]-monitor->sortedstp.ptr.p_double[stpidx+0], monitor->sortedstp.ptr.p_double[stpidx+2]-monitor->sortedstp.ptr.p_double[stpidx+1], monitor->sortedstp.ptr.p_double[stpidx+3]-monitor->sortedstp.ptr.p_double[stpidx+2], ae_false, &rating, &lipschitz, _state);
24327 0 : if( rating>optserv_ogminrating0 )
24328 : {
24329 :
24330 : /*
24331 : * Store to total report
24332 : */
24333 0 : monitor->rep.nonc0suspected = ae_true;
24334 0 : monitor->rep.nonc0test0positive = ae_true;
24335 0 : if( rating>monitor->nonc0currentrating )
24336 : {
24337 0 : monitor->nonc0currentrating = rating;
24338 0 : monitor->rep.nonc0lipschitzc = lipschitz;
24339 0 : monitor->rep.nonc0fidx = funcidx;
24340 : }
24341 :
24342 : /*
24343 : * Store to "strongest" report
24344 : */
24345 0 : if( rating>monitor->nonc0strrating )
24346 : {
24347 0 : monitor->nonc0strrating = rating;
24348 0 : monitor->nonc0strrep.positive = ae_true;
24349 0 : monitor->nonc0strrep.fidx = funcidx;
24350 0 : monitor->nonc0strrep.n = n;
24351 0 : monitor->nonc0strrep.cnt = sortedcnt;
24352 0 : monitor->nonc0strrep.stpidxa = stpidx+0;
24353 0 : monitor->nonc0strrep.stpidxb = stpidx+3;
24354 0 : rvectorsetlengthatleast(&monitor->nonc0strrep.x0, n, _state);
24355 0 : rvectorsetlengthatleast(&monitor->nonc0strrep.d, n, _state);
24356 0 : for(i=0; i<=n-1; i++)
24357 : {
24358 0 : monitor->nonc0strrep.x0.ptr.p_double[i] = monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[0]*n+i];
24359 0 : monitor->nonc0strrep.d.ptr.p_double[i] = monitor->dcur.ptr.p_double[i];
24360 : }
24361 0 : rvectorsetlengthatleast(&monitor->nonc0strrep.stp, sortedcnt, _state);
24362 0 : rvectorsetlengthatleast(&monitor->nonc0strrep.f, sortedcnt, _state);
24363 0 : for(i=0; i<=sortedcnt-1; i++)
24364 : {
24365 0 : monitor->nonc0strrep.stp.ptr.p_double[i] = monitor->sortedstp.ptr.p_double[i];
24366 0 : monitor->nonc0strrep.f.ptr.p_double[i] = monitor->f.ptr.p_double[i];
24367 : }
24368 : }
24369 :
24370 : /*
24371 : * Store to "longest" report
24372 : */
24373 0 : nrm = (double)(0);
24374 0 : for(i=0; i<=n-1; i++)
24375 : {
24376 0 : nrm = nrm+ae_sqr(monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[0]*n+i]-monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[sortedcnt-1]*n+i], _state);
24377 : }
24378 0 : nrm = ae_sqrt(nrm, _state);
24379 0 : nrm = ae_minreal(nrm, 1.0, _state);
24380 0 : nrm = coalesce(nrm, ae_machineepsilon, _state);
24381 0 : lengthrating = sortedcnt+ae_log(nrm, _state)/ae_log((double)(100), _state);
24382 0 : if( lengthrating>monitor->nonc0lngrating )
24383 : {
24384 0 : monitor->nonc0lngrating = lengthrating;
24385 0 : monitor->nonc0lngrep.positive = ae_true;
24386 0 : monitor->nonc0lngrep.fidx = funcidx;
24387 0 : monitor->nonc0lngrep.n = n;
24388 0 : monitor->nonc0lngrep.cnt = sortedcnt;
24389 0 : monitor->nonc0lngrep.stpidxa = stpidx+0;
24390 0 : monitor->nonc0lngrep.stpidxb = stpidx+3;
24391 0 : rvectorsetlengthatleast(&monitor->nonc0lngrep.x0, n, _state);
24392 0 : rvectorsetlengthatleast(&monitor->nonc0lngrep.d, n, _state);
24393 0 : for(i=0; i<=n-1; i++)
24394 : {
24395 0 : monitor->nonc0lngrep.x0.ptr.p_double[i] = monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[0]*n+i];
24396 0 : monitor->nonc0lngrep.d.ptr.p_double[i] = monitor->dcur.ptr.p_double[i];
24397 : }
24398 0 : rvectorsetlengthatleast(&monitor->nonc0lngrep.stp, sortedcnt, _state);
24399 0 : rvectorsetlengthatleast(&monitor->nonc0lngrep.f, sortedcnt, _state);
24400 0 : for(i=0; i<=sortedcnt-1; i++)
24401 : {
24402 0 : monitor->nonc0lngrep.stp.ptr.p_double[i] = monitor->sortedstp.ptr.p_double[i];
24403 0 : monitor->nonc0lngrep.f.ptr.p_double[i] = monitor->f.ptr.p_double[i];
24404 : }
24405 : }
24406 : }
24407 : }
24408 : }
24409 :
24410 : /*
24411 : * C1 continuity test #0
24412 : */
24413 0 : for(stpidx=0; stpidx<=sortedcnt-7; stpidx++)
24414 : {
24415 :
24416 : /*
24417 : * Fetch function values
24418 : */
24419 0 : f2 = monitor->f.ptr.p_double[stpidx+2];
24420 0 : f3 = monitor->f.ptr.p_double[stpidx+3];
24421 0 : f4 = monitor->f.ptr.p_double[stpidx+4];
24422 0 : noise2 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f2, _state), 1.0, _state);
24423 0 : noise3 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f3, _state), 1.0, _state);
24424 :
24425 : /*
24426 : * Decide whether we want to test this interval or not; for target
24427 : * function we test intervals around minimum, for constraints we
24428 : * test intervals of sign change.
24429 : */
24430 0 : if( funcidx==0 )
24431 : {
24432 :
24433 : /*
24434 : * Skip if not minimum
24435 : */
24436 0 : if( !(f3<f2+(noise2+noise3)&&f3<f4) )
24437 : {
24438 0 : continue;
24439 : }
24440 : }
24441 : else
24442 : {
24443 :
24444 : /*
24445 : * Skip if sign does not change
24446 : */
24447 0 : if( ae_sign(f2*f4, _state)>0 )
24448 : {
24449 0 : continue;
24450 : }
24451 : }
24452 0 : optserv_c1continuitytest0(monitor, funcidx, stpidx+0, sortedcnt, _state);
24453 0 : optserv_c1continuitytest0(monitor, funcidx, stpidx+1, sortedcnt, _state);
24454 : }
24455 :
24456 : /*
24457 : * C1 continuity test #1
24458 : */
24459 0 : for(stpidx=0; stpidx<=sortedcnt-4; stpidx++)
24460 : {
24461 :
24462 : /*
24463 : * Fetch function values from the interval being tested
24464 : */
24465 0 : f0 = monitor->f.ptr.p_double[stpidx+0];
24466 0 : f1 = monitor->f.ptr.p_double[stpidx+1];
24467 0 : f2 = monitor->f.ptr.p_double[stpidx+2];
24468 0 : f3 = monitor->f.ptr.p_double[stpidx+3];
24469 0 : noise0 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f0, _state), 1.0, _state);
24470 0 : noise1 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f1, _state), 1.0, _state);
24471 0 : noise2 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f2, _state), 1.0, _state);
24472 0 : noise3 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f3, _state), 1.0, _state);
24473 :
24474 : /*
24475 : * Decide whether we want to test this interval or not; for target
24476 : * function we test intervals around minimum, for constraints we
24477 : * test intervals of sign change.
24478 : */
24479 0 : if( funcidx==0 )
24480 : {
24481 :
24482 : /*
24483 : * Skip if not minimum
24484 : */
24485 0 : if( !(f1<f0+(noise0+noise1)&&f2<f3+noise2+noise3) )
24486 : {
24487 0 : continue;
24488 : }
24489 : }
24490 : else
24491 : {
24492 :
24493 : /*
24494 : * Skip if sign does not change
24495 : */
24496 0 : if( ae_sign(f0*f3, _state)>0 )
24497 : {
24498 0 : continue;
24499 : }
24500 : }
24501 0 : optserv_c1continuitytest1(monitor, funcidx, stpidx, sortedcnt, _state);
24502 : }
24503 : }
24504 : }
24505 :
24506 :
24507 : /*************************************************************************
24508 : This subroutine enqueues one more trial point for a task with scalar
24509 : function with unscaled variables - a convenience wrapper for more general
24510 : EnqueuePoint()
24511 :
24512 : -- ALGLIB --
24513 : Copyright 19.11.2018 by Bochkanov Sergey
24514 : *************************************************************************/
24515 4391 : void smoothnessmonitorenqueuepoint1u(smoothnessmonitor* monitor,
24516 : /* Real */ ae_vector* s,
24517 : /* Real */ ae_vector* invs,
24518 : /* Real */ ae_vector* d,
24519 : double stp,
24520 : /* Real */ ae_vector* x,
24521 : double f0,
24522 : /* Real */ ae_vector* j0,
24523 : ae_state *_state)
24524 : {
24525 : ae_int_t n;
24526 : ae_int_t k;
24527 : ae_int_t i;
24528 :
24529 :
24530 4391 : n = monitor->n;
24531 4391 : k = monitor->k;
24532 4391 : if( !monitor->checksmoothness )
24533 : {
24534 4391 : return;
24535 : }
24536 0 : ae_assert(k==1, "SmoothnessMonitorEnqueuePoint1: K<>1", _state);
24537 0 : rvectorsetlengthatleast(&monitor->xu, n, _state);
24538 0 : rvectorsetlengthatleast(&monitor->du, n, _state);
24539 0 : rvectorsetlengthatleast(&monitor->f0, 1, _state);
24540 0 : rmatrixsetlengthatleast(&monitor->j0, 1, n, _state);
24541 0 : monitor->f0.ptr.p_double[0] = f0;
24542 0 : for(i=0; i<=n-1; i++)
24543 : {
24544 0 : monitor->xu.ptr.p_double[i] = x->ptr.p_double[i]*invs->ptr.p_double[i];
24545 0 : monitor->du.ptr.p_double[i] = d->ptr.p_double[i]*invs->ptr.p_double[i];
24546 0 : monitor->j0.ptr.pp_double[0][i] = j0->ptr.p_double[i]*s->ptr.p_double[i];
24547 : }
24548 0 : smoothnessmonitorenqueuepoint(monitor, &monitor->du, stp, &monitor->xu, &monitor->f0, &monitor->j0, _state);
24549 : }
24550 :
24551 :
24552 : /*************************************************************************
24553 : This subroutine finalizes line search
24554 :
24555 : -- ALGLIB --
24556 : Copyright 19.11.2018 by Bochkanov Sergey
24557 : *************************************************************************/
24558 1269 : void smoothnessmonitorfinalizelinesearch(smoothnessmonitor* monitor,
24559 : ae_state *_state)
24560 : {
24561 :
24562 :
24563 :
24564 : /*
24565 : * As for now - nothing to be done.
24566 : */
24567 1269 : }
24568 :
24569 :
24570 : /*************************************************************************
24571 : This function starts aggressive probing for a range of step lengths [0,StpMax].
24572 :
24573 : This function stores NValues values per step, with the first one (index 0)
24574 : value being "primary" one (target function / merit function) and the rest
24575 : being supplementary ones.
24576 :
24577 : -- ALGLIB --
24578 : Copyright 10.10.2019 by Bochkanov Sergey
24579 : *************************************************************************/
24580 0 : void smoothnessmonitorstartprobing(smoothnessmonitor* monitor,
24581 : double stpmax,
24582 : ae_int_t nvalues,
24583 : double stepscale,
24584 : ae_state *_state)
24585 : {
24586 :
24587 :
24588 0 : ae_assert(ae_isfinite(stpmax, _state)&&ae_fp_greater(stpmax,(double)(0)), "SmoothnessMonitorStartProbing: StpMax<=0", _state);
24589 0 : ae_assert(nvalues>=1, "SmoothnessMonitorStartProbing: NValues<1", _state);
24590 0 : ae_assert(ae_isfinite(stepscale, _state)&&ae_fp_greater_eq(stepscale,(double)(0)), "SmoothnessMonitorStartProbing: StepScale<0", _state);
24591 0 : monitor->probingnvalues = nvalues;
24592 0 : monitor->probingnstepsstored = 0;
24593 0 : monitor->probingstepmax = stpmax;
24594 0 : monitor->probingstepscale = stepscale;
24595 0 : rvectorsetlengthatleast(&monitor->probingf, nvalues, _state);
24596 0 : ae_vector_set_length(&monitor->probingrcomm.ia, 2+1, _state);
24597 0 : ae_vector_set_length(&monitor->probingrcomm.ra, 3+1, _state);
24598 0 : monitor->probingrcomm.stage = -1;
24599 0 : }
24600 :
24601 :
24602 : /*************************************************************************
24603 : This function performs aggressive probing.
24604 :
24605 : After each call it returns step to evaluate in Monitor.ProbingStp. Load
24606 : values being probed into Monitor.ProbingF and continue iteration.
24607 :
24608 : Monitor.ProbingF[0] is a special value which is used to guide probing process
24609 : towards discontinuities and nonsmooth points.
24610 :
24611 : -- ALGLIB --
24612 : Copyright 10.10.2019 by Bochkanov Sergey
24613 : *************************************************************************/
24614 0 : ae_bool smoothnessmonitorprobe(smoothnessmonitor* monitor,
24615 : ae_state *_state)
24616 : {
24617 : ae_int_t i;
24618 : ae_int_t j;
24619 : ae_int_t idx;
24620 : double vlargest;
24621 : double v;
24622 : double v0;
24623 : double v1;
24624 : ae_bool result;
24625 :
24626 :
24627 :
24628 : /*
24629 : * Reverse communication preparations
24630 : * I know it looks ugly, but it works the same way
24631 : * anywhere from C++ to Python.
24632 : *
24633 : * This code initializes locals by:
24634 : * * random values determined during code
24635 : * generation - on first subroutine call
24636 : * * values from previous call - on subsequent calls
24637 : */
24638 0 : if( monitor->probingrcomm.stage>=0 )
24639 : {
24640 0 : i = monitor->probingrcomm.ia.ptr.p_int[0];
24641 0 : j = monitor->probingrcomm.ia.ptr.p_int[1];
24642 0 : idx = monitor->probingrcomm.ia.ptr.p_int[2];
24643 0 : vlargest = monitor->probingrcomm.ra.ptr.p_double[0];
24644 0 : v = monitor->probingrcomm.ra.ptr.p_double[1];
24645 0 : v0 = monitor->probingrcomm.ra.ptr.p_double[2];
24646 0 : v1 = monitor->probingrcomm.ra.ptr.p_double[3];
24647 : }
24648 : else
24649 : {
24650 0 : i = 359;
24651 0 : j = -58;
24652 0 : idx = -919;
24653 0 : vlargest = -909;
24654 0 : v = 81;
24655 0 : v0 = 255;
24656 0 : v1 = 74;
24657 : }
24658 0 : if( monitor->probingrcomm.stage==0 )
24659 : {
24660 0 : goto lbl_0;
24661 : }
24662 :
24663 : /*
24664 : * Routine body
24665 : */
24666 0 : i = 0;
24667 0 : lbl_1:
24668 0 : if( i>40 )
24669 : {
24670 0 : goto lbl_3;
24671 : }
24672 :
24673 : /*
24674 : * Increase storage size
24675 : */
24676 0 : rvectorgrowto(&monitor->probingsteps, monitor->probingnstepsstored+1, _state);
24677 0 : rmatrixgrowrowsto(&monitor->probingvalues, monitor->probingnstepsstored+1, monitor->probingnvalues, _state);
24678 0 : rmatrixgrowrowsto(&monitor->probingslopes, monitor->probingnstepsstored+1, monitor->probingnvalues, _state);
24679 :
24680 : /*
24681 : * Determine probing step length, save step to the end of the storage
24682 : */
24683 0 : if( i<=10 )
24684 : {
24685 :
24686 : /*
24687 : * First 11 steps are performed over equidistant grid
24688 : */
24689 0 : monitor->probingstp = (double)i/(double)10*monitor->probingstepmax;
24690 : }
24691 : else
24692 : {
24693 :
24694 : /*
24695 : * Subsequent steps target either points with maximum change in F[0]
24696 : * (search for discontinuity) or maximum change in slope of F[0] (search
24697 : * for nonsmoothness)
24698 : */
24699 0 : ae_assert(monitor->probingnstepsstored>=3, "SMonitor: critical integrity check failed", _state);
24700 0 : if( i%2==0 )
24701 : {
24702 :
24703 : /*
24704 : * Target interval with maximum change in F[0]
24705 : */
24706 0 : idx = -1;
24707 0 : vlargest = (double)(0);
24708 0 : for(j=0; j<=monitor->probingnstepsstored-2; j++)
24709 : {
24710 0 : v = ae_fabs(monitor->probingvalues.ptr.pp_double[j+1][0]-monitor->probingvalues.ptr.pp_double[j][0], _state);
24711 0 : if( idx<0||ae_fp_greater(v,vlargest) )
24712 : {
24713 0 : idx = j;
24714 0 : vlargest = v;
24715 : }
24716 : }
24717 0 : monitor->probingstp = 0.5*(monitor->probingsteps.ptr.p_double[idx]+monitor->probingsteps.ptr.p_double[idx+1]);
24718 : }
24719 : else
24720 : {
24721 :
24722 : /*
24723 : * Target interval [J,J+2] with maximum change in slope of F[0], select
24724 : * subinterval [J,J+1] or [J+1,J+2] with maximum length.
24725 : */
24726 0 : idx = -1;
24727 0 : vlargest = (double)(0);
24728 0 : for(j=0; j<=monitor->probingnstepsstored-3; j++)
24729 : {
24730 0 : v0 = (monitor->probingvalues.ptr.pp_double[j+1][0]-monitor->probingvalues.ptr.pp_double[j+0][0])/(monitor->probingsteps.ptr.p_double[j+1]-monitor->probingsteps.ptr.p_double[j+0]+ae_machineepsilon);
24731 0 : v1 = (monitor->probingvalues.ptr.pp_double[j+2][0]-monitor->probingvalues.ptr.pp_double[j+1][0])/(monitor->probingsteps.ptr.p_double[j+2]-monitor->probingsteps.ptr.p_double[j+1]+ae_machineepsilon);
24732 0 : v = ae_fabs(v0-v1, _state);
24733 0 : if( idx<0||ae_fp_greater(v,vlargest) )
24734 : {
24735 0 : idx = j;
24736 0 : vlargest = v;
24737 : }
24738 : }
24739 0 : if( ae_fp_greater(monitor->probingsteps.ptr.p_double[idx+2]-monitor->probingsteps.ptr.p_double[idx+1],monitor->probingsteps.ptr.p_double[idx+1]-monitor->probingsteps.ptr.p_double[idx+0]) )
24740 : {
24741 0 : monitor->probingstp = 0.5*(monitor->probingsteps.ptr.p_double[idx+2]+monitor->probingsteps.ptr.p_double[idx+1]);
24742 : }
24743 : else
24744 : {
24745 0 : monitor->probingstp = 0.5*(monitor->probingsteps.ptr.p_double[idx+1]+monitor->probingsteps.ptr.p_double[idx+0]);
24746 : }
24747 : }
24748 : }
24749 0 : monitor->probingsteps.ptr.p_double[monitor->probingnstepsstored] = monitor->probingstp;
24750 :
24751 : /*
24752 : * Retrieve user values
24753 : */
24754 0 : monitor->probingrcomm.stage = 0;
24755 0 : goto lbl_rcomm;
24756 0 : lbl_0:
24757 0 : for(j=0; j<=monitor->probingnvalues-1; j++)
24758 : {
24759 0 : monitor->probingvalues.ptr.pp_double[monitor->probingnstepsstored][j] = monitor->probingf.ptr.p_double[j];
24760 0 : monitor->probingslopes.ptr.pp_double[monitor->probingnstepsstored][j] = (double)(0);
24761 : }
24762 0 : inc(&monitor->probingnstepsstored, _state);
24763 :
24764 : /*
24765 : * Resort
24766 : */
24767 0 : for(j=monitor->probingnstepsstored-1; j>=1; j--)
24768 : {
24769 0 : if( ae_fp_less_eq(monitor->probingsteps.ptr.p_double[j-1],monitor->probingsteps.ptr.p_double[j]) )
24770 : {
24771 0 : break;
24772 : }
24773 0 : swapelements(&monitor->probingsteps, j-1, j, _state);
24774 0 : swaprows(&monitor->probingvalues, j-1, j, monitor->probingnvalues, _state);
24775 : }
24776 0 : i = i+1;
24777 0 : goto lbl_1;
24778 0 : lbl_3:
24779 0 : result = ae_false;
24780 0 : return result;
24781 :
24782 : /*
24783 : * Saving state
24784 : */
24785 0 : lbl_rcomm:
24786 0 : result = ae_true;
24787 0 : monitor->probingrcomm.ia.ptr.p_int[0] = i;
24788 0 : monitor->probingrcomm.ia.ptr.p_int[1] = j;
24789 0 : monitor->probingrcomm.ia.ptr.p_int[2] = idx;
24790 0 : monitor->probingrcomm.ra.ptr.p_double[0] = vlargest;
24791 0 : monitor->probingrcomm.ra.ptr.p_double[1] = v;
24792 0 : monitor->probingrcomm.ra.ptr.p_double[2] = v0;
24793 0 : monitor->probingrcomm.ra.ptr.p_double[3] = v1;
24794 0 : return result;
24795 : }
24796 :
24797 :
24798 : /*************************************************************************
24799 : This function prints probing results to trace log.
24800 :
24801 : Tracing is performed using fixed width for all columns, so you may print
24802 : a header before printing trace - and reasonably expect that its width will
24803 : match that of the trace. This function promises that it wont change trace
24804 : output format without introducing breaking changes into its signature.
24805 :
24806 : NOTE: this function ALWAYS tries to print results; it is caller's responsibility
24807 : to decide whether he needs tracing or not.
24808 :
24809 : -- ALGLIB --
24810 : Copyright 10.10.2019 by Bochkanov Sergey
24811 : *************************************************************************/
24812 0 : void smoothnessmonitortraceprobingresults(smoothnessmonitor* monitor,
24813 : ae_state *_state)
24814 : {
24815 : ae_int_t i;
24816 : ae_int_t j;
24817 : double steplen;
24818 :
24819 :
24820 :
24821 : /*
24822 : * Compute slopes
24823 : */
24824 0 : for(i=0; i<=monitor->probingnstepsstored-2; i++)
24825 : {
24826 0 : for(j=0; j<=monitor->probingnvalues-1; j++)
24827 : {
24828 0 : steplen = (monitor->probingsteps.ptr.p_double[i+1]-monitor->probingsteps.ptr.p_double[i]+100*ae_machineepsilon)*(monitor->probingstepscale+ae_machineepsilon);
24829 0 : monitor->probingslopes.ptr.pp_double[i][j] = (monitor->probingvalues.ptr.pp_double[i+1][j]-monitor->probingvalues.ptr.pp_double[i][j])/steplen;
24830 : }
24831 : }
24832 0 : if( monitor->probingnstepsstored>=1 )
24833 : {
24834 0 : for(j=0; j<=monitor->probingnvalues-1; j++)
24835 : {
24836 0 : monitor->probingslopes.ptr.pp_double[monitor->probingnstepsstored-1][j] = monitor->probingslopes.ptr.pp_double[ae_maxint(monitor->probingnstepsstored-2, 0, _state)][j];
24837 : }
24838 : }
24839 :
24840 : /*
24841 : * Print to trace log
24842 : */
24843 0 : ae_trace("*** ----------");
24844 0 : for(j=0; j<=monitor->probingnvalues-1; j++)
24845 : {
24846 0 : ae_trace("-------------------------");
24847 : }
24848 0 : ae_trace("\n");
24849 0 : for(i=0; i<=monitor->probingnstepsstored-1; i++)
24850 : {
24851 0 : ae_trace("*** | %0.4f |",
24852 0 : (double)(monitor->probingsteps.ptr.p_double[i]));
24853 0 : for(j=0; j<=monitor->probingnvalues-1; j++)
24854 : {
24855 0 : ae_trace(" %11.3e %10.2e |",
24856 0 : (double)(monitor->probingvalues.ptr.pp_double[i][j]-monitor->probingvalues.ptr.pp_double[0][j]),
24857 0 : (double)(monitor->probingslopes.ptr.pp_double[i][j]));
24858 : }
24859 0 : ae_trace("\n");
24860 : }
24861 0 : ae_trace("*** ----------");
24862 0 : for(j=0; j<=monitor->probingnvalues-1; j++)
24863 : {
24864 0 : ae_trace("-------------------------");
24865 : }
24866 0 : ae_trace("\n");
24867 0 : }
24868 :
24869 :
24870 : /*************************************************************************
24871 : This subroutine tells monitor to output trace info.
24872 :
24873 : If CallerSuggestsTrace=True, monitor ALWAYS prints trace, even if no
24874 : suspicions were raised during optimization. If CallerSuggestsTrace=False,
24875 : the monitor will print trace only if:
24876 : * trace was requested by trace tag 'OPTGUARD' AND suspicious points were
24877 : found during optimization
24878 : * trace was requested by trace tag 'OPTGUARD.ALWAYS' - always
24879 :
24880 : -- ALGLIB --
24881 : Copyright 11.10.2019 by Bochkanov Sergey
24882 : *************************************************************************/
24883 0 : void smoothnessmonitortracestatus(smoothnessmonitor* monitor,
24884 : ae_bool callersuggeststrace,
24885 : ae_state *_state)
24886 : {
24887 : ae_bool needreport;
24888 : ae_bool needxdreport;
24889 : ae_bool suspicionsraised;
24890 : ae_int_t i;
24891 : double slope;
24892 :
24893 :
24894 :
24895 : /*
24896 : * Do we need trace report?
24897 : */
24898 0 : suspicionsraised = (monitor->rep.nonc0suspected||monitor->rep.nonc1suspected)||monitor->rep.badgradsuspected;
24899 0 : needreport = ae_false;
24900 0 : needreport = needreport||callersuggeststrace;
24901 0 : needreport = needreport||ae_is_trace_enabled("OPTGUARD.ALWAYS");
24902 0 : needreport = needreport||(ae_is_trace_enabled("OPTGUARD")&&suspicionsraised);
24903 0 : if( !needreport )
24904 : {
24905 0 : return;
24906 : }
24907 0 : needxdreport = needreport&&ae_is_trace_enabled("OPTIMIZERS.X");
24908 :
24909 : /*
24910 : *
24911 : */
24912 0 : ae_trace("\n");
24913 0 : ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n");
24914 0 : ae_trace("// OPTGUARD INTEGRITY CHECKER REPORT //\n");
24915 0 : ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n");
24916 0 : if( !suspicionsraised )
24917 : {
24918 0 : ae_trace("> no discontinuity/nonsmoothness/bad-gradient suspicions were raised during optimization\n");
24919 0 : return;
24920 : }
24921 0 : if( monitor->rep.nonc0suspected )
24922 : {
24923 0 : ae_trace("> [WARNING] suspected discontinuity (aka C0-discontinuity)\n");
24924 : }
24925 0 : if( monitor->rep.nonc1suspected )
24926 : {
24927 0 : ae_trace("> [WARNING] suspected nonsmoothness (aka C1-discontinuity)\n");
24928 : }
24929 0 : ae_trace("> printing out test reports...\n");
24930 0 : if( monitor->rep.nonc0suspected&&monitor->rep.nonc0test0positive )
24931 : {
24932 0 : ae_trace("> printing out discontinuity test #0 report:\n");
24933 0 : ae_trace("*** -------------------------------------------------------\n");
24934 0 : ae_trace("*** | Test #0 for discontinuity was triggered (this test |\n");
24935 0 : ae_trace("*** | analyzes changes in function values). See below for |\n");
24936 0 : ae_trace("*** | detailed info: |\n");
24937 0 : ae_trace("*** | * function index: %10d",
24938 0 : (int)(monitor->nonc0lngrep.fidx));
24939 0 : if( monitor->nonc0lngrep.fidx==0 )
24940 : {
24941 0 : ae_trace(" (target) |\n");
24942 : }
24943 : else
24944 : {
24945 0 : ae_trace(" (constraint) |\n");
24946 : }
24947 0 : ae_trace("*** | * F() Lipschitz const: %10.2e |\n",
24948 0 : (double)(monitor->rep.nonc0lipschitzc));
24949 0 : ae_trace("*** | Printing out log of suspicious line search XK+Stp*D |\n");
24950 0 : ae_trace("*** | Look for abrupt changes in slope. |\n");
24951 0 : if( !needxdreport )
24952 : {
24953 0 : ae_trace("*** | NOTE: XK and D are not printed by default. If you |\n");
24954 0 : ae_trace("*** | need them, add trace tag OPTIMIZERS.X |\n");
24955 : }
24956 0 : ae_trace("*** -------------------------------------------------------\n");
24957 0 : ae_trace("*** | step along D | delta F | slope |\n");
24958 0 : ae_trace("*** ------------------------------------------------------|\n");
24959 0 : for(i=0; i<=monitor->nonc0lngrep.cnt-1; i++)
24960 : {
24961 0 : slope = monitor->nonc0lngrep.f.ptr.p_double[ae_minint(i+1, monitor->nonc0lngrep.cnt-1, _state)]-monitor->nonc0lngrep.f.ptr.p_double[i];
24962 0 : slope = slope/(1.0e-15+monitor->nonc0lngrep.stp.ptr.p_double[ae_minint(i+1, monitor->nonc0lngrep.cnt-1, _state)]-monitor->nonc0lngrep.stp.ptr.p_double[i]);
24963 0 : ae_trace("*** | %13.5e | %13.5e | %11.3e |",
24964 0 : (double)(monitor->nonc0lngrep.stp.ptr.p_double[i]),
24965 0 : (double)(monitor->nonc0lngrep.f.ptr.p_double[i]-monitor->nonc0lngrep.f.ptr.p_double[0]),
24966 : (double)(slope));
24967 0 : if( i>=monitor->nonc0lngrep.stpidxa&&i<=monitor->nonc0lngrep.stpidxb )
24968 : {
24969 0 : ae_trace(" <---");
24970 : }
24971 0 : ae_trace("\n");
24972 : }
24973 0 : ae_trace("*** ------------------------------------------------------|\n");
24974 0 : if( needxdreport )
24975 : {
24976 0 : ae_trace("*** > printing raw variables\n");
24977 0 : ae_trace("*** XK = ");
24978 0 : tracevectorunscaledunshiftedautoprec(&monitor->nonc0lngrep.x0, monitor->n, &monitor->s, ae_true, &monitor->s, ae_false, _state);
24979 0 : ae_trace("\n");
24980 0 : ae_trace("*** D = ");
24981 0 : tracevectorunscaledunshiftedautoprec(&monitor->nonc0lngrep.d, monitor->n, &monitor->s, ae_true, &monitor->s, ae_false, _state);
24982 0 : ae_trace("\n");
24983 0 : ae_trace("*** > printing scaled variables (values are divided by user-specified scales)\n");
24984 0 : ae_trace("*** XK = ");
24985 0 : tracevectorautoprec(&monitor->nonc0lngrep.x0, 0, monitor->n, _state);
24986 0 : ae_trace("\n");
24987 0 : ae_trace("*** D = ");
24988 0 : tracevectorautoprec(&monitor->nonc0lngrep.d, 0, monitor->n, _state);
24989 0 : ae_trace("\n");
24990 : }
24991 : }
24992 0 : if( monitor->rep.nonc1suspected&&monitor->rep.nonc1test0positive )
24993 : {
24994 0 : ae_trace("> printing out nonsmoothness test #0 report:\n");
24995 0 : ae_trace("*** -------------------------------------------------------\n");
24996 0 : ae_trace("*** | Test #0 for nonsmoothness was triggered (this test |\n");
24997 0 : ae_trace("*** | analyzes changes in function values and ignores |\n");
24998 0 : ae_trace("*** | gradient info). See below for detailed info: |\n");
24999 0 : ae_trace("*** | * function index: %10d",
25000 0 : (int)(monitor->nonc1test0lngrep.fidx));
25001 0 : if( monitor->nonc1test0lngrep.fidx==0 )
25002 : {
25003 0 : ae_trace(" (target) |\n");
25004 : }
25005 : else
25006 : {
25007 0 : ae_trace(" (constraint) |\n");
25008 : }
25009 0 : ae_trace("*** | * dF/dX Lipschitz const: %10.2e |\n",
25010 0 : (double)(monitor->rep.nonc1lipschitzc));
25011 0 : ae_trace("*** | Printing out log of suspicious line search XK+Stp*D |\n");
25012 0 : ae_trace("*** | Look for abrupt changes in slope. |\n");
25013 0 : if( !needxdreport )
25014 : {
25015 0 : ae_trace("*** | NOTE: XK and D are not printed by default. If you |\n");
25016 0 : ae_trace("*** | need them, add trace tag OPTIMIZERS.X |\n");
25017 : }
25018 0 : ae_trace("*** -------------------------------------------------------\n");
25019 0 : ae_trace("*** | step along D | delta F | slope |\n");
25020 0 : ae_trace("*** ------------------------------------------------------|\n");
25021 0 : for(i=0; i<=monitor->nonc1test0lngrep.cnt-1; i++)
25022 : {
25023 0 : slope = monitor->nonc1test0lngrep.f.ptr.p_double[ae_minint(i+1, monitor->nonc1test0lngrep.cnt-1, _state)]-monitor->nonc1test0lngrep.f.ptr.p_double[i];
25024 0 : slope = slope/(1.0e-15+monitor->nonc1test0lngrep.stp.ptr.p_double[ae_minint(i+1, monitor->nonc1test0lngrep.cnt-1, _state)]-monitor->nonc1test0lngrep.stp.ptr.p_double[i]);
25025 0 : ae_trace("*** | %13.5e | %13.5e | %11.3e |",
25026 0 : (double)(monitor->nonc1test0lngrep.stp.ptr.p_double[i]),
25027 0 : (double)(monitor->nonc1test0lngrep.f.ptr.p_double[i]-monitor->nonc1test0lngrep.f.ptr.p_double[0]),
25028 : (double)(slope));
25029 0 : if( i>=monitor->nonc1test0lngrep.stpidxa&&i<=monitor->nonc1test0lngrep.stpidxb )
25030 : {
25031 0 : ae_trace(" <---");
25032 : }
25033 0 : ae_trace("\n");
25034 : }
25035 0 : ae_trace("*** ------------------------------------------------------|\n");
25036 0 : if( needxdreport )
25037 : {
25038 0 : ae_trace("*** > printing raw variables\n");
25039 0 : ae_trace("*** XK = ");
25040 0 : tracevectorunscaledunshiftedautoprec(&monitor->nonc1test0lngrep.x0, monitor->n, &monitor->s, ae_true, &monitor->s, ae_false, _state);
25041 0 : ae_trace("\n");
25042 0 : ae_trace("*** D = ");
25043 0 : tracevectorunscaledunshiftedautoprec(&monitor->nonc1test0lngrep.d, monitor->n, &monitor->s, ae_true, &monitor->s, ae_false, _state);
25044 0 : ae_trace("\n");
25045 0 : ae_trace("*** > printing scaled variables (values are divided by user-specified scales)\n");
25046 0 : ae_trace("*** XK = ");
25047 0 : tracevectorautoprec(&monitor->nonc1test0lngrep.x0, 0, monitor->n, _state);
25048 0 : ae_trace("\n");
25049 0 : ae_trace("*** D = ");
25050 0 : tracevectorautoprec(&monitor->nonc1test0lngrep.d, 0, monitor->n, _state);
25051 0 : ae_trace("\n");
25052 : }
25053 : }
25054 0 : if( monitor->rep.nonc1suspected&&monitor->rep.nonc1test1positive )
25055 : {
25056 0 : ae_trace("> printing out nonsmoothness test #1 report:\n");
25057 0 : ae_trace("*** -------------------------------------------------------\n");
25058 0 : ae_trace("*** | Test #1 for nonsmoothness was triggered (this test |\n");
25059 0 : ae_trace("*** | analyzes changes in gradient components). See below |\n");
25060 0 : ae_trace("*** | for detailed info: |\n");
25061 0 : ae_trace("*** | * function index: %10d",
25062 0 : (int)(monitor->nonc1test1lngrep.fidx));
25063 0 : if( monitor->nonc1test1lngrep.fidx==0 )
25064 : {
25065 0 : ae_trace(" (target) |\n");
25066 : }
25067 : else
25068 : {
25069 0 : ae_trace(" (constraint) |\n");
25070 : }
25071 0 : ae_trace("*** | * variable index I: %10d |\n",
25072 0 : (int)(monitor->nonc1test1lngrep.vidx));
25073 0 : ae_trace("*** | * dF/dX Lipschitz const: %10.2e |\n",
25074 0 : (double)(monitor->rep.nonc1lipschitzc));
25075 0 : ae_trace("*** | Printing out log of suspicious line search XK+Stp*D |\n");
25076 0 : ae_trace("*** | Look for abrupt changes in slope. |\n");
25077 0 : if( !needxdreport )
25078 : {
25079 0 : ae_trace("*** | NOTE: XK and D are not printed by default. If you |\n");
25080 0 : ae_trace("*** | need them, add trace tag OPTIMIZERS.X |\n");
25081 : }
25082 0 : ae_trace("*** -------------------------------------------------------\n");
25083 0 : ae_trace("*** | step along D | delta Gi | slope |\n");
25084 0 : ae_trace("*** ------------------------------------------------------|\n");
25085 0 : for(i=0; i<=monitor->nonc1test1lngrep.cnt-1; i++)
25086 : {
25087 0 : slope = monitor->nonc1test1lngrep.g.ptr.p_double[ae_minint(i+1, monitor->nonc1test1lngrep.cnt-1, _state)]-monitor->nonc1test1lngrep.g.ptr.p_double[i];
25088 0 : slope = slope/(1.0e-15+monitor->nonc1test1lngrep.stp.ptr.p_double[ae_minint(i+1, monitor->nonc1test1lngrep.cnt-1, _state)]-monitor->nonc1test1lngrep.stp.ptr.p_double[i]);
25089 0 : ae_trace("*** | %13.5e | %13.5e | %11.3e |",
25090 0 : (double)(monitor->nonc1test1lngrep.stp.ptr.p_double[i]),
25091 0 : (double)(monitor->nonc1test1lngrep.g.ptr.p_double[i]-monitor->nonc1test1lngrep.g.ptr.p_double[0]),
25092 : (double)(slope));
25093 0 : if( i>=monitor->nonc1test1lngrep.stpidxa&&i<=monitor->nonc1test1lngrep.stpidxb )
25094 : {
25095 0 : ae_trace(" <---");
25096 : }
25097 0 : ae_trace("\n");
25098 : }
25099 0 : ae_trace("*** ------------------------------------------------------|\n");
25100 0 : if( needxdreport )
25101 : {
25102 0 : ae_trace("*** > printing raw variables\n");
25103 0 : ae_trace("*** XK = ");
25104 0 : tracevectorunscaledunshiftedautoprec(&monitor->nonc1test1lngrep.x0, monitor->n, &monitor->s, ae_true, &monitor->s, ae_false, _state);
25105 0 : ae_trace("\n");
25106 0 : ae_trace("*** D = ");
25107 0 : tracevectorunscaledunshiftedautoprec(&monitor->nonc1test1lngrep.d, monitor->n, &monitor->s, ae_true, &monitor->s, ae_false, _state);
25108 0 : ae_trace("\n");
25109 0 : ae_trace("*** > printing scaled variables (values are divided by user-specified scales)\n");
25110 0 : ae_trace("*** XK = ");
25111 0 : tracevectorautoprec(&monitor->nonc1test1lngrep.x0, 0, monitor->n, _state);
25112 0 : ae_trace("\n");
25113 0 : ae_trace("*** D = ");
25114 0 : tracevectorautoprec(&monitor->nonc1test1lngrep.d, 0, monitor->n, _state);
25115 0 : ae_trace("\n");
25116 : }
25117 : }
25118 : }
25119 :
25120 :
25121 : /*************************************************************************
25122 : This subroutine exports report to user-readable representation (all arrays
25123 : are forced to have exactly same size as needed; unused arrays are set to
25124 : zero length).
25125 :
25126 : -- ALGLIB --
25127 : Copyright 19.11.2018 by Bochkanov Sergey
25128 : *************************************************************************/
25129 0 : void smoothnessmonitorexportreport(smoothnessmonitor* monitor,
25130 : optguardreport* rep,
25131 : ae_state *_state)
25132 : {
25133 :
25134 :
25135 :
25136 : /*
25137 : * Finalize last line search, just to be sure
25138 : */
25139 0 : if( monitor->enqueuedcnt>0 )
25140 : {
25141 0 : smoothnessmonitorfinalizelinesearch(monitor, _state);
25142 : }
25143 :
25144 : /*
25145 : * Export report
25146 : */
25147 0 : optguardexportreport(&monitor->rep, monitor->n, monitor->k, monitor->badgradhasxj, rep, _state);
25148 0 : }
25149 :
25150 :
25151 : /*************************************************************************
25152 : Check numerical gradient at point X0 (unscaled variables!), with optional
25153 : box constraints [BndL,BndU] (if HasBoxConstraints=True) and with scale
25154 : vector S[].
25155 :
25156 : Step S[i]*TestStep is performed along I-th variable.
25157 :
25158 : NeedFiJ rcomm protocol is used to request derivative information.
25159 :
25160 : Box constraints BndL/BndU are expected to be feasible. It is possible to
25161 : have BndL=BndU.
25162 :
25163 : -- ALGLIB --
25164 : Copyright 06.12.2018 by Bochkanov Sergey
25165 : *************************************************************************/
25166 0 : ae_bool smoothnessmonitorcheckgradientatx0(smoothnessmonitor* monitor,
25167 : /* Real */ ae_vector* unscaledx0,
25168 : /* Real */ ae_vector* s,
25169 : /* Real */ ae_vector* bndl,
25170 : /* Real */ ae_vector* bndu,
25171 : ae_bool hasboxconstraints,
25172 : double teststep,
25173 : ae_state *_state)
25174 : {
25175 : ae_int_t n;
25176 : ae_int_t k;
25177 : ae_int_t i;
25178 : ae_int_t j;
25179 : ae_int_t varidx;
25180 : double v;
25181 : double vp;
25182 : double vm;
25183 : double vc;
25184 : ae_bool result;
25185 :
25186 :
25187 :
25188 : /*
25189 : * Reverse communication preparations
25190 : * I know it looks ugly, but it works the same way
25191 : * anywhere from C++ to Python.
25192 : *
25193 : * This code initializes locals by:
25194 : * * random values determined during code
25195 : * generation - on first subroutine call
25196 : * * values from previous call - on subsequent calls
25197 : */
25198 0 : if( monitor->rstateg0.stage>=0 )
25199 : {
25200 0 : n = monitor->rstateg0.ia.ptr.p_int[0];
25201 0 : k = monitor->rstateg0.ia.ptr.p_int[1];
25202 0 : i = monitor->rstateg0.ia.ptr.p_int[2];
25203 0 : j = monitor->rstateg0.ia.ptr.p_int[3];
25204 0 : varidx = monitor->rstateg0.ia.ptr.p_int[4];
25205 0 : v = monitor->rstateg0.ra.ptr.p_double[0];
25206 0 : vp = monitor->rstateg0.ra.ptr.p_double[1];
25207 0 : vm = monitor->rstateg0.ra.ptr.p_double[2];
25208 0 : vc = monitor->rstateg0.ra.ptr.p_double[3];
25209 : }
25210 : else
25211 : {
25212 0 : n = -788;
25213 0 : k = 809;
25214 0 : i = 205;
25215 0 : j = -838;
25216 0 : varidx = 939;
25217 0 : v = -526;
25218 0 : vp = 763;
25219 0 : vm = -541;
25220 0 : vc = -698;
25221 : }
25222 0 : if( monitor->rstateg0.stage==0 )
25223 : {
25224 0 : goto lbl_0;
25225 : }
25226 0 : if( monitor->rstateg0.stage==1 )
25227 : {
25228 0 : goto lbl_1;
25229 : }
25230 0 : if( monitor->rstateg0.stage==2 )
25231 : {
25232 0 : goto lbl_2;
25233 : }
25234 0 : if( monitor->rstateg0.stage==3 )
25235 : {
25236 0 : goto lbl_3;
25237 : }
25238 :
25239 : /*
25240 : * Routine body
25241 : */
25242 0 : n = monitor->n;
25243 0 : k = monitor->k;
25244 0 : monitor->needfij = ae_false;
25245 :
25246 : /*
25247 : * Quick exit
25248 : */
25249 0 : if( ((n<=0||k<=0)||!ae_isfinite(teststep, _state))||ae_fp_eq(teststep,(double)(0)) )
25250 : {
25251 0 : result = ae_false;
25252 0 : return result;
25253 : }
25254 0 : teststep = ae_fabs(teststep, _state);
25255 :
25256 : /*
25257 : * Allocate storage
25258 : */
25259 0 : rvectorsetlengthatleast(&monitor->x, n, _state);
25260 0 : rvectorsetlengthatleast(&monitor->fi, k, _state);
25261 0 : rmatrixsetlengthatleast(&monitor->j, k, n, _state);
25262 0 : rvectorsetlengthatleast(&monitor->xbase, n, _state);
25263 0 : rvectorsetlengthatleast(&monitor->fbase, k, _state);
25264 0 : rvectorsetlengthatleast(&monitor->fm, k, _state);
25265 0 : rvectorsetlengthatleast(&monitor->fc, k, _state);
25266 0 : rvectorsetlengthatleast(&monitor->fp, k, _state);
25267 0 : rvectorsetlengthatleast(&monitor->jm, k, _state);
25268 0 : rvectorsetlengthatleast(&monitor->jc, k, _state);
25269 0 : rvectorsetlengthatleast(&monitor->jp, k, _state);
25270 0 : rmatrixsetlengthatleast(&monitor->jbaseusr, k, n, _state);
25271 0 : rmatrixsetlengthatleast(&monitor->jbasenum, k, n, _state);
25272 0 : rvectorsetlengthatleast(&monitor->rep.badgradxbase, n, _state);
25273 0 : rmatrixsetlengthatleast(&monitor->rep.badgraduser, k, n, _state);
25274 0 : rmatrixsetlengthatleast(&monitor->rep.badgradnum, k, n, _state);
25275 :
25276 : /*
25277 : * Set XBase/Jacobian presence flag
25278 : */
25279 0 : monitor->badgradhasxj = ae_true;
25280 :
25281 : /*
25282 : * Determine reference point, compute function vector and user-supplied Jacobian
25283 : */
25284 0 : for(i=0; i<=n-1; i++)
25285 : {
25286 0 : v = unscaledx0->ptr.p_double[i];
25287 0 : if( (hasboxconstraints&&ae_isfinite(bndl->ptr.p_double[i], _state))&&ae_fp_less(v,bndl->ptr.p_double[i]) )
25288 : {
25289 0 : v = bndl->ptr.p_double[i];
25290 : }
25291 0 : if( (hasboxconstraints&&ae_isfinite(bndu->ptr.p_double[i], _state))&&ae_fp_greater(v,bndu->ptr.p_double[i]) )
25292 : {
25293 0 : v = bndu->ptr.p_double[i];
25294 : }
25295 0 : monitor->xbase.ptr.p_double[i] = v;
25296 0 : monitor->rep.badgradxbase.ptr.p_double[i] = v;
25297 0 : monitor->x.ptr.p_double[i] = v;
25298 : }
25299 0 : monitor->needfij = ae_true;
25300 0 : monitor->rstateg0.stage = 0;
25301 0 : goto lbl_rcomm;
25302 0 : lbl_0:
25303 0 : monitor->needfij = ae_false;
25304 0 : for(i=0; i<=k-1; i++)
25305 : {
25306 0 : monitor->fbase.ptr.p_double[i] = monitor->fi.ptr.p_double[i];
25307 0 : for(j=0; j<=n-1; j++)
25308 : {
25309 0 : monitor->jbaseusr.ptr.pp_double[i][j] = monitor->j.ptr.pp_double[i][j];
25310 0 : monitor->rep.badgraduser.ptr.pp_double[i][j] = monitor->j.ptr.pp_double[i][j];
25311 : }
25312 : }
25313 :
25314 : /*
25315 : * Check Jacobian column by column
25316 : */
25317 0 : varidx = 0;
25318 0 : lbl_4:
25319 0 : if( varidx>n-1 )
25320 : {
25321 0 : goto lbl_6;
25322 : }
25323 :
25324 : /*
25325 : * Determine test location.
25326 : */
25327 0 : v = monitor->xbase.ptr.p_double[varidx];
25328 0 : vm = v-s->ptr.p_double[varidx]*teststep;
25329 0 : vp = v+s->ptr.p_double[varidx]*teststep;
25330 0 : if( (hasboxconstraints&&ae_isfinite(bndl->ptr.p_double[varidx], _state))&&ae_fp_less(vm,bndl->ptr.p_double[varidx]) )
25331 : {
25332 0 : vm = bndl->ptr.p_double[varidx];
25333 : }
25334 0 : if( (hasboxconstraints&&ae_isfinite(bndu->ptr.p_double[varidx], _state))&&ae_fp_greater(vp,bndu->ptr.p_double[varidx]) )
25335 : {
25336 0 : vp = bndu->ptr.p_double[varidx];
25337 : }
25338 0 : vc = vm+(vp-vm)/2;
25339 :
25340 : /*
25341 : * Quickly skip fixed variables
25342 : */
25343 0 : if( (ae_fp_eq(vm,vp)||ae_fp_eq(vc,vm))||ae_fp_eq(vc,vp) )
25344 : {
25345 0 : for(i=0; i<=k-1; i++)
25346 : {
25347 0 : monitor->rep.badgradnum.ptr.pp_double[i][varidx] = (double)(0);
25348 : }
25349 0 : goto lbl_5;
25350 : }
25351 :
25352 : /*
25353 : * Compute F/J at three trial points
25354 : */
25355 0 : for(i=0; i<=n-1; i++)
25356 : {
25357 0 : monitor->x.ptr.p_double[i] = monitor->xbase.ptr.p_double[i];
25358 : }
25359 0 : monitor->x.ptr.p_double[varidx] = vm;
25360 0 : monitor->needfij = ae_true;
25361 0 : monitor->rstateg0.stage = 1;
25362 0 : goto lbl_rcomm;
25363 0 : lbl_1:
25364 0 : monitor->needfij = ae_false;
25365 0 : for(i=0; i<=k-1; i++)
25366 : {
25367 0 : monitor->fm.ptr.p_double[i] = monitor->fi.ptr.p_double[i];
25368 0 : monitor->jm.ptr.p_double[i] = monitor->j.ptr.pp_double[i][varidx];
25369 : }
25370 0 : for(i=0; i<=n-1; i++)
25371 : {
25372 0 : monitor->x.ptr.p_double[i] = monitor->xbase.ptr.p_double[i];
25373 : }
25374 0 : monitor->x.ptr.p_double[varidx] = vc;
25375 0 : monitor->needfij = ae_true;
25376 0 : monitor->rstateg0.stage = 2;
25377 0 : goto lbl_rcomm;
25378 0 : lbl_2:
25379 0 : monitor->needfij = ae_false;
25380 0 : for(i=0; i<=k-1; i++)
25381 : {
25382 0 : monitor->fc.ptr.p_double[i] = monitor->fi.ptr.p_double[i];
25383 0 : monitor->jc.ptr.p_double[i] = monitor->j.ptr.pp_double[i][varidx];
25384 : }
25385 0 : for(i=0; i<=n-1; i++)
25386 : {
25387 0 : monitor->x.ptr.p_double[i] = monitor->xbase.ptr.p_double[i];
25388 : }
25389 0 : monitor->x.ptr.p_double[varidx] = vp;
25390 0 : monitor->needfij = ae_true;
25391 0 : monitor->rstateg0.stage = 3;
25392 0 : goto lbl_rcomm;
25393 0 : lbl_3:
25394 0 : monitor->needfij = ae_false;
25395 0 : for(i=0; i<=k-1; i++)
25396 : {
25397 0 : monitor->fp.ptr.p_double[i] = monitor->fi.ptr.p_double[i];
25398 0 : monitor->jp.ptr.p_double[i] = monitor->j.ptr.pp_double[i][varidx];
25399 : }
25400 :
25401 : /*
25402 : * Check derivative
25403 : */
25404 0 : for(i=0; i<=k-1; i++)
25405 : {
25406 0 : monitor->rep.badgradnum.ptr.pp_double[i][varidx] = (monitor->fp.ptr.p_double[i]-monitor->fm.ptr.p_double[i])/(vp-vm);
25407 0 : if( !derivativecheck(monitor->fm.ptr.p_double[i], monitor->jm.ptr.p_double[i]*s->ptr.p_double[varidx], monitor->fp.ptr.p_double[i], monitor->jp.ptr.p_double[i]*s->ptr.p_double[varidx], monitor->fc.ptr.p_double[i], monitor->jc.ptr.p_double[i]*s->ptr.p_double[varidx], (vp-vm)/s->ptr.p_double[varidx], _state) )
25408 : {
25409 0 : monitor->rep.badgradsuspected = ae_true;
25410 0 : monitor->rep.badgradfidx = i;
25411 0 : monitor->rep.badgradvidx = varidx;
25412 : }
25413 : }
25414 0 : lbl_5:
25415 0 : varidx = varidx+1;
25416 0 : goto lbl_4;
25417 0 : lbl_6:
25418 0 : result = ae_false;
25419 0 : return result;
25420 :
25421 : /*
25422 : * Saving state
25423 : */
25424 0 : lbl_rcomm:
25425 0 : result = ae_true;
25426 0 : monitor->rstateg0.ia.ptr.p_int[0] = n;
25427 0 : monitor->rstateg0.ia.ptr.p_int[1] = k;
25428 0 : monitor->rstateg0.ia.ptr.p_int[2] = i;
25429 0 : monitor->rstateg0.ia.ptr.p_int[3] = j;
25430 0 : monitor->rstateg0.ia.ptr.p_int[4] = varidx;
25431 0 : monitor->rstateg0.ra.ptr.p_double[0] = v;
25432 0 : monitor->rstateg0.ra.ptr.p_double[1] = vp;
25433 0 : monitor->rstateg0.ra.ptr.p_double[2] = vm;
25434 0 : monitor->rstateg0.ra.ptr.p_double[3] = vc;
25435 0 : return result;
25436 : }
25437 :
25438 :
25439 : /*************************************************************************
25440 : This function calculates feasibility error (square root of sum of squared
25441 : errors) for a Kx(NMain+NSlack) system of linear equalities.
25442 :
25443 : INPUT PARAMETERS:
25444 : CE - set of K equality constraints, array[K,NMain+NSlack+1]
25445 : X - candidate point, array [NMain+NSlack]
25446 : NMain - number of primary variables
25447 : NSlack - number of slack variables
25448 : K - number of constraints
25449 : Tmp0 - possible preallocated buffer, automatically resized
25450 :
25451 : RESULT:
25452 : Sqrt(SUM(Err^2))
25453 :
25454 : -- ALGLIB --
25455 : Copyright 17.09.2015 by Bochkanov Sergey
25456 : *************************************************************************/
25457 0 : static double optserv_feasibilityerror(/* Real */ ae_matrix* ce,
25458 : /* Real */ ae_vector* x,
25459 : ae_int_t nmain,
25460 : ae_int_t nslack,
25461 : ae_int_t k,
25462 : /* Real */ ae_vector* tmp0,
25463 : ae_state *_state)
25464 : {
25465 : ae_int_t i;
25466 : double result;
25467 :
25468 :
25469 0 : rvectorsetlengthatleast(tmp0, k, _state);
25470 0 : for(i=0; i<=k-1; i++)
25471 : {
25472 0 : tmp0->ptr.p_double[i] = -ce->ptr.pp_double[i][nmain+nslack];
25473 : }
25474 0 : rmatrixgemv(k, nmain+nslack, 1.0, ce, 0, 0, 0, x, 0, 1.0, tmp0, 0, _state);
25475 0 : result = 0.0;
25476 0 : for(i=0; i<=k-1; i++)
25477 : {
25478 0 : result = result+tmp0->ptr.p_double[i]*tmp0->ptr.p_double[i];
25479 : }
25480 0 : result = ae_sqrt(result, _state);
25481 0 : return result;
25482 : }
25483 :
25484 :
25485 : /*************************************************************************
25486 : This function calculates feasibility error (square root of sum of squared
25487 : errors) for a Kx(NMain+NSlack) system of linear equalities and error
25488 : gradient (with respect to x)
25489 :
25490 : INPUT PARAMETERS:
25491 : CE - set of K equality constraints, array[K,NMain+NSlack+1]
25492 : X - candidate point, array [NMain+NSlack]
25493 : NMain - number of primary variables
25494 : NSlack - number of slack variables
25495 : K - number of constraints
25496 : Grad - preallocated array[NMain+NSlack]
25497 : Tmp0 - possible preallocated buffer, automatically resized
25498 :
25499 : RESULT:
25500 : Err - Sqrt(SUM(Err^2))
25501 : Grad - error gradient with respect to X, array[NMain+NSlack]
25502 :
25503 : -- ALGLIB --
25504 : Copyright 17.09.2015 by Bochkanov Sergey
25505 : *************************************************************************/
25506 0 : static void optserv_feasibilityerrorgrad(/* Real */ ae_matrix* ce,
25507 : /* Real */ ae_vector* x,
25508 : ae_int_t nmain,
25509 : ae_int_t nslack,
25510 : ae_int_t k,
25511 : double* err,
25512 : /* Real */ ae_vector* grad,
25513 : /* Real */ ae_vector* tmp0,
25514 : ae_state *_state)
25515 : {
25516 : ae_int_t i;
25517 : double v;
25518 :
25519 0 : *err = 0;
25520 :
25521 0 : ae_assert(grad->cnt>=nmain+nslack, "FeasibilityErrorGrad: integrity check failed", _state);
25522 0 : rvectorsetlengthatleast(tmp0, k, _state);
25523 0 : rmatrixgemv(k, nmain+nslack, 1.0, ce, 0, 0, 0, x, 0, 0.0, tmp0, 0, _state);
25524 0 : *err = 0.0;
25525 0 : for(i=0; i<=k-1; i++)
25526 : {
25527 0 : v = tmp0->ptr.p_double[i]-ce->ptr.pp_double[i][nmain+nslack];
25528 0 : tmp0->ptr.p_double[i] = v;
25529 0 : *err = *err+v*v;
25530 : }
25531 0 : *err = ae_sqrt(*err, _state);
25532 0 : rmatrixgemv(nmain+nslack, k, 1.0, ce, 0, 0, 1, tmp0, 0, 0.0, grad, 0, _state);
25533 0 : }
25534 :
25535 :
25536 : /*************************************************************************
25537 : This subroutine checks C0 continuity and returns continuity rating
25538 : (normalized value, with values above 50-500 being good indication of the
25539 : discontinuity) and Lipschitz constant.
25540 :
25541 : An interval between F1 and F2 is tested for (dis)continuity. Per-point
25542 : noise estimates are provided. Delta[i] is a step from F[i] to F[i+1].
25543 :
25544 : ApplySpecialCorrection parameter should be set to True if you use this
25545 : function to estimate continuity of the model around minimum; it adds
25546 : special correction which helps to detect "max(0,1/x)"-like discontinuities.
25547 : Without this correction algorithm will still work, but will be a bit less
25548 : powerful. Do not use this correction for situations when you want to
25549 : estimate continuity around some non-extremal point - it may result in
25550 : spurious discontinuities being reported.
25551 :
25552 : -- ALGLIB --
25553 : Copyright 19.11.2018 by Bochkanov Sergey
25554 : *************************************************************************/
25555 0 : static void optserv_testc0continuity(double f0,
25556 : double f1,
25557 : double f2,
25558 : double f3,
25559 : double noise0,
25560 : double noise1,
25561 : double noise2,
25562 : double noise3,
25563 : double delta0,
25564 : double delta1,
25565 : double delta2,
25566 : ae_bool applyspecialcorrection,
25567 : double* rating,
25568 : double* lipschitz,
25569 : ae_state *_state)
25570 : {
25571 : double lipschitz01;
25572 : double lipschitz12;
25573 : double lipschitz23;
25574 :
25575 0 : *rating = 0;
25576 0 : *lipschitz = 0;
25577 :
25578 :
25579 : /*
25580 : * Compute Lipschitz constant for the interval [0,1],
25581 : * add noise correction in order to get increased estimate (makes
25582 : * comparison below more conservative).
25583 : */
25584 0 : lipschitz01 = (ae_fabs(f1-f0, _state)+(noise0+noise1))/delta0;
25585 :
25586 : /*
25587 : * Compute Lipschitz constant for the interval [StpIdx+1,StpIdx+2],
25588 : * SUBTRACT noise correction in order to get decreased estimate (makes
25589 : * comparison below more conservative).
25590 : */
25591 0 : lipschitz12 = ae_maxreal(ae_fabs(f2-f1, _state)-(noise1+noise2), 0.0, _state)/delta1;
25592 :
25593 : /*
25594 : * Compute Lipschitz constant for the interval [StpIdx+2,StpIdx+3]
25595 : * using special algorithm:
25596 : * a) if F3<F2-Noise23, Lipschitz constant is assumed to be zero
25597 : * b) otherwise, we compute Lipschitz constant as usual,
25598 : * with noise correction term being added
25599 : *
25600 : * We need case (a) because some kinds of discontinuities
25601 : * (like one introduced by max(1/x,0)) manifest themselves
25602 : * in a quite special way.
25603 : */
25604 0 : if( applyspecialcorrection&&f3<f2-(noise2+noise3) )
25605 : {
25606 0 : lipschitz23 = (double)(0);
25607 : }
25608 : else
25609 : {
25610 0 : lipschitz23 = (ae_fabs(f3-f2, _state)+(noise2+noise3))/delta2;
25611 : }
25612 :
25613 : /*
25614 : * Compute rating (ratio of two Lipschitz constants)
25615 : */
25616 0 : ae_assert(ae_maxreal(lipschitz01, lipschitz23, _state)>0, "OptGuard: integrity check failed", _state);
25617 0 : *rating = lipschitz12/ae_maxreal(lipschitz01, lipschitz23, _state);
25618 0 : *lipschitz = lipschitz12;
25619 0 : }
25620 :
25621 :
25622 : /*************************************************************************
25623 : This subroutine checks C1 continuity using test #0 (function values from
25624 : the line search log are studied, gradient is not used).
25625 :
25626 : An interval between F[StpIdx+0] and F[StpIdx+5]is tested for continuity.
25627 : An normalized error metric (Lipschitz constant growth for the derivative)
25628 : for the interval in question is calculated. Values above 50 are a good
25629 : indication of the discontinuity.
25630 :
25631 : A six-point algorithm is used for testing, so we expect that Monitor.F and
25632 : Monitor.Stp have enough points for this test.
25633 :
25634 : -- ALGLIB --
25635 : Copyright 19.11.2018 by Bochkanov Sergey
25636 : *************************************************************************/
25637 0 : static void optserv_c1continuitytest0(smoothnessmonitor* monitor,
25638 : ae_int_t funcidx,
25639 : ae_int_t stpidx,
25640 : ae_int_t sortedcnt,
25641 : ae_state *_state)
25642 : {
25643 : double f0;
25644 : double f1;
25645 : double f2;
25646 : double f3;
25647 : double f4;
25648 : double f5;
25649 : double noise0;
25650 : double noise1;
25651 : double noise2;
25652 : double noise3;
25653 : double noise4;
25654 : double noise5;
25655 : double delta0;
25656 : double delta1;
25657 : double delta2;
25658 : double delta3;
25659 : double delta4;
25660 : double d0;
25661 : double d1;
25662 : double d2;
25663 : double d3;
25664 : double newnoise0;
25665 : double newnoise1;
25666 : double newnoise2;
25667 : double newnoise3;
25668 : double newdelta0;
25669 : double newdelta1;
25670 : double newdelta2;
25671 : double rating;
25672 : double lipschitz;
25673 : double lengthrating;
25674 : ae_int_t i;
25675 : ae_int_t n;
25676 : double nrm;
25677 :
25678 :
25679 0 : n = monitor->n;
25680 0 : ae_assert(stpidx+5<sortedcnt, "C1ContinuityTest0: integrity check failed", _state);
25681 0 : ae_assert(ae_fp_eq(monitor->sortedstp.ptr.p_double[0],(double)(0)), "C1ContinuityTest0: integrity check failed", _state);
25682 0 : ae_assert(ae_fp_greater(monitor->sortedstp.ptr.p_double[sortedcnt-1],(double)(0)), "C1ContinuityTest0: integrity check failed", _state);
25683 :
25684 : /*
25685 : * Fetch F, noise, Delta's
25686 : */
25687 0 : f0 = monitor->f.ptr.p_double[stpidx+0];
25688 0 : f1 = monitor->f.ptr.p_double[stpidx+1];
25689 0 : f2 = monitor->f.ptr.p_double[stpidx+2];
25690 0 : f3 = monitor->f.ptr.p_double[stpidx+3];
25691 0 : f4 = monitor->f.ptr.p_double[stpidx+4];
25692 0 : f5 = monitor->f.ptr.p_double[stpidx+5];
25693 0 : noise0 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f0, _state), 1.0, _state);
25694 0 : noise1 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f1, _state), 1.0, _state);
25695 0 : noise2 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f2, _state), 1.0, _state);
25696 0 : noise3 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f3, _state), 1.0, _state);
25697 0 : noise4 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f4, _state), 1.0, _state);
25698 0 : noise5 = optserv_ognoiselevelf*ae_maxreal(ae_fabs(f5, _state), 1.0, _state);
25699 0 : delta0 = monitor->sortedstp.ptr.p_double[stpidx+1]-monitor->sortedstp.ptr.p_double[stpidx+0];
25700 0 : delta1 = monitor->sortedstp.ptr.p_double[stpidx+2]-monitor->sortedstp.ptr.p_double[stpidx+1];
25701 0 : delta2 = monitor->sortedstp.ptr.p_double[stpidx+3]-monitor->sortedstp.ptr.p_double[stpidx+2];
25702 0 : delta3 = monitor->sortedstp.ptr.p_double[stpidx+4]-monitor->sortedstp.ptr.p_double[stpidx+3];
25703 0 : delta4 = monitor->sortedstp.ptr.p_double[stpidx+5]-monitor->sortedstp.ptr.p_double[stpidx+4];
25704 :
25705 : /*
25706 : * Differentiate functions, get derivative values and noise
25707 : * estimates at points (0+1)/2, (1+2)/2, (3+4)/2, (3+4)/2,
25708 : * (4+5)/2. Compute new step values NewDelta[i] and new
25709 : * noise estimates.
25710 : */
25711 0 : d0 = (f1-f0)/delta0;
25712 0 : d1 = (f2-f1)/delta1;
25713 0 : d2 = (f4-f3)/delta3;
25714 0 : d3 = (f5-f4)/delta4;
25715 0 : newnoise0 = (noise0+noise1)/delta0;
25716 0 : newnoise1 = (noise1+noise2)/delta1;
25717 0 : newnoise2 = (noise3+noise4)/delta3;
25718 0 : newnoise3 = (noise4+noise5)/delta4;
25719 0 : newdelta0 = 0.5*(delta0+delta1);
25720 0 : newdelta1 = 0.5*delta1+delta2+0.5*delta3;
25721 0 : newdelta2 = 0.5*(delta3+delta4);
25722 :
25723 : /*
25724 : * Test with C0 continuity tester. "Special correction" is
25725 : * turned off for this test.
25726 : */
25727 0 : optserv_testc0continuity(d0, d1, d2, d3, newnoise0, newnoise1, newnoise2, newnoise3, newdelta0, newdelta1, newdelta2, ae_false, &rating, &lipschitz, _state);
25728 :
25729 : /*
25730 : * Store results
25731 : */
25732 0 : if( rating>optserv_ogminrating1 )
25733 : {
25734 :
25735 : /*
25736 : * Store to total report
25737 : */
25738 0 : monitor->rep.nonc1test0positive = ae_true;
25739 0 : if( rating>monitor->nonc1currentrating )
25740 : {
25741 0 : monitor->nonc1currentrating = rating;
25742 0 : monitor->rep.nonc1suspected = ae_true;
25743 0 : monitor->rep.nonc1lipschitzc = lipschitz;
25744 0 : monitor->rep.nonc1fidx = funcidx;
25745 : }
25746 :
25747 : /*
25748 : * Store to "strongest" report
25749 : */
25750 0 : if( rating>monitor->nonc1test0strrating )
25751 : {
25752 0 : monitor->nonc1test0strrating = rating;
25753 0 : monitor->nonc1test0strrep.positive = ae_true;
25754 0 : monitor->nonc1test0strrep.fidx = funcidx;
25755 0 : monitor->nonc1test0strrep.n = n;
25756 0 : monitor->nonc1test0strrep.cnt = sortedcnt;
25757 0 : monitor->nonc1test0strrep.stpidxa = stpidx+1;
25758 0 : monitor->nonc1test0strrep.stpidxb = stpidx+4;
25759 0 : rvectorsetlengthatleast(&monitor->nonc1test0strrep.x0, n, _state);
25760 0 : rvectorsetlengthatleast(&monitor->nonc1test0strrep.d, n, _state);
25761 0 : for(i=0; i<=n-1; i++)
25762 : {
25763 0 : monitor->nonc1test0strrep.x0.ptr.p_double[i] = monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[0]*n+i];
25764 0 : monitor->nonc1test0strrep.d.ptr.p_double[i] = monitor->dcur.ptr.p_double[i];
25765 : }
25766 0 : rvectorsetlengthatleast(&monitor->nonc1test0strrep.stp, sortedcnt, _state);
25767 0 : rvectorsetlengthatleast(&monitor->nonc1test0strrep.f, sortedcnt, _state);
25768 0 : for(i=0; i<=sortedcnt-1; i++)
25769 : {
25770 0 : monitor->nonc1test0strrep.stp.ptr.p_double[i] = monitor->sortedstp.ptr.p_double[i];
25771 0 : monitor->nonc1test0strrep.f.ptr.p_double[i] = monitor->f.ptr.p_double[i];
25772 : }
25773 : }
25774 :
25775 : /*
25776 : * Store to "longest" report
25777 : */
25778 0 : nrm = (double)(0);
25779 0 : for(i=0; i<=n-1; i++)
25780 : {
25781 0 : nrm = nrm+ae_sqr(monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[0]*n+i]-monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[sortedcnt-1]*n+i], _state);
25782 : }
25783 0 : nrm = ae_sqrt(nrm, _state);
25784 0 : nrm = ae_minreal(nrm, 1.0, _state);
25785 0 : nrm = coalesce(nrm, ae_machineepsilon, _state);
25786 0 : lengthrating = sortedcnt+ae_log(nrm, _state)/ae_log((double)(100), _state);
25787 0 : if( lengthrating>monitor->nonc1test0lngrating )
25788 : {
25789 0 : monitor->nonc1test0lngrating = lengthrating;
25790 0 : monitor->nonc1test0lngrep.positive = ae_true;
25791 0 : monitor->nonc1test0lngrep.fidx = funcidx;
25792 0 : monitor->nonc1test0lngrep.n = n;
25793 0 : monitor->nonc1test0lngrep.cnt = sortedcnt;
25794 0 : monitor->nonc1test0lngrep.stpidxa = stpidx+1;
25795 0 : monitor->nonc1test0lngrep.stpidxb = stpidx+4;
25796 0 : rvectorsetlengthatleast(&monitor->nonc1test0lngrep.x0, n, _state);
25797 0 : rvectorsetlengthatleast(&monitor->nonc1test0lngrep.d, n, _state);
25798 0 : for(i=0; i<=n-1; i++)
25799 : {
25800 0 : monitor->nonc1test0lngrep.x0.ptr.p_double[i] = monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[0]*n+i];
25801 0 : monitor->nonc1test0lngrep.d.ptr.p_double[i] = monitor->dcur.ptr.p_double[i];
25802 : }
25803 0 : rvectorsetlengthatleast(&monitor->nonc1test0lngrep.stp, sortedcnt, _state);
25804 0 : rvectorsetlengthatleast(&monitor->nonc1test0lngrep.f, sortedcnt, _state);
25805 0 : for(i=0; i<=sortedcnt-1; i++)
25806 : {
25807 0 : monitor->nonc1test0lngrep.stp.ptr.p_double[i] = monitor->sortedstp.ptr.p_double[i];
25808 0 : monitor->nonc1test0lngrep.f.ptr.p_double[i] = monitor->f.ptr.p_double[i];
25809 : }
25810 : }
25811 : }
25812 0 : }
25813 :
25814 :
25815 : /*************************************************************************
25816 : This subroutine checks C1 continuity using test #1 (individual gradient
25817 : components from the line search log are studied for continuity).
25818 :
25819 : An interval between F[StpIdx+0] and F[StpIdx+3]is tested for continuity.
25820 : An normalized error metric (Lipschitz constant growth for the derivative)
25821 : for the interval in question is calculated. Values above 50 are a good
25822 : indication of the discontinuity.
25823 :
25824 : -- ALGLIB --
25825 : Copyright 19.11.2018 by Bochkanov Sergey
25826 : *************************************************************************/
25827 0 : static void optserv_c1continuitytest1(smoothnessmonitor* monitor,
25828 : ae_int_t funcidx,
25829 : ae_int_t stpidx,
25830 : ae_int_t sortedcnt,
25831 : ae_state *_state)
25832 : {
25833 : ae_int_t i;
25834 : ae_int_t varidx;
25835 : ae_int_t n;
25836 : double f0;
25837 : double f1;
25838 : double f2;
25839 : double f3;
25840 : double noise0;
25841 : double noise1;
25842 : double noise2;
25843 : double noise3;
25844 : double nrm;
25845 : double rating;
25846 : double lengthrating;
25847 : double lipschitz;
25848 :
25849 :
25850 0 : n = monitor->n;
25851 0 : ae_assert(stpidx+3<sortedcnt, "C1ContinuityTest1: integrity check failed", _state);
25852 0 : ae_assert(ae_fp_eq(monitor->sortedstp.ptr.p_double[0],(double)(0)), "C1ContinuityTest1: integrity check failed", _state);
25853 0 : ae_assert(ae_fp_greater(monitor->sortedstp.ptr.p_double[sortedcnt-1],(double)(0)), "C1ContinuityTest1: integrity check failed", _state);
25854 :
25855 : /*
25856 : * Study each component of the gradient in the interval in question
25857 : */
25858 0 : for(varidx=0; varidx<=n-1; varidx++)
25859 : {
25860 0 : f0 = monitor->g.ptr.p_double[(stpidx+0)*n+varidx];
25861 0 : f1 = monitor->g.ptr.p_double[(stpidx+1)*n+varidx];
25862 0 : f2 = monitor->g.ptr.p_double[(stpidx+2)*n+varidx];
25863 0 : f3 = monitor->g.ptr.p_double[(stpidx+3)*n+varidx];
25864 0 : noise0 = optserv_ognoiselevelg*ae_maxreal(ae_fabs(f0, _state), 1.0, _state);
25865 0 : noise1 = optserv_ognoiselevelg*ae_maxreal(ae_fabs(f1, _state), 1.0, _state);
25866 0 : noise2 = optserv_ognoiselevelg*ae_maxreal(ae_fabs(f2, _state), 1.0, _state);
25867 0 : noise3 = optserv_ognoiselevelg*ae_maxreal(ae_fabs(f3, _state), 1.0, _state);
25868 0 : optserv_testc0continuity(f0, f1, f2, f3, noise0, noise1, noise2, noise3, monitor->sortedstp.ptr.p_double[stpidx+1]-monitor->sortedstp.ptr.p_double[stpidx+0], monitor->sortedstp.ptr.p_double[stpidx+2]-monitor->sortedstp.ptr.p_double[stpidx+1], monitor->sortedstp.ptr.p_double[stpidx+3]-monitor->sortedstp.ptr.p_double[stpidx+2], ae_false, &rating, &lipschitz, _state);
25869 :
25870 : /*
25871 : * Store results
25872 : */
25873 0 : if( rating>optserv_ogminrating1 )
25874 : {
25875 :
25876 : /*
25877 : * Store to total report
25878 : */
25879 0 : monitor->rep.nonc1test1positive = ae_true;
25880 0 : if( rating>monitor->nonc1currentrating )
25881 : {
25882 0 : monitor->nonc1currentrating = rating;
25883 0 : monitor->rep.nonc1suspected = ae_true;
25884 0 : monitor->rep.nonc1lipschitzc = lipschitz;
25885 0 : monitor->rep.nonc1fidx = funcidx;
25886 : }
25887 :
25888 : /*
25889 : * Store to "strongest" report
25890 : */
25891 0 : if( rating>monitor->nonc1test1strrating )
25892 : {
25893 0 : monitor->nonc1test1strrating = rating;
25894 0 : monitor->nonc1test1strrep.positive = ae_true;
25895 0 : monitor->nonc1test1strrep.fidx = funcidx;
25896 0 : monitor->nonc1test1strrep.vidx = varidx;
25897 0 : monitor->nonc1test1strrep.n = n;
25898 0 : monitor->nonc1test1strrep.cnt = sortedcnt;
25899 0 : monitor->nonc1test1strrep.stpidxa = stpidx+0;
25900 0 : monitor->nonc1test1strrep.stpidxb = stpidx+3;
25901 0 : rvectorsetlengthatleast(&monitor->nonc1test1strrep.x0, n, _state);
25902 0 : rvectorsetlengthatleast(&monitor->nonc1test1strrep.d, n, _state);
25903 0 : for(i=0; i<=n-1; i++)
25904 : {
25905 0 : monitor->nonc1test1strrep.x0.ptr.p_double[i] = monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[0]*n+i];
25906 0 : monitor->nonc1test1strrep.d.ptr.p_double[i] = monitor->dcur.ptr.p_double[i];
25907 : }
25908 0 : rvectorsetlengthatleast(&monitor->nonc1test1strrep.stp, sortedcnt, _state);
25909 0 : rvectorsetlengthatleast(&monitor->nonc1test1strrep.g, sortedcnt, _state);
25910 0 : for(i=0; i<=sortedcnt-1; i++)
25911 : {
25912 0 : monitor->nonc1test1strrep.stp.ptr.p_double[i] = monitor->sortedstp.ptr.p_double[i];
25913 0 : monitor->nonc1test1strrep.g.ptr.p_double[i] = monitor->g.ptr.p_double[i*n+varidx];
25914 : }
25915 : }
25916 :
25917 : /*
25918 : * Store to "longest" report
25919 : */
25920 0 : nrm = (double)(0);
25921 0 : for(i=0; i<=n-1; i++)
25922 : {
25923 0 : nrm = nrm+ae_sqr(monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[0]*n+i]-monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[sortedcnt-1]*n+i], _state);
25924 : }
25925 0 : nrm = ae_sqrt(nrm, _state);
25926 0 : nrm = ae_minreal(nrm, 1.0, _state);
25927 0 : nrm = coalesce(nrm, ae_machineepsilon, _state);
25928 0 : lengthrating = sortedcnt+ae_log(nrm, _state)/ae_log((double)(100), _state);
25929 0 : if( lengthrating>monitor->nonc1test1lngrating )
25930 : {
25931 0 : monitor->nonc1test1lngrating = lengthrating;
25932 0 : monitor->nonc1test1lngrep.positive = ae_true;
25933 0 : monitor->nonc1test1lngrep.fidx = funcidx;
25934 0 : monitor->nonc1test1lngrep.vidx = varidx;
25935 0 : monitor->nonc1test1lngrep.n = n;
25936 0 : monitor->nonc1test1lngrep.cnt = sortedcnt;
25937 0 : monitor->nonc1test1lngrep.stpidxa = stpidx+0;
25938 0 : monitor->nonc1test1lngrep.stpidxb = stpidx+3;
25939 0 : rvectorsetlengthatleast(&monitor->nonc1test1lngrep.x0, n, _state);
25940 0 : rvectorsetlengthatleast(&monitor->nonc1test1lngrep.d, n, _state);
25941 0 : for(i=0; i<=n-1; i++)
25942 : {
25943 0 : monitor->nonc1test1lngrep.x0.ptr.p_double[i] = monitor->enqueuedx.ptr.p_double[monitor->sortedidx.ptr.p_int[0]*n+i];
25944 0 : monitor->nonc1test1lngrep.d.ptr.p_double[i] = monitor->dcur.ptr.p_double[i];
25945 : }
25946 0 : rvectorsetlengthatleast(&monitor->nonc1test1lngrep.stp, sortedcnt, _state);
25947 0 : rvectorsetlengthatleast(&monitor->nonc1test1lngrep.g, sortedcnt, _state);
25948 0 : for(i=0; i<=sortedcnt-1; i++)
25949 : {
25950 0 : monitor->nonc1test1lngrep.stp.ptr.p_double[i] = monitor->sortedstp.ptr.p_double[i];
25951 0 : monitor->nonc1test1lngrep.g.ptr.p_double[i] = monitor->g.ptr.p_double[i*n+varidx];
25952 : }
25953 : }
25954 : }
25955 : }
25956 0 : }
25957 :
25958 :
25959 498 : void _precbuflbfgs_init(void* _p, ae_state *_state, ae_bool make_automatic)
25960 : {
25961 498 : precbuflbfgs *p = (precbuflbfgs*)_p;
25962 498 : ae_touch_ptr((void*)p);
25963 498 : ae_vector_init(&p->norms, 0, DT_REAL, _state, make_automatic);
25964 498 : ae_vector_init(&p->alpha, 0, DT_REAL, _state, make_automatic);
25965 498 : ae_vector_init(&p->rho, 0, DT_REAL, _state, make_automatic);
25966 498 : ae_matrix_init(&p->yk, 0, 0, DT_REAL, _state, make_automatic);
25967 498 : ae_vector_init(&p->idx, 0, DT_INT, _state, make_automatic);
25968 498 : ae_vector_init(&p->bufa, 0, DT_REAL, _state, make_automatic);
25969 498 : ae_vector_init(&p->bufb, 0, DT_INT, _state, make_automatic);
25970 498 : }
25971 :
25972 :
25973 0 : void _precbuflbfgs_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
25974 : {
25975 0 : precbuflbfgs *dst = (precbuflbfgs*)_dst;
25976 0 : precbuflbfgs *src = (precbuflbfgs*)_src;
25977 0 : ae_vector_init_copy(&dst->norms, &src->norms, _state, make_automatic);
25978 0 : ae_vector_init_copy(&dst->alpha, &src->alpha, _state, make_automatic);
25979 0 : ae_vector_init_copy(&dst->rho, &src->rho, _state, make_automatic);
25980 0 : ae_matrix_init_copy(&dst->yk, &src->yk, _state, make_automatic);
25981 0 : ae_vector_init_copy(&dst->idx, &src->idx, _state, make_automatic);
25982 0 : ae_vector_init_copy(&dst->bufa, &src->bufa, _state, make_automatic);
25983 0 : ae_vector_init_copy(&dst->bufb, &src->bufb, _state, make_automatic);
25984 0 : }
25985 :
25986 :
25987 498 : void _precbuflbfgs_clear(void* _p)
25988 : {
25989 498 : precbuflbfgs *p = (precbuflbfgs*)_p;
25990 498 : ae_touch_ptr((void*)p);
25991 498 : ae_vector_clear(&p->norms);
25992 498 : ae_vector_clear(&p->alpha);
25993 498 : ae_vector_clear(&p->rho);
25994 498 : ae_matrix_clear(&p->yk);
25995 498 : ae_vector_clear(&p->idx);
25996 498 : ae_vector_clear(&p->bufa);
25997 498 : ae_vector_clear(&p->bufb);
25998 498 : }
25999 :
26000 :
26001 498 : void _precbuflbfgs_destroy(void* _p)
26002 : {
26003 498 : precbuflbfgs *p = (precbuflbfgs*)_p;
26004 498 : ae_touch_ptr((void*)p);
26005 498 : ae_vector_destroy(&p->norms);
26006 498 : ae_vector_destroy(&p->alpha);
26007 498 : ae_vector_destroy(&p->rho);
26008 498 : ae_matrix_destroy(&p->yk);
26009 498 : ae_vector_destroy(&p->idx);
26010 498 : ae_vector_destroy(&p->bufa);
26011 498 : ae_vector_destroy(&p->bufb);
26012 498 : }
26013 :
26014 :
26015 498 : void _precbuflowrank_init(void* _p, ae_state *_state, ae_bool make_automatic)
26016 : {
26017 498 : precbuflowrank *p = (precbuflowrank*)_p;
26018 498 : ae_touch_ptr((void*)p);
26019 498 : ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic);
26020 498 : ae_matrix_init(&p->v, 0, 0, DT_REAL, _state, make_automatic);
26021 498 : ae_vector_init(&p->bufc, 0, DT_REAL, _state, make_automatic);
26022 498 : ae_matrix_init(&p->bufz, 0, 0, DT_REAL, _state, make_automatic);
26023 498 : ae_matrix_init(&p->bufw, 0, 0, DT_REAL, _state, make_automatic);
26024 498 : ae_vector_init(&p->tmp, 0, DT_REAL, _state, make_automatic);
26025 498 : }
26026 :
26027 :
26028 0 : void _precbuflowrank_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
26029 : {
26030 0 : precbuflowrank *dst = (precbuflowrank*)_dst;
26031 0 : precbuflowrank *src = (precbuflowrank*)_src;
26032 0 : dst->n = src->n;
26033 0 : dst->k = src->k;
26034 0 : ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic);
26035 0 : ae_matrix_init_copy(&dst->v, &src->v, _state, make_automatic);
26036 0 : ae_vector_init_copy(&dst->bufc, &src->bufc, _state, make_automatic);
26037 0 : ae_matrix_init_copy(&dst->bufz, &src->bufz, _state, make_automatic);
26038 0 : ae_matrix_init_copy(&dst->bufw, &src->bufw, _state, make_automatic);
26039 0 : ae_vector_init_copy(&dst->tmp, &src->tmp, _state, make_automatic);
26040 0 : }
26041 :
26042 :
26043 498 : void _precbuflowrank_clear(void* _p)
26044 : {
26045 498 : precbuflowrank *p = (precbuflowrank*)_p;
26046 498 : ae_touch_ptr((void*)p);
26047 498 : ae_vector_clear(&p->d);
26048 498 : ae_matrix_clear(&p->v);
26049 498 : ae_vector_clear(&p->bufc);
26050 498 : ae_matrix_clear(&p->bufz);
26051 498 : ae_matrix_clear(&p->bufw);
26052 498 : ae_vector_clear(&p->tmp);
26053 498 : }
26054 :
26055 :
26056 498 : void _precbuflowrank_destroy(void* _p)
26057 : {
26058 498 : precbuflowrank *p = (precbuflowrank*)_p;
26059 498 : ae_touch_ptr((void*)p);
26060 498 : ae_vector_destroy(&p->d);
26061 498 : ae_matrix_destroy(&p->v);
26062 498 : ae_vector_destroy(&p->bufc);
26063 498 : ae_matrix_destroy(&p->bufz);
26064 498 : ae_matrix_destroy(&p->bufw);
26065 498 : ae_vector_destroy(&p->tmp);
26066 498 : }
26067 :
26068 :
26069 498 : void _smoothnessmonitor_init(void* _p, ae_state *_state, ae_bool make_automatic)
26070 : {
26071 498 : smoothnessmonitor *p = (smoothnessmonitor*)_p;
26072 498 : ae_touch_ptr((void*)p);
26073 498 : ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic);
26074 498 : ae_vector_init(&p->dcur, 0, DT_REAL, _state, make_automatic);
26075 498 : ae_vector_init(&p->enqueuedstp, 0, DT_REAL, _state, make_automatic);
26076 498 : ae_vector_init(&p->enqueuedx, 0, DT_REAL, _state, make_automatic);
26077 498 : ae_vector_init(&p->enqueuedfunc, 0, DT_REAL, _state, make_automatic);
26078 498 : ae_matrix_init(&p->enqueuedjac, 0, 0, DT_REAL, _state, make_automatic);
26079 498 : ae_vector_init(&p->sortedstp, 0, DT_REAL, _state, make_automatic);
26080 498 : ae_vector_init(&p->sortedidx, 0, DT_INT, _state, make_automatic);
26081 498 : ae_vector_init(&p->probingf, 0, DT_REAL, _state, make_automatic);
26082 498 : ae_vector_init(&p->probingsteps, 0, DT_REAL, _state, make_automatic);
26083 498 : ae_matrix_init(&p->probingvalues, 0, 0, DT_REAL, _state, make_automatic);
26084 498 : ae_matrix_init(&p->probingslopes, 0, 0, DT_REAL, _state, make_automatic);
26085 498 : _rcommstate_init(&p->probingrcomm, _state, make_automatic);
26086 498 : _optguardreport_init(&p->rep, _state, make_automatic);
26087 498 : _optguardnonc0report_init(&p->nonc0strrep, _state, make_automatic);
26088 498 : _optguardnonc0report_init(&p->nonc0lngrep, _state, make_automatic);
26089 498 : _optguardnonc1test0report_init(&p->nonc1test0strrep, _state, make_automatic);
26090 498 : _optguardnonc1test0report_init(&p->nonc1test0lngrep, _state, make_automatic);
26091 498 : _optguardnonc1test1report_init(&p->nonc1test1strrep, _state, make_automatic);
26092 498 : _optguardnonc1test1report_init(&p->nonc1test1lngrep, _state, make_automatic);
26093 498 : ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
26094 498 : ae_vector_init(&p->fi, 0, DT_REAL, _state, make_automatic);
26095 498 : ae_matrix_init(&p->j, 0, 0, DT_REAL, _state, make_automatic);
26096 498 : _rcommstate_init(&p->rstateg0, _state, make_automatic);
26097 498 : ae_vector_init(&p->xbase, 0, DT_REAL, _state, make_automatic);
26098 498 : ae_vector_init(&p->fbase, 0, DT_REAL, _state, make_automatic);
26099 498 : ae_vector_init(&p->fm, 0, DT_REAL, _state, make_automatic);
26100 498 : ae_vector_init(&p->fc, 0, DT_REAL, _state, make_automatic);
26101 498 : ae_vector_init(&p->fp, 0, DT_REAL, _state, make_automatic);
26102 498 : ae_vector_init(&p->jm, 0, DT_REAL, _state, make_automatic);
26103 498 : ae_vector_init(&p->jc, 0, DT_REAL, _state, make_automatic);
26104 498 : ae_vector_init(&p->jp, 0, DT_REAL, _state, make_automatic);
26105 498 : ae_matrix_init(&p->jbaseusr, 0, 0, DT_REAL, _state, make_automatic);
26106 498 : ae_matrix_init(&p->jbasenum, 0, 0, DT_REAL, _state, make_automatic);
26107 498 : ae_vector_init(&p->stp, 0, DT_REAL, _state, make_automatic);
26108 498 : ae_vector_init(&p->bufr, 0, DT_REAL, _state, make_automatic);
26109 498 : ae_vector_init(&p->f, 0, DT_REAL, _state, make_automatic);
26110 498 : ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic);
26111 498 : ae_vector_init(&p->deltax, 0, DT_REAL, _state, make_automatic);
26112 498 : ae_vector_init(&p->tmpidx, 0, DT_INT, _state, make_automatic);
26113 498 : ae_vector_init(&p->bufi, 0, DT_INT, _state, make_automatic);
26114 498 : ae_vector_init(&p->xu, 0, DT_REAL, _state, make_automatic);
26115 498 : ae_vector_init(&p->du, 0, DT_REAL, _state, make_automatic);
26116 498 : ae_vector_init(&p->f0, 0, DT_REAL, _state, make_automatic);
26117 498 : ae_matrix_init(&p->j0, 0, 0, DT_REAL, _state, make_automatic);
26118 498 : }
26119 :
26120 :
26121 0 : void _smoothnessmonitor_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
26122 : {
26123 0 : smoothnessmonitor *dst = (smoothnessmonitor*)_dst;
26124 0 : smoothnessmonitor *src = (smoothnessmonitor*)_src;
26125 0 : dst->n = src->n;
26126 0 : dst->k = src->k;
26127 0 : dst->checksmoothness = src->checksmoothness;
26128 0 : ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic);
26129 0 : ae_vector_init_copy(&dst->dcur, &src->dcur, _state, make_automatic);
26130 0 : dst->enqueuedcnt = src->enqueuedcnt;
26131 0 : ae_vector_init_copy(&dst->enqueuedstp, &src->enqueuedstp, _state, make_automatic);
26132 0 : ae_vector_init_copy(&dst->enqueuedx, &src->enqueuedx, _state, make_automatic);
26133 0 : ae_vector_init_copy(&dst->enqueuedfunc, &src->enqueuedfunc, _state, make_automatic);
26134 0 : ae_matrix_init_copy(&dst->enqueuedjac, &src->enqueuedjac, _state, make_automatic);
26135 0 : ae_vector_init_copy(&dst->sortedstp, &src->sortedstp, _state, make_automatic);
26136 0 : ae_vector_init_copy(&dst->sortedidx, &src->sortedidx, _state, make_automatic);
26137 0 : dst->sortedcnt = src->sortedcnt;
26138 0 : dst->probingstp = src->probingstp;
26139 0 : ae_vector_init_copy(&dst->probingf, &src->probingf, _state, make_automatic);
26140 0 : dst->probingnvalues = src->probingnvalues;
26141 0 : dst->probingstepmax = src->probingstepmax;
26142 0 : dst->probingstepscale = src->probingstepscale;
26143 0 : dst->probingnstepsstored = src->probingnstepsstored;
26144 0 : ae_vector_init_copy(&dst->probingsteps, &src->probingsteps, _state, make_automatic);
26145 0 : ae_matrix_init_copy(&dst->probingvalues, &src->probingvalues, _state, make_automatic);
26146 0 : ae_matrix_init_copy(&dst->probingslopes, &src->probingslopes, _state, make_automatic);
26147 0 : _rcommstate_init_copy(&dst->probingrcomm, &src->probingrcomm, _state, make_automatic);
26148 0 : dst->linesearchspoiled = src->linesearchspoiled;
26149 0 : dst->linesearchstarted = src->linesearchstarted;
26150 0 : dst->nonc0currentrating = src->nonc0currentrating;
26151 0 : dst->nonc1currentrating = src->nonc1currentrating;
26152 0 : dst->badgradhasxj = src->badgradhasxj;
26153 0 : _optguardreport_init_copy(&dst->rep, &src->rep, _state, make_automatic);
26154 0 : dst->nonc0strrating = src->nonc0strrating;
26155 0 : dst->nonc0lngrating = src->nonc0lngrating;
26156 0 : _optguardnonc0report_init_copy(&dst->nonc0strrep, &src->nonc0strrep, _state, make_automatic);
26157 0 : _optguardnonc0report_init_copy(&dst->nonc0lngrep, &src->nonc0lngrep, _state, make_automatic);
26158 0 : dst->nonc1test0strrating = src->nonc1test0strrating;
26159 0 : dst->nonc1test0lngrating = src->nonc1test0lngrating;
26160 0 : _optguardnonc1test0report_init_copy(&dst->nonc1test0strrep, &src->nonc1test0strrep, _state, make_automatic);
26161 0 : _optguardnonc1test0report_init_copy(&dst->nonc1test0lngrep, &src->nonc1test0lngrep, _state, make_automatic);
26162 0 : dst->nonc1test1strrating = src->nonc1test1strrating;
26163 0 : dst->nonc1test1lngrating = src->nonc1test1lngrating;
26164 0 : _optguardnonc1test1report_init_copy(&dst->nonc1test1strrep, &src->nonc1test1strrep, _state, make_automatic);
26165 0 : _optguardnonc1test1report_init_copy(&dst->nonc1test1lngrep, &src->nonc1test1lngrep, _state, make_automatic);
26166 0 : dst->needfij = src->needfij;
26167 0 : ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
26168 0 : ae_vector_init_copy(&dst->fi, &src->fi, _state, make_automatic);
26169 0 : ae_matrix_init_copy(&dst->j, &src->j, _state, make_automatic);
26170 0 : _rcommstate_init_copy(&dst->rstateg0, &src->rstateg0, _state, make_automatic);
26171 0 : ae_vector_init_copy(&dst->xbase, &src->xbase, _state, make_automatic);
26172 0 : ae_vector_init_copy(&dst->fbase, &src->fbase, _state, make_automatic);
26173 0 : ae_vector_init_copy(&dst->fm, &src->fm, _state, make_automatic);
26174 0 : ae_vector_init_copy(&dst->fc, &src->fc, _state, make_automatic);
26175 0 : ae_vector_init_copy(&dst->fp, &src->fp, _state, make_automatic);
26176 0 : ae_vector_init_copy(&dst->jm, &src->jm, _state, make_automatic);
26177 0 : ae_vector_init_copy(&dst->jc, &src->jc, _state, make_automatic);
26178 0 : ae_vector_init_copy(&dst->jp, &src->jp, _state, make_automatic);
26179 0 : ae_matrix_init_copy(&dst->jbaseusr, &src->jbaseusr, _state, make_automatic);
26180 0 : ae_matrix_init_copy(&dst->jbasenum, &src->jbasenum, _state, make_automatic);
26181 0 : ae_vector_init_copy(&dst->stp, &src->stp, _state, make_automatic);
26182 0 : ae_vector_init_copy(&dst->bufr, &src->bufr, _state, make_automatic);
26183 0 : ae_vector_init_copy(&dst->f, &src->f, _state, make_automatic);
26184 0 : ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic);
26185 0 : ae_vector_init_copy(&dst->deltax, &src->deltax, _state, make_automatic);
26186 0 : ae_vector_init_copy(&dst->tmpidx, &src->tmpidx, _state, make_automatic);
26187 0 : ae_vector_init_copy(&dst->bufi, &src->bufi, _state, make_automatic);
26188 0 : ae_vector_init_copy(&dst->xu, &src->xu, _state, make_automatic);
26189 0 : ae_vector_init_copy(&dst->du, &src->du, _state, make_automatic);
26190 0 : ae_vector_init_copy(&dst->f0, &src->f0, _state, make_automatic);
26191 0 : ae_matrix_init_copy(&dst->j0, &src->j0, _state, make_automatic);
26192 0 : }
26193 :
26194 :
26195 498 : void _smoothnessmonitor_clear(void* _p)
26196 : {
26197 498 : smoothnessmonitor *p = (smoothnessmonitor*)_p;
26198 498 : ae_touch_ptr((void*)p);
26199 498 : ae_vector_clear(&p->s);
26200 498 : ae_vector_clear(&p->dcur);
26201 498 : ae_vector_clear(&p->enqueuedstp);
26202 498 : ae_vector_clear(&p->enqueuedx);
26203 498 : ae_vector_clear(&p->enqueuedfunc);
26204 498 : ae_matrix_clear(&p->enqueuedjac);
26205 498 : ae_vector_clear(&p->sortedstp);
26206 498 : ae_vector_clear(&p->sortedidx);
26207 498 : ae_vector_clear(&p->probingf);
26208 498 : ae_vector_clear(&p->probingsteps);
26209 498 : ae_matrix_clear(&p->probingvalues);
26210 498 : ae_matrix_clear(&p->probingslopes);
26211 498 : _rcommstate_clear(&p->probingrcomm);
26212 498 : _optguardreport_clear(&p->rep);
26213 498 : _optguardnonc0report_clear(&p->nonc0strrep);
26214 498 : _optguardnonc0report_clear(&p->nonc0lngrep);
26215 498 : _optguardnonc1test0report_clear(&p->nonc1test0strrep);
26216 498 : _optguardnonc1test0report_clear(&p->nonc1test0lngrep);
26217 498 : _optguardnonc1test1report_clear(&p->nonc1test1strrep);
26218 498 : _optguardnonc1test1report_clear(&p->nonc1test1lngrep);
26219 498 : ae_vector_clear(&p->x);
26220 498 : ae_vector_clear(&p->fi);
26221 498 : ae_matrix_clear(&p->j);
26222 498 : _rcommstate_clear(&p->rstateg0);
26223 498 : ae_vector_clear(&p->xbase);
26224 498 : ae_vector_clear(&p->fbase);
26225 498 : ae_vector_clear(&p->fm);
26226 498 : ae_vector_clear(&p->fc);
26227 498 : ae_vector_clear(&p->fp);
26228 498 : ae_vector_clear(&p->jm);
26229 498 : ae_vector_clear(&p->jc);
26230 498 : ae_vector_clear(&p->jp);
26231 498 : ae_matrix_clear(&p->jbaseusr);
26232 498 : ae_matrix_clear(&p->jbasenum);
26233 498 : ae_vector_clear(&p->stp);
26234 498 : ae_vector_clear(&p->bufr);
26235 498 : ae_vector_clear(&p->f);
26236 498 : ae_vector_clear(&p->g);
26237 498 : ae_vector_clear(&p->deltax);
26238 498 : ae_vector_clear(&p->tmpidx);
26239 498 : ae_vector_clear(&p->bufi);
26240 498 : ae_vector_clear(&p->xu);
26241 498 : ae_vector_clear(&p->du);
26242 498 : ae_vector_clear(&p->f0);
26243 498 : ae_matrix_clear(&p->j0);
26244 498 : }
26245 :
26246 :
26247 498 : void _smoothnessmonitor_destroy(void* _p)
26248 : {
26249 498 : smoothnessmonitor *p = (smoothnessmonitor*)_p;
26250 498 : ae_touch_ptr((void*)p);
26251 498 : ae_vector_destroy(&p->s);
26252 498 : ae_vector_destroy(&p->dcur);
26253 498 : ae_vector_destroy(&p->enqueuedstp);
26254 498 : ae_vector_destroy(&p->enqueuedx);
26255 498 : ae_vector_destroy(&p->enqueuedfunc);
26256 498 : ae_matrix_destroy(&p->enqueuedjac);
26257 498 : ae_vector_destroy(&p->sortedstp);
26258 498 : ae_vector_destroy(&p->sortedidx);
26259 498 : ae_vector_destroy(&p->probingf);
26260 498 : ae_vector_destroy(&p->probingsteps);
26261 498 : ae_matrix_destroy(&p->probingvalues);
26262 498 : ae_matrix_destroy(&p->probingslopes);
26263 498 : _rcommstate_destroy(&p->probingrcomm);
26264 498 : _optguardreport_destroy(&p->rep);
26265 498 : _optguardnonc0report_destroy(&p->nonc0strrep);
26266 498 : _optguardnonc0report_destroy(&p->nonc0lngrep);
26267 498 : _optguardnonc1test0report_destroy(&p->nonc1test0strrep);
26268 498 : _optguardnonc1test0report_destroy(&p->nonc1test0lngrep);
26269 498 : _optguardnonc1test1report_destroy(&p->nonc1test1strrep);
26270 498 : _optguardnonc1test1report_destroy(&p->nonc1test1lngrep);
26271 498 : ae_vector_destroy(&p->x);
26272 498 : ae_vector_destroy(&p->fi);
26273 498 : ae_matrix_destroy(&p->j);
26274 498 : _rcommstate_destroy(&p->rstateg0);
26275 498 : ae_vector_destroy(&p->xbase);
26276 498 : ae_vector_destroy(&p->fbase);
26277 498 : ae_vector_destroy(&p->fm);
26278 498 : ae_vector_destroy(&p->fc);
26279 498 : ae_vector_destroy(&p->fp);
26280 498 : ae_vector_destroy(&p->jm);
26281 498 : ae_vector_destroy(&p->jc);
26282 498 : ae_vector_destroy(&p->jp);
26283 498 : ae_matrix_destroy(&p->jbaseusr);
26284 498 : ae_matrix_destroy(&p->jbasenum);
26285 498 : ae_vector_destroy(&p->stp);
26286 498 : ae_vector_destroy(&p->bufr);
26287 498 : ae_vector_destroy(&p->f);
26288 498 : ae_vector_destroy(&p->g);
26289 498 : ae_vector_destroy(&p->deltax);
26290 498 : ae_vector_destroy(&p->tmpidx);
26291 498 : ae_vector_destroy(&p->bufi);
26292 498 : ae_vector_destroy(&p->xu);
26293 498 : ae_vector_destroy(&p->du);
26294 498 : ae_vector_destroy(&p->f0);
26295 498 : ae_matrix_destroy(&p->j0);
26296 498 : }
26297 :
26298 :
26299 : #endif
26300 : #if defined(AE_COMPILE_SNNLS) || !defined(AE_PARTIAL_BUILD)
26301 :
26302 :
26303 : /*************************************************************************
26304 : This subroutine is used to initialize SNNLS solver.
26305 :
26306 : By default, empty NNLS problem is produced, but we allocated enough space
26307 : to store problems with NSMax+NDMax columns and NRMax rows. It is good
26308 : place to provide algorithm with initial estimate of the space requirements,
26309 : although you may underestimate problem size or even pass zero estimates -
26310 : in this case buffer variables will be resized automatically when you set
26311 : NNLS problem.
26312 :
26313 : Previously allocated buffer variables are reused as much as possible. This
26314 : function does not clear structure completely, it tries to preserve as much
26315 : dynamically allocated memory as possible.
26316 :
26317 : -- ALGLIB --
26318 : Copyright 10.10.2012 by Bochkanov Sergey
26319 : *************************************************************************/
26320 0 : void snnlsinit(ae_int_t nsmax,
26321 : ae_int_t ndmax,
26322 : ae_int_t nrmax,
26323 : snnlssolver* s,
26324 : ae_state *_state)
26325 : {
26326 :
26327 :
26328 0 : s->ns = 0;
26329 0 : s->nd = 0;
26330 0 : s->nr = 0;
26331 0 : rmatrixsetlengthatleast(&s->densea, nrmax, ndmax, _state);
26332 0 : rmatrixsetlengthatleast(&s->tmpca, nrmax, ndmax, _state);
26333 0 : rvectorsetlengthatleast(&s->b, nrmax, _state);
26334 0 : bvectorsetlengthatleast(&s->nnc, nsmax+ndmax, _state);
26335 0 : s->debugflops = 0.0;
26336 0 : s->debugmaxinnerits = 0;
26337 0 : }
26338 :
26339 :
26340 : /*************************************************************************
26341 : This subroutine is used to set NNLS problem:
26342 :
26343 : ( [ 1 | ] [ ] [ ] )^2
26344 : ( [ 1 | ] [ ] [ ] )
26345 : min ( [ 1 | Ad ] * [ x ] - [ b ] ) s.t. x>=0
26346 : ( [ | ] [ ] [ ] )
26347 : ( [ | ] [ ] [ ] )
26348 :
26349 : where:
26350 : * identity matrix has NS*NS size (NS<=NR, NS can be zero)
26351 : * dense matrix Ad has NR*ND size
26352 : * b is NR*1 vector
26353 : * x is (NS+ND)*1 vector
26354 : * all elements of x are non-negative (this constraint can be removed later
26355 : by calling SNNLSDropNNC() function)
26356 :
26357 : Previously allocated buffer variables are reused as much as possible.
26358 : After you set problem, you can solve it with SNNLSSolve().
26359 :
26360 : INPUT PARAMETERS:
26361 : S - SNNLS solver, must be initialized with SNNLSInit() call
26362 : A - array[NR,ND], dense part of the system
26363 : B - array[NR], right part
26364 : NS - size of the sparse part of the system, 0<=NS<=NR
26365 : ND - size of the dense part of the system, ND>=0
26366 : NR - rows count, NR>0
26367 :
26368 : NOTE:
26369 : 1. You can have NS+ND=0, solver will correctly accept such combination
26370 : and return empty array as problem solution.
26371 :
26372 : -- ALGLIB --
26373 : Copyright 10.10.2012 by Bochkanov Sergey
26374 : *************************************************************************/
26375 0 : void snnlssetproblem(snnlssolver* s,
26376 : /* Real */ ae_matrix* a,
26377 : /* Real */ ae_vector* b,
26378 : ae_int_t ns,
26379 : ae_int_t nd,
26380 : ae_int_t nr,
26381 : ae_state *_state)
26382 : {
26383 : ae_int_t i;
26384 :
26385 :
26386 0 : ae_assert(nd>=0, "SNNLSSetProblem: ND<0", _state);
26387 0 : ae_assert(ns>=0, "SNNLSSetProblem: NS<0", _state);
26388 0 : ae_assert(nr>0, "SNNLSSetProblem: NR<=0", _state);
26389 0 : ae_assert(ns<=nr, "SNNLSSetProblem: NS>NR", _state);
26390 0 : ae_assert(a->rows>=nr||nd==0, "SNNLSSetProblem: rows(A)<NR", _state);
26391 0 : ae_assert(a->cols>=nd, "SNNLSSetProblem: cols(A)<ND", _state);
26392 0 : ae_assert(b->cnt>=nr, "SNNLSSetProblem: length(B)<NR", _state);
26393 0 : ae_assert(apservisfinitematrix(a, nr, nd, _state), "SNNLSSetProblem: A contains INF/NAN", _state);
26394 0 : ae_assert(isfinitevector(b, nr, _state), "SNNLSSetProblem: B contains INF/NAN", _state);
26395 :
26396 : /*
26397 : * Copy problem
26398 : */
26399 0 : s->ns = ns;
26400 0 : s->nd = nd;
26401 0 : s->nr = nr;
26402 0 : if( nd>0 )
26403 : {
26404 0 : rmatrixsetlengthatleast(&s->densea, nr, nd, _state);
26405 0 : for(i=0; i<=nr-1; i++)
26406 : {
26407 0 : ae_v_move(&s->densea.ptr.pp_double[i][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,nd-1));
26408 : }
26409 : }
26410 0 : rvectorsetlengthatleast(&s->b, nr, _state);
26411 0 : ae_v_move(&s->b.ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,nr-1));
26412 0 : bvectorsetlengthatleast(&s->nnc, ns+nd, _state);
26413 0 : for(i=0; i<=ns+nd-1; i++)
26414 : {
26415 0 : s->nnc.ptr.p_bool[i] = ae_true;
26416 : }
26417 0 : }
26418 :
26419 :
26420 : /*************************************************************************
26421 : This subroutine drops non-negativity constraint from the problem set by
26422 : SNNLSSetProblem() call. This function must be called AFTER problem is set,
26423 : because each SetProblem() call resets constraints to their default state
26424 : (all constraints are present).
26425 :
26426 : INPUT PARAMETERS:
26427 : S - SNNLS solver, must be initialized with SNNLSInit() call,
26428 : problem must be set with SNNLSSetProblem() call.
26429 : Idx - constraint index, 0<=IDX<NS+ND
26430 :
26431 : -- ALGLIB --
26432 : Copyright 10.10.2012 by Bochkanov Sergey
26433 : *************************************************************************/
26434 0 : void snnlsdropnnc(snnlssolver* s, ae_int_t idx, ae_state *_state)
26435 : {
26436 :
26437 :
26438 0 : ae_assert(idx>=0, "SNNLSDropNNC: Idx<0", _state);
26439 0 : ae_assert(idx<s->ns+s->nd, "SNNLSDropNNC: Idx>=NS+ND", _state);
26440 0 : s->nnc.ptr.p_bool[idx] = ae_false;
26441 0 : }
26442 :
26443 :
26444 : /*************************************************************************
26445 : This subroutine is used to solve NNLS problem.
26446 :
26447 : INPUT PARAMETERS:
26448 : S - SNNLS solver, must be initialized with SNNLSInit() call and
26449 : problem must be set up with SNNLSSetProblem() call.
26450 : X - possibly preallocated buffer, automatically resized if needed
26451 :
26452 : OUTPUT PARAMETERS:
26453 : X - array[NS+ND], solution
26454 :
26455 : NOTE:
26456 : 1. You can have NS+ND=0, solver will correctly accept such combination
26457 : and return empty array as problem solution.
26458 :
26459 : 2. Internal field S.DebugFLOPS contains rough estimate of FLOPs used
26460 : to solve problem. It can be used for debugging purposes. This field
26461 : is real-valued.
26462 :
26463 : -- ALGLIB --
26464 : Copyright 10.10.2012 by Bochkanov Sergey
26465 : *************************************************************************/
26466 0 : void snnlssolve(snnlssolver* s,
26467 : /* Real */ ae_vector* x,
26468 : ae_state *_state)
26469 : {
26470 : ae_int_t i;
26471 : ae_int_t ns;
26472 : ae_int_t nd;
26473 : ae_int_t nr;
26474 : ae_bool wasactivation;
26475 : double lambdav;
26476 : double v0;
26477 : double v1;
26478 : double v;
26479 : ae_int_t outerits;
26480 : ae_int_t innerits;
26481 : ae_int_t maxouterits;
26482 : double xtol;
26483 : double kicklength;
26484 : ae_bool kickneeded;
26485 : double f0;
26486 : double f1;
26487 : double dnrm;
26488 : ae_int_t actidx;
26489 : double stp;
26490 : double stpmax;
26491 :
26492 :
26493 :
26494 : /*
26495 : * Prepare
26496 : */
26497 0 : ns = s->ns;
26498 0 : nd = s->nd;
26499 0 : nr = s->nr;
26500 0 : s->debugflops = 0.0;
26501 :
26502 : /*
26503 : * Handle special cases:
26504 : * * NS+ND=0
26505 : * * ND=0
26506 : */
26507 0 : if( ns+nd==0 )
26508 : {
26509 0 : return;
26510 : }
26511 0 : if( nd==0 )
26512 : {
26513 0 : rvectorsetlengthatleast(x, ns, _state);
26514 0 : for(i=0; i<=ns-1; i++)
26515 : {
26516 0 : x->ptr.p_double[i] = s->b.ptr.p_double[i];
26517 0 : if( s->nnc.ptr.p_bool[i] )
26518 : {
26519 0 : x->ptr.p_double[i] = ae_maxreal(x->ptr.p_double[i], 0.0, _state);
26520 : }
26521 : }
26522 0 : return;
26523 : }
26524 :
26525 : /*
26526 : * Main cycle of BLEIC-SNNLS algorithm.
26527 : * Below we assume that ND>0.
26528 : */
26529 0 : rvectorsetlengthatleast(x, ns+nd, _state);
26530 0 : rvectorsetlengthatleast(&s->xn, ns+nd, _state);
26531 0 : rvectorsetlengthatleast(&s->xp, ns+nd, _state);
26532 0 : rvectorsetlengthatleast(&s->g, ns+nd, _state);
26533 0 : rvectorsetlengthatleast(&s->d, ns+nd, _state);
26534 0 : rvectorsetlengthatleast(&s->r, nr, _state);
26535 0 : rvectorsetlengthatleast(&s->diagaa, nd, _state);
26536 0 : rvectorsetlengthatleast(&s->regdiag, ns+nd, _state);
26537 0 : rvectorsetlengthatleast(&s->dx, ns+nd, _state);
26538 0 : for(i=0; i<=ns+nd-1; i++)
26539 : {
26540 0 : x->ptr.p_double[i] = 0.0;
26541 0 : s->regdiag.ptr.p_double[i] = 1.0;
26542 : }
26543 0 : lambdav = 1.0E6*ae_machineepsilon;
26544 0 : maxouterits = 10;
26545 0 : outerits = 0;
26546 0 : innerits = 0;
26547 0 : xtol = 1.0E3*ae_machineepsilon;
26548 0 : kicklength = ae_sqrt(ae_minrealnumber, _state);
26549 : for(;;)
26550 : {
26551 :
26552 : /*
26553 : * Initial check for correctness of X
26554 : */
26555 0 : for(i=0; i<=ns+nd-1; i++)
26556 : {
26557 0 : ae_assert(!s->nnc.ptr.p_bool[i]||ae_fp_greater_eq(x->ptr.p_double[i],(double)(0)), "SNNLS: integrity check failed", _state);
26558 : }
26559 :
26560 : /*
26561 : * Calculate gradient G and constrained descent direction D
26562 : */
26563 0 : snnls_funcgradu(s, x, &s->r, &s->g, &f0, _state);
26564 0 : for(i=0; i<=ns+nd-1; i++)
26565 : {
26566 0 : if( (s->nnc.ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],(double)(0)))&&ae_fp_greater(s->g.ptr.p_double[i],(double)(0)) )
26567 : {
26568 0 : s->d.ptr.p_double[i] = 0.0;
26569 : }
26570 : else
26571 : {
26572 0 : s->d.ptr.p_double[i] = -s->g.ptr.p_double[i];
26573 : }
26574 : }
26575 :
26576 : /*
26577 : * Decide whether we need "kick" stage: special stage
26578 : * that moves us away from boundary constraints which are
26579 : * not strictly active (i.e. such constraints that x[i]=0.0 and d[i]>0).
26580 : *
26581 : * If we need kick stage, we make a kick - and restart iteration.
26582 : * If not, after this block we can rely on the fact that
26583 : * for all x[i]=0.0 we have d[i]=0.0
26584 : *
26585 : * NOTE: we do not increase outer iterations counter here
26586 : */
26587 0 : kickneeded = ae_false;
26588 0 : for(i=0; i<=ns+nd-1; i++)
26589 : {
26590 0 : if( (s->nnc.ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],0.0))&&ae_fp_greater(s->d.ptr.p_double[i],0.0) )
26591 : {
26592 0 : kickneeded = ae_true;
26593 : }
26594 : }
26595 0 : if( kickneeded )
26596 : {
26597 :
26598 : /*
26599 : * Perform kick.
26600 : * Restart.
26601 : * Do not increase iterations counter.
26602 : */
26603 0 : for(i=0; i<=ns+nd-1; i++)
26604 : {
26605 0 : if( ae_fp_eq(x->ptr.p_double[i],0.0)&&ae_fp_greater(s->d.ptr.p_double[i],0.0) )
26606 : {
26607 0 : x->ptr.p_double[i] = x->ptr.p_double[i]+kicklength;
26608 : }
26609 : }
26610 0 : continue;
26611 : }
26612 :
26613 : /*
26614 : * Newton phase
26615 : * Reduce problem to constrained triangular form and perform Newton
26616 : * steps with quick activation of constrants (triangular form is
26617 : * updated in order to handle changed constraints).
26618 : */
26619 0 : for(i=0; i<=ns+nd-1; i++)
26620 : {
26621 0 : s->xp.ptr.p_double[i] = x->ptr.p_double[i];
26622 : }
26623 0 : snnls_trdprepare(s, x, &s->regdiag, lambdav, &s->trdd, &s->trda, &s->tmp0, &s->tmp1, &s->tmp2, &s->tmplq, _state);
26624 : for(;;)
26625 : {
26626 :
26627 : /*
26628 : * Skip if debug limit on inner iterations count is turned on.
26629 : */
26630 0 : if( s->debugmaxinnerits>0&&innerits>=s->debugmaxinnerits )
26631 : {
26632 0 : break;
26633 : }
26634 :
26635 : /*
26636 : * Prepare step vector.
26637 : */
26638 0 : snnls_funcgradu(s, x, &s->r, &s->g, &f0, _state);
26639 0 : for(i=0; i<=ns+nd-1; i++)
26640 : {
26641 0 : s->d.ptr.p_double[i] = -s->g.ptr.p_double[i];
26642 0 : if( s->nnc.ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],0.0) )
26643 : {
26644 0 : s->d.ptr.p_double[i] = 0.0;
26645 : }
26646 : }
26647 0 : snnls_trdsolve(&s->trdd, &s->trda, ns, nd, &s->d, _state);
26648 :
26649 : /*
26650 : * Perform unconstrained trial step and compare function values.
26651 : */
26652 0 : for(i=0; i<=ns+nd-1; i++)
26653 : {
26654 0 : s->xn.ptr.p_double[i] = x->ptr.p_double[i]+s->d.ptr.p_double[i];
26655 : }
26656 0 : snnls_func(s, &s->xn, &f1, _state);
26657 0 : if( ae_fp_greater_eq(f1,f0) )
26658 : {
26659 0 : break;
26660 : }
26661 :
26662 : /*
26663 : * Calculate length of D, maximum step and component which is
26664 : * activated by this step. Break if D is exactly zero.
26665 : */
26666 0 : dnrm = 0.0;
26667 0 : for(i=0; i<=ns+nd-1; i++)
26668 : {
26669 0 : dnrm = dnrm+ae_sqr(s->d.ptr.p_double[i], _state);
26670 : }
26671 0 : dnrm = ae_sqrt(dnrm, _state);
26672 0 : actidx = -1;
26673 0 : stpmax = 1.0E50;
26674 0 : for(i=0; i<=ns+nd-1; i++)
26675 : {
26676 0 : if( s->nnc.ptr.p_bool[i]&&ae_fp_less(s->d.ptr.p_double[i],0.0) )
26677 : {
26678 0 : v = stpmax;
26679 0 : stpmax = safeminposrv(x->ptr.p_double[i], -s->d.ptr.p_double[i], stpmax, _state);
26680 0 : if( ae_fp_less(stpmax,v) )
26681 : {
26682 0 : actidx = i;
26683 : }
26684 : }
26685 : }
26686 0 : if( ae_fp_eq(dnrm,0.0) )
26687 : {
26688 0 : break;
26689 : }
26690 :
26691 : /*
26692 : * Perform constrained step and update X
26693 : * and triangular model.
26694 : */
26695 0 : stp = ae_minreal(1.0, stpmax, _state);
26696 0 : for(i=0; i<=ns+nd-1; i++)
26697 : {
26698 0 : v = x->ptr.p_double[i]+stp*s->d.ptr.p_double[i];
26699 0 : if( s->nnc.ptr.p_bool[i] )
26700 : {
26701 0 : v = ae_maxreal(v, 0.0, _state);
26702 : }
26703 0 : s->xn.ptr.p_double[i] = v;
26704 : }
26705 0 : if( ae_fp_eq(stp,stpmax)&&actidx>=0 )
26706 : {
26707 0 : s->xn.ptr.p_double[actidx] = 0.0;
26708 : }
26709 0 : wasactivation = ae_false;
26710 0 : for(i=0; i<=ns+nd-1; i++)
26711 : {
26712 0 : if( ae_fp_eq(s->xn.ptr.p_double[i],0.0)&&ae_fp_neq(x->ptr.p_double[i],0.0) )
26713 : {
26714 0 : wasactivation = ae_true;
26715 0 : snnls_trdfixvariable(&s->trdd, &s->trda, ns, nd, i, &s->tmpcholesky, _state);
26716 : }
26717 : }
26718 0 : for(i=0; i<=ns+nd-1; i++)
26719 : {
26720 0 : x->ptr.p_double[i] = s->xn.ptr.p_double[i];
26721 : }
26722 :
26723 : /*
26724 : * Increment iterations counter.
26725 : * Terminate if no constraint was activated.
26726 : */
26727 0 : inc(&innerits, _state);
26728 0 : if( !wasactivation )
26729 : {
26730 0 : break;
26731 : }
26732 : }
26733 :
26734 : /*
26735 : * Update outer iterations counter.
26736 : *
26737 : * Break if necessary:
26738 : * * maximum number of outer iterations performed
26739 : * * relative change in X is small enough
26740 : */
26741 0 : inc(&outerits, _state);
26742 0 : if( outerits>=maxouterits )
26743 : {
26744 0 : break;
26745 : }
26746 0 : v = (double)(0);
26747 0 : for(i=0; i<=ns+nd-1; i++)
26748 : {
26749 0 : v0 = ae_fabs(s->xp.ptr.p_double[i], _state);
26750 0 : v1 = ae_fabs(x->ptr.p_double[i], _state);
26751 0 : if( ae_fp_neq(v0,(double)(0))||ae_fp_neq(v1,(double)(0)) )
26752 : {
26753 0 : v = ae_maxreal(v, ae_fabs(x->ptr.p_double[i]-s->xp.ptr.p_double[i], _state)/ae_maxreal(v0, v1, _state), _state);
26754 : }
26755 : }
26756 0 : if( ae_fp_less_eq(v,xtol) )
26757 : {
26758 0 : break;
26759 : }
26760 : }
26761 : }
26762 :
26763 :
26764 : /*************************************************************************
26765 : This function calculates:
26766 : * residual vector R = A*x-b
26767 : * unconstrained gradient vector G
26768 : * function value F = 0.5*|R|^2
26769 :
26770 : R and G must have at least N elements.
26771 :
26772 : -- ALGLIB --
26773 : Copyright 15.07.2015 by Bochkanov Sergey
26774 : *************************************************************************/
26775 0 : static void snnls_funcgradu(snnlssolver* s,
26776 : /* Real */ ae_vector* x,
26777 : /* Real */ ae_vector* r,
26778 : /* Real */ ae_vector* g,
26779 : double* f,
26780 : ae_state *_state)
26781 : {
26782 : ae_int_t i;
26783 : ae_int_t nr;
26784 : ae_int_t nd;
26785 : ae_int_t ns;
26786 : double v;
26787 :
26788 0 : *f = 0;
26789 :
26790 0 : nr = s->nr;
26791 0 : nd = s->nd;
26792 0 : ns = s->ns;
26793 0 : *f = 0.0;
26794 0 : for(i=0; i<=nr-1; i++)
26795 : {
26796 0 : v = ae_v_dotproduct(&s->densea.ptr.pp_double[i][0], 1, &x->ptr.p_double[ns], 1, ae_v_len(0,nd-1));
26797 0 : if( i<ns )
26798 : {
26799 0 : v = v+x->ptr.p_double[i];
26800 : }
26801 0 : v = v-s->b.ptr.p_double[i];
26802 0 : r->ptr.p_double[i] = v;
26803 0 : *f = *f+0.5*v*v;
26804 : }
26805 0 : for(i=0; i<=ns-1; i++)
26806 : {
26807 0 : g->ptr.p_double[i] = r->ptr.p_double[i];
26808 : }
26809 0 : for(i=ns; i<=ns+nd-1; i++)
26810 : {
26811 0 : g->ptr.p_double[i] = 0.0;
26812 : }
26813 0 : for(i=0; i<=nr-1; i++)
26814 : {
26815 0 : v = r->ptr.p_double[i];
26816 0 : ae_v_addd(&g->ptr.p_double[ns], 1, &s->densea.ptr.pp_double[i][0], 1, ae_v_len(ns,ns+nd-1), v);
26817 : }
26818 0 : }
26819 :
26820 :
26821 : /*************************************************************************
26822 : This function calculates function value F = 0.5*|R|^2 at X.
26823 :
26824 : -- ALGLIB --
26825 : Copyright 15.07.2015 by Bochkanov Sergey
26826 : *************************************************************************/
26827 0 : static void snnls_func(snnlssolver* s,
26828 : /* Real */ ae_vector* x,
26829 : double* f,
26830 : ae_state *_state)
26831 : {
26832 : ae_int_t i;
26833 : ae_int_t nr;
26834 : ae_int_t nd;
26835 : ae_int_t ns;
26836 : double v;
26837 :
26838 0 : *f = 0;
26839 :
26840 0 : nr = s->nr;
26841 0 : nd = s->nd;
26842 0 : ns = s->ns;
26843 0 : *f = 0.0;
26844 0 : for(i=0; i<=nr-1; i++)
26845 : {
26846 0 : v = ae_v_dotproduct(&s->densea.ptr.pp_double[i][0], 1, &x->ptr.p_double[ns], 1, ae_v_len(0,nd-1));
26847 0 : if( i<ns )
26848 : {
26849 0 : v = v+x->ptr.p_double[i];
26850 : }
26851 0 : v = v-s->b.ptr.p_double[i];
26852 0 : *f = *f+0.5*v*v;
26853 : }
26854 0 : }
26855 :
26856 :
26857 0 : static void snnls_trdprepare(snnlssolver* s,
26858 : /* Real */ ae_vector* x,
26859 : /* Real */ ae_vector* diag,
26860 : double lambdav,
26861 : /* Real */ ae_vector* trdd,
26862 : /* Real */ ae_matrix* trda,
26863 : /* Real */ ae_vector* tmp0,
26864 : /* Real */ ae_vector* tmp1,
26865 : /* Real */ ae_vector* tmp2,
26866 : /* Real */ ae_matrix* tmplq,
26867 : ae_state *_state)
26868 : {
26869 : ae_int_t i;
26870 : ae_int_t j;
26871 : ae_int_t ns;
26872 : ae_int_t nd;
26873 : ae_int_t nr;
26874 : double v;
26875 : double cs;
26876 : double sn;
26877 : double r;
26878 :
26879 :
26880 :
26881 : /*
26882 : * Prepare
26883 : */
26884 0 : ns = s->ns;
26885 0 : nd = s->nd;
26886 0 : nr = s->nr;
26887 :
26888 : /*
26889 : * Triangular reduction
26890 : */
26891 0 : rvectorsetlengthatleast(trdd, ns, _state);
26892 0 : rmatrixsetlengthatleast(trda, ns+nd, nd, _state);
26893 0 : rmatrixsetlengthatleast(tmplq, nd, nr+nd, _state);
26894 0 : for(i=0; i<=ns-1; i++)
26895 : {
26896 :
26897 : /*
26898 : * Apply rotation to I-th row and corresponding row of
26899 : * regularizer. Here V is diagonal element of I-th row,
26900 : * which is set to 1.0 or 0.0 depending on variable
26901 : * status (constrained or not).
26902 : */
26903 0 : v = 1.0;
26904 0 : if( s->nnc.ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],0.0) )
26905 : {
26906 0 : v = 0.0;
26907 : }
26908 0 : generaterotation(v, lambdav, &cs, &sn, &r, _state);
26909 0 : trdd->ptr.p_double[i] = cs*v+sn*lambdav;
26910 0 : for(j=0; j<=nd-1; j++)
26911 : {
26912 0 : v = s->densea.ptr.pp_double[i][j];
26913 0 : trda->ptr.pp_double[i][j] = cs*v;
26914 0 : tmplq->ptr.pp_double[j][i] = -sn*v;
26915 : }
26916 : }
26917 0 : for(j=0; j<=nd-1; j++)
26918 : {
26919 0 : for(i=ns; i<=nr-1; i++)
26920 : {
26921 0 : tmplq->ptr.pp_double[j][i] = s->densea.ptr.pp_double[i][j];
26922 : }
26923 : }
26924 0 : for(j=0; j<=nd-1; j++)
26925 : {
26926 0 : if( s->nnc.ptr.p_bool[ns+j]&&ae_fp_eq(x->ptr.p_double[ns+j],0.0) )
26927 : {
26928 :
26929 : /*
26930 : * Variable is constrained, entire row is set to zero.
26931 : */
26932 0 : for(i=0; i<=nr-1; i++)
26933 : {
26934 0 : tmplq->ptr.pp_double[j][i] = 0.0;
26935 : }
26936 0 : for(i=0; i<=ns-1; i++)
26937 : {
26938 0 : trda->ptr.pp_double[i][j] = 0.0;
26939 : }
26940 : }
26941 : }
26942 0 : for(i=0; i<=nd-1; i++)
26943 : {
26944 0 : for(j=0; j<=nd-1; j++)
26945 : {
26946 0 : tmplq->ptr.pp_double[j][nr+i] = 0.0;
26947 : }
26948 0 : tmplq->ptr.pp_double[i][nr+i] = lambdav*diag->ptr.p_double[i];
26949 : }
26950 0 : rvectorsetlengthatleast(tmp0, nr+nd+1, _state);
26951 0 : rvectorsetlengthatleast(tmp1, nr+nd+1, _state);
26952 0 : rvectorsetlengthatleast(tmp2, nr+nd+1, _state);
26953 0 : rmatrixlqbasecase(tmplq, nd, nr+nd, tmp0, tmp1, tmp2, _state);
26954 0 : for(i=0; i<=nd-1; i++)
26955 : {
26956 0 : if( ae_fp_less(tmplq->ptr.pp_double[i][i],0.0) )
26957 : {
26958 0 : for(j=i; j<=nd-1; j++)
26959 : {
26960 0 : tmplq->ptr.pp_double[j][i] = -tmplq->ptr.pp_double[j][i];
26961 : }
26962 : }
26963 : }
26964 0 : for(i=0; i<=nd-1; i++)
26965 : {
26966 0 : for(j=0; j<=i; j++)
26967 : {
26968 0 : trda->ptr.pp_double[ns+j][i] = tmplq->ptr.pp_double[i][j];
26969 : }
26970 : }
26971 0 : }
26972 :
26973 :
26974 0 : static void snnls_trdsolve(/* Real */ ae_vector* trdd,
26975 : /* Real */ ae_matrix* trda,
26976 : ae_int_t ns,
26977 : ae_int_t nd,
26978 : /* Real */ ae_vector* d,
26979 : ae_state *_state)
26980 : {
26981 : ae_int_t i;
26982 : ae_int_t j;
26983 : double v;
26984 :
26985 :
26986 :
26987 : /*
26988 : * Solve U'*y=d first.
26989 : *
26990 : * This section includes two parts:
26991 : * * solve diagonal part of U'
26992 : * * solve dense part of U'
26993 : */
26994 0 : for(i=0; i<=ns-1; i++)
26995 : {
26996 0 : d->ptr.p_double[i] = d->ptr.p_double[i]/trdd->ptr.p_double[i];
26997 0 : v = d->ptr.p_double[i];
26998 0 : for(j=0; j<=nd-1; j++)
26999 : {
27000 0 : d->ptr.p_double[ns+j] = d->ptr.p_double[ns+j]-v*trda->ptr.pp_double[i][j];
27001 : }
27002 : }
27003 0 : for(i=0; i<=nd-1; i++)
27004 : {
27005 0 : d->ptr.p_double[ns+i] = d->ptr.p_double[ns+i]/trda->ptr.pp_double[ns+i][i];
27006 0 : v = d->ptr.p_double[ns+i];
27007 0 : for(j=i+1; j<=nd-1; j++)
27008 : {
27009 0 : d->ptr.p_double[ns+j] = d->ptr.p_double[ns+j]-v*trda->ptr.pp_double[ns+i][j];
27010 : }
27011 : }
27012 :
27013 : /*
27014 : * Solve U*x=y then.
27015 : *
27016 : * This section includes two parts:
27017 : * * solve trailing triangular part of U
27018 : * * solve combination of diagonal and dense parts of U
27019 : */
27020 0 : for(i=nd-1; i>=0; i--)
27021 : {
27022 0 : v = 0.0;
27023 0 : for(j=i+1; j<=nd-1; j++)
27024 : {
27025 0 : v = v+trda->ptr.pp_double[ns+i][j]*d->ptr.p_double[ns+j];
27026 : }
27027 0 : d->ptr.p_double[ns+i] = (d->ptr.p_double[ns+i]-v)/trda->ptr.pp_double[ns+i][i];
27028 : }
27029 0 : for(i=ns-1; i>=0; i--)
27030 : {
27031 0 : v = 0.0;
27032 0 : for(j=0; j<=nd-1; j++)
27033 : {
27034 0 : v = v+trda->ptr.pp_double[i][j]*d->ptr.p_double[ns+j];
27035 : }
27036 0 : d->ptr.p_double[i] = (d->ptr.p_double[i]-v)/trdd->ptr.p_double[i];
27037 : }
27038 0 : }
27039 :
27040 :
27041 0 : static void snnls_trdfixvariable(/* Real */ ae_vector* trdd,
27042 : /* Real */ ae_matrix* trda,
27043 : ae_int_t ns,
27044 : ae_int_t nd,
27045 : ae_int_t idx,
27046 : /* Real */ ae_vector* tmp,
27047 : ae_state *_state)
27048 : {
27049 : ae_int_t i;
27050 : ae_int_t j;
27051 : ae_int_t k;
27052 : double cs;
27053 : double sn;
27054 : double r;
27055 : double v;
27056 : double vv;
27057 :
27058 :
27059 0 : ae_assert(ns>=0, "TRDFixVariable: integrity error", _state);
27060 0 : ae_assert(nd>=0, "TRDFixVariable: integrity error", _state);
27061 0 : ae_assert(ns+nd>0, "TRDFixVariable: integrity error", _state);
27062 0 : ae_assert(idx>=0, "TRDFixVariable: integrity error", _state);
27063 0 : ae_assert(idx<ns+nd, "TRDFixVariable: integrity error", _state);
27064 0 : rvectorsetlengthatleast(tmp, nd, _state);
27065 :
27066 : /*
27067 : * Depending on variable index, two situations are possible
27068 : */
27069 0 : if( idx<ns )
27070 : {
27071 :
27072 : /*
27073 : * We fix variable in the diagonal part of the model. It means
27074 : * that prior to fixing we have:
27075 : *
27076 : * ( | )
27077 : * ( D | )
27078 : * ( | )
27079 : * (-----| A )
27080 : * ( |0 )
27081 : * ( |00 )
27082 : * ( |000 )
27083 : * ( |0000 )
27084 : * ( |00000)
27085 : *
27086 : * then we replace idx-th column by zeros:
27087 : *
27088 : * (D 0 | )
27089 : * ( 0 | )
27090 : * ( 0 D| )
27091 : * (-----| A )
27092 : * ( | )
27093 : * ( | )
27094 : * ( | )
27095 : *
27096 : * and append row with unit element to bottom, in order to
27097 : * regularize problem
27098 : *
27099 : * (D 0 | )
27100 : * ( 0 | )
27101 : * ( 0 D| )
27102 : * (-----| A )
27103 : * ( | )
27104 : * ( | )
27105 : * ( | )
27106 : * (00100|00000) <- appended
27107 : *
27108 : * and then we nullify this row by applying rotations:
27109 : *
27110 : * (D 0 | )
27111 : * ( 0 | ) <- first rotation is applied here
27112 : * ( 0 D| )
27113 : * (-----| A ) <- subsequent rotations are applied to this row and rows below
27114 : * ( | )
27115 : * ( | )
27116 : * ( | )
27117 : * ( 0 | 0 ) <- as result, row becomes zero
27118 : *
27119 : * and triangular structure is preserved
27120 : */
27121 0 : if( nd==0 )
27122 : {
27123 :
27124 : /*
27125 : * Quick exit for empty dense part
27126 : */
27127 0 : trdd->ptr.p_double[idx] = 1.0;
27128 0 : return;
27129 : }
27130 0 : for(j=0; j<=nd-1; j++)
27131 : {
27132 :
27133 : /*
27134 : * Apply first rotation
27135 : */
27136 0 : tmp->ptr.p_double[j] = trda->ptr.pp_double[idx][j];
27137 0 : trda->ptr.pp_double[idx][j] = 0.0;
27138 : }
27139 0 : trdd->ptr.p_double[idx] = 1.0;
27140 0 : for(i=0; i<=nd-1; i++)
27141 : {
27142 0 : if( ae_fp_neq(tmp->ptr.p_double[i],(double)(0)) )
27143 : {
27144 :
27145 : /*
27146 : * Apply subsequent rotations with bottom triangular part of A
27147 : */
27148 0 : generaterotation(trda->ptr.pp_double[ns+i][i], tmp->ptr.p_double[i], &cs, &sn, &r, _state);
27149 0 : for(j=i; j<=nd-1; j++)
27150 : {
27151 0 : v = trda->ptr.pp_double[ns+i][j];
27152 0 : vv = tmp->ptr.p_double[j];
27153 0 : trda->ptr.pp_double[ns+i][j] = v*cs+vv*sn;
27154 0 : tmp->ptr.p_double[j] = vv*cs-v*sn;
27155 : }
27156 : }
27157 : }
27158 : }
27159 : else
27160 : {
27161 :
27162 : /*
27163 : * We fix variable in the dense part of the model. It means
27164 : * that prior to fixing we have:
27165 : *
27166 : * ( | )
27167 : * ( D | )
27168 : * ( | )
27169 : * (-----| A )
27170 : * ( |0 )
27171 : * ( |00 )
27172 : * ( |000 )
27173 : * ( |0000 )
27174 : * ( |00000)
27175 : *
27176 : * then we replace idx-th column by zeros:
27177 : *
27178 : * ( | 0 )
27179 : * ( D | 0 )
27180 : * ( | 0 )
27181 : * (-----|A 0 A)
27182 : * ( | 0 )
27183 : * ( | 0 )
27184 : * ( | 0 )
27185 : *
27186 : * and append row with unit element to bottom, in order to
27187 : * regularize problem
27188 : *
27189 : * ( | 0 )
27190 : * ( D | 0 )
27191 : * ( | 0 )
27192 : * (-----|A 0 A)
27193 : * ( | 0 )
27194 : * ( | 0 )
27195 : * ( | 0 )
27196 : * (00000|00100) <- appended
27197 : *
27198 : * and then we nullify this row by applying rotations:
27199 : *
27200 : * (D 0 | )
27201 : * ( 0 | )
27202 : * ( 0 D| )
27203 : * (-----| A )
27204 : * ( | )
27205 : * ( | ) <- first rotation is applied here
27206 : * ( | ) <- subsequent rotations are applied to rows below
27207 : * ( 0 | 0 ) <- as result, row becomes zero
27208 : *
27209 : * and triangular structure is preserved.
27210 : */
27211 0 : k = idx-ns;
27212 0 : for(i=0; i<=ns+nd-1; i++)
27213 : {
27214 0 : trda->ptr.pp_double[i][k] = 0.0;
27215 : }
27216 0 : for(j=k+1; j<=nd-1; j++)
27217 : {
27218 :
27219 : /*
27220 : * Apply first rotation
27221 : */
27222 0 : tmp->ptr.p_double[j] = trda->ptr.pp_double[idx][j];
27223 0 : trda->ptr.pp_double[idx][j] = 0.0;
27224 : }
27225 0 : trda->ptr.pp_double[idx][k] = 1.0;
27226 0 : for(i=k+1; i<=nd-1; i++)
27227 : {
27228 0 : if( ae_fp_neq(tmp->ptr.p_double[i],(double)(0)) )
27229 : {
27230 :
27231 : /*
27232 : * Apply subsequent rotations with bottom triangular part of A
27233 : */
27234 0 : generaterotation(trda->ptr.pp_double[ns+i][i], tmp->ptr.p_double[i], &cs, &sn, &r, _state);
27235 0 : for(j=i; j<=nd-1; j++)
27236 : {
27237 0 : v = trda->ptr.pp_double[ns+i][j];
27238 0 : vv = tmp->ptr.p_double[j];
27239 0 : trda->ptr.pp_double[ns+i][j] = v*cs+vv*sn;
27240 0 : tmp->ptr.p_double[j] = vv*cs-v*sn;
27241 : }
27242 : }
27243 : }
27244 : }
27245 : }
27246 :
27247 :
27248 0 : void _snnlssolver_init(void* _p, ae_state *_state, ae_bool make_automatic)
27249 : {
27250 0 : snnlssolver *p = (snnlssolver*)_p;
27251 0 : ae_touch_ptr((void*)p);
27252 0 : ae_matrix_init(&p->densea, 0, 0, DT_REAL, _state, make_automatic);
27253 0 : ae_vector_init(&p->b, 0, DT_REAL, _state, make_automatic);
27254 0 : ae_vector_init(&p->nnc, 0, DT_BOOL, _state, make_automatic);
27255 0 : ae_vector_init(&p->xn, 0, DT_REAL, _state, make_automatic);
27256 0 : ae_vector_init(&p->xp, 0, DT_REAL, _state, make_automatic);
27257 0 : ae_matrix_init(&p->tmpca, 0, 0, DT_REAL, _state, make_automatic);
27258 0 : ae_matrix_init(&p->tmplq, 0, 0, DT_REAL, _state, make_automatic);
27259 0 : ae_matrix_init(&p->trda, 0, 0, DT_REAL, _state, make_automatic);
27260 0 : ae_vector_init(&p->trdd, 0, DT_REAL, _state, make_automatic);
27261 0 : ae_vector_init(&p->crb, 0, DT_REAL, _state, make_automatic);
27262 0 : ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic);
27263 0 : ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic);
27264 0 : ae_vector_init(&p->dx, 0, DT_REAL, _state, make_automatic);
27265 0 : ae_vector_init(&p->diagaa, 0, DT_REAL, _state, make_automatic);
27266 0 : ae_vector_init(&p->cb, 0, DT_REAL, _state, make_automatic);
27267 0 : ae_vector_init(&p->cx, 0, DT_REAL, _state, make_automatic);
27268 0 : ae_vector_init(&p->cborg, 0, DT_REAL, _state, make_automatic);
27269 0 : ae_vector_init(&p->tmpcholesky, 0, DT_REAL, _state, make_automatic);
27270 0 : ae_vector_init(&p->r, 0, DT_REAL, _state, make_automatic);
27271 0 : ae_vector_init(&p->regdiag, 0, DT_REAL, _state, make_automatic);
27272 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
27273 0 : ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic);
27274 0 : ae_vector_init(&p->tmp2, 0, DT_REAL, _state, make_automatic);
27275 0 : ae_vector_init(&p->rdtmprowmap, 0, DT_INT, _state, make_automatic);
27276 0 : }
27277 :
27278 :
27279 0 : void _snnlssolver_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
27280 : {
27281 0 : snnlssolver *dst = (snnlssolver*)_dst;
27282 0 : snnlssolver *src = (snnlssolver*)_src;
27283 0 : dst->ns = src->ns;
27284 0 : dst->nd = src->nd;
27285 0 : dst->nr = src->nr;
27286 0 : ae_matrix_init_copy(&dst->densea, &src->densea, _state, make_automatic);
27287 0 : ae_vector_init_copy(&dst->b, &src->b, _state, make_automatic);
27288 0 : ae_vector_init_copy(&dst->nnc, &src->nnc, _state, make_automatic);
27289 0 : dst->debugflops = src->debugflops;
27290 0 : dst->debugmaxinnerits = src->debugmaxinnerits;
27291 0 : ae_vector_init_copy(&dst->xn, &src->xn, _state, make_automatic);
27292 0 : ae_vector_init_copy(&dst->xp, &src->xp, _state, make_automatic);
27293 0 : ae_matrix_init_copy(&dst->tmpca, &src->tmpca, _state, make_automatic);
27294 0 : ae_matrix_init_copy(&dst->tmplq, &src->tmplq, _state, make_automatic);
27295 0 : ae_matrix_init_copy(&dst->trda, &src->trda, _state, make_automatic);
27296 0 : ae_vector_init_copy(&dst->trdd, &src->trdd, _state, make_automatic);
27297 0 : ae_vector_init_copy(&dst->crb, &src->crb, _state, make_automatic);
27298 0 : ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic);
27299 0 : ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic);
27300 0 : ae_vector_init_copy(&dst->dx, &src->dx, _state, make_automatic);
27301 0 : ae_vector_init_copy(&dst->diagaa, &src->diagaa, _state, make_automatic);
27302 0 : ae_vector_init_copy(&dst->cb, &src->cb, _state, make_automatic);
27303 0 : ae_vector_init_copy(&dst->cx, &src->cx, _state, make_automatic);
27304 0 : ae_vector_init_copy(&dst->cborg, &src->cborg, _state, make_automatic);
27305 0 : ae_vector_init_copy(&dst->tmpcholesky, &src->tmpcholesky, _state, make_automatic);
27306 0 : ae_vector_init_copy(&dst->r, &src->r, _state, make_automatic);
27307 0 : ae_vector_init_copy(&dst->regdiag, &src->regdiag, _state, make_automatic);
27308 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
27309 0 : ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic);
27310 0 : ae_vector_init_copy(&dst->tmp2, &src->tmp2, _state, make_automatic);
27311 0 : ae_vector_init_copy(&dst->rdtmprowmap, &src->rdtmprowmap, _state, make_automatic);
27312 0 : }
27313 :
27314 :
27315 0 : void _snnlssolver_clear(void* _p)
27316 : {
27317 0 : snnlssolver *p = (snnlssolver*)_p;
27318 0 : ae_touch_ptr((void*)p);
27319 0 : ae_matrix_clear(&p->densea);
27320 0 : ae_vector_clear(&p->b);
27321 0 : ae_vector_clear(&p->nnc);
27322 0 : ae_vector_clear(&p->xn);
27323 0 : ae_vector_clear(&p->xp);
27324 0 : ae_matrix_clear(&p->tmpca);
27325 0 : ae_matrix_clear(&p->tmplq);
27326 0 : ae_matrix_clear(&p->trda);
27327 0 : ae_vector_clear(&p->trdd);
27328 0 : ae_vector_clear(&p->crb);
27329 0 : ae_vector_clear(&p->g);
27330 0 : ae_vector_clear(&p->d);
27331 0 : ae_vector_clear(&p->dx);
27332 0 : ae_vector_clear(&p->diagaa);
27333 0 : ae_vector_clear(&p->cb);
27334 0 : ae_vector_clear(&p->cx);
27335 0 : ae_vector_clear(&p->cborg);
27336 0 : ae_vector_clear(&p->tmpcholesky);
27337 0 : ae_vector_clear(&p->r);
27338 0 : ae_vector_clear(&p->regdiag);
27339 0 : ae_vector_clear(&p->tmp0);
27340 0 : ae_vector_clear(&p->tmp1);
27341 0 : ae_vector_clear(&p->tmp2);
27342 0 : ae_vector_clear(&p->rdtmprowmap);
27343 0 : }
27344 :
27345 :
27346 0 : void _snnlssolver_destroy(void* _p)
27347 : {
27348 0 : snnlssolver *p = (snnlssolver*)_p;
27349 0 : ae_touch_ptr((void*)p);
27350 0 : ae_matrix_destroy(&p->densea);
27351 0 : ae_vector_destroy(&p->b);
27352 0 : ae_vector_destroy(&p->nnc);
27353 0 : ae_vector_destroy(&p->xn);
27354 0 : ae_vector_destroy(&p->xp);
27355 0 : ae_matrix_destroy(&p->tmpca);
27356 0 : ae_matrix_destroy(&p->tmplq);
27357 0 : ae_matrix_destroy(&p->trda);
27358 0 : ae_vector_destroy(&p->trdd);
27359 0 : ae_vector_destroy(&p->crb);
27360 0 : ae_vector_destroy(&p->g);
27361 0 : ae_vector_destroy(&p->d);
27362 0 : ae_vector_destroy(&p->dx);
27363 0 : ae_vector_destroy(&p->diagaa);
27364 0 : ae_vector_destroy(&p->cb);
27365 0 : ae_vector_destroy(&p->cx);
27366 0 : ae_vector_destroy(&p->cborg);
27367 0 : ae_vector_destroy(&p->tmpcholesky);
27368 0 : ae_vector_destroy(&p->r);
27369 0 : ae_vector_destroy(&p->regdiag);
27370 0 : ae_vector_destroy(&p->tmp0);
27371 0 : ae_vector_destroy(&p->tmp1);
27372 0 : ae_vector_destroy(&p->tmp2);
27373 0 : ae_vector_destroy(&p->rdtmprowmap);
27374 0 : }
27375 :
27376 :
27377 : #endif
27378 : #if defined(AE_COMPILE_SACTIVESETS) || !defined(AE_PARTIAL_BUILD)
27379 :
27380 :
27381 : /*************************************************************************
27382 : This subroutine is used to initialize active set. By default, empty
27383 : N-variable model with no constraints is generated. Previously allocated
27384 : buffer variables are reused as much as possible.
27385 :
27386 : Two use cases for this object are described below.
27387 :
27388 : CASE 1 - STEEPEST DESCENT:
27389 :
27390 : SASInit()
27391 : repeat:
27392 : SASReactivateConstraints()
27393 : SASDescentDirection()
27394 : SASExploreDirection()
27395 : SASMoveTo()
27396 : until convergence
27397 :
27398 : CASE 1 - PRECONDITIONED STEEPEST DESCENT:
27399 :
27400 : SASInit()
27401 : repeat:
27402 : SASReactivateConstraintsPrec()
27403 : SASDescentDirectionPrec()
27404 : SASExploreDirection()
27405 : SASMoveTo()
27406 : until convergence
27407 :
27408 : -- ALGLIB --
27409 : Copyright 21.12.2012 by Bochkanov Sergey
27410 : *************************************************************************/
27411 0 : void sasinit(ae_int_t n, sactiveset* s, ae_state *_state)
27412 : {
27413 : ae_int_t i;
27414 :
27415 :
27416 0 : s->n = n;
27417 0 : s->algostate = 0;
27418 :
27419 : /*
27420 : * Constraints
27421 : */
27422 0 : s->constraintschanged = ae_true;
27423 0 : s->nec = 0;
27424 0 : s->nic = 0;
27425 0 : rvectorsetlengthatleast(&s->bndl, n, _state);
27426 0 : bvectorsetlengthatleast(&s->hasbndl, n, _state);
27427 0 : rvectorsetlengthatleast(&s->bndu, n, _state);
27428 0 : bvectorsetlengthatleast(&s->hasbndu, n, _state);
27429 0 : for(i=0; i<=n-1; i++)
27430 : {
27431 0 : s->bndl.ptr.p_double[i] = _state->v_neginf;
27432 0 : s->bndu.ptr.p_double[i] = _state->v_posinf;
27433 0 : s->hasbndl.ptr.p_bool[i] = ae_false;
27434 0 : s->hasbndu.ptr.p_bool[i] = ae_false;
27435 : }
27436 :
27437 : /*
27438 : * current point, scale
27439 : */
27440 0 : s->hasxc = ae_false;
27441 0 : rvectorsetlengthatleast(&s->xc, n, _state);
27442 0 : rvectorsetlengthatleast(&s->s, n, _state);
27443 0 : rvectorsetlengthatleast(&s->h, n, _state);
27444 0 : for(i=0; i<=n-1; i++)
27445 : {
27446 0 : s->xc.ptr.p_double[i] = 0.0;
27447 0 : s->s.ptr.p_double[i] = 1.0;
27448 0 : s->h.ptr.p_double[i] = 1.0;
27449 : }
27450 :
27451 : /*
27452 : * Other
27453 : */
27454 0 : rvectorsetlengthatleast(&s->unitdiagonal, n, _state);
27455 0 : for(i=0; i<=n-1; i++)
27456 : {
27457 0 : s->unitdiagonal.ptr.p_double[i] = 1.0;
27458 : }
27459 0 : }
27460 :
27461 :
27462 : /*************************************************************************
27463 : This function sets scaling coefficients for SAS object.
27464 :
27465 : ALGLIB optimizers use scaling matrices to test stopping conditions (step
27466 : size and gradient are scaled before comparison with tolerances). Scale of
27467 : the I-th variable is a translation invariant measure of:
27468 : a) "how large" the variable is
27469 : b) how large the step should be to make significant changes in the function
27470 :
27471 : During orthogonalization phase, scale is used to calculate drop tolerances
27472 : (whether vector is significantly non-zero or not).
27473 :
27474 : INPUT PARAMETERS:
27475 : State - structure stores algorithm state
27476 : S - array[N], non-zero scaling coefficients
27477 : S[i] may be negative, sign doesn't matter.
27478 :
27479 : -- ALGLIB --
27480 : Copyright 21.12.2012 by Bochkanov Sergey
27481 : *************************************************************************/
27482 0 : void sassetscale(sactiveset* state,
27483 : /* Real */ ae_vector* s,
27484 : ae_state *_state)
27485 : {
27486 : ae_int_t i;
27487 :
27488 :
27489 0 : ae_assert(state->algostate==0, "SASSetScale: you may change scale only in modification mode", _state);
27490 0 : ae_assert(s->cnt>=state->n, "SASSetScale: Length(S)<N", _state);
27491 0 : for(i=0; i<=state->n-1; i++)
27492 : {
27493 0 : ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "SASSetScale: S contains infinite or NAN elements", _state);
27494 0 : ae_assert(ae_fp_neq(s->ptr.p_double[i],(double)(0)), "SASSetScale: S contains zero elements", _state);
27495 : }
27496 0 : for(i=0; i<=state->n-1; i++)
27497 : {
27498 0 : state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state);
27499 : }
27500 0 : }
27501 :
27502 :
27503 : /*************************************************************************
27504 : Modification of the preconditioner: diagonal of approximate Hessian is
27505 : used.
27506 :
27507 : INPUT PARAMETERS:
27508 : State - structure which stores algorithm state
27509 : D - diagonal of the approximate Hessian, array[0..N-1],
27510 : (if larger, only leading N elements are used).
27511 :
27512 : NOTE 1: D[i] should be positive. Exception will be thrown otherwise.
27513 :
27514 : NOTE 2: you should pass diagonal of approximate Hessian - NOT ITS INVERSE.
27515 :
27516 : -- ALGLIB --
27517 : Copyright 21.12.2012 by Bochkanov Sergey
27518 : *************************************************************************/
27519 0 : void sassetprecdiag(sactiveset* state,
27520 : /* Real */ ae_vector* d,
27521 : ae_state *_state)
27522 : {
27523 : ae_int_t i;
27524 :
27525 :
27526 0 : ae_assert(state->algostate==0, "SASSetPrecDiag: you may change preconditioner only in modification mode", _state);
27527 0 : ae_assert(d->cnt>=state->n, "SASSetPrecDiag: D is too short", _state);
27528 0 : for(i=0; i<=state->n-1; i++)
27529 : {
27530 0 : ae_assert(ae_isfinite(d->ptr.p_double[i], _state), "SASSetPrecDiag: D contains infinite or NAN elements", _state);
27531 0 : ae_assert(ae_fp_greater(d->ptr.p_double[i],(double)(0)), "SASSetPrecDiag: D contains non-positive elements", _state);
27532 : }
27533 0 : for(i=0; i<=state->n-1; i++)
27534 : {
27535 0 : state->h.ptr.p_double[i] = d->ptr.p_double[i];
27536 : }
27537 0 : }
27538 :
27539 :
27540 : /*************************************************************************
27541 : This function sets/changes boundary constraints.
27542 :
27543 : INPUT PARAMETERS:
27544 : State - structure stores algorithm state
27545 : BndL - lower bounds, array[N].
27546 : If some (all) variables are unbounded, you may specify
27547 : very small number or -INF.
27548 : BndU - upper bounds, array[N].
27549 : If some (all) variables are unbounded, you may specify
27550 : very large number or +INF.
27551 :
27552 : NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th
27553 : variable will be "frozen" at X[i]=BndL[i]=BndU[i].
27554 :
27555 : -- ALGLIB --
27556 : Copyright 21.12.2012 by Bochkanov Sergey
27557 : *************************************************************************/
27558 0 : void sassetbc(sactiveset* state,
27559 : /* Real */ ae_vector* bndl,
27560 : /* Real */ ae_vector* bndu,
27561 : ae_state *_state)
27562 : {
27563 : ae_int_t i;
27564 : ae_int_t n;
27565 :
27566 :
27567 0 : ae_assert(state->algostate==0, "SASSetBC: you may change constraints only in modification mode", _state);
27568 0 : n = state->n;
27569 0 : ae_assert(bndl->cnt>=n, "SASSetBC: Length(BndL)<N", _state);
27570 0 : ae_assert(bndu->cnt>=n, "SASSetBC: Length(BndU)<N", _state);
27571 0 : for(i=0; i<=n-1; i++)
27572 : {
27573 0 : 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);
27574 0 : 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);
27575 0 : state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i];
27576 0 : state->hasbndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state);
27577 0 : state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i];
27578 0 : state->hasbndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state);
27579 : }
27580 0 : state->constraintschanged = ae_true;
27581 0 : }
27582 :
27583 :
27584 : /*************************************************************************
27585 : This function sets linear constraints for SAS object.
27586 :
27587 : Linear constraints are inactive by default (after initial creation).
27588 :
27589 : INPUT PARAMETERS:
27590 : State - SAS structure
27591 : C - linear constraints, array[K,N+1].
27592 : Each row of C represents one constraint, either equality
27593 : or inequality (see below):
27594 : * first N elements correspond to coefficients,
27595 : * last element corresponds to the right part.
27596 : All elements of C (including right part) must be finite.
27597 : CT - type of constraints, array[K]:
27598 : * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
27599 : * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
27600 : * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
27601 : K - number of equality/inequality constraints, K>=0
27602 :
27603 : NOTE 1: linear (non-bound) constraints are satisfied only approximately:
27604 : * there always exists some minor violation (about Epsilon in magnitude)
27605 : due to rounding errors
27606 : * numerical differentiation, if used, may lead to function evaluations
27607 : outside of the feasible area, because algorithm does NOT change
27608 : numerical differentiation formula according to linear constraints.
27609 : If you want constraints to be satisfied exactly, try to reformulate your
27610 : problem in such manner that all constraints will become boundary ones
27611 : (this kind of constraints is always satisfied exactly, both in the final
27612 : solution and in all intermediate points).
27613 :
27614 : -- ALGLIB --
27615 : Copyright 28.11.2010 by Bochkanov Sergey
27616 : *************************************************************************/
27617 0 : void sassetlc(sactiveset* state,
27618 : /* Real */ ae_matrix* c,
27619 : /* Integer */ ae_vector* ct,
27620 : ae_int_t k,
27621 : ae_state *_state)
27622 : {
27623 : ae_int_t n;
27624 : ae_int_t i;
27625 :
27626 :
27627 0 : ae_assert(state->algostate==0, "SASSetLC: you may change constraints only in modification mode", _state);
27628 0 : n = state->n;
27629 :
27630 : /*
27631 : * First, check for errors in the inputs
27632 : */
27633 0 : ae_assert(k>=0, "SASSetLC: K<0", _state);
27634 0 : ae_assert(c->cols>=n+1||k==0, "SASSetLC: Cols(C)<N+1", _state);
27635 0 : ae_assert(c->rows>=k, "SASSetLC: Rows(C)<K", _state);
27636 0 : ae_assert(ct->cnt>=k, "SASSetLC: Length(CT)<K", _state);
27637 0 : ae_assert(apservisfinitematrix(c, k, n+1, _state), "SASSetLC: C contains infinite or NaN values!", _state);
27638 :
27639 : /*
27640 : * Handle zero K
27641 : */
27642 0 : if( k==0 )
27643 : {
27644 0 : state->nec = 0;
27645 0 : state->nic = 0;
27646 0 : state->constraintschanged = ae_true;
27647 0 : return;
27648 : }
27649 :
27650 : /*
27651 : * Equality constraints are stored first, in the upper
27652 : * NEC rows of State.CLEIC matrix. Inequality constraints
27653 : * are stored in the next NIC rows.
27654 : *
27655 : * NOTE: we convert inequality constraints to the form
27656 : * A*x<=b before copying them.
27657 : */
27658 0 : rmatrixsetlengthatleast(&state->cleic, k, n+1, _state);
27659 0 : state->nec = 0;
27660 0 : state->nic = 0;
27661 0 : for(i=0; i<=k-1; i++)
27662 : {
27663 0 : if( ct->ptr.p_int[i]==0 )
27664 : {
27665 0 : ae_v_move(&state->cleic.ptr.pp_double[state->nec][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n));
27666 0 : state->nec = state->nec+1;
27667 : }
27668 : }
27669 0 : for(i=0; i<=k-1; i++)
27670 : {
27671 0 : if( ct->ptr.p_int[i]!=0 )
27672 : {
27673 0 : if( ct->ptr.p_int[i]>0 )
27674 : {
27675 0 : 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));
27676 : }
27677 : else
27678 : {
27679 0 : 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));
27680 : }
27681 0 : state->nic = state->nic+1;
27682 : }
27683 : }
27684 :
27685 : /*
27686 : * Mark state as changed
27687 : */
27688 0 : state->constraintschanged = ae_true;
27689 : }
27690 :
27691 :
27692 : /*************************************************************************
27693 : Another variation of SASSetLC(), which accepts linear constraints using
27694 : another representation.
27695 :
27696 : Linear constraints are inactive by default (after initial creation).
27697 :
27698 : INPUT PARAMETERS:
27699 : State - SAS structure
27700 : CLEIC - linear constraints, array[NEC+NIC,N+1].
27701 : Each row of C represents one constraint:
27702 : * first N elements correspond to coefficients,
27703 : * last element corresponds to the right part.
27704 : First NEC rows store equality constraints, next NIC - are
27705 : inequality ones.
27706 : All elements of C (including right part) must be finite.
27707 : NEC - number of equality constraints, NEC>=0
27708 : NIC - number of inequality constraints, NIC>=0
27709 :
27710 : NOTE 1: linear (non-bound) constraints are satisfied only approximately:
27711 : * there always exists some minor violation (about Epsilon in magnitude)
27712 : due to rounding errors
27713 : * numerical differentiation, if used, may lead to function evaluations
27714 : outside of the feasible area, because algorithm does NOT change
27715 : numerical differentiation formula according to linear constraints.
27716 : If you want constraints to be satisfied exactly, try to reformulate your
27717 : problem in such manner that all constraints will become boundary ones
27718 : (this kind of constraints is always satisfied exactly, both in the final
27719 : solution and in all intermediate points).
27720 :
27721 : -- ALGLIB --
27722 : Copyright 28.11.2010 by Bochkanov Sergey
27723 : *************************************************************************/
27724 0 : void sassetlcx(sactiveset* state,
27725 : /* Real */ ae_matrix* cleic,
27726 : ae_int_t nec,
27727 : ae_int_t nic,
27728 : ae_state *_state)
27729 : {
27730 : ae_int_t n;
27731 : ae_int_t i;
27732 : ae_int_t j;
27733 :
27734 :
27735 0 : ae_assert(state->algostate==0, "SASSetLCX: you may change constraints only in modification mode", _state);
27736 0 : n = state->n;
27737 :
27738 : /*
27739 : * First, check for errors in the inputs
27740 : */
27741 0 : ae_assert(nec>=0, "SASSetLCX: NEC<0", _state);
27742 0 : ae_assert(nic>=0, "SASSetLCX: NIC<0", _state);
27743 0 : ae_assert(cleic->cols>=n+1||nec+nic==0, "SASSetLCX: Cols(CLEIC)<N+1", _state);
27744 0 : ae_assert(cleic->rows>=nec+nic, "SASSetLCX: Rows(CLEIC)<NEC+NIC", _state);
27745 0 : ae_assert(apservisfinitematrix(cleic, nec+nic, n+1, _state), "SASSetLCX: CLEIC contains infinite or NaN values!", _state);
27746 :
27747 : /*
27748 : * Store constraints
27749 : */
27750 0 : rmatrixsetlengthatleast(&state->cleic, nec+nic, n+1, _state);
27751 0 : state->nec = nec;
27752 0 : state->nic = nic;
27753 0 : for(i=0; i<=nec+nic-1; i++)
27754 : {
27755 0 : for(j=0; j<=n; j++)
27756 : {
27757 0 : state->cleic.ptr.pp_double[i][j] = cleic->ptr.pp_double[i][j];
27758 : }
27759 : }
27760 :
27761 : /*
27762 : * Mark state as changed
27763 : */
27764 0 : state->constraintschanged = ae_true;
27765 0 : }
27766 :
27767 :
27768 : /*************************************************************************
27769 : This subroutine turns on optimization mode:
27770 : 1. feasibility in X is enforced (in case X=S.XC and constraints have not
27771 : changed, algorithm just uses X without any modifications at all)
27772 : 2. constraints are marked as "candidate" or "inactive"
27773 :
27774 : INPUT PARAMETERS:
27775 : S - active set object
27776 : X - initial point (candidate), array[N]. It is expected that X
27777 : contains only finite values (we do not check it).
27778 :
27779 : OUTPUT PARAMETERS:
27780 : S - state is changed
27781 : X - initial point can be changed to enforce feasibility
27782 :
27783 : RESULT:
27784 : True in case feasible point was found (mode was changed to "optimization")
27785 : False in case no feasible point was found (mode was not changed)
27786 :
27787 : -- ALGLIB --
27788 : Copyright 21.12.2012 by Bochkanov Sergey
27789 : *************************************************************************/
27790 0 : ae_bool sasstartoptimization(sactiveset* state,
27791 : /* Real */ ae_vector* x,
27792 : ae_state *_state)
27793 : {
27794 : ae_int_t n;
27795 : ae_int_t nec;
27796 : ae_int_t nic;
27797 : ae_int_t i;
27798 : ae_int_t j;
27799 : double v;
27800 : double v0;
27801 : double v1;
27802 : double vv;
27803 : double vc;
27804 : double vx;
27805 : ae_bool result;
27806 :
27807 :
27808 0 : ae_assert(state->algostate==0, "SASStartOptimization: already in optimization mode", _state);
27809 0 : result = ae_false;
27810 0 : n = state->n;
27811 0 : nec = state->nec;
27812 0 : nic = state->nic;
27813 :
27814 : /*
27815 : * Enforce feasibility and calculate set of "candidate"/"active" constraints.
27816 : * Always active equality constraints are marked as "active", all other constraints
27817 : * are marked as "candidate".
27818 : */
27819 0 : ivectorsetlengthatleast(&state->cstatus, n+nec+nic, _state);
27820 0 : for(i=0; i<=n-1; i++)
27821 : {
27822 0 : if( state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i] )
27823 : {
27824 0 : if( ae_fp_greater(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
27825 : {
27826 0 : return result;
27827 : }
27828 : }
27829 : }
27830 0 : ae_v_move(&state->xc.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
27831 0 : if( state->nec+state->nic>0 )
27832 : {
27833 :
27834 : /*
27835 : * General linear constraints are present.
27836 : * Try to use fast code for feasible initial point with modest
27837 : * memory requirements.
27838 : */
27839 0 : rvectorsetlengthatleast(&state->tmp0, n, _state);
27840 0 : state->feasinitpt = ae_true;
27841 0 : for(i=0; i<=n-1; i++)
27842 : {
27843 0 : state->tmp0.ptr.p_double[i] = x->ptr.p_double[i];
27844 0 : state->cstatus.ptr.p_int[i] = -1;
27845 0 : 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]) )
27846 : {
27847 0 : state->tmp0.ptr.p_double[i] = state->bndl.ptr.p_double[i];
27848 0 : state->cstatus.ptr.p_int[i] = 1;
27849 0 : continue;
27850 : }
27851 0 : if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less_eq(state->tmp0.ptr.p_double[i],state->bndl.ptr.p_double[i]) )
27852 : {
27853 0 : state->cstatus.ptr.p_int[i] = 0;
27854 0 : state->tmp0.ptr.p_double[i] = state->bndl.ptr.p_double[i];
27855 : }
27856 0 : if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater_eq(state->tmp0.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
27857 : {
27858 0 : state->cstatus.ptr.p_int[i] = 0;
27859 0 : state->tmp0.ptr.p_double[i] = state->bndu.ptr.p_double[i];
27860 : }
27861 : }
27862 0 : for(i=0; i<=state->nec+state->nic-1; i++)
27863 : {
27864 0 : v = -state->cleic.ptr.pp_double[i][n];
27865 0 : v0 = (double)(0);
27866 0 : v1 = (double)(0);
27867 0 : for(j=0; j<=n-1; j++)
27868 : {
27869 0 : vx = state->tmp0.ptr.p_double[j]/state->s.ptr.p_double[j];
27870 0 : vc = state->cleic.ptr.pp_double[i][j]*state->s.ptr.p_double[j];
27871 0 : v = v+vx*vc;
27872 0 : v0 = v0+ae_sqr(vx, _state);
27873 0 : v1 = v1+ae_sqr(vc, _state);
27874 : }
27875 0 : vv = ae_sqrt(v0, _state)*ae_sqrt(v1, _state)*1000*ae_machineepsilon;
27876 0 : if( i<state->nec )
27877 : {
27878 0 : state->cstatus.ptr.p_int[n+i] = 1;
27879 0 : state->feasinitpt = state->feasinitpt&&ae_fp_less(ae_fabs(v, _state),vv);
27880 : }
27881 : else
27882 : {
27883 0 : state->feasinitpt = state->feasinitpt&&ae_fp_less(v,vv);
27884 0 : if( ae_fp_less(v,-vv) )
27885 : {
27886 0 : state->cstatus.ptr.p_int[n+i] = -1;
27887 : }
27888 : else
27889 : {
27890 0 : state->cstatus.ptr.p_int[n+i] = 0;
27891 : }
27892 : }
27893 : }
27894 0 : if( state->feasinitpt )
27895 : {
27896 0 : ae_v_move(&state->xc.ptr.p_double[0], 1, &state->tmp0.ptr.p_double[0], 1, ae_v_len(0,n-1));
27897 : }
27898 :
27899 : /*
27900 : * Fast code failed? Use general code with ~(N+NIC)^2 memory requirements
27901 : */
27902 0 : if( !state->feasinitpt )
27903 : {
27904 0 : rvectorsetlengthatleast(&state->tmp0, n, _state);
27905 0 : rvectorsetlengthatleast(&state->tmpfeas, n+state->nic, _state);
27906 0 : rmatrixsetlengthatleast(&state->tmpm0, state->nec+state->nic, n+state->nic+1, _state);
27907 0 : for(i=0; i<=state->nec+state->nic-1; i++)
27908 : {
27909 0 : 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));
27910 0 : for(j=n; j<=n+state->nic-1; j++)
27911 : {
27912 0 : state->tmpm0.ptr.pp_double[i][j] = (double)(0);
27913 : }
27914 0 : if( i>=state->nec )
27915 : {
27916 0 : state->tmpm0.ptr.pp_double[i][n+i-state->nec] = 1.0;
27917 : }
27918 0 : state->tmpm0.ptr.pp_double[i][n+state->nic] = state->cleic.ptr.pp_double[i][n];
27919 : }
27920 0 : ae_v_move(&state->tmpfeas.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
27921 0 : for(i=0; i<=state->nic-1; i++)
27922 : {
27923 0 : 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));
27924 0 : state->tmpfeas.ptr.p_double[i+n] = ae_maxreal(state->cleic.ptr.pp_double[i+state->nec][n]-v, 0.0, _state);
27925 : }
27926 0 : 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) )
27927 : {
27928 0 : return result;
27929 : }
27930 0 : ae_v_move(&state->xc.ptr.p_double[0], 1, &state->tmpfeas.ptr.p_double[0], 1, ae_v_len(0,n-1));
27931 0 : for(i=0; i<=n-1; i++)
27932 : {
27933 0 : 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]) )
27934 : {
27935 0 : state->cstatus.ptr.p_int[i] = 1;
27936 0 : continue;
27937 : }
27938 0 : 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])) )
27939 : {
27940 0 : state->cstatus.ptr.p_int[i] = 0;
27941 0 : continue;
27942 : }
27943 0 : state->cstatus.ptr.p_int[i] = -1;
27944 : }
27945 0 : for(i=0; i<=state->nec-1; i++)
27946 : {
27947 0 : state->cstatus.ptr.p_int[n+i] = 1;
27948 : }
27949 0 : for(i=0; i<=state->nic-1; i++)
27950 : {
27951 0 : if( ae_fp_eq(state->tmpfeas.ptr.p_double[n+i],(double)(0)) )
27952 : {
27953 0 : state->cstatus.ptr.p_int[n+state->nec+i] = 0;
27954 : }
27955 : else
27956 : {
27957 0 : state->cstatus.ptr.p_int[n+state->nec+i] = -1;
27958 : }
27959 : }
27960 : }
27961 : }
27962 : else
27963 : {
27964 :
27965 : /*
27966 : * Only box constraints are present, quick code can be used
27967 : */
27968 0 : for(i=0; i<=n-1; i++)
27969 : {
27970 0 : state->cstatus.ptr.p_int[i] = -1;
27971 0 : 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]) )
27972 : {
27973 0 : state->cstatus.ptr.p_int[i] = 1;
27974 0 : state->xc.ptr.p_double[i] = state->bndl.ptr.p_double[i];
27975 0 : continue;
27976 : }
27977 0 : if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less_eq(state->xc.ptr.p_double[i],state->bndl.ptr.p_double[i]) )
27978 : {
27979 0 : state->xc.ptr.p_double[i] = state->bndl.ptr.p_double[i];
27980 0 : state->cstatus.ptr.p_int[i] = 0;
27981 0 : continue;
27982 : }
27983 0 : if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater_eq(state->xc.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
27984 : {
27985 0 : state->xc.ptr.p_double[i] = state->bndu.ptr.p_double[i];
27986 0 : state->cstatus.ptr.p_int[i] = 0;
27987 0 : continue;
27988 : }
27989 : }
27990 0 : state->feasinitpt = ae_true;
27991 : }
27992 :
27993 : /*
27994 : * Change state, allocate temporaries
27995 : */
27996 0 : result = ae_true;
27997 0 : state->algostate = 1;
27998 0 : state->basisisready = ae_false;
27999 0 : state->hasxc = ae_true;
28000 0 : return result;
28001 : }
28002 :
28003 :
28004 : /*************************************************************************
28005 : This function explores search direction and calculates bound for step as
28006 : well as information for activation of constraints.
28007 :
28008 : INPUT PARAMETERS:
28009 : State - SAS structure which stores current point and all other
28010 : active set related information
28011 : D - descent direction to explore
28012 :
28013 : OUTPUT PARAMETERS:
28014 : StpMax - upper limit on step length imposed by yet inactive
28015 : constraints. Can be zero in case some constraints
28016 : can be activated by zero step. Equal to some large
28017 : value in case step is unlimited.
28018 : CIdx - -1 for unlimited step, in [0,N+NEC+NIC) in case of
28019 : limited step.
28020 : VVal - value which is assigned to X[CIdx] during activation.
28021 : For CIdx<0 or CIdx>=N some dummy value is assigned to
28022 : this parameter.
28023 : *************************************************************************/
28024 0 : void sasexploredirection(sactiveset* state,
28025 : /* Real */ ae_vector* d,
28026 : double* stpmax,
28027 : ae_int_t* cidx,
28028 : double* vval,
28029 : ae_state *_state)
28030 : {
28031 : ae_int_t n;
28032 : ae_int_t nec;
28033 : ae_int_t nic;
28034 : ae_int_t i;
28035 : double prevmax;
28036 : double vc;
28037 : double vd;
28038 :
28039 0 : *stpmax = 0;
28040 0 : *cidx = 0;
28041 0 : *vval = 0;
28042 :
28043 0 : ae_assert(state->algostate==1, "SASExploreDirection: is not in optimization mode", _state);
28044 0 : n = state->n;
28045 0 : nec = state->nec;
28046 0 : nic = state->nic;
28047 0 : *cidx = -1;
28048 0 : *vval = (double)(0);
28049 0 : *stpmax = 1.0E50;
28050 0 : for(i=0; i<=n-1; i++)
28051 : {
28052 0 : if( state->cstatus.ptr.p_int[i]<=0 )
28053 : {
28054 0 : 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);
28055 0 : 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);
28056 0 : if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less(d->ptr.p_double[i],(double)(0)) )
28057 : {
28058 0 : prevmax = *stpmax;
28059 0 : *stpmax = safeminposrv(state->xc.ptr.p_double[i]-state->bndl.ptr.p_double[i], -d->ptr.p_double[i], *stpmax, _state);
28060 0 : if( ae_fp_less(*stpmax,prevmax) )
28061 : {
28062 0 : *cidx = i;
28063 0 : *vval = state->bndl.ptr.p_double[i];
28064 : }
28065 : }
28066 0 : if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater(d->ptr.p_double[i],(double)(0)) )
28067 : {
28068 0 : prevmax = *stpmax;
28069 0 : *stpmax = safeminposrv(state->bndu.ptr.p_double[i]-state->xc.ptr.p_double[i], d->ptr.p_double[i], *stpmax, _state);
28070 0 : if( ae_fp_less(*stpmax,prevmax) )
28071 : {
28072 0 : *cidx = i;
28073 0 : *vval = state->bndu.ptr.p_double[i];
28074 : }
28075 : }
28076 : }
28077 : }
28078 0 : for(i=nec; i<=nec+nic-1; i++)
28079 : {
28080 0 : if( state->cstatus.ptr.p_int[n+i]<=0 )
28081 : {
28082 0 : 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));
28083 0 : vc = vc-state->cleic.ptr.pp_double[i][n];
28084 0 : vd = ae_v_dotproduct(&state->cleic.ptr.pp_double[i][0], 1, &d->ptr.p_double[0], 1, ae_v_len(0,n-1));
28085 0 : if( ae_fp_less_eq(vd,(double)(0)) )
28086 : {
28087 0 : continue;
28088 : }
28089 0 : if( ae_fp_less(vc,(double)(0)) )
28090 : {
28091 :
28092 : /*
28093 : * XC is strictly feasible with respect to I-th constraint,
28094 : * we can perform non-zero step because there is non-zero distance
28095 : * between XC and bound.
28096 : */
28097 0 : prevmax = *stpmax;
28098 0 : *stpmax = safeminposrv(-vc, vd, *stpmax, _state);
28099 0 : if( ae_fp_less(*stpmax,prevmax) )
28100 : {
28101 0 : *cidx = n+i;
28102 : }
28103 : }
28104 : else
28105 : {
28106 :
28107 : /*
28108 : * XC is at the boundary (or slightly beyond it), and step vector
28109 : * points beyond the boundary.
28110 : *
28111 : * The only thing we can do is to perform zero step and activate
28112 : * I-th constraint.
28113 : */
28114 0 : *stpmax = (double)(0);
28115 0 : *cidx = n+i;
28116 : }
28117 : }
28118 : }
28119 0 : }
28120 :
28121 :
28122 : /*************************************************************************
28123 : This subroutine moves current point to XN, which can be:
28124 : a) point in the direction previously explored with SASExploreDirection()
28125 : function (in this case NeedAct/CIdx/CVal are used)
28126 : b) point in arbitrary direction, not necessarily previously checked with
28127 : SASExploreDirection() function.
28128 :
28129 : Step may activate one constraint. It is assumed than XN is approximately
28130 : feasible (small error as large as several ulps is possible). Strict
28131 : feasibility with respect to bound constraints is enforced during
28132 : activation, feasibility with respect to general linear constraints is not
28133 : enforced.
28134 :
28135 : This function activates boundary constraints, such that both is True:
28136 : 1) XC[I] is not at the boundary
28137 : 2) XN[I] is at the boundary or beyond it
28138 :
28139 : INPUT PARAMETERS:
28140 : S - active set object
28141 : XN - new point.
28142 : NeedAct - True in case one constraint needs activation
28143 : CIdx - index of constraint, in [0,N+NEC+NIC).
28144 : Ignored if NeedAct is false.
28145 : This value is calculated by SASExploreDirection().
28146 : CVal - for CIdx in [0,N) this field stores value which is
28147 : assigned to XC[CIdx] during activation. CVal is ignored in
28148 : other cases.
28149 : This value is calculated by SASExploreDirection().
28150 :
28151 : OUTPUT PARAMETERS:
28152 : S - current point and list of active constraints are changed.
28153 :
28154 : RESULT:
28155 : >0, in case at least one inactive non-candidate constraint was activated
28156 : =0, in case only "candidate" constraints were activated
28157 : <0, in case no constraints were activated by the step
28158 :
28159 : NOTE: in general case State.XC<>XN because activation of constraints may
28160 : slightly change current point (to enforce feasibility).
28161 :
28162 : -- ALGLIB --
28163 : Copyright 21.12.2012 by Bochkanov Sergey
28164 : *************************************************************************/
28165 0 : ae_int_t sasmoveto(sactiveset* state,
28166 : /* Real */ ae_vector* xn,
28167 : ae_bool needact,
28168 : ae_int_t cidx,
28169 : double cval,
28170 : ae_state *_state)
28171 : {
28172 : ae_int_t n;
28173 : ae_int_t nec;
28174 : ae_int_t nic;
28175 : ae_int_t i;
28176 : ae_bool wasactivation;
28177 : ae_int_t result;
28178 :
28179 :
28180 0 : ae_assert(state->algostate==1, "SASMoveTo: is not in optimization mode", _state);
28181 0 : n = state->n;
28182 0 : nec = state->nec;
28183 0 : nic = state->nic;
28184 :
28185 : /*
28186 : * Save previous state, update current point
28187 : */
28188 0 : rvectorsetlengthatleast(&state->mtx, n, _state);
28189 0 : ivectorsetlengthatleast(&state->mtas, n+nec+nic, _state);
28190 0 : for(i=0; i<=n-1; i++)
28191 : {
28192 0 : state->mtx.ptr.p_double[i] = state->xc.ptr.p_double[i];
28193 0 : state->xc.ptr.p_double[i] = xn->ptr.p_double[i];
28194 : }
28195 0 : for(i=0; i<=n+nec+nic-1; i++)
28196 : {
28197 0 : state->mtas.ptr.p_int[i] = state->cstatus.ptr.p_int[i];
28198 : }
28199 :
28200 : /*
28201 : * Activate constraints
28202 : */
28203 0 : bvectorsetlengthatleast(&state->mtnew, n+nec+nic, _state);
28204 0 : wasactivation = ae_false;
28205 0 : for(i=0; i<=n+nec+nic-1; i++)
28206 : {
28207 0 : state->mtnew.ptr.p_bool[i] = ae_false;
28208 : }
28209 0 : if( needact )
28210 : {
28211 :
28212 : /*
28213 : * Activation
28214 : */
28215 0 : ae_assert(cidx>=0&&cidx<n+nec+nic, "SASMoveTo: incorrect CIdx", _state);
28216 0 : if( cidx<n )
28217 : {
28218 :
28219 : /*
28220 : * CIdx in [0,N-1] means that bound constraint was activated.
28221 : * We activate it explicitly to avoid situation when roundoff-error
28222 : * prevents us from moving EXACTLY to x=CVal.
28223 : */
28224 0 : state->xc.ptr.p_double[cidx] = cval;
28225 : }
28226 0 : state->cstatus.ptr.p_int[cidx] = 1;
28227 0 : state->mtnew.ptr.p_bool[cidx] = ae_true;
28228 0 : wasactivation = ae_true;
28229 : }
28230 0 : for(i=0; i<=n-1; i++)
28231 : {
28232 :
28233 : /*
28234 : * Post-check (some constraints may be activated because of numerical errors)
28235 : */
28236 0 : if( (state->hasbndl.ptr.p_bool[i]&&ae_fp_less_eq(state->xc.ptr.p_double[i],state->bndl.ptr.p_double[i]))&&ae_fp_neq(state->xc.ptr.p_double[i],state->mtx.ptr.p_double[i]) )
28237 : {
28238 0 : state->xc.ptr.p_double[i] = state->bndl.ptr.p_double[i];
28239 0 : state->cstatus.ptr.p_int[i] = 1;
28240 0 : state->mtnew.ptr.p_bool[i] = ae_true;
28241 0 : wasactivation = ae_true;
28242 : }
28243 0 : if( (state->hasbndu.ptr.p_bool[i]&&ae_fp_greater_eq(state->xc.ptr.p_double[i],state->bndu.ptr.p_double[i]))&&ae_fp_neq(state->xc.ptr.p_double[i],state->mtx.ptr.p_double[i]) )
28244 : {
28245 0 : state->xc.ptr.p_double[i] = state->bndu.ptr.p_double[i];
28246 0 : state->cstatus.ptr.p_int[i] = 1;
28247 0 : state->mtnew.ptr.p_bool[i] = ae_true;
28248 0 : wasactivation = ae_true;
28249 : }
28250 : }
28251 :
28252 : /*
28253 : * Determine return status:
28254 : * * -1 in case no constraints were activated
28255 : * * 0 in case only "candidate" constraints were activated
28256 : * * +1 in case at least one "non-candidate" constraint was activated
28257 : */
28258 0 : if( wasactivation )
28259 : {
28260 :
28261 : /*
28262 : * Step activated one/several constraints, but sometimes it is spurious
28263 : * activation - RecalculateConstraints() tells us that constraint is
28264 : * inactive (negative Largrange multiplier), but step activates it
28265 : * because of numerical noise.
28266 : *
28267 : * This block of code checks whether step activated truly new constraints
28268 : * (ones which were not in the active set at the solution):
28269 : *
28270 : * * for non-boundary constraint it is enough to check that previous value
28271 : * of CStatus[i] is negative (=far from boundary), and new one is
28272 : * positive (=we are at the boundary, constraint is activated).
28273 : *
28274 : * * for boundary constraints previous criterion won't work. Each variable
28275 : * has two constraints, and simply checking their status is not enough -
28276 : * we have to correctly identify cases when we leave one boundary
28277 : * (PrevActiveSet[i]=0) and move to another boundary (CStatus[i]>0).
28278 : * Such cases can be identified if we compare previous X with new X.
28279 : *
28280 : * In case only "candidate" constraints were activated, result variable
28281 : * is set to 0. In case at least one new constraint was activated, result
28282 : * is set to 1.
28283 : */
28284 0 : result = 0;
28285 0 : for(i=0; i<=n-1; i++)
28286 : {
28287 0 : if( state->cstatus.ptr.p_int[i]>0&&ae_fp_neq(state->xc.ptr.p_double[i],state->mtx.ptr.p_double[i]) )
28288 : {
28289 0 : result = 1;
28290 : }
28291 : }
28292 0 : for(i=n; i<=n+state->nec+state->nic-1; i++)
28293 : {
28294 0 : if( state->mtas.ptr.p_int[i]<0&&state->cstatus.ptr.p_int[i]>0 )
28295 : {
28296 0 : result = 1;
28297 : }
28298 : }
28299 : }
28300 : else
28301 : {
28302 :
28303 : /*
28304 : * No activation, return -1
28305 : */
28306 0 : result = -1;
28307 : }
28308 :
28309 : /*
28310 : * Update basis
28311 : */
28312 0 : sasappendtobasis(state, &state->mtnew, _state);
28313 0 : return result;
28314 : }
28315 :
28316 :
28317 : /*************************************************************************
28318 : This subroutine performs immediate activation of one constraint:
28319 : * "immediate" means that we do not have to move to activate it
28320 : * in case boundary constraint is activated, we enforce current point to be
28321 : exactly at the boundary
28322 :
28323 : INPUT PARAMETERS:
28324 : S - active set object
28325 : CIdx - index of constraint, in [0,N+NEC+NIC).
28326 : This value is calculated by SASExploreDirection().
28327 : CVal - for CIdx in [0,N) this field stores value which is
28328 : assigned to XC[CIdx] during activation. CVal is ignored in
28329 : other cases.
28330 : This value is calculated by SASExploreDirection().
28331 :
28332 : -- ALGLIB --
28333 : Copyright 21.12.2012 by Bochkanov Sergey
28334 : *************************************************************************/
28335 0 : void sasimmediateactivation(sactiveset* state,
28336 : ae_int_t cidx,
28337 : double cval,
28338 : ae_state *_state)
28339 : {
28340 : ae_int_t i;
28341 :
28342 :
28343 0 : ae_assert(state->algostate==1, "SASMoveTo: is not in optimization mode", _state);
28344 0 : if( cidx<state->n )
28345 : {
28346 0 : state->xc.ptr.p_double[cidx] = cval;
28347 : }
28348 0 : state->cstatus.ptr.p_int[cidx] = 1;
28349 0 : bvectorsetlengthatleast(&state->mtnew, state->n+state->nec+state->nic, _state);
28350 0 : for(i=0; i<=state->n+state->nec+state->nic-1; i++)
28351 : {
28352 0 : state->mtnew.ptr.p_bool[i] = ae_false;
28353 : }
28354 0 : state->mtnew.ptr.p_bool[cidx] = ae_true;
28355 0 : sasappendtobasis(state, &state->mtnew, _state);
28356 0 : }
28357 :
28358 :
28359 : /*************************************************************************
28360 : This subroutine calculates descent direction subject to current active set.
28361 :
28362 : INPUT PARAMETERS:
28363 : S - active set object
28364 : G - array[N], gradient
28365 : D - possibly prealocated buffer;
28366 : automatically resized if needed.
28367 :
28368 : OUTPUT PARAMETERS:
28369 : D - descent direction projected onto current active set.
28370 : Components of D which correspond to active boundary
28371 : constraints are forced to be exactly zero.
28372 : In case D is non-zero, it is normalized to have unit norm.
28373 :
28374 : NOTE: in case active set has N active constraints (or more), descent
28375 : direction is forced to be exactly zero.
28376 :
28377 : -- ALGLIB --
28378 : Copyright 21.12.2012 by Bochkanov Sergey
28379 : *************************************************************************/
28380 0 : void sasconstraineddescent(sactiveset* state,
28381 : /* Real */ ae_vector* g,
28382 : /* Real */ ae_vector* d,
28383 : ae_state *_state)
28384 : {
28385 :
28386 :
28387 0 : ae_assert(state->algostate==1, "SASConstrainedDescent: is not in optimization mode", _state);
28388 0 : sasrebuildbasis(state, _state);
28389 0 : sactivesets_constraineddescent(state, g, &state->unitdiagonal, &state->idensebatch, ae_true, d, _state);
28390 0 : }
28391 :
28392 :
28393 : /*************************************************************************
28394 : This subroutine calculates preconditioned descent direction subject to
28395 : current active set.
28396 :
28397 : INPUT PARAMETERS:
28398 : S - active set object
28399 : G - array[N], gradient
28400 : D - possibly prealocated buffer;
28401 : automatically resized if needed.
28402 :
28403 : OUTPUT PARAMETERS:
28404 : D - descent direction projected onto current active set.
28405 : Components of D which correspond to active boundary
28406 : constraints are forced to be exactly zero.
28407 : In case D is non-zero, it is normalized to have unit norm.
28408 :
28409 : NOTE: in case active set has N active constraints (or more), descent
28410 : direction is forced to be exactly zero.
28411 :
28412 : -- ALGLIB --
28413 : Copyright 21.12.2012 by Bochkanov Sergey
28414 : *************************************************************************/
28415 0 : void sasconstraineddescentprec(sactiveset* state,
28416 : /* Real */ ae_vector* g,
28417 : /* Real */ ae_vector* d,
28418 : ae_state *_state)
28419 : {
28420 :
28421 :
28422 0 : ae_assert(state->algostate==1, "SASConstrainedDescentPrec: is not in optimization mode", _state);
28423 0 : sasrebuildbasis(state, _state);
28424 0 : sactivesets_constraineddescent(state, g, &state->h, &state->pdensebatch, ae_true, d, _state);
28425 0 : }
28426 :
28427 :
28428 : /*************************************************************************
28429 : This subroutine calculates projection of direction vector to current
28430 : active set.
28431 :
28432 : INPUT PARAMETERS:
28433 : S - active set object
28434 : D - array[N], direction
28435 :
28436 : OUTPUT PARAMETERS:
28437 : D - direction projected onto current active set.
28438 : Components of D which correspond to active boundary
28439 : constraints are forced to be exactly zero.
28440 :
28441 : NOTE: in case active set has N active constraints (or more), descent
28442 : direction is forced to be exactly zero.
28443 :
28444 : -- ALGLIB --
28445 : Copyright 21.12.2012 by Bochkanov Sergey
28446 : *************************************************************************/
28447 0 : void sasconstraineddirection(sactiveset* state,
28448 : /* Real */ ae_vector* d,
28449 : ae_state *_state)
28450 : {
28451 : ae_int_t i;
28452 :
28453 :
28454 0 : ae_assert(state->algostate==1, "SASConstrainedAntigradientPrec: is not in optimization mode", _state);
28455 0 : sasrebuildbasis(state, _state);
28456 0 : sactivesets_constraineddescent(state, d, &state->unitdiagonal, &state->idensebatch, ae_false, &state->cdtmp, _state);
28457 0 : for(i=0; i<=state->n-1; i++)
28458 : {
28459 0 : d->ptr.p_double[i] = -state->cdtmp.ptr.p_double[i];
28460 : }
28461 0 : }
28462 :
28463 :
28464 : /*************************************************************************
28465 : This subroutine calculates product of direction vector and preconditioner
28466 : multiplied subject to current active set.
28467 :
28468 : INPUT PARAMETERS:
28469 : S - active set object
28470 : D - array[N], direction
28471 :
28472 : OUTPUT PARAMETERS:
28473 : D - preconditioned direction projected onto current active set.
28474 : Components of D which correspond to active boundary
28475 : constraints are forced to be exactly zero.
28476 :
28477 : NOTE: in case active set has N active constraints (or more), descent
28478 : direction is forced to be exactly zero.
28479 :
28480 : -- ALGLIB --
28481 : Copyright 21.12.2012 by Bochkanov Sergey
28482 : *************************************************************************/
28483 0 : void sasconstraineddirectionprec(sactiveset* state,
28484 : /* Real */ ae_vector* d,
28485 : ae_state *_state)
28486 : {
28487 : ae_int_t i;
28488 :
28489 :
28490 0 : ae_assert(state->algostate==1, "SASConstrainedAntigradientPrec: is not in optimization mode", _state);
28491 0 : sasrebuildbasis(state, _state);
28492 0 : sactivesets_constraineddescent(state, d, &state->h, &state->pdensebatch, ae_false, &state->cdtmp, _state);
28493 0 : for(i=0; i<=state->n-1; i++)
28494 : {
28495 0 : d->ptr.p_double[i] = -state->cdtmp.ptr.p_double[i];
28496 : }
28497 0 : }
28498 :
28499 :
28500 : /*************************************************************************
28501 : This subroutine performs correction of some (possibly infeasible) point
28502 : with respect to a) current active set, b) all boundary constraints, both
28503 : active and inactive:
28504 :
28505 : 0) we calculate L1 penalty term for violation of active linear constraints
28506 : (one which is returned by SASActiveLCPenalty1() function).
28507 : 1) first, it performs projection (orthogonal with respect to scale matrix
28508 : S) of X into current active set: X -> X1.
28509 : 2) next, we perform projection with respect to ALL boundary constraints
28510 : which are violated at X1: X1 -> X2.
28511 : 3) X is replaced by X2.
28512 :
28513 : The idea is that this function can preserve and enforce feasibility during
28514 : optimization, and additional penalty parameter can be used to prevent algo
28515 : from leaving feasible set because of rounding errors.
28516 :
28517 : INPUT PARAMETERS:
28518 : S - active set object
28519 : X - array[N], candidate point
28520 :
28521 : OUTPUT PARAMETERS:
28522 : X - "improved" candidate point:
28523 : a) feasible with respect to all boundary constraints
28524 : b) feasibility with respect to active set is retained at
28525 : good level.
28526 : Penalty - penalty term, which can be added to function value if user
28527 : wants to penalize violation of constraints (recommended).
28528 :
28529 : NOTE: this function is not intended to find exact projection (i.e. best
28530 : approximation) of X into feasible set. It just improves situation a
28531 : bit.
28532 : Regular use of this function will help you to retain feasibility
28533 : - if you already have something to start with and constrain your
28534 : steps is such way that the only source of infeasibility are roundoff
28535 : errors.
28536 :
28537 : -- ALGLIB --
28538 : Copyright 21.12.2012 by Bochkanov Sergey
28539 : *************************************************************************/
28540 0 : void sascorrection(sactiveset* state,
28541 : /* Real */ ae_vector* x,
28542 : double* penalty,
28543 : ae_state *_state)
28544 : {
28545 : ae_int_t i;
28546 : ae_int_t j;
28547 : ae_int_t n;
28548 : double v;
28549 :
28550 0 : *penalty = 0;
28551 :
28552 0 : ae_assert(state->algostate==1, "SASCorrection: is not in optimization mode", _state);
28553 0 : sasrebuildbasis(state, _state);
28554 0 : n = state->n;
28555 0 : rvectorsetlengthatleast(&state->corrtmp, n, _state);
28556 :
28557 : /*
28558 : * Calculate penalty term.
28559 : */
28560 0 : *penalty = sasactivelcpenalty1(state, x, _state);
28561 :
28562 : /*
28563 : * Perform projection 1.
28564 : *
28565 : * This projecton is given by:
28566 : *
28567 : * x_proj = x - S*S*As'*(As*x-b)
28568 : *
28569 : * where x is original x before projection, S is a scale matrix,
28570 : * As is a matrix of equality constraints (active set) which were
28571 : * orthogonalized with respect to inner product given by S (i.e. we
28572 : * have As*S*S'*As'=I), b is a right part of the orthogonalized
28573 : * constraints.
28574 : *
28575 : * NOTE: you can verify that x_proj is strictly feasible w.r.t.
28576 : * active set by multiplying it by As - you will get
28577 : * As*x_proj = As*x - As*x + b = b.
28578 : *
28579 : * This formula for projection can be obtained by solving
28580 : * following minimization problem.
28581 : *
28582 : * min ||inv(S)*(x_proj-x)||^2 s.t. As*x_proj=b
28583 : *
28584 : * NOTE: we apply sparse batch by examining CStatus[]; it is guaranteed
28585 : * to contain sparse batch, but avoids roundoff errors associated
28586 : * with the fact that some box constraints were moved to sparse
28587 : * storage
28588 : *
28589 : */
28590 0 : ae_v_move(&state->corrtmp.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
28591 0 : for(i=0; i<=state->densebatchsize-1; i++)
28592 : {
28593 0 : v = -state->sdensebatch.ptr.pp_double[i][n];
28594 0 : for(j=0; j<=n-1; j++)
28595 : {
28596 0 : v = v+state->sdensebatch.ptr.pp_double[i][j]*state->corrtmp.ptr.p_double[j];
28597 : }
28598 0 : for(j=0; j<=n-1; j++)
28599 : {
28600 0 : state->corrtmp.ptr.p_double[j] = state->corrtmp.ptr.p_double[j]-v*state->sdensebatch.ptr.pp_double[i][j]*ae_sqr(state->s.ptr.p_double[j], _state);
28601 : }
28602 : }
28603 0 : for(i=0; i<=n-1; i++)
28604 : {
28605 0 : if( state->cstatus.ptr.p_int[i]>0 )
28606 : {
28607 0 : state->corrtmp.ptr.p_double[i] = state->xc.ptr.p_double[i];
28608 : }
28609 : }
28610 :
28611 : /*
28612 : * Perform projection 2
28613 : */
28614 0 : for(i=0; i<=n-1; i++)
28615 : {
28616 0 : x->ptr.p_double[i] = state->corrtmp.ptr.p_double[i];
28617 0 : if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less(x->ptr.p_double[i],state->bndl.ptr.p_double[i]) )
28618 : {
28619 0 : x->ptr.p_double[i] = state->bndl.ptr.p_double[i];
28620 : }
28621 0 : if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater(x->ptr.p_double[i],state->bndu.ptr.p_double[i]) )
28622 : {
28623 0 : x->ptr.p_double[i] = state->bndu.ptr.p_double[i];
28624 : }
28625 : }
28626 0 : }
28627 :
28628 :
28629 : /*************************************************************************
28630 : This subroutine returns L1 penalty for violation of active general linear
28631 : constraints (violation of boundary or inactive linear constraints is not
28632 : added to penalty).
28633 :
28634 : Penalty term is equal to:
28635 :
28636 : Penalty = SUM( Abs((C_i*x-R_i)/Alpha_i) )
28637 :
28638 : Here:
28639 : * summation is performed for I=0...NEC+NIC-1, CStatus[N+I]>0
28640 : (only for rows of CLEIC which are in active set)
28641 : * C_i is I-th row of CLEIC
28642 : * R_i is corresponding right part
28643 : * S is a scale matrix
28644 : * Alpha_i = ||S*C_i|| - is a scaling coefficient which "normalizes"
28645 : I-th summation term according to its scale.
28646 :
28647 : INPUT PARAMETERS:
28648 : S - active set object
28649 : X - array[N], candidate point
28650 :
28651 : -- ALGLIB --
28652 : Copyright 21.12.2012 by Bochkanov Sergey
28653 : *************************************************************************/
28654 0 : double sasactivelcpenalty1(sactiveset* state,
28655 : /* Real */ ae_vector* x,
28656 : ae_state *_state)
28657 : {
28658 : ae_int_t i;
28659 : ae_int_t j;
28660 : ae_int_t n;
28661 : ae_int_t nec;
28662 : ae_int_t nic;
28663 : double v;
28664 : double alpha;
28665 : double p;
28666 : double result;
28667 :
28668 :
28669 0 : ae_assert(state->algostate==1, "SASActiveLCPenalty1: is not in optimization mode", _state);
28670 0 : sasrebuildbasis(state, _state);
28671 0 : n = state->n;
28672 0 : nec = state->nec;
28673 0 : nic = state->nic;
28674 :
28675 : /*
28676 : * Calculate penalty term.
28677 : */
28678 0 : result = (double)(0);
28679 0 : for(i=0; i<=nec+nic-1; i++)
28680 : {
28681 0 : if( state->cstatus.ptr.p_int[n+i]>0 )
28682 : {
28683 0 : alpha = (double)(0);
28684 0 : p = -state->cleic.ptr.pp_double[i][n];
28685 0 : for(j=0; j<=n-1; j++)
28686 : {
28687 0 : v = state->cleic.ptr.pp_double[i][j];
28688 0 : p = p+v*x->ptr.p_double[j];
28689 0 : alpha = alpha+ae_sqr(v*state->s.ptr.p_double[j], _state);
28690 : }
28691 0 : alpha = ae_sqrt(alpha, _state);
28692 0 : if( ae_fp_neq(alpha,(double)(0)) )
28693 : {
28694 0 : result = result+ae_fabs(p/alpha, _state);
28695 : }
28696 : }
28697 : }
28698 0 : return result;
28699 : }
28700 :
28701 :
28702 : /*************************************************************************
28703 : This subroutine calculates scaled norm of vector after projection onto
28704 : subspace of active constraints. Most often this function is used to test
28705 : stopping conditions.
28706 :
28707 : INPUT PARAMETERS:
28708 : S - active set object
28709 : D - vector whose norm is calculated
28710 :
28711 : RESULT:
28712 : Vector norm (after projection and scaling)
28713 :
28714 : NOTE: projection is performed first, scaling is performed after projection
28715 :
28716 : NOTE: if we have N active constraints, zero value (exact zero) is returned
28717 :
28718 : -- ALGLIB --
28719 : Copyright 21.12.2012 by Bochkanov Sergey
28720 : *************************************************************************/
28721 0 : double sasscaledconstrainednorm(sactiveset* state,
28722 : /* Real */ ae_vector* d,
28723 : ae_state *_state)
28724 : {
28725 : ae_int_t i;
28726 : ae_int_t n;
28727 : double v;
28728 : double result;
28729 :
28730 :
28731 0 : ae_assert(state->algostate==1, "SASMoveTo: is not in optimization mode", _state);
28732 0 : n = state->n;
28733 0 : rvectorsetlengthatleast(&state->scntmp, n, _state);
28734 :
28735 : /*
28736 : * Prepare basis (if needed)
28737 : */
28738 0 : sasrebuildbasis(state, _state);
28739 :
28740 : /*
28741 : * Calculate descent direction
28742 : */
28743 0 : if( state->sparsebatchsize+state->densebatchsize>=n )
28744 : {
28745 :
28746 : /*
28747 : * Quick exit if number of active constraints is N or larger
28748 : */
28749 0 : result = 0.0;
28750 0 : return result;
28751 : }
28752 0 : for(i=0; i<=n-1; i++)
28753 : {
28754 0 : state->scntmp.ptr.p_double[i] = d->ptr.p_double[i];
28755 : }
28756 0 : for(i=0; i<=state->densebatchsize-1; i++)
28757 : {
28758 0 : v = ae_v_dotproduct(&state->idensebatch.ptr.pp_double[i][0], 1, &state->scntmp.ptr.p_double[0], 1, ae_v_len(0,n-1));
28759 0 : ae_v_subd(&state->scntmp.ptr.p_double[0], 1, &state->idensebatch.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v);
28760 : }
28761 0 : for(i=0; i<=n-1; i++)
28762 : {
28763 0 : if( state->cstatus.ptr.p_int[i]>0 )
28764 : {
28765 0 : state->scntmp.ptr.p_double[i] = (double)(0);
28766 : }
28767 : }
28768 0 : v = 0.0;
28769 0 : for(i=0; i<=n-1; i++)
28770 : {
28771 0 : v = v+ae_sqr(state->s.ptr.p_double[i]*state->scntmp.ptr.p_double[i], _state);
28772 : }
28773 0 : result = ae_sqrt(v, _state);
28774 0 : return result;
28775 : }
28776 :
28777 :
28778 : /*************************************************************************
28779 : This subroutine turns off optimization mode.
28780 :
28781 : INPUT PARAMETERS:
28782 : S - active set object
28783 :
28784 : OUTPUT PARAMETERS:
28785 : S - state is changed
28786 :
28787 : NOTE: this function can be called many times for optimizer which was
28788 : already stopped.
28789 :
28790 : -- ALGLIB --
28791 : Copyright 21.12.2012 by Bochkanov Sergey
28792 : *************************************************************************/
28793 0 : void sasstopoptimization(sactiveset* state, ae_state *_state)
28794 : {
28795 :
28796 :
28797 0 : state->algostate = 0;
28798 0 : }
28799 :
28800 :
28801 : /*************************************************************************
28802 : This function recalculates constraints - activates and deactivates them
28803 : according to gradient value at current point. Algorithm assumes that we
28804 : want to make steepest descent step from current point; constraints are
28805 : activated and deactivated in such way that we won't violate any constraint
28806 : by steepest descent step.
28807 :
28808 : After call to this function active set is ready to try steepest descent
28809 : step (SASDescentDirection-SASExploreDirection-SASMoveTo).
28810 :
28811 : Only already "active" and "candidate" elements of ActiveSet are examined;
28812 : constraints which are not active are not examined.
28813 :
28814 : INPUT PARAMETERS:
28815 : State - active set object
28816 : GC - array[N], gradient at XC
28817 :
28818 : OUTPUT PARAMETERS:
28819 : State - active set object, with new set of constraint
28820 :
28821 : -- ALGLIB --
28822 : Copyright 26.09.2012 by Bochkanov Sergey
28823 : *************************************************************************/
28824 0 : void sasreactivateconstraints(sactiveset* state,
28825 : /* Real */ ae_vector* gc,
28826 : ae_state *_state)
28827 : {
28828 :
28829 :
28830 0 : ae_assert(state->algostate==1, "SASReactivateConstraints: must be in optimization mode", _state);
28831 0 : sactivesets_reactivateconstraints(state, gc, &state->unitdiagonal, _state);
28832 0 : }
28833 :
28834 :
28835 : /*************************************************************************
28836 : This function recalculates constraints - activates and deactivates them
28837 : according to gradient value at current point.
28838 :
28839 : Algorithm assumes that we want to make Quasi-Newton step from current
28840 : point with diagonal Quasi-Newton matrix H. Constraints are activated and
28841 : deactivated in such way that we won't violate any constraint by step.
28842 :
28843 : After call to this function active set is ready to try preconditioned
28844 : steepest descent step (SASDescentDirection-SASExploreDirection-SASMoveTo).
28845 :
28846 : Only already "active" and "candidate" elements of ActiveSet are examined;
28847 : constraints which are not active are not examined.
28848 :
28849 : INPUT PARAMETERS:
28850 : State - active set object
28851 : GC - array[N], gradient at XC
28852 :
28853 : OUTPUT PARAMETERS:
28854 : State - active set object, with new set of constraint
28855 :
28856 : -- ALGLIB --
28857 : Copyright 26.09.2012 by Bochkanov Sergey
28858 : *************************************************************************/
28859 0 : void sasreactivateconstraintsprec(sactiveset* state,
28860 : /* Real */ ae_vector* gc,
28861 : ae_state *_state)
28862 : {
28863 :
28864 :
28865 0 : ae_assert(state->algostate==1, "SASReactivateConstraintsPrec: must be in optimization mode", _state);
28866 0 : sactivesets_reactivateconstraints(state, gc, &state->h, _state);
28867 0 : }
28868 :
28869 :
28870 : /*************************************************************************
28871 : This function builds three orthonormal basises for current active set:
28872 : * P-orthogonal one, which is orthogonalized with inner product
28873 : (x,y) = x'*P*y, where P=inv(H) is current preconditioner
28874 : * S-orthogonal one, which is orthogonalized with inner product
28875 : (x,y) = x'*S'*S*y, where S is diagonal scaling matrix
28876 : * I-orthogonal one, which is orthogonalized with standard dot product
28877 :
28878 : NOTE: all sets of orthogonal vectors are guaranteed to have same size.
28879 : P-orthogonal basis is built first, I/S-orthogonal basises are forced
28880 : to have same number of vectors as P-orthogonal one (padded by zero
28881 : vectors if needed).
28882 :
28883 : NOTE: this function tracks changes in active set; first call will result
28884 : in reorthogonalization
28885 :
28886 : INPUT PARAMETERS:
28887 : State - active set object
28888 : H - diagonal preconditioner, H[i]>0
28889 :
28890 : OUTPUT PARAMETERS:
28891 : State - active set object with new basis
28892 :
28893 : -- ALGLIB --
28894 : Copyright 20.06.2012 by Bochkanov Sergey
28895 : *************************************************************************/
28896 0 : void sasrebuildbasis(sactiveset* state, ae_state *_state)
28897 : {
28898 : ae_int_t n;
28899 : ae_int_t nec;
28900 : ae_int_t nic;
28901 : ae_int_t i;
28902 : ae_int_t j;
28903 : ae_bool hasactivelin;
28904 : ae_int_t candidatescnt;
28905 : double v;
28906 : double vv;
28907 : double vmax;
28908 : ae_int_t kmax;
28909 :
28910 :
28911 0 : if( state->basisisready )
28912 : {
28913 0 : return;
28914 : }
28915 0 : n = state->n;
28916 0 : nec = state->nec;
28917 0 : nic = state->nic;
28918 0 : rvectorsetlengthatleast(&state->tmp0, n, _state);
28919 0 : rvectorsetlengthatleast(&state->tmpprodp, n, _state);
28920 0 : rvectorsetlengthatleast(&state->tmpprods, n, _state);
28921 0 : rvectorsetlengthatleast(&state->tmpcp, n+1, _state);
28922 0 : rvectorsetlengthatleast(&state->tmpcs, n+1, _state);
28923 0 : rvectorsetlengthatleast(&state->tmpci, n+1, _state);
28924 0 : rmatrixsetlengthatleast(&state->tmpbasis, nec+nic, n+1, _state);
28925 0 : rmatrixsetlengthatleast(&state->pdensebatch, nec+nic, n+1, _state);
28926 0 : rmatrixsetlengthatleast(&state->idensebatch, nec+nic, n+1, _state);
28927 0 : rmatrixsetlengthatleast(&state->sdensebatch, nec+nic, n+1, _state);
28928 0 : ivectorsetlengthatleast(&state->sparsebatch, n, _state);
28929 0 : state->sparsebatchsize = 0;
28930 0 : state->densebatchsize = 0;
28931 0 : state->basisage = 0;
28932 0 : state->basisisready = ae_true;
28933 :
28934 : /*
28935 : * Determine number of active boundary and non-boundary
28936 : * constraints, move them to TmpBasis. Quick exit if no
28937 : * non-boundary constraints were detected.
28938 : */
28939 0 : hasactivelin = ae_false;
28940 0 : for(i=0; i<=nec+nic-1; i++)
28941 : {
28942 0 : if( state->cstatus.ptr.p_int[n+i]>0 )
28943 : {
28944 0 : hasactivelin = ae_true;
28945 : }
28946 : }
28947 0 : for(j=0; j<=n-1; j++)
28948 : {
28949 0 : if( state->cstatus.ptr.p_int[j]>0 )
28950 : {
28951 0 : state->sparsebatch.ptr.p_int[state->sparsebatchsize] = j;
28952 0 : state->sparsebatchsize = state->sparsebatchsize+1;
28953 : }
28954 : }
28955 0 : if( !hasactivelin )
28956 : {
28957 0 : return;
28958 : }
28959 :
28960 : /*
28961 : * Prepare precomputed values
28962 : */
28963 0 : rvectorsetlengthatleast(&state->tmpreciph, n, _state);
28964 0 : for(i=0; i<=n-1; i++)
28965 : {
28966 0 : state->tmpreciph.ptr.p_double[i] = 1/state->h.ptr.p_double[i];
28967 : }
28968 :
28969 : /*
28970 : * Prepare initial candidate set:
28971 : * * select active constraints
28972 : * * normalize (inner product is given by preconditioner)
28973 : * * orthogonalize with respect to active box constraints
28974 : * * copy normalized/orthogonalized candidates to PBasis/SBasis/IBasis
28975 : */
28976 0 : candidatescnt = 0;
28977 0 : for(i=0; i<=nec+nic-1; i++)
28978 : {
28979 0 : if( state->cstatus.ptr.p_int[n+i]>0 )
28980 : {
28981 0 : ae_v_move(&state->tmpbasis.ptr.pp_double[candidatescnt][0], 1, &state->cleic.ptr.pp_double[i][0], 1, ae_v_len(0,n));
28982 0 : inc(&candidatescnt, _state);
28983 : }
28984 : }
28985 0 : for(i=0; i<=candidatescnt-1; i++)
28986 : {
28987 0 : v = 0.0;
28988 0 : for(j=0; j<=n-1; j++)
28989 : {
28990 0 : v = v+ae_sqr(state->tmpbasis.ptr.pp_double[i][j], _state)*state->tmpreciph.ptr.p_double[j];
28991 : }
28992 0 : if( ae_fp_greater(v,(double)(0)) )
28993 : {
28994 0 : v = 1/ae_sqrt(v, _state);
28995 0 : for(j=0; j<=n; j++)
28996 : {
28997 0 : state->tmpbasis.ptr.pp_double[i][j] = state->tmpbasis.ptr.pp_double[i][j]*v;
28998 : }
28999 : }
29000 : }
29001 0 : for(j=0; j<=n-1; j++)
29002 : {
29003 0 : if( state->cstatus.ptr.p_int[j]>0 )
29004 : {
29005 0 : for(i=0; i<=candidatescnt-1; i++)
29006 : {
29007 0 : 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];
29008 0 : state->tmpbasis.ptr.pp_double[i][j] = 0.0;
29009 : }
29010 : }
29011 : }
29012 0 : for(i=0; i<=candidatescnt-1; i++)
29013 : {
29014 0 : for(j=0; j<=n; j++)
29015 : {
29016 0 : state->pdensebatch.ptr.pp_double[i][j] = state->tmpbasis.ptr.pp_double[i][j];
29017 0 : state->sdensebatch.ptr.pp_double[i][j] = state->tmpbasis.ptr.pp_double[i][j];
29018 0 : state->idensebatch.ptr.pp_double[i][j] = state->tmpbasis.ptr.pp_double[i][j];
29019 : }
29020 : }
29021 :
29022 : /*
29023 : * Perform orthogonalization of general linear constraints with respect
29024 : * to each other (constraints in P/S/IBasis are already normalized w.r.t.
29025 : * box constraints). During this process we select strictly active constraints
29026 : * from the candidate set, and drop ones which were detected as redundant
29027 : * during orthogonalization.
29028 : *
29029 : * Orthogonalization is performed with the help of Gram-Schmidt process.
29030 : * Due to accumulation of round-off errors it is beneficial to perform
29031 : * pivoting, i.e. to select candidate vector with largest norm at each
29032 : * step.
29033 : *
29034 : * First (basic) version of the algorithm is:
29035 : * 0. split all constraints into two sets: basis ones (initially empty)
29036 : * and candidate ones (all constraints)
29037 : * 1. fill PBasis with H-normalized candidate constraints, fill
29038 : * corresponding entries of S/IBasis with corresponding
29039 : * (non-normalized) constraints
29040 : * 2. select row of PBasis with largest norm, move it (and its S/IBasis
29041 : * counterparts) to the beginning of the candidate set, H-normalize
29042 : * this row (rows of S/IBasis are normalized using corresponding norms).
29043 : * Stop if largest row is nearly (or exactly) zero.
29044 : * 3. orthogonalize remaining rows of P/S/IBasis with respect to
29045 : * one chosen at step (2). It can be done efficiently using
29046 : * combination of DGEMV/DGER BLAS calls.
29047 : * 4. increase basis size by one, decrease candidate set size by one,
29048 : * goto (2)
29049 : *
29050 : * However, naive implementation of the algorithm above spends significant
29051 : * amount of time in step (2) - selection of row with largest H-norm. Step
29052 : * (3) can be efficiently implemented with optimized BLAS, but we have no
29053 : * optimized BLAS kernels for step(2). And because step (3) changes row norms,
29054 : * step (2) have to be re-calculated every time, which is quite slow.
29055 : *
29056 : * We can save significant amount of calculations by noticing that:
29057 : * * step (3) DECREASES row norms, but never increases it
29058 : * * we can maintain upper bounds for row H-norms is a separate array,
29059 : * use them for initial evaluation of best candidates, and update them
29060 : * after we find some promising row (all bounds are invalidated after
29061 : * step 3, but their old values still carry some information)
29062 : * * it is beneficial re-evaluate bounds only for rows which are
29063 : * significantly (at least few percents) larger than best one found so far
29064 : * * because rows are initially normalized, initial values for upper bounds
29065 : * can be set to 1.0
29066 : */
29067 0 : ae_assert(state->densebatchsize==0, "SAS: integrity check failed", _state);
29068 0 : ae_assert(ae_fp_greater(sactivesets_minnormseparation,(double)(0)), "SAS: integrity check failed", _state);
29069 0 : rvectorsetlengthatleast(&state->tmpnormestimates, candidatescnt, _state);
29070 0 : for(i=0; i<=candidatescnt-1; i++)
29071 : {
29072 0 : state->tmpnormestimates.ptr.p_double[i] = 1.0;
29073 : }
29074 0 : while(state->sparsebatchsize+state->densebatchsize<n)
29075 : {
29076 :
29077 : /*
29078 : * No candidates? We are done!
29079 : */
29080 0 : if( candidatescnt==0 )
29081 : {
29082 0 : break;
29083 : }
29084 :
29085 : /*
29086 : * Find largest vector
29087 : */
29088 0 : vmax = (double)(0);
29089 0 : kmax = -1;
29090 0 : for(i=state->densebatchsize; i<=state->densebatchsize+candidatescnt-1; i++)
29091 : {
29092 :
29093 : /*
29094 : * Use upper bound for row norm for initial evaluation.
29095 : * Skip rows whose upper bound is less than best candidate
29096 : * found so far.
29097 : *
29098 : * NOTE: in fact, we may skip rows whose upper bound is
29099 : * marginally higher than that of best candidate.
29100 : * No need to perform costly re-evaluation in order
29101 : * to get just few percents of improvement.
29102 : */
29103 0 : if( ae_fp_less(state->tmpnormestimates.ptr.p_double[i],vmax*(1+sactivesets_minnormseparation)) )
29104 : {
29105 0 : continue;
29106 : }
29107 :
29108 : /*
29109 : * OK, upper bound is large enough... lets perform full
29110 : * re-evaluation and update of the estimate.
29111 : */
29112 0 : v = 0.0;
29113 0 : for(j=0; j<=n-1; j++)
29114 : {
29115 0 : vv = state->pdensebatch.ptr.pp_double[i][j];
29116 0 : v = v+vv*vv*state->tmpreciph.ptr.p_double[j];
29117 : }
29118 0 : v = ae_sqrt(v, _state);
29119 0 : state->tmpnormestimates.ptr.p_double[i] = v;
29120 :
29121 : /*
29122 : * Now compare with best candidate so far
29123 : */
29124 0 : if( ae_fp_greater(v,vmax) )
29125 : {
29126 0 : vmax = v;
29127 0 : kmax = i;
29128 : }
29129 : }
29130 0 : if( ae_fp_less(vmax,1.0E4*ae_machineepsilon)||kmax<0 )
29131 : {
29132 :
29133 : /*
29134 : * All candidates are either zero or too small (after orthogonalization)
29135 : */
29136 0 : candidatescnt = 0;
29137 0 : break;
29138 : }
29139 :
29140 : /*
29141 : * Candidate is selected for inclusion into basis set.
29142 : *
29143 : * Move candidate row to the beginning of candidate array (which is
29144 : * right past the end of the approved basis). Normalize (for P-basis
29145 : * we perform preconditioner-based normalization, for S-basis - scale
29146 : * based, for I-basis - identity based).
29147 : */
29148 0 : swaprows(&state->pdensebatch, state->densebatchsize, kmax, n+1, _state);
29149 0 : swaprows(&state->sdensebatch, state->densebatchsize, kmax, n+1, _state);
29150 0 : swaprows(&state->idensebatch, state->densebatchsize, kmax, n+1, _state);
29151 0 : swapelements(&state->tmpnormestimates, state->densebatchsize, kmax, _state);
29152 0 : v = 1/vmax;
29153 0 : ae_v_muld(&state->pdensebatch.ptr.pp_double[state->densebatchsize][0], 1, ae_v_len(0,n), v);
29154 0 : v = (double)(0);
29155 0 : for(j=0; j<=n-1; j++)
29156 : {
29157 0 : vv = state->sdensebatch.ptr.pp_double[state->densebatchsize][j]*state->s.ptr.p_double[j];
29158 0 : v = v+vv*vv;
29159 : }
29160 0 : ae_assert(ae_fp_greater(v,(double)(0)), "SActiveSet.RebuildBasis(): integrity check failed, SNorm=0", _state);
29161 0 : v = 1/ae_sqrt(v, _state);
29162 0 : ae_v_muld(&state->sdensebatch.ptr.pp_double[state->densebatchsize][0], 1, ae_v_len(0,n), v);
29163 0 : v = (double)(0);
29164 0 : for(j=0; j<=n-1; j++)
29165 : {
29166 0 : vv = state->idensebatch.ptr.pp_double[state->densebatchsize][j];
29167 0 : v = v+vv*vv;
29168 : }
29169 0 : ae_assert(ae_fp_greater(v,(double)(0)), "SActiveSet.RebuildBasis(): integrity check failed, INorm=0", _state);
29170 0 : v = 1/ae_sqrt(v, _state);
29171 0 : ae_v_muld(&state->idensebatch.ptr.pp_double[state->densebatchsize][0], 1, ae_v_len(0,n), v);
29172 :
29173 : /*
29174 : * Reorthogonalize other candidates with respect to candidate #0:
29175 : * * calculate projections en masse with GEMV()
29176 : * * subtract projections with GER()
29177 : */
29178 0 : rvectorsetlengthatleast(&state->tmp0, candidatescnt-1, _state);
29179 0 : for(j=0; j<=n-1; j++)
29180 : {
29181 0 : state->tmpprodp.ptr.p_double[j] = state->pdensebatch.ptr.pp_double[state->densebatchsize][j]/state->h.ptr.p_double[j];
29182 0 : state->tmpprods.ptr.p_double[j] = state->sdensebatch.ptr.pp_double[state->densebatchsize][j]*ae_sqr(state->s.ptr.p_double[j], _state);
29183 : }
29184 0 : for(j=0; j<=n; j++)
29185 : {
29186 0 : state->tmpcp.ptr.p_double[j] = state->pdensebatch.ptr.pp_double[state->densebatchsize][j];
29187 0 : state->tmpcs.ptr.p_double[j] = state->sdensebatch.ptr.pp_double[state->densebatchsize][j];
29188 0 : state->tmpci.ptr.p_double[j] = state->idensebatch.ptr.pp_double[state->densebatchsize][j];
29189 : }
29190 0 : rmatrixgemv(candidatescnt-1, n, 1.0, &state->pdensebatch, state->densebatchsize+1, 0, 0, &state->tmpprodp, 0, 0.0, &state->tmp0, 0, _state);
29191 0 : rmatrixger(candidatescnt-1, n+1, &state->pdensebatch, state->densebatchsize+1, 0, -1.0, &state->tmp0, 0, &state->tmpcp, 0, _state);
29192 0 : rmatrixgemv(candidatescnt-1, n, 1.0, &state->sdensebatch, state->densebatchsize+1, 0, 0, &state->tmpprods, 0, 0.0, &state->tmp0, 0, _state);
29193 0 : rmatrixger(candidatescnt-1, n+1, &state->sdensebatch, state->densebatchsize+1, 0, -1.0, &state->tmp0, 0, &state->tmpcs, 0, _state);
29194 0 : rmatrixgemv(candidatescnt-1, n, 1.0, &state->idensebatch, state->densebatchsize+1, 0, 0, &state->tmpci, 0, 0.0, &state->tmp0, 0, _state);
29195 0 : rmatrixger(candidatescnt-1, n+1, &state->idensebatch, state->densebatchsize+1, 0, -1.0, &state->tmp0, 0, &state->tmpci, 0, _state);
29196 :
29197 : /*
29198 : * Increase basis, decrease candidates count
29199 : */
29200 0 : inc(&state->densebatchsize, _state);
29201 0 : dec(&candidatescnt, _state);
29202 : }
29203 : }
29204 :
29205 :
29206 : /*************************************************************************
29207 : This function appends new constraints (if possible; sometimes it isn't!)
29208 : to three orthonormal basises for current active set:
29209 : * P-orthogonal one, which is orthogonalized with inner product
29210 : (x,y) = x'*P*y, where P=inv(H) is current preconditioner
29211 : * S-orthogonal one, which is orthogonalized with inner product
29212 : (x,y) = x'*S'*S*y, where S is diagonal scaling matrix
29213 : * I-orthogonal one, which is orthogonalized with standard dot product
29214 :
29215 : NOTE: all sets of orthogonal vectors are guaranteed to have same size.
29216 : P-orthogonal basis is built first, I/S-orthogonal basises are forced
29217 : to have same number of vectors as P-orthogonal one (padded by zero
29218 : vectors if needed).
29219 :
29220 : NOTE: this function may fail to update basis without full recalculation;
29221 : in such case it will set BasisIsReady to False and silently return;
29222 : if it succeeds, it will increase BasisSize.
29223 :
29224 : INPUT PARAMETERS:
29225 : State - active set object
29226 : NewEntries - array[N+NEC+NIC], indexes of constraints being added
29227 : are marked as True; it is responsibility of the caller
29228 : to specify only those constraints which were previously
29229 : inactive; when some constraint is already in the
29230 : active set, algorithm behavior is undefined.
29231 :
29232 : OUTPUT PARAMETERS:
29233 : State - active set object with new basis
29234 :
29235 : -- ALGLIB --
29236 : Copyright 03.10.2017 by Bochkanov Sergey
29237 : *************************************************************************/
29238 0 : void sasappendtobasis(sactiveset* state,
29239 : /* Boolean */ ae_vector* newentries,
29240 : ae_state *_state)
29241 : {
29242 : ae_int_t n;
29243 : ae_int_t nec;
29244 : ae_int_t nic;
29245 : ae_int_t i;
29246 : ae_int_t j;
29247 : ae_int_t t;
29248 : ae_int_t nact;
29249 : double v;
29250 : double vp;
29251 : double vs;
29252 : double vi;
29253 : double initnormp;
29254 : double projnormp;
29255 : double projnorms;
29256 : double projnormi;
29257 :
29258 :
29259 0 : if( !state->basisisready )
29260 : {
29261 0 : return;
29262 : }
29263 0 : n = state->n;
29264 0 : nec = state->nec;
29265 0 : nic = state->nic;
29266 :
29267 : /*
29268 : * Count number of constraints to activate;
29269 : * perform integrity check.
29270 : */
29271 0 : nact = 0;
29272 0 : for(i=0; i<=n-1; i++)
29273 : {
29274 0 : if( newentries->ptr.p_bool[i] )
29275 : {
29276 0 : nact = nact+1;
29277 : }
29278 : }
29279 0 : for(i=n; i<=n+nec-1; i++)
29280 : {
29281 0 : ae_assert(!newentries->ptr.p_bool[i], "SAS: integrity check failed (appendtobasis.0)", _state);
29282 : }
29283 0 : for(i=n+nec; i<=n+nec+nic-1; i++)
29284 : {
29285 0 : if( newentries->ptr.p_bool[i] )
29286 : {
29287 0 : nact = nact+1;
29288 : }
29289 : }
29290 0 : if( nact+state->basisage>sactivesets_maxbasisage )
29291 : {
29292 0 : state->basisisready = ae_false;
29293 0 : return;
29294 : }
29295 :
29296 : /*
29297 : * Resize basis matrices if needed
29298 : */
29299 0 : rmatrixgrowrowsto(&state->pdensebatch, state->densebatchsize+nact, n+1, _state);
29300 0 : rmatrixgrowrowsto(&state->sdensebatch, state->densebatchsize+nact, n+1, _state);
29301 0 : rmatrixgrowrowsto(&state->idensebatch, state->densebatchsize+nact, n+1, _state);
29302 :
29303 : /*
29304 : * Try adding recommended entries to basis.
29305 : * If reorthogonalization removes too much of candidate constraint,
29306 : * we will invalidate basis and try to rebuild it from scratch.
29307 : */
29308 0 : rvectorsetlengthatleast(&state->tmp0, n+1, _state);
29309 0 : rvectorsetlengthatleast(&state->tmpcp, n+1, _state);
29310 0 : rvectorsetlengthatleast(&state->tmpcs, n+1, _state);
29311 0 : rvectorsetlengthatleast(&state->tmpci, n+1, _state);
29312 0 : rvectorsetlengthatleast(&state->tmpprodp, n, _state);
29313 0 : rvectorsetlengthatleast(&state->tmpprods, n, _state);
29314 0 : for(t=0; t<=n+nec+nic-1; t++)
29315 : {
29316 0 : if( newentries->ptr.p_bool[t] )
29317 : {
29318 :
29319 : /*
29320 : * Basis is full? Quick skip!
29321 : */
29322 0 : if( state->sparsebatchsize+state->densebatchsize>=n )
29323 : {
29324 0 : ae_assert(state->sparsebatchsize+state->densebatchsize==n, "SAS: integrity check failed (sasappendtobasis)", _state);
29325 0 : break;
29326 : }
29327 :
29328 : /*
29329 : * Copy constraint to temporary storage.
29330 : */
29331 0 : if( t<n )
29332 : {
29333 :
29334 : /*
29335 : * Copy box constraint
29336 : */
29337 0 : for(j=0; j<=n; j++)
29338 : {
29339 0 : state->tmp0.ptr.p_double[j] = (double)(0);
29340 : }
29341 0 : state->tmp0.ptr.p_double[t] = 1.0;
29342 0 : state->tmp0.ptr.p_double[n] = state->xc.ptr.p_double[t];
29343 : }
29344 : else
29345 : {
29346 :
29347 : /*
29348 : * Copy general linear constraint
29349 : */
29350 0 : for(j=0; j<=n; j++)
29351 : {
29352 0 : state->tmp0.ptr.p_double[j] = state->cleic.ptr.pp_double[t-n][j];
29353 : }
29354 : }
29355 :
29356 : /*
29357 : * Calculate initial norm (preconditioner is used for norm calculation).
29358 : */
29359 0 : initnormp = 0.0;
29360 0 : for(j=0; j<=n-1; j++)
29361 : {
29362 0 : v = state->tmp0.ptr.p_double[j];
29363 0 : initnormp = initnormp+v*v/state->h.ptr.p_double[j];
29364 : }
29365 0 : initnormp = ae_sqrt(initnormp, _state);
29366 0 : if( ae_fp_eq(initnormp,(double)(0)) )
29367 : {
29368 :
29369 : /*
29370 : * Well, it is not expected. Let's just rebuild basis
29371 : * from scratch and forget about this strange situation...
29372 : */
29373 0 : state->basisisready = ae_false;
29374 0 : return;
29375 : }
29376 :
29377 : /*
29378 : * Orthogonalize Tmp0 w.r.t. sparse batch (box constraints stored in sparse storage).
29379 : *
29380 : * Copy to TmpCP/TmpCS/TmpCI (P for preconditioner-based inner product
29381 : * used for orthogonalization, S for scale-based orthogonalization,
29382 : * I for "traditional" inner product used for Gram-Schmidt orthogonalization).
29383 : */
29384 0 : for(i=0; i<=state->sparsebatchsize-1; i++)
29385 : {
29386 0 : j = state->sparsebatch.ptr.p_int[i];
29387 0 : state->tmp0.ptr.p_double[n] = state->tmp0.ptr.p_double[n]-state->tmp0.ptr.p_double[j]*state->xc.ptr.p_double[j];
29388 0 : state->tmp0.ptr.p_double[j] = 0.0;
29389 : }
29390 0 : for(j=0; j<=n; j++)
29391 : {
29392 0 : state->tmpcp.ptr.p_double[j] = state->tmp0.ptr.p_double[j];
29393 0 : state->tmpcs.ptr.p_double[j] = state->tmp0.ptr.p_double[j];
29394 0 : state->tmpci.ptr.p_double[j] = state->tmp0.ptr.p_double[j];
29395 : }
29396 :
29397 : /*
29398 : * Orthogonalize TmpCP/S/I with respect to active linear constraints from dense batch.
29399 : * Corresponding norm (preconditioner, scale, identity) is used in each case.
29400 : */
29401 0 : for(j=0; j<=n-1; j++)
29402 : {
29403 0 : state->tmpprodp.ptr.p_double[j] = 1/state->h.ptr.p_double[j];
29404 0 : state->tmpprods.ptr.p_double[j] = ae_sqr(state->s.ptr.p_double[j], _state);
29405 : }
29406 0 : for(i=0; i<=state->densebatchsize-1; i++)
29407 : {
29408 0 : vp = (double)(0);
29409 0 : vs = (double)(0);
29410 0 : vi = (double)(0);
29411 0 : for(j=0; j<=n-1; j++)
29412 : {
29413 0 : vp = vp+state->pdensebatch.ptr.pp_double[i][j]*state->tmpcp.ptr.p_double[j]*state->tmpprodp.ptr.p_double[j];
29414 0 : vs = vs+state->sdensebatch.ptr.pp_double[i][j]*state->tmpcs.ptr.p_double[j]*state->tmpprods.ptr.p_double[j];
29415 0 : vi = vi+state->idensebatch.ptr.pp_double[i][j]*state->tmpci.ptr.p_double[j];
29416 : }
29417 0 : ae_v_subd(&state->tmpcp.ptr.p_double[0], 1, &state->pdensebatch.ptr.pp_double[i][0], 1, ae_v_len(0,n), vp);
29418 0 : ae_v_subd(&state->tmpcs.ptr.p_double[0], 1, &state->sdensebatch.ptr.pp_double[i][0], 1, ae_v_len(0,n), vs);
29419 0 : ae_v_subd(&state->tmpci.ptr.p_double[0], 1, &state->idensebatch.ptr.pp_double[i][0], 1, ae_v_len(0,n), vi);
29420 : }
29421 0 : projnormp = 0.0;
29422 0 : projnorms = 0.0;
29423 0 : projnormi = 0.0;
29424 0 : for(j=0; j<=n-1; j++)
29425 : {
29426 0 : projnormp = projnormp+ae_sqr(state->tmpcp.ptr.p_double[j], _state)/state->h.ptr.p_double[j];
29427 0 : projnorms = projnorms+ae_sqr(state->tmpcs.ptr.p_double[j], _state)*ae_sqr(state->s.ptr.p_double[j], _state);
29428 0 : projnormi = projnormi+ae_sqr(state->tmpci.ptr.p_double[j], _state);
29429 : }
29430 0 : projnormp = ae_sqrt(projnormp, _state);
29431 0 : projnorms = ae_sqrt(projnorms, _state);
29432 0 : projnormi = ae_sqrt(projnormi, _state);
29433 0 : if( ae_fp_less_eq(projnormp,sactivesets_maxbasisdecay*initnormp) )
29434 : {
29435 0 : state->basisisready = ae_false;
29436 0 : return;
29437 :
29438 : /*
29439 : * Nearly zero row, skip
29440 : */
29441 : }
29442 0 : ae_assert(ae_fp_greater(projnormp,(double)(0)), "SAS: integrity check failed, ProjNormP=0", _state);
29443 0 : ae_assert(ae_fp_greater(projnorms,(double)(0)), "SAS: integrity check failed, ProjNormS=0", _state);
29444 0 : ae_assert(ae_fp_greater(projnormi,(double)(0)), "SAS: integrity check failed, ProjNormI=0", _state);
29445 0 : v = 1/projnormp;
29446 0 : ae_v_moved(&state->pdensebatch.ptr.pp_double[state->densebatchsize][0], 1, &state->tmpcp.ptr.p_double[0], 1, ae_v_len(0,n), v);
29447 0 : v = 1/projnorms;
29448 0 : ae_v_moved(&state->sdensebatch.ptr.pp_double[state->densebatchsize][0], 1, &state->tmpcs.ptr.p_double[0], 1, ae_v_len(0,n), v);
29449 0 : v = 1/projnormi;
29450 0 : ae_v_moved(&state->idensebatch.ptr.pp_double[state->densebatchsize][0], 1, &state->tmpci.ptr.p_double[0], 1, ae_v_len(0,n), v);
29451 :
29452 : /*
29453 : * Increase set size
29454 : */
29455 0 : inc(&state->densebatchsize, _state);
29456 0 : inc(&state->basisage, _state);
29457 : }
29458 : }
29459 : }
29460 :
29461 :
29462 : /*************************************************************************
29463 : This subroutine calculates preconditioned descent direction subject to
29464 : current active set.
29465 :
29466 : INPUT PARAMETERS:
29467 : State - active set object
29468 : G - array[N], gradient
29469 : H - array[N], Hessian matrix
29470 : HA - active constraints orthogonalized in such way
29471 : that HA*inv(H)*HA'= I.
29472 : Normalize- whether we need normalized descent or not
29473 : D - possibly preallocated buffer; automatically resized.
29474 :
29475 : OUTPUT PARAMETERS:
29476 : D - descent direction projected onto current active set.
29477 : Components of D which correspond to active boundary
29478 : constraints are forced to be exactly zero.
29479 : In case D is non-zero and Normalize is True, it is
29480 : normalized to have unit norm.
29481 :
29482 : NOTE: if we have N active constraints, D is explicitly set to zero.
29483 :
29484 : -- ALGLIB --
29485 : Copyright 21.12.2012 by Bochkanov Sergey
29486 : *************************************************************************/
29487 0 : static void sactivesets_constraineddescent(sactiveset* state,
29488 : /* Real */ ae_vector* g,
29489 : /* Real */ ae_vector* h,
29490 : /* Real */ ae_matrix* ha,
29491 : ae_bool normalize,
29492 : /* Real */ ae_vector* d,
29493 : ae_state *_state)
29494 : {
29495 : ae_int_t i;
29496 : ae_int_t j;
29497 : ae_int_t n;
29498 : double v;
29499 :
29500 :
29501 0 : ae_assert(state->algostate==1, "SAS: internal error in ConstrainedDescent() - not in optimization mode", _state);
29502 0 : ae_assert(state->basisisready, "SAS: internal error in ConstrainedDescent() - no basis", _state);
29503 0 : n = state->n;
29504 0 : rvectorsetlengthatleast(d, n, _state);
29505 :
29506 : /*
29507 : * Calculate preconditioned constrained descent direction:
29508 : *
29509 : * d := -inv(H)*( g - HA'*(HA*inv(H)*g) )
29510 : *
29511 : * Formula above always gives direction which is orthogonal to rows of HA.
29512 : * You can verify it by multiplication of both sides by HA[i] (I-th row),
29513 : * taking into account that HA*inv(H)*HA'= I (by definition of HA - it is
29514 : * orthogonal basis with inner product given by inv(H)).
29515 : */
29516 0 : for(i=0; i<=n-1; i++)
29517 : {
29518 0 : d->ptr.p_double[i] = g->ptr.p_double[i];
29519 : }
29520 0 : for(i=0; i<=state->densebatchsize-1; i++)
29521 : {
29522 0 : v = 0.0;
29523 0 : for(j=0; j<=n-1; j++)
29524 : {
29525 0 : v = v+ha->ptr.pp_double[i][j]*d->ptr.p_double[j]/h->ptr.p_double[j];
29526 : }
29527 0 : ae_v_subd(&d->ptr.p_double[0], 1, &ha->ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v);
29528 : }
29529 0 : for(i=0; i<=n-1; i++)
29530 : {
29531 0 : if( state->cstatus.ptr.p_int[i]>0 )
29532 : {
29533 0 : d->ptr.p_double[i] = (double)(0);
29534 : }
29535 : }
29536 0 : v = 0.0;
29537 0 : for(i=0; i<=n-1; i++)
29538 : {
29539 0 : d->ptr.p_double[i] = -d->ptr.p_double[i]/h->ptr.p_double[i];
29540 0 : v = v+ae_sqr(d->ptr.p_double[i], _state);
29541 : }
29542 0 : v = ae_sqrt(v, _state);
29543 0 : if( state->sparsebatchsize+state->densebatchsize>=n )
29544 : {
29545 0 : v = (double)(0);
29546 0 : for(i=0; i<=n-1; i++)
29547 : {
29548 0 : d->ptr.p_double[i] = (double)(0);
29549 : }
29550 : }
29551 0 : if( normalize&&ae_fp_greater(v,(double)(0)) )
29552 : {
29553 0 : for(i=0; i<=n-1; i++)
29554 : {
29555 0 : d->ptr.p_double[i] = d->ptr.p_double[i]/v;
29556 : }
29557 : }
29558 0 : }
29559 :
29560 :
29561 : /*************************************************************************
29562 : This function recalculates constraints - activates and deactivates them
29563 : according to gradient value at current point.
29564 :
29565 : Algorithm assumes that we want to make Quasi-Newton step from current
29566 : point with diagonal Quasi-Newton matrix H. Constraints are activated and
29567 : deactivated in such way that we won't violate any constraint by step.
29568 :
29569 : Only already "active" and "candidate" elements of ActiveSet are examined;
29570 : constraints which are not active are not examined.
29571 :
29572 : INPUT PARAMETERS:
29573 : State - active set object
29574 : GC - array[N], gradient at XC
29575 : H - array[N], Hessian matrix
29576 :
29577 : OUTPUT PARAMETERS:
29578 : State - active set object, with new set of constraint
29579 :
29580 : -- ALGLIB --
29581 : Copyright 26.09.2012 by Bochkanov Sergey
29582 : *************************************************************************/
29583 0 : static void sactivesets_reactivateconstraints(sactiveset* state,
29584 : /* Real */ ae_vector* gc,
29585 : /* Real */ ae_vector* h,
29586 : ae_state *_state)
29587 : {
29588 : ae_int_t n;
29589 : ae_int_t nec;
29590 : ae_int_t nic;
29591 : ae_int_t i;
29592 : ae_int_t j;
29593 : ae_int_t idx0;
29594 : ae_int_t idx1;
29595 : double v;
29596 : ae_int_t nactivebnd;
29597 : ae_int_t nactivelin;
29598 : ae_int_t nactiveconstraints;
29599 : double rowscale;
29600 :
29601 :
29602 0 : ae_assert(state->algostate==1, "SASReactivateConstraintsPrec: must be in optimization mode", _state);
29603 :
29604 : /*
29605 : * Prepare
29606 : */
29607 0 : n = state->n;
29608 0 : nec = state->nec;
29609 0 : nic = state->nic;
29610 0 : state->basisisready = ae_false;
29611 :
29612 : /*
29613 : * Handle important special case - no linear constraints,
29614 : * only boundary constraints are present
29615 : */
29616 0 : if( nec+nic==0 )
29617 : {
29618 0 : for(i=0; i<=n-1; i++)
29619 : {
29620 0 : 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]) )
29621 : {
29622 0 : state->cstatus.ptr.p_int[i] = 1;
29623 0 : continue;
29624 : }
29625 0 : 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],(double)(0)) )
29626 : {
29627 0 : state->cstatus.ptr.p_int[i] = 1;
29628 0 : continue;
29629 : }
29630 0 : 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],(double)(0)) )
29631 : {
29632 0 : state->cstatus.ptr.p_int[i] = 1;
29633 0 : continue;
29634 : }
29635 0 : state->cstatus.ptr.p_int[i] = -1;
29636 : }
29637 0 : return;
29638 : }
29639 :
29640 : /*
29641 : * General case.
29642 : * Allocate temporaries.
29643 : */
29644 0 : rvectorsetlengthatleast(&state->rctmpg, n, _state);
29645 0 : rvectorsetlengthatleast(&state->rctmprightpart, n, _state);
29646 0 : rvectorsetlengthatleast(&state->rctmps, n, _state);
29647 0 : rmatrixsetlengthatleast(&state->rctmpdense0, n, nec+nic, _state);
29648 0 : rmatrixsetlengthatleast(&state->rctmpdense1, n, nec+nic, _state);
29649 0 : bvectorsetlengthatleast(&state->rctmpisequality, n+nec+nic, _state);
29650 0 : ivectorsetlengthatleast(&state->rctmpconstraintidx, n+nec+nic, _state);
29651 :
29652 : /*
29653 : * Calculate descent direction
29654 : */
29655 0 : ae_v_moveneg(&state->rctmpg.ptr.p_double[0], 1, &gc->ptr.p_double[0], 1, ae_v_len(0,n-1));
29656 :
29657 : /*
29658 : * Determine candidates to the active set.
29659 : *
29660 : * After this block constraints become either "inactive" (CStatus[i]<0)
29661 : * or "candidates" (CStatus[i]=0). Previously active constraints always
29662 : * become "candidates".
29663 : */
29664 0 : for(i=0; i<=n-1; i++)
29665 : {
29666 0 : state->cstatus.ptr.p_int[i] = -1;
29667 : }
29668 0 : for(i=n; i<=n+nec+nic-1; i++)
29669 : {
29670 0 : if( state->cstatus.ptr.p_int[i]>0 )
29671 : {
29672 0 : state->cstatus.ptr.p_int[i] = 0;
29673 : }
29674 : else
29675 : {
29676 0 : state->cstatus.ptr.p_int[i] = -1;
29677 : }
29678 : }
29679 0 : nactiveconstraints = 0;
29680 0 : nactivebnd = 0;
29681 0 : nactivelin = 0;
29682 0 : for(i=0; i<=n-1; i++)
29683 : {
29684 :
29685 : /*
29686 : * Activate boundary constraints:
29687 : * * copy constraint index to RCTmpConstraintIdx
29688 : * * set corresponding element of CStatus[] to "candidate"
29689 : * * fill RCTmpS by either +1 (lower bound) or -1 (upper bound)
29690 : * * set RCTmpIsEquality to False (BndL<BndU) or True (BndL=BndU)
29691 : * * increase counters
29692 : */
29693 0 : 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]) )
29694 : {
29695 :
29696 : /*
29697 : * Equality constraint is activated
29698 : */
29699 0 : state->rctmpconstraintidx.ptr.p_int[nactiveconstraints] = i;
29700 0 : state->cstatus.ptr.p_int[i] = 0;
29701 0 : state->rctmps.ptr.p_double[i] = 1.0;
29702 0 : state->rctmpisequality.ptr.p_bool[nactiveconstraints] = ae_true;
29703 0 : nactiveconstraints = nactiveconstraints+1;
29704 0 : nactivebnd = nactivebnd+1;
29705 0 : continue;
29706 : }
29707 0 : if( state->hasbndl.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndl.ptr.p_double[i]) )
29708 : {
29709 :
29710 : /*
29711 : * Lower bound is activated
29712 : */
29713 0 : state->rctmpconstraintidx.ptr.p_int[nactiveconstraints] = i;
29714 0 : state->cstatus.ptr.p_int[i] = 0;
29715 0 : state->rctmps.ptr.p_double[i] = -1.0;
29716 0 : state->rctmpisequality.ptr.p_bool[nactiveconstraints] = ae_false;
29717 0 : nactiveconstraints = nactiveconstraints+1;
29718 0 : nactivebnd = nactivebnd+1;
29719 0 : continue;
29720 : }
29721 0 : if( state->hasbndu.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
29722 : {
29723 :
29724 : /*
29725 : * Upper bound is activated
29726 : */
29727 0 : state->rctmpconstraintidx.ptr.p_int[nactiveconstraints] = i;
29728 0 : state->cstatus.ptr.p_int[i] = 0;
29729 0 : state->rctmps.ptr.p_double[i] = 1.0;
29730 0 : state->rctmpisequality.ptr.p_bool[nactiveconstraints] = ae_false;
29731 0 : nactiveconstraints = nactiveconstraints+1;
29732 0 : nactivebnd = nactivebnd+1;
29733 0 : continue;
29734 : }
29735 : }
29736 0 : for(i=0; i<=nec+nic-1; i++)
29737 : {
29738 0 : if( i>=nec&&state->cstatus.ptr.p_int[n+i]<0 )
29739 : {
29740 :
29741 : /*
29742 : * Inequality constraints are skipped if both (a) constraint was
29743 : * not active, and (b) we are too far away from the boundary.
29744 : */
29745 0 : rowscale = 0.0;
29746 0 : v = -state->cleic.ptr.pp_double[i][n];
29747 0 : for(j=0; j<=n-1; j++)
29748 : {
29749 0 : v = v+state->cleic.ptr.pp_double[i][j]*state->xc.ptr.p_double[j];
29750 0 : rowscale = ae_maxreal(rowscale, ae_fabs(state->cleic.ptr.pp_double[i][j]*state->s.ptr.p_double[j], _state), _state);
29751 : }
29752 0 : if( ae_fp_less_eq(v,-1.0E5*ae_machineepsilon*rowscale) )
29753 : {
29754 :
29755 : /*
29756 : * NOTE: it is important to check for non-strict inequality
29757 : * because we have to correctly handle zero constraint
29758 : * 0*x<=0
29759 : */
29760 0 : continue;
29761 : }
29762 : }
29763 0 : 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));
29764 0 : state->rctmpconstraintidx.ptr.p_int[nactiveconstraints] = n+i;
29765 0 : state->cstatus.ptr.p_int[n+i] = 0;
29766 0 : state->rctmpisequality.ptr.p_bool[nactiveconstraints] = i<nec;
29767 0 : nactiveconstraints = nactiveconstraints+1;
29768 0 : nactivelin = nactivelin+1;
29769 : }
29770 :
29771 : /*
29772 : * Skip if no "candidate" constraints was found
29773 : */
29774 0 : if( nactiveconstraints==0 )
29775 : {
29776 0 : for(i=0; i<=n-1; i++)
29777 : {
29778 0 : 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]) )
29779 : {
29780 0 : state->cstatus.ptr.p_int[i] = 1;
29781 0 : continue;
29782 : }
29783 0 : 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],(double)(0)) )
29784 : {
29785 0 : state->cstatus.ptr.p_int[i] = 1;
29786 0 : continue;
29787 : }
29788 0 : 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],(double)(0)) )
29789 : {
29790 0 : state->cstatus.ptr.p_int[i] = 1;
29791 0 : continue;
29792 : }
29793 : }
29794 0 : return;
29795 : }
29796 :
29797 : /*
29798 : * General case.
29799 : *
29800 : * APPROACH TO CONSTRAINTS ACTIVATION/DEACTIVATION
29801 : *
29802 : * We have NActiveConstraints "candidates": NActiveBnd boundary candidates,
29803 : * NActiveLin linear candidates. Indexes of boundary constraints are stored
29804 : * in RCTmpConstraintIdx[0:NActiveBnd-1], indexes of linear ones are stored
29805 : * in RCTmpConstraintIdx[NActiveBnd:NActiveBnd+NActiveLin-1]. Some of the
29806 : * constraints are equality ones, some are inequality - as specified by
29807 : * RCTmpIsEquality[i].
29808 : *
29809 : * Now we have to determine active subset of "candidates" set. In order to
29810 : * do so we solve following constrained minimization problem:
29811 : * ( )^2
29812 : * min ( SUM(lambda[i]*A[i]) + G )
29813 : * ( )
29814 : * Here:
29815 : * * G is a gradient (column vector)
29816 : * * A[i] is a column vector, linear (left) part of I-th constraint.
29817 : * I=0..NActiveConstraints-1, first NActiveBnd elements of A are just
29818 : * subset of identity matrix (boundary constraints), next NActiveLin
29819 : * elements are subset of rows of the matrix of general linear constraints.
29820 : * * lambda[i] is a Lagrange multiplier corresponding to I-th constraint
29821 : *
29822 : * NOTE: for preconditioned setting A is replaced by A*H^(-0.5), G is
29823 : * replaced by G*H^(-0.5). We apply this scaling at the last stage,
29824 : * before passing data to NNLS solver.
29825 : *
29826 : * Minimization is performed subject to non-negativity constraints on
29827 : * lambda[i] corresponding to inequality constraints. Inequality constraints
29828 : * which correspond to non-zero lambda are activated, equality constraints
29829 : * are always considered active.
29830 : *
29831 : * Informally speaking, we "decompose" descent direction -G and represent
29832 : * it as sum of constraint vectors and "residual" part (which is equal to
29833 : * the actual descent direction subject to constraints).
29834 : *
29835 : * SOLUTION OF THE NNLS PROBLEM
29836 : *
29837 : * We solve this optimization problem with Non-Negative Least Squares solver,
29838 : * which can efficiently solve least squares problems of the form
29839 : *
29840 : * ( [ I | AU ] )^2
29841 : * min ( [ | ]*x-b ) s.t. non-negativity constraints on some x[i]
29842 : * ( [ 0 | AL ] )
29843 : *
29844 : * In order to use this solver we have to rearrange rows of A[] and G in
29845 : * such way that first NActiveBnd columns of A store identity matrix (before
29846 : * sorting non-zero elements are randomly distributed in the first NActiveBnd
29847 : * columns of A, during sorting we move them to first NActiveBnd rows).
29848 : *
29849 : * Then we create instance of NNLS solver (we reuse instance left from the
29850 : * previous run of the optimization problem) and solve NNLS problem.
29851 : */
29852 0 : idx0 = 0;
29853 0 : idx1 = nactivebnd;
29854 0 : for(i=0; i<=n-1; i++)
29855 : {
29856 0 : if( state->cstatus.ptr.p_int[i]>=0 )
29857 : {
29858 0 : v = 1/ae_sqrt(h->ptr.p_double[i], _state);
29859 0 : for(j=0; j<=nactivelin-1; j++)
29860 : {
29861 0 : state->rctmpdense1.ptr.pp_double[idx0][j] = state->rctmpdense0.ptr.pp_double[i][j]/state->rctmps.ptr.p_double[i]*v;
29862 : }
29863 0 : state->rctmprightpart.ptr.p_double[idx0] = state->rctmpg.ptr.p_double[i]/state->rctmps.ptr.p_double[i]*v;
29864 0 : idx0 = idx0+1;
29865 : }
29866 : else
29867 : {
29868 0 : v = 1/ae_sqrt(h->ptr.p_double[i], _state);
29869 0 : for(j=0; j<=nactivelin-1; j++)
29870 : {
29871 0 : state->rctmpdense1.ptr.pp_double[idx1][j] = state->rctmpdense0.ptr.pp_double[i][j]*v;
29872 : }
29873 0 : state->rctmprightpart.ptr.p_double[idx1] = state->rctmpg.ptr.p_double[i]*v;
29874 0 : idx1 = idx1+1;
29875 : }
29876 : }
29877 0 : snnlsinit(n, ae_minint(nec+nic, n, _state), n, &state->solver, _state);
29878 0 : snnlssetproblem(&state->solver, &state->rctmpdense1, &state->rctmprightpart, nactivebnd, nactiveconstraints-nactivebnd, n, _state);
29879 0 : for(i=0; i<=nactiveconstraints-1; i++)
29880 : {
29881 0 : if( state->rctmpisequality.ptr.p_bool[i] )
29882 : {
29883 0 : snnlsdropnnc(&state->solver, i, _state);
29884 : }
29885 : }
29886 0 : snnlssolve(&state->solver, &state->rctmplambdas, _state);
29887 :
29888 : /*
29889 : * After solution of the problem we activate equality constraints (always active)
29890 : * and inequality constraints with non-zero Lagrange multipliers. Then we reorthogonalize
29891 : * active constraints.
29892 : */
29893 0 : for(i=0; i<=n+nec+nic-1; i++)
29894 : {
29895 0 : state->cstatus.ptr.p_int[i] = -1;
29896 : }
29897 0 : for(i=0; i<=nactiveconstraints-1; i++)
29898 : {
29899 0 : if( state->rctmpisequality.ptr.p_bool[i]||ae_fp_greater(state->rctmplambdas.ptr.p_double[i],(double)(0)) )
29900 : {
29901 0 : state->cstatus.ptr.p_int[state->rctmpconstraintidx.ptr.p_int[i]] = 1;
29902 : }
29903 : else
29904 : {
29905 0 : state->cstatus.ptr.p_int[state->rctmpconstraintidx.ptr.p_int[i]] = 0;
29906 : }
29907 : }
29908 0 : sasrebuildbasis(state, _state);
29909 : }
29910 :
29911 :
29912 0 : void _sactiveset_init(void* _p, ae_state *_state, ae_bool make_automatic)
29913 : {
29914 0 : sactiveset *p = (sactiveset*)_p;
29915 0 : ae_touch_ptr((void*)p);
29916 0 : ae_vector_init(&p->xc, 0, DT_REAL, _state, make_automatic);
29917 0 : ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic);
29918 0 : ae_vector_init(&p->h, 0, DT_REAL, _state, make_automatic);
29919 0 : ae_vector_init(&p->cstatus, 0, DT_INT, _state, make_automatic);
29920 0 : ae_matrix_init(&p->sdensebatch, 0, 0, DT_REAL, _state, make_automatic);
29921 0 : ae_matrix_init(&p->pdensebatch, 0, 0, DT_REAL, _state, make_automatic);
29922 0 : ae_matrix_init(&p->idensebatch, 0, 0, DT_REAL, _state, make_automatic);
29923 0 : ae_vector_init(&p->sparsebatch, 0, DT_INT, _state, make_automatic);
29924 0 : ae_vector_init(&p->hasbndl, 0, DT_BOOL, _state, make_automatic);
29925 0 : ae_vector_init(&p->hasbndu, 0, DT_BOOL, _state, make_automatic);
29926 0 : ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic);
29927 0 : ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic);
29928 0 : ae_matrix_init(&p->cleic, 0, 0, DT_REAL, _state, make_automatic);
29929 0 : ae_vector_init(&p->mtnew, 0, DT_BOOL, _state, make_automatic);
29930 0 : ae_vector_init(&p->mtx, 0, DT_REAL, _state, make_automatic);
29931 0 : ae_vector_init(&p->mtas, 0, DT_INT, _state, make_automatic);
29932 0 : ae_vector_init(&p->cdtmp, 0, DT_REAL, _state, make_automatic);
29933 0 : ae_vector_init(&p->corrtmp, 0, DT_REAL, _state, make_automatic);
29934 0 : ae_vector_init(&p->unitdiagonal, 0, DT_REAL, _state, make_automatic);
29935 0 : _snnlssolver_init(&p->solver, _state, make_automatic);
29936 0 : ae_vector_init(&p->scntmp, 0, DT_REAL, _state, make_automatic);
29937 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
29938 0 : ae_vector_init(&p->tmpfeas, 0, DT_REAL, _state, make_automatic);
29939 0 : ae_matrix_init(&p->tmpm0, 0, 0, DT_REAL, _state, make_automatic);
29940 0 : ae_vector_init(&p->rctmps, 0, DT_REAL, _state, make_automatic);
29941 0 : ae_vector_init(&p->rctmpg, 0, DT_REAL, _state, make_automatic);
29942 0 : ae_vector_init(&p->rctmprightpart, 0, DT_REAL, _state, make_automatic);
29943 0 : ae_matrix_init(&p->rctmpdense0, 0, 0, DT_REAL, _state, make_automatic);
29944 0 : ae_matrix_init(&p->rctmpdense1, 0, 0, DT_REAL, _state, make_automatic);
29945 0 : ae_vector_init(&p->rctmpisequality, 0, DT_BOOL, _state, make_automatic);
29946 0 : ae_vector_init(&p->rctmpconstraintidx, 0, DT_INT, _state, make_automatic);
29947 0 : ae_vector_init(&p->rctmplambdas, 0, DT_REAL, _state, make_automatic);
29948 0 : ae_matrix_init(&p->tmpbasis, 0, 0, DT_REAL, _state, make_automatic);
29949 0 : ae_vector_init(&p->tmpnormestimates, 0, DT_REAL, _state, make_automatic);
29950 0 : ae_vector_init(&p->tmpreciph, 0, DT_REAL, _state, make_automatic);
29951 0 : ae_vector_init(&p->tmpprodp, 0, DT_REAL, _state, make_automatic);
29952 0 : ae_vector_init(&p->tmpprods, 0, DT_REAL, _state, make_automatic);
29953 0 : ae_vector_init(&p->tmpcp, 0, DT_REAL, _state, make_automatic);
29954 0 : ae_vector_init(&p->tmpcs, 0, DT_REAL, _state, make_automatic);
29955 0 : ae_vector_init(&p->tmpci, 0, DT_REAL, _state, make_automatic);
29956 0 : }
29957 :
29958 :
29959 0 : void _sactiveset_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
29960 : {
29961 0 : sactiveset *dst = (sactiveset*)_dst;
29962 0 : sactiveset *src = (sactiveset*)_src;
29963 0 : dst->n = src->n;
29964 0 : dst->algostate = src->algostate;
29965 0 : ae_vector_init_copy(&dst->xc, &src->xc, _state, make_automatic);
29966 0 : dst->hasxc = src->hasxc;
29967 0 : ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic);
29968 0 : ae_vector_init_copy(&dst->h, &src->h, _state, make_automatic);
29969 0 : ae_vector_init_copy(&dst->cstatus, &src->cstatus, _state, make_automatic);
29970 0 : dst->basisisready = src->basisisready;
29971 0 : ae_matrix_init_copy(&dst->sdensebatch, &src->sdensebatch, _state, make_automatic);
29972 0 : ae_matrix_init_copy(&dst->pdensebatch, &src->pdensebatch, _state, make_automatic);
29973 0 : ae_matrix_init_copy(&dst->idensebatch, &src->idensebatch, _state, make_automatic);
29974 0 : dst->densebatchsize = src->densebatchsize;
29975 0 : ae_vector_init_copy(&dst->sparsebatch, &src->sparsebatch, _state, make_automatic);
29976 0 : dst->sparsebatchsize = src->sparsebatchsize;
29977 0 : dst->basisage = src->basisage;
29978 0 : dst->feasinitpt = src->feasinitpt;
29979 0 : dst->constraintschanged = src->constraintschanged;
29980 0 : ae_vector_init_copy(&dst->hasbndl, &src->hasbndl, _state, make_automatic);
29981 0 : ae_vector_init_copy(&dst->hasbndu, &src->hasbndu, _state, make_automatic);
29982 0 : ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic);
29983 0 : ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic);
29984 0 : ae_matrix_init_copy(&dst->cleic, &src->cleic, _state, make_automatic);
29985 0 : dst->nec = src->nec;
29986 0 : dst->nic = src->nic;
29987 0 : ae_vector_init_copy(&dst->mtnew, &src->mtnew, _state, make_automatic);
29988 0 : ae_vector_init_copy(&dst->mtx, &src->mtx, _state, make_automatic);
29989 0 : ae_vector_init_copy(&dst->mtas, &src->mtas, _state, make_automatic);
29990 0 : ae_vector_init_copy(&dst->cdtmp, &src->cdtmp, _state, make_automatic);
29991 0 : ae_vector_init_copy(&dst->corrtmp, &src->corrtmp, _state, make_automatic);
29992 0 : ae_vector_init_copy(&dst->unitdiagonal, &src->unitdiagonal, _state, make_automatic);
29993 0 : _snnlssolver_init_copy(&dst->solver, &src->solver, _state, make_automatic);
29994 0 : ae_vector_init_copy(&dst->scntmp, &src->scntmp, _state, make_automatic);
29995 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
29996 0 : ae_vector_init_copy(&dst->tmpfeas, &src->tmpfeas, _state, make_automatic);
29997 0 : ae_matrix_init_copy(&dst->tmpm0, &src->tmpm0, _state, make_automatic);
29998 0 : ae_vector_init_copy(&dst->rctmps, &src->rctmps, _state, make_automatic);
29999 0 : ae_vector_init_copy(&dst->rctmpg, &src->rctmpg, _state, make_automatic);
30000 0 : ae_vector_init_copy(&dst->rctmprightpart, &src->rctmprightpart, _state, make_automatic);
30001 0 : ae_matrix_init_copy(&dst->rctmpdense0, &src->rctmpdense0, _state, make_automatic);
30002 0 : ae_matrix_init_copy(&dst->rctmpdense1, &src->rctmpdense1, _state, make_automatic);
30003 0 : ae_vector_init_copy(&dst->rctmpisequality, &src->rctmpisequality, _state, make_automatic);
30004 0 : ae_vector_init_copy(&dst->rctmpconstraintidx, &src->rctmpconstraintidx, _state, make_automatic);
30005 0 : ae_vector_init_copy(&dst->rctmplambdas, &src->rctmplambdas, _state, make_automatic);
30006 0 : ae_matrix_init_copy(&dst->tmpbasis, &src->tmpbasis, _state, make_automatic);
30007 0 : ae_vector_init_copy(&dst->tmpnormestimates, &src->tmpnormestimates, _state, make_automatic);
30008 0 : ae_vector_init_copy(&dst->tmpreciph, &src->tmpreciph, _state, make_automatic);
30009 0 : ae_vector_init_copy(&dst->tmpprodp, &src->tmpprodp, _state, make_automatic);
30010 0 : ae_vector_init_copy(&dst->tmpprods, &src->tmpprods, _state, make_automatic);
30011 0 : ae_vector_init_copy(&dst->tmpcp, &src->tmpcp, _state, make_automatic);
30012 0 : ae_vector_init_copy(&dst->tmpcs, &src->tmpcs, _state, make_automatic);
30013 0 : ae_vector_init_copy(&dst->tmpci, &src->tmpci, _state, make_automatic);
30014 0 : }
30015 :
30016 :
30017 0 : void _sactiveset_clear(void* _p)
30018 : {
30019 0 : sactiveset *p = (sactiveset*)_p;
30020 0 : ae_touch_ptr((void*)p);
30021 0 : ae_vector_clear(&p->xc);
30022 0 : ae_vector_clear(&p->s);
30023 0 : ae_vector_clear(&p->h);
30024 0 : ae_vector_clear(&p->cstatus);
30025 0 : ae_matrix_clear(&p->sdensebatch);
30026 0 : ae_matrix_clear(&p->pdensebatch);
30027 0 : ae_matrix_clear(&p->idensebatch);
30028 0 : ae_vector_clear(&p->sparsebatch);
30029 0 : ae_vector_clear(&p->hasbndl);
30030 0 : ae_vector_clear(&p->hasbndu);
30031 0 : ae_vector_clear(&p->bndl);
30032 0 : ae_vector_clear(&p->bndu);
30033 0 : ae_matrix_clear(&p->cleic);
30034 0 : ae_vector_clear(&p->mtnew);
30035 0 : ae_vector_clear(&p->mtx);
30036 0 : ae_vector_clear(&p->mtas);
30037 0 : ae_vector_clear(&p->cdtmp);
30038 0 : ae_vector_clear(&p->corrtmp);
30039 0 : ae_vector_clear(&p->unitdiagonal);
30040 0 : _snnlssolver_clear(&p->solver);
30041 0 : ae_vector_clear(&p->scntmp);
30042 0 : ae_vector_clear(&p->tmp0);
30043 0 : ae_vector_clear(&p->tmpfeas);
30044 0 : ae_matrix_clear(&p->tmpm0);
30045 0 : ae_vector_clear(&p->rctmps);
30046 0 : ae_vector_clear(&p->rctmpg);
30047 0 : ae_vector_clear(&p->rctmprightpart);
30048 0 : ae_matrix_clear(&p->rctmpdense0);
30049 0 : ae_matrix_clear(&p->rctmpdense1);
30050 0 : ae_vector_clear(&p->rctmpisequality);
30051 0 : ae_vector_clear(&p->rctmpconstraintidx);
30052 0 : ae_vector_clear(&p->rctmplambdas);
30053 0 : ae_matrix_clear(&p->tmpbasis);
30054 0 : ae_vector_clear(&p->tmpnormestimates);
30055 0 : ae_vector_clear(&p->tmpreciph);
30056 0 : ae_vector_clear(&p->tmpprodp);
30057 0 : ae_vector_clear(&p->tmpprods);
30058 0 : ae_vector_clear(&p->tmpcp);
30059 0 : ae_vector_clear(&p->tmpcs);
30060 0 : ae_vector_clear(&p->tmpci);
30061 0 : }
30062 :
30063 :
30064 0 : void _sactiveset_destroy(void* _p)
30065 : {
30066 0 : sactiveset *p = (sactiveset*)_p;
30067 0 : ae_touch_ptr((void*)p);
30068 0 : ae_vector_destroy(&p->xc);
30069 0 : ae_vector_destroy(&p->s);
30070 0 : ae_vector_destroy(&p->h);
30071 0 : ae_vector_destroy(&p->cstatus);
30072 0 : ae_matrix_destroy(&p->sdensebatch);
30073 0 : ae_matrix_destroy(&p->pdensebatch);
30074 0 : ae_matrix_destroy(&p->idensebatch);
30075 0 : ae_vector_destroy(&p->sparsebatch);
30076 0 : ae_vector_destroy(&p->hasbndl);
30077 0 : ae_vector_destroy(&p->hasbndu);
30078 0 : ae_vector_destroy(&p->bndl);
30079 0 : ae_vector_destroy(&p->bndu);
30080 0 : ae_matrix_destroy(&p->cleic);
30081 0 : ae_vector_destroy(&p->mtnew);
30082 0 : ae_vector_destroy(&p->mtx);
30083 0 : ae_vector_destroy(&p->mtas);
30084 0 : ae_vector_destroy(&p->cdtmp);
30085 0 : ae_vector_destroy(&p->corrtmp);
30086 0 : ae_vector_destroy(&p->unitdiagonal);
30087 0 : _snnlssolver_destroy(&p->solver);
30088 0 : ae_vector_destroy(&p->scntmp);
30089 0 : ae_vector_destroy(&p->tmp0);
30090 0 : ae_vector_destroy(&p->tmpfeas);
30091 0 : ae_matrix_destroy(&p->tmpm0);
30092 0 : ae_vector_destroy(&p->rctmps);
30093 0 : ae_vector_destroy(&p->rctmpg);
30094 0 : ae_vector_destroy(&p->rctmprightpart);
30095 0 : ae_matrix_destroy(&p->rctmpdense0);
30096 0 : ae_matrix_destroy(&p->rctmpdense1);
30097 0 : ae_vector_destroy(&p->rctmpisequality);
30098 0 : ae_vector_destroy(&p->rctmpconstraintidx);
30099 0 : ae_vector_destroy(&p->rctmplambdas);
30100 0 : ae_matrix_destroy(&p->tmpbasis);
30101 0 : ae_vector_destroy(&p->tmpnormestimates);
30102 0 : ae_vector_destroy(&p->tmpreciph);
30103 0 : ae_vector_destroy(&p->tmpprodp);
30104 0 : ae_vector_destroy(&p->tmpprods);
30105 0 : ae_vector_destroy(&p->tmpcp);
30106 0 : ae_vector_destroy(&p->tmpcs);
30107 0 : ae_vector_destroy(&p->tmpci);
30108 0 : }
30109 :
30110 :
30111 : #endif
30112 : #if defined(AE_COMPILE_QQPSOLVER) || !defined(AE_PARTIAL_BUILD)
30113 :
30114 :
30115 : /*************************************************************************
30116 : This function initializes QQPSettings structure with default settings.
30117 :
30118 : Newly created structure MUST be initialized by default settings - or by
30119 : copy of the already initialized structure.
30120 :
30121 : -- ALGLIB --
30122 : Copyright 14.05.2011 by Bochkanov Sergey
30123 : *************************************************************************/
30124 0 : void qqploaddefaults(ae_int_t n, qqpsettings* s, ae_state *_state)
30125 : {
30126 :
30127 :
30128 0 : s->epsg = 0.0;
30129 0 : s->epsf = 0.0;
30130 0 : s->epsx = 1.0E-6;
30131 0 : s->maxouterits = 0;
30132 0 : s->cgphase = ae_true;
30133 0 : s->cnphase = ae_true;
30134 0 : s->cgminits = 5;
30135 0 : s->cgmaxits = ae_maxint(s->cgminits, ae_round(1+0.33*n, _state), _state);
30136 0 : s->sparsesolver = 0;
30137 0 : s->cnmaxupdates = ae_round(1+0.1*n, _state);
30138 0 : }
30139 :
30140 :
30141 : /*************************************************************************
30142 : This function initializes QQPSettings structure with copy of another,
30143 : already initialized structure.
30144 :
30145 : -- ALGLIB --
30146 : Copyright 14.05.2011 by Bochkanov Sergey
30147 : *************************************************************************/
30148 0 : void qqpcopysettings(qqpsettings* src, qqpsettings* dst, ae_state *_state)
30149 : {
30150 :
30151 :
30152 0 : dst->epsg = src->epsg;
30153 0 : dst->epsf = src->epsf;
30154 0 : dst->epsx = src->epsx;
30155 0 : dst->maxouterits = src->maxouterits;
30156 0 : dst->cgphase = src->cgphase;
30157 0 : dst->cnphase = src->cnphase;
30158 0 : dst->cgminits = src->cgminits;
30159 0 : dst->cgmaxits = src->cgmaxits;
30160 0 : dst->sparsesolver = src->sparsesolver;
30161 0 : dst->cnmaxupdates = src->cnmaxupdates;
30162 0 : }
30163 :
30164 :
30165 : /*************************************************************************
30166 : This function performs preallocation of internal 2D matrices. If matrix
30167 : size is less than expected, we grow to some larger value (specified by user).
30168 :
30169 : It can be useful in cases when we solve many subsequent QP problems with
30170 : increasing sizes - helps to avoid multiple allocations.
30171 :
30172 : INPUT PARAMETERS:
30173 : SState - object which stores temporaries:
30174 : * uninitialized object is automatically initialized
30175 : * previously allocated memory is reused as much
30176 : as possible
30177 : NExpected - if internal buffers have size enough for NExpected,
30178 : no preallocation happens. If size is less than NExpected,
30179 : buffers are preallocated up to NGrowTo*NGrowTo
30180 : NGrowTo - new size
30181 :
30182 :
30183 : OUTPUT PARAMETERS:
30184 : SState - temporary buffers, some of them are preallocated
30185 :
30186 : -- ALGLIB --
30187 : Copyright 09.10.2017 by Bochkanov Sergey
30188 : *************************************************************************/
30189 0 : void qqppreallocategrowdense(qqpbuffers* sstate,
30190 : ae_int_t nexpected,
30191 : ae_int_t ngrowto,
30192 : ae_state *_state)
30193 : {
30194 :
30195 :
30196 0 : if( sstate->densea.rows<nexpected||sstate->densea.cols<nexpected )
30197 : {
30198 0 : rmatrixsetlengthatleast(&sstate->densea, ngrowto, ngrowto, _state);
30199 : }
30200 0 : if( sstate->densez.rows<nexpected||sstate->densez.cols<nexpected )
30201 : {
30202 0 : rmatrixsetlengthatleast(&sstate->densez, ngrowto, ngrowto, _state);
30203 : }
30204 0 : }
30205 :
30206 :
30207 : /*************************************************************************
30208 : This function runs QQP solver; it returns after optimization process was
30209 : completed. Following QP problem is solved:
30210 :
30211 : min(0.5*(x-x_origin)'*A*(x-x_origin)+b'*(x-x_origin))
30212 :
30213 : subject to boundary constraints.
30214 :
30215 : IMPORTANT: UNLIKE MANY OTHER SOLVERS, THIS FUNCTION DOES NOT REQUIRE YOU
30216 : TO INITIALIZE STATE OBJECT. IT CAN BE AUTOMATICALLY INITIALIZED
30217 : DURING SOLUTION PROCESS.
30218 :
30219 : INPUT PARAMETERS:
30220 : AC - for dense problems given by CQM model (AKind=0) A-term
30221 : of CQM object contains system matrix. Other terms are
30222 : unspecified and should not be referenced.
30223 : SparseAC - for sparse problems (AKind=1)
30224 : DenseAC - for traditional dense matrices (AKind=2)
30225 : AKind - matrix term to use:
30226 : * 0 for dense CQM (CQMAC)
30227 : * 1 for sparse matrix (SparseAC)
30228 : * 2 for dense matrix (DenseAC)
30229 : IsUpper - which triangle of SparseAC/DenseAC stores matrix -
30230 : upper or lower one (for dense matrices this parameter
30231 : is not actual).
30232 : BC - linear term, array[NC]
30233 : BndLC - lower bound, array[NC]
30234 : BndUC - upper bound, array[NC]
30235 : SC - scale vector, array[NC]:
30236 : * I-th element contains scale of I-th variable,
30237 : * SC[I]>0
30238 : XOriginC - origin term, array[NC]. Can be zero.
30239 : NC - number of variables in the original formulation (no
30240 : slack variables).
30241 : CLEICC - linear equality/inequality constraints. Present version
30242 : of this function does NOT provide publicly available
30243 : support for linear constraints. This feature will be
30244 : introduced in the future versions of the function.
30245 : NEC, NIC - number of equality/inequality constraints.
30246 : MUST BE ZERO IN THE CURRENT VERSION!!!
30247 : Settings - QQPSettings object initialized by one of the initialization
30248 : functions.
30249 : SState - object which stores temporaries:
30250 : * uninitialized object is automatically initialized
30251 : * previously allocated memory is reused as much
30252 : as possible
30253 : XS - initial point, array[NC]
30254 :
30255 :
30256 : OUTPUT PARAMETERS:
30257 : XS - last point
30258 : TerminationType-termination type:
30259 : *
30260 : *
30261 : *
30262 :
30263 : -- ALGLIB --
30264 : Copyright 14.05.2011 by Bochkanov Sergey
30265 : *************************************************************************/
30266 0 : void qqpoptimize(convexquadraticmodel* cqmac,
30267 : sparsematrix* sparseac,
30268 : /* Real */ ae_matrix* denseac,
30269 : ae_int_t akind,
30270 : ae_bool isupper,
30271 : /* Real */ ae_vector* bc,
30272 : /* Real */ ae_vector* bndlc,
30273 : /* Real */ ae_vector* bnduc,
30274 : /* Real */ ae_vector* sc,
30275 : /* Real */ ae_vector* xoriginc,
30276 : ae_int_t nc,
30277 : qqpsettings* settings,
30278 : qqpbuffers* sstate,
30279 : /* Real */ ae_vector* xs,
30280 : ae_int_t* terminationtype,
30281 : ae_state *_state)
30282 : {
30283 : ae_int_t n;
30284 : ae_int_t i;
30285 : ae_int_t j;
30286 : ae_int_t k;
30287 : double v;
30288 : double vv;
30289 : double d2;
30290 : double d1;
30291 : ae_int_t d1est;
30292 : ae_int_t d2est;
30293 : ae_bool needact;
30294 : double reststp;
30295 : double fullstp;
30296 : double stpmax;
30297 : double stp;
30298 : ae_int_t stpcnt;
30299 : ae_int_t cidx;
30300 : double cval;
30301 : ae_int_t cgcnt;
30302 : ae_int_t cgmax;
30303 : ae_int_t newtcnt;
30304 : ae_int_t sparsesolver;
30305 : double beta;
30306 : ae_bool b;
30307 : double fprev;
30308 : double fcur;
30309 : ae_bool problemsolved;
30310 : ae_bool isconstrained;
30311 : double f0;
30312 : double f1;
30313 :
30314 0 : *terminationtype = 0;
30315 :
30316 :
30317 : /*
30318 : * Primary checks
30319 : */
30320 0 : ae_assert((akind==0||akind==1)||akind==2, "QQPOptimize: incorrect AKind", _state);
30321 0 : sstate->n = nc;
30322 0 : n = sstate->n;
30323 0 : *terminationtype = 0;
30324 0 : sstate->repinneriterationscount = 0;
30325 0 : sstate->repouteriterationscount = 0;
30326 0 : sstate->repncholesky = 0;
30327 0 : sstate->repncupdates = 0;
30328 :
30329 : /*
30330 : * Several checks
30331 : * * matrix size
30332 : * * scale vector
30333 : * * consistency of bound constraints
30334 : * * consistency of settings
30335 : */
30336 0 : if( akind==1 )
30337 : {
30338 0 : ae_assert(sparsegetnrows(sparseac, _state)==n, "QQPOptimize: rows(SparseAC)<>N", _state);
30339 0 : ae_assert(sparsegetncols(sparseac, _state)==n, "QQPOptimize: cols(SparseAC)<>N", _state);
30340 : }
30341 0 : for(i=0; i<=n-1; i++)
30342 : {
30343 0 : ae_assert(ae_isfinite(sc->ptr.p_double[i], _state)&&ae_fp_greater(sc->ptr.p_double[i],(double)(0)), "QQPOptimize: incorrect scale", _state);
30344 : }
30345 0 : for(i=0; i<=n-1; i++)
30346 : {
30347 0 : if( ae_isfinite(bndlc->ptr.p_double[i], _state)&&ae_isfinite(bnduc->ptr.p_double[i], _state) )
30348 : {
30349 0 : if( ae_fp_greater(bndlc->ptr.p_double[i],bnduc->ptr.p_double[i]) )
30350 : {
30351 0 : *terminationtype = -3;
30352 0 : return;
30353 : }
30354 : }
30355 : }
30356 0 : ae_assert(settings->cgphase||settings->cnphase, "QQPOptimize: both phases (CG and Newton) are inactive", _state);
30357 :
30358 : /*
30359 : * Allocate data structures
30360 : */
30361 0 : rvectorsetlengthatleast(&sstate->bndl, n, _state);
30362 0 : rvectorsetlengthatleast(&sstate->bndu, n, _state);
30363 0 : bvectorsetlengthatleast(&sstate->havebndl, n, _state);
30364 0 : bvectorsetlengthatleast(&sstate->havebndu, n, _state);
30365 0 : rvectorsetlengthatleast(&sstate->xs, n, _state);
30366 0 : rvectorsetlengthatleast(&sstate->xf, n, _state);
30367 0 : rvectorsetlengthatleast(&sstate->xp, n, _state);
30368 0 : rvectorsetlengthatleast(&sstate->gc, n, _state);
30369 0 : rvectorsetlengthatleast(&sstate->cgc, n, _state);
30370 0 : rvectorsetlengthatleast(&sstate->cgp, n, _state);
30371 0 : rvectorsetlengthatleast(&sstate->dc, n, _state);
30372 0 : rvectorsetlengthatleast(&sstate->dp, n, _state);
30373 0 : rvectorsetlengthatleast(&sstate->tmp0, n, _state);
30374 0 : rvectorsetlengthatleast(&sstate->tmp1, n, _state);
30375 0 : rvectorsetlengthatleast(&sstate->stpbuf, 15, _state);
30376 0 : sasinit(n, &sstate->sas, _state);
30377 :
30378 : /*
30379 : * Scale/shift problem coefficients:
30380 : *
30381 : * min { 0.5*(x-x0)'*A*(x-x0) + b'*(x-x0) }
30382 : *
30383 : * becomes (after transformation "x = S*y+x0")
30384 : *
30385 : * min { 0.5*y'*(S*A*S)*y + (S*b)'*y
30386 : *
30387 : * Modified A_mod=S*A*S and b_mod=S*(b+A*x0) are
30388 : * stored into SState.DenseA and SState.B.
30389 : *
30390 : */
30391 0 : rvectorsetlengthatleast(&sstate->b, n, _state);
30392 0 : for(i=0; i<=n-1; i++)
30393 : {
30394 0 : sstate->b.ptr.p_double[i] = sc->ptr.p_double[i]*bc->ptr.p_double[i];
30395 : }
30396 0 : sstate->akind = -99;
30397 0 : if( akind==0 )
30398 : {
30399 :
30400 : /*
30401 : * Dense QP problem - just copy and scale.
30402 : */
30403 0 : rmatrixsetlengthatleast(&sstate->densea, n, n, _state);
30404 0 : cqmgeta(cqmac, &sstate->densea, _state);
30405 0 : sstate->akind = 0;
30406 0 : sstate->absamax = (double)(0);
30407 0 : sstate->absasum = (double)(0);
30408 0 : sstate->absasum2 = (double)(0);
30409 0 : for(i=0; i<=n-1; i++)
30410 : {
30411 0 : for(j=0; j<=n-1; j++)
30412 : {
30413 0 : v = sc->ptr.p_double[i]*sstate->densea.ptr.pp_double[i][j]*sc->ptr.p_double[j];
30414 0 : vv = ae_fabs(v, _state);
30415 0 : sstate->densea.ptr.pp_double[i][j] = v;
30416 0 : sstate->absamax = ae_maxreal(sstate->absamax, vv, _state);
30417 0 : sstate->absasum = sstate->absasum+vv;
30418 0 : sstate->absasum2 = sstate->absasum2+vv*vv;
30419 : }
30420 : }
30421 : }
30422 0 : if( akind==1 )
30423 : {
30424 :
30425 : /*
30426 : * Sparse QP problem - a bit tricky. Depending on format of the
30427 : * input we use different strategies for copying matrix:
30428 : * * SKS matrices are copied to SKS format
30429 : * * anything else is copied to CRS format
30430 : */
30431 0 : sparsecopytosksbuf(sparseac, &sstate->sparsea, _state);
30432 0 : if( isupper )
30433 : {
30434 0 : sparsetransposesks(&sstate->sparsea, _state);
30435 : }
30436 0 : sstate->akind = 1;
30437 0 : sstate->sparseupper = ae_false;
30438 0 : sstate->absamax = (double)(0);
30439 0 : sstate->absasum = (double)(0);
30440 0 : sstate->absasum2 = (double)(0);
30441 0 : for(i=0; i<=n-1; i++)
30442 : {
30443 0 : k = sstate->sparsea.ridx.ptr.p_int[i];
30444 0 : for(j=i-sstate->sparsea.didx.ptr.p_int[i]; j<=i; j++)
30445 : {
30446 0 : v = sc->ptr.p_double[i]*sstate->sparsea.vals.ptr.p_double[k]*sc->ptr.p_double[j];
30447 0 : vv = ae_fabs(v, _state);
30448 0 : sstate->sparsea.vals.ptr.p_double[k] = v;
30449 0 : if( i==j )
30450 : {
30451 :
30452 : /*
30453 : * Diagonal terms are counted only once
30454 : */
30455 0 : sstate->absamax = ae_maxreal(sstate->absamax, vv, _state);
30456 0 : sstate->absasum = sstate->absasum+vv;
30457 0 : sstate->absasum2 = sstate->absasum2+vv*vv;
30458 : }
30459 : else
30460 : {
30461 :
30462 : /*
30463 : * Offdiagonal terms are counted twice
30464 : */
30465 0 : sstate->absamax = ae_maxreal(sstate->absamax, vv, _state);
30466 0 : sstate->absasum = sstate->absasum+2*vv;
30467 0 : sstate->absasum2 = sstate->absasum2+2*vv*vv;
30468 : }
30469 0 : k = k+1;
30470 : }
30471 : }
30472 : }
30473 0 : if( akind==2 )
30474 : {
30475 :
30476 : /*
30477 : * Dense QP problem - just copy and scale.
30478 : */
30479 0 : rmatrixsetlengthatleast(&sstate->densea, n, n, _state);
30480 0 : sstate->akind = 0;
30481 0 : sstate->absamax = (double)(0);
30482 0 : sstate->absasum = (double)(0);
30483 0 : sstate->absasum2 = (double)(0);
30484 0 : if( isupper )
30485 : {
30486 0 : for(i=0; i<=n-1; i++)
30487 : {
30488 0 : for(j=i; j<=n-1; j++)
30489 : {
30490 0 : v = sc->ptr.p_double[i]*denseac->ptr.pp_double[i][j]*sc->ptr.p_double[j];
30491 0 : vv = ae_fabs(v, _state);
30492 0 : sstate->densea.ptr.pp_double[i][j] = v;
30493 0 : sstate->densea.ptr.pp_double[j][i] = v;
30494 0 : if( ae_fp_eq((double)(i),v) )
30495 : {
30496 0 : k = 1;
30497 : }
30498 : else
30499 : {
30500 0 : k = 2;
30501 : }
30502 0 : sstate->absamax = ae_maxreal(sstate->absamax, vv, _state);
30503 0 : sstate->absasum = sstate->absasum+vv*k;
30504 0 : sstate->absasum2 = sstate->absasum2+vv*vv*k;
30505 : }
30506 : }
30507 : }
30508 : else
30509 : {
30510 0 : for(i=0; i<=n-1; i++)
30511 : {
30512 0 : for(j=0; j<=i; j++)
30513 : {
30514 0 : v = sc->ptr.p_double[i]*denseac->ptr.pp_double[i][j]*sc->ptr.p_double[j];
30515 0 : vv = ae_fabs(v, _state);
30516 0 : sstate->densea.ptr.pp_double[i][j] = v;
30517 0 : sstate->densea.ptr.pp_double[j][i] = v;
30518 0 : if( ae_fp_eq((double)(i),v) )
30519 : {
30520 0 : k = 1;
30521 : }
30522 : else
30523 : {
30524 0 : k = 2;
30525 : }
30526 0 : sstate->absamax = ae_maxreal(sstate->absamax, vv, _state);
30527 0 : sstate->absasum = sstate->absasum+vv*k;
30528 0 : sstate->absasum2 = sstate->absasum2+vv*vv*k;
30529 : }
30530 : }
30531 : }
30532 : }
30533 0 : ae_assert(sstate->akind>=0, "QQP: integrity check failed", _state);
30534 :
30535 : /*
30536 : * Load box constraints into State structure.
30537 : *
30538 : * We apply transformation to variables: y=(x-x_origin)/s,
30539 : * each of the constraints is appropriately shifted/scaled.
30540 : */
30541 0 : for(i=0; i<=n-1; i++)
30542 : {
30543 0 : sstate->havebndl.ptr.p_bool[i] = ae_isfinite(bndlc->ptr.p_double[i], _state);
30544 0 : if( sstate->havebndl.ptr.p_bool[i] )
30545 : {
30546 0 : sstate->bndl.ptr.p_double[i] = (bndlc->ptr.p_double[i]-xoriginc->ptr.p_double[i])/sc->ptr.p_double[i];
30547 : }
30548 : else
30549 : {
30550 0 : ae_assert(ae_isneginf(bndlc->ptr.p_double[i], _state), "QQPOptimize: incorrect lower bound", _state);
30551 0 : sstate->bndl.ptr.p_double[i] = _state->v_neginf;
30552 : }
30553 0 : sstate->havebndu.ptr.p_bool[i] = ae_isfinite(bnduc->ptr.p_double[i], _state);
30554 0 : if( sstate->havebndu.ptr.p_bool[i] )
30555 : {
30556 0 : sstate->bndu.ptr.p_double[i] = (bnduc->ptr.p_double[i]-xoriginc->ptr.p_double[i])/sc->ptr.p_double[i];
30557 : }
30558 : else
30559 : {
30560 0 : ae_assert(ae_isposinf(bnduc->ptr.p_double[i], _state), "QQPOptimize: incorrect upper bound", _state);
30561 0 : sstate->bndu.ptr.p_double[i] = _state->v_posinf;
30562 : }
30563 : }
30564 :
30565 : /*
30566 : * Process initial point:
30567 : * * set it to XS-XOriginC
30568 : * * make sure that boundary constraints are preserved by transformation
30569 : */
30570 0 : for(i=0; i<=n-1; i++)
30571 : {
30572 0 : sstate->xs.ptr.p_double[i] = (xs->ptr.p_double[i]-xoriginc->ptr.p_double[i])/sc->ptr.p_double[i];
30573 0 : if( sstate->havebndl.ptr.p_bool[i]&&ae_fp_less(sstate->xs.ptr.p_double[i],sstate->bndl.ptr.p_double[i]) )
30574 : {
30575 0 : sstate->xs.ptr.p_double[i] = sstate->bndl.ptr.p_double[i];
30576 : }
30577 0 : if( sstate->havebndu.ptr.p_bool[i]&&ae_fp_greater(sstate->xs.ptr.p_double[i],sstate->bndu.ptr.p_double[i]) )
30578 : {
30579 0 : sstate->xs.ptr.p_double[i] = sstate->bndu.ptr.p_double[i];
30580 : }
30581 0 : if( sstate->havebndl.ptr.p_bool[i]&&ae_fp_eq(xs->ptr.p_double[i],bndlc->ptr.p_double[i]) )
30582 : {
30583 0 : sstate->xs.ptr.p_double[i] = sstate->bndl.ptr.p_double[i];
30584 : }
30585 0 : if( sstate->havebndu.ptr.p_bool[i]&&ae_fp_eq(xs->ptr.p_double[i],bnduc->ptr.p_double[i]) )
30586 : {
30587 0 : sstate->xs.ptr.p_double[i] = sstate->bndu.ptr.p_double[i];
30588 : }
30589 : }
30590 :
30591 : /*
30592 : * Select sparse direct solver
30593 : */
30594 0 : if( akind==1 )
30595 : {
30596 0 : sparsesolver = settings->sparsesolver;
30597 0 : if( sparsesolver==0 )
30598 : {
30599 0 : sparsesolver = 1;
30600 : }
30601 0 : if( sparseissks(&sstate->sparsea, _state) )
30602 : {
30603 0 : sparsesolver = 2;
30604 : }
30605 0 : sparsesolver = 2;
30606 0 : ae_assert(sparsesolver==1||sparsesolver==2, "QQPOptimize: incorrect SparseSolver", _state);
30607 : }
30608 : else
30609 : {
30610 0 : sparsesolver = 0;
30611 : }
30612 :
30613 : /*
30614 : * For unconstrained problems - try to use fast approach which requires
30615 : * just one unregularized Cholesky decomposition for solution. If it fails,
30616 : * switch to general QQP code.
30617 : */
30618 0 : problemsolved = ae_false;
30619 0 : isconstrained = ae_false;
30620 0 : for(i=0; i<=n-1; i++)
30621 : {
30622 0 : isconstrained = (isconstrained||sstate->havebndl.ptr.p_bool[i])||sstate->havebndu.ptr.p_bool[i];
30623 : }
30624 0 : if( (!isconstrained&&settings->cnphase)&&akind==0 )
30625 : {
30626 0 : rmatrixsetlengthatleast(&sstate->densez, n, n, _state);
30627 0 : rvectorsetlengthatleast(&sstate->tmpcn, n, _state);
30628 0 : for(i=0; i<=n-1; i++)
30629 : {
30630 0 : for(j=i; j<=n-1; j++)
30631 : {
30632 0 : sstate->densez.ptr.pp_double[i][j] = sstate->densea.ptr.pp_double[i][j];
30633 : }
30634 : }
30635 0 : inc(&sstate->repncholesky, _state);
30636 0 : if( spdmatrixcholeskyrec(&sstate->densez, 0, n, ae_true, &sstate->tmpcn, _state) )
30637 : {
30638 0 : ae_v_move(&sstate->xf.ptr.p_double[0], 1, &sstate->xs.ptr.p_double[0], 1, ae_v_len(0,n-1));
30639 0 : for(i=0; i<=n-1; i++)
30640 : {
30641 0 : sstate->dc.ptr.p_double[i] = (double)(0);
30642 : }
30643 0 : f0 = qqpsolver_projectedtargetfunction(sstate, &sstate->xf, &sstate->dc, 0.0, &sstate->tmpcn, &sstate->tmp1, _state);
30644 0 : for(k=0; k<=3; k++)
30645 : {
30646 0 : rmatrixmv(n, n, &sstate->densea, 0, 0, 0, &sstate->xf, 0, &sstate->gc, 0, _state);
30647 0 : ae_v_add(&sstate->gc.ptr.p_double[0], 1, &sstate->b.ptr.p_double[0], 1, ae_v_len(0,n-1));
30648 0 : for(i=0; i<=n-1; i++)
30649 : {
30650 0 : sstate->dc.ptr.p_double[i] = -sstate->gc.ptr.p_double[i];
30651 : }
30652 0 : fblscholeskysolve(&sstate->densez, 1.0, n, ae_true, &sstate->dc, &sstate->tmpcn, _state);
30653 0 : f1 = qqpsolver_projectedtargetfunction(sstate, &sstate->xf, &sstate->dc, 1.0, &sstate->tmpcn, &sstate->tmp1, _state);
30654 0 : if( ae_fp_greater_eq(f1,f0) )
30655 : {
30656 0 : break;
30657 : }
30658 0 : ae_v_add(&sstate->xf.ptr.p_double[0], 1, &sstate->dc.ptr.p_double[0], 1, ae_v_len(0,n-1));
30659 0 : f0 = f1;
30660 : }
30661 0 : *terminationtype = 2;
30662 0 : problemsolved = ae_true;
30663 : }
30664 : }
30665 :
30666 : /*
30667 : * Attempt to solve problem with fast approach failed, use generic QQP
30668 : */
30669 0 : if( !problemsolved )
30670 : {
30671 :
30672 : /*
30673 : * Prepare "active set" structure
30674 : */
30675 0 : sassetbc(&sstate->sas, &sstate->bndl, &sstate->bndu, _state);
30676 0 : if( !sasstartoptimization(&sstate->sas, &sstate->xs, _state) )
30677 : {
30678 0 : *terminationtype = -3;
30679 0 : return;
30680 : }
30681 :
30682 : /*
30683 : * Main loop.
30684 : *
30685 : * Following variables are used:
30686 : * * GC stores current gradient (unconstrained)
30687 : * * CGC stores current gradient (constrained)
30688 : * * DC stores current search direction
30689 : * * CGP stores constrained gradient at previous point
30690 : * (zero on initial entry)
30691 : * * DP stores previous search direction
30692 : * (zero on initial entry)
30693 : */
30694 0 : cgmax = settings->cgminits;
30695 0 : sstate->repinneriterationscount = 0;
30696 0 : sstate->repouteriterationscount = 0;
30697 : for(;;)
30698 : {
30699 0 : if( settings->maxouterits>0&&sstate->repouteriterationscount>=settings->maxouterits )
30700 : {
30701 0 : *terminationtype = 5;
30702 0 : break;
30703 : }
30704 0 : if( sstate->repouteriterationscount>0 )
30705 : {
30706 :
30707 : /*
30708 : * Check EpsF- and EpsX-based stopping criteria.
30709 : * Because problem was already scaled, we do not scale step before checking its length.
30710 : * NOTE: these checks are performed only after at least one outer iteration was made.
30711 : */
30712 0 : if( ae_fp_greater(settings->epsf,(double)(0)) )
30713 : {
30714 :
30715 : /*
30716 : * NOTE 1: here we rely on the fact that ProjectedTargetFunction() ignore D when Stp=0
30717 : * NOTE 2: code below handles situation when update increases function value instead
30718 : * of decreasing it.
30719 : */
30720 0 : fprev = qqpsolver_projectedtargetfunction(sstate, &sstate->xp, &sstate->dc, 0.0, &sstate->tmp0, &sstate->tmp1, _state);
30721 0 : fcur = qqpsolver_projectedtargetfunction(sstate, &sstate->sas.xc, &sstate->dc, 0.0, &sstate->tmp0, &sstate->tmp1, _state);
30722 0 : if( ae_fp_less_eq(fprev-fcur,settings->epsf*ae_maxreal(ae_fabs(fprev, _state), ae_maxreal(ae_fabs(fcur, _state), 1.0, _state), _state)) )
30723 : {
30724 0 : *terminationtype = 1;
30725 0 : break;
30726 : }
30727 : }
30728 0 : if( ae_fp_greater(settings->epsx,(double)(0)) )
30729 : {
30730 0 : v = 0.0;
30731 0 : for(i=0; i<=n-1; i++)
30732 : {
30733 0 : v = v+ae_sqr(sstate->xp.ptr.p_double[i]-sstate->sas.xc.ptr.p_double[i], _state);
30734 : }
30735 0 : if( ae_fp_less_eq(ae_sqrt(v, _state),settings->epsx) )
30736 : {
30737 0 : *terminationtype = 2;
30738 0 : break;
30739 : }
30740 : }
30741 : }
30742 0 : inc(&sstate->repouteriterationscount, _state);
30743 0 : ae_v_move(&sstate->xp.ptr.p_double[0], 1, &sstate->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
30744 0 : if( !settings->cgphase )
30745 : {
30746 0 : cgmax = 0;
30747 : }
30748 0 : for(i=0; i<=n-1; i++)
30749 : {
30750 0 : sstate->cgp.ptr.p_double[i] = 0.0;
30751 0 : sstate->dp.ptr.p_double[i] = 0.0;
30752 : }
30753 0 : for(cgcnt=0; cgcnt<=cgmax-1; cgcnt++)
30754 : {
30755 :
30756 : /*
30757 : * Calculate unconstrained gradient GC for "extended" QP problem
30758 : * Determine active set, current constrained gradient CGC.
30759 : * Check gradient-based stopping condition.
30760 : *
30761 : * NOTE: because problem was scaled, we do not have to apply scaling
30762 : * to gradient before checking stopping condition.
30763 : */
30764 0 : qqpsolver_targetgradient(sstate, &sstate->sas.xc, &sstate->gc, _state);
30765 0 : sasreactivateconstraints(&sstate->sas, &sstate->gc, _state);
30766 0 : ae_v_move(&sstate->cgc.ptr.p_double[0], 1, &sstate->gc.ptr.p_double[0], 1, ae_v_len(0,n-1));
30767 0 : sasconstraineddirection(&sstate->sas, &sstate->cgc, _state);
30768 0 : v = ae_v_dotproduct(&sstate->cgc.ptr.p_double[0], 1, &sstate->cgc.ptr.p_double[0], 1, ae_v_len(0,n-1));
30769 0 : if( ae_fp_less_eq(ae_sqrt(v, _state),settings->epsg) )
30770 : {
30771 0 : *terminationtype = 4;
30772 0 : break;
30773 : }
30774 :
30775 : /*
30776 : * Prepare search direction DC and explore it.
30777 : *
30778 : * We try to use CGP/DP to prepare conjugate gradient step,
30779 : * but we resort to steepest descent step (Beta=0) in case
30780 : * we are at I-th boundary, but DP[I]<>0.
30781 : *
30782 : * Such approach allows us to ALWAYS have feasible DC, with
30783 : * guaranteed compatibility with both feasible area and current
30784 : * active set.
30785 : *
30786 : * Automatic CG reset performed every time DP is incompatible
30787 : * with current active set and/or feasible area. We also
30788 : * perform reset every QuickQPRestartCG iterations.
30789 : */
30790 0 : ae_v_moveneg(&sstate->dc.ptr.p_double[0], 1, &sstate->cgc.ptr.p_double[0], 1, ae_v_len(0,n-1));
30791 0 : v = 0.0;
30792 0 : vv = 0.0;
30793 0 : b = ae_false;
30794 0 : for(i=0; i<=n-1; i++)
30795 : {
30796 0 : v = v+sstate->cgc.ptr.p_double[i]*sstate->cgc.ptr.p_double[i];
30797 0 : vv = vv+sstate->cgp.ptr.p_double[i]*sstate->cgp.ptr.p_double[i];
30798 0 : b = b||((sstate->havebndl.ptr.p_bool[i]&&ae_fp_eq(sstate->sas.xc.ptr.p_double[i],sstate->bndl.ptr.p_double[i]))&&ae_fp_neq(sstate->dp.ptr.p_double[i],(double)(0)));
30799 0 : b = b||((sstate->havebndu.ptr.p_bool[i]&&ae_fp_eq(sstate->sas.xc.ptr.p_double[i],sstate->bndu.ptr.p_double[i]))&&ae_fp_neq(sstate->dp.ptr.p_double[i],(double)(0)));
30800 : }
30801 0 : b = b||ae_fp_eq(vv,(double)(0));
30802 0 : b = b||cgcnt%qqpsolver_quickqprestartcg==0;
30803 0 : if( !b )
30804 : {
30805 0 : beta = v/vv;
30806 : }
30807 : else
30808 : {
30809 0 : beta = 0.0;
30810 : }
30811 0 : ae_v_addd(&sstate->dc.ptr.p_double[0], 1, &sstate->dp.ptr.p_double[0], 1, ae_v_len(0,n-1), beta);
30812 0 : sasconstraineddirection(&sstate->sas, &sstate->dc, _state);
30813 0 : sasexploredirection(&sstate->sas, &sstate->dc, &stpmax, &cidx, &cval, _state);
30814 :
30815 : /*
30816 : * Build quadratic model of F along descent direction:
30817 : *
30818 : * F(xc+alpha*D) = D2*alpha^2 + D1*alpha
30819 : *
30820 : * Terminate algorithm if needed.
30821 : *
30822 : * NOTE: we do not maintain constant term D0
30823 : */
30824 0 : qqpsolver_quadraticmodel(sstate, &sstate->sas.xc, &sstate->dc, &sstate->gc, &d1, &d1est, &d2, &d2est, &sstate->tmp0, _state);
30825 0 : if( ae_fp_eq(d1,(double)(0))&&ae_fp_eq(d2,(double)(0)) )
30826 : {
30827 :
30828 : /*
30829 : * D1 and D2 are exactly zero, success.
30830 : * After this if-then we assume that D is non-zero.
30831 : */
30832 0 : *terminationtype = 4;
30833 0 : break;
30834 : }
30835 0 : if( d1est>=0 )
30836 : {
30837 :
30838 : /*
30839 : * Numerical noise is too large, it means that we are close
30840 : * to minimum - and that further improvement is impossible.
30841 : *
30842 : * After this if-then we assume that D1 is definitely negative
30843 : * (even under presence of numerical errors).
30844 : */
30845 0 : *terminationtype = 7;
30846 0 : break;
30847 : }
30848 0 : if( d2est<=0&&cidx<0 )
30849 : {
30850 :
30851 : /*
30852 : * Function is unbounded from below:
30853 : * * D1<0 (verified by previous block)
30854 : * * D2Est<=0, which means that either D2<0 - or it can not
30855 : * be reliably distinguished from zero.
30856 : * * step is unconstrained
30857 : *
30858 : * If these conditions are true, we abnormally terminate QP
30859 : * algorithm with return code -4
30860 : */
30861 0 : *terminationtype = -4;
30862 0 : break;
30863 : }
30864 :
30865 : /*
30866 : * Perform step along DC.
30867 : *
30868 : * In this block of code we maintain two step length:
30869 : * * RestStp - restricted step, maximum step length along DC which does
30870 : * not violate constraints
30871 : * * FullStp - step length along DC which minimizes quadratic function
30872 : * without taking constraints into account. If problem is
30873 : * unbounded from below without constraints, FullStp is
30874 : * forced to be RestStp.
30875 : *
30876 : * So, if function is convex (D2>0):
30877 : * * FullStp = -D1/(2*D2)
30878 : * * RestStp = restricted FullStp
30879 : * * 0<=RestStp<=FullStp
30880 : *
30881 : * If function is non-convex, but bounded from below under constraints:
30882 : * * RestStp = step length subject to constraints
30883 : * * FullStp = RestStp
30884 : *
30885 : * After RestStp and FullStp are initialized, we generate several trial
30886 : * steps which are different multiples of RestStp and FullStp.
30887 : */
30888 0 : if( d2est>0 )
30889 : {
30890 0 : ae_assert(ae_fp_less(d1,(double)(0)), "QQPOptimize: internal error", _state);
30891 0 : fullstp = -d1/(2*d2);
30892 0 : needact = ae_fp_greater_eq(fullstp,stpmax);
30893 0 : if( needact )
30894 : {
30895 0 : ae_assert(sstate->stpbuf.cnt>=3, "QQPOptimize: StpBuf overflow", _state);
30896 0 : reststp = stpmax;
30897 0 : stp = reststp;
30898 0 : sstate->stpbuf.ptr.p_double[0] = reststp*4;
30899 0 : sstate->stpbuf.ptr.p_double[1] = fullstp;
30900 0 : sstate->stpbuf.ptr.p_double[2] = fullstp/4;
30901 0 : stpcnt = 3;
30902 : }
30903 : else
30904 : {
30905 0 : reststp = fullstp;
30906 0 : stp = fullstp;
30907 0 : stpcnt = 0;
30908 : }
30909 : }
30910 : else
30911 : {
30912 0 : ae_assert(cidx>=0, "QQPOptimize: internal error", _state);
30913 0 : ae_assert(sstate->stpbuf.cnt>=2, "QQPOptimize: StpBuf overflow", _state);
30914 0 : reststp = stpmax;
30915 0 : fullstp = stpmax;
30916 0 : stp = reststp;
30917 0 : needact = ae_true;
30918 0 : sstate->stpbuf.ptr.p_double[0] = 4*reststp;
30919 0 : stpcnt = 1;
30920 : }
30921 0 : qqpsolver_findbeststepandmove(sstate, &sstate->sas, &sstate->dc, stp, needact, cidx, cval, &sstate->stpbuf, stpcnt, &sstate->activated, &sstate->tmp0, &sstate->tmp1, _state);
30922 :
30923 : /*
30924 : * Update CG information.
30925 : */
30926 0 : ae_v_move(&sstate->dp.ptr.p_double[0], 1, &sstate->dc.ptr.p_double[0], 1, ae_v_len(0,n-1));
30927 0 : ae_v_move(&sstate->cgp.ptr.p_double[0], 1, &sstate->cgc.ptr.p_double[0], 1, ae_v_len(0,n-1));
30928 :
30929 : /*
30930 : * Update iterations counter
30931 : */
30932 0 : sstate->repinneriterationscount = sstate->repinneriterationscount+1;
30933 : }
30934 0 : if( *terminationtype!=0 )
30935 : {
30936 0 : break;
30937 : }
30938 0 : cgmax = settings->cgmaxits;
30939 :
30940 : /*
30941 : * Generate YIdx - reordering of variables for constrained Newton phase.
30942 : * Free variables come first, fixed are last ones.
30943 : */
30944 0 : newtcnt = 0;
30945 : for(;;)
30946 : {
30947 :
30948 : /*
30949 : * Skip iteration if constrained Newton is turned off.
30950 : */
30951 0 : if( !settings->cnphase )
30952 : {
30953 0 : break;
30954 : }
30955 :
30956 : /*
30957 : * At the first iteration - build Cholesky decomposition of Hessian.
30958 : * At subsequent iterations - refine Hessian by adding new constraints.
30959 : *
30960 : * Loop is terminated in following cases:
30961 : * * Hessian is not positive definite subject to current constraints
30962 : * (termination during initial decomposition)
30963 : * * there were no new constraints being activated
30964 : * (termination during update)
30965 : * * all constraints were activated during last step
30966 : * (termination during update)
30967 : * * CNMaxUpdates were performed on matrix
30968 : * (termination during update)
30969 : */
30970 0 : if( newtcnt==0 )
30971 : {
30972 :
30973 : /*
30974 : * Perform initial Newton step. If Cholesky decomposition fails,
30975 : * increase number of CG iterations to CGMaxIts - it should help
30976 : * us to find set of constraints which will make matrix positive
30977 : * definite.
30978 : */
30979 0 : b = qqpsolver_cnewtonbuild(sstate, sparsesolver, &sstate->repncholesky, _state);
30980 0 : if( b )
30981 : {
30982 0 : cgmax = settings->cgminits;
30983 : }
30984 : }
30985 : else
30986 : {
30987 0 : b = qqpsolver_cnewtonupdate(sstate, settings, &sstate->repncupdates, _state);
30988 : }
30989 0 : if( !b )
30990 : {
30991 0 : break;
30992 : }
30993 0 : inc(&newtcnt, _state);
30994 :
30995 : /*
30996 : * Calculate gradient GC.
30997 : */
30998 0 : qqpsolver_targetgradient(sstate, &sstate->sas.xc, &sstate->gc, _state);
30999 :
31000 : /*
31001 : * Bound-constrained Newton step
31002 : */
31003 0 : for(i=0; i<=n-1; i++)
31004 : {
31005 0 : sstate->dc.ptr.p_double[i] = sstate->gc.ptr.p_double[i];
31006 : }
31007 0 : if( !qqpsolver_cnewtonstep(sstate, settings, &sstate->dc, _state) )
31008 : {
31009 0 : break;
31010 : }
31011 0 : qqpsolver_quadraticmodel(sstate, &sstate->sas.xc, &sstate->dc, &sstate->gc, &d1, &d1est, &d2, &d2est, &sstate->tmp0, _state);
31012 0 : if( d1est>=0 )
31013 : {
31014 :
31015 : /*
31016 : * We are close to minimum, derivative is nearly zero, break Newton iteration
31017 : */
31018 0 : break;
31019 : }
31020 0 : if( d2est>0 )
31021 : {
31022 :
31023 : /*
31024 : * Positive definite matrix, we can perform Newton step
31025 : */
31026 0 : ae_assert(ae_fp_less(d1,(double)(0)), "QQPOptimize: internal error", _state);
31027 0 : fullstp = -d1/(2*d2);
31028 0 : sasexploredirection(&sstate->sas, &sstate->dc, &stpmax, &cidx, &cval, _state);
31029 0 : needact = ae_fp_greater_eq(fullstp,stpmax);
31030 0 : if( needact )
31031 : {
31032 0 : ae_assert(sstate->stpbuf.cnt>=3, "QQPOptimize: StpBuf overflow", _state);
31033 0 : reststp = stpmax;
31034 0 : stp = reststp;
31035 0 : sstate->stpbuf.ptr.p_double[0] = reststp*4;
31036 0 : sstate->stpbuf.ptr.p_double[1] = fullstp;
31037 0 : sstate->stpbuf.ptr.p_double[2] = fullstp/4;
31038 0 : stpcnt = 3;
31039 : }
31040 : else
31041 : {
31042 0 : reststp = fullstp;
31043 0 : stp = fullstp;
31044 0 : stpcnt = 0;
31045 : }
31046 0 : qqpsolver_findbeststepandmove(sstate, &sstate->sas, &sstate->dc, stp, needact, cidx, cval, &sstate->stpbuf, stpcnt, &sstate->activated, &sstate->tmp0, &sstate->tmp1, _state);
31047 : }
31048 : else
31049 : {
31050 :
31051 : /*
31052 : * Matrix is semi-definite or indefinite, but regularized
31053 : * Cholesky succeeded and gave us descent direction in DC.
31054 : *
31055 : * We will investigate it and try to perform descent step:
31056 : * * first, we explore direction:
31057 : * * if it is unbounded, we stop algorithm with
31058 : * appropriate termination code -4.
31059 : * * if StpMax=0, we break Newton phase and return to
31060 : * CG phase - constraint geometry is complicated near
31061 : * current point, so it is better to use simpler algo.
31062 : * * second, we check that bounded step decreases function;
31063 : * if not, we again skip to CG phase
31064 : * * finally, we use FindBestStep...() function to choose
31065 : * between bounded step and projection of full-length step
31066 : * (latter may give additional decrease in
31067 : */
31068 0 : sasexploredirection(&sstate->sas, &sstate->dc, &stpmax, &cidx, &cval, _state);
31069 0 : if( cidx<0 )
31070 : {
31071 :
31072 : /*
31073 : * Function is unbounded from below:
31074 : * * D1<0 (verified by previous block)
31075 : * * D2Est<=0, which means that either D2<0 - or it can not
31076 : * be reliably distinguished from zero.
31077 : * * step is unconstrained
31078 : *
31079 : * If these conditions are true, we abnormally terminate QP
31080 : * algorithm with return code -4
31081 : */
31082 0 : *terminationtype = -4;
31083 0 : break;
31084 : }
31085 0 : if( ae_fp_eq(stpmax,(double)(0)) )
31086 : {
31087 :
31088 : /*
31089 : * Resort to CG phase.
31090 : * Increase number of CG iterations.
31091 : */
31092 0 : cgmax = settings->cgmaxits;
31093 0 : break;
31094 : }
31095 0 : ae_assert(ae_fp_greater(stpmax,(double)(0)), "QQPOptimize: internal error", _state);
31096 0 : f0 = qqpsolver_projectedtargetfunction(sstate, &sstate->sas.xc, &sstate->dc, 0.0, &sstate->tmp0, &sstate->tmp1, _state);
31097 0 : f1 = qqpsolver_projectedtargetfunction(sstate, &sstate->sas.xc, &sstate->dc, stpmax, &sstate->tmp0, &sstate->tmp1, _state);
31098 0 : if( ae_fp_greater_eq(f1,f0) )
31099 : {
31100 :
31101 : /*
31102 : * Descent direction does not actually decrease function value.
31103 : * Resort to CG phase
31104 : * Increase number of CG iterations.
31105 : */
31106 0 : cgmax = settings->cgmaxits;
31107 0 : break;
31108 : }
31109 0 : ae_assert(sstate->stpbuf.cnt>=3, "QQPOptimize: StpBuf overflow", _state);
31110 0 : reststp = stpmax;
31111 0 : stp = reststp;
31112 0 : sstate->stpbuf.ptr.p_double[0] = reststp*4;
31113 0 : sstate->stpbuf.ptr.p_double[1] = 1.00;
31114 0 : sstate->stpbuf.ptr.p_double[2] = 0.25;
31115 0 : stpcnt = 3;
31116 0 : qqpsolver_findbeststepandmove(sstate, &sstate->sas, &sstate->dc, stp, ae_true, cidx, cval, &sstate->stpbuf, stpcnt, &sstate->activated, &sstate->tmp0, &sstate->tmp1, _state);
31117 : }
31118 : }
31119 0 : if( *terminationtype!=0 )
31120 : {
31121 0 : break;
31122 : }
31123 : }
31124 0 : sasstopoptimization(&sstate->sas, _state);
31125 0 : ae_v_move(&sstate->xf.ptr.p_double[0], 1, &sstate->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
31126 : }
31127 :
31128 : /*
31129 : * Stop optimization and unpack results.
31130 : *
31131 : * Add XOriginC to XS and make sure that boundary constraints are
31132 : * both (a) satisfied, (b) preserved. Former means that "shifted"
31133 : * point is feasible, while latter means that point which was exactly
31134 : * at the boundary before shift will be exactly at the boundary
31135 : * after shift.
31136 : */
31137 0 : for(i=0; i<=n-1; i++)
31138 : {
31139 0 : xs->ptr.p_double[i] = sc->ptr.p_double[i]*sstate->xf.ptr.p_double[i]+xoriginc->ptr.p_double[i];
31140 0 : if( sstate->havebndl.ptr.p_bool[i]&&ae_fp_less(xs->ptr.p_double[i],bndlc->ptr.p_double[i]) )
31141 : {
31142 0 : xs->ptr.p_double[i] = bndlc->ptr.p_double[i];
31143 : }
31144 0 : if( sstate->havebndu.ptr.p_bool[i]&&ae_fp_greater(xs->ptr.p_double[i],bnduc->ptr.p_double[i]) )
31145 : {
31146 0 : xs->ptr.p_double[i] = bnduc->ptr.p_double[i];
31147 : }
31148 0 : if( sstate->havebndl.ptr.p_bool[i]&&ae_fp_eq(sstate->xf.ptr.p_double[i],sstate->bndl.ptr.p_double[i]) )
31149 : {
31150 0 : xs->ptr.p_double[i] = bndlc->ptr.p_double[i];
31151 : }
31152 0 : if( sstate->havebndu.ptr.p_bool[i]&&ae_fp_eq(sstate->xf.ptr.p_double[i],sstate->bndu.ptr.p_double[i]) )
31153 : {
31154 0 : xs->ptr.p_double[i] = bnduc->ptr.p_double[i];
31155 : }
31156 : }
31157 : }
31158 :
31159 :
31160 : /*************************************************************************
31161 : Target function at point PROJ(X+Stp*D), where PROJ(.) is a projection into
31162 : feasible set.
31163 :
31164 : NOTE: if Stp=0, D is not referenced at all. Thus, there is no need to
31165 : fill it by some meaningful values for Stp=0.
31166 :
31167 : This subroutine uses temporary buffers Tmp0/1, which are automatically
31168 : resized if needed.
31169 :
31170 : -- ALGLIB --
31171 : Copyright 21.12.2013 by Bochkanov Sergey
31172 : *************************************************************************/
31173 0 : static double qqpsolver_projectedtargetfunction(qqpbuffers* sstate,
31174 : /* Real */ ae_vector* x,
31175 : /* Real */ ae_vector* d,
31176 : double stp,
31177 : /* Real */ ae_vector* tmp0,
31178 : /* Real */ ae_vector* tmp1,
31179 : ae_state *_state)
31180 : {
31181 : ae_int_t n;
31182 : ae_int_t i;
31183 : double v;
31184 : double result;
31185 :
31186 :
31187 0 : n = sstate->n;
31188 0 : rvectorsetlengthatleast(tmp0, n, _state);
31189 0 : rvectorsetlengthatleast(tmp1, n, _state);
31190 :
31191 : /*
31192 : * Calculate projected point
31193 : */
31194 0 : for(i=0; i<=n-1; i++)
31195 : {
31196 0 : if( ae_fp_neq(stp,(double)(0)) )
31197 : {
31198 0 : v = x->ptr.p_double[i]+stp*d->ptr.p_double[i];
31199 : }
31200 : else
31201 : {
31202 0 : v = x->ptr.p_double[i];
31203 : }
31204 0 : if( sstate->havebndl.ptr.p_bool[i]&&ae_fp_less(v,sstate->bndl.ptr.p_double[i]) )
31205 : {
31206 0 : v = sstate->bndl.ptr.p_double[i];
31207 : }
31208 0 : if( sstate->havebndu.ptr.p_bool[i]&&ae_fp_greater(v,sstate->bndu.ptr.p_double[i]) )
31209 : {
31210 0 : v = sstate->bndu.ptr.p_double[i];
31211 : }
31212 0 : tmp0->ptr.p_double[i] = v;
31213 : }
31214 :
31215 : /*
31216 : * Function value at the Tmp0:
31217 : *
31218 : * f(x) = 0.5*x'*A*x + b'*x
31219 : */
31220 0 : result = 0.0;
31221 0 : for(i=0; i<=n-1; i++)
31222 : {
31223 0 : result = result+sstate->b.ptr.p_double[i]*tmp0->ptr.p_double[i];
31224 : }
31225 0 : if( sstate->akind==0 )
31226 : {
31227 :
31228 : /*
31229 : * Dense matrix A
31230 : */
31231 0 : result = result+0.5*rmatrixsyvmv(n, &sstate->densea, 0, 0, ae_true, tmp0, 0, tmp1, _state);
31232 : }
31233 : else
31234 : {
31235 :
31236 : /*
31237 : * sparse matrix A
31238 : */
31239 0 : ae_assert(sstate->akind==1, "QQPOptimize: unexpected AKind in ProjectedTargetFunction", _state);
31240 0 : result = result+0.5*sparsevsmv(&sstate->sparsea, sstate->sparseupper, tmp0, _state);
31241 : }
31242 0 : return result;
31243 : }
31244 :
31245 :
31246 : /*************************************************************************
31247 : Gradient of the target function:
31248 :
31249 : f(x) = 0.5*x'*A*x + b'*x
31250 :
31251 : which is equal to
31252 :
31253 : grad = A*x + b
31254 :
31255 : Here:
31256 : * x is array[N]
31257 : * A is array[N,N]
31258 : * b is array[N]
31259 :
31260 : INPUT PARAMETERS:
31261 : SState - structure which stores function terms (not modified)
31262 : X - location
31263 : G - possibly preallocated buffer
31264 :
31265 : OUTPUT PARAMETERS:
31266 : G - array[N], gradient
31267 :
31268 : -- ALGLIB --
31269 : Copyright 21.12.2013 by Bochkanov Sergey
31270 : *************************************************************************/
31271 0 : static void qqpsolver_targetgradient(qqpbuffers* sstate,
31272 : /* Real */ ae_vector* x,
31273 : /* Real */ ae_vector* g,
31274 : ae_state *_state)
31275 : {
31276 : ae_int_t n;
31277 :
31278 :
31279 0 : n = sstate->n;
31280 0 : rvectorsetlengthatleast(g, n, _state);
31281 0 : if( sstate->akind==0 )
31282 : {
31283 :
31284 : /*
31285 : * Dense matrix A
31286 : */
31287 0 : rmatrixsymv(n, 1.0, &sstate->densea, 0, 0, ae_true, x, 0, 0.0, g, 0, _state);
31288 : }
31289 : else
31290 : {
31291 :
31292 : /*
31293 : * Sparse matrix A
31294 : */
31295 0 : ae_assert(sstate->akind==1, "QQPOptimize: unexpected AKind in TargetGradient", _state);
31296 0 : sparsesmv(&sstate->sparsea, sstate->sparseupper, x, g, _state);
31297 : }
31298 0 : ae_v_add(&g->ptr.p_double[0], 1, &sstate->b.ptr.p_double[0], 1, ae_v_len(0,n-1));
31299 0 : }
31300 :
31301 :
31302 : /*************************************************************************
31303 : First and second derivatives of the "extended" target function along
31304 : specified direction. Target function is called "extended" because of
31305 : additional slack variables and has form:
31306 :
31307 : f(x) = 0.5*x'*A*x + b'*x + penaltyfactor*0.5*(C*x-b)'*(C*x-b)
31308 :
31309 : with gradient
31310 :
31311 : grad = A*x + b + penaltyfactor*C'*(C*x-b)
31312 :
31313 : Quadratic model has form
31314 :
31315 : F(x0+alpha*D) = D2*alpha^2 + D1*alpha
31316 :
31317 : INPUT PARAMETERS:
31318 : SState - structure which is used to obtain quadratic term of the model
31319 : X - current point, array[N]
31320 : D - direction across which derivatives are calculated, array[N]
31321 : G - gradient at current point (pre-calculated by caller), array[N]
31322 :
31323 : OUTPUT PARAMETERS:
31324 : D1 - linear coefficient
31325 : D1Est - estimate of D1 sign, accounting for possible numerical
31326 : errors:
31327 : * >0 means "almost surely positive"
31328 : * <0 means "almost surely negative"
31329 : * =0 means "pessimistic estimate of numerical errors
31330 : in D1 is larger than magnitude of D1 itself; it is
31331 : impossible to reliably distinguish D1 from zero".
31332 : D2 - quadratic coefficient
31333 : D2Est - estimate of D2 sign, accounting for possible numerical
31334 : errors:
31335 : * >0 means "almost surely positive"
31336 : * <0 means "almost surely negative"
31337 : * =0 means "pessimistic estimate of numerical errors
31338 : in D2 is larger than magnitude of D2 itself; it is
31339 : impossible to reliably distinguish D2 from zero".
31340 :
31341 : -- ALGLIB --
31342 : Copyright 14.05.2014 by Bochkanov Sergey
31343 : *************************************************************************/
31344 0 : static void qqpsolver_quadraticmodel(qqpbuffers* sstate,
31345 : /* Real */ ae_vector* x,
31346 : /* Real */ ae_vector* d,
31347 : /* Real */ ae_vector* g,
31348 : double* d1,
31349 : ae_int_t* d1est,
31350 : double* d2,
31351 : ae_int_t* d2est,
31352 : /* Real */ ae_vector* tmp0,
31353 : ae_state *_state)
31354 : {
31355 : ae_int_t n;
31356 : ae_int_t i;
31357 : double v;
31358 : double mx;
31359 : double mb;
31360 : double md;
31361 :
31362 0 : *d1 = 0;
31363 0 : *d1est = 0;
31364 0 : *d2 = 0;
31365 0 : *d2est = 0;
31366 :
31367 0 : n = sstate->n;
31368 :
31369 : /*
31370 : * Maximums
31371 : */
31372 0 : mx = 0.0;
31373 0 : md = 0.0;
31374 0 : mb = 0.0;
31375 0 : for(i=0; i<=n-1; i++)
31376 : {
31377 0 : mx = ae_maxreal(mx, ae_fabs(x->ptr.p_double[i], _state), _state);
31378 0 : md = ae_maxreal(md, ae_fabs(d->ptr.p_double[i], _state), _state);
31379 : }
31380 0 : for(i=0; i<=n-1; i++)
31381 : {
31382 0 : mb = ae_maxreal(mb, ae_fabs(sstate->b.ptr.p_double[i], _state), _state);
31383 : }
31384 :
31385 : /*
31386 : * D2
31387 : */
31388 0 : if( sstate->akind==0 )
31389 : {
31390 :
31391 : /*
31392 : * Dense matrix A
31393 : */
31394 0 : *d2 = 0.5*rmatrixsyvmv(n, &sstate->densea, 0, 0, ae_true, d, 0, tmp0, _state);
31395 : }
31396 : else
31397 : {
31398 :
31399 : /*
31400 : * Sparse matrix A
31401 : */
31402 0 : ae_assert(sstate->akind==1, "QQPOptimize: unexpected AKind in TargetGradient", _state);
31403 0 : *d2 = 0.5*sparsevsmv(&sstate->sparsea, sstate->sparseupper, d, _state);
31404 : }
31405 0 : v = ae_v_dotproduct(&d->ptr.p_double[0], 1, &g->ptr.p_double[0], 1, ae_v_len(0,n-1));
31406 0 : *d1 = v;
31407 :
31408 : /*
31409 : * Error estimates
31410 : */
31411 0 : estimateparabolicmodel(sstate->absasum, sstate->absasum2, mx, mb, md, *d1, *d2, d1est, d2est, _state);
31412 0 : }
31413 :
31414 :
31415 : /*************************************************************************
31416 : This function accepts quadratic model of the form
31417 :
31418 : f(x) = 0.5*x'*A*x + b'*x + penaltyfactor*0.5*(C*x-b)'*(C*x-b)
31419 :
31420 : and list of possible steps along direction D. It chooses best step (one
31421 : which achieves minimum value of the target function) and moves current
31422 : point (given by SAS object) to the new location. Step is bounded subject
31423 : to boundary constraints.
31424 :
31425 : Candidate steps are divided into two groups:
31426 : * "default" step, which is always performed when no candidate steps LONGER
31427 : THAN THE DEFAULT ONE is given. This candidate MUST reduce target
31428 : function value; it is responsibility of caller to provide default
31429 : candidate which reduces target function.
31430 : * "additional candidates", which may be shorter or longer than the default
31431 : step. Candidates which are shorter that the default step are ignored;
31432 : candidates which are longer than the "default" step are tested.
31433 :
31434 : The idea is that we ALWAYS try "default" step, and it is responsibility of
31435 : the caller to provide us with something which is worth trying. This step
31436 : may activate some constraint - that's why we stopped at "default" step
31437 : size. However, we may also try longer steps which may activate additional
31438 : constraints and further reduce function value.
31439 :
31440 : INPUT PARAMETERS:
31441 : SState - structure which stores model
31442 : SAS - active set structure which stores current point in SAS.XC
31443 : D - direction for step
31444 : Stp - step length for "default" candidate
31445 : NeedAct - whether default candidate activates some constraint;
31446 : if NeedAct is True, constraint given by CIdc/CVal is
31447 : GUARANTEED to be activated in the final point.
31448 : CIdx - if NeedAct is True, stores index of the constraint to activate
31449 : CVal - if NeedAct is True, stores constrained value;
31450 : SAS.XC[CIdx] is forced to be equal to CVal.
31451 : AddSteps- array[AddStepsCnt] of additional steps:
31452 : * AddSteps[]<=Stp are ignored
31453 : * AddSteps[]>Stp are tried
31454 : Activated- possibly preallocated buffer; previously allocated memory
31455 : will be reused.
31456 : Tmp0/1 - possibly preallocated buffers; previously allocated memory
31457 : will be reused.
31458 :
31459 : OUTPUT PARAMETERS:
31460 : SAS - SAS.XC is set to new point; if there was a constraint
31461 : specified by NeedAct/CIdx/CVal, it will be activated
31462 : (other constraints may be activated too, but this one is
31463 : guaranteed to be active in the final point).
31464 : Activated- elements of this array are set to True, if I-th constraint
31465 : as inactive at previous point, but become active in the
31466 : new one.
31467 : Situations when we deactivate xi>=0 and activate xi<=1 are
31468 : considered as activation of previously inactive constraint
31469 :
31470 : -- ALGLIB --
31471 : Copyright 14.05.2014 by Bochkanov Sergey
31472 : *************************************************************************/
31473 0 : static void qqpsolver_findbeststepandmove(qqpbuffers* sstate,
31474 : sactiveset* sas,
31475 : /* Real */ ae_vector* d,
31476 : double stp,
31477 : ae_bool needact,
31478 : ae_int_t cidx,
31479 : double cval,
31480 : /* Real */ ae_vector* addsteps,
31481 : ae_int_t addstepscnt,
31482 : /* Boolean */ ae_vector* activated,
31483 : /* Real */ ae_vector* tmp0,
31484 : /* Real */ ae_vector* tmp1,
31485 : ae_state *_state)
31486 : {
31487 : ae_int_t n;
31488 : ae_int_t i;
31489 : ae_int_t k;
31490 : double v;
31491 : double stpbest;
31492 : double fbest;
31493 : double fcand;
31494 :
31495 :
31496 0 : n = sstate->n;
31497 0 : rvectorsetlengthatleast(tmp0, n, _state);
31498 0 : bvectorsetlengthatleast(activated, n, _state);
31499 :
31500 : /*
31501 : * Calculate initial step, store to Tmp0
31502 : *
31503 : * NOTE: Tmp0 is guaranteed to be feasible w.r.t. boundary constraints
31504 : */
31505 0 : for(i=0; i<=n-1; i++)
31506 : {
31507 0 : v = sas->xc.ptr.p_double[i]+stp*d->ptr.p_double[i];
31508 0 : if( sstate->havebndl.ptr.p_bool[i]&&ae_fp_less(v,sstate->bndl.ptr.p_double[i]) )
31509 : {
31510 0 : v = sstate->bndl.ptr.p_double[i];
31511 : }
31512 0 : if( sstate->havebndu.ptr.p_bool[i]&&ae_fp_greater(v,sstate->bndu.ptr.p_double[i]) )
31513 : {
31514 0 : v = sstate->bndu.ptr.p_double[i];
31515 : }
31516 0 : tmp0->ptr.p_double[i] = v;
31517 : }
31518 0 : if( needact )
31519 : {
31520 0 : tmp0->ptr.p_double[cidx] = cval;
31521 : }
31522 :
31523 : /*
31524 : * Try additional steps, if AddStepsCnt>0
31525 : */
31526 0 : if( addstepscnt>0 )
31527 : {
31528 :
31529 : /*
31530 : * Find best step
31531 : */
31532 0 : stpbest = stp;
31533 0 : fbest = qqpsolver_projectedtargetfunction(sstate, &sas->xc, d, stpbest, tmp0, tmp1, _state);
31534 0 : for(k=0; k<=addstepscnt-1; k++)
31535 : {
31536 0 : if( ae_fp_greater(addsteps->ptr.p_double[k],stp) )
31537 : {
31538 0 : fcand = qqpsolver_projectedtargetfunction(sstate, &sas->xc, d, addsteps->ptr.p_double[k], tmp0, tmp1, _state);
31539 0 : if( ae_fp_less(fcand,fbest) )
31540 : {
31541 0 : fbest = fcand;
31542 0 : stpbest = addsteps->ptr.p_double[k];
31543 : }
31544 : }
31545 : }
31546 :
31547 : /*
31548 : * Prepare best step
31549 : *
31550 : * NOTE: because only AddSteps[]>Stp were checked,
31551 : * this step will activate constraint CIdx.
31552 : */
31553 0 : for(i=0; i<=n-1; i++)
31554 : {
31555 0 : v = sas->xc.ptr.p_double[i]+stpbest*d->ptr.p_double[i];
31556 0 : if( sstate->havebndl.ptr.p_bool[i]&&ae_fp_less(v,sstate->bndl.ptr.p_double[i]) )
31557 : {
31558 0 : v = sstate->bndl.ptr.p_double[i];
31559 : }
31560 0 : if( sstate->havebndu.ptr.p_bool[i]&&ae_fp_greater(v,sstate->bndu.ptr.p_double[i]) )
31561 : {
31562 0 : v = sstate->bndu.ptr.p_double[i];
31563 : }
31564 0 : tmp0->ptr.p_double[i] = v;
31565 : }
31566 0 : if( needact )
31567 : {
31568 0 : tmp0->ptr.p_double[cidx] = cval;
31569 : }
31570 : }
31571 :
31572 : /*
31573 : * Fill Activated array by information about activated constraints.
31574 : * Perform step
31575 : */
31576 0 : for(i=0; i<=n-1; i++)
31577 : {
31578 0 : activated->ptr.p_bool[i] = ae_false;
31579 0 : v = tmp0->ptr.p_double[i];
31580 0 : if( ae_fp_eq(v,sas->xc.ptr.p_double[i]) )
31581 : {
31582 0 : continue;
31583 : }
31584 0 : if( sstate->havebndl.ptr.p_bool[i]&&ae_fp_eq(v,sstate->bndl.ptr.p_double[i]) )
31585 : {
31586 0 : activated->ptr.p_bool[i] = ae_true;
31587 : }
31588 0 : if( sstate->havebndu.ptr.p_bool[i]&&ae_fp_eq(v,sstate->bndu.ptr.p_double[i]) )
31589 : {
31590 0 : activated->ptr.p_bool[i] = ae_true;
31591 : }
31592 : }
31593 0 : sasmoveto(sas, tmp0, needact, cidx, cval, _state);
31594 0 : }
31595 :
31596 :
31597 : /*************************************************************************
31598 : This function prepares data for constrained Newton step for penalized
31599 : quadratic model of the form
31600 :
31601 : f(x) = 0.5*x'*A*x + b'*x + penaltyfactor*0.5*(C*x-b)'*(C*x-b)
31602 :
31603 : where A can be dense or sparse, and model is considered subject to equality
31604 : constraints specified by SState.SAS.XC object. Constraint is considered
31605 : active if XC[i] is exactly BndL[i] or BndU[i], i.e. we ignore internal
31606 : list of constraints monitored by SAS object. Our own set of constraints
31607 : includes all constraints stored by SAS, but also may include some
31608 : constraints which are inactive in SAS.
31609 :
31610 : "Preparation" means that Cholesky decomposition of the effective system
31611 : matrix is performed, and we can perform constrained Newton step.
31612 :
31613 : This function works as black box. It uses fields of SState which are marked
31614 : as "Variables for constrained Newton phase", and only this function and
31615 : its friends know about these variables. Everyone else should use:
31616 : * CNewtonBuild() to prepare initial Cholesky decomposition for step
31617 : * CNewtonStep() to perform constrained Newton step
31618 : * CNewtonUpdate() to update Cholesky matrix after point was moved and
31619 : constraints were updated. In some cases it is possible to efficiently
31620 : re-calculate Cholesky decomposition if you know which constraints were
31621 : activated. If efficient re-calculation is impossible, this function
31622 : returns False.
31623 :
31624 : INPUT PARAMETERS:
31625 : SState - structure which stores model and temporaries for CN phase;
31626 : in particular, SAS.XC stores current point.
31627 : SparseSolver-which sparse solver to use for sparse model; ignored for
31628 : dense QP. Can be:
31629 : * 2 - SKS-based Cholesky
31630 : NCholesky- counter which is incremented after Cholesky (successful or
31631 : failed one)
31632 :
31633 : OUTPUT PARAMETERS:
31634 : NCholesky- possibly updated counter
31635 :
31636 : RESULT:
31637 : True, if Cholesky decomposition was successfully performed.
31638 : False, if a) matrix was semi-definite or indefinite, or b) particular
31639 : combination of matrix type (sparse) and constraints (general linear)
31640 : is not supported.
31641 :
31642 : NOTE: this function may routinely return False, for indefinite matrices or
31643 : for sparse problems with general linear constraints. You should be
31644 : able to handle such situations.
31645 :
31646 : -- ALGLIB --
31647 : Copyright 14.05.2014 by Bochkanov Sergey
31648 : *************************************************************************/
31649 0 : static ae_bool qqpsolver_cnewtonbuild(qqpbuffers* sstate,
31650 : ae_int_t sparsesolver,
31651 : ae_int_t* ncholesky,
31652 : ae_state *_state)
31653 : {
31654 : ae_int_t n;
31655 : ae_int_t i;
31656 : ae_int_t j;
31657 : ae_int_t k;
31658 : double v;
31659 : ae_bool b;
31660 : ae_int_t ridx0;
31661 : ae_int_t ridx1;
31662 : ae_int_t nfree;
31663 : ae_bool result;
31664 :
31665 :
31666 0 : result = ae_false;
31667 :
31668 : /*
31669 : * Fetch often used fields
31670 : */
31671 0 : n = sstate->n;
31672 :
31673 : /*
31674 : * 1. Set CNModelAge to zero
31675 : * 2. Generate YIdx - reordering of variables such that free variables
31676 : * come first and are ordered by ascending, fixed are last ones and
31677 : * have no particular ordering.
31678 : *
31679 : * This step is same for dense and sparse problems.
31680 : */
31681 0 : sstate->cnmodelage = 0;
31682 0 : ivectorsetlengthatleast(&sstate->yidx, n, _state);
31683 0 : ridx0 = 0;
31684 0 : ridx1 = n-1;
31685 0 : for(i=0; i<=n-1; i++)
31686 : {
31687 0 : sstate->yidx.ptr.p_int[i] = -1;
31688 : }
31689 0 : for(i=0; i<=n-1; i++)
31690 : {
31691 0 : ae_assert(!sstate->havebndl.ptr.p_bool[i]||ae_fp_greater_eq(sstate->sas.xc.ptr.p_double[i],sstate->bndl.ptr.p_double[i]), "CNewtonBuild: internal error", _state);
31692 0 : ae_assert(!sstate->havebndu.ptr.p_bool[i]||ae_fp_less_eq(sstate->sas.xc.ptr.p_double[i],sstate->bndu.ptr.p_double[i]), "CNewtonBuild: internal error", _state);
31693 0 : b = ae_false;
31694 0 : b = b||(sstate->havebndl.ptr.p_bool[i]&&ae_fp_eq(sstate->sas.xc.ptr.p_double[i],sstate->bndl.ptr.p_double[i]));
31695 0 : b = b||(sstate->havebndu.ptr.p_bool[i]&&ae_fp_eq(sstate->sas.xc.ptr.p_double[i],sstate->bndu.ptr.p_double[i]));
31696 0 : if( b )
31697 : {
31698 0 : sstate->yidx.ptr.p_int[ridx1] = i;
31699 0 : ridx1 = ridx1-1;
31700 : }
31701 : else
31702 : {
31703 0 : sstate->yidx.ptr.p_int[ridx0] = i;
31704 0 : ridx0 = ridx0+1;
31705 : }
31706 : }
31707 0 : ae_assert(ridx0==ridx1+1, "CNewtonBuild: internal error", _state);
31708 0 : nfree = ridx0;
31709 0 : sstate->nfree = nfree;
31710 0 : if( nfree==0 )
31711 : {
31712 0 : return result;
31713 : }
31714 :
31715 : /*
31716 : * Constrained Newton matrix: dense version
31717 : */
31718 0 : if( sstate->akind==0 )
31719 : {
31720 0 : rmatrixsetlengthatleast(&sstate->densez, n, n, _state);
31721 0 : rvectorsetlengthatleast(&sstate->tmpcn, n, _state);
31722 0 : for(i=0; i<=n-1; i++)
31723 : {
31724 0 : for(j=i; j<=n-1; j++)
31725 : {
31726 0 : sstate->densez.ptr.pp_double[i][j] = sstate->densea.ptr.pp_double[i][j];
31727 : }
31728 : }
31729 0 : for(i=1; i<=nfree-1; i++)
31730 : {
31731 0 : ae_assert(sstate->yidx.ptr.p_int[i]>sstate->yidx.ptr.p_int[i-1], "CNewtonBuild: integrity check failed", _state);
31732 : }
31733 0 : for(i=0; i<=nfree-1; i++)
31734 : {
31735 0 : k = sstate->yidx.ptr.p_int[i];
31736 0 : for(j=i; j<=nfree-1; j++)
31737 : {
31738 0 : sstate->densez.ptr.pp_double[i][j] = sstate->densez.ptr.pp_double[k][sstate->yidx.ptr.p_int[j]];
31739 : }
31740 : }
31741 0 : rvectorsetlengthatleast(&sstate->regdiag, n, _state);
31742 0 : for(i=0; i<=nfree-1; i++)
31743 : {
31744 0 : v = 0.0;
31745 0 : for(j=0; j<=i-1; j++)
31746 : {
31747 0 : v = v+ae_fabs(sstate->densez.ptr.pp_double[j][i], _state);
31748 : }
31749 0 : for(j=i; j<=nfree-1; j++)
31750 : {
31751 0 : v = v+ae_fabs(sstate->densez.ptr.pp_double[i][j], _state);
31752 : }
31753 0 : if( ae_fp_eq(v,(double)(0)) )
31754 : {
31755 0 : v = 1.0;
31756 : }
31757 0 : sstate->regdiag.ptr.p_double[i] = qqpsolver_regz*v;
31758 : }
31759 0 : for(i=0; i<=nfree-1; i++)
31760 : {
31761 0 : sstate->densez.ptr.pp_double[i][i] = sstate->densez.ptr.pp_double[i][i]+sstate->regdiag.ptr.p_double[i];
31762 : }
31763 0 : inc(ncholesky, _state);
31764 0 : if( !spdmatrixcholeskyrec(&sstate->densez, 0, nfree, ae_true, &sstate->tmpcn, _state) )
31765 : {
31766 0 : return result;
31767 : }
31768 0 : for(i=nfree-1; i>=0; i--)
31769 : {
31770 0 : ae_v_move(&sstate->tmpcn.ptr.p_double[i], 1, &sstate->densez.ptr.pp_double[i][i], 1, ae_v_len(i,nfree-1));
31771 0 : k = sstate->yidx.ptr.p_int[i];
31772 0 : for(j=k; j<=n-1; j++)
31773 : {
31774 0 : sstate->densez.ptr.pp_double[k][j] = (double)(0);
31775 : }
31776 0 : for(j=i; j<=nfree-1; j++)
31777 : {
31778 0 : sstate->densez.ptr.pp_double[k][sstate->yidx.ptr.p_int[j]] = sstate->tmpcn.ptr.p_double[j];
31779 : }
31780 : }
31781 0 : for(i=nfree; i<=n-1; i++)
31782 : {
31783 0 : k = sstate->yidx.ptr.p_int[i];
31784 0 : sstate->densez.ptr.pp_double[k][k] = 1.0;
31785 0 : for(j=k+1; j<=n-1; j++)
31786 : {
31787 0 : sstate->densez.ptr.pp_double[k][j] = (double)(0);
31788 : }
31789 : }
31790 0 : result = ae_true;
31791 0 : return result;
31792 : }
31793 :
31794 : /*
31795 : * Constrained Newton matrix: sparse version
31796 : */
31797 0 : if( sstate->akind==1 )
31798 : {
31799 0 : ae_assert(sparsesolver==2, "CNewtonBuild: internal error", _state);
31800 :
31801 : /*
31802 : * Copy sparse A to Z and fill rows/columns corresponding to active
31803 : * constraints by zeros. Diagonal elements corresponding to active
31804 : * constraints are filled by unit values.
31805 : */
31806 0 : sparsecopytosksbuf(&sstate->sparsea, &sstate->sparsecca, _state);
31807 0 : rvectorsetlengthatleast(&sstate->tmpcn, n, _state);
31808 0 : for(i=0; i<=n-1; i++)
31809 : {
31810 0 : sstate->tmpcn.ptr.p_double[i] = (double)(0);
31811 : }
31812 0 : for(i=nfree; i<=n-1; i++)
31813 : {
31814 0 : sstate->tmpcn.ptr.p_double[sstate->yidx.ptr.p_int[i]] = (double)(1);
31815 : }
31816 0 : for(i=0; i<=n-1; i++)
31817 : {
31818 0 : k = sstate->sparsecca.ridx.ptr.p_int[i];
31819 0 : for(j=i-sstate->sparsecca.didx.ptr.p_int[i]; j<=i; j++)
31820 : {
31821 0 : if( ae_fp_neq(sstate->tmpcn.ptr.p_double[i],(double)(0))||ae_fp_neq(sstate->tmpcn.ptr.p_double[j],(double)(0)) )
31822 : {
31823 :
31824 : /*
31825 : * I-th or J-th variable is in active set (constrained)
31826 : */
31827 0 : if( i==j )
31828 : {
31829 0 : sstate->sparsecca.vals.ptr.p_double[k] = 1.0;
31830 : }
31831 : else
31832 : {
31833 0 : sstate->sparsecca.vals.ptr.p_double[k] = 0.0;
31834 : }
31835 : }
31836 0 : k = k+1;
31837 : }
31838 : }
31839 :
31840 : /*
31841 : * Perform sparse Cholesky
31842 : */
31843 0 : inc(ncholesky, _state);
31844 0 : if( !sparsecholeskyskyline(&sstate->sparsecca, n, sstate->sparseupper, _state) )
31845 : {
31846 0 : return result;
31847 : }
31848 0 : result = ae_true;
31849 0 : return result;
31850 : }
31851 :
31852 : /*
31853 : * Unexpected :)
31854 : */
31855 0 : ae_assert(ae_false, "CNewtonBuild: internal error", _state);
31856 0 : return result;
31857 : }
31858 :
31859 :
31860 : /*************************************************************************
31861 : This function updates equality-constrained Cholesky matrix after
31862 : activation of the new equality constraints. Matrix being updated is
31863 : quadratic term of the function below
31864 :
31865 : f(x) = 0.5*x'*A*x + b'*x + penaltyfactor*0.5*(C*x-b)'*(C*x-b)
31866 :
31867 : where A can be dense or sparse.
31868 :
31869 : This function uses YIdx[] array (set by CNewtonBuild() function) to
31870 : distinguish between active and inactive constraints.
31871 :
31872 : This function works as black box. It uses fields of SState which are marked
31873 : as "Variables for constrained Newton phase", and only this function and
31874 : its friends know about these variables. Everyone else should use:
31875 : * CNewtonBuild() to prepare initial Cholesky decomposition for step
31876 : * CNewtonStep() to perform constrained Newton step
31877 : * CNewtonUpdate() to update Cholesky matrix after point was moved and
31878 : constraints were updated. In some cases it is possible to efficiently
31879 : re-calculate Cholesky decomposition if you know which constraints were
31880 : activated. If efficient re-calculation is impossible, this function
31881 : returns False.
31882 :
31883 : INPUT PARAMETERS:
31884 : SState - structure which stores model and temporaries for CN phase;
31885 : in particular, SAS.XC stores current point.
31886 : Settings - QQPSettings object which was initialized by appropriate
31887 : construction function.
31888 : NCUpdates- counter which is incremented after each update (one update
31889 : means one variable being fixed)
31890 :
31891 : OUTPUT PARAMETERS:
31892 : NCUpdates- possibly updated counter
31893 :
31894 : RESULT:
31895 : True, if Cholesky decomposition was successfully performed.
31896 : False, if a) model age was too high, or b) particular combination of
31897 : matrix type (sparse) and constraints (general linear) is not supported
31898 :
31899 : NOTE: this function may routinely return False.
31900 : You should be able to handle such situations.
31901 :
31902 : -- ALGLIB --
31903 : Copyright 14.05.2014 by Bochkanov Sergey
31904 : *************************************************************************/
31905 0 : static ae_bool qqpsolver_cnewtonupdate(qqpbuffers* sstate,
31906 : qqpsettings* settings,
31907 : ae_int_t* ncupdates,
31908 : ae_state *_state)
31909 : {
31910 : ae_int_t n;
31911 : ae_int_t nfree;
31912 : ae_int_t ntofix;
31913 : ae_bool b;
31914 : ae_int_t ridx0;
31915 : ae_int_t ridx1;
31916 : ae_int_t i;
31917 : ae_int_t k;
31918 : ae_bool result;
31919 :
31920 :
31921 0 : result = ae_false;
31922 :
31923 : /*
31924 : * Cholesky updates for sparse problems are not supported
31925 : */
31926 0 : if( sstate->akind==1 )
31927 : {
31928 0 : return result;
31929 : }
31930 :
31931 : /*
31932 : * Fetch often used fields
31933 : */
31934 0 : n = sstate->n;
31935 0 : nfree = sstate->nfree;
31936 :
31937 : /*
31938 : * Determine variables to fix and move them to YIdx[NFree-NToFix:NFree-1]
31939 : * Exit if CNModelAge increased too much.
31940 : */
31941 0 : ivectorsetlengthatleast(&sstate->tmpcni, n, _state);
31942 0 : ridx0 = 0;
31943 0 : ridx1 = nfree-1;
31944 0 : for(i=0; i<=nfree-1; i++)
31945 : {
31946 0 : sstate->tmpcni.ptr.p_int[i] = -1;
31947 : }
31948 0 : for(k=0; k<=nfree-1; k++)
31949 : {
31950 0 : i = sstate->yidx.ptr.p_int[k];
31951 0 : ae_assert(!sstate->havebndl.ptr.p_bool[i]||ae_fp_greater_eq(sstate->sas.xc.ptr.p_double[i],sstate->bndl.ptr.p_double[i]), "CNewtonUpdate: internal error", _state);
31952 0 : ae_assert(!sstate->havebndu.ptr.p_bool[i]||ae_fp_less_eq(sstate->sas.xc.ptr.p_double[i],sstate->bndu.ptr.p_double[i]), "CNewtonUpdate: internal error", _state);
31953 0 : b = ae_false;
31954 0 : b = b||(sstate->havebndl.ptr.p_bool[i]&&ae_fp_eq(sstate->sas.xc.ptr.p_double[i],sstate->bndl.ptr.p_double[i]));
31955 0 : b = b||(sstate->havebndu.ptr.p_bool[i]&&ae_fp_eq(sstate->sas.xc.ptr.p_double[i],sstate->bndu.ptr.p_double[i]));
31956 0 : if( b )
31957 : {
31958 0 : sstate->tmpcni.ptr.p_int[ridx1] = i;
31959 0 : ridx1 = ridx1-1;
31960 : }
31961 : else
31962 : {
31963 0 : sstate->tmpcni.ptr.p_int[ridx0] = i;
31964 0 : ridx0 = ridx0+1;
31965 : }
31966 : }
31967 0 : ae_assert(ridx0==ridx1+1, "CNewtonUpdate: internal error", _state);
31968 0 : ntofix = nfree-ridx0;
31969 0 : if( ntofix==0||ntofix==nfree )
31970 : {
31971 0 : return result;
31972 : }
31973 0 : if( sstate->cnmodelage+ntofix>settings->cnmaxupdates )
31974 : {
31975 0 : return result;
31976 : }
31977 0 : for(i=0; i<=nfree-1; i++)
31978 : {
31979 0 : sstate->yidx.ptr.p_int[i] = sstate->tmpcni.ptr.p_int[i];
31980 : }
31981 :
31982 : /*
31983 : * Constrained Newton matrix: dense version.
31984 : */
31985 0 : if( sstate->akind==0 )
31986 : {
31987 :
31988 : /*
31989 : * Update Cholesky matrix with SPDMatrixCholeskyUpdateFixBuf()
31990 : */
31991 0 : bvectorsetlengthatleast(&sstate->tmpcnb, n, _state);
31992 0 : for(i=0; i<=n-1; i++)
31993 : {
31994 0 : sstate->tmpcnb.ptr.p_bool[i] = ae_false;
31995 : }
31996 0 : for(i=nfree-ntofix; i<=nfree-1; i++)
31997 : {
31998 0 : sstate->tmpcnb.ptr.p_bool[sstate->yidx.ptr.p_int[i]] = ae_true;
31999 : }
32000 0 : spdmatrixcholeskyupdatefixbuf(&sstate->densez, n, ae_true, &sstate->tmpcnb, &sstate->tmpcn, _state);
32001 :
32002 : /*
32003 : * Update information stored in State and exit
32004 : */
32005 0 : sstate->nfree = nfree-ntofix;
32006 0 : sstate->cnmodelage = sstate->cnmodelage+ntofix;
32007 0 : *ncupdates = *ncupdates+ntofix;
32008 0 : result = ae_true;
32009 0 : return result;
32010 : }
32011 :
32012 : /*
32013 : * Unexpected :)
32014 : */
32015 0 : ae_assert(ae_false, "CNewtonUpdate: internal error", _state);
32016 0 : return result;
32017 : }
32018 :
32019 :
32020 : /*************************************************************************
32021 : This function prepares equality-constrained Newton step using previously
32022 : calculated constrained Cholesky matrix of the problem
32023 :
32024 : f(x) = 0.5*x'*A*x + b'*x + penaltyfactor*0.5*(C*x-b)'*(C*x-b)
32025 :
32026 : where A can be dense or sparse.
32027 :
32028 : As input, this function accepts gradient at the current location. As
32029 : output, it returns step vector (replaces gradient).
32030 :
32031 : This function works as black box. It uses fields of SState which are marked
32032 : as "Variables for constrained Newton phase", and only this function and
32033 : its friends know about these variables. Everyone else should use:
32034 : * CNewtonBuild() to prepare initial Cholesky decomposition for step
32035 : * CNewtonStep() to perform constrained Newton step
32036 : * CNewtonUpdate() to update Cholesky matrix after point was moved and
32037 : constraints were updated. In some cases it is possible to efficiently
32038 : re-calculate Cholesky decomposition if you know which constraints were
32039 : activated. If efficient re-calculation is impossible, this function
32040 : returns False.
32041 :
32042 : INPUT PARAMETERS:
32043 : SState - structure which stores model and temporaries for CN phase;
32044 : in particular, SAS.XC stores current point.
32045 : Settings - QQPSettings object which was initialized by appropriate
32046 : construction function.
32047 : GC - array[N], gradient of the target function
32048 :
32049 : OUTPUT PARAMETERS:
32050 : GC - array[N], step vector (on success)
32051 :
32052 : RESULT:
32053 : True, if step was successfully calculated.
32054 : False, if step calculation failed:
32055 : a) gradient was exactly zero,
32056 : b) gradient norm was smaller than EpsG (stopping condition)
32057 : c) all variables were equality-constrained
32058 :
32059 : NOTE: this function may routinely return False.
32060 : You should be able to handle such situations.
32061 :
32062 : -- ALGLIB --
32063 : Copyright 14.05.2014 by Bochkanov Sergey
32064 : *************************************************************************/
32065 0 : static ae_bool qqpsolver_cnewtonstep(qqpbuffers* sstate,
32066 : qqpsettings* settings,
32067 : /* Real */ ae_vector* gc,
32068 : ae_state *_state)
32069 : {
32070 : ae_int_t i;
32071 : ae_int_t n;
32072 : ae_int_t nfree;
32073 : double v;
32074 : ae_bool result;
32075 :
32076 :
32077 0 : result = ae_false;
32078 0 : n = sstate->n;
32079 0 : nfree = sstate->nfree;
32080 0 : for(i=nfree; i<=n-1; i++)
32081 : {
32082 0 : gc->ptr.p_double[sstate->yidx.ptr.p_int[i]] = 0.0;
32083 : }
32084 0 : v = ae_v_dotproduct(&gc->ptr.p_double[0], 1, &gc->ptr.p_double[0], 1, ae_v_len(0,n-1));
32085 0 : if( ae_fp_less_eq(ae_sqrt(v, _state),settings->epsg) )
32086 : {
32087 0 : return result;
32088 : }
32089 0 : for(i=0; i<=n-1; i++)
32090 : {
32091 0 : gc->ptr.p_double[i] = -gc->ptr.p_double[i];
32092 : }
32093 0 : if( sstate->akind==0 )
32094 : {
32095 :
32096 : /*
32097 : * Dense Newton step.
32098 : * Use straightforward Cholesky solver.
32099 : */
32100 0 : fblscholeskysolve(&sstate->densez, 1.0, n, ae_true, gc, &sstate->tmpcn, _state);
32101 0 : result = ae_true;
32102 0 : return result;
32103 : }
32104 0 : if( sstate->akind==1 )
32105 : {
32106 :
32107 : /*
32108 : * Sparse Newton step.
32109 : *
32110 : * We have T*T' = L*L' = U'*U (depending on specific triangle stored in SparseCCA).
32111 : */
32112 0 : if( sstate->sparseupper )
32113 : {
32114 0 : sparsetrsv(&sstate->sparsecca, sstate->sparseupper, ae_false, 1, gc, _state);
32115 0 : sparsetrsv(&sstate->sparsecca, sstate->sparseupper, ae_false, 0, gc, _state);
32116 : }
32117 : else
32118 : {
32119 0 : sparsetrsv(&sstate->sparsecca, sstate->sparseupper, ae_false, 0, gc, _state);
32120 0 : sparsetrsv(&sstate->sparsecca, sstate->sparseupper, ae_false, 1, gc, _state);
32121 : }
32122 0 : result = ae_true;
32123 0 : return result;
32124 : }
32125 0 : ae_assert(ae_false, "CNewtonStep: internal error", _state);
32126 0 : return result;
32127 : }
32128 :
32129 :
32130 0 : void _qqpsettings_init(void* _p, ae_state *_state, ae_bool make_automatic)
32131 : {
32132 0 : qqpsettings *p = (qqpsettings*)_p;
32133 0 : ae_touch_ptr((void*)p);
32134 0 : }
32135 :
32136 :
32137 0 : void _qqpsettings_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
32138 : {
32139 0 : qqpsettings *dst = (qqpsettings*)_dst;
32140 0 : qqpsettings *src = (qqpsettings*)_src;
32141 0 : dst->epsg = src->epsg;
32142 0 : dst->epsf = src->epsf;
32143 0 : dst->epsx = src->epsx;
32144 0 : dst->maxouterits = src->maxouterits;
32145 0 : dst->cgphase = src->cgphase;
32146 0 : dst->cnphase = src->cnphase;
32147 0 : dst->cgminits = src->cgminits;
32148 0 : dst->cgmaxits = src->cgmaxits;
32149 0 : dst->cnmaxupdates = src->cnmaxupdates;
32150 0 : dst->sparsesolver = src->sparsesolver;
32151 0 : }
32152 :
32153 :
32154 0 : void _qqpsettings_clear(void* _p)
32155 : {
32156 0 : qqpsettings *p = (qqpsettings*)_p;
32157 0 : ae_touch_ptr((void*)p);
32158 0 : }
32159 :
32160 :
32161 0 : void _qqpsettings_destroy(void* _p)
32162 : {
32163 0 : qqpsettings *p = (qqpsettings*)_p;
32164 0 : ae_touch_ptr((void*)p);
32165 0 : }
32166 :
32167 :
32168 0 : void _qqpbuffers_init(void* _p, ae_state *_state, ae_bool make_automatic)
32169 : {
32170 0 : qqpbuffers *p = (qqpbuffers*)_p;
32171 0 : ae_touch_ptr((void*)p);
32172 0 : ae_matrix_init(&p->densea, 0, 0, DT_REAL, _state, make_automatic);
32173 0 : _sparsematrix_init(&p->sparsea, _state, make_automatic);
32174 0 : ae_vector_init(&p->b, 0, DT_REAL, _state, make_automatic);
32175 0 : ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic);
32176 0 : ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic);
32177 0 : ae_vector_init(&p->havebndl, 0, DT_BOOL, _state, make_automatic);
32178 0 : ae_vector_init(&p->havebndu, 0, DT_BOOL, _state, make_automatic);
32179 0 : ae_vector_init(&p->xs, 0, DT_REAL, _state, make_automatic);
32180 0 : ae_vector_init(&p->xf, 0, DT_REAL, _state, make_automatic);
32181 0 : ae_vector_init(&p->gc, 0, DT_REAL, _state, make_automatic);
32182 0 : ae_vector_init(&p->xp, 0, DT_REAL, _state, make_automatic);
32183 0 : ae_vector_init(&p->dc, 0, DT_REAL, _state, make_automatic);
32184 0 : ae_vector_init(&p->dp, 0, DT_REAL, _state, make_automatic);
32185 0 : ae_vector_init(&p->cgc, 0, DT_REAL, _state, make_automatic);
32186 0 : ae_vector_init(&p->cgp, 0, DT_REAL, _state, make_automatic);
32187 0 : _sactiveset_init(&p->sas, _state, make_automatic);
32188 0 : ae_vector_init(&p->activated, 0, DT_BOOL, _state, make_automatic);
32189 0 : ae_matrix_init(&p->densez, 0, 0, DT_REAL, _state, make_automatic);
32190 0 : _sparsematrix_init(&p->sparsecca, _state, make_automatic);
32191 0 : ae_vector_init(&p->yidx, 0, DT_INT, _state, make_automatic);
32192 0 : ae_vector_init(&p->regdiag, 0, DT_REAL, _state, make_automatic);
32193 0 : ae_vector_init(&p->regx0, 0, DT_REAL, _state, make_automatic);
32194 0 : ae_vector_init(&p->tmpcn, 0, DT_REAL, _state, make_automatic);
32195 0 : ae_vector_init(&p->tmpcni, 0, DT_INT, _state, make_automatic);
32196 0 : ae_vector_init(&p->tmpcnb, 0, DT_BOOL, _state, make_automatic);
32197 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
32198 0 : ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic);
32199 0 : ae_vector_init(&p->stpbuf, 0, DT_REAL, _state, make_automatic);
32200 0 : _sparsebuffers_init(&p->sbuf, _state, make_automatic);
32201 0 : }
32202 :
32203 :
32204 0 : void _qqpbuffers_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
32205 : {
32206 0 : qqpbuffers *dst = (qqpbuffers*)_dst;
32207 0 : qqpbuffers *src = (qqpbuffers*)_src;
32208 0 : dst->n = src->n;
32209 0 : dst->akind = src->akind;
32210 0 : ae_matrix_init_copy(&dst->densea, &src->densea, _state, make_automatic);
32211 0 : _sparsematrix_init_copy(&dst->sparsea, &src->sparsea, _state, make_automatic);
32212 0 : dst->sparseupper = src->sparseupper;
32213 0 : dst->absamax = src->absamax;
32214 0 : dst->absasum = src->absasum;
32215 0 : dst->absasum2 = src->absasum2;
32216 0 : ae_vector_init_copy(&dst->b, &src->b, _state, make_automatic);
32217 0 : ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic);
32218 0 : ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic);
32219 0 : ae_vector_init_copy(&dst->havebndl, &src->havebndl, _state, make_automatic);
32220 0 : ae_vector_init_copy(&dst->havebndu, &src->havebndu, _state, make_automatic);
32221 0 : ae_vector_init_copy(&dst->xs, &src->xs, _state, make_automatic);
32222 0 : ae_vector_init_copy(&dst->xf, &src->xf, _state, make_automatic);
32223 0 : ae_vector_init_copy(&dst->gc, &src->gc, _state, make_automatic);
32224 0 : ae_vector_init_copy(&dst->xp, &src->xp, _state, make_automatic);
32225 0 : ae_vector_init_copy(&dst->dc, &src->dc, _state, make_automatic);
32226 0 : ae_vector_init_copy(&dst->dp, &src->dp, _state, make_automatic);
32227 0 : ae_vector_init_copy(&dst->cgc, &src->cgc, _state, make_automatic);
32228 0 : ae_vector_init_copy(&dst->cgp, &src->cgp, _state, make_automatic);
32229 0 : _sactiveset_init_copy(&dst->sas, &src->sas, _state, make_automatic);
32230 0 : ae_vector_init_copy(&dst->activated, &src->activated, _state, make_automatic);
32231 0 : dst->nfree = src->nfree;
32232 0 : dst->cnmodelage = src->cnmodelage;
32233 0 : ae_matrix_init_copy(&dst->densez, &src->densez, _state, make_automatic);
32234 0 : _sparsematrix_init_copy(&dst->sparsecca, &src->sparsecca, _state, make_automatic);
32235 0 : ae_vector_init_copy(&dst->yidx, &src->yidx, _state, make_automatic);
32236 0 : ae_vector_init_copy(&dst->regdiag, &src->regdiag, _state, make_automatic);
32237 0 : ae_vector_init_copy(&dst->regx0, &src->regx0, _state, make_automatic);
32238 0 : ae_vector_init_copy(&dst->tmpcn, &src->tmpcn, _state, make_automatic);
32239 0 : ae_vector_init_copy(&dst->tmpcni, &src->tmpcni, _state, make_automatic);
32240 0 : ae_vector_init_copy(&dst->tmpcnb, &src->tmpcnb, _state, make_automatic);
32241 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
32242 0 : ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic);
32243 0 : ae_vector_init_copy(&dst->stpbuf, &src->stpbuf, _state, make_automatic);
32244 0 : _sparsebuffers_init_copy(&dst->sbuf, &src->sbuf, _state, make_automatic);
32245 0 : dst->repinneriterationscount = src->repinneriterationscount;
32246 0 : dst->repouteriterationscount = src->repouteriterationscount;
32247 0 : dst->repncholesky = src->repncholesky;
32248 0 : dst->repncupdates = src->repncupdates;
32249 0 : }
32250 :
32251 :
32252 0 : void _qqpbuffers_clear(void* _p)
32253 : {
32254 0 : qqpbuffers *p = (qqpbuffers*)_p;
32255 0 : ae_touch_ptr((void*)p);
32256 0 : ae_matrix_clear(&p->densea);
32257 0 : _sparsematrix_clear(&p->sparsea);
32258 0 : ae_vector_clear(&p->b);
32259 0 : ae_vector_clear(&p->bndl);
32260 0 : ae_vector_clear(&p->bndu);
32261 0 : ae_vector_clear(&p->havebndl);
32262 0 : ae_vector_clear(&p->havebndu);
32263 0 : ae_vector_clear(&p->xs);
32264 0 : ae_vector_clear(&p->xf);
32265 0 : ae_vector_clear(&p->gc);
32266 0 : ae_vector_clear(&p->xp);
32267 0 : ae_vector_clear(&p->dc);
32268 0 : ae_vector_clear(&p->dp);
32269 0 : ae_vector_clear(&p->cgc);
32270 0 : ae_vector_clear(&p->cgp);
32271 0 : _sactiveset_clear(&p->sas);
32272 0 : ae_vector_clear(&p->activated);
32273 0 : ae_matrix_clear(&p->densez);
32274 0 : _sparsematrix_clear(&p->sparsecca);
32275 0 : ae_vector_clear(&p->yidx);
32276 0 : ae_vector_clear(&p->regdiag);
32277 0 : ae_vector_clear(&p->regx0);
32278 0 : ae_vector_clear(&p->tmpcn);
32279 0 : ae_vector_clear(&p->tmpcni);
32280 0 : ae_vector_clear(&p->tmpcnb);
32281 0 : ae_vector_clear(&p->tmp0);
32282 0 : ae_vector_clear(&p->tmp1);
32283 0 : ae_vector_clear(&p->stpbuf);
32284 0 : _sparsebuffers_clear(&p->sbuf);
32285 0 : }
32286 :
32287 :
32288 0 : void _qqpbuffers_destroy(void* _p)
32289 : {
32290 0 : qqpbuffers *p = (qqpbuffers*)_p;
32291 0 : ae_touch_ptr((void*)p);
32292 0 : ae_matrix_destroy(&p->densea);
32293 0 : _sparsematrix_destroy(&p->sparsea);
32294 0 : ae_vector_destroy(&p->b);
32295 0 : ae_vector_destroy(&p->bndl);
32296 0 : ae_vector_destroy(&p->bndu);
32297 0 : ae_vector_destroy(&p->havebndl);
32298 0 : ae_vector_destroy(&p->havebndu);
32299 0 : ae_vector_destroy(&p->xs);
32300 0 : ae_vector_destroy(&p->xf);
32301 0 : ae_vector_destroy(&p->gc);
32302 0 : ae_vector_destroy(&p->xp);
32303 0 : ae_vector_destroy(&p->dc);
32304 0 : ae_vector_destroy(&p->dp);
32305 0 : ae_vector_destroy(&p->cgc);
32306 0 : ae_vector_destroy(&p->cgp);
32307 0 : _sactiveset_destroy(&p->sas);
32308 0 : ae_vector_destroy(&p->activated);
32309 0 : ae_matrix_destroy(&p->densez);
32310 0 : _sparsematrix_destroy(&p->sparsecca);
32311 0 : ae_vector_destroy(&p->yidx);
32312 0 : ae_vector_destroy(&p->regdiag);
32313 0 : ae_vector_destroy(&p->regx0);
32314 0 : ae_vector_destroy(&p->tmpcn);
32315 0 : ae_vector_destroy(&p->tmpcni);
32316 0 : ae_vector_destroy(&p->tmpcnb);
32317 0 : ae_vector_destroy(&p->tmp0);
32318 0 : ae_vector_destroy(&p->tmp1);
32319 0 : ae_vector_destroy(&p->stpbuf);
32320 0 : _sparsebuffers_destroy(&p->sbuf);
32321 0 : }
32322 :
32323 :
32324 : #endif
32325 : #if defined(AE_COMPILE_MINLBFGS) || !defined(AE_PARTIAL_BUILD)
32326 :
32327 :
32328 : /*************************************************************************
32329 : LIMITED MEMORY BFGS METHOD FOR LARGE SCALE OPTIMIZATION
32330 :
32331 : DESCRIPTION:
32332 : The subroutine minimizes function F(x) of N arguments by using a quasi-
32333 : Newton method (LBFGS scheme) which is optimized to use a minimum amount
32334 : of memory.
32335 : The subroutine generates the approximation of an inverse Hessian matrix by
32336 : using information about the last M steps of the algorithm (instead of N).
32337 : It lessens a required amount of memory from a value of order N^2 to a
32338 : value of order 2*N*M.
32339 :
32340 :
32341 : REQUIREMENTS:
32342 : Algorithm will request following information during its operation:
32343 : * function value F and its gradient G (simultaneously) at given point X
32344 :
32345 :
32346 : USAGE:
32347 : 1. User initializes algorithm state with MinLBFGSCreate() call
32348 : 2. User tunes solver parameters with MinLBFGSSetCond() MinLBFGSSetStpMax()
32349 : and other functions
32350 : 3. User calls MinLBFGSOptimize() function which takes algorithm state and
32351 : pointer (delegate, etc.) to callback function which calculates F/G.
32352 : 4. User calls MinLBFGSResults() to get solution
32353 : 5. Optionally user may call MinLBFGSRestartFrom() to solve another problem
32354 : with same N/M but another starting point and/or another function.
32355 : MinLBFGSRestartFrom() allows to reuse already initialized structure.
32356 :
32357 :
32358 : INPUT PARAMETERS:
32359 : N - problem dimension. N>0
32360 : M - number of corrections in the BFGS scheme of Hessian
32361 : approximation update. Recommended value: 3<=M<=7. The smaller
32362 : value causes worse convergence, the bigger will not cause a
32363 : considerably better convergence, but will cause a fall in the
32364 : performance. M<=N.
32365 : X - initial solution approximation, array[0..N-1].
32366 :
32367 :
32368 : OUTPUT PARAMETERS:
32369 : State - structure which stores algorithm state
32370 :
32371 :
32372 : NOTES:
32373 : 1. you may tune stopping conditions with MinLBFGSSetCond() function
32374 : 2. if target function contains exp() or other fast growing functions, and
32375 : optimization algorithm makes too large steps which leads to overflow,
32376 : use MinLBFGSSetStpMax() function to bound algorithm's steps. However,
32377 : L-BFGS rarely needs such a tuning.
32378 :
32379 :
32380 : -- ALGLIB --
32381 : Copyright 02.04.2010 by Bochkanov Sergey
32382 : *************************************************************************/
32383 498 : void minlbfgscreate(ae_int_t n,
32384 : ae_int_t m,
32385 : /* Real */ ae_vector* x,
32386 : minlbfgsstate* state,
32387 : ae_state *_state)
32388 : {
32389 :
32390 498 : _minlbfgsstate_clear(state);
32391 :
32392 498 : ae_assert(n>=1, "MinLBFGSCreate: N<1!", _state);
32393 498 : ae_assert(m>=1, "MinLBFGSCreate: M<1", _state);
32394 498 : ae_assert(m<=n, "MinLBFGSCreate: M>N", _state);
32395 498 : ae_assert(x->cnt>=n, "MinLBFGSCreate: Length(X)<N!", _state);
32396 498 : ae_assert(isfinitevector(x, n, _state), "MinLBFGSCreate: X contains infinite or NaN values!", _state);
32397 498 : minlbfgscreatex(n, m, x, 0, 0.0, state, _state);
32398 498 : }
32399 :
32400 :
32401 : /*************************************************************************
32402 : The subroutine is finite difference variant of MinLBFGSCreate(). It uses
32403 : finite differences in order to differentiate target function.
32404 :
32405 : Description below contains information which is specific to this function
32406 : only. We recommend to read comments on MinLBFGSCreate() in order to get
32407 : more information about creation of LBFGS optimizer.
32408 :
32409 : INPUT PARAMETERS:
32410 : N - problem dimension, N>0:
32411 : * if given, only leading N elements of X are used
32412 : * if not given, automatically determined from size of X
32413 : M - number of corrections in the BFGS scheme of Hessian
32414 : approximation update. Recommended value: 3<=M<=7. The smaller
32415 : value causes worse convergence, the bigger will not cause a
32416 : considerably better convergence, but will cause a fall in the
32417 : performance. M<=N.
32418 : X - starting point, array[0..N-1].
32419 : DiffStep- differentiation step, >0
32420 :
32421 : OUTPUT PARAMETERS:
32422 : State - structure which stores algorithm state
32423 :
32424 : NOTES:
32425 : 1. algorithm uses 4-point central formula for differentiation.
32426 : 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
32427 : S[] is scaling vector which can be set by MinLBFGSSetScale() call.
32428 : 3. we recommend you to use moderate values of differentiation step. Too
32429 : large step will result in too large truncation errors, while too small
32430 : step will result in too large numerical errors. 1.0E-6 can be good
32431 : value to start with.
32432 : 4. Numerical differentiation is very inefficient - one gradient
32433 : calculation needs 4*N function evaluations. This function will work for
32434 : any N - either small (1...10), moderate (10...100) or large (100...).
32435 : However, performance penalty will be too severe for any N's except for
32436 : small ones.
32437 : We should also say that code which relies on numerical differentiation
32438 : is less robust and precise. LBFGS needs exact gradient values.
32439 : Imprecise gradient may slow down convergence, especially on highly
32440 : nonlinear problems.
32441 : Thus we recommend to use this function for fast prototyping on small-
32442 : dimensional problems only, and to implement analytical gradient as soon
32443 : as possible.
32444 :
32445 : -- ALGLIB --
32446 : Copyright 16.05.2011 by Bochkanov Sergey
32447 : *************************************************************************/
32448 0 : void minlbfgscreatef(ae_int_t n,
32449 : ae_int_t m,
32450 : /* Real */ ae_vector* x,
32451 : double diffstep,
32452 : minlbfgsstate* state,
32453 : ae_state *_state)
32454 : {
32455 :
32456 0 : _minlbfgsstate_clear(state);
32457 :
32458 0 : ae_assert(n>=1, "MinLBFGSCreateF: N too small!", _state);
32459 0 : ae_assert(m>=1, "MinLBFGSCreateF: M<1", _state);
32460 0 : ae_assert(m<=n, "MinLBFGSCreateF: M>N", _state);
32461 0 : ae_assert(x->cnt>=n, "MinLBFGSCreateF: Length(X)<N!", _state);
32462 0 : ae_assert(isfinitevector(x, n, _state), "MinLBFGSCreateF: X contains infinite or NaN values!", _state);
32463 0 : ae_assert(ae_isfinite(diffstep, _state), "MinLBFGSCreateF: DiffStep is infinite or NaN!", _state);
32464 0 : ae_assert(ae_fp_greater(diffstep,(double)(0)), "MinLBFGSCreateF: DiffStep is non-positive!", _state);
32465 0 : minlbfgscreatex(n, m, x, 0, diffstep, state, _state);
32466 0 : }
32467 :
32468 :
32469 : /*************************************************************************
32470 : This function sets stopping conditions for L-BFGS optimization algorithm.
32471 :
32472 : INPUT PARAMETERS:
32473 : State - structure which stores algorithm state
32474 : EpsG - >=0
32475 : The subroutine finishes its work if the condition
32476 : |v|<EpsG is satisfied, where:
32477 : * |.| means Euclidian norm
32478 : * v - scaled gradient vector, v[i]=g[i]*s[i]
32479 : * g - gradient
32480 : * s - scaling coefficients set by MinLBFGSSetScale()
32481 : EpsF - >=0
32482 : The subroutine finishes its work if on k+1-th iteration
32483 : the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
32484 : is satisfied.
32485 : EpsX - >=0
32486 : The subroutine finishes its work if on k+1-th iteration
32487 : the condition |v|<=EpsX is fulfilled, where:
32488 : * |.| means Euclidian norm
32489 : * v - scaled step vector, v[i]=dx[i]/s[i]
32490 : * dx - ste pvector, dx=X(k+1)-X(k)
32491 : * s - scaling coefficients set by MinLBFGSSetScale()
32492 : MaxIts - maximum number of iterations. If MaxIts=0, the number of
32493 : iterations is unlimited.
32494 :
32495 : Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to
32496 : automatic stopping criterion selection (small EpsX).
32497 :
32498 : -- ALGLIB --
32499 : Copyright 02.04.2010 by Bochkanov Sergey
32500 : *************************************************************************/
32501 996 : void minlbfgssetcond(minlbfgsstate* state,
32502 : double epsg,
32503 : double epsf,
32504 : double epsx,
32505 : ae_int_t maxits,
32506 : ae_state *_state)
32507 : {
32508 :
32509 :
32510 996 : ae_assert(ae_isfinite(epsg, _state), "MinLBFGSSetCond: EpsG is not finite number!", _state);
32511 996 : ae_assert(ae_fp_greater_eq(epsg,(double)(0)), "MinLBFGSSetCond: negative EpsG!", _state);
32512 996 : ae_assert(ae_isfinite(epsf, _state), "MinLBFGSSetCond: EpsF is not finite number!", _state);
32513 996 : ae_assert(ae_fp_greater_eq(epsf,(double)(0)), "MinLBFGSSetCond: negative EpsF!", _state);
32514 996 : ae_assert(ae_isfinite(epsx, _state), "MinLBFGSSetCond: EpsX is not finite number!", _state);
32515 996 : ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "MinLBFGSSetCond: negative EpsX!", _state);
32516 996 : ae_assert(maxits>=0, "MinLBFGSSetCond: negative MaxIts!", _state);
32517 996 : if( ((ae_fp_eq(epsg,(double)(0))&&ae_fp_eq(epsf,(double)(0)))&&ae_fp_eq(epsx,(double)(0)))&&maxits==0 )
32518 : {
32519 498 : epsx = 1.0E-6;
32520 : }
32521 996 : state->epsg = epsg;
32522 996 : state->epsf = epsf;
32523 996 : state->epsx = epsx;
32524 996 : state->maxits = maxits;
32525 996 : }
32526 :
32527 :
32528 : /*************************************************************************
32529 : This function turns on/off reporting.
32530 :
32531 : INPUT PARAMETERS:
32532 : State - structure which stores algorithm state
32533 : NeedXRep- whether iteration reports are needed or not
32534 :
32535 : If NeedXRep is True, algorithm will call rep() callback function if it is
32536 : provided to MinLBFGSOptimize().
32537 :
32538 :
32539 : -- ALGLIB --
32540 : Copyright 02.04.2010 by Bochkanov Sergey
32541 : *************************************************************************/
32542 498 : void minlbfgssetxrep(minlbfgsstate* state,
32543 : ae_bool needxrep,
32544 : ae_state *_state)
32545 : {
32546 :
32547 :
32548 498 : state->xrep = needxrep;
32549 498 : }
32550 :
32551 :
32552 : /*************************************************************************
32553 : This function sets maximum step length
32554 :
32555 : INPUT PARAMETERS:
32556 : State - structure which stores algorithm state
32557 : StpMax - maximum step length, >=0. Set StpMax to 0.0 (default), if
32558 : you don't want to limit step length.
32559 :
32560 : Use this subroutine when you optimize target function which contains exp()
32561 : or other fast growing functions, and optimization algorithm makes too
32562 : large steps which leads to overflow. This function allows us to reject
32563 : steps that are too large (and therefore expose us to the possible
32564 : overflow) without actually calculating function value at the x+stp*d.
32565 :
32566 : -- ALGLIB --
32567 : Copyright 02.04.2010 by Bochkanov Sergey
32568 : *************************************************************************/
32569 498 : void minlbfgssetstpmax(minlbfgsstate* state,
32570 : double stpmax,
32571 : ae_state *_state)
32572 : {
32573 :
32574 :
32575 498 : ae_assert(ae_isfinite(stpmax, _state), "MinLBFGSSetStpMax: StpMax is not finite!", _state);
32576 498 : ae_assert(ae_fp_greater_eq(stpmax,(double)(0)), "MinLBFGSSetStpMax: StpMax<0!", _state);
32577 498 : state->stpmax = stpmax;
32578 498 : }
32579 :
32580 :
32581 : /*************************************************************************
32582 : This function sets scaling coefficients for LBFGS optimizer.
32583 :
32584 : ALGLIB optimizers use scaling matrices to test stopping conditions (step
32585 : size and gradient are scaled before comparison with tolerances). Scale of
32586 : the I-th variable is a translation invariant measure of:
32587 : a) "how large" the variable is
32588 : b) how large the step should be to make significant changes in the function
32589 :
32590 : Scaling is also used by finite difference variant of the optimizer - step
32591 : along I-th axis is equal to DiffStep*S[I].
32592 :
32593 : In most optimizers (and in the LBFGS too) scaling is NOT a form of
32594 : preconditioning. It just affects stopping conditions. You should set
32595 : preconditioner by separate call to one of the MinLBFGSSetPrec...()
32596 : functions.
32597 :
32598 : There is special preconditioning mode, however, which uses scaling
32599 : coefficients to form diagonal preconditioning matrix. You can turn this
32600 : mode on, if you want. But you should understand that scaling is not the
32601 : same thing as preconditioning - these are two different, although related
32602 : forms of tuning solver.
32603 :
32604 : INPUT PARAMETERS:
32605 : State - structure stores algorithm state
32606 : S - array[N], non-zero scaling coefficients
32607 : S[i] may be negative, sign doesn't matter.
32608 :
32609 : -- ALGLIB --
32610 : Copyright 14.01.2011 by Bochkanov Sergey
32611 : *************************************************************************/
32612 498 : void minlbfgssetscale(minlbfgsstate* state,
32613 : /* Real */ ae_vector* s,
32614 : ae_state *_state)
32615 : {
32616 : ae_int_t i;
32617 :
32618 :
32619 498 : ae_assert(s->cnt>=state->n, "MinLBFGSSetScale: Length(S)<N", _state);
32620 1494 : for(i=0; i<=state->n-1; i++)
32621 : {
32622 996 : ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "MinLBFGSSetScale: S contains infinite or NAN elements", _state);
32623 996 : ae_assert(ae_fp_neq(s->ptr.p_double[i],(double)(0)), "MinLBFGSSetScale: S contains zero elements", _state);
32624 996 : state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state);
32625 : }
32626 498 : }
32627 :
32628 :
32629 : /*************************************************************************
32630 : Extended subroutine for internal use only.
32631 :
32632 : Accepts additional parameters:
32633 :
32634 : Flags - additional settings:
32635 : * Flags = 0 means no additional settings
32636 : * Flags = 1 "do not allocate memory". used when solving
32637 : a many subsequent tasks with same N/M values.
32638 : First call MUST be without this flag bit set,
32639 : subsequent calls of MinLBFGS with same
32640 : MinLBFGSState structure can set Flags to 1.
32641 : DiffStep - numerical differentiation step
32642 :
32643 : -- ALGLIB --
32644 : Copyright 02.04.2010 by Bochkanov Sergey
32645 : *************************************************************************/
32646 498 : void minlbfgscreatex(ae_int_t n,
32647 : ae_int_t m,
32648 : /* Real */ ae_vector* x,
32649 : ae_int_t flags,
32650 : double diffstep,
32651 : minlbfgsstate* state,
32652 : ae_state *_state)
32653 : {
32654 : ae_bool allocatemem;
32655 : ae_int_t i;
32656 :
32657 :
32658 498 : ae_assert(n>=1, "MinLBFGS: N too small!", _state);
32659 498 : ae_assert(m>=1, "MinLBFGS: M too small!", _state);
32660 498 : ae_assert(m<=n, "MinLBFGS: M too large!", _state);
32661 :
32662 : /*
32663 : * Initialize
32664 : */
32665 498 : state->teststep = (double)(0);
32666 498 : state->smoothnessguardlevel = 0;
32667 498 : smoothnessmonitorinit(&state->smonitor, &state->s, 0, 0, ae_false, _state);
32668 498 : state->diffstep = diffstep;
32669 498 : state->n = n;
32670 498 : state->m = m;
32671 498 : allocatemem = flags%2==0;
32672 498 : flags = flags/2;
32673 498 : if( allocatemem )
32674 : {
32675 498 : rvectorsetlengthatleast(&state->rho, m, _state);
32676 498 : rvectorsetlengthatleast(&state->theta, m, _state);
32677 498 : rmatrixsetlengthatleast(&state->yk, m, n, _state);
32678 498 : rmatrixsetlengthatleast(&state->sk, m, n, _state);
32679 498 : rvectorsetlengthatleast(&state->d, n, _state);
32680 498 : rvectorsetlengthatleast(&state->xp, n, _state);
32681 498 : rvectorsetlengthatleast(&state->x, n, _state);
32682 498 : rvectorsetlengthatleast(&state->xbase, n, _state);
32683 498 : rvectorsetlengthatleast(&state->s, n, _state);
32684 498 : rvectorsetlengthatleast(&state->invs, n, _state);
32685 498 : rvectorsetlengthatleast(&state->lastscaleused, n, _state);
32686 498 : rvectorsetlengthatleast(&state->g, n, _state);
32687 498 : rvectorsetlengthatleast(&state->work, n, _state);
32688 : }
32689 1494 : for(i=0; i<=n-1; i++)
32690 : {
32691 996 : state->s.ptr.p_double[i] = 1.0;
32692 996 : state->invs.ptr.p_double[i] = 1.0;
32693 996 : state->lastscaleused.ptr.p_double[i] = 1.0;
32694 : }
32695 498 : state->prectype = 0;
32696 498 : minlbfgssetcond(state, (double)(0), (double)(0), (double)(0), 0, _state);
32697 498 : minlbfgssetxrep(state, ae_false, _state);
32698 498 : minlbfgssetstpmax(state, (double)(0), _state);
32699 498 : minlbfgsrestartfrom(state, x, _state);
32700 498 : }
32701 :
32702 :
32703 : /*************************************************************************
32704 : Modification of the preconditioner: default preconditioner (simple
32705 : scaling, same for all elements of X) is used.
32706 :
32707 : INPUT PARAMETERS:
32708 : State - structure which stores algorithm state
32709 :
32710 : NOTE: you can change preconditioner "on the fly", during algorithm
32711 : iterations.
32712 :
32713 : -- ALGLIB --
32714 : Copyright 13.10.2010 by Bochkanov Sergey
32715 : *************************************************************************/
32716 0 : void minlbfgssetprecdefault(minlbfgsstate* state, ae_state *_state)
32717 : {
32718 :
32719 :
32720 0 : state->prectype = 0;
32721 0 : }
32722 :
32723 :
32724 : /*************************************************************************
32725 : Modification of the preconditioner: Cholesky factorization of approximate
32726 : Hessian is used.
32727 :
32728 : INPUT PARAMETERS:
32729 : State - structure which stores algorithm state
32730 : P - triangular preconditioner, Cholesky factorization of
32731 : the approximate Hessian. array[0..N-1,0..N-1],
32732 : (if larger, only leading N elements are used).
32733 : IsUpper - whether upper or lower triangle of P is given
32734 : (other triangle is not referenced)
32735 :
32736 : After call to this function preconditioner is changed to P (P is copied
32737 : into the internal buffer).
32738 :
32739 : NOTE: you can change preconditioner "on the fly", during algorithm
32740 : iterations.
32741 :
32742 : NOTE 2: P should be nonsingular. Exception will be thrown otherwise.
32743 :
32744 : -- ALGLIB --
32745 : Copyright 13.10.2010 by Bochkanov Sergey
32746 : *************************************************************************/
32747 0 : void minlbfgssetpreccholesky(minlbfgsstate* state,
32748 : /* Real */ ae_matrix* p,
32749 : ae_bool isupper,
32750 : ae_state *_state)
32751 : {
32752 : ae_int_t i;
32753 : double mx;
32754 :
32755 :
32756 0 : ae_assert(isfinitertrmatrix(p, state->n, isupper, _state), "MinLBFGSSetPrecCholesky: P contains infinite or NAN values!", _state);
32757 0 : mx = (double)(0);
32758 0 : for(i=0; i<=state->n-1; i++)
32759 : {
32760 0 : mx = ae_maxreal(mx, ae_fabs(p->ptr.pp_double[i][i], _state), _state);
32761 : }
32762 0 : ae_assert(ae_fp_greater(mx,(double)(0)), "MinLBFGSSetPrecCholesky: P is strictly singular!", _state);
32763 0 : if( state->denseh.rows<state->n||state->denseh.cols<state->n )
32764 : {
32765 0 : ae_matrix_set_length(&state->denseh, state->n, state->n, _state);
32766 : }
32767 0 : state->prectype = 1;
32768 0 : if( isupper )
32769 : {
32770 0 : rmatrixcopy(state->n, state->n, p, 0, 0, &state->denseh, 0, 0, _state);
32771 : }
32772 : else
32773 : {
32774 0 : rmatrixtranspose(state->n, state->n, p, 0, 0, &state->denseh, 0, 0, _state);
32775 : }
32776 0 : }
32777 :
32778 :
32779 : /*************************************************************************
32780 : Modification of the preconditioner: diagonal of approximate Hessian is
32781 : used.
32782 :
32783 : INPUT PARAMETERS:
32784 : State - structure which stores algorithm state
32785 : D - diagonal of the approximate Hessian, array[0..N-1],
32786 : (if larger, only leading N elements are used).
32787 :
32788 : NOTE: you can change preconditioner "on the fly", during algorithm
32789 : iterations.
32790 :
32791 : NOTE 2: D[i] should be positive. Exception will be thrown otherwise.
32792 :
32793 : NOTE 3: you should pass diagonal of approximate Hessian - NOT ITS INVERSE.
32794 :
32795 : -- ALGLIB --
32796 : Copyright 13.10.2010 by Bochkanov Sergey
32797 : *************************************************************************/
32798 0 : void minlbfgssetprecdiag(minlbfgsstate* state,
32799 : /* Real */ ae_vector* d,
32800 : ae_state *_state)
32801 : {
32802 : ae_int_t i;
32803 :
32804 :
32805 0 : ae_assert(d->cnt>=state->n, "MinLBFGSSetPrecDiag: D is too short", _state);
32806 0 : for(i=0; i<=state->n-1; i++)
32807 : {
32808 0 : ae_assert(ae_isfinite(d->ptr.p_double[i], _state), "MinLBFGSSetPrecDiag: D contains infinite or NAN elements", _state);
32809 0 : ae_assert(ae_fp_greater(d->ptr.p_double[i],(double)(0)), "MinLBFGSSetPrecDiag: D contains non-positive elements", _state);
32810 : }
32811 0 : rvectorsetlengthatleast(&state->diagh, state->n, _state);
32812 0 : state->prectype = 2;
32813 0 : for(i=0; i<=state->n-1; i++)
32814 : {
32815 0 : state->diagh.ptr.p_double[i] = d->ptr.p_double[i];
32816 : }
32817 0 : }
32818 :
32819 :
32820 : /*************************************************************************
32821 : Modification of the preconditioner: scale-based diagonal preconditioning.
32822 :
32823 : This preconditioning mode can be useful when you don't have approximate
32824 : diagonal of Hessian, but you know that your variables are badly scaled
32825 : (for example, one variable is in [1,10], and another in [1000,100000]),
32826 : and most part of the ill-conditioning comes from different scales of vars.
32827 :
32828 : In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2),
32829 : can greatly improve convergence.
32830 :
32831 : IMPRTANT: you should set scale of your variables with MinLBFGSSetScale()
32832 : call (before or after MinLBFGSSetPrecScale() call). Without knowledge of
32833 : the scale of your variables scale-based preconditioner will be just unit
32834 : matrix.
32835 :
32836 : INPUT PARAMETERS:
32837 : State - structure which stores algorithm state
32838 :
32839 : -- ALGLIB --
32840 : Copyright 13.10.2010 by Bochkanov Sergey
32841 : *************************************************************************/
32842 0 : void minlbfgssetprecscale(minlbfgsstate* state, ae_state *_state)
32843 : {
32844 :
32845 :
32846 0 : state->prectype = 3;
32847 0 : }
32848 :
32849 :
32850 : /*************************************************************************
32851 : This function sets low-rank preconditioner for Hessian matrix H=D+W'*C*W,
32852 : where:
32853 : * H is a Hessian matrix, which is approximated by D/W/C
32854 : * D is a NxN diagonal positive definite matrix
32855 : * W is a KxN low-rank correction
32856 : * C is a KxK positive definite diagonal factor of low-rank correction
32857 :
32858 : This preconditioner is inexact but fast - it requires O(N*K) time to be
32859 : applied. Preconditioner P is calculated by artificially constructing a set
32860 : of BFGS updates which tries to reproduce behavior of H:
32861 : * Sk = Wk (k-th row of W)
32862 : * Yk = (D+Wk'*Ck*Wk)*Sk
32863 : * Yk/Sk are reordered by ascending of C[k]*norm(Wk)^2
32864 :
32865 : Here we assume that rows of Wk are orthogonal or nearly orthogonal, which
32866 : allows us to have O(N*K+K^2) update instead of O(N*K^2) one. Reordering of
32867 : updates is essential for having good performance on non-orthogonal problems
32868 : (updates which do not add much of curvature are added first, and updates
32869 : which add very large eigenvalues are added last and override effect of the
32870 : first updates).
32871 :
32872 : In practice, this preconditioner is perfect when ortogonal correction is
32873 : applied; on non-orthogonal problems sometimes it allows to achieve 5x
32874 : speedup (when compared to non-preconditioned solver).
32875 :
32876 : -- ALGLIB --
32877 : Copyright 13.10.2010 by Bochkanov Sergey
32878 : *************************************************************************/
32879 0 : void minlbfgssetprecrankklbfgsfast(minlbfgsstate* state,
32880 : /* Real */ ae_vector* d,
32881 : /* Real */ ae_vector* c,
32882 : /* Real */ ae_matrix* w,
32883 : ae_int_t cnt,
32884 : ae_state *_state)
32885 : {
32886 : ae_int_t i;
32887 : ae_int_t j;
32888 : ae_int_t n;
32889 :
32890 :
32891 0 : n = state->n;
32892 0 : state->prectype = 4;
32893 0 : state->preck = cnt;
32894 0 : rvectorsetlengthatleast(&state->precc, cnt, _state);
32895 0 : rvectorsetlengthatleast(&state->precd, n, _state);
32896 0 : rmatrixsetlengthatleast(&state->precw, cnt, n, _state);
32897 0 : for(i=0; i<=n-1; i++)
32898 : {
32899 0 : state->precd.ptr.p_double[i] = d->ptr.p_double[i];
32900 : }
32901 0 : for(i=0; i<=cnt-1; i++)
32902 : {
32903 0 : state->precc.ptr.p_double[i] = c->ptr.p_double[i];
32904 0 : for(j=0; j<=n-1; j++)
32905 : {
32906 0 : state->precw.ptr.pp_double[i][j] = w->ptr.pp_double[i][j];
32907 : }
32908 : }
32909 0 : }
32910 :
32911 :
32912 : /*************************************************************************
32913 : This function sets exact low-rank preconditioner for Hessian matrix
32914 : H=D+W'*C*W, where:
32915 : * H is a Hessian matrix, which is approximated by D/W/C
32916 : * D is a NxN diagonal positive definite matrix
32917 : * W is a KxN low-rank correction
32918 : * C is a KxK semidefinite diagonal factor of low-rank correction
32919 :
32920 : This preconditioner is exact but slow - it requires O(N*K^2) time to be
32921 : built and O(N*K) time to be applied. Woodbury matrix identity is used to
32922 : build inverse matrix.
32923 :
32924 : -- ALGLIB --
32925 : Copyright 13.10.2010 by Bochkanov Sergey
32926 : *************************************************************************/
32927 0 : void minlbfgssetpreclowrankexact(minlbfgsstate* state,
32928 : /* Real */ ae_vector* d,
32929 : /* Real */ ae_vector* c,
32930 : /* Real */ ae_matrix* w,
32931 : ae_int_t cnt,
32932 : ae_state *_state)
32933 : {
32934 :
32935 :
32936 0 : state->prectype = 5;
32937 0 : preparelowrankpreconditioner(d, c, w, state->n, cnt, &state->lowrankbuf, _state);
32938 0 : }
32939 :
32940 :
32941 : /*************************************************************************
32942 : NOTES:
32943 :
32944 : 1. This function has two different implementations: one which uses exact
32945 : (analytical) user-supplied gradient, and one which uses function value
32946 : only and numerically differentiates function in order to obtain
32947 : gradient.
32948 :
32949 : Depending on the specific function used to create optimizer object
32950 : (either MinLBFGSCreate() for analytical gradient or MinLBFGSCreateF()
32951 : for numerical differentiation) you should choose appropriate variant of
32952 : MinLBFGSOptimize() - one which accepts function AND gradient or one
32953 : which accepts function ONLY.
32954 :
32955 : Be careful to choose variant of MinLBFGSOptimize() which corresponds to
32956 : your optimization scheme! Table below lists different combinations of
32957 : callback (function/gradient) passed to MinLBFGSOptimize() and specific
32958 : function used to create optimizer.
32959 :
32960 :
32961 : | USER PASSED TO MinLBFGSOptimize()
32962 : CREATED WITH | function only | function and gradient
32963 : ------------------------------------------------------------
32964 : MinLBFGSCreateF() | work FAIL
32965 : MinLBFGSCreate() | FAIL work
32966 :
32967 : Here "FAIL" denotes inappropriate combinations of optimizer creation
32968 : function and MinLBFGSOptimize() version. Attemps to use such
32969 : combination (for example, to create optimizer with MinLBFGSCreateF() and
32970 : to pass gradient information to MinCGOptimize()) will lead to exception
32971 : being thrown. Either you did not pass gradient when it WAS needed or
32972 : you passed gradient when it was NOT needed.
32973 :
32974 : -- ALGLIB --
32975 : Copyright 20.03.2009 by Bochkanov Sergey
32976 : *************************************************************************/
32977 5387 : ae_bool minlbfgsiteration(minlbfgsstate* state, ae_state *_state)
32978 : {
32979 : ae_int_t n;
32980 : ae_int_t m;
32981 : ae_int_t i;
32982 : ae_int_t j;
32983 : ae_int_t ic;
32984 : ae_int_t mcinfo;
32985 : double v;
32986 : double vv;
32987 : ae_bool result;
32988 :
32989 :
32990 :
32991 : /*
32992 : * Reverse communication preparations
32993 : * I know it looks ugly, but it works the same way
32994 : * anywhere from C++ to Python.
32995 : *
32996 : * This code initializes locals by:
32997 : * * random values determined during code
32998 : * generation - on first subroutine call
32999 : * * values from previous call - on subsequent calls
33000 : */
33001 5387 : if( state->rstate.stage>=0 )
33002 : {
33003 4889 : n = state->rstate.ia.ptr.p_int[0];
33004 4889 : m = state->rstate.ia.ptr.p_int[1];
33005 4889 : i = state->rstate.ia.ptr.p_int[2];
33006 4889 : j = state->rstate.ia.ptr.p_int[3];
33007 4889 : ic = state->rstate.ia.ptr.p_int[4];
33008 4889 : mcinfo = state->rstate.ia.ptr.p_int[5];
33009 4889 : v = state->rstate.ra.ptr.p_double[0];
33010 4889 : vv = state->rstate.ra.ptr.p_double[1];
33011 : }
33012 : else
33013 : {
33014 498 : n = 359;
33015 498 : m = -58;
33016 498 : i = -919;
33017 498 : j = -909;
33018 498 : ic = 81;
33019 498 : mcinfo = 255;
33020 498 : v = 74;
33021 498 : vv = -788;
33022 : }
33023 5387 : if( state->rstate.stage==0 )
33024 : {
33025 0 : goto lbl_0;
33026 : }
33027 5387 : if( state->rstate.stage==1 )
33028 : {
33029 498 : goto lbl_1;
33030 : }
33031 4889 : if( state->rstate.stage==2 )
33032 : {
33033 0 : goto lbl_2;
33034 : }
33035 4889 : if( state->rstate.stage==3 )
33036 : {
33037 0 : goto lbl_3;
33038 : }
33039 4889 : if( state->rstate.stage==4 )
33040 : {
33041 0 : goto lbl_4;
33042 : }
33043 4889 : if( state->rstate.stage==5 )
33044 : {
33045 0 : goto lbl_5;
33046 : }
33047 4889 : if( state->rstate.stage==6 )
33048 : {
33049 0 : goto lbl_6;
33050 : }
33051 4889 : if( state->rstate.stage==7 )
33052 : {
33053 0 : goto lbl_7;
33054 : }
33055 4889 : if( state->rstate.stage==8 )
33056 : {
33057 4391 : goto lbl_8;
33058 : }
33059 498 : if( state->rstate.stage==9 )
33060 : {
33061 0 : goto lbl_9;
33062 : }
33063 498 : if( state->rstate.stage==10 )
33064 : {
33065 0 : goto lbl_10;
33066 : }
33067 498 : if( state->rstate.stage==11 )
33068 : {
33069 0 : goto lbl_11;
33070 : }
33071 498 : if( state->rstate.stage==12 )
33072 : {
33073 0 : goto lbl_12;
33074 : }
33075 498 : if( state->rstate.stage==13 )
33076 : {
33077 0 : goto lbl_13;
33078 : }
33079 498 : if( state->rstate.stage==14 )
33080 : {
33081 0 : goto lbl_14;
33082 : }
33083 :
33084 : /*
33085 : * Routine body
33086 : */
33087 :
33088 : /*
33089 : * Unload frequently used variables from State structure
33090 : * (just for typing convinience)
33091 : */
33092 498 : n = state->n;
33093 498 : m = state->m;
33094 :
33095 : /*
33096 : * Init
33097 : */
33098 498 : state->userterminationneeded = ae_false;
33099 498 : state->repterminationtype = 0;
33100 498 : state->repiterationscount = 0;
33101 498 : state->repnfev = 0;
33102 498 : smoothnessmonitorinit(&state->smonitor, &state->s, n, 1, state->smoothnessguardlevel>0, _state);
33103 498 : rvectorsetlengthatleast(&state->invs, n, _state);
33104 1494 : for(i=0; i<=n-1; i++)
33105 : {
33106 996 : state->lastscaleused.ptr.p_double[i] = state->s.ptr.p_double[i];
33107 996 : state->invs.ptr.p_double[i] = 1/state->s.ptr.p_double[i];
33108 : }
33109 :
33110 : /*
33111 : * Check, that transferred derivative value is right
33112 : */
33113 498 : state->stp = (double)(0);
33114 498 : minlbfgs_clearrequestfields(state, _state);
33115 498 : if( !(ae_fp_eq(state->diffstep,(double)(0))&&ae_fp_greater(state->teststep,(double)(0))) )
33116 : {
33117 498 : goto lbl_15;
33118 : }
33119 0 : lbl_17:
33120 0 : if( !smoothnessmonitorcheckgradientatx0(&state->smonitor, &state->xbase, &state->s, &state->s, &state->s, ae_false, state->teststep, _state) )
33121 : {
33122 0 : goto lbl_18;
33123 : }
33124 0 : for(i=0; i<=n-1; i++)
33125 : {
33126 0 : state->x.ptr.p_double[i] = state->smonitor.x.ptr.p_double[i];
33127 : }
33128 0 : state->needfg = ae_true;
33129 0 : state->rstate.stage = 0;
33130 0 : goto lbl_rcomm;
33131 0 : lbl_0:
33132 0 : state->needfg = ae_false;
33133 0 : state->smonitor.fi.ptr.p_double[0] = state->f;
33134 0 : for(i=0; i<=n-1; i++)
33135 : {
33136 0 : state->smonitor.j.ptr.pp_double[0][i] = state->g.ptr.p_double[i];
33137 : }
33138 0 : goto lbl_17;
33139 498 : lbl_18:
33140 498 : lbl_15:
33141 :
33142 : /*
33143 : * Calculate F/G at the initial point
33144 : */
33145 1494 : for(i=0; i<=n-1; i++)
33146 : {
33147 996 : state->x.ptr.p_double[i] = state->xbase.ptr.p_double[i];
33148 : }
33149 498 : state->stp = (double)(0);
33150 498 : minlbfgs_clearrequestfields(state, _state);
33151 498 : if( ae_fp_neq(state->diffstep,(double)(0)) )
33152 : {
33153 0 : goto lbl_19;
33154 : }
33155 498 : state->needfg = ae_true;
33156 498 : state->rstate.stage = 1;
33157 498 : goto lbl_rcomm;
33158 498 : lbl_1:
33159 498 : state->needfg = ae_false;
33160 498 : goto lbl_20;
33161 0 : lbl_19:
33162 0 : state->needf = ae_true;
33163 0 : state->rstate.stage = 2;
33164 0 : goto lbl_rcomm;
33165 0 : lbl_2:
33166 0 : state->fbase = state->f;
33167 0 : i = 0;
33168 0 : lbl_21:
33169 0 : if( i>n-1 )
33170 : {
33171 0 : goto lbl_23;
33172 : }
33173 0 : v = state->x.ptr.p_double[i];
33174 0 : state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i];
33175 0 : state->rstate.stage = 3;
33176 0 : goto lbl_rcomm;
33177 0 : lbl_3:
33178 0 : state->fm2 = state->f;
33179 0 : state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i];
33180 0 : state->rstate.stage = 4;
33181 0 : goto lbl_rcomm;
33182 0 : lbl_4:
33183 0 : state->fm1 = state->f;
33184 0 : state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i];
33185 0 : state->rstate.stage = 5;
33186 0 : goto lbl_rcomm;
33187 0 : lbl_5:
33188 0 : state->fp1 = state->f;
33189 0 : state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i];
33190 0 : state->rstate.stage = 6;
33191 0 : goto lbl_rcomm;
33192 0 : lbl_6:
33193 0 : state->fp2 = state->f;
33194 0 : state->x.ptr.p_double[i] = v;
33195 0 : state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]);
33196 0 : i = i+1;
33197 0 : goto lbl_21;
33198 0 : lbl_23:
33199 0 : state->f = state->fbase;
33200 0 : state->needf = ae_false;
33201 498 : lbl_20:
33202 498 : trimprepare(state->f, &state->trimthreshold, _state);
33203 498 : if( !state->xrep )
33204 : {
33205 498 : goto lbl_24;
33206 : }
33207 0 : minlbfgs_clearrequestfields(state, _state);
33208 0 : state->xupdated = ae_true;
33209 0 : state->rstate.stage = 7;
33210 0 : goto lbl_rcomm;
33211 0 : lbl_7:
33212 0 : state->xupdated = ae_false;
33213 498 : lbl_24:
33214 498 : if( state->userterminationneeded )
33215 : {
33216 :
33217 : /*
33218 : * User requested termination
33219 : */
33220 0 : state->repterminationtype = 8;
33221 0 : result = ae_false;
33222 0 : return result;
33223 : }
33224 498 : state->repnfev = 1;
33225 498 : state->fold = state->f;
33226 498 : v = (double)(0);
33227 1494 : for(i=0; i<=n-1; i++)
33228 : {
33229 996 : v = v+ae_sqr(state->g.ptr.p_double[i]*state->s.ptr.p_double[i], _state);
33230 : }
33231 498 : if( ae_fp_less_eq(ae_sqrt(v, _state),state->epsg) )
33232 : {
33233 0 : state->repterminationtype = 4;
33234 0 : result = ae_false;
33235 0 : return result;
33236 : }
33237 :
33238 : /*
33239 : * Choose initial step and direction.
33240 : * Apply preconditioner, if we have something other than default.
33241 : */
33242 498 : ae_v_moveneg(&state->d.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
33243 498 : if( state->prectype==0 )
33244 : {
33245 :
33246 : /*
33247 : * Default preconditioner is used, but we can't use it before iterations will start
33248 : */
33249 498 : v = ae_v_dotproduct(&state->g.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
33250 498 : v = ae_sqrt(v, _state);
33251 498 : if( ae_fp_eq(state->stpmax,(double)(0)) )
33252 : {
33253 498 : state->stp = ae_minreal(1.0/v, (double)(1), _state);
33254 : }
33255 : else
33256 : {
33257 0 : state->stp = ae_minreal(1.0/v, state->stpmax, _state);
33258 : }
33259 : }
33260 498 : if( state->prectype==1 )
33261 : {
33262 :
33263 : /*
33264 : * Cholesky preconditioner is used
33265 : */
33266 0 : fblscholeskysolve(&state->denseh, 1.0, n, ae_true, &state->d, &state->autobuf, _state);
33267 0 : state->stp = (double)(1);
33268 : }
33269 498 : if( state->prectype==2 )
33270 : {
33271 :
33272 : /*
33273 : * diagonal approximation is used
33274 : */
33275 0 : for(i=0; i<=n-1; i++)
33276 : {
33277 0 : state->d.ptr.p_double[i] = state->d.ptr.p_double[i]/state->diagh.ptr.p_double[i];
33278 : }
33279 0 : state->stp = (double)(1);
33280 : }
33281 498 : if( state->prectype==3 )
33282 : {
33283 :
33284 : /*
33285 : * scale-based preconditioner is used
33286 : */
33287 0 : for(i=0; i<=n-1; i++)
33288 : {
33289 0 : state->d.ptr.p_double[i] = state->d.ptr.p_double[i]*state->s.ptr.p_double[i]*state->s.ptr.p_double[i];
33290 : }
33291 0 : state->stp = (double)(1);
33292 : }
33293 498 : if( state->prectype==4 )
33294 : {
33295 :
33296 : /*
33297 : * rank-k BFGS-based preconditioner is used
33298 : */
33299 0 : inexactlbfgspreconditioner(&state->d, n, &state->precd, &state->precc, &state->precw, state->preck, &state->precbuf, _state);
33300 0 : state->stp = (double)(1);
33301 : }
33302 498 : if( state->prectype==5 )
33303 : {
33304 :
33305 : /*
33306 : * exact low-rank preconditioner is used
33307 : */
33308 0 : applylowrankpreconditioner(&state->d, &state->lowrankbuf, _state);
33309 0 : state->stp = (double)(1);
33310 : }
33311 :
33312 : /*
33313 : * Main cycle
33314 : */
33315 498 : state->k = 0;
33316 1269 : lbl_26:
33317 : if( ae_false )
33318 : {
33319 : goto lbl_27;
33320 : }
33321 :
33322 : /*
33323 : * Main cycle: prepare to 1-D line search
33324 : */
33325 1269 : state->p = state->k%m;
33326 1269 : state->q = ae_minint(state->k, m-1, _state);
33327 :
33328 : /*
33329 : * Store X[k], G[k]
33330 : */
33331 1269 : ae_v_move(&state->xp.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1));
33332 1269 : 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));
33333 1269 : 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));
33334 :
33335 : /*
33336 : * Minimize F(x+alpha*d)
33337 : * Calculate S[k], Y[k]
33338 : */
33339 1269 : state->mcstage = 0;
33340 1269 : if( state->k!=0 )
33341 : {
33342 771 : state->stp = 1.0;
33343 : }
33344 1269 : linminnormalized(&state->d, &state->stp, n, _state);
33345 1269 : smoothnessmonitorstartlinesearch1u(&state->smonitor, &state->s, &state->invs, &state->x, state->f, &state->g, _state);
33346 1269 : 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);
33347 5660 : lbl_28:
33348 5660 : if( state->mcstage==0 )
33349 : {
33350 1269 : goto lbl_29;
33351 : }
33352 4391 : minlbfgs_clearrequestfields(state, _state);
33353 4391 : if( ae_fp_neq(state->diffstep,(double)(0)) )
33354 : {
33355 0 : goto lbl_30;
33356 : }
33357 4391 : state->needfg = ae_true;
33358 4391 : state->rstate.stage = 8;
33359 4391 : goto lbl_rcomm;
33360 4391 : lbl_8:
33361 4391 : state->needfg = ae_false;
33362 4391 : goto lbl_31;
33363 0 : lbl_30:
33364 0 : state->needf = ae_true;
33365 0 : state->rstate.stage = 9;
33366 0 : goto lbl_rcomm;
33367 0 : lbl_9:
33368 0 : state->fbase = state->f;
33369 0 : i = 0;
33370 0 : lbl_32:
33371 0 : if( i>n-1 )
33372 : {
33373 0 : goto lbl_34;
33374 : }
33375 0 : v = state->x.ptr.p_double[i];
33376 0 : state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i];
33377 0 : state->rstate.stage = 10;
33378 0 : goto lbl_rcomm;
33379 0 : lbl_10:
33380 0 : state->fm2 = state->f;
33381 0 : state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i];
33382 0 : state->rstate.stage = 11;
33383 0 : goto lbl_rcomm;
33384 0 : lbl_11:
33385 0 : state->fm1 = state->f;
33386 0 : state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i];
33387 0 : state->rstate.stage = 12;
33388 0 : goto lbl_rcomm;
33389 0 : lbl_12:
33390 0 : state->fp1 = state->f;
33391 0 : state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i];
33392 0 : state->rstate.stage = 13;
33393 0 : goto lbl_rcomm;
33394 0 : lbl_13:
33395 0 : state->fp2 = state->f;
33396 0 : state->x.ptr.p_double[i] = v;
33397 0 : state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]);
33398 0 : i = i+1;
33399 0 : goto lbl_32;
33400 0 : lbl_34:
33401 0 : state->f = state->fbase;
33402 0 : state->needf = ae_false;
33403 4391 : lbl_31:
33404 4391 : smoothnessmonitorenqueuepoint1u(&state->smonitor, &state->s, &state->invs, &state->d, state->stp, &state->x, state->f, &state->g, _state);
33405 4391 : trimfunction(&state->f, &state->g, n, state->trimthreshold, _state);
33406 4391 : 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);
33407 4391 : goto lbl_28;
33408 1269 : lbl_29:
33409 1269 : smoothnessmonitorfinalizelinesearch(&state->smonitor, _state);
33410 1269 : if( state->userterminationneeded )
33411 : {
33412 :
33413 : /*
33414 : * User requested termination.
33415 : * Restore previous point and return.
33416 : */
33417 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xp.ptr.p_double[0], 1, ae_v_len(0,n-1));
33418 0 : state->repterminationtype = 8;
33419 0 : result = ae_false;
33420 0 : return result;
33421 : }
33422 1269 : if( !state->xrep )
33423 : {
33424 1269 : goto lbl_35;
33425 : }
33426 :
33427 : /*
33428 : * report
33429 : */
33430 0 : minlbfgs_clearrequestfields(state, _state);
33431 0 : state->xupdated = ae_true;
33432 0 : state->rstate.stage = 14;
33433 0 : goto lbl_rcomm;
33434 0 : lbl_14:
33435 0 : state->xupdated = ae_false;
33436 1269 : lbl_35:
33437 1269 : state->repnfev = state->repnfev+state->nfev;
33438 1269 : state->repiterationscount = state->repiterationscount+1;
33439 1269 : 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));
33440 1269 : 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));
33441 :
33442 : /*
33443 : * Stopping conditions
33444 : */
33445 1269 : v = (double)(0);
33446 3807 : for(i=0; i<=n-1; i++)
33447 : {
33448 2538 : v = v+ae_sqr(state->g.ptr.p_double[i]*state->s.ptr.p_double[i], _state);
33449 : }
33450 1269 : if( !ae_isfinite(v, _state)||!ae_isfinite(state->f, _state) )
33451 : {
33452 :
33453 : /*
33454 : * Abnormal termination - infinities in function/gradient
33455 : */
33456 0 : state->repterminationtype = -8;
33457 0 : result = ae_false;
33458 0 : return result;
33459 : }
33460 1269 : if( state->repiterationscount>=state->maxits&&state->maxits>0 )
33461 : {
33462 :
33463 : /*
33464 : * Too many iterations
33465 : */
33466 30 : state->repterminationtype = 5;
33467 30 : result = ae_false;
33468 30 : return result;
33469 : }
33470 1239 : if( ae_fp_less_eq(ae_sqrt(v, _state),state->epsg) )
33471 : {
33472 :
33473 : /*
33474 : * Gradient is small enough
33475 : */
33476 3 : state->repterminationtype = 4;
33477 3 : result = ae_false;
33478 3 : return result;
33479 : }
33480 1236 : 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)) )
33481 : {
33482 :
33483 : /*
33484 : * F(k+1)-F(k) is small enough
33485 : */
33486 465 : state->repterminationtype = 1;
33487 465 : result = ae_false;
33488 465 : return result;
33489 : }
33490 771 : v = (double)(0);
33491 2313 : for(i=0; i<=n-1; i++)
33492 : {
33493 1542 : v = v+ae_sqr(state->sk.ptr.pp_double[state->p][i]/state->s.ptr.p_double[i], _state);
33494 : }
33495 771 : if( ae_fp_less_eq(ae_sqrt(v, _state),state->epsx) )
33496 : {
33497 :
33498 : /*
33499 : * X(k+1)-X(k) is small enough
33500 : */
33501 0 : state->repterminationtype = 2;
33502 0 : result = ae_false;
33503 0 : return result;
33504 : }
33505 :
33506 : /*
33507 : * If Wolfe conditions are satisfied, we can update
33508 : * limited memory model.
33509 : *
33510 : * However, if conditions are not satisfied (NFEV limit is met,
33511 : * function is too wild, ...), we'll skip L-BFGS update
33512 : */
33513 771 : if( mcinfo!=1 )
33514 : {
33515 :
33516 : /*
33517 : * Skip update.
33518 : *
33519 : * In such cases we'll initialize search direction by
33520 : * antigradient vector, because it leads to more
33521 : * transparent code with less number of special cases
33522 : */
33523 42 : state->fold = state->f;
33524 42 : ae_v_moveneg(&state->d.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
33525 : }
33526 : else
33527 : {
33528 :
33529 : /*
33530 : * Calculate Rho[k], GammaK
33531 : */
33532 729 : 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));
33533 729 : 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));
33534 729 : if( ae_fp_eq(v,(double)(0))||ae_fp_eq(vv,(double)(0)) )
33535 : {
33536 :
33537 : /*
33538 : * Rounding errors make further iterations impossible.
33539 : */
33540 0 : state->repterminationtype = -2;
33541 0 : result = ae_false;
33542 0 : return result;
33543 : }
33544 729 : state->rho.ptr.p_double[state->p] = 1/v;
33545 729 : state->gammak = v/vv;
33546 :
33547 : /*
33548 : * Calculate d(k+1) = -H(k+1)*g(k+1)
33549 : *
33550 : * for I:=K downto K-Q do
33551 : * V = s(i)^T * work(iteration:I)
33552 : * theta(i) = V
33553 : * work(iteration:I+1) = work(iteration:I) - V*Rho(i)*y(i)
33554 : * work(last iteration) = H0*work(last iteration) - preconditioner
33555 : * for I:=K-Q to K do
33556 : * V = y(i)^T*work(iteration:I)
33557 : * work(iteration:I+1) = work(iteration:I) +(-V+theta(i))*Rho(i)*s(i)
33558 : *
33559 : * NOW WORK CONTAINS d(k+1)
33560 : */
33561 729 : ae_v_move(&state->work.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
33562 1458 : for(i=state->k; i>=state->k-state->q; i--)
33563 : {
33564 729 : ic = i%m;
33565 729 : 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));
33566 729 : state->theta.ptr.p_double[ic] = v;
33567 729 : vv = v*state->rho.ptr.p_double[ic];
33568 729 : 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);
33569 : }
33570 729 : if( state->prectype==0 )
33571 : {
33572 :
33573 : /*
33574 : * Simple preconditioner is used
33575 : */
33576 729 : v = state->gammak;
33577 729 : ae_v_muld(&state->work.ptr.p_double[0], 1, ae_v_len(0,n-1), v);
33578 : }
33579 729 : if( state->prectype==1 )
33580 : {
33581 :
33582 : /*
33583 : * Cholesky preconditioner is used
33584 : */
33585 0 : fblscholeskysolve(&state->denseh, (double)(1), n, ae_true, &state->work, &state->autobuf, _state);
33586 : }
33587 729 : if( state->prectype==2 )
33588 : {
33589 :
33590 : /*
33591 : * diagonal approximation is used
33592 : */
33593 0 : for(i=0; i<=n-1; i++)
33594 : {
33595 0 : state->work.ptr.p_double[i] = state->work.ptr.p_double[i]/state->diagh.ptr.p_double[i];
33596 : }
33597 : }
33598 729 : if( state->prectype==3 )
33599 : {
33600 :
33601 : /*
33602 : * scale-based preconditioner is used
33603 : */
33604 0 : for(i=0; i<=n-1; i++)
33605 : {
33606 0 : state->work.ptr.p_double[i] = state->work.ptr.p_double[i]*state->s.ptr.p_double[i]*state->s.ptr.p_double[i];
33607 : }
33608 : }
33609 729 : if( state->prectype==4 )
33610 : {
33611 :
33612 : /*
33613 : * Rank-K BFGS-based preconditioner is used
33614 : */
33615 0 : inexactlbfgspreconditioner(&state->work, n, &state->precd, &state->precc, &state->precw, state->preck, &state->precbuf, _state);
33616 : }
33617 729 : if( state->prectype==5 )
33618 : {
33619 :
33620 : /*
33621 : * Exact low-rank preconditioner is used
33622 : */
33623 0 : applylowrankpreconditioner(&state->work, &state->lowrankbuf, _state);
33624 : }
33625 1458 : for(i=state->k-state->q; i<=state->k; i++)
33626 : {
33627 729 : ic = i%m;
33628 729 : 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));
33629 729 : vv = state->rho.ptr.p_double[ic]*(-v+state->theta.ptr.p_double[ic]);
33630 729 : 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);
33631 : }
33632 729 : ae_v_moveneg(&state->d.ptr.p_double[0], 1, &state->work.ptr.p_double[0], 1, ae_v_len(0,n-1));
33633 :
33634 : /*
33635 : * Next step
33636 : */
33637 729 : state->fold = state->f;
33638 729 : state->k = state->k+1;
33639 : }
33640 771 : goto lbl_26;
33641 : lbl_27:
33642 : result = ae_false;
33643 : return result;
33644 :
33645 : /*
33646 : * Saving state
33647 : */
33648 4889 : lbl_rcomm:
33649 4889 : result = ae_true;
33650 4889 : state->rstate.ia.ptr.p_int[0] = n;
33651 4889 : state->rstate.ia.ptr.p_int[1] = m;
33652 4889 : state->rstate.ia.ptr.p_int[2] = i;
33653 4889 : state->rstate.ia.ptr.p_int[3] = j;
33654 4889 : state->rstate.ia.ptr.p_int[4] = ic;
33655 4889 : state->rstate.ia.ptr.p_int[5] = mcinfo;
33656 4889 : state->rstate.ra.ptr.p_double[0] = v;
33657 4889 : state->rstate.ra.ptr.p_double[1] = vv;
33658 4889 : return result;
33659 : }
33660 :
33661 :
33662 : /*************************************************************************
33663 : This function activates/deactivates verification of the user-supplied
33664 : analytic gradient.
33665 :
33666 : Upon activation of this option OptGuard integrity checker performs
33667 : numerical differentiation of your target function at the initial point
33668 : (note: future versions may also perform check at the final point) and
33669 : compares numerical gradient with analytic one provided by you.
33670 :
33671 : If difference is too large, an error flag is set and optimization session
33672 : continues. After optimization session is over, you can retrieve the report
33673 : which stores both gradients and specific components highlighted as
33674 : suspicious by the OptGuard.
33675 :
33676 : The primary OptGuard report can be retrieved with minlbfgsoptguardresults().
33677 :
33678 : IMPORTANT: gradient check is a high-overhead option which will cost you
33679 : about 3*N additional function evaluations. In many cases it may
33680 : cost as much as the rest of the optimization session.
33681 :
33682 : YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO
33683 : CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY.
33684 :
33685 : NOTE: unlike previous incarnation of the gradient checking code, OptGuard
33686 : does NOT interrupt optimization even if it discovers bad gradient.
33687 :
33688 : INPUT PARAMETERS:
33689 : State - structure used to store algorithm state
33690 : TestStep - verification step used for numerical differentiation:
33691 : * TestStep=0 turns verification off
33692 : * TestStep>0 activates verification
33693 : You should carefully choose TestStep. Value which is
33694 : too large (so large that function behavior is non-
33695 : cubic at this scale) will lead to false alarms. Too
33696 : short step will result in rounding errors dominating
33697 : numerical derivative.
33698 :
33699 : You may use different step for different parameters by
33700 : means of setting scale with minlbfgssetscale().
33701 :
33702 : === EXPLANATION ==========================================================
33703 :
33704 : In order to verify gradient algorithm performs following steps:
33705 : * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i],
33706 : where X[i] is i-th component of the initial point and S[i] is a scale
33707 : of i-th parameter
33708 : * F(X) is evaluated at these trial points
33709 : * we perform one more evaluation in the middle point of the interval
33710 : * we build cubic model using function values and derivatives at trial
33711 : points and we compare its prediction with actual value in the middle
33712 : point
33713 :
33714 : -- ALGLIB --
33715 : Copyright 15.06.2014 by Bochkanov Sergey
33716 : *************************************************************************/
33717 0 : void minlbfgsoptguardgradient(minlbfgsstate* state,
33718 : double teststep,
33719 : ae_state *_state)
33720 : {
33721 :
33722 :
33723 0 : ae_assert(ae_isfinite(teststep, _state), "MinLBFGSOptGuardGradient: TestStep contains NaN or INF", _state);
33724 0 : ae_assert(ae_fp_greater_eq(teststep,(double)(0)), "MinLBFGSOptGuardGradient: invalid argument TestStep(TestStep<0)", _state);
33725 0 : state->teststep = teststep;
33726 0 : }
33727 :
33728 :
33729 : /*************************************************************************
33730 : This function activates/deactivates nonsmoothness monitoring option of
33731 : the OptGuard integrity checker. Smoothness monitor silently observes
33732 : solution process and tries to detect ill-posed problems, i.e. ones with:
33733 : a) discontinuous target function (non-C0)
33734 : b) nonsmooth target function (non-C1)
33735 :
33736 : Smoothness monitoring does NOT interrupt optimization even if it suspects
33737 : that your problem is nonsmooth. It just sets corresponding flags in the
33738 : OptGuard report which can be retrieved after optimization is over.
33739 :
33740 : Smoothness monitoring is a moderate overhead option which often adds less
33741 : than 1% to the optimizer running time. Thus, you can use it even for large
33742 : scale problems.
33743 :
33744 : NOTE: OptGuard does NOT guarantee that it will always detect C0/C1
33745 : continuity violations.
33746 :
33747 : First, minor errors are hard to catch - say, a 0.0001 difference in
33748 : the model values at two sides of the gap may be due to discontinuity
33749 : of the model - or simply because the model has changed.
33750 :
33751 : Second, C1-violations are especially difficult to detect in a
33752 : noninvasive way. The optimizer usually performs very short steps
33753 : near the nonsmoothness, and differentiation usually introduces a
33754 : lot of numerical noise. It is hard to tell whether some tiny
33755 : discontinuity in the slope is due to real nonsmoothness or just due
33756 : to numerical noise alone.
33757 :
33758 : Our top priority was to avoid false positives, so in some rare cases
33759 : minor errors may went unnoticed (however, in most cases they can be
33760 : spotted with restart from different initial point).
33761 :
33762 : INPUT PARAMETERS:
33763 : state - algorithm state
33764 : level - monitoring level:
33765 : * 0 - monitoring is disabled
33766 : * 1 - noninvasive low-overhead monitoring; function values
33767 : and/or gradients are recorded, but OptGuard does not
33768 : try to perform additional evaluations in order to
33769 : get more information about suspicious locations.
33770 :
33771 : === EXPLANATION ==========================================================
33772 :
33773 : One major source of headache during optimization is the possibility of
33774 : the coding errors in the target function/constraints (or their gradients).
33775 : Such errors most often manifest themselves as discontinuity or
33776 : nonsmoothness of the target/constraints.
33777 :
33778 : Another frequent situation is when you try to optimize something involving
33779 : lots of min() and max() operations, i.e. nonsmooth target. Although not a
33780 : coding error, it is nonsmoothness anyway - and smooth optimizers usually
33781 : stop right after encountering nonsmoothness, well before reaching solution.
33782 :
33783 : OptGuard integrity checker helps you to catch such situations: it monitors
33784 : function values/gradients being passed to the optimizer and tries to
33785 : errors. Upon discovering suspicious pair of points it raises appropriate
33786 : flag (and allows you to continue optimization). When optimization is done,
33787 : you can study OptGuard result.
33788 :
33789 : -- ALGLIB --
33790 : Copyright 21.11.2018 by Bochkanov Sergey
33791 : *************************************************************************/
33792 0 : void minlbfgsoptguardsmoothness(minlbfgsstate* state,
33793 : ae_int_t level,
33794 : ae_state *_state)
33795 : {
33796 :
33797 :
33798 0 : ae_assert(level==0||level==1, "MinLBFGSOptGuardSmoothness: unexpected value of level parameter", _state);
33799 0 : state->smoothnessguardlevel = level;
33800 0 : }
33801 :
33802 :
33803 : /*************************************************************************
33804 : Results of OptGuard integrity check, should be called after optimization
33805 : session is over.
33806 :
33807 : === PRIMARY REPORT =======================================================
33808 :
33809 : OptGuard performs several checks which are intended to catch common errors
33810 : in the implementation of nonlinear function/gradient:
33811 : * incorrect analytic gradient
33812 : * discontinuous (non-C0) target functions (constraints)
33813 : * nonsmooth (non-C1) target functions (constraints)
33814 :
33815 : Each of these checks is activated with appropriate function:
33816 : * minlbfgsoptguardgradient() for gradient verification
33817 : * minlbfgsoptguardsmoothness() for C0/C1 checks
33818 :
33819 : Following flags are set when these errors are suspected:
33820 : * rep.badgradsuspected, and additionally:
33821 : * rep.badgradvidx for specific variable (gradient element) suspected
33822 : * rep.badgradxbase, a point where gradient is tested
33823 : * rep.badgraduser, user-provided gradient (stored as 2D matrix with
33824 : single row in order to make report structure compatible with more
33825 : complex optimizers like MinNLC or MinLM)
33826 : * rep.badgradnum, reference gradient obtained via numerical
33827 : differentiation (stored as 2D matrix with single row in order to make
33828 : report structure compatible with more complex optimizers like MinNLC
33829 : or MinLM)
33830 : * rep.nonc0suspected
33831 : * rep.nonc1suspected
33832 :
33833 : === ADDITIONAL REPORTS/LOGS ==============================================
33834 :
33835 : Several different tests are performed to catch C0/C1 errors, you can find
33836 : out specific test signaled error by looking to:
33837 : * rep.nonc0test0positive, for non-C0 test #0
33838 : * rep.nonc1test0positive, for non-C1 test #0
33839 : * rep.nonc1test1positive, for non-C1 test #1
33840 :
33841 : Additional information (including line search logs) can be obtained by
33842 : means of:
33843 : * minlbfgsoptguardnonc1test0results()
33844 : * minlbfgsoptguardnonc1test1results()
33845 : which return detailed error reports, specific points where discontinuities
33846 : were found, and so on.
33847 :
33848 : ==========================================================================
33849 :
33850 : INPUT PARAMETERS:
33851 : state - algorithm state
33852 :
33853 : OUTPUT PARAMETERS:
33854 : rep - generic OptGuard report; more detailed reports can be
33855 : retrieved with other functions.
33856 :
33857 : NOTE: false negatives (nonsmooth problems are not identified as nonsmooth
33858 : ones) are possible although unlikely.
33859 :
33860 : The reason is that you need to make several evaluations around
33861 : nonsmoothness in order to accumulate enough information about
33862 : function curvature. Say, if you start right from the nonsmooth point,
33863 : optimizer simply won't get enough data to understand what is going
33864 : wrong before it terminates due to abrupt changes in the derivative.
33865 : It is also possible that "unlucky" step will move us to the
33866 : termination too quickly.
33867 :
33868 : Our current approach is to have less than 0.1% false negatives in
33869 : our test examples (measured with multiple restarts from random
33870 : points), and to have exactly 0% false positives.
33871 :
33872 : -- ALGLIB --
33873 : Copyright 21.11.2018 by Bochkanov Sergey
33874 : *************************************************************************/
33875 0 : void minlbfgsoptguardresults(minlbfgsstate* state,
33876 : optguardreport* rep,
33877 : ae_state *_state)
33878 : {
33879 :
33880 0 : _optguardreport_clear(rep);
33881 :
33882 0 : smoothnessmonitorexportreport(&state->smonitor, rep, _state);
33883 0 : }
33884 :
33885 :
33886 : /*************************************************************************
33887 : Detailed results of the OptGuard integrity check for nonsmoothness test #0
33888 :
33889 : Nonsmoothness (non-C1) test #0 studies function values (not gradient!)
33890 : obtained during line searches and monitors behavior of the directional
33891 : derivative estimate.
33892 :
33893 : This test is less powerful than test #1, but it does not depend on the
33894 : gradient values and thus it is more robust against artifacts introduced by
33895 : numerical differentiation.
33896 :
33897 : Two reports are returned:
33898 : * a "strongest" one, corresponding to line search which had highest
33899 : value of the nonsmoothness indicator
33900 : * a "longest" one, corresponding to line search which had more function
33901 : evaluations, and thus is more detailed
33902 :
33903 : In both cases following fields are returned:
33904 :
33905 : * positive - is TRUE when test flagged suspicious point; FALSE if test
33906 : did not notice anything (in the latter cases fields below are empty).
33907 : * x0[], d[] - arrays of length N which store initial point and direction
33908 : for line search (d[] can be normalized, but does not have to)
33909 : * stp[], f[] - arrays of length CNT which store step lengths and function
33910 : values at these points; f[i] is evaluated in x0+stp[i]*d.
33911 : * stpidxa, stpidxb - we suspect that function violates C1 continuity
33912 : between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3,
33913 : with most likely position of the violation between stpidxa+1 and
33914 : stpidxa+2.
33915 :
33916 : ==========================================================================
33917 : = SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will
33918 : = see where C1 continuity is violated.
33919 : ==========================================================================
33920 :
33921 : INPUT PARAMETERS:
33922 : state - algorithm state
33923 :
33924 : OUTPUT PARAMETERS:
33925 : strrep - C1 test #0 "strong" report
33926 : lngrep - C1 test #0 "long" report
33927 :
33928 : -- ALGLIB --
33929 : Copyright 21.11.2018 by Bochkanov Sergey
33930 : *************************************************************************/
33931 0 : void minlbfgsoptguardnonc1test0results(minlbfgsstate* state,
33932 : optguardnonc1test0report* strrep,
33933 : optguardnonc1test0report* lngrep,
33934 : ae_state *_state)
33935 : {
33936 :
33937 0 : _optguardnonc1test0report_clear(strrep);
33938 0 : _optguardnonc1test0report_clear(lngrep);
33939 :
33940 0 : smoothnessmonitorexportc1test0report(&state->smonitor.nonc1test0strrep, &state->lastscaleused, strrep, _state);
33941 0 : smoothnessmonitorexportc1test0report(&state->smonitor.nonc1test0lngrep, &state->lastscaleused, lngrep, _state);
33942 0 : }
33943 :
33944 :
33945 : /*************************************************************************
33946 : Detailed results of the OptGuard integrity check for nonsmoothness test #1
33947 :
33948 : Nonsmoothness (non-C1) test #1 studies individual components of the
33949 : gradient computed during line search.
33950 :
33951 : When precise analytic gradient is provided this test is more powerful than
33952 : test #0 which works with function values and ignores user-provided
33953 : gradient. However, test #0 becomes more powerful when numerical
33954 : differentiation is employed (in such cases test #1 detects higher levels
33955 : of numerical noise and becomes too conservative).
33956 :
33957 : This test also tells specific components of the gradient which violate C1
33958 : continuity, which makes it more informative than #0, which just tells that
33959 : continuity is violated.
33960 :
33961 : Two reports are returned:
33962 : * a "strongest" one, corresponding to line search which had highest
33963 : value of the nonsmoothness indicator
33964 : * a "longest" one, corresponding to line search which had more function
33965 : evaluations, and thus is more detailed
33966 :
33967 : In both cases following fields are returned:
33968 :
33969 : * positive - is TRUE when test flagged suspicious point; FALSE if test
33970 : did not notice anything (in the latter cases fields below are empty).
33971 : * vidx - is an index of the variable in [0,N) with nonsmooth derivative
33972 : * x0[], d[] - arrays of length N which store initial point and direction
33973 : for line search (d[] can be normalized, but does not have to)
33974 : * stp[], g[] - arrays of length CNT which store step lengths and gradient
33975 : values at these points; g[i] is evaluated in x0+stp[i]*d and contains
33976 : vidx-th component of the gradient.
33977 : * stpidxa, stpidxb - we suspect that function violates C1 continuity
33978 : between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3,
33979 : with most likely position of the violation between stpidxa+1 and
33980 : stpidxa+2.
33981 :
33982 : ==========================================================================
33983 : = SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will
33984 : = see where C1 continuity is violated.
33985 : ==========================================================================
33986 :
33987 : INPUT PARAMETERS:
33988 : state - algorithm state
33989 :
33990 : OUTPUT PARAMETERS:
33991 : strrep - C1 test #1 "strong" report
33992 : lngrep - C1 test #1 "long" report
33993 :
33994 : -- ALGLIB --
33995 : Copyright 21.11.2018 by Bochkanov Sergey
33996 : *************************************************************************/
33997 0 : void minlbfgsoptguardnonc1test1results(minlbfgsstate* state,
33998 : optguardnonc1test1report* strrep,
33999 : optguardnonc1test1report* lngrep,
34000 : ae_state *_state)
34001 : {
34002 :
34003 0 : _optguardnonc1test1report_clear(strrep);
34004 0 : _optguardnonc1test1report_clear(lngrep);
34005 :
34006 0 : smoothnessmonitorexportc1test1report(&state->smonitor.nonc1test1strrep, &state->lastscaleused, strrep, _state);
34007 0 : smoothnessmonitorexportc1test1report(&state->smonitor.nonc1test1lngrep, &state->lastscaleused, lngrep, _state);
34008 0 : }
34009 :
34010 :
34011 : /*************************************************************************
34012 : L-BFGS algorithm results
34013 :
34014 : INPUT PARAMETERS:
34015 : State - algorithm state
34016 :
34017 : OUTPUT PARAMETERS:
34018 : X - array[0..N-1], solution
34019 : Rep - optimization report:
34020 : * Rep.TerminationType completetion code:
34021 : * -8 internal integrity control detected infinite
34022 : or NAN values in function/gradient. Abnormal
34023 : termination signalled.
34024 : * -2 rounding errors prevent further improvement.
34025 : X contains best point found.
34026 : * -1 incorrect parameters were specified
34027 : * 1 relative function improvement is no more than
34028 : EpsF.
34029 : * 2 relative step is no more than EpsX.
34030 : * 4 gradient norm is no more than EpsG
34031 : * 5 MaxIts steps was taken
34032 : * 7 stopping conditions are too stringent,
34033 : further improvement is impossible
34034 : * 8 terminated by user who called minlbfgsrequesttermination().
34035 : X contains point which was "current accepted" when
34036 : termination request was submitted.
34037 : * Rep.IterationsCount contains iterations count
34038 : * NFEV countains number of function calculations
34039 :
34040 : -- ALGLIB --
34041 : Copyright 02.04.2010 by Bochkanov Sergey
34042 : *************************************************************************/
34043 498 : void minlbfgsresults(minlbfgsstate* state,
34044 : /* Real */ ae_vector* x,
34045 : minlbfgsreport* rep,
34046 : ae_state *_state)
34047 : {
34048 :
34049 498 : ae_vector_clear(x);
34050 498 : _minlbfgsreport_clear(rep);
34051 :
34052 498 : minlbfgsresultsbuf(state, x, rep, _state);
34053 498 : }
34054 :
34055 :
34056 : /*************************************************************************
34057 : L-BFGS algorithm results
34058 :
34059 : Buffered implementation of MinLBFGSResults which uses pre-allocated buffer
34060 : to store X[]. If buffer size is too small, it resizes buffer. It is
34061 : intended to be used in the inner cycles of performance critical algorithms
34062 : where array reallocation penalty is too large to be ignored.
34063 :
34064 : -- ALGLIB --
34065 : Copyright 20.08.2010 by Bochkanov Sergey
34066 : *************************************************************************/
34067 498 : void minlbfgsresultsbuf(minlbfgsstate* state,
34068 : /* Real */ ae_vector* x,
34069 : minlbfgsreport* rep,
34070 : ae_state *_state)
34071 : {
34072 :
34073 :
34074 498 : if( x->cnt<state->n )
34075 : {
34076 498 : ae_vector_set_length(x, state->n, _state);
34077 : }
34078 498 : ae_v_move(&x->ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,state->n-1));
34079 498 : rep->iterationscount = state->repiterationscount;
34080 498 : rep->nfev = state->repnfev;
34081 498 : rep->terminationtype = state->repterminationtype;
34082 498 : }
34083 :
34084 :
34085 : /*************************************************************************
34086 : This subroutine restarts LBFGS algorithm from new point. All optimization
34087 : parameters are left unchanged.
34088 :
34089 : This function allows to solve multiple optimization problems (which
34090 : must have same number of dimensions) without object reallocation penalty.
34091 :
34092 : INPUT PARAMETERS:
34093 : State - structure used to store algorithm state
34094 : X - new starting point.
34095 :
34096 : -- ALGLIB --
34097 : Copyright 30.07.2010 by Bochkanov Sergey
34098 : *************************************************************************/
34099 498 : void minlbfgsrestartfrom(minlbfgsstate* state,
34100 : /* Real */ ae_vector* x,
34101 : ae_state *_state)
34102 : {
34103 :
34104 :
34105 498 : ae_assert(x->cnt>=state->n, "MinLBFGSRestartFrom: Length(X)<N!", _state);
34106 498 : ae_assert(isfinitevector(x, state->n, _state), "MinLBFGSRestartFrom: X contains infinite or NaN values!", _state);
34107 498 : ae_v_move(&state->xbase.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,state->n-1));
34108 498 : ae_vector_set_length(&state->rstate.ia, 5+1, _state);
34109 498 : ae_vector_set_length(&state->rstate.ra, 1+1, _state);
34110 498 : state->rstate.stage = -1;
34111 498 : minlbfgs_clearrequestfields(state, _state);
34112 498 : }
34113 :
34114 :
34115 : /*************************************************************************
34116 : This subroutine submits request for termination of running optimizer. It
34117 : should be called from user-supplied callback when user decides that it is
34118 : time to "smoothly" terminate optimization process. As result, optimizer
34119 : stops at point which was "current accepted" when termination request was
34120 : submitted and returns error code 8 (successful termination).
34121 :
34122 : INPUT PARAMETERS:
34123 : State - optimizer structure
34124 :
34125 : NOTE: after request for termination optimizer may perform several
34126 : additional calls to user-supplied callbacks. It does NOT guarantee
34127 : to stop immediately - it just guarantees that these additional calls
34128 : will be discarded later.
34129 :
34130 : NOTE: calling this function on optimizer which is NOT running will have no
34131 : effect.
34132 :
34133 : NOTE: multiple calls to this function are possible. First call is counted,
34134 : subsequent calls are silently ignored.
34135 :
34136 : -- ALGLIB --
34137 : Copyright 08.10.2014 by Bochkanov Sergey
34138 : *************************************************************************/
34139 0 : void minlbfgsrequesttermination(minlbfgsstate* state, ae_state *_state)
34140 : {
34141 :
34142 :
34143 0 : state->userterminationneeded = ae_true;
34144 0 : }
34145 :
34146 :
34147 : /*************************************************************************
34148 : Clears request fileds (to be sure that we don't forgot to clear something)
34149 : *************************************************************************/
34150 5885 : static void minlbfgs_clearrequestfields(minlbfgsstate* state,
34151 : ae_state *_state)
34152 : {
34153 :
34154 :
34155 5885 : state->needf = ae_false;
34156 5885 : state->needfg = ae_false;
34157 5885 : state->xupdated = ae_false;
34158 5885 : }
34159 :
34160 :
34161 498 : void _minlbfgsstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
34162 : {
34163 498 : minlbfgsstate *p = (minlbfgsstate*)_p;
34164 498 : ae_touch_ptr((void*)p);
34165 498 : ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic);
34166 498 : ae_vector_init(&p->rho, 0, DT_REAL, _state, make_automatic);
34167 498 : ae_matrix_init(&p->yk, 0, 0, DT_REAL, _state, make_automatic);
34168 498 : ae_matrix_init(&p->sk, 0, 0, DT_REAL, _state, make_automatic);
34169 498 : ae_vector_init(&p->xp, 0, DT_REAL, _state, make_automatic);
34170 498 : ae_vector_init(&p->theta, 0, DT_REAL, _state, make_automatic);
34171 498 : ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic);
34172 498 : ae_vector_init(&p->work, 0, DT_REAL, _state, make_automatic);
34173 498 : ae_vector_init(&p->xbase, 0, DT_REAL, _state, make_automatic);
34174 498 : ae_matrix_init(&p->denseh, 0, 0, DT_REAL, _state, make_automatic);
34175 498 : ae_vector_init(&p->diagh, 0, DT_REAL, _state, make_automatic);
34176 498 : ae_vector_init(&p->precc, 0, DT_REAL, _state, make_automatic);
34177 498 : ae_vector_init(&p->precd, 0, DT_REAL, _state, make_automatic);
34178 498 : ae_matrix_init(&p->precw, 0, 0, DT_REAL, _state, make_automatic);
34179 498 : _precbuflbfgs_init(&p->precbuf, _state, make_automatic);
34180 498 : _precbuflowrank_init(&p->lowrankbuf, _state, make_automatic);
34181 498 : ae_vector_init(&p->autobuf, 0, DT_REAL, _state, make_automatic);
34182 498 : ae_vector_init(&p->invs, 0, DT_REAL, _state, make_automatic);
34183 498 : ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
34184 498 : ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic);
34185 498 : _rcommstate_init(&p->rstate, _state, make_automatic);
34186 498 : _linminstate_init(&p->lstate, _state, make_automatic);
34187 498 : _smoothnessmonitor_init(&p->smonitor, _state, make_automatic);
34188 498 : ae_vector_init(&p->lastscaleused, 0, DT_REAL, _state, make_automatic);
34189 498 : }
34190 :
34191 :
34192 0 : void _minlbfgsstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
34193 : {
34194 0 : minlbfgsstate *dst = (minlbfgsstate*)_dst;
34195 0 : minlbfgsstate *src = (minlbfgsstate*)_src;
34196 0 : dst->n = src->n;
34197 0 : dst->m = src->m;
34198 0 : dst->epsg = src->epsg;
34199 0 : dst->epsf = src->epsf;
34200 0 : dst->epsx = src->epsx;
34201 0 : dst->maxits = src->maxits;
34202 0 : dst->xrep = src->xrep;
34203 0 : dst->stpmax = src->stpmax;
34204 0 : ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic);
34205 0 : dst->diffstep = src->diffstep;
34206 0 : dst->nfev = src->nfev;
34207 0 : dst->mcstage = src->mcstage;
34208 0 : dst->k = src->k;
34209 0 : dst->q = src->q;
34210 0 : dst->p = src->p;
34211 0 : ae_vector_init_copy(&dst->rho, &src->rho, _state, make_automatic);
34212 0 : ae_matrix_init_copy(&dst->yk, &src->yk, _state, make_automatic);
34213 0 : ae_matrix_init_copy(&dst->sk, &src->sk, _state, make_automatic);
34214 0 : ae_vector_init_copy(&dst->xp, &src->xp, _state, make_automatic);
34215 0 : ae_vector_init_copy(&dst->theta, &src->theta, _state, make_automatic);
34216 0 : ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic);
34217 0 : dst->stp = src->stp;
34218 0 : ae_vector_init_copy(&dst->work, &src->work, _state, make_automatic);
34219 0 : dst->fold = src->fold;
34220 0 : dst->trimthreshold = src->trimthreshold;
34221 0 : ae_vector_init_copy(&dst->xbase, &src->xbase, _state, make_automatic);
34222 0 : dst->prectype = src->prectype;
34223 0 : dst->gammak = src->gammak;
34224 0 : ae_matrix_init_copy(&dst->denseh, &src->denseh, _state, make_automatic);
34225 0 : ae_vector_init_copy(&dst->diagh, &src->diagh, _state, make_automatic);
34226 0 : ae_vector_init_copy(&dst->precc, &src->precc, _state, make_automatic);
34227 0 : ae_vector_init_copy(&dst->precd, &src->precd, _state, make_automatic);
34228 0 : ae_matrix_init_copy(&dst->precw, &src->precw, _state, make_automatic);
34229 0 : dst->preck = src->preck;
34230 0 : _precbuflbfgs_init_copy(&dst->precbuf, &src->precbuf, _state, make_automatic);
34231 0 : _precbuflowrank_init_copy(&dst->lowrankbuf, &src->lowrankbuf, _state, make_automatic);
34232 0 : dst->fbase = src->fbase;
34233 0 : dst->fm2 = src->fm2;
34234 0 : dst->fm1 = src->fm1;
34235 0 : dst->fp1 = src->fp1;
34236 0 : dst->fp2 = src->fp2;
34237 0 : ae_vector_init_copy(&dst->autobuf, &src->autobuf, _state, make_automatic);
34238 0 : ae_vector_init_copy(&dst->invs, &src->invs, _state, make_automatic);
34239 0 : ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
34240 0 : dst->f = src->f;
34241 0 : ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic);
34242 0 : dst->needf = src->needf;
34243 0 : dst->needfg = src->needfg;
34244 0 : dst->xupdated = src->xupdated;
34245 0 : dst->userterminationneeded = src->userterminationneeded;
34246 0 : dst->teststep = src->teststep;
34247 0 : _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic);
34248 0 : dst->repiterationscount = src->repiterationscount;
34249 0 : dst->repnfev = src->repnfev;
34250 0 : dst->repterminationtype = src->repterminationtype;
34251 0 : _linminstate_init_copy(&dst->lstate, &src->lstate, _state, make_automatic);
34252 0 : dst->smoothnessguardlevel = src->smoothnessguardlevel;
34253 0 : _smoothnessmonitor_init_copy(&dst->smonitor, &src->smonitor, _state, make_automatic);
34254 0 : ae_vector_init_copy(&dst->lastscaleused, &src->lastscaleused, _state, make_automatic);
34255 0 : }
34256 :
34257 :
34258 498 : void _minlbfgsstate_clear(void* _p)
34259 : {
34260 498 : minlbfgsstate *p = (minlbfgsstate*)_p;
34261 498 : ae_touch_ptr((void*)p);
34262 498 : ae_vector_clear(&p->s);
34263 498 : ae_vector_clear(&p->rho);
34264 498 : ae_matrix_clear(&p->yk);
34265 498 : ae_matrix_clear(&p->sk);
34266 498 : ae_vector_clear(&p->xp);
34267 498 : ae_vector_clear(&p->theta);
34268 498 : ae_vector_clear(&p->d);
34269 498 : ae_vector_clear(&p->work);
34270 498 : ae_vector_clear(&p->xbase);
34271 498 : ae_matrix_clear(&p->denseh);
34272 498 : ae_vector_clear(&p->diagh);
34273 498 : ae_vector_clear(&p->precc);
34274 498 : ae_vector_clear(&p->precd);
34275 498 : ae_matrix_clear(&p->precw);
34276 498 : _precbuflbfgs_clear(&p->precbuf);
34277 498 : _precbuflowrank_clear(&p->lowrankbuf);
34278 498 : ae_vector_clear(&p->autobuf);
34279 498 : ae_vector_clear(&p->invs);
34280 498 : ae_vector_clear(&p->x);
34281 498 : ae_vector_clear(&p->g);
34282 498 : _rcommstate_clear(&p->rstate);
34283 498 : _linminstate_clear(&p->lstate);
34284 498 : _smoothnessmonitor_clear(&p->smonitor);
34285 498 : ae_vector_clear(&p->lastscaleused);
34286 498 : }
34287 :
34288 :
34289 498 : void _minlbfgsstate_destroy(void* _p)
34290 : {
34291 498 : minlbfgsstate *p = (minlbfgsstate*)_p;
34292 498 : ae_touch_ptr((void*)p);
34293 498 : ae_vector_destroy(&p->s);
34294 498 : ae_vector_destroy(&p->rho);
34295 498 : ae_matrix_destroy(&p->yk);
34296 498 : ae_matrix_destroy(&p->sk);
34297 498 : ae_vector_destroy(&p->xp);
34298 498 : ae_vector_destroy(&p->theta);
34299 498 : ae_vector_destroy(&p->d);
34300 498 : ae_vector_destroy(&p->work);
34301 498 : ae_vector_destroy(&p->xbase);
34302 498 : ae_matrix_destroy(&p->denseh);
34303 498 : ae_vector_destroy(&p->diagh);
34304 498 : ae_vector_destroy(&p->precc);
34305 498 : ae_vector_destroy(&p->precd);
34306 498 : ae_matrix_destroy(&p->precw);
34307 498 : _precbuflbfgs_destroy(&p->precbuf);
34308 498 : _precbuflowrank_destroy(&p->lowrankbuf);
34309 498 : ae_vector_destroy(&p->autobuf);
34310 498 : ae_vector_destroy(&p->invs);
34311 498 : ae_vector_destroy(&p->x);
34312 498 : ae_vector_destroy(&p->g);
34313 498 : _rcommstate_destroy(&p->rstate);
34314 498 : _linminstate_destroy(&p->lstate);
34315 498 : _smoothnessmonitor_destroy(&p->smonitor);
34316 498 : ae_vector_destroy(&p->lastscaleused);
34317 498 : }
34318 :
34319 :
34320 498 : void _minlbfgsreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
34321 : {
34322 498 : minlbfgsreport *p = (minlbfgsreport*)_p;
34323 498 : ae_touch_ptr((void*)p);
34324 498 : }
34325 :
34326 :
34327 0 : void _minlbfgsreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
34328 : {
34329 0 : minlbfgsreport *dst = (minlbfgsreport*)_dst;
34330 0 : minlbfgsreport *src = (minlbfgsreport*)_src;
34331 0 : dst->iterationscount = src->iterationscount;
34332 0 : dst->nfev = src->nfev;
34333 0 : dst->terminationtype = src->terminationtype;
34334 0 : }
34335 :
34336 :
34337 498 : void _minlbfgsreport_clear(void* _p)
34338 : {
34339 498 : minlbfgsreport *p = (minlbfgsreport*)_p;
34340 498 : ae_touch_ptr((void*)p);
34341 498 : }
34342 :
34343 :
34344 498 : void _minlbfgsreport_destroy(void* _p)
34345 : {
34346 498 : minlbfgsreport *p = (minlbfgsreport*)_p;
34347 498 : ae_touch_ptr((void*)p);
34348 498 : }
34349 :
34350 :
34351 : #endif
34352 : #if defined(AE_COMPILE_LPQPSERV) || !defined(AE_PARTIAL_BUILD)
34353 :
34354 :
34355 : /*************************************************************************
34356 : This function generates scaled (by S) and shifted (by XC) reformulation of
34357 : the box constraints.
34358 :
34359 : INPUT PARAMETERS:
34360 : S - scale vector, array[N]:
34361 : * I-th element contains scale of I-th variable,
34362 : * SC[I]>0
34363 : XOrigin - origin term, array[N]. Can be zero.
34364 : BndL - raw lower bounds, array[N]
34365 : BndU - raw upper bounds, array[N]
34366 : N - number of variables.
34367 :
34368 : OUTPUT PARAMETERS:
34369 : BndL - replaced by scaled/shifted lower bounds, array[N]
34370 : BndU - replaced by scaled/shifted upper bounds, array[N]
34371 :
34372 : -- ALGLIB --
34373 : Copyright 01.11.2019 by Bochkanov Sergey
34374 : *************************************************************************/
34375 0 : void scaleshiftbcinplace(/* Real */ ae_vector* s,
34376 : /* Real */ ae_vector* xorigin,
34377 : /* Real */ ae_vector* bndl,
34378 : /* Real */ ae_vector* bndu,
34379 : ae_int_t n,
34380 : ae_state *_state)
34381 : {
34382 : ae_int_t i;
34383 : ae_bool hasbndl;
34384 : ae_bool hasbndu;
34385 :
34386 :
34387 0 : for(i=0; i<=n-1; i++)
34388 : {
34389 0 : ae_assert(ae_isfinite(s->ptr.p_double[i], _state)&&s->ptr.p_double[i]>0.0, "ScaleShiftBC: S[i] is nonpositive", _state);
34390 0 : ae_assert(ae_isfinite(bndl->ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "ScaleShiftBC: BndL[i] is +INF or NAN", _state);
34391 0 : ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "ScaleShiftBC: BndU[i] is -INF or NAN", _state);
34392 0 : hasbndl = ae_isfinite(bndl->ptr.p_double[i], _state);
34393 0 : hasbndu = ae_isfinite(bndu->ptr.p_double[i], _state);
34394 0 : if( (hasbndl&&hasbndu)&&ae_fp_eq(bndl->ptr.p_double[i],bndu->ptr.p_double[i]) )
34395 : {
34396 :
34397 : /*
34398 : * Make sure that BndL[I]=BndU[I] bit-to-bit
34399 : * even with CRAZY optimizing compiler.
34400 : */
34401 0 : bndu->ptr.p_double[i] = (bndu->ptr.p_double[i]-xorigin->ptr.p_double[i])/s->ptr.p_double[i];
34402 0 : bndl->ptr.p_double[i] = bndu->ptr.p_double[i];
34403 0 : continue;
34404 : }
34405 0 : if( hasbndl )
34406 : {
34407 0 : bndl->ptr.p_double[i] = (bndl->ptr.p_double[i]-xorigin->ptr.p_double[i])/s->ptr.p_double[i];
34408 : }
34409 0 : if( hasbndu )
34410 : {
34411 0 : bndu->ptr.p_double[i] = (bndu->ptr.p_double[i]-xorigin->ptr.p_double[i])/s->ptr.p_double[i];
34412 : }
34413 : }
34414 0 : }
34415 :
34416 :
34417 : /*************************************************************************
34418 : This function generates scaled (by S) and shifted (by XC) reformulation of
34419 : two-sided "lower-bound/range" constraints stored in dense format.
34420 :
34421 : INPUT PARAMETERS:
34422 : S - scale vector, array[N]:
34423 : * I-th element contains scale of I-th variable,
34424 : * SC[I]>0
34425 : XOrigin - origin term, array[N]. Can be zero.
34426 : N - number of variables.
34427 : DenseA - array[M,N], constraint matrix
34428 : AB - lower bounds for constraints, always present and
34429 : finite, array[M]
34430 : AR - ranges for constraints, can be zero (equality
34431 : constraint), positive (range constraint) or +INF
34432 : (lower bound constraint), array[M]
34433 : M - constraint count, M>=0
34434 :
34435 : OUTPUT PARAMETERS:
34436 : DenseA - replaced by scaled/shifted constraints, array[M,N]
34437 : AB - replaced by scaled/shifted lower bounds, array[M]
34438 : AR - replaced by scaled/shifted ranges, array[M]
34439 :
34440 : -- ALGLIB --
34441 : Copyright 01.11.2019 by Bochkanov Sergey
34442 : *************************************************************************/
34443 0 : void scaleshiftdensebrlcinplace(/* Real */ ae_vector* s,
34444 : /* Real */ ae_vector* xorigin,
34445 : ae_int_t n,
34446 : /* Real */ ae_matrix* densea,
34447 : /* Real */ ae_vector* ab,
34448 : /* Real */ ae_vector* ar,
34449 : ae_int_t m,
34450 : ae_state *_state)
34451 : {
34452 : ae_int_t i;
34453 : ae_int_t j;
34454 : double v;
34455 : double vv;
34456 :
34457 :
34458 0 : for(i=0; i<=m-1; i++)
34459 : {
34460 :
34461 : /*
34462 : * Scale/shift constraint; shift its lower bound
34463 : *
34464 : * NOTE: range is NOT scaled or shifted
34465 : */
34466 0 : v = 0.0;
34467 0 : for(j=0; j<=n-1; j++)
34468 : {
34469 0 : vv = densea->ptr.pp_double[i][j];
34470 0 : v = v+vv*xorigin->ptr.p_double[j];
34471 0 : densea->ptr.pp_double[i][j] = vv*s->ptr.p_double[j];
34472 : }
34473 0 : ab->ptr.p_double[i] = ab->ptr.p_double[i]-v;
34474 : }
34475 0 : }
34476 :
34477 :
34478 : /*************************************************************************
34479 : This function generates scaled (by S) and shifted (by XC) reformulation of
34480 : two-sided "lower-bound/range" constraints stored in dense format.
34481 :
34482 : INPUT PARAMETERS:
34483 : S - scale vector, array[N]:
34484 : * I-th element contains scale of I-th variable,
34485 : * SC[I]>0
34486 : XOrigin - origin term, array[N]. Can be zero.
34487 : N - number of variables.
34488 : SparseA - sparse MSparse*N constraint matrix in CRS format;
34489 : ignored if MSparse=0.
34490 : MSparse - dense constraint count, MSparse>=0
34491 : DenseA - array[MDense,N], constraint matrix;
34492 : ignored if MDense=0.
34493 : MDense - dense constraint count, MDense>=0
34494 : AB - lower bounds for constraints, always present and
34495 : finite, array[MSparse+MDense]
34496 : AR - ranges for constraints, can be zero (equality
34497 : constraint), positive (range constraint) or +INF
34498 : (lower bound constraint), array[MSparse+MDense]
34499 :
34500 : OUTPUT PARAMETERS:
34501 : DenseA - replaced by scaled/shifted constraints, array[MDense,N]
34502 : SparseA - replaced by scaled/shifted constraints, array[MSparse,N]
34503 : AB - replaced by scaled/shifted lower bounds, array[MDense+MSparse]
34504 : AR - replaced by scaled/shifted ranges, array[MDense+MSparse]
34505 :
34506 : -- ALGLIB --
34507 : Copyright 01.11.2019 by Bochkanov Sergey
34508 : *************************************************************************/
34509 0 : void scaleshiftmixedbrlcinplace(/* Real */ ae_vector* s,
34510 : /* Real */ ae_vector* xorigin,
34511 : ae_int_t n,
34512 : sparsematrix* sparsea,
34513 : ae_int_t msparse,
34514 : /* Real */ ae_matrix* densea,
34515 : ae_int_t mdense,
34516 : /* Real */ ae_vector* ab,
34517 : /* Real */ ae_vector* ar,
34518 : ae_state *_state)
34519 : {
34520 : ae_int_t i;
34521 : ae_int_t j;
34522 : ae_int_t k;
34523 : ae_int_t k0;
34524 : ae_int_t k1;
34525 : double v;
34526 : double vv;
34527 :
34528 :
34529 0 : ae_assert(msparse==0||((sparsea->matrixtype==1&&sparsea->m==msparse)&&sparsea->n==n), "ScaleShiftMixedBRLCInplace: non-CRS sparse constraint matrix!", _state);
34530 0 : for(i=0; i<=msparse-1; i++)
34531 : {
34532 :
34533 : /*
34534 : * Scale/shift constraint; shift its lower bound
34535 : *
34536 : * NOTE: range is NOT scaled or shifted
34537 : */
34538 0 : v = 0.0;
34539 0 : k0 = sparsea->ridx.ptr.p_int[i];
34540 0 : k1 = sparsea->ridx.ptr.p_int[i+1]-1;
34541 0 : for(k=k0; k<=k1; k++)
34542 : {
34543 0 : j = sparsea->idx.ptr.p_int[k];
34544 0 : vv = sparsea->vals.ptr.p_double[k];
34545 0 : v = v+vv*xorigin->ptr.p_double[j];
34546 0 : sparsea->vals.ptr.p_double[k] = vv*s->ptr.p_double[j];
34547 : }
34548 0 : ab->ptr.p_double[i] = ab->ptr.p_double[i]-v;
34549 : }
34550 0 : for(i=0; i<=mdense-1; i++)
34551 : {
34552 :
34553 : /*
34554 : * Scale/shift constraint; shift its lower bound
34555 : *
34556 : * NOTE: range is NOT scaled or shifted
34557 : */
34558 0 : v = 0.0;
34559 0 : for(j=0; j<=n-1; j++)
34560 : {
34561 0 : vv = densea->ptr.pp_double[i][j];
34562 0 : v = v+vv*xorigin->ptr.p_double[j];
34563 0 : densea->ptr.pp_double[i][j] = vv*s->ptr.p_double[j];
34564 : }
34565 0 : ab->ptr.p_double[msparse+i] = ab->ptr.p_double[msparse+i]-v;
34566 : }
34567 0 : }
34568 :
34569 :
34570 : /*************************************************************************
34571 : This function generates scaled (by S) reformulation of dense quadratic and
34572 : linear terms in QP problem.
34573 :
34574 : INPUT PARAMETERS:
34575 : N - number of variables.
34576 : DenseA - array[NMain,NMain], quadratic term
34577 : IsUpper - whether upper or lower triangle is present
34578 : NMain - number of nonslack vars, 1<=NMain<=NTotal
34579 : DenseB - array[NTotal], linear term
34580 : NTotal - total number of variables, NTotal>=1
34581 : S - scale vector, array[NTotal]:
34582 : * I-th element contains scale of I-th variable,
34583 : * SC[I]>0
34584 :
34585 : OUTPUT PARAMETERS:
34586 : DenseA - replaced by scaled term, array[N,N]
34587 : DenseB - replaced by scaled term, array[N]
34588 :
34589 : -- ALGLIB --
34590 : Copyright 01.11.2019 by Bochkanov Sergey
34591 : *************************************************************************/
34592 0 : void scaledenseqpinplace(/* Real */ ae_matrix* densea,
34593 : ae_bool isupper,
34594 : ae_int_t nmain,
34595 : /* Real */ ae_vector* denseb,
34596 : ae_int_t ntotal,
34597 : /* Real */ ae_vector* s,
34598 : ae_state *_state)
34599 : {
34600 : ae_int_t i;
34601 : ae_int_t j;
34602 : ae_int_t j0;
34603 : ae_int_t j1;
34604 : double si;
34605 :
34606 :
34607 0 : for(i=0; i<=nmain-1; i++)
34608 : {
34609 0 : si = s->ptr.p_double[i];
34610 0 : if( isupper )
34611 : {
34612 0 : j0 = i;
34613 0 : j1 = nmain-1;
34614 : }
34615 : else
34616 : {
34617 0 : j0 = 0;
34618 0 : j1 = i;
34619 : }
34620 0 : for(j=j0; j<=j1; j++)
34621 : {
34622 0 : densea->ptr.pp_double[i][j] = densea->ptr.pp_double[i][j]*si*s->ptr.p_double[j];
34623 : }
34624 : }
34625 0 : for(i=0; i<=ntotal-1; i++)
34626 : {
34627 0 : denseb->ptr.p_double[i] = denseb->ptr.p_double[i]*s->ptr.p_double[i];
34628 : }
34629 0 : }
34630 :
34631 :
34632 : /*************************************************************************
34633 : This function generates scaled (by S) reformulation of sparse quadratic and
34634 : linear terms in QP problem.
34635 :
34636 : INPUT PARAMETERS:
34637 : S - scale vector, array[N]:
34638 : * I-th element contains scale of I-th variable,
34639 : * SC[I]>0
34640 : N - number of variables.
34641 : SparseA - NxN SparseMatrix in CRS format (any triangle can
34642 : be present, we will scale everything)
34643 : DenseB - array[N], linear term
34644 :
34645 : OUTPUT PARAMETERS:
34646 : SparseA - replaced by scaled term
34647 : DenseB - replaced by scaled term
34648 :
34649 : -- ALGLIB --
34650 : Copyright 01.11.2019 by Bochkanov Sergey
34651 : *************************************************************************/
34652 0 : void scalesparseqpinplace(/* Real */ ae_vector* s,
34653 : ae_int_t n,
34654 : sparsematrix* sparsea,
34655 : /* Real */ ae_vector* denseb,
34656 : ae_state *_state)
34657 : {
34658 : ae_int_t i;
34659 : ae_int_t k0;
34660 : ae_int_t k1;
34661 : ae_int_t k;
34662 : double si;
34663 :
34664 :
34665 0 : ae_assert((sparsea->matrixtype==1&&sparsea->m==n)&&sparsea->n==n, "ScaleSparseQPInplace: SparseA in unexpected format", _state);
34666 0 : for(i=0; i<=n-1; i++)
34667 : {
34668 0 : si = s->ptr.p_double[i];
34669 0 : k0 = sparsea->ridx.ptr.p_int[i];
34670 0 : k1 = sparsea->ridx.ptr.p_int[i+1]-1;
34671 0 : for(k=k0; k<=k1; k++)
34672 : {
34673 0 : sparsea->vals.ptr.p_double[k] = sparsea->vals.ptr.p_double[k]*si*s->ptr.p_double[sparsea->idx.ptr.p_int[k]];
34674 : }
34675 0 : denseb->ptr.p_double[i] = denseb->ptr.p_double[i]*si;
34676 : }
34677 0 : }
34678 :
34679 :
34680 : /*************************************************************************
34681 : This function normalizes two-sided "lower-bound/range" constraints stored
34682 : in dense format in such a way that L2 norms of rows (right hand side NOT
34683 : included) become equal to 1.0. Exactly zero rows are handled correctly.
34684 :
34685 : INPUT PARAMETERS:
34686 : DenseA - array[M,N], constraint matrix
34687 : AB - lower bounds for constraints, always present and
34688 : finite, array[M]
34689 : AR - ranges for constraints, can be zero (equality
34690 : constraint), positive (range constraint) or +INF
34691 : (lower bound constraint), array[M]
34692 : N - number of variables, N>=1.
34693 : M - constraint count, M>=0
34694 : NeedNorms - whether we need row norms or not
34695 :
34696 : OUTPUT PARAMETERS:
34697 : DenseA - replaced by normalized constraints, array[M,N]
34698 : AB - replaced by normalized lower bounds, array[M]
34699 : AR - replaced by normalized ranges, array[M]
34700 : RowNorms - if NeedNorms is true, leading M elements (resized
34701 : if length is less than M) are filled by row norms
34702 : before normalization was performed.
34703 :
34704 :
34705 : -- ALGLIB --
34706 : Copyright 01.11.2019 by Bochkanov Sergey
34707 : *************************************************************************/
34708 0 : void normalizedensebrlcinplace(/* Real */ ae_matrix* densea,
34709 : /* Real */ ae_vector* ab,
34710 : /* Real */ ae_vector* ar,
34711 : ae_int_t n,
34712 : ae_int_t m,
34713 : /* Real */ ae_vector* rownorms,
34714 : ae_bool neednorms,
34715 : ae_state *_state)
34716 : {
34717 : ae_int_t i;
34718 : ae_int_t j;
34719 : double v;
34720 : double vv;
34721 :
34722 :
34723 0 : if( neednorms )
34724 : {
34725 0 : rvectorsetlengthatleast(rownorms, m, _state);
34726 : }
34727 0 : for(i=0; i<=m-1; i++)
34728 : {
34729 0 : vv = 0.0;
34730 0 : for(j=0; j<=n-1; j++)
34731 : {
34732 0 : v = densea->ptr.pp_double[i][j];
34733 0 : vv = vv+v*v;
34734 : }
34735 0 : vv = ae_sqrt(vv, _state);
34736 0 : if( neednorms )
34737 : {
34738 0 : rownorms->ptr.p_double[i] = vv;
34739 : }
34740 0 : if( ae_fp_greater(vv,(double)(0)) )
34741 : {
34742 0 : vv = 1/vv;
34743 0 : for(j=0; j<=n-1; j++)
34744 : {
34745 0 : densea->ptr.pp_double[i][j] = densea->ptr.pp_double[i][j]*vv;
34746 : }
34747 0 : ab->ptr.p_double[i] = ab->ptr.p_double[i]*vv;
34748 0 : if( ae_isfinite(ar->ptr.p_double[i], _state) )
34749 : {
34750 0 : ar->ptr.p_double[i] = ar->ptr.p_double[i]*vv;
34751 : }
34752 : }
34753 : }
34754 0 : }
34755 :
34756 :
34757 : /*************************************************************************
34758 : This function normalizes two-sided "lower-bound/range" constraints stored
34759 : in dense format in such a way that L2 norms of rows (right hand side NOT
34760 : included) become equal to 1.0. Exactly zero rows are handled correctly.
34761 :
34762 : INPUT PARAMETERS:
34763 : SparseA - sparse MSparse*N constraint matrix in CRS format;
34764 : ignored if MSparse=0.
34765 : MSparse - dense constraint count, MSparse>=0
34766 : DenseA - array[MDense,N], constraint matrix;
34767 : ignored if MDense=0.
34768 : MDense - dense constraint count, MDense>=0
34769 : AB - lower bounds for constraints, always present and
34770 : finite, array[MSparse+MDense]
34771 : AR - ranges for constraints, can be zero (equality
34772 : constraint), positive (range constraint) or +INF
34773 : (lower bound constraint), array[MSparse+MDense]
34774 : N - number of variables, N>=1.
34775 : LimitedAmplification- whether row amplification is limited or not:
34776 : * if False, rows with small norms (less than 1.0)
34777 : are always normalized
34778 : * if True, we do not increase individual row norms
34779 : during normalization - only decrease. However,
34780 : we may apply one amplification rount to entire
34781 : constraint matrix, i.e. amplify all rows by same
34782 : coefficient. As result, we do not overamplify
34783 : any single row, but still make sure than entire
34784 : problem is well scaled.
34785 : If True, only large rows are normalized.
34786 : NeedNorms - whether we need row norms or not
34787 :
34788 : OUTPUT PARAMETERS:
34789 : DenseA - replaced by normalized constraints, array[M,N]
34790 : AB - replaced by normalized lower bounds, array[M]
34791 : AR - replaced by normalized ranges, array[M]
34792 : RowNorms - if NeedNorms is true, leading M elements (resized
34793 : if length is less than M) are filled by row norms
34794 : before normalization was performed.
34795 :
34796 :
34797 : -- ALGLIB --
34798 : Copyright 01.11.2019 by Bochkanov Sergey
34799 : *************************************************************************/
34800 0 : void normalizemixedbrlcinplace(sparsematrix* sparsea,
34801 : ae_int_t msparse,
34802 : /* Real */ ae_matrix* densea,
34803 : ae_int_t mdense,
34804 : /* Real */ ae_vector* ab,
34805 : /* Real */ ae_vector* ar,
34806 : ae_int_t n,
34807 : ae_bool limitedamplification,
34808 : /* Real */ ae_vector* rownorms,
34809 : ae_bool neednorms,
34810 : ae_state *_state)
34811 : {
34812 : ae_int_t i;
34813 : ae_int_t j;
34814 : ae_int_t k;
34815 : ae_int_t k0;
34816 : ae_int_t k1;
34817 : double v;
34818 : double vv;
34819 : double maxnrm2;
34820 :
34821 :
34822 0 : ae_assert(msparse==0||((sparsea->matrixtype==1&&sparsea->m==msparse)&&sparsea->n==n), "ScaleShiftMixedBRLCInplace: non-CRS sparse constraint matrix!", _state);
34823 0 : if( neednorms )
34824 : {
34825 0 : rvectorsetlengthatleast(rownorms, mdense+msparse, _state);
34826 : }
34827 :
34828 : /*
34829 : * First round of normalization - normalize row 2-norms subject to limited amplification status
34830 : */
34831 0 : maxnrm2 = (double)(0);
34832 0 : for(i=0; i<=msparse-1; i++)
34833 : {
34834 0 : vv = 0.0;
34835 0 : k0 = sparsea->ridx.ptr.p_int[i];
34836 0 : k1 = sparsea->ridx.ptr.p_int[i+1]-1;
34837 0 : for(k=k0; k<=k1; k++)
34838 : {
34839 0 : v = sparsea->vals.ptr.p_double[k];
34840 0 : vv = vv+v*v;
34841 : }
34842 0 : vv = ae_sqrt(vv, _state);
34843 0 : maxnrm2 = ae_maxreal(maxnrm2, vv, _state);
34844 0 : if( limitedamplification )
34845 : {
34846 0 : vv = ae_maxreal(vv, 1.0, _state);
34847 : }
34848 0 : if( neednorms )
34849 : {
34850 0 : rownorms->ptr.p_double[i] = vv;
34851 : }
34852 0 : if( ae_fp_greater(vv,(double)(0)) )
34853 : {
34854 0 : vv = 1/vv;
34855 0 : for(k=k0; k<=k1; k++)
34856 : {
34857 0 : sparsea->vals.ptr.p_double[k] = sparsea->vals.ptr.p_double[k]*vv;
34858 : }
34859 0 : ab->ptr.p_double[i] = ab->ptr.p_double[i]*vv;
34860 0 : if( ae_isfinite(ar->ptr.p_double[i], _state) )
34861 : {
34862 0 : ar->ptr.p_double[i] = ar->ptr.p_double[i]*vv;
34863 : }
34864 : }
34865 : }
34866 0 : for(i=0; i<=mdense-1; i++)
34867 : {
34868 0 : vv = 0.0;
34869 0 : for(j=0; j<=n-1; j++)
34870 : {
34871 0 : v = densea->ptr.pp_double[i][j];
34872 0 : vv = vv+v*v;
34873 : }
34874 0 : vv = ae_sqrt(vv, _state);
34875 0 : maxnrm2 = ae_maxreal(maxnrm2, vv, _state);
34876 0 : if( limitedamplification )
34877 : {
34878 0 : vv = ae_maxreal(vv, 1.0, _state);
34879 : }
34880 0 : if( neednorms )
34881 : {
34882 0 : rownorms->ptr.p_double[msparse+i] = vv;
34883 : }
34884 0 : if( ae_fp_greater(vv,(double)(0)) )
34885 : {
34886 0 : vv = 1/vv;
34887 0 : for(j=0; j<=n-1; j++)
34888 : {
34889 0 : densea->ptr.pp_double[i][j] = densea->ptr.pp_double[i][j]*vv;
34890 : }
34891 0 : ab->ptr.p_double[msparse+i] = ab->ptr.p_double[msparse+i]*vv;
34892 0 : if( ae_isfinite(ar->ptr.p_double[msparse+i], _state) )
34893 : {
34894 0 : ar->ptr.p_double[msparse+i] = ar->ptr.p_double[msparse+i]*vv;
34895 : }
34896 : }
34897 : }
34898 :
34899 : /*
34900 : * If amplification was limited, perform second round of normalization
34901 : */
34902 0 : if( (limitedamplification&&ae_fp_less(maxnrm2,1.0))&&ae_fp_greater(maxnrm2,(double)(0)) )
34903 : {
34904 0 : if( neednorms )
34905 : {
34906 0 : rmulv(mdense+msparse, maxnrm2, rownorms, _state);
34907 : }
34908 0 : vv = 1/maxnrm2;
34909 0 : for(i=0; i<=msparse-1; i++)
34910 : {
34911 0 : k0 = sparsea->ridx.ptr.p_int[i];
34912 0 : k1 = sparsea->ridx.ptr.p_int[i+1]-1;
34913 0 : for(k=k0; k<=k1; k++)
34914 : {
34915 0 : sparsea->vals.ptr.p_double[k] = sparsea->vals.ptr.p_double[k]*vv;
34916 : }
34917 0 : ab->ptr.p_double[i] = ab->ptr.p_double[i]*vv;
34918 0 : if( ae_isfinite(ar->ptr.p_double[i], _state) )
34919 : {
34920 0 : ar->ptr.p_double[i] = ar->ptr.p_double[i]*vv;
34921 : }
34922 : }
34923 0 : for(i=0; i<=mdense-1; i++)
34924 : {
34925 0 : rmulr(n, vv, densea, i, _state);
34926 0 : ab->ptr.p_double[msparse+i] = ab->ptr.p_double[msparse+i]*vv;
34927 0 : if( ae_isfinite(ar->ptr.p_double[msparse+i], _state) )
34928 : {
34929 0 : ar->ptr.p_double[msparse+i] = ar->ptr.p_double[msparse+i]*vv;
34930 : }
34931 : }
34932 : }
34933 0 : }
34934 :
34935 :
34936 : /*************************************************************************
34937 : This function normalizes dense QP problem in such a way that maximum over
34938 : its linear/quadratic coefficients max(max(A),max(B)) becomes equal to 1.0.
34939 :
34940 : NOTE: completely zero A and B are handled correctly.
34941 :
34942 : INPUT PARAMETERS:
34943 : DenseA - array[NMain,NMain], quadratic term
34944 : IsUpper - whether upper or lower triangle is present
34945 : NMain - number of nonslack vars, 1<=NMain<=NTotal
34946 : DenseB - array[NTotal], linear term
34947 : NTotal - total number of variables.
34948 :
34949 : OUTPUT PARAMETERS:
34950 : DenseA - replaced by normalized term
34951 : DenseB - replaced by normalized term
34952 :
34953 : RESULT:
34954 : max(max(A),max(B)) is returned
34955 :
34956 : -- ALGLIB --
34957 : Copyright 01.11.2019 by Bochkanov Sergey
34958 : *************************************************************************/
34959 0 : double normalizedenseqpinplace(/* Real */ ae_matrix* densea,
34960 : ae_bool isupper,
34961 : ae_int_t nmain,
34962 : /* Real */ ae_vector* denseb,
34963 : ae_int_t ntotal,
34964 : ae_state *_state)
34965 : {
34966 : ae_int_t i;
34967 : ae_int_t j;
34968 : ae_int_t j0;
34969 : ae_int_t j1;
34970 : double mx;
34971 : double v;
34972 : double result;
34973 :
34974 :
34975 0 : mx = (double)(0);
34976 0 : for(i=0; i<=nmain-1; i++)
34977 : {
34978 0 : if( isupper )
34979 : {
34980 0 : j0 = i;
34981 0 : j1 = nmain-1;
34982 : }
34983 : else
34984 : {
34985 0 : j0 = 0;
34986 0 : j1 = i;
34987 : }
34988 0 : for(j=j0; j<=j1; j++)
34989 : {
34990 0 : mx = ae_maxreal(mx, ae_fabs(densea->ptr.pp_double[i][j], _state), _state);
34991 : }
34992 : }
34993 0 : for(i=0; i<=ntotal-1; i++)
34994 : {
34995 0 : mx = ae_maxreal(mx, ae_fabs(denseb->ptr.p_double[i], _state), _state);
34996 : }
34997 0 : result = mx;
34998 0 : if( ae_fp_eq(mx,(double)(0)) )
34999 : {
35000 0 : return result;
35001 : }
35002 0 : v = 1/mx;
35003 0 : for(i=0; i<=nmain-1; i++)
35004 : {
35005 0 : if( isupper )
35006 : {
35007 0 : j0 = i;
35008 0 : j1 = nmain-1;
35009 : }
35010 : else
35011 : {
35012 0 : j0 = 0;
35013 0 : j1 = i;
35014 : }
35015 0 : for(j=j0; j<=j1; j++)
35016 : {
35017 0 : densea->ptr.pp_double[i][j] = densea->ptr.pp_double[i][j]*v;
35018 : }
35019 : }
35020 0 : for(i=0; i<=ntotal-1; i++)
35021 : {
35022 0 : denseb->ptr.p_double[i] = denseb->ptr.p_double[i]*v;
35023 : }
35024 0 : return result;
35025 : }
35026 :
35027 :
35028 : /*************************************************************************
35029 : This function normalizes sparse QP problem in such a way that maximum over
35030 : its linear/quadratic coefficients max(max(A),max(B)) becomes equal to 1.0.
35031 :
35032 : NOTE: completely zero A and B are handled correctly.
35033 :
35034 : INPUT PARAMETERS:
35035 : SparseA - Sparse NxN matrix, either upper or lower triangle,
35036 : diagonal MUST be present
35037 : IsUpper - which triangle is present (other one is ignored)
35038 : DenseB - array[N], linear term
35039 : N - number of variables.
35040 :
35041 : OUTPUT PARAMETERS:
35042 : DenseA - replaced by normalized term, array[N,N]
35043 : DenseB - replaced by normalized term, array[N]
35044 :
35045 : RESULT:
35046 : max(max(A),max(B)) is returned
35047 :
35048 : -- ALGLIB --
35049 : Copyright 01.11.2019 by Bochkanov Sergey
35050 : *************************************************************************/
35051 0 : double normalizesparseqpinplace(sparsematrix* sparsea,
35052 : ae_bool isupper,
35053 : /* Real */ ae_vector* denseb,
35054 : ae_int_t n,
35055 : ae_state *_state)
35056 : {
35057 : ae_int_t i;
35058 : ae_int_t k;
35059 : ae_int_t k0;
35060 : ae_int_t k1;
35061 : double mx;
35062 : double v;
35063 : double result;
35064 :
35065 :
35066 0 : ae_assert((sparsea->matrixtype==1&&sparsea->m==n)&&sparsea->n==n, "ScaleSparseQPInplace: SparseA in unexpected format", _state);
35067 0 : mx = (double)(0);
35068 0 : for(i=0; i<=n-1; i++)
35069 : {
35070 0 : ae_assert(sparsea->didx.ptr.p_int[i]+1==sparsea->uidx.ptr.p_int[i], "NormalizeSparseQPInplace: critical integrity check failed, sparse diagonal not found", _state);
35071 0 : if( isupper )
35072 : {
35073 0 : k0 = sparsea->didx.ptr.p_int[i];
35074 0 : k1 = sparsea->ridx.ptr.p_int[i+1]-1;
35075 : }
35076 : else
35077 : {
35078 0 : k0 = sparsea->ridx.ptr.p_int[i];
35079 0 : k1 = sparsea->didx.ptr.p_int[i];
35080 : }
35081 0 : for(k=k0; k<=k1; k++)
35082 : {
35083 0 : mx = ae_maxreal(mx, ae_fabs(sparsea->vals.ptr.p_double[k], _state), _state);
35084 : }
35085 0 : mx = ae_maxreal(mx, ae_fabs(denseb->ptr.p_double[i], _state), _state);
35086 : }
35087 0 : result = mx;
35088 0 : if( ae_fp_eq(mx,(double)(0)) )
35089 : {
35090 0 : return result;
35091 : }
35092 0 : v = 1/mx;
35093 0 : for(i=0; i<=n-1; i++)
35094 : {
35095 0 : k0 = sparsea->ridx.ptr.p_int[i];
35096 0 : k1 = sparsea->ridx.ptr.p_int[i+1]-1;
35097 0 : for(k=k0; k<=k1; k++)
35098 : {
35099 0 : sparsea->vals.ptr.p_double[k] = sparsea->vals.ptr.p_double[k]*v;
35100 : }
35101 0 : denseb->ptr.p_double[i] = denseb->ptr.p_double[i]*v;
35102 : }
35103 0 : return result;
35104 : }
35105 :
35106 :
35107 : /*************************************************************************
35108 : This function performs transformation of X from scaled/shifted coordinates
35109 : to unscaled/unshifted ones, paying special attention to box constraints:
35110 : * points which were exactly at the boundary before scaling will be mapped
35111 : to corresponding boundary after scaling
35112 : * in any case, unscaled box constraints will be satisfied
35113 :
35114 : -- ALGLIB --
35115 : Copyright 02.06.2015 by Bochkanov Sergey
35116 : *************************************************************************/
35117 0 : void unscaleunshiftpointbc(/* Real */ ae_vector* s,
35118 : /* Real */ ae_vector* xorigin,
35119 : /* Real */ ae_vector* rawbndl,
35120 : /* Real */ ae_vector* rawbndu,
35121 : /* Real */ ae_vector* sclsftbndl,
35122 : /* Real */ ae_vector* sclsftbndu,
35123 : /* Boolean */ ae_vector* hasbndl,
35124 : /* Boolean */ ae_vector* hasbndu,
35125 : /* Real */ ae_vector* x,
35126 : ae_int_t n,
35127 : ae_state *_state)
35128 : {
35129 : ae_int_t i;
35130 :
35131 :
35132 0 : for(i=0; i<=n-1; i++)
35133 : {
35134 0 : if( hasbndl->ptr.p_bool[i]&&ae_fp_less_eq(x->ptr.p_double[i],sclsftbndl->ptr.p_double[i]) )
35135 : {
35136 0 : x->ptr.p_double[i] = rawbndl->ptr.p_double[i];
35137 0 : continue;
35138 : }
35139 0 : if( hasbndu->ptr.p_bool[i]&&ae_fp_greater_eq(x->ptr.p_double[i],sclsftbndu->ptr.p_double[i]) )
35140 : {
35141 0 : x->ptr.p_double[i] = rawbndu->ptr.p_double[i];
35142 0 : continue;
35143 : }
35144 0 : x->ptr.p_double[i] = x->ptr.p_double[i]*s->ptr.p_double[i]+xorigin->ptr.p_double[i];
35145 0 : if( hasbndl->ptr.p_bool[i]&&ae_fp_less_eq(x->ptr.p_double[i],rawbndl->ptr.p_double[i]) )
35146 : {
35147 0 : x->ptr.p_double[i] = rawbndl->ptr.p_double[i];
35148 : }
35149 0 : if( hasbndu->ptr.p_bool[i]&&ae_fp_greater_eq(x->ptr.p_double[i],rawbndu->ptr.p_double[i]) )
35150 : {
35151 0 : x->ptr.p_double[i] = rawbndu->ptr.p_double[i];
35152 : }
35153 : }
35154 0 : }
35155 :
35156 :
35157 : #endif
35158 : #if defined(AE_COMPILE_VIPMSOLVER) || !defined(AE_PARTIAL_BUILD)
35159 :
35160 :
35161 : /*************************************************************************
35162 : Initializes QP-IPM state and prepares it to receive quadratic/linear terms
35163 : and constraints.
35164 :
35165 : The solver is configured to work internally with dense NxN factorization,
35166 : no matter what exactly is passed - dense or sparse matrices.
35167 :
35168 : INPUT PARAMETERS:
35169 : State - solver state to be configured; previously allocated
35170 : memory is reused as much as possible
35171 : S - scale vector, array[N]:
35172 : * I-th element contains scale of I-th variable,
35173 : * S[I]>0
35174 : XOrigin - origin term, array[N]. Can be zero. The solver solves
35175 : problem of the form
35176 :
35177 : >
35178 : > min(0.5*(x-x_origin)'*A*(x-x_origin)+b'*(x-x_origin))
35179 : >
35180 :
35181 : The terms A and b (as well as constraints) will be
35182 : specified later with separate calls.
35183 :
35184 : -- ALGLIB --
35185 : Copyright 01.11.2019 by Bochkanov Sergey
35186 : *************************************************************************/
35187 0 : void vipminitdense(vipmstate* state,
35188 : /* Real */ ae_vector* s,
35189 : /* Real */ ae_vector* xorigin,
35190 : ae_int_t n,
35191 : ae_state *_state)
35192 : {
35193 :
35194 :
35195 0 : ae_assert(n>=1, "VIPMInitDense: N<1", _state);
35196 0 : ae_assert(isfinitevector(s, n, _state), "VIPMInitDense: S contains infinite or NaN elements", _state);
35197 0 : ae_assert(isfinitevector(xorigin, n, _state), "VIPMInitDense: XOrigin contains infinite or NaN elements", _state);
35198 0 : vipmsolver_vipminit(state, s, xorigin, n, n, 0, _state);
35199 0 : }
35200 :
35201 :
35202 : /*************************************************************************
35203 : Initializes QP-IPM state and prepares it to receive quadratic/linear terms
35204 : and constraints.
35205 :
35206 : The solver is configured to work internally with dense NxN problem divided
35207 : into two distinct parts - "main" and slack one:
35208 : * dense quadratic term is a NMain*NMain matrix (NMain<=N), quadratic
35209 : coefficients are zero for variables outside of [0,NMain) range)
35210 : * linear term is general vector of length N
35211 : * linear constraints have special structure for variable with indexes in
35212 : [NMain,N) range: at most one element per column can be nonzero.
35213 :
35214 : This mode is intended for problems arising during SL1QP nonlinear programming.
35215 :
35216 : INPUT PARAMETERS:
35217 : State - solver state to be configured; previously allocated
35218 : memory is reused as much as possible
35219 : S - scale vector, array[N]:
35220 : * I-th element contains scale of I-th variable,
35221 : * S[I]>0
35222 : XOrigin - origin term, array[N]. Can be zero. The solver solves
35223 : problem of the form
35224 :
35225 : >
35226 : > min(0.5*(x-x_origin)'*A*(x-x_origin)+b'*(x-x_origin))
35227 : >
35228 :
35229 : The terms A and b (as well as constraints) will be
35230 : specified later with separate calls.
35231 : NMain - number of "main" variables, 1<=NMain<=N
35232 : N - total number of variables including slack ones
35233 :
35234 : -- ALGLIB --
35235 : Copyright 01.11.2019 by Bochkanov Sergey
35236 : *************************************************************************/
35237 0 : void vipminitdensewithslacks(vipmstate* state,
35238 : /* Real */ ae_vector* s,
35239 : /* Real */ ae_vector* xorigin,
35240 : ae_int_t nmain,
35241 : ae_int_t n,
35242 : ae_state *_state)
35243 : {
35244 :
35245 :
35246 0 : ae_assert(nmain>=1, "VIPMInitDense: NMain<1", _state);
35247 0 : ae_assert(n>=1, "VIPMInitDense: N<1", _state);
35248 0 : ae_assert(nmain<=n, "VIPMInitDense: NMain>N", _state);
35249 0 : ae_assert(isfinitevector(s, n, _state), "VIPMInitDense: S contains infinite or NaN elements", _state);
35250 0 : ae_assert(isfinitevector(xorigin, n, _state), "VIPMInitDense: XOrigin contains infinite or NaN elements", _state);
35251 0 : vipmsolver_vipminit(state, s, xorigin, n, nmain, 0, _state);
35252 0 : }
35253 :
35254 :
35255 : /*************************************************************************
35256 : Initializes QP-IPM state and prepares it to receive quadratic/linear terms
35257 : and constraints.
35258 :
35259 : The solver is configured to work internally with sparse (N+M)x(N+M)
35260 : factorization no matter what exactly is passed - dense or sparse matrices.
35261 : Dense quadratic term will be sparsified prior to storage.
35262 :
35263 : INPUT PARAMETERS:
35264 : State - solver state to be configured; previously allocated
35265 : memory is reused as much as possible
35266 : S - scale vector, array[N]:
35267 : * I-th element contains scale of I-th variable,
35268 : * S[I]>0
35269 : XOrigin - origin term, array[N]. Can be zero. The solver solves
35270 : problem of the form
35271 : >
35272 : > min(0.5*(x-x_origin)'*A*(x-x_origin)+b'*(x-x_origin))
35273 : >
35274 : The terms A and b (as well as constraints) will be
35275 : specified later with separate calls.
35276 : N - total number of variables, N>=1
35277 :
35278 : This optimization mode assumes that no slack variables is present.
35279 :
35280 : -- ALGLIB --
35281 : Copyright 01.11.2019 by Bochkanov Sergey
35282 : *************************************************************************/
35283 0 : void vipminitsparse(vipmstate* state,
35284 : /* Real */ ae_vector* s,
35285 : /* Real */ ae_vector* xorigin,
35286 : ae_int_t n,
35287 : ae_state *_state)
35288 : {
35289 :
35290 :
35291 0 : ae_assert(n>=1, "VIPMInitSparse: N<1", _state);
35292 0 : ae_assert(isfinitevector(s, n, _state), "VIPMInitSparse: S contains infinite or NaN elements", _state);
35293 0 : ae_assert(isfinitevector(xorigin, n, _state), "VIPMInitSparse: XOrigin contains infinite or NaN elements", _state);
35294 0 : vipmsolver_vipminit(state, s, xorigin, n, n, 1, _state);
35295 0 : }
35296 :
35297 :
35298 : /*************************************************************************
35299 : Sets linear/quadratic terms for QP-IPM solver
35300 :
35301 : If you initialized solver with VIMPInitDenseWithSlacks(), NMain below is a
35302 : number of non-slack variables. In other cases, NMain=N.
35303 :
35304 : INPUT PARAMETERS:
35305 : State - instance initialized with one of the initialization
35306 : functions
35307 : DenseH - if HKind=0: array[NMain,NMain], dense quadratic term
35308 : (either upper or lower triangle)
35309 : SparseH - if HKind=1: array[NMain,NMain], sparse quadratic term
35310 : (either upper or lower triangle)
35311 : HKind - 0 or 1, quadratic term format
35312 : IsUpper - whether dense/sparse H contains lower or upper
35313 : triangle of the quadratic term
35314 : C - array[N], linear term
35315 :
35316 : -- ALGLIB --
35317 : Copyright 01.11.2019 by Bochkanov Sergey
35318 : *************************************************************************/
35319 0 : void vipmsetquadraticlinear(vipmstate* state,
35320 : /* Real */ ae_matrix* denseh,
35321 : sparsematrix* sparseh,
35322 : ae_int_t hkind,
35323 : ae_bool isupper,
35324 : /* Real */ ae_vector* c,
35325 : ae_state *_state)
35326 : {
35327 : ae_int_t nmain;
35328 : ae_int_t n;
35329 : ae_int_t i;
35330 : ae_int_t j;
35331 : ae_int_t k;
35332 : ae_int_t j0;
35333 : ae_int_t j1;
35334 : double v;
35335 : double vv;
35336 : ae_int_t nnz;
35337 : ae_int_t offs;
35338 :
35339 :
35340 0 : nmain = state->nmain;
35341 0 : n = state->n;
35342 0 : ae_assert(hkind==0||hkind==1, "VIPMSetQuadraticLinear: incorrect HKind", _state);
35343 0 : ae_assert(isfinitevector(c, n, _state), "VIPMSetQuadraticLinear: C contains infinite or NaN elements", _state);
35344 0 : ae_assert(state->factorizationtype==0||state->factorizationtype==1, "VIPMSetQuadraticLinear: unexpected factorization type", _state);
35345 :
35346 : /*
35347 : * Set problem info, reset factorization flag
35348 : */
35349 0 : state->islinear = ae_false;
35350 0 : state->factorizationpresent = ae_false;
35351 0 : state->factorizationpoweredup = ae_false;
35352 :
35353 : /*
35354 : * Linear term
35355 : */
35356 0 : rvectorsetlengthatleast(&state->c, n, _state);
35357 0 : rvectorcopy(n, c, 0, &state->c, 0, _state);
35358 :
35359 : /*
35360 : * Quadratic term and normalization
35361 : *
35362 : * NOTE: we perform integrity check for inifinities/NANs by
35363 : * computing sum of all matrix elements and checking its
35364 : * value for being finite. It is a bit faster than checking
35365 : * each element individually.
35366 : */
35367 0 : state->hkind = -1;
35368 0 : state->targetscale = 1.0;
35369 0 : if( state->factorizationtype==0 )
35370 : {
35371 :
35372 : /*
35373 : * Quadratic term is stored in dense format: either copy dense
35374 : * term of densify sparse one
35375 : */
35376 0 : state->hkind = 0;
35377 0 : rmatrixsetlengthatleast(&state->denseh, nmain, nmain, _state);
35378 0 : if( hkind==0 )
35379 : {
35380 :
35381 : /*
35382 : * Copy dense quadratic term
35383 : */
35384 0 : if( isupper )
35385 : {
35386 0 : rmatrixtranspose(nmain, nmain, denseh, 0, 0, &state->denseh, 0, 0, _state);
35387 : }
35388 : else
35389 : {
35390 0 : rmatrixcopy(nmain, nmain, denseh, 0, 0, &state->denseh, 0, 0, _state);
35391 : }
35392 : }
35393 0 : if( hkind==1 )
35394 : {
35395 :
35396 : /*
35397 : * Extract sparse quadratic term
35398 : */
35399 0 : ae_assert(sparseh->matrixtype==1, "VIPMSetQuadraticLinear: unexpected sparse matrix format", _state);
35400 0 : ae_assert(sparseh->m==nmain, "VIPMSetQuadraticLinear: unexpected sparse matrix size", _state);
35401 0 : ae_assert(sparseh->n==nmain, "VIPMSetQuadraticLinear: unexpected sparse matrix size", _state);
35402 0 : for(i=0; i<=nmain-1; i++)
35403 : {
35404 0 : for(j=0; j<=i; j++)
35405 : {
35406 0 : state->denseh.ptr.pp_double[i][j] = (double)(0);
35407 : }
35408 : }
35409 0 : for(i=0; i<=nmain-1; i++)
35410 : {
35411 :
35412 : /*
35413 : * diagonal element
35414 : */
35415 0 : if( sparseh->didx.ptr.p_int[i]!=sparseh->uidx.ptr.p_int[i] )
35416 : {
35417 0 : state->denseh.ptr.pp_double[i][i] = sparseh->vals.ptr.p_double[sparseh->didx.ptr.p_int[i]];
35418 : }
35419 :
35420 : /*
35421 : * Off-diagonal elements
35422 : */
35423 0 : if( isupper )
35424 : {
35425 :
35426 : /*
35427 : * superdiagonal elements are moved to subdiagonal part
35428 : */
35429 0 : j0 = sparseh->uidx.ptr.p_int[i];
35430 0 : j1 = sparseh->ridx.ptr.p_int[i+1]-1;
35431 0 : for(j=j0; j<=j1; j++)
35432 : {
35433 0 : state->denseh.ptr.pp_double[sparseh->idx.ptr.p_int[j]][i] = sparseh->vals.ptr.p_double[j];
35434 : }
35435 : }
35436 : else
35437 : {
35438 :
35439 : /*
35440 : * subdiagonal elements are moved to subdiagonal part
35441 : */
35442 0 : j0 = sparseh->ridx.ptr.p_int[i];
35443 0 : j1 = sparseh->didx.ptr.p_int[i]-1;
35444 0 : for(j=j0; j<=j1; j++)
35445 : {
35446 0 : state->denseh.ptr.pp_double[i][sparseh->idx.ptr.p_int[j]] = sparseh->vals.ptr.p_double[j];
35447 : }
35448 : }
35449 : }
35450 : }
35451 0 : vv = (double)(0);
35452 0 : for(i=0; i<=nmain-1; i++)
35453 : {
35454 0 : for(j=0; j<=i; j++)
35455 : {
35456 0 : vv = vv+state->denseh.ptr.pp_double[i][j];
35457 : }
35458 : }
35459 0 : ae_assert(ae_isfinite(vv, _state), "VIPMSetQuadraticLinear: DenseH contains infinite or NaN values!", _state);
35460 0 : scaledenseqpinplace(&state->denseh, ae_false, nmain, &state->c, n, &state->scl, _state);
35461 0 : state->targetscale = normalizedenseqpinplace(&state->denseh, ae_false, nmain, &state->c, n, _state);
35462 : }
35463 0 : if( state->factorizationtype==1 )
35464 : {
35465 0 : ae_assert(nmain==n, "VIPMSetQuadraticLinear: critical integrity check failed, NMain!=N", _state);
35466 :
35467 : /*
35468 : * Quadratic term is stored in sparse format: either sparsify dense
35469 : * term of copy sparse one
35470 : */
35471 0 : state->hkind = 1;
35472 0 : state->sparseh.matrixtype = 1;
35473 0 : state->sparseh.m = n;
35474 0 : state->sparseh.n = n;
35475 0 : if( hkind==0 )
35476 : {
35477 :
35478 : /*
35479 : * Sparsify dense term
35480 : */
35481 0 : nnz = 0;
35482 0 : for(i=0; i<=n-1; i++)
35483 : {
35484 0 : nnz = nnz+1;
35485 0 : if( isupper )
35486 : {
35487 0 : j0 = i+1;
35488 0 : j1 = n-1;
35489 : }
35490 : else
35491 : {
35492 0 : j0 = 0;
35493 0 : j1 = i-1;
35494 : }
35495 0 : for(j=j0; j<=j1; j++)
35496 : {
35497 0 : if( denseh->ptr.pp_double[i][j]!=0 )
35498 : {
35499 0 : nnz = nnz+1;
35500 : }
35501 : }
35502 : }
35503 0 : ivectorsetlengthatleast(&state->sparseh.ridx, n+1, _state);
35504 0 : ivectorsetlengthatleast(&state->sparseh.idx, nnz, _state);
35505 0 : rvectorsetlengthatleast(&state->sparseh.vals, nnz, _state);
35506 0 : state->sparseh.ridx.ptr.p_int[0] = 0;
35507 0 : offs = 0;
35508 0 : vv = (double)(0);
35509 0 : for(i=0; i<=n-1; i++)
35510 : {
35511 :
35512 : /*
35513 : * Off-diagonal elements are copied only when nonzero
35514 : */
35515 0 : if( !isupper )
35516 : {
35517 0 : for(j=0; j<=i-1; j++)
35518 : {
35519 0 : if( denseh->ptr.pp_double[i][j]!=0 )
35520 : {
35521 0 : v = denseh->ptr.pp_double[i][j];
35522 0 : state->sparseh.idx.ptr.p_int[offs] = j;
35523 0 : state->sparseh.vals.ptr.p_double[offs] = v;
35524 0 : vv = vv+v;
35525 0 : offs = offs+1;
35526 : }
35527 : }
35528 : }
35529 :
35530 : /*
35531 : * Diagonal element is always copied
35532 : */
35533 0 : v = denseh->ptr.pp_double[i][i];
35534 0 : state->sparseh.idx.ptr.p_int[offs] = i;
35535 0 : state->sparseh.vals.ptr.p_double[offs] = v;
35536 0 : vv = vv+v;
35537 0 : offs = offs+1;
35538 :
35539 : /*
35540 : * Off-diagonal elements are copied only when nonzero
35541 : */
35542 0 : if( isupper )
35543 : {
35544 0 : for(j=i+1; j<=n-1; j++)
35545 : {
35546 0 : if( denseh->ptr.pp_double[i][j]!=0 )
35547 : {
35548 0 : v = denseh->ptr.pp_double[i][j];
35549 0 : state->sparseh.idx.ptr.p_int[offs] = j;
35550 0 : state->sparseh.vals.ptr.p_double[offs] = v;
35551 0 : vv = vv+v;
35552 0 : offs = offs+1;
35553 : }
35554 : }
35555 : }
35556 :
35557 : /*
35558 : * Finalize row
35559 : */
35560 0 : state->sparseh.ridx.ptr.p_int[i+1] = offs;
35561 : }
35562 0 : ae_assert(ae_isfinite(vv, _state), "VIPMSetQuadraticLinear: DenseH contains infinite or NaN values!", _state);
35563 0 : ae_assert(offs==nnz, "VIPMSetQuadraticLinear: integrity check failed", _state);
35564 0 : sparsecreatecrsinplace(&state->sparseh, _state);
35565 : }
35566 0 : if( hkind==1 )
35567 : {
35568 :
35569 : /*
35570 : * Copy sparse quadratic term, but make sure that we have diagonal elements
35571 : * present (we add diagonal if it is not present)
35572 : */
35573 0 : ae_assert(sparseh->matrixtype==1, "VIPMSetQuadraticLinear: unexpected sparse matrix format", _state);
35574 0 : ae_assert(sparseh->m==n, "VIPMSetQuadraticLinear: unexpected sparse matrix size", _state);
35575 0 : ae_assert(sparseh->n==n, "VIPMSetQuadraticLinear: unexpected sparse matrix size", _state);
35576 0 : ivectorsetlengthatleast(&state->sparseh.ridx, n+1, _state);
35577 0 : ivectorsetlengthatleast(&state->sparseh.idx, sparseh->ridx.ptr.p_int[n]+n, _state);
35578 0 : rvectorsetlengthatleast(&state->sparseh.vals, sparseh->ridx.ptr.p_int[n]+n, _state);
35579 0 : state->sparseh.ridx.ptr.p_int[0] = 0;
35580 0 : offs = 0;
35581 0 : vv = (double)(0);
35582 0 : for(i=0; i<=n-1; i++)
35583 : {
35584 :
35585 : /*
35586 : * Copy subdiagonal elements (if needed)
35587 : */
35588 0 : if( !isupper )
35589 : {
35590 0 : j0 = sparseh->ridx.ptr.p_int[i];
35591 0 : j1 = sparseh->didx.ptr.p_int[i]-1;
35592 0 : for(k=j0; k<=j1; k++)
35593 : {
35594 0 : v = sparseh->vals.ptr.p_double[k];
35595 0 : state->sparseh.idx.ptr.p_int[offs] = sparseh->idx.ptr.p_int[k];
35596 0 : state->sparseh.vals.ptr.p_double[offs] = v;
35597 0 : vv = vv+v;
35598 0 : offs = offs+1;
35599 : }
35600 : }
35601 :
35602 : /*
35603 : * Diagonal element is always copied
35604 : */
35605 0 : v = (double)(0);
35606 0 : if( sparseh->uidx.ptr.p_int[i]!=sparseh->didx.ptr.p_int[i] )
35607 : {
35608 0 : v = sparseh->vals.ptr.p_double[sparseh->didx.ptr.p_int[i]];
35609 : }
35610 0 : state->sparseh.idx.ptr.p_int[offs] = i;
35611 0 : state->sparseh.vals.ptr.p_double[offs] = v;
35612 0 : vv = vv+v;
35613 0 : offs = offs+1;
35614 :
35615 : /*
35616 : * Copy superdiagonal elements (if needed)
35617 : */
35618 0 : if( isupper )
35619 : {
35620 0 : j0 = sparseh->uidx.ptr.p_int[i];
35621 0 : j1 = sparseh->ridx.ptr.p_int[i+1]-1;
35622 0 : for(k=j0; k<=j1; k++)
35623 : {
35624 0 : v = sparseh->vals.ptr.p_double[k];
35625 0 : state->sparseh.idx.ptr.p_int[offs] = sparseh->idx.ptr.p_int[k];
35626 0 : state->sparseh.vals.ptr.p_double[offs] = v;
35627 0 : vv = vv+v;
35628 0 : offs = offs+1;
35629 : }
35630 : }
35631 :
35632 : /*
35633 : * Finalize row
35634 : */
35635 0 : state->sparseh.ridx.ptr.p_int[i+1] = offs;
35636 : }
35637 0 : ae_assert(ae_isfinite(vv, _state), "VIPMSetQuadraticLinear: SparseH contains infinite or NaN values!", _state);
35638 0 : ae_assert(offs<=state->sparseh.vals.cnt&&offs<=state->sparseh.idx.cnt, "VIPMSetQuadraticLinear: integrity check failed", _state);
35639 0 : sparsecreatecrsinplace(&state->sparseh, _state);
35640 0 : if( isupper )
35641 : {
35642 0 : sparsecopytransposecrsbuf(&state->sparseh, &state->tmpsparse0, _state);
35643 0 : sparsecopybuf(&state->tmpsparse0, &state->sparseh, _state);
35644 : }
35645 : }
35646 0 : scalesparseqpinplace(&state->scl, n, &state->sparseh, &state->c, _state);
35647 0 : state->targetscale = normalizesparseqpinplace(&state->sparseh, ae_false, &state->c, n, _state);
35648 : }
35649 0 : ae_assert(state->hkind>=0, "VIPMSetQuadraticLinear: integrity check failed", _state);
35650 0 : }
35651 :
35652 :
35653 : /*************************************************************************
35654 : Sets constraints for QP-IPM solver
35655 :
35656 : INPUT PARAMETERS:
35657 : State - instance initialized with one of the initialization
35658 : functions
35659 : BndL, BndU - lower and upper bound. BndL[] can be -INF,
35660 : BndU[] can be +INF.
35661 : SparseA - sparse constraint matrix, CRS format
35662 : MSparse - number of sparse constraints
35663 : DenseA - array[MDense,N], dense part of the constraints
35664 : MDense - number of dense constraints
35665 : CL, CU - lower and upper bounds for constraints, first
35666 : MSparse are bounds for sparse part, following
35667 : MDense ones are bounds for dense part,
35668 : MSparse+MDense in total.
35669 : -INF <= CL[I] <= CU[I] <= +INF.
35670 :
35671 : This function throws exception if constraints have inconsistent bounds, i.e.
35672 : either BndL[I]>BndU[I] or CL[I]>CU[I]. In all other cases it succeeds.
35673 :
35674 : -- ALGLIB --
35675 : Copyright 01.11.2019 by Bochkanov Sergey
35676 : *************************************************************************/
35677 0 : void vipmsetconstraints(vipmstate* state,
35678 : /* Real */ ae_vector* bndl,
35679 : /* Real */ ae_vector* bndu,
35680 : sparsematrix* sparsea,
35681 : ae_int_t msparse,
35682 : /* Real */ ae_matrix* densea,
35683 : ae_int_t mdense,
35684 : /* Real */ ae_vector* cl,
35685 : /* Real */ ae_vector* cu,
35686 : ae_state *_state)
35687 : {
35688 : ae_int_t m;
35689 : ae_int_t n;
35690 : ae_int_t nmain;
35691 : ae_int_t nslack;
35692 : ae_int_t i;
35693 : ae_int_t j;
35694 : ae_int_t j0;
35695 : ae_int_t j1;
35696 : ae_int_t k;
35697 : ae_int_t offsmain;
35698 : ae_int_t offscombined;
35699 : double vs;
35700 : double v;
35701 :
35702 :
35703 0 : n = state->n;
35704 0 : nmain = state->nmain;
35705 0 : nslack = n-nmain;
35706 0 : ae_assert(mdense>=0, "VIPMSetConstraints: MDense<0", _state);
35707 0 : ae_assert(msparse>=0, "VIPMSetConstraints: MSparse<0", _state);
35708 0 : ae_assert(apservisfinitematrix(densea, mdense, n, _state), "VIPMSetConstraints: DenseA contains infinite or NaN values!", _state);
35709 0 : ae_assert(msparse==0||sparsea->matrixtype==1, "VIPMSetConstraints: non-CRS constraint matrix!", _state);
35710 0 : ae_assert(msparse==0||(sparsea->m==msparse&&sparsea->n==n), "VIPMSetConstraints: constraint matrix has incorrect size", _state);
35711 0 : ae_assert(cl->cnt>=mdense+msparse, "VIPMSetConstraints: CL is too short!", _state);
35712 0 : ae_assert(cu->cnt>=mdense+msparse, "VIPMSetConstraints: CU is too short!", _state);
35713 :
35714 : /*
35715 : * Reset factorization flag
35716 : */
35717 0 : state->factorizationpresent = ae_false;
35718 0 : state->factorizationpoweredup = ae_false;
35719 :
35720 : /*
35721 : * Box constraints
35722 : */
35723 0 : rvectorsetlengthatleast(&state->bndl, n, _state);
35724 0 : rvectorsetlengthatleast(&state->bndu, n, _state);
35725 0 : rvectorsetlengthatleast(&state->rawbndl, n, _state);
35726 0 : rvectorsetlengthatleast(&state->rawbndu, n, _state);
35727 0 : bvectorsetlengthatleast(&state->hasbndl, n, _state);
35728 0 : bvectorsetlengthatleast(&state->hasbndu, n, _state);
35729 0 : for(i=0; i<=n-1; i++)
35730 : {
35731 0 : state->hasbndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state);
35732 0 : state->hasbndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state);
35733 0 : ae_assert(!((state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i])&&ae_fp_greater(bndl->ptr.p_double[i],bndu->ptr.p_double[i])), "VIPMInitDenseQuadratic: inconsistent range for box constraints", _state);
35734 0 : state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i];
35735 0 : state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i];
35736 0 : state->rawbndl.ptr.p_double[i] = bndl->ptr.p_double[i];
35737 0 : state->rawbndu.ptr.p_double[i] = bndu->ptr.p_double[i];
35738 : }
35739 0 : scaleshiftbcinplace(&state->scl, &state->xorigin, &state->bndl, &state->bndu, n, _state);
35740 :
35741 : /*
35742 : * Linear constraints (full matrices)
35743 : */
35744 0 : m = mdense+msparse;
35745 0 : rvectorsetlengthatleast(&state->b, m, _state);
35746 0 : rvectorsetlengthatleast(&state->r, m, _state);
35747 0 : rvectorsetlengthatleast(&state->ascales, m, _state);
35748 0 : bvectorsetlengthatleast(&state->aflips, m, _state);
35749 0 : bvectorsetlengthatleast(&state->hasr, m, _state);
35750 0 : rmatrixsetlengthatleast(&state->denseafull, mdense, n, _state);
35751 0 : if( msparse>0 )
35752 : {
35753 0 : sparsecopytocrsbuf(sparsea, &state->sparseafull, _state);
35754 : }
35755 0 : if( mdense>0 )
35756 : {
35757 0 : rmatrixcopy(mdense, n, densea, 0, 0, &state->denseafull, 0, 0, _state);
35758 : }
35759 0 : for(i=0; i<=m-1; i++)
35760 : {
35761 0 : ae_assert(ae_isfinite(cl->ptr.p_double[i], _state)||ae_isneginf(cl->ptr.p_double[i], _state), "VIPMInitDenseQuadratic: CL is not finite number or -INF", _state);
35762 0 : ae_assert(ae_isfinite(cu->ptr.p_double[i], _state)||ae_isposinf(cu->ptr.p_double[i], _state), "VIPMInitDenseQuadratic: CU is not finite number or +INF", _state);
35763 :
35764 : /*
35765 : * Store range
35766 : */
35767 0 : if( ae_isfinite(cl->ptr.p_double[i], _state)||ae_isfinite(cu->ptr.p_double[i], _state) )
35768 : {
35769 :
35770 : /*
35771 : * Non-degenerate constraint, at least one of bounds is present
35772 : */
35773 0 : if( ae_isfinite(cl->ptr.p_double[i], _state) )
35774 : {
35775 0 : ae_assert(!ae_isfinite(cu->ptr.p_double[i], _state)||ae_fp_greater_eq(cu->ptr.p_double[i],cl->ptr.p_double[i]), "VIPMInitDenseQuadratic: inconsistent range (right-hand side) for linear constraint", _state);
35776 0 : if( ae_isfinite(cu->ptr.p_double[i], _state) )
35777 : {
35778 :
35779 : /*
35780 : * We have both CL and CU, i.e. CL <= A*x <= CU.
35781 : *
35782 : * It can be either equality constraint (no slacks) or range constraint
35783 : * (two pairs of slacks variables).
35784 : *
35785 : * Try to arrange things in such a way that |CU|>=|CL| (it can be done
35786 : * by multiplication by -1 and boundaries swap).
35787 : *
35788 : * Having |CU|>=|CL| will allow us to drop huge irrelevant bound CU,
35789 : * if we find it irrelevant during computations. Due to limitations
35790 : * of our slack variable substitution, it can be done only for CU.
35791 : */
35792 0 : if( ae_fp_greater_eq(ae_fabs(cu->ptr.p_double[i], _state),ae_fabs(cl->ptr.p_double[i], _state)) )
35793 : {
35794 0 : state->b.ptr.p_double[i] = cl->ptr.p_double[i];
35795 0 : state->r.ptr.p_double[i] = cu->ptr.p_double[i]-cl->ptr.p_double[i];
35796 0 : state->hasr.ptr.p_bool[i] = ae_true;
35797 0 : state->aflips.ptr.p_bool[i] = ae_false;
35798 0 : vs = (double)(1);
35799 : }
35800 : else
35801 : {
35802 0 : state->b.ptr.p_double[i] = -cu->ptr.p_double[i];
35803 0 : state->r.ptr.p_double[i] = cu->ptr.p_double[i]-cl->ptr.p_double[i];
35804 0 : state->hasr.ptr.p_bool[i] = ae_true;
35805 0 : state->aflips.ptr.p_bool[i] = ae_true;
35806 0 : vs = (double)(-1);
35807 : }
35808 : }
35809 : else
35810 : {
35811 :
35812 : /*
35813 : * Only lower bound: CL <= A*x.
35814 : *
35815 : * One pair of slack variables added.
35816 : */
35817 0 : state->b.ptr.p_double[i] = cl->ptr.p_double[i];
35818 0 : state->r.ptr.p_double[i] = _state->v_posinf;
35819 0 : state->hasr.ptr.p_bool[i] = ae_false;
35820 0 : state->aflips.ptr.p_bool[i] = ae_false;
35821 0 : vs = (double)(1);
35822 : }
35823 : }
35824 : else
35825 : {
35826 :
35827 : /*
35828 : * Only upper bound: A*x <= CU
35829 : *
35830 : * One pair of slack variables added.
35831 : */
35832 0 : state->b.ptr.p_double[i] = -cu->ptr.p_double[i];
35833 0 : state->r.ptr.p_double[i] = _state->v_posinf;
35834 0 : state->hasr.ptr.p_bool[i] = ae_false;
35835 0 : state->aflips.ptr.p_bool[i] = ae_true;
35836 0 : vs = (double)(-1);
35837 : }
35838 : }
35839 : else
35840 : {
35841 :
35842 : /*
35843 : * Degenerate constraint -inf <= Ax <= +inf.
35844 : * Generate dummy formulation.
35845 : */
35846 0 : state->b.ptr.p_double[i] = (double)(-1);
35847 0 : state->r.ptr.p_double[i] = (double)(2);
35848 0 : state->hasr.ptr.p_bool[i] = ae_true;
35849 0 : state->aflips.ptr.p_bool[i] = ae_false;
35850 0 : vs = (double)(0);
35851 : }
35852 :
35853 : /*
35854 : * Store matrix row and its scaling coefficient
35855 : */
35856 0 : if( i<msparse )
35857 : {
35858 0 : j0 = state->sparseafull.ridx.ptr.p_int[i];
35859 0 : j1 = state->sparseafull.ridx.ptr.p_int[i+1]-1;
35860 0 : for(j=j0; j<=j1; j++)
35861 : {
35862 0 : state->sparseafull.vals.ptr.p_double[j] = state->sparseafull.vals.ptr.p_double[j]*vs;
35863 : }
35864 : }
35865 : else
35866 : {
35867 0 : for(j=0; j<=n-1; j++)
35868 : {
35869 0 : state->denseafull.ptr.pp_double[i-msparse][j] = state->denseafull.ptr.pp_double[i-msparse][j]*vs;
35870 : }
35871 : }
35872 0 : state->ascales.ptr.p_double[i] = vs;
35873 : }
35874 0 : scaleshiftmixedbrlcinplace(&state->scl, &state->xorigin, n, &state->sparseafull, msparse, &state->denseafull, mdense, &state->b, &state->r, _state);
35875 0 : normalizemixedbrlcinplace(&state->sparseafull, msparse, &state->denseafull, mdense, &state->b, &state->r, n, ae_true, &state->tmp0, ae_true, _state);
35876 0 : for(i=0; i<=m-1; i++)
35877 : {
35878 0 : state->ascales.ptr.p_double[i] = state->ascales.ptr.p_double[i]*state->tmp0.ptr.p_double[i];
35879 : }
35880 0 : state->mdense = mdense;
35881 0 : state->msparse = msparse;
35882 :
35883 : /*
35884 : * Separate main and slack parts of the constraint matrices
35885 : */
35886 0 : ivectorsetlengthatleast(&state->tmpi, nslack, _state);
35887 0 : for(i=0; i<=nslack-1; i++)
35888 : {
35889 0 : state->tmpi.ptr.p_int[i] = 0;
35890 : }
35891 0 : state->combinedaslack.m = mdense+msparse;
35892 0 : state->combinedaslack.n = nslack;
35893 0 : ivectorsetlengthatleast(&state->combinedaslack.ridx, mdense+msparse+1, _state);
35894 0 : ivectorsetlengthatleast(&state->combinedaslack.idx, nslack, _state);
35895 0 : rvectorsetlengthatleast(&state->combinedaslack.vals, nslack, _state);
35896 0 : state->combinedaslack.ridx.ptr.p_int[0] = 0;
35897 0 : state->sparseamain.m = msparse;
35898 0 : state->sparseamain.n = nmain;
35899 0 : if( msparse>0 )
35900 : {
35901 0 : ivectorsetlengthatleast(&state->sparseamain.ridx, msparse+1, _state);
35902 0 : ivectorsetlengthatleast(&state->sparseamain.idx, sparsea->ridx.ptr.p_int[msparse], _state);
35903 0 : rvectorsetlengthatleast(&state->sparseamain.vals, sparsea->ridx.ptr.p_int[msparse], _state);
35904 0 : state->sparseamain.ridx.ptr.p_int[0] = 0;
35905 0 : for(i=0; i<=msparse-1; i++)
35906 : {
35907 0 : offsmain = state->sparseamain.ridx.ptr.p_int[i];
35908 0 : offscombined = state->combinedaslack.ridx.ptr.p_int[i];
35909 0 : j0 = state->sparseafull.ridx.ptr.p_int[i];
35910 0 : j1 = state->sparseafull.ridx.ptr.p_int[i+1]-1;
35911 0 : for(j=j0; j<=j1; j++)
35912 : {
35913 0 : v = state->sparseafull.vals.ptr.p_double[j];
35914 0 : k = state->sparseafull.idx.ptr.p_int[j];
35915 0 : if( k<nmain )
35916 : {
35917 0 : state->sparseamain.idx.ptr.p_int[offsmain] = k;
35918 0 : state->sparseamain.vals.ptr.p_double[offsmain] = v;
35919 0 : offsmain = offsmain+1;
35920 : }
35921 : else
35922 : {
35923 0 : ae_assert(state->tmpi.ptr.p_int[k-nmain]==0, "VIPMSetConstraints: slack column contains more than one nonzero element", _state);
35924 0 : state->combinedaslack.idx.ptr.p_int[offscombined] = k-nmain;
35925 0 : state->combinedaslack.vals.ptr.p_double[offscombined] = v;
35926 0 : state->tmpi.ptr.p_int[k-nmain] = state->tmpi.ptr.p_int[k-nmain]+1;
35927 0 : offscombined = offscombined+1;
35928 : }
35929 : }
35930 0 : state->sparseamain.ridx.ptr.p_int[i+1] = offsmain;
35931 0 : state->combinedaslack.ridx.ptr.p_int[i+1] = offscombined;
35932 : }
35933 : }
35934 0 : sparsecreatecrsinplace(&state->sparseamain, _state);
35935 0 : if( mdense>0 )
35936 : {
35937 0 : rmatrixsetlengthatleast(&state->denseamain, mdense, nmain, _state);
35938 0 : rmatrixcopy(mdense, nmain, &state->denseafull, 0, 0, &state->denseamain, 0, 0, _state);
35939 0 : for(i=0; i<=mdense-1; i++)
35940 : {
35941 0 : offscombined = state->combinedaslack.ridx.ptr.p_int[msparse+i];
35942 0 : for(k=nmain; k<=n-1; k++)
35943 : {
35944 0 : if( state->denseafull.ptr.pp_double[i][k]!=0 )
35945 : {
35946 0 : ae_assert(state->tmpi.ptr.p_int[k-nmain]==0, "VIPMSetConstraints: slack column contains more than one nonzero element", _state);
35947 0 : state->combinedaslack.idx.ptr.p_int[offscombined] = k-nmain;
35948 0 : state->combinedaslack.vals.ptr.p_double[offscombined] = state->denseafull.ptr.pp_double[i][k];
35949 0 : state->tmpi.ptr.p_int[k-nmain] = state->tmpi.ptr.p_int[k-nmain]+1;
35950 0 : offscombined = offscombined+1;
35951 : }
35952 : }
35953 0 : state->combinedaslack.ridx.ptr.p_int[msparse+i+1] = offscombined;
35954 : }
35955 : }
35956 0 : sparsecreatecrsinplace(&state->combinedaslack, _state);
35957 0 : }
35958 :
35959 :
35960 : /*************************************************************************
35961 : Sets stopping criteria for QP-IPM solver.
35962 :
35963 : You can set all epsilon-values to one small value, about 1.0E-6.
35964 :
35965 : INPUT PARAMETERS:
35966 : State - instance initialized with one of the initialization
35967 : functions
35968 : EpsP - maximum primal error allowed in the solution,
35969 : EpsP>=0. Zero will be automatically replaced
35970 : by recommended default value, which is equal
35971 : to 10*Sqrt(Epsilon) in the current version
35972 : EpsD - maximum dual error allowed in the solution,
35973 : EpsP>=0. Zero will be automatically replaced
35974 : by recommended default value, which is equal
35975 : to 10*Sqrt(Epsilon) in the current version
35976 : EpsGap - maximum duality gap allowed in the solution,
35977 : EpsP>=0. Zero will be automatically replaced
35978 : by recommended default value, which is equal
35979 : to 10*Sqrt(Epsilon) in the current version
35980 :
35981 : -- ALGLIB --
35982 : Copyright 01.11.2019 by Bochkanov Sergey
35983 : *************************************************************************/
35984 0 : void vipmsetcond(vipmstate* state,
35985 : double epsp,
35986 : double epsd,
35987 : double epsgap,
35988 : ae_state *_state)
35989 : {
35990 : double sml;
35991 :
35992 :
35993 0 : ae_assert(ae_isfinite(epsp, _state)&&ae_fp_greater_eq(epsp,(double)(0)), "VIPMSetCond: EpsP is infinite or negative", _state);
35994 0 : ae_assert(ae_isfinite(epsd, _state)&&ae_fp_greater_eq(epsd,(double)(0)), "VIPMSetCond: EpsD is infinite or negative", _state);
35995 0 : ae_assert(ae_isfinite(epsgap, _state)&&ae_fp_greater_eq(epsgap,(double)(0)), "VIPMSetCond: EpsP is infinite or negative", _state);
35996 0 : sml = ae_sqrt(ae_machineepsilon, _state);
35997 0 : state->epsp = coalesce(epsp, sml, _state);
35998 0 : state->epsd = coalesce(epsd, sml, _state);
35999 0 : state->epsgap = coalesce(epsgap, sml, _state);
36000 0 : }
36001 :
36002 :
36003 : /*************************************************************************
36004 : Solve QP problem.
36005 :
36006 : INPUT PARAMETERS:
36007 : State - solver instance
36008 : DropBigBounds - If True, algorithm may drop box and linear constraints
36009 : with huge bound values that destabilize algorithm.
36010 :
36011 : OUTPUT PARAMETERS:
36012 : XS - array[N], solution
36013 : LagBC - array[N], Lagrange multipliers for box constraints
36014 : LagLC - array[M], Lagrange multipliers for linear constraints
36015 : TerminationType - completion code, positive values for success,
36016 : negative for failures (XS constrains best point
36017 : found so far):
36018 : * -2 the task is either unbounded or infeasible;
36019 : the IPM solver has difficulty distinguishing between these two.
36020 : * +1 stopping criteria are met
36021 : * +7 stopping criteria are too stringent
36022 :
36023 : RESULT:
36024 :
36025 : This function ALWAYS returns something meaningful in XS, LagBC, LagLC -
36026 : either solution or the best point so far, even for negative TerminationType.
36027 :
36028 : -- ALGLIB --
36029 : Copyright 01.11.2019 by Bochkanov Sergey
36030 : *************************************************************************/
36031 0 : void vipmoptimize(vipmstate* state,
36032 : ae_bool dropbigbounds,
36033 : /* Real */ ae_vector* xs,
36034 : /* Real */ ae_vector* lagbc,
36035 : /* Real */ ae_vector* laglc,
36036 : ae_int_t* terminationtype,
36037 : ae_state *_state)
36038 : {
36039 : ae_int_t n;
36040 : ae_int_t m;
36041 : ae_int_t i;
36042 : ae_int_t iteridx;
36043 : double mu;
36044 : double muaff;
36045 : double sigma;
36046 : double alphaaffp;
36047 : double alphaaffd;
36048 : double alphap;
36049 : double alphad;
36050 : ae_int_t primalstagnationcnt;
36051 : ae_int_t dualstagnationcnt;
36052 : double regeps;
36053 : double dampeps;
36054 : double safedampeps;
36055 : double modeps;
36056 : double maxdampeps;
36057 : double regfree;
36058 : double dampfree;
36059 : ae_int_t droppedbounds;
36060 : double primalxscale;
36061 : double errp2;
36062 : double errd2;
36063 : double errpinf;
36064 : double errdinf;
36065 : double preverrp2;
36066 : double preverrd2;
36067 : double errgap;
36068 : double eprimal;
36069 : double edual;
36070 : double egap;
36071 : double mumin;
36072 : double mustop;
36073 : double y0nrm;
36074 : double bady;
36075 : double mxprimal;
36076 : double mxdeltaprimal;
36077 : ae_int_t bestiteridx;
36078 : double besterr;
36079 : double bestegap;
36080 : double besteprimal;
36081 : double bestedual;
36082 : ae_bool loadbest;
36083 :
36084 0 : *terminationtype = 0;
36085 :
36086 0 : n = state->n;
36087 0 : m = state->mdense+state->msparse;
36088 0 : state->dotrace = ae_is_trace_enabled("IPM");
36089 0 : state->dodetailedtrace = state->dotrace&&ae_is_trace_enabled("IPM.DETAILED");
36090 :
36091 : /*
36092 : * Prepare outputs
36093 : */
36094 0 : rsetallocv(n, 0.0, xs, _state);
36095 0 : rsetallocv(n, 0.0, lagbc, _state);
36096 0 : rsetallocv(m, 0.0, laglc, _state);
36097 :
36098 : /*
36099 : * Some integrity checks:
36100 : * * we need PrimalStagnationLen<DualStagnationLen in order to be able to correctly
36101 : * detect infeasible instances (stagnated dual error is present in both infeasible
36102 : * and unbounded instances, so we should check for primal stagnation a few iters
36103 : * before checking for dual stagnation)
36104 : */
36105 0 : ae_assert(vipmsolver_primalstagnationlen<vipmsolver_dualstagnationlen, "VIPM: critical integrity failure - incorrect configuration parameters", _state);
36106 :
36107 : /*
36108 : * Trace output (if needed)
36109 : */
36110 0 : if( state->dotrace )
36111 : {
36112 0 : ae_trace("\n\n");
36113 0 : ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n");
36114 0 : ae_trace("// IPM SOLVER STARTED //\n");
36115 0 : ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n");
36116 : }
36117 :
36118 : /*
36119 : * Prepare regularization coefficients:
36120 : * * RegEps - one that is applied to initial (5N+5M)x(5N+5M) KKT system. This one has to be
36121 : * small because it perturbs solution returned by the algorithm. Essential in order to
36122 : * avoid stalling at extremely large points.
36123 : * * ModEps - small modification applied to LDLT decomposition in order to preserve sign
36124 : * of diagonal elements
36125 : * * DampEps - damping coefficient for damped Newton step. Comes along with SafeDampEps
36126 : * (threshold value when some safeguards are turned off in order to preserve convergence
36127 : * speed) and MaxDampEps - threshold value when we consider problem overregularized and stop.
36128 : * * DampFree - additional damping coefficient for free variables
36129 : */
36130 0 : regfree = ae_pow(ae_machineepsilon, 0.75, _state);
36131 0 : dampfree = (double)(0);
36132 0 : regeps = 100*ae_machineepsilon;
36133 0 : modeps = (100+ae_sqrt((double)(n), _state))*ae_machineepsilon;
36134 0 : dampeps = (100+ae_sqrt((double)(n), _state))*ae_machineepsilon;
36135 0 : safedampeps = ae_sqrt(ae_machineepsilon, _state);
36136 0 : maxdampeps = ae_sqrt(ae_sqrt(ae_machineepsilon, _state), _state);
36137 :
36138 : /*
36139 : * Set up initial state
36140 : */
36141 0 : state->repiterationscount = 0;
36142 0 : state->repncholesky = 0;
36143 0 : mustop = (100+ae_sqrt((double)(n), _state))*ae_machineepsilon;
36144 0 : mumin = 0.01*mustop;
36145 0 : vipmsolver_vipmpowerup(state, regfree, _state);
36146 0 : vipmsolver_varsinitfrom(&state->x0, &state->current, _state);
36147 0 : vipmsolver_varsinitfrom(&state->best, &state->current, _state);
36148 0 : vipmsolver_varsinitbyzero(&state->zerovars, n, m, _state);
36149 0 : bestiteridx = -1;
36150 0 : besterr = ae_maxrealnumber;
36151 0 : bestegap = ae_maxrealnumber;
36152 0 : besteprimal = ae_maxrealnumber;
36153 0 : bestedual = ae_maxrealnumber;
36154 0 : vipmsolver_traceprogress(state, 0.0, 0.0, 0.0, 0.0, 0.0, _state);
36155 0 : y0nrm = (double)(0);
36156 0 : y0nrm = ae_maxreal(y0nrm, rmaxabsv(m, &state->current.y, _state), _state);
36157 0 : y0nrm = ae_maxreal(y0nrm, rmaxabsv(m, &state->current.v, _state), _state);
36158 0 : y0nrm = ae_maxreal(y0nrm, rmaxabsv(m, &state->current.q, _state), _state);
36159 0 : y0nrm = ae_maxreal(y0nrm, rmaxabsv(n, &state->current.z, _state), _state);
36160 0 : y0nrm = ae_maxreal(y0nrm, rmaxabsv(n, &state->current.s, _state), _state);
36161 :
36162 : /*
36163 : * Start iteration
36164 : */
36165 0 : loadbest = ae_true;
36166 0 : primalstagnationcnt = 0;
36167 0 : dualstagnationcnt = 0;
36168 0 : *terminationtype = 7;
36169 0 : errp2 = ae_maxrealnumber;
36170 0 : errd2 = ae_maxrealnumber;
36171 0 : for(iteridx=0; iteridx<=vipmsolver_maxipmits-1; iteridx++)
36172 : {
36173 0 : vipmsolver_varsinitfrom(&state->x0, &state->current, _state);
36174 :
36175 : /*
36176 : * Trace beginning
36177 : */
36178 0 : if( state->dotrace )
36179 : {
36180 0 : ae_trace("=== PREDICTOR-CORRECTOR STEP %2d ====================================================================\n",
36181 : (int)(iteridx));
36182 : }
36183 :
36184 : /*
36185 : * Check regularization status, terminate if overregularized
36186 : */
36187 0 : if( ae_fp_greater_eq(dampeps,maxdampeps) )
36188 : {
36189 0 : if( state->dotrace )
36190 : {
36191 0 : ae_trace("> tried to increase regularization parameter, but it is too large\n");
36192 0 : ae_trace("> it is likely that stopping conditions are too stringent, stopping at the best point found so far\n");
36193 : }
36194 0 : *terminationtype = 7;
36195 0 : break;
36196 : }
36197 :
36198 : /*
36199 : * Precompute factorization
36200 : *
36201 : * NOTE: we use "solver" regularization coefficient at this moment
36202 : */
36203 0 : if( !vipmsolver_vipmprecomputenewtonfactorization(state, &state->current, regeps, modeps, dampeps, dampfree, _state) )
36204 : {
36205 :
36206 : /*
36207 : * KKT factorization failed.
36208 : * Increase regularization parameter and skip this iteration.
36209 : */
36210 0 : dampeps = 10*dampeps;
36211 0 : if( state->dotrace )
36212 : {
36213 0 : ae_trace("> LDLT factorization failed due to rounding errors\n");
36214 0 : ae_trace("> increasing damping coefficient to %0.2e, skipping iteration\n",
36215 : (double)(dampeps));
36216 : }
36217 0 : continue;
36218 : }
36219 :
36220 : /*
36221 : * Compute Mu
36222 : */
36223 0 : mu = vipmsolver_varscomputemu(&state->current, _state);
36224 :
36225 : /*
36226 : * Compute affine scaling step for Mehrotra's predictor-corrector algorithm
36227 : */
36228 0 : vipmsolver_varsinitbyzero(&state->deltaaff, n, m, _state);
36229 0 : if( !vipmsolver_vipmcomputestepdirection(state, &state->current, 0.0, &state->zerovars, &state->deltaaff, regeps, ae_fp_greater_eq(dampeps,safedampeps), _state) )
36230 : {
36231 :
36232 : /*
36233 : * Affine scaling step failed due to numerical errors.
36234 : * Increase regularization parameter and skip this iteration.
36235 : */
36236 0 : dampeps = 10*dampeps;
36237 0 : if( state->dotrace )
36238 : {
36239 0 : ae_trace("> affine scaling step failed to decrease residual due to rounding errors\n");
36240 0 : ae_trace("> increasing damping coefficient to %0.2e, skipping iteration\n",
36241 : (double)(dampeps));
36242 : }
36243 0 : continue;
36244 : }
36245 0 : vipmsolver_vipmcomputesteplength(state, &state->current, &state->deltaaff, vipmsolver_steplengthdecay, &alphaaffp, &alphaaffd, _state);
36246 :
36247 : /*
36248 : * Compute MuAff and centering parameter
36249 : */
36250 0 : vipmsolver_varsinitfrom(&state->trial, &state->current, _state);
36251 0 : vipmsolver_varsaddstep(&state->trial, &state->deltaaff, alphaaffp, alphaaffd, _state);
36252 0 : muaff = vipmsolver_varscomputemu(&state->trial, _state);
36253 0 : sigma = ae_minreal(ae_pow((muaff+mumin)/(mu+mumin), (double)(3), _state), 1.0, _state);
36254 0 : ae_assert(ae_isfinite(sigma, _state)&&ae_fp_less_eq(sigma,(double)(1)), "VIPMOptimize: critical integrity check failed for Sigma (infinite or greater than 1)", _state);
36255 :
36256 : /*
36257 : * Compute corrector step
36258 : */
36259 0 : vipmsolver_varsinitbyzero(&state->deltacorr, n, m, _state);
36260 0 : if( !vipmsolver_vipmcomputestepdirection(state, &state->current, sigma*mu+mumin, &state->deltaaff, &state->deltacorr, regeps, ae_fp_greater_eq(dampeps,safedampeps), _state) )
36261 : {
36262 :
36263 : /*
36264 : * Affine scaling step failed due to numerical errors.
36265 : * Increase regularization parameter and skip this iteration.
36266 : */
36267 0 : dampeps = 10*dampeps;
36268 0 : if( state->dotrace )
36269 : {
36270 0 : ae_trace("> corrector step failed to decrease residual due to rounding errors\n");
36271 0 : ae_trace("> increasing damping coefficient to %0.2e, skipping iteration\n",
36272 : (double)(dampeps));
36273 : }
36274 0 : continue;
36275 : }
36276 0 : vipmsolver_vipmcomputesteplength(state, &state->current, &state->deltacorr, vipmsolver_steplengthdecay, &alphap, &alphad, _state);
36277 0 : if( ae_fp_greater_eq((double)(iteridx),vipmsolver_minitersbeforesafeguards)&&(ae_fp_less_eq(alphap,vipmsolver_badsteplength)||ae_fp_less_eq(alphad,vipmsolver_badsteplength)) )
36278 : {
36279 :
36280 : /*
36281 : * Affine scaling step failed due to numerical errors.
36282 : * Increase regularization parameter and skip this iteration.
36283 : */
36284 0 : dampeps = 10*dampeps;
36285 0 : if( state->dotrace )
36286 : {
36287 0 : ae_trace("> step length is too short, suspecting rounding errors\n");
36288 0 : ae_trace("> increasing damping coefficient to %0.2e, skipping iteration\n",
36289 : (double)(dampeps));
36290 : }
36291 0 : continue;
36292 : }
36293 :
36294 : /*
36295 : * Perform a step
36296 : */
36297 0 : vipmsolver_runintegritychecks(state, &state->current, &state->deltacorr, alphap, alphad, _state);
36298 0 : vipmsolver_vipmperformstep(state, alphap, alphad, _state);
36299 0 : vipmsolver_traceprogress(state, mu, muaff, sigma, alphap, alphad, _state);
36300 :
36301 : /*
36302 : * Check for excessive bounds (one that are so large that they are both irrelevant
36303 : * and destabilizing due to their magnitude)
36304 : */
36305 0 : if( dropbigbounds&&iteridx>=vipmsolver_minitersbeforedroppingbounds )
36306 : {
36307 0 : ae_assert(ae_fp_less_eq(10*vipmsolver_bigconstrmag,1/vipmsolver_bigconstrxtol), "VIPMOptimize: integrity check failed (incorrect BigConstr settings)", _state);
36308 0 : droppedbounds = 0;
36309 :
36310 : /*
36311 : * Determine variable and step scales.
36312 : * Both quantities are bounded from below by 1.0
36313 : */
36314 0 : mxprimal = 1.0;
36315 0 : mxprimal = ae_maxreal(mxprimal, rmaxabsv(n, &state->current.x, _state), _state);
36316 0 : mxprimal = ae_maxreal(mxprimal, rmaxabsv(n, &state->current.g, _state), _state);
36317 0 : mxprimal = ae_maxreal(mxprimal, rmaxabsv(n, &state->current.t, _state), _state);
36318 0 : mxprimal = ae_maxreal(mxprimal, rmaxabsv(m, &state->current.w, _state), _state);
36319 0 : mxprimal = ae_maxreal(mxprimal, rmaxabsv(m, &state->current.p, _state), _state);
36320 0 : mxdeltaprimal = 1.0;
36321 0 : mxdeltaprimal = ae_maxreal(mxdeltaprimal, alphap*rmaxabsv(n, &state->deltacorr.x, _state), _state);
36322 0 : mxdeltaprimal = ae_maxreal(mxdeltaprimal, alphap*rmaxabsv(n, &state->deltacorr.g, _state), _state);
36323 0 : mxdeltaprimal = ae_maxreal(mxdeltaprimal, alphap*rmaxabsv(n, &state->deltacorr.t, _state), _state);
36324 0 : mxdeltaprimal = ae_maxreal(mxdeltaprimal, alphap*rmaxabsv(m, &state->deltacorr.w, _state), _state);
36325 0 : mxdeltaprimal = ae_maxreal(mxdeltaprimal, alphap*rmaxabsv(m, &state->deltacorr.p, _state), _state);
36326 :
36327 : /*
36328 : * If changes in primal variables are small enough, try dropping too large bounds
36329 : */
36330 0 : if( ae_fp_less(mxdeltaprimal,mxprimal*vipmsolver_bigconstrxtol) )
36331 : {
36332 :
36333 : /*
36334 : * Drop irrelevant box constraints
36335 : */
36336 0 : primalxscale = 1.0;
36337 0 : primalxscale = ae_maxreal(primalxscale, rmaxabsv(n, &state->current.x, _state), _state);
36338 0 : for(i=0; i<=n-1; i++)
36339 : {
36340 0 : if( (state->hasbndl.ptr.p_bool[i]&&state->hasgz.ptr.p_bool[i])&&ae_fp_greater(ae_fabs(state->bndl.ptr.p_double[i], _state),vipmsolver_bigconstrmag*primalxscale) )
36341 : {
36342 0 : state->hasgz.ptr.p_bool[i] = ae_false;
36343 0 : state->current.g.ptr.p_double[i] = (double)(0);
36344 0 : state->current.z.ptr.p_double[i] = (double)(0);
36345 0 : inc(&droppedbounds, _state);
36346 : }
36347 0 : if( (state->hasbndu.ptr.p_bool[i]&&state->hasts.ptr.p_bool[i])&&ae_fp_greater(ae_fabs(state->bndu.ptr.p_double[i], _state),vipmsolver_bigconstrmag*primalxscale) )
36348 : {
36349 0 : state->hasts.ptr.p_bool[i] = ae_false;
36350 0 : state->current.t.ptr.p_double[i] = (double)(0);
36351 0 : state->current.s.ptr.p_double[i] = (double)(0);
36352 0 : inc(&droppedbounds, _state);
36353 : }
36354 : }
36355 :
36356 : /*
36357 : * Drop irrelevant linear constraints. Due to specifics of the solver
36358 : * we can drop only right part part of b<=Ax<=b+r.
36359 : *
36360 : * We can't drop b<=A from b<=A<=b+r because it impossible with our choice of
36361 : * slack variables. Usually we do not need to do so because we reorder constraints
36362 : * during initialization in such a way that |b+r|>|b| and because typical
36363 : * applications do not have excessively large lower AND upper bound (user may
36364 : * specify large value for 'absent' bound, but usually he does not mark both bounds as absent).
36365 : */
36366 0 : vipmsolver_multiplygeax(state, 1.0, &state->current.x, 0, 0.0, &state->tmpax, 0, _state);
36367 0 : primalxscale = 1.0;
36368 0 : primalxscale = ae_maxreal(primalxscale, rmaxabsv(n, &state->current.x, _state), _state);
36369 0 : primalxscale = ae_maxreal(primalxscale, rmaxabsv(m, &state->tmpax, _state), _state);
36370 0 : for(i=0; i<=m-1; i++)
36371 : {
36372 0 : if( ((state->hasr.ptr.p_bool[i]&&state->haspq.ptr.p_bool[i])&&ae_fp_greater(ae_fabs(state->b.ptr.p_double[i]+state->r.ptr.p_double[i], _state),vipmsolver_bigconstrmag*primalxscale))&&ae_fp_less(ae_fabs(state->b.ptr.p_double[i], _state),vipmsolver_bigconstrmag*primalxscale) )
36373 : {
36374 0 : ae_assert(state->haswv.ptr.p_bool[i]&&state->haspq.ptr.p_bool[i], "VIPMOptimize: unexpected integrity check failure (4y64)", _state);
36375 0 : state->haspq.ptr.p_bool[i] = ae_false;
36376 0 : state->current.p.ptr.p_double[i] = (double)(0);
36377 0 : state->current.q.ptr.p_double[i] = (double)(0);
36378 0 : inc(&droppedbounds, _state);
36379 : }
36380 : }
36381 :
36382 : /*
36383 : * Trace output
36384 : */
36385 0 : if( droppedbounds>0 )
36386 : {
36387 0 : if( state->dotrace )
36388 : {
36389 0 : ae_trace("[NOTICE] detected %0d irrelevant constraints with huge bounds, X converged to values well below them, dropping...\n",
36390 : (int)(droppedbounds));
36391 : }
36392 : }
36393 : }
36394 : }
36395 :
36396 : /*
36397 : * Check stopping criteria
36398 : * * primal and dual stagnation are checked only when following criteria are met:
36399 : * 1) Mu is smaller than 1 (we already converged close enough)
36400 : * 2) we performed more than MinItersBeforeStagnation iterations
36401 : */
36402 0 : preverrp2 = errp2;
36403 0 : preverrd2 = errd2;
36404 0 : vipmsolver_computeerrors(state, &errp2, &errd2, &errpinf, &errdinf, &errgap, _state);
36405 0 : mu = vipmsolver_varscomputemu(&state->current, _state);
36406 0 : egap = errgap;
36407 0 : eprimal = errpinf;
36408 0 : edual = errdinf;
36409 0 : if( ae_fp_less(rmax3(egap, eprimal, edual, _state),besterr) )
36410 : {
36411 :
36412 : /*
36413 : * Save best point found so far
36414 : */
36415 0 : vipmsolver_varsinitfrom(&state->best, &state->current, _state);
36416 0 : bestiteridx = iteridx;
36417 0 : besterr = rmax3(egap, eprimal, edual, _state);
36418 0 : bestegap = egap;
36419 0 : besteprimal = eprimal;
36420 0 : bestedual = edual;
36421 : }
36422 0 : if( bestiteridx>0&&iteridx>bestiteridx+vipmsolver_minitersbeforeeworststagnation )
36423 : {
36424 0 : if( state->dotrace )
36425 : {
36426 0 : ae_trace("> worst of primal/dual/gap errors stagnated for %0d its, stopping at the best point found so far\n",
36427 : (int)(vipmsolver_minitersbeforeeworststagnation));
36428 : }
36429 0 : break;
36430 : }
36431 0 : if( ((ae_fp_less_eq(egap,state->epsgap)&&ae_fp_greater_eq(errp2,vipmsolver_stagnationdelta*preverrp2))&&ae_fp_greater_eq(errpinf,vipmsolver_primalinfeasible1))&&iteridx>=vipmsolver_minitersbeforestagnation )
36432 : {
36433 0 : inc(&primalstagnationcnt, _state);
36434 0 : if( primalstagnationcnt>=vipmsolver_primalstagnationlen )
36435 : {
36436 0 : if( state->dotrace )
36437 : {
36438 0 : ae_trace("> primal error stagnated for %0d its, stopping at the best point found so far\n",
36439 : (int)(vipmsolver_primalstagnationlen));
36440 : }
36441 0 : break;
36442 : }
36443 : }
36444 : else
36445 : {
36446 0 : primalstagnationcnt = 0;
36447 : }
36448 0 : if( ((ae_fp_less_eq(egap,state->epsgap)&&ae_fp_greater_eq(errd2,vipmsolver_stagnationdelta*preverrd2))&&ae_fp_greater_eq(errdinf,vipmsolver_dualinfeasible1))&&iteridx>=vipmsolver_minitersbeforestagnation )
36449 : {
36450 0 : inc(&dualstagnationcnt, _state);
36451 0 : if( dualstagnationcnt>=vipmsolver_dualstagnationlen )
36452 : {
36453 0 : if( state->dotrace )
36454 : {
36455 0 : ae_trace("> dual error stagnated for %0d its, stopping at the best point found so far\n",
36456 : (int)(vipmsolver_dualstagnationlen));
36457 : }
36458 0 : break;
36459 : }
36460 : }
36461 : else
36462 : {
36463 0 : dualstagnationcnt = 0;
36464 : }
36465 0 : if( ae_fp_less_eq(mu,mustop)&&iteridx>=vipmsolver_itersfortoostringentcond )
36466 : {
36467 0 : if( state->dotrace )
36468 : {
36469 0 : ae_trace("> stopping conditions are too stringent, stopping at the best point found so far\n");
36470 : }
36471 0 : *terminationtype = 7;
36472 0 : break;
36473 : }
36474 0 : if( (ae_fp_less_eq(egap,state->epsgap)&&ae_fp_less_eq(eprimal,state->epsp))&&ae_fp_less_eq(edual,state->epsd) )
36475 : {
36476 0 : if( state->dotrace )
36477 : {
36478 0 : ae_trace("> stopping criteria are met\n");
36479 : }
36480 0 : *terminationtype = 1;
36481 0 : loadbest = ae_false;
36482 0 : break;
36483 : }
36484 0 : bady = vipmsolver_bigy;
36485 0 : bady = ae_maxreal(bady, vipmsolver_ygrowth*y0nrm, _state);
36486 0 : bady = ae_maxreal(bady, vipmsolver_ygrowth*rmaxabsv(n, &state->current.x, _state), _state);
36487 0 : bady = ae_maxreal(bady, vipmsolver_ygrowth*rmaxabsv(n, &state->current.g, _state), _state);
36488 0 : bady = ae_maxreal(bady, vipmsolver_ygrowth*rmaxabsv(n, &state->current.t, _state), _state);
36489 0 : bady = ae_maxreal(bady, vipmsolver_ygrowth*rmaxabsv(m, &state->current.w, _state), _state);
36490 0 : bady = ae_maxreal(bady, vipmsolver_ygrowth*rmaxabsv(m, &state->current.p, _state), _state);
36491 0 : if( ae_fp_greater_eq(rmaxabsv(m, &state->current.y, _state),bady)&&iteridx>=vipmsolver_minitersbeforeinfeasible )
36492 : {
36493 0 : if( state->dotrace )
36494 : {
36495 0 : ae_trace("> |Y| increased beyond %0.1e, stopping at the best point found so far\n",
36496 : (double)(bady));
36497 : }
36498 0 : break;
36499 : }
36500 : }
36501 :
36502 : /*
36503 : * Load best point, perform some checks
36504 : */
36505 0 : if( loadbest )
36506 : {
36507 :
36508 : /*
36509 : * Load best point
36510 : *
36511 : * NOTE: TouchReal() is used to avoid spurious compiler warnings about 'set but unused'
36512 : */
36513 0 : if( state->dotrace )
36514 : {
36515 0 : ae_trace("> the best point so far is one from iteration %0d\n",
36516 : (int)(bestiteridx));
36517 : }
36518 0 : vipmsolver_varsinitfrom(&state->current, &state->best, _state);
36519 0 : touchreal(&besteprimal, _state);
36520 0 : touchreal(&bestedual, _state);
36521 0 : touchreal(&bestegap, _state);
36522 :
36523 : /*
36524 : * If no error flags were set yet, check solution quality
36525 : */
36526 0 : bady = vipmsolver_bigy;
36527 0 : bady = ae_maxreal(bady, vipmsolver_ygrowth*y0nrm, _state);
36528 0 : bady = ae_maxreal(bady, vipmsolver_ygrowth*rmaxabsv(n, &state->current.x, _state), _state);
36529 0 : bady = ae_maxreal(bady, vipmsolver_ygrowth*rmaxabsv(n, &state->current.g, _state), _state);
36530 0 : bady = ae_maxreal(bady, vipmsolver_ygrowth*rmaxabsv(n, &state->current.t, _state), _state);
36531 0 : bady = ae_maxreal(bady, vipmsolver_ygrowth*rmaxabsv(m, &state->current.w, _state), _state);
36532 0 : bady = ae_maxreal(bady, vipmsolver_ygrowth*rmaxabsv(m, &state->current.p, _state), _state);
36533 0 : if( *terminationtype>0&&ae_fp_greater_eq(rmaxabsv(m, &state->current.y, _state),bady) )
36534 : {
36535 0 : *terminationtype = -2;
36536 0 : if( state->dotrace )
36537 : {
36538 0 : ae_trace("> |Y| increased beyond %0.1e, declaring infeasibility/unboundedness\n",
36539 : (double)(bady));
36540 : }
36541 : }
36542 0 : if( *terminationtype>0&&ae_fp_greater_eq(besteprimal,vipmsolver_primalinfeasible1) )
36543 : {
36544 0 : *terminationtype = -2;
36545 0 : if( state->dotrace )
36546 : {
36547 0 : ae_trace("> primal error at the best point is too high, declaring infeasibility/unboundedness\n");
36548 : }
36549 : }
36550 0 : if( *terminationtype>0&&ae_fp_greater_eq(bestedual,vipmsolver_dualinfeasible1) )
36551 : {
36552 0 : *terminationtype = -2;
36553 0 : if( state->dotrace )
36554 : {
36555 0 : ae_trace("> dual error at the best point is too high, declaring infeasibility/unboundedness\n");
36556 : }
36557 : }
36558 : }
36559 :
36560 : /*
36561 : * Output
36562 : */
36563 0 : vipmsolver_multiplyhx(state, &state->current.x, &state->tmp0, _state);
36564 0 : raddv(n, 1.0, &state->c, &state->tmp0, _state);
36565 0 : vipmsolver_multiplygeatx(state, -1.0, &state->current.y, 0, 1.0, &state->tmp0, 0, _state);
36566 0 : for(i=0; i<=n-1; i++)
36567 : {
36568 0 : if( state->isfrozen.ptr.p_bool[i] )
36569 : {
36570 :
36571 : /*
36572 : * I-th variable is frozen, use its frozen value.
36573 : * By the definition, I-th Lagrangian multiplier is an I-th component of Lagrangian gradient
36574 : */
36575 0 : xs->ptr.p_double[i] = state->current.x.ptr.p_double[i];
36576 0 : lagbc->ptr.p_double[i] = -state->tmp0.ptr.p_double[i];
36577 : }
36578 : else
36579 : {
36580 0 : xs->ptr.p_double[i] = state->current.x.ptr.p_double[i];
36581 0 : lagbc->ptr.p_double[i] = 0.0;
36582 0 : if( state->hasgz.ptr.p_bool[i] )
36583 : {
36584 0 : lagbc->ptr.p_double[i] = lagbc->ptr.p_double[i]-state->current.z.ptr.p_double[i];
36585 : }
36586 0 : if( state->hasts.ptr.p_bool[i] )
36587 : {
36588 0 : lagbc->ptr.p_double[i] = lagbc->ptr.p_double[i]+state->current.s.ptr.p_double[i];
36589 : }
36590 : }
36591 : }
36592 0 : for(i=0; i<=m-1; i++)
36593 : {
36594 0 : laglc->ptr.p_double[i] = -state->current.y.ptr.p_double[i];
36595 : }
36596 :
36597 : /*
36598 : * Unscale point and Lagrange multipliers
36599 : */
36600 0 : unscaleunshiftpointbc(&state->scl, &state->xorigin, &state->rawbndl, &state->rawbndu, &state->bndl, &state->bndu, &state->hasbndl, &state->hasbndu, xs, n, _state);
36601 0 : for(i=0; i<=n-1; i++)
36602 : {
36603 0 : lagbc->ptr.p_double[i] = lagbc->ptr.p_double[i]*state->targetscale/state->scl.ptr.p_double[i];
36604 : }
36605 0 : for(i=0; i<=m-1; i++)
36606 : {
36607 0 : laglc->ptr.p_double[i] = laglc->ptr.p_double[i]*state->targetscale/coalesce(state->ascales.ptr.p_double[i], 1.0, _state);
36608 : }
36609 0 : }
36610 :
36611 :
36612 : /*************************************************************************
36613 : Allocates place for variables of IPM and fills by zeros.
36614 :
36615 : -- ALGLIB --
36616 : Copyright 01.11.2019 by Bochkanov Sergey
36617 : *************************************************************************/
36618 0 : static void vipmsolver_varsinitbyzero(vipmvars* vstate,
36619 : ae_int_t n,
36620 : ae_int_t m,
36621 : ae_state *_state)
36622 : {
36623 :
36624 :
36625 0 : ae_assert(n>=1, "VarsInitByZero: N<1", _state);
36626 0 : ae_assert(m>=0, "VarsInitByZero: M<0", _state);
36627 0 : vstate->n = n;
36628 0 : vstate->m = m;
36629 0 : rsetallocv(n, 0.0, &vstate->x, _state);
36630 0 : rsetallocv(n, 0.0, &vstate->g, _state);
36631 0 : rsetallocv(n, 0.0, &vstate->t, _state);
36632 0 : rsetallocv(n, 0.0, &vstate->z, _state);
36633 0 : rsetallocv(n, 0.0, &vstate->s, _state);
36634 0 : rsetallocv(m, 0.0, &vstate->y, _state);
36635 0 : rsetallocv(m, 0.0, &vstate->w, _state);
36636 0 : rsetallocv(m, 0.0, &vstate->p, _state);
36637 0 : rsetallocv(m, 0.0, &vstate->v, _state);
36638 0 : rsetallocv(m, 0.0, &vstate->q, _state);
36639 0 : }
36640 :
36641 :
36642 : /*************************************************************************
36643 : Allocates place for variables of IPM and fills them by values of
36644 : the source
36645 :
36646 : -- ALGLIB --
36647 : Copyright 01.11.2019 by Bochkanov Sergey
36648 : *************************************************************************/
36649 0 : static void vipmsolver_varsinitfrom(vipmvars* vstate,
36650 : vipmvars* vsrc,
36651 : ae_state *_state)
36652 : {
36653 : ae_int_t i;
36654 : ae_int_t n;
36655 : ae_int_t m;
36656 :
36657 :
36658 0 : n = vsrc->n;
36659 0 : m = vsrc->m;
36660 0 : ae_assert(n>=1, "VarsInitFrom: N<1", _state);
36661 0 : ae_assert(m>=0, "VarsInitFrom: M<0", _state);
36662 0 : vstate->n = n;
36663 0 : vstate->m = m;
36664 0 : rvectorsetlengthatleast(&vstate->x, n, _state);
36665 0 : rvectorsetlengthatleast(&vstate->g, n, _state);
36666 0 : rvectorsetlengthatleast(&vstate->t, n, _state);
36667 0 : rvectorsetlengthatleast(&vstate->w, m, _state);
36668 0 : rvectorsetlengthatleast(&vstate->p, m, _state);
36669 0 : rvectorsetlengthatleast(&vstate->z, n, _state);
36670 0 : rvectorsetlengthatleast(&vstate->s, n, _state);
36671 0 : rvectorsetlengthatleast(&vstate->y, m, _state);
36672 0 : rvectorsetlengthatleast(&vstate->v, m, _state);
36673 0 : rvectorsetlengthatleast(&vstate->q, m, _state);
36674 0 : for(i=0; i<=n-1; i++)
36675 : {
36676 0 : vstate->x.ptr.p_double[i] = vsrc->x.ptr.p_double[i];
36677 0 : vstate->g.ptr.p_double[i] = vsrc->g.ptr.p_double[i];
36678 0 : vstate->t.ptr.p_double[i] = vsrc->t.ptr.p_double[i];
36679 0 : vstate->z.ptr.p_double[i] = vsrc->z.ptr.p_double[i];
36680 0 : vstate->s.ptr.p_double[i] = vsrc->s.ptr.p_double[i];
36681 : }
36682 0 : for(i=0; i<=m-1; i++)
36683 : {
36684 0 : vstate->w.ptr.p_double[i] = vsrc->w.ptr.p_double[i];
36685 0 : vstate->p.ptr.p_double[i] = vsrc->p.ptr.p_double[i];
36686 0 : vstate->y.ptr.p_double[i] = vsrc->y.ptr.p_double[i];
36687 0 : vstate->v.ptr.p_double[i] = vsrc->v.ptr.p_double[i];
36688 0 : vstate->q.ptr.p_double[i] = vsrc->q.ptr.p_double[i];
36689 : }
36690 0 : }
36691 :
36692 :
36693 : /*************************************************************************
36694 : Adds to variables direction vector times step length. Different
36695 : lengths are used for primal and dual steps.
36696 :
36697 : -- ALGLIB --
36698 : Copyright 01.11.2019 by Bochkanov Sergey
36699 : *************************************************************************/
36700 0 : static void vipmsolver_varsaddstep(vipmvars* vstate,
36701 : vipmvars* vdir,
36702 : double stpp,
36703 : double stpd,
36704 : ae_state *_state)
36705 : {
36706 : ae_int_t i;
36707 : ae_int_t n;
36708 : ae_int_t m;
36709 :
36710 :
36711 0 : n = vstate->n;
36712 0 : m = vstate->m;
36713 0 : ae_assert(n>=1, "VarsAddStep: N<1", _state);
36714 0 : ae_assert(m>=0, "VarsAddStep: M<0", _state);
36715 0 : ae_assert(n==vdir->n, "VarsAddStep: sizes mismatch", _state);
36716 0 : ae_assert(m==vdir->m, "VarsAddStep: sizes mismatch", _state);
36717 0 : for(i=0; i<=n-1; i++)
36718 : {
36719 0 : vstate->x.ptr.p_double[i] = vstate->x.ptr.p_double[i]+stpp*vdir->x.ptr.p_double[i];
36720 0 : vstate->g.ptr.p_double[i] = vstate->g.ptr.p_double[i]+stpp*vdir->g.ptr.p_double[i];
36721 0 : vstate->t.ptr.p_double[i] = vstate->t.ptr.p_double[i]+stpp*vdir->t.ptr.p_double[i];
36722 0 : vstate->z.ptr.p_double[i] = vstate->z.ptr.p_double[i]+stpd*vdir->z.ptr.p_double[i];
36723 0 : vstate->s.ptr.p_double[i] = vstate->s.ptr.p_double[i]+stpd*vdir->s.ptr.p_double[i];
36724 : }
36725 0 : for(i=0; i<=m-1; i++)
36726 : {
36727 0 : vstate->w.ptr.p_double[i] = vstate->w.ptr.p_double[i]+stpp*vdir->w.ptr.p_double[i];
36728 0 : vstate->p.ptr.p_double[i] = vstate->p.ptr.p_double[i]+stpp*vdir->p.ptr.p_double[i];
36729 0 : vstate->y.ptr.p_double[i] = vstate->y.ptr.p_double[i]+stpd*vdir->y.ptr.p_double[i];
36730 0 : vstate->v.ptr.p_double[i] = vstate->v.ptr.p_double[i]+stpd*vdir->v.ptr.p_double[i];
36731 0 : vstate->q.ptr.p_double[i] = vstate->q.ptr.p_double[i]+stpd*vdir->q.ptr.p_double[i];
36732 : }
36733 0 : }
36734 :
36735 :
36736 : /*************************************************************************
36737 : Computes complementarity gap
36738 :
36739 : -- ALGLIB --
36740 : Copyright 01.11.2019 by Bochkanov Sergey
36741 : *************************************************************************/
36742 0 : static double vipmsolver_varscomputecomplementaritygap(vipmvars* vstate,
36743 : ae_state *_state)
36744 : {
36745 : ae_int_t i;
36746 : ae_int_t n;
36747 : ae_int_t m;
36748 : double result;
36749 :
36750 :
36751 0 : n = vstate->n;
36752 0 : m = vstate->m;
36753 0 : result = (double)(0);
36754 0 : for(i=0; i<=n-1; i++)
36755 : {
36756 0 : result = result+vstate->z.ptr.p_double[i]*vstate->g.ptr.p_double[i]+vstate->s.ptr.p_double[i]*vstate->t.ptr.p_double[i];
36757 : }
36758 0 : for(i=0; i<=m-1; i++)
36759 : {
36760 0 : result = result+vstate->v.ptr.p_double[i]*vstate->w.ptr.p_double[i]+vstate->p.ptr.p_double[i]*vstate->q.ptr.p_double[i];
36761 : }
36762 0 : return result;
36763 : }
36764 :
36765 :
36766 : /*************************************************************************
36767 : Computes empirical value of the barrier parameter Mu
36768 :
36769 : -- ALGLIB --
36770 : Copyright 01.11.2019 by Bochkanov Sergey
36771 : *************************************************************************/
36772 0 : static double vipmsolver_varscomputemu(vipmvars* vstate, ae_state *_state)
36773 : {
36774 : ae_int_t i;
36775 : ae_int_t k;
36776 : double result;
36777 :
36778 :
36779 0 : k = 0;
36780 0 : result = (double)(0);
36781 0 : for(i=0; i<=vstate->n-1; i++)
36782 : {
36783 0 : result = result+vstate->z.ptr.p_double[i]*vstate->g.ptr.p_double[i]+vstate->s.ptr.p_double[i]*vstate->t.ptr.p_double[i];
36784 0 : if( !(vstate->z.ptr.p_double[i]*vstate->g.ptr.p_double[i]==0.0) )
36785 : {
36786 0 : k = k+1;
36787 : }
36788 0 : if( !(vstate->s.ptr.p_double[i]*vstate->t.ptr.p_double[i]==0.0) )
36789 : {
36790 0 : k = k+1;
36791 : }
36792 : }
36793 0 : for(i=0; i<=vstate->m-1; i++)
36794 : {
36795 0 : result = result+vstate->v.ptr.p_double[i]*vstate->w.ptr.p_double[i]+vstate->p.ptr.p_double[i]*vstate->q.ptr.p_double[i];
36796 0 : if( !(vstate->v.ptr.p_double[i]*vstate->w.ptr.p_double[i]==0.0) )
36797 : {
36798 0 : k = k+1;
36799 : }
36800 0 : if( !(vstate->p.ptr.p_double[i]*vstate->q.ptr.p_double[i]==0.0) )
36801 : {
36802 0 : k = k+1;
36803 : }
36804 : }
36805 0 : result = result/coalesce((double)(k), (double)(1), _state);
36806 0 : return result;
36807 : }
36808 :
36809 :
36810 : /*************************************************************************
36811 : Initializes QP-IPM state and prepares it to receive quadratic/linear terms
36812 : and constraints.
36813 :
36814 : The solver is configured to work internally with factorization FType
36815 :
36816 : INPUT PARAMETERS:
36817 : State - solver state to be configured; previously allocated
36818 : memory is reused as much as possible
36819 : S - scale vector, array[N]:
36820 : * I-th element contains scale of I-th variable,
36821 : * S[I]>0
36822 : XOrigin - origin term, array[N]. Can be zero. The solver solves
36823 : problem of the form
36824 :
36825 : >
36826 : > min(0.5*(x-x_origin)'*A*(x-x_origin)+b'*(x-x_origin))
36827 : >
36828 :
36829 : The terms A and b (as well as constraints) will be
36830 : specified later with separate calls.
36831 : FType - factorization type:
36832 : * 0 for dense NxN factorization (normal equations)
36833 : * 1 for sparse (N+M)x(N+M) factorization
36834 :
36835 : -- ALGLIB --
36836 : Copyright 01.11.2019 by Bochkanov Sergey
36837 : *************************************************************************/
36838 0 : static void vipmsolver_vipminit(vipmstate* state,
36839 : /* Real */ ae_vector* s,
36840 : /* Real */ ae_vector* xorigin,
36841 : ae_int_t n,
36842 : ae_int_t nmain,
36843 : ae_int_t ftype,
36844 : ae_state *_state)
36845 : {
36846 : ae_int_t i;
36847 : ae_int_t j;
36848 : ae_int_t nslack;
36849 :
36850 :
36851 0 : ae_assert(n>=1, "VIPMInit: N<1", _state);
36852 0 : ae_assert(isfinitevector(s, n, _state), "VIPMInit: S contains infinite or NaN elements", _state);
36853 0 : ae_assert(isfinitevector(xorigin, n, _state), "VIPMInit: XOrigin contains infinite or NaN elements", _state);
36854 0 : ae_assert(ftype==0||ftype==1, "VIPMInit: unexpected FType", _state);
36855 0 : ae_assert(nmain>=1, "VIPMInit: NMain<1", _state);
36856 0 : ae_assert(nmain<=n, "VIPMInit: NMain>N", _state);
36857 0 : nslack = n-nmain;
36858 :
36859 : /*
36860 : * Problem metrics, settings and type
36861 : */
36862 0 : state->n = n;
36863 0 : state->nmain = nmain;
36864 0 : state->islinear = ae_true;
36865 0 : state->factorizationtype = ftype;
36866 0 : state->factorizationpresent = ae_false;
36867 0 : state->factorizationpoweredup = ae_false;
36868 0 : vipmsetcond(state, 0.0, 0.0, 0.0, _state);
36869 0 : state->slacksforequalityconstraints = ae_true;
36870 :
36871 : /*
36872 : * Reports
36873 : */
36874 0 : state->repiterationscount = 0;
36875 0 : state->repncholesky = 0;
36876 :
36877 : /*
36878 : * Trace
36879 : */
36880 0 : state->dotrace = ae_false;
36881 0 : state->dodetailedtrace = ae_false;
36882 :
36883 : /*
36884 : * Scale and origin
36885 : */
36886 0 : rvectorsetlengthatleast(&state->scl, n, _state);
36887 0 : rvectorsetlengthatleast(&state->invscl, n, _state);
36888 0 : rvectorsetlengthatleast(&state->xorigin, n, _state);
36889 0 : for(i=0; i<=n-1; i++)
36890 : {
36891 0 : ae_assert(s->ptr.p_double[i]>0.0, "VIPMInit: S[i] is non-positive", _state);
36892 0 : state->scl.ptr.p_double[i] = s->ptr.p_double[i];
36893 0 : state->invscl.ptr.p_double[i] = 1/s->ptr.p_double[i];
36894 0 : state->xorigin.ptr.p_double[i] = xorigin->ptr.p_double[i];
36895 : }
36896 0 : state->targetscale = 1.0;
36897 :
36898 : /*
36899 : * Linear and quadratic terms - default value
36900 : */
36901 0 : rvectorsetlengthatleast(&state->c, n, _state);
36902 0 : for(i=0; i<=n-1; i++)
36903 : {
36904 0 : state->c.ptr.p_double[i] = (double)(0);
36905 : }
36906 0 : state->hkind = -1;
36907 0 : if( ftype==0 )
36908 : {
36909 :
36910 : /*
36911 : * Dense quadratic term
36912 : */
36913 0 : rmatrixsetlengthatleast(&state->denseh, nmain, nmain, _state);
36914 0 : for(i=0; i<=nmain-1; i++)
36915 : {
36916 0 : for(j=0; j<=i; j++)
36917 : {
36918 0 : state->denseh.ptr.pp_double[i][j] = (double)(0);
36919 : }
36920 : }
36921 0 : state->hkind = 0;
36922 : }
36923 0 : if( ftype==1 )
36924 : {
36925 :
36926 : /*
36927 : * Sparse quadratic term
36928 : */
36929 0 : state->sparseh.matrixtype = 1;
36930 0 : state->sparseh.m = n;
36931 0 : state->sparseh.n = n;
36932 0 : state->sparseh.ninitialized = n;
36933 0 : ivectorsetlengthatleast(&state->sparseh.idx, n, _state);
36934 0 : rvectorsetlengthatleast(&state->sparseh.vals, n, _state);
36935 0 : ivectorsetlengthatleast(&state->sparseh.ridx, n+1, _state);
36936 0 : for(i=0; i<=n-1; i++)
36937 : {
36938 0 : state->sparseh.idx.ptr.p_int[i] = i;
36939 0 : state->sparseh.vals.ptr.p_double[i] = 0.0;
36940 0 : state->sparseh.ridx.ptr.p_int[i] = i;
36941 : }
36942 0 : state->sparseh.ridx.ptr.p_int[n] = n;
36943 0 : sparsecreatecrsinplace(&state->sparseh, _state);
36944 0 : state->hkind = 1;
36945 : }
36946 0 : ae_assert(state->hkind>=0, "VIPMInit: integrity check failed", _state);
36947 :
36948 : /*
36949 : * Box constraints - default values
36950 : */
36951 0 : rvectorsetlengthatleast(&state->bndl, n, _state);
36952 0 : rvectorsetlengthatleast(&state->bndu, n, _state);
36953 0 : bvectorsetlengthatleast(&state->hasbndl, n, _state);
36954 0 : bvectorsetlengthatleast(&state->hasbndu, n, _state);
36955 0 : for(i=0; i<=n-1; i++)
36956 : {
36957 0 : state->hasbndl.ptr.p_bool[i] = ae_false;
36958 0 : state->hasbndu.ptr.p_bool[i] = ae_false;
36959 0 : state->bndl.ptr.p_double[i] = _state->v_neginf;
36960 0 : state->bndu.ptr.p_double[i] = _state->v_posinf;
36961 : }
36962 :
36963 : /*
36964 : * Linear constraints - empty
36965 : */
36966 0 : state->mdense = 0;
36967 0 : state->msparse = 0;
36968 0 : state->combinedaslack.m = 0;
36969 0 : state->combinedaslack.n = nslack;
36970 0 : state->sparseamain.m = 0;
36971 0 : state->sparseamain.n = nmain;
36972 0 : sparsecreatecrsinplace(&state->sparseamain, _state);
36973 0 : sparsecreatecrsinplace(&state->combinedaslack, _state);
36974 0 : }
36975 :
36976 :
36977 : /*************************************************************************
36978 : Computes target function 0.5*x'*H*x+c'*x
36979 :
36980 : -- ALGLIB --
36981 : Copyright 01.11.2019 by Bochkanov Sergey
36982 : *************************************************************************/
36983 0 : static double vipmsolver_vipmtarget(vipmstate* state,
36984 : /* Real */ ae_vector* x,
36985 : ae_state *_state)
36986 : {
36987 : ae_int_t n;
36988 : ae_int_t nmain;
36989 : ae_int_t i;
36990 : ae_int_t j;
36991 : ae_int_t k;
36992 : ae_int_t j0;
36993 : ae_int_t j1;
36994 : double v;
36995 : double result;
36996 :
36997 :
36998 0 : n = state->n;
36999 0 : nmain = state->nmain;
37000 0 : ae_assert(state->hkind==0||state->hkind==1, "VIPMTarget: unexpected HKind", _state);
37001 0 : result = (double)(0);
37002 :
37003 : /*
37004 : * Dense
37005 : */
37006 0 : if( state->hkind==0 )
37007 : {
37008 0 : for(i=0; i<=nmain-1; i++)
37009 : {
37010 0 : for(j=0; j<=i-1; j++)
37011 : {
37012 0 : result = result+x->ptr.p_double[i]*state->denseh.ptr.pp_double[i][j]*x->ptr.p_double[j];
37013 : }
37014 0 : result = result+0.5*x->ptr.p_double[i]*x->ptr.p_double[i]*state->denseh.ptr.pp_double[i][i];
37015 : }
37016 0 : for(i=0; i<=n-1; i++)
37017 : {
37018 0 : result = result+state->c.ptr.p_double[i]*x->ptr.p_double[i];
37019 : }
37020 0 : return result;
37021 : }
37022 :
37023 : /*
37024 : * Sparse
37025 : */
37026 0 : if( state->hkind==1 )
37027 : {
37028 0 : for(i=0; i<=n-1; i++)
37029 : {
37030 0 : result = result+state->c.ptr.p_double[i]*x->ptr.p_double[i];
37031 0 : j0 = state->sparseh.ridx.ptr.p_int[i];
37032 0 : j1 = state->sparseh.didx.ptr.p_int[i]-1;
37033 0 : for(k=j0; k<=j1; k++)
37034 : {
37035 0 : v = state->sparseh.vals.ptr.p_double[k];
37036 0 : j = state->sparseh.idx.ptr.p_int[k];
37037 0 : result = result+v*x->ptr.p_double[i]*x->ptr.p_double[j];
37038 : }
37039 0 : ae_assert(state->sparseh.uidx.ptr.p_int[i]!=state->sparseh.didx.ptr.p_int[i], "VIPMTarget: sparse diagonal not found", _state);
37040 0 : v = state->sparseh.vals.ptr.p_double[state->sparseh.didx.ptr.p_int[i]];
37041 0 : result = result+0.5*v*x->ptr.p_double[i]*x->ptr.p_double[i];
37042 : }
37043 0 : return result;
37044 : }
37045 0 : return result;
37046 : }
37047 :
37048 :
37049 : /*************************************************************************
37050 : Computes
37051 :
37052 : Y := alpha*A*x + beta*Y
37053 :
37054 : where A is constraint matrix, X is user-specified source, Y is target.
37055 :
37056 : Beta can be zero (in this case original contents of Y is ignored).
37057 : If Beta is nonzero, we expect that Y contains preallocated array.
37058 :
37059 : -- ALGLIB --
37060 : Copyright 01.11.2019 by Bochkanov Sergey
37061 : *************************************************************************/
37062 0 : static void vipmsolver_multiplygeax(vipmstate* state,
37063 : double alpha,
37064 : /* Real */ ae_vector* x,
37065 : ae_int_t offsx,
37066 : double beta,
37067 : /* Real */ ae_vector* y,
37068 : ae_int_t offsax,
37069 : ae_state *_state)
37070 : {
37071 : ae_int_t n;
37072 : ae_int_t m;
37073 : ae_int_t mdense;
37074 : ae_int_t msparse;
37075 :
37076 :
37077 0 : n = state->n;
37078 0 : m = state->mdense+state->msparse;
37079 0 : mdense = state->mdense;
37080 0 : msparse = state->msparse;
37081 0 : if( ae_fp_eq(beta,(double)(0)) )
37082 : {
37083 0 : rallocv(offsax+m, y, _state);
37084 : }
37085 : else
37086 : {
37087 0 : ae_assert(y->cnt>=offsax+m, "MultiplyGEAX: Y is too short", _state);
37088 : }
37089 0 : if( msparse>0 )
37090 : {
37091 0 : sparsegemv(&state->sparseafull, alpha, 0, x, offsx, beta, y, offsax, _state);
37092 : }
37093 0 : if( mdense>0 )
37094 : {
37095 0 : rmatrixgemv(mdense, n, alpha, &state->denseafull, 0, 0, 0, x, offsx, beta, y, offsax+msparse, _state);
37096 : }
37097 0 : }
37098 :
37099 :
37100 : /*************************************************************************
37101 : Computes
37102 :
37103 : Y := alpha*A'*x + beta*Y
37104 :
37105 : where A is constraint matrix, X is user-specified source, Y is target.
37106 :
37107 : Beta can be zero, in this case we automatically reallocate target if it is
37108 : too short (but do NOT reallocate it if its size is large enough).
37109 : If Beta is nonzero, we expect that Y contains preallocated array.
37110 :
37111 : -- ALGLIB --
37112 : Copyright 01.11.2019 by Bochkanov Sergey
37113 : *************************************************************************/
37114 0 : static void vipmsolver_multiplygeatx(vipmstate* state,
37115 : double alpha,
37116 : /* Real */ ae_vector* x,
37117 : ae_int_t offsx,
37118 : double beta,
37119 : /* Real */ ae_vector* y,
37120 : ae_int_t offsy,
37121 : ae_state *_state)
37122 : {
37123 : ae_int_t n;
37124 : ae_int_t mdense;
37125 : ae_int_t msparse;
37126 :
37127 :
37128 0 : n = state->n;
37129 0 : mdense = state->mdense;
37130 0 : msparse = state->msparse;
37131 0 : if( ae_fp_eq(beta,(double)(0)) )
37132 : {
37133 0 : rallocv(offsy+n, y, _state);
37134 0 : rsetvx(n, 0.0, y, offsy, _state);
37135 : }
37136 : else
37137 : {
37138 0 : ae_assert(y->cnt>=offsy+n, "MultiplyGEATX: Y is too short", _state);
37139 0 : rmulvx(n, beta, y, offsy, _state);
37140 : }
37141 0 : if( msparse>0 )
37142 : {
37143 0 : sparsegemv(&state->sparseafull, alpha, 1, x, offsx, 1.0, y, offsy, _state);
37144 : }
37145 0 : if( mdense>0 )
37146 : {
37147 0 : rmatrixgemv(n, mdense, alpha, &state->denseafull, 0, 0, 1, x, offsx+msparse, 1.0, y, offsy, _state);
37148 : }
37149 0 : }
37150 :
37151 :
37152 : /*************************************************************************
37153 : Computes H*x, does not support advanced functionality of GEAX/GEATX
37154 :
37155 : -- ALGLIB --
37156 : Copyright 01.11.2019 by Bochkanov Sergey
37157 : *************************************************************************/
37158 0 : static void vipmsolver_multiplyhx(vipmstate* state,
37159 : /* Real */ ae_vector* x,
37160 : /* Real */ ae_vector* hx,
37161 : ae_state *_state)
37162 : {
37163 : ae_int_t n;
37164 : ae_int_t nmain;
37165 : ae_int_t i;
37166 :
37167 :
37168 0 : n = state->n;
37169 0 : nmain = state->nmain;
37170 0 : rvectorsetlengthatleast(hx, n, _state);
37171 0 : ae_assert(state->hkind==0||state->hkind==1, "VIPMMultiplyHX: unexpected HKind", _state);
37172 0 : if( state->hkind==0 )
37173 : {
37174 0 : rmatrixsymv(nmain, 1.0, &state->denseh, 0, 0, ae_false, x, 0, 0.0, hx, 0, _state);
37175 0 : for(i=nmain; i<=n-1; i++)
37176 : {
37177 0 : hx->ptr.p_double[i] = (double)(0);
37178 : }
37179 : }
37180 0 : if( state->hkind==1 )
37181 : {
37182 0 : ae_assert(state->sparseh.n==n&&state->sparseh.m==n, "VIPMMultiplyHX: sparse H has incorrect size", _state);
37183 0 : sparsesmv(&state->sparseh, ae_false, x, hx, _state);
37184 : }
37185 0 : for(i=0; i<=n-1; i++)
37186 : {
37187 0 : hx->ptr.p_double[i] = hx->ptr.p_double[i]+x->ptr.p_double[i]*state->diagr.ptr.p_double[i];
37188 : }
37189 0 : }
37190 :
37191 :
37192 : /*************************************************************************
37193 : Computes products H*x, A*x, A^T*y
37194 :
37195 : -- ALGLIB --
37196 : Copyright 01.11.2019 by Bochkanov Sergey
37197 : *************************************************************************/
37198 0 : static void vipmsolver_vipmmultiply(vipmstate* state,
37199 : /* Real */ ae_vector* x,
37200 : /* Real */ ae_vector* y,
37201 : /* Real */ ae_vector* hx,
37202 : /* Real */ ae_vector* ax,
37203 : /* Real */ ae_vector* aty,
37204 : ae_state *_state)
37205 : {
37206 :
37207 :
37208 0 : vipmsolver_multiplygeax(state, 1.0, x, 0, 0.0, ax, 0, _state);
37209 0 : vipmsolver_multiplygeatx(state, 1.0, y, 0, 0.0, aty, 0, _state);
37210 0 : vipmsolver_multiplyhx(state, x, hx, _state);
37211 0 : }
37212 :
37213 :
37214 : /*************************************************************************
37215 : This function "powers up" factorization, i.e. prepares some important
37216 : temporaries. It should be called once prior to the first call to
37217 : VIPMInitialPoint() or VIPMFactorize().
37218 :
37219 : Parameters:
37220 : RegFree - regularization for free variables;
37221 : good value sqrt(MachineEpsilon)
37222 :
37223 : -- ALGLIB --
37224 : Copyright 01.11.2019 by Bochkanov Sergey
37225 : *************************************************************************/
37226 0 : static void vipmsolver_vipmpowerup(vipmstate* state,
37227 : double regfree,
37228 : ae_state *_state)
37229 : {
37230 : ae_int_t n;
37231 : ae_int_t m;
37232 : ae_int_t nnzmax;
37233 : ae_int_t offs;
37234 : ae_int_t rowoffs;
37235 : ae_int_t i;
37236 : ae_int_t j;
37237 : ae_int_t k;
37238 : ae_int_t k0;
37239 : ae_int_t k1;
37240 : double v;
37241 : double vrhs;
37242 : ae_int_t factldlt;
37243 : ae_int_t permauto;
37244 : double maxinitialnoncentrality;
37245 : double maxinitialimbalance;
37246 : double priorcoeff;
37247 : double initprimslack;
37248 : double initdualslack;
37249 : double mu0;
37250 : double mumin;
37251 : ae_bool success;
37252 :
37253 :
37254 0 : ae_assert(state->factorizationtype==0||state->factorizationtype==1, "VIPMPowerUp: unexpected factorization type", _state);
37255 0 : n = state->n;
37256 0 : m = state->mdense+state->msparse;
37257 0 : ae_assert(!state->factorizationpoweredup, "VIPMPowerUp: repeated call", _state);
37258 0 : maxinitialnoncentrality = 1.0E-6;
37259 0 : maxinitialimbalance = 1.0E-6;
37260 :
37261 : /*
37262 : * Set up information about presence of slack variables.
37263 : * Decide which components of X should be frozen.
37264 : * Compute diagonal regularization matrix R.
37265 : */
37266 0 : bcopyallocv(n, &state->hasbndl, &state->hasgz, _state);
37267 0 : bcopyallocv(n, &state->hasbndu, &state->hasts, _state);
37268 0 : bsetallocv(n, ae_false, &state->isfrozen, _state);
37269 0 : rsetallocv(n, 0.0, &state->diagr, _state);
37270 0 : vipmsolver_varsinitbyzero(&state->current, n, m, _state);
37271 0 : for(i=0; i<=n-1; i++)
37272 : {
37273 0 : 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]) )
37274 : {
37275 0 : state->isfrozen.ptr.p_bool[i] = ae_true;
37276 0 : state->hasgz.ptr.p_bool[i] = ae_false;
37277 0 : state->hasts.ptr.p_bool[i] = ae_false;
37278 0 : state->current.x.ptr.p_double[i] = state->bndl.ptr.p_double[i];
37279 : }
37280 0 : if( !state->hasbndl.ptr.p_bool[i]&&!state->hasbndu.ptr.p_bool[i] )
37281 : {
37282 0 : state->diagr.ptr.p_double[i] = regfree;
37283 : }
37284 : }
37285 0 : ballocv(m, &state->haspq, _state);
37286 0 : ballocv(m, &state->haswv, _state);
37287 0 : for(i=0; i<=m-1; i++)
37288 : {
37289 0 : state->haswv.ptr.p_bool[i] = (state->slacksforequalityconstraints||!state->hasr.ptr.p_bool[i])||ae_fp_greater(state->r.ptr.p_double[i],(double)(0));
37290 0 : state->haspq.ptr.p_bool[i] = state->hasr.ptr.p_bool[i]&&state->haswv.ptr.p_bool[i];
37291 : }
37292 :
37293 : /*
37294 : * Only sparse factorization needs special powering up
37295 : */
37296 0 : if( state->factorizationtype==1 )
37297 : {
37298 0 : ae_assert(state->hkind==1, "VIPMPowerUp: unexpected HKind", _state);
37299 0 : nnzmax = state->sparseh.ridx.ptr.p_int[n];
37300 0 : if( state->msparse>0 )
37301 : {
37302 0 : nnzmax = nnzmax+state->sparseafull.ridx.ptr.p_int[state->msparse];
37303 : }
37304 0 : if( state->mdense>0 )
37305 : {
37306 0 : nnzmax = nnzmax+n*state->mdense;
37307 : }
37308 0 : nnzmax = nnzmax+(n+m);
37309 :
37310 : /*
37311 : * Prepare strictly lower triangle of template KKT matrix (KKT system without D and E
37312 : * terms being added to diagonals)
37313 : */
37314 0 : state->factsparsekkttmpl.m = n+m;
37315 0 : state->factsparsekkttmpl.n = n+m;
37316 0 : ivectorsetlengthatleast(&state->factsparsekkttmpl.idx, nnzmax, _state);
37317 0 : rvectorsetlengthatleast(&state->factsparsekkttmpl.vals, nnzmax, _state);
37318 0 : ivectorsetlengthatleast(&state->factsparsekkttmpl.ridx, n+m+1, _state);
37319 0 : state->factsparsekkttmpl.ridx.ptr.p_int[0] = 0;
37320 0 : offs = 0;
37321 0 : rowoffs = 0;
37322 0 : for(i=0; i<=n-1; i++)
37323 : {
37324 0 : ae_assert(state->sparseh.didx.ptr.p_int[i]+1==state->sparseh.uidx.ptr.p_int[i], "VIPMPowerUp: critical integrity check failed for diagonal of H", _state);
37325 0 : if( !state->isfrozen.ptr.p_bool[i] )
37326 : {
37327 :
37328 : /*
37329 : * Entire row is not frozen, but some of its entries can be.
37330 : * Output non-frozen offdiagonal entries.
37331 : */
37332 0 : k0 = state->sparseh.ridx.ptr.p_int[i];
37333 0 : k1 = state->sparseh.didx.ptr.p_int[i]-1;
37334 0 : for(k=k0; k<=k1; k++)
37335 : {
37336 0 : j = state->sparseh.idx.ptr.p_int[k];
37337 0 : if( !state->isfrozen.ptr.p_bool[j] )
37338 : {
37339 0 : state->factsparsekkttmpl.idx.ptr.p_int[offs] = j;
37340 0 : state->factsparsekkttmpl.vals.ptr.p_double[offs] = -state->sparseh.vals.ptr.p_double[k];
37341 0 : offs = offs+1;
37342 : }
37343 : }
37344 :
37345 : /*
37346 : * Output diagonal entry (it is always not frozen)
37347 : */
37348 0 : state->factsparsekkttmpl.idx.ptr.p_int[offs] = i;
37349 0 : state->factsparsekkttmpl.vals.ptr.p_double[offs] = -state->sparseh.vals.ptr.p_double[state->sparseh.didx.ptr.p_int[i]];
37350 0 : offs = offs+1;
37351 : }
37352 : else
37353 : {
37354 :
37355 : /*
37356 : * Entire row is frozen, output just -1
37357 : */
37358 0 : state->factsparsekkttmpl.idx.ptr.p_int[offs] = i;
37359 0 : state->factsparsekkttmpl.vals.ptr.p_double[offs] = -1.0;
37360 0 : offs = offs+1;
37361 : }
37362 0 : rowoffs = rowoffs+1;
37363 0 : state->factsparsekkttmpl.ridx.ptr.p_int[rowoffs] = offs;
37364 : }
37365 0 : for(i=0; i<=state->msparse-1; i++)
37366 : {
37367 0 : k0 = state->sparseafull.ridx.ptr.p_int[i];
37368 0 : k1 = state->sparseafull.ridx.ptr.p_int[i+1]-1;
37369 0 : for(k=k0; k<=k1; k++)
37370 : {
37371 0 : j = state->sparseafull.idx.ptr.p_int[k];
37372 0 : if( !state->isfrozen.ptr.p_bool[j] )
37373 : {
37374 0 : state->factsparsekkttmpl.idx.ptr.p_int[offs] = j;
37375 0 : state->factsparsekkttmpl.vals.ptr.p_double[offs] = state->sparseafull.vals.ptr.p_double[k];
37376 0 : offs = offs+1;
37377 : }
37378 : }
37379 0 : state->factsparsekkttmpl.idx.ptr.p_int[offs] = rowoffs;
37380 0 : state->factsparsekkttmpl.vals.ptr.p_double[offs] = 0.0;
37381 0 : offs = offs+1;
37382 0 : rowoffs = rowoffs+1;
37383 0 : state->factsparsekkttmpl.ridx.ptr.p_int[rowoffs] = offs;
37384 : }
37385 0 : for(i=0; i<=state->mdense-1; i++)
37386 : {
37387 0 : for(k=0; k<=n-1; k++)
37388 : {
37389 0 : if( state->denseafull.ptr.pp_double[i][k]!=0.0&&!state->isfrozen.ptr.p_bool[k] )
37390 : {
37391 0 : state->factsparsekkttmpl.idx.ptr.p_int[offs] = k;
37392 0 : state->factsparsekkttmpl.vals.ptr.p_double[offs] = state->denseafull.ptr.pp_double[i][k];
37393 0 : offs = offs+1;
37394 : }
37395 : }
37396 0 : state->factsparsekkttmpl.idx.ptr.p_int[offs] = rowoffs;
37397 0 : state->factsparsekkttmpl.vals.ptr.p_double[offs] = 0.0;
37398 0 : offs = offs+1;
37399 0 : rowoffs = rowoffs+1;
37400 0 : state->factsparsekkttmpl.ridx.ptr.p_int[rowoffs] = offs;
37401 : }
37402 0 : ae_assert(rowoffs==m+n, "VIPMPowerUp: critical integrity check failed", _state);
37403 0 : ae_assert(offs<=nnzmax, "VIPMPowerUp: critical integrity check failed", _state);
37404 0 : sparsecreatecrsinplace(&state->factsparsekkttmpl, _state);
37405 0 : factldlt = 1;
37406 0 : permauto = 0;
37407 0 : if( !spsymmanalyze(&state->factsparsekkttmpl, factldlt, permauto, &state->ldltanalysis, _state) )
37408 : {
37409 0 : ae_assert(ae_false, "VIPMPowerUp: critical integrity check failed, symbolically degenerate KKT system encountered", _state);
37410 : }
37411 : }
37412 0 : state->factorizationpoweredup = ae_true;
37413 :
37414 : /*
37415 : * Set up initial values of primal and dual variables X and Y by solving
37416 : * modified KKT system which tries to enforce linear constraints (ignoring
37417 : * box constraints for a while) subject to minimization of additional prior
37418 : * term which moves solution towards some interior point.
37419 : *
37420 : * Here we expect that State.Current.X contains zeros in non-fixed variables
37421 : * and their fixed values for fixed ones.
37422 : */
37423 0 : priorcoeff = 1.0;
37424 0 : success = vipmsolver_vipmfactorize(state, 0.0, &state->diagddr, 0.0, &state->diagder, priorcoeff, priorcoeff, ae_machineepsilon, ae_machineepsilon, _state);
37425 0 : ae_assert(success, "VIPMInitialPoint: impossible failure of LDLT factorization", _state);
37426 0 : vipmsolver_multiplyhx(state, &state->current.x, &state->tmp0, _state);
37427 0 : vipmsolver_multiplygeax(state, 1.0, &state->current.x, 0, 0.0, &state->tmp1, 0, _state);
37428 0 : rallocv(n+m, &state->deltaxy, _state);
37429 0 : for(i=0; i<=n-1; i++)
37430 : {
37431 0 : state->deltaxy.ptr.p_double[i] = state->c.ptr.p_double[i]+state->tmp0.ptr.p_double[i];
37432 : }
37433 0 : for(i=0; i<=m-1; i++)
37434 : {
37435 :
37436 : /*
37437 : * We need to specify target right-hand sides for constraints.
37438 : *
37439 : * Ether zero, b or b+r is used (depending on presence of r and
37440 : * magnitudes of b and b+r, and subject to current state of frozen
37441 : * variables).
37442 : */
37443 0 : vrhs = state->b.ptr.p_double[i]-state->tmp1.ptr.p_double[i];
37444 0 : if( state->hasr.ptr.p_bool[i] )
37445 : {
37446 :
37447 : /*
37448 : * Range constraint b<=Ax<=b+r
37449 : */
37450 0 : if( ae_fp_greater_eq(vrhs,(double)(0)) )
37451 : {
37452 :
37453 : /*
37454 : * 0<=b<=b+r, select target at lower bound
37455 : */
37456 0 : v = vrhs;
37457 : }
37458 : else
37459 : {
37460 :
37461 : /*
37462 : * b<=0, b+r can have any sign.
37463 : * Select zero target if possible, if not - one with smallest absolute value.
37464 : */
37465 0 : v = ae_minreal(vrhs+state->r.ptr.p_double[i], 0.0, _state);
37466 : }
37467 : }
37468 : else
37469 : {
37470 :
37471 : /*
37472 : * Single-sided constraint Ax>=b.
37473 : * Select zero target if possible, if not - one with smallest absolute value.
37474 : */
37475 0 : v = ae_maxreal(vrhs, 0.0, _state);
37476 : }
37477 0 : state->deltaxy.ptr.p_double[n+i] = v;
37478 : }
37479 0 : vipmsolver_solvereducedkktsystem(state, &state->deltaxy, _state);
37480 0 : for(i=0; i<=n-1; i++)
37481 : {
37482 0 : if( !state->isfrozen.ptr.p_bool[i] )
37483 : {
37484 0 : state->current.x.ptr.p_double[i] = state->deltaxy.ptr.p_double[i];
37485 : }
37486 : }
37487 0 : for(i=0; i<=m-1; i++)
37488 : {
37489 0 : state->current.y.ptr.p_double[i] = state->deltaxy.ptr.p_double[n+i];
37490 : }
37491 :
37492 : /*
37493 : * Set up slacks according to our own heuristic
37494 : */
37495 0 : initprimslack = ae_maxreal(vipmsolver_initslackval, rmaxabsv(n, &state->current.x, _state), _state);
37496 0 : initdualslack = ae_maxreal(vipmsolver_initslackval, rmaxabsv(m, &state->current.y, _state), _state);
37497 0 : vipmsolver_multiplygeax(state, 1.0, &state->current.x, 0, 0.0, &state->tmpax, 0, _state);
37498 0 : mu0 = 1.0;
37499 0 : for(i=0; i<=n-1; i++)
37500 : {
37501 0 : if( state->hasgz.ptr.p_bool[i] )
37502 : {
37503 0 : state->current.g.ptr.p_double[i] = ae_maxreal(ae_fabs(state->current.x.ptr.p_double[i]-state->bndl.ptr.p_double[i], _state), initprimslack, _state);
37504 0 : state->current.z.ptr.p_double[i] = ae_maxreal(state->current.g.ptr.p_double[i]*maxinitialimbalance, initdualslack, _state);
37505 0 : mu0 = ae_maxreal(mu0, state->current.g.ptr.p_double[i]*state->current.z.ptr.p_double[i], _state);
37506 : }
37507 0 : if( state->hasts.ptr.p_bool[i] )
37508 : {
37509 0 : state->current.t.ptr.p_double[i] = ae_maxreal(ae_fabs(state->current.x.ptr.p_double[i]-state->bndu.ptr.p_double[i], _state), initprimslack, _state);
37510 0 : state->current.s.ptr.p_double[i] = ae_maxreal(state->current.t.ptr.p_double[i]*maxinitialimbalance, initdualslack, _state);
37511 0 : mu0 = ae_maxreal(mu0, state->current.t.ptr.p_double[i]*state->current.s.ptr.p_double[i], _state);
37512 : }
37513 : }
37514 0 : for(i=0; i<=m-1; i++)
37515 : {
37516 0 : if( state->haswv.ptr.p_bool[i] )
37517 : {
37518 0 : state->current.w.ptr.p_double[i] = ae_maxreal(ae_fabs(state->tmpax.ptr.p_double[i]-state->b.ptr.p_double[i], _state), initprimslack, _state);
37519 0 : state->current.v.ptr.p_double[i] = rmax3(state->current.w.ptr.p_double[i]*maxinitialimbalance, ae_fabs(state->current.y.ptr.p_double[i], _state), vipmsolver_initslackval, _state);
37520 0 : mu0 = ae_maxreal(mu0, state->current.w.ptr.p_double[i]*state->current.v.ptr.p_double[i], _state);
37521 : }
37522 0 : if( state->haspq.ptr.p_bool[i] )
37523 : {
37524 0 : state->current.p.ptr.p_double[i] = ae_maxreal(ae_fabs(state->r.ptr.p_double[i]-state->current.w.ptr.p_double[i], _state), initprimslack, _state);
37525 0 : state->current.q.ptr.p_double[i] = rmax3(state->current.p.ptr.p_double[i]*maxinitialimbalance, ae_fabs(state->current.y.ptr.p_double[i], _state), vipmsolver_initslackval, _state);
37526 0 : mu0 = ae_maxreal(mu0, state->current.p.ptr.p_double[i]*state->current.q.ptr.p_double[i], _state);
37527 : }
37528 : }
37529 :
37530 : /*
37531 : * Additional shift to ensure that initial point is not too non-centered
37532 : */
37533 0 : mumin = mu0*maxinitialnoncentrality;
37534 0 : for(i=0; i<=n-1; i++)
37535 : {
37536 0 : if( state->hasgz.ptr.p_bool[i]&&ae_fp_less(state->current.g.ptr.p_double[i]*state->current.z.ptr.p_double[i],mumin) )
37537 : {
37538 0 : v = ae_sqrt(mumin/(state->current.g.ptr.p_double[i]*state->current.z.ptr.p_double[i]), _state);
37539 0 : state->current.g.ptr.p_double[i] = state->current.g.ptr.p_double[i]*v;
37540 0 : state->current.z.ptr.p_double[i] = state->current.z.ptr.p_double[i]*v;
37541 : }
37542 0 : if( state->hasts.ptr.p_bool[i]&&ae_fp_less(state->current.t.ptr.p_double[i]*state->current.s.ptr.p_double[i],mumin) )
37543 : {
37544 0 : v = ae_sqrt(mumin/(state->current.t.ptr.p_double[i]*state->current.s.ptr.p_double[i]), _state);
37545 0 : state->current.t.ptr.p_double[i] = state->current.t.ptr.p_double[i]*v;
37546 0 : state->current.s.ptr.p_double[i] = state->current.s.ptr.p_double[i]*v;
37547 : }
37548 : }
37549 0 : for(i=0; i<=m-1; i++)
37550 : {
37551 0 : if( state->haswv.ptr.p_bool[i]&&ae_fp_less(state->current.w.ptr.p_double[i]*state->current.v.ptr.p_double[i],mumin) )
37552 : {
37553 0 : v = ae_sqrt(mumin/(state->current.w.ptr.p_double[i]*state->current.v.ptr.p_double[i]), _state);
37554 0 : state->current.w.ptr.p_double[i] = state->current.w.ptr.p_double[i]*v;
37555 0 : state->current.v.ptr.p_double[i] = state->current.v.ptr.p_double[i]*v;
37556 : }
37557 0 : if( state->haspq.ptr.p_bool[i]&&ae_fp_less(state->current.p.ptr.p_double[i]*state->current.q.ptr.p_double[i],mumin) )
37558 : {
37559 0 : v = ae_sqrt(mumin/(state->current.p.ptr.p_double[i]*state->current.q.ptr.p_double[i]), _state);
37560 0 : state->current.p.ptr.p_double[i] = state->current.p.ptr.p_double[i]*v;
37561 0 : state->current.q.ptr.p_double[i] = state->current.q.ptr.p_double[i]*v;
37562 : }
37563 : }
37564 :
37565 : /*
37566 : * Almost done
37567 : */
37568 0 : if( state->dotrace )
37569 : {
37570 0 : ae_trace("> initial point was generated\n");
37571 : }
37572 0 : }
37573 :
37574 :
37575 : /*************************************************************************
37576 : This function performs factorization of modified KKT system
37577 :
37578 : ( | )
37579 : ( -(H+alpha0*D+alpha1*I) | A^T )
37580 : ( | )
37581 : (------------------------|-----------------)
37582 : ( | )
37583 : ( A | beta0*E+beta1*I )
37584 : ( | )
37585 :
37586 : where:
37587 : * H is an NxN quadratic term
37588 : * A is an MxN matrix of linear constraint
37589 : * alpha0, alpha1, beta0, beta1 are nonnegative scalars
37590 : * D and E are diagonal matrices with nonnegative entries (which are ignored
37591 : if alpha0 and beta0 are zero - arrays are not referenced at all)
37592 : * I is an NxN or MxM identity matrix
37593 :
37594 : Additionally, regularizing term
37595 :
37596 : ( | )
37597 : ( -reg*I | )
37598 : ( | )
37599 : (--------|--------)
37600 : ( | )
37601 : ( | +reg*I )
37602 : ( | )
37603 :
37604 : is added to the entire KKT system prior to factorization in order to
37605 : improve its numerical stability.
37606 :
37607 : Returns True on success, False on falure of factorization (it is recommended
37608 : to increase regularization parameter and try one more time).
37609 :
37610 :
37611 : -- ALGLIB --
37612 : Copyright 01.11.2019 by Bochkanov Sergey
37613 : *************************************************************************/
37614 0 : static ae_bool vipmsolver_vipmfactorize(vipmstate* state,
37615 : double alpha0,
37616 : /* Real */ ae_vector* d,
37617 : double beta0,
37618 : /* Real */ ae_vector* e,
37619 : double alpha11,
37620 : double beta11,
37621 : double modeps,
37622 : double dampeps,
37623 : ae_state *_state)
37624 : {
37625 : ae_int_t n;
37626 : ae_int_t nmain;
37627 : ae_int_t nslack;
37628 : ae_int_t m;
37629 : ae_int_t mdense;
37630 : ae_int_t msparse;
37631 : ae_int_t i;
37632 : ae_int_t j;
37633 : ae_int_t k;
37634 : ae_int_t k0;
37635 : ae_int_t k1;
37636 : ae_int_t ka;
37637 : ae_int_t kb;
37638 : ae_int_t ja;
37639 : ae_int_t jb;
37640 : double va;
37641 : double vb;
37642 : double v;
37643 : double vv;
37644 : double badchol;
37645 : double sumsq;
37646 : double errsq;
37647 : ae_bool result;
37648 :
37649 :
37650 0 : ae_assert(ae_isfinite(alpha0, _state)&&ae_fp_greater_eq(alpha0,(double)(0)), "VIPMFactorize: Alpha0 is infinite or negative", _state);
37651 0 : ae_assert(ae_isfinite(alpha11, _state)&&ae_fp_greater_eq(alpha11,(double)(0)), "VIPMFactorize: Alpha1 is infinite or negative", _state);
37652 0 : ae_assert(ae_isfinite(beta0, _state)&&ae_fp_greater_eq(beta0,(double)(0)), "VIPMFactorize: Beta0 is infinite or negative", _state);
37653 0 : ae_assert(ae_isfinite(beta11, _state)&&ae_fp_greater_eq(beta11,(double)(0)), "VIPMFactorize: Beta1 is infinite or negative", _state);
37654 0 : ae_assert(state->factorizationtype==0||state->factorizationtype==1, "VIPMFactorize: unexpected factorization type", _state);
37655 0 : ae_assert(state->factorizationpoweredup, "VIPMFactorize: critical integrity check failed (no powerup stage)", _state);
37656 0 : n = state->n;
37657 0 : nmain = state->nmain;
37658 0 : nslack = n-nmain;
37659 0 : m = state->mdense+state->msparse;
37660 0 : mdense = state->mdense;
37661 0 : msparse = state->msparse;
37662 0 : state->factorizationpresent = ae_false;
37663 0 : badchol = 1.0E50;
37664 0 : result = ae_true;
37665 :
37666 : /*
37667 : * Dense NxN normal equations approach
37668 : */
37669 0 : if( state->factorizationtype==0 )
37670 : {
37671 :
37672 : /*
37673 : * A problem formulation with possible slacks.
37674 : *
37675 : * === A FORMULATION WITHOUT FROZEN VARIABLES ===
37676 : *
37677 : * We have to solve following system:
37678 : *
37679 : * [ -(H+Dh+Rh) Ah' ] [ Xh ] [ Bh ]
37680 : * [ -(Dz+Rz) Az' ] [ Xz ] = [ Bz ]
37681 : * [ Ah Az E ] [ Y ] [ By ]
37682 : *
37683 : * with Xh being NMain-dimensional vector, Xz being NSlack-dimensional vector, constraint
37684 : * matrix A being divided into non-slack and slack parts Ah and Az (and Ah, in turn, being
37685 : * divided into sparse and dense parts), Rh and Rz being diagonal regularization matrix,
37686 : * Y being M-dimensional vector.
37687 : *
37688 : * NOTE: due to definition of slack variables following holds: for any diagonal matrix W
37689 : * a product Az*W*Az' is a diagonal matrix.
37690 : *
37691 : * From the second line we get
37692 : *
37693 : * Xz = inv(Dz+Rz)*Az'*y - inv(Dz+Rz)*Bz
37694 : * = inv(Dz+Rz)*Az'*y - BzWave
37695 : *
37696 : * Using this value for Zx, third line gives us
37697 : *
37698 : * Y = inv(E+Az*inv(Dz+Rz)*Az')*(By+Az*BzWave-Ah*Xh)
37699 : * = inv(EWave)*(ByWave-Ah*Xh)
37700 : * with EWave = E+Az*inv(Dz+Rz)*Az' and ByWave = By+Az*BzWave
37701 : *
37702 : * Finally, first line gives us
37703 : *
37704 : * Xh = -inv(H+Dh+Rh+Ah'*inv(EWave)*Ah)*(Bh-Ah'*inv(EWave)*ByWave)
37705 : * = -inv(HWave)*BhWave
37706 : * with HWave = H+Dh+Rh+Ah'*inv(EWave)*Ah and BhWave = Bh-Ah'*inv(EWave)*ByWave
37707 : *
37708 : * In order to prepare factorization we need to compute:
37709 : * (a) diagonal matrices Dh, Rh, Dz and Rz (and precomputed inverse of Dz+Rz)
37710 : * (b) EWave
37711 : * (c) HWave
37712 : *
37713 : * === SPECIAL HANDLING OF FROZEN VARIABLES ===
37714 : *
37715 : * Frozen variables result in zero steps, i.e. zero components of Xh and Xz.
37716 : * It could be implemented by explicit modification of KKT system (zeroing out
37717 : * columns/rows of KKT matrix, rows of right part, putting 1's to diagonal).
37718 : *
37719 : * However, it is possible to do without actually modifying quadratic term and
37720 : * constraints:
37721 : * * freezing elements of Xz can be implemented by zeroing out corresponding
37722 : * columns of inv(Dz+Rz) because Az always appears in computations along with diagonal Dz+Rz.
37723 : * * freezing elements of Xh is a bit more complex - it needs:
37724 : * * zeroing out columns/rows of HWave and setting up unit diagonal prior to solving for Xh
37725 : * * explicitly zeroing out computed elements of Xh prior to computing Y and Xz
37726 : */
37727 0 : rvectorsetlengthatleast(&state->factregdhrh, nmain, _state);
37728 0 : rvectorsetlengthatleast(&state->factinvregdzrz, nslack, _state);
37729 0 : for(i=0; i<=n-1; i++)
37730 : {
37731 0 : v = (double)(0);
37732 0 : if( ae_fp_greater(alpha0,(double)(0)) )
37733 : {
37734 0 : v = v+alpha0*d->ptr.p_double[i];
37735 : }
37736 0 : if( ae_fp_greater(alpha11,(double)(0)) )
37737 : {
37738 0 : v = v+alpha11;
37739 : }
37740 0 : v = v+state->diagr.ptr.p_double[i];
37741 0 : v = v+dampeps;
37742 0 : ae_assert(ae_fp_greater(v,(double)(0)), "VIPMFactorize: integrity check failed, degenerate diagonal matrix", _state);
37743 0 : if( i>=nmain )
37744 : {
37745 0 : if( !state->isfrozen.ptr.p_bool[i] )
37746 : {
37747 0 : state->factinvregdzrz.ptr.p_double[i-nmain] = 1/v;
37748 : }
37749 : else
37750 : {
37751 0 : state->factinvregdzrz.ptr.p_double[i-nmain] = 0.0;
37752 : }
37753 : }
37754 : else
37755 : {
37756 0 : state->factregdhrh.ptr.p_double[i] = v;
37757 : }
37758 : }
37759 :
37760 : /*
37761 : * Now we are ready to compute EWave
37762 : */
37763 0 : rvectorsetlengthatleast(&state->factregewave, m, _state);
37764 0 : for(i=0; i<=m-1; i++)
37765 : {
37766 :
37767 : /*
37768 : * Compute diagonal element of E
37769 : */
37770 0 : v = (double)(0);
37771 0 : if( ae_fp_greater(beta0,(double)(0)) )
37772 : {
37773 0 : v = v+beta0*e->ptr.p_double[i];
37774 : }
37775 0 : if( ae_fp_greater(beta11,(double)(0)) )
37776 : {
37777 0 : v = v+beta11;
37778 : }
37779 0 : v = v+dampeps;
37780 0 : ae_assert(ae_fp_greater(v,(double)(0)), "VIPMFactorize: integrity check failed, degenerate diagonal matrix", _state);
37781 :
37782 : /*
37783 : * Compute diagonal modification Az*inv(Dz)*Az'
37784 : */
37785 0 : k0 = state->combinedaslack.ridx.ptr.p_int[i];
37786 0 : k1 = state->combinedaslack.ridx.ptr.p_int[i+1]-1;
37787 0 : for(k=k0; k<=k1; k++)
37788 : {
37789 0 : vv = state->combinedaslack.vals.ptr.p_double[k];
37790 0 : v = v+vv*vv*state->factinvregdzrz.ptr.p_double[state->combinedaslack.idx.ptr.p_int[k]];
37791 : }
37792 :
37793 : /*
37794 : * Save EWave
37795 : */
37796 0 : state->factregewave.ptr.p_double[i] = v;
37797 : }
37798 :
37799 : /*
37800 : * Now we are ready to compute HWave:
37801 : * * store H
37802 : * * add Dh
37803 : * * add Ah'*inv(EWave)*Ah
37804 : */
37805 0 : rmatrixsetlengthatleast(&state->factdensehaug, nmain, nmain, _state);
37806 0 : ae_assert(state->hkind==0, "VIPMFactorize: unexpected HKind", _state);
37807 0 : rmatrixcopy(nmain, nmain, &state->denseh, 0, 0, &state->factdensehaug, 0, 0, _state);
37808 0 : for(i=0; i<=nmain-1; i++)
37809 : {
37810 0 : state->factdensehaug.ptr.pp_double[i][i] = state->factdensehaug.ptr.pp_double[i][i]+state->factregdhrh.ptr.p_double[i];
37811 : }
37812 0 : if( msparse>0 )
37813 : {
37814 :
37815 : /*
37816 : * Handle sparse part of Ah in Ah'*inv(EWave)*Ah
37817 : */
37818 0 : for(i=0; i<=msparse-1; i++)
37819 : {
37820 0 : v = 1.0/state->factregewave.ptr.p_double[i];
37821 0 : k0 = state->sparseamain.ridx.ptr.p_int[i];
37822 0 : k1 = state->sparseamain.ridx.ptr.p_int[i+1]-1;
37823 0 : for(ka=k0; ka<=k1; ka++)
37824 : {
37825 0 : ja = state->sparseamain.idx.ptr.p_int[ka];
37826 0 : va = state->sparseamain.vals.ptr.p_double[ka];
37827 0 : for(kb=k0; kb<=ka; kb++)
37828 : {
37829 0 : jb = state->sparseamain.idx.ptr.p_int[kb];
37830 0 : vb = state->sparseamain.vals.ptr.p_double[kb];
37831 0 : state->factdensehaug.ptr.pp_double[ja][jb] = state->factdensehaug.ptr.pp_double[ja][jb]+v*va*vb;
37832 : }
37833 : }
37834 : }
37835 : }
37836 0 : if( mdense>0 )
37837 : {
37838 :
37839 : /*
37840 : * Handle dense part of Ah in Ah'*inv(EWave)*Ah
37841 : */
37842 0 : rmatrixsetlengthatleast(&state->tmpr2, mdense, nmain, _state);
37843 0 : rmatrixcopy(mdense, nmain, &state->denseamain, 0, 0, &state->tmpr2, 0, 0, _state);
37844 0 : for(i=0; i<=mdense-1; i++)
37845 : {
37846 0 : v = 1.0/ae_sqrt(state->factregewave.ptr.p_double[msparse+i], _state);
37847 0 : for(j=0; j<=nmain-1; j++)
37848 : {
37849 0 : state->tmpr2.ptr.pp_double[i][j] = v*state->tmpr2.ptr.pp_double[i][j];
37850 : }
37851 : }
37852 0 : rmatrixsyrk(nmain, mdense, 1.0, &state->tmpr2, 0, 0, 2, 1.0, &state->factdensehaug, 0, 0, ae_false, _state);
37853 : }
37854 :
37855 : /*
37856 : * Zero out rows/cols of HWave corresponding to frozen variables, set up unit diagonal
37857 : */
37858 0 : rsetallocv(nmain, 1.0, &state->tmp0, _state);
37859 0 : for(i=0; i<=nmain-1; i++)
37860 : {
37861 0 : if( state->isfrozen.ptr.p_bool[i] )
37862 : {
37863 0 : state->tmp0.ptr.p_double[i] = 0.0;
37864 : }
37865 : }
37866 0 : for(i=0; i<=nmain-1; i++)
37867 : {
37868 0 : if( state->isfrozen.ptr.p_bool[i] )
37869 : {
37870 :
37871 : /*
37872 : * Entire row is nullified except for diagonal element
37873 : */
37874 0 : rsetr(i+1, 0.0, &state->factdensehaug, i, _state);
37875 0 : state->factdensehaug.ptr.pp_double[i][i] = 1.0;
37876 : }
37877 : else
37878 : {
37879 :
37880 : /*
37881 : * Only some components are nullified
37882 : */
37883 0 : rmergemulvr(i+1, &state->tmp0, &state->factdensehaug, i, _state);
37884 : }
37885 : }
37886 :
37887 : /*
37888 : * Compute Cholesky factorization of HWave
37889 : */
37890 0 : if( !spdmatrixcholesky(&state->factdensehaug, nmain, ae_false, _state) )
37891 : {
37892 0 : result = ae_false;
37893 0 : return result;
37894 : }
37895 0 : v = (double)(0);
37896 0 : for(i=0; i<=nmain-1; i++)
37897 : {
37898 0 : v = v+state->factdensehaug.ptr.pp_double[i][i];
37899 : }
37900 0 : if( !ae_isfinite(v, _state)||ae_fp_greater(v,badchol) )
37901 : {
37902 0 : result = ae_false;
37903 0 : return result;
37904 : }
37905 0 : state->factorizationpresent = ae_true;
37906 : }
37907 :
37908 : /*
37909 : * Sparse (M+N)x(M+N) factorization
37910 : */
37911 0 : if( state->factorizationtype==1 )
37912 : {
37913 :
37914 : /*
37915 : * Generate reduced KKT matrix
37916 : */
37917 0 : rallocv(n+m, &state->facttmpdiag, _state);
37918 0 : sparsecopybuf(&state->factsparsekkttmpl, &state->factsparsekkt, _state);
37919 0 : for(i=0; i<=n-1; i++)
37920 : {
37921 0 : ae_assert(state->factsparsekkt.didx.ptr.p_int[i]+1==state->factsparsekkt.uidx.ptr.p_int[i], "VIPMFactorize: integrity check failed, no diagonal element", _state);
37922 0 : v = state->factsparsekkt.vals.ptr.p_double[state->factsparsekkt.didx.ptr.p_int[i]];
37923 0 : vv = (double)(0);
37924 0 : if( ae_fp_greater(alpha0,(double)(0)) )
37925 : {
37926 0 : vv = vv+alpha0*d->ptr.p_double[i];
37927 : }
37928 0 : if( ae_fp_greater(alpha11,(double)(0)) )
37929 : {
37930 0 : vv = vv+alpha11;
37931 : }
37932 0 : vv = vv+state->diagr.ptr.p_double[i];
37933 0 : vv = vv+dampeps;
37934 0 : v = v-vv;
37935 0 : state->factsparsekkt.vals.ptr.p_double[state->factsparsekkt.didx.ptr.p_int[i]] = v;
37936 0 : state->facttmpdiag.ptr.p_double[i] = v;
37937 0 : ae_assert(ae_fp_less(v,(double)(0)), "VIPMFactorize: integrity check failed, degenerate diagonal matrix", _state);
37938 : }
37939 0 : for(i=0; i<=msparse+mdense-1; i++)
37940 : {
37941 0 : ae_assert(state->factsparsekkt.didx.ptr.p_int[n+i]+1==state->factsparsekkt.uidx.ptr.p_int[n+i], "VIPMFactorize: integrity check failed, no diagonal element", _state);
37942 0 : v = state->factsparsekkt.vals.ptr.p_double[state->factsparsekkt.didx.ptr.p_int[n+i]];
37943 0 : vv = (double)(0);
37944 0 : if( ae_fp_greater(beta0,(double)(0)) )
37945 : {
37946 0 : vv = vv+beta0*e->ptr.p_double[i];
37947 : }
37948 0 : if( ae_fp_greater(beta11,(double)(0)) )
37949 : {
37950 0 : vv = vv+beta11;
37951 : }
37952 0 : vv = vv+dampeps;
37953 0 : v = v+vv;
37954 0 : state->factsparsekkt.vals.ptr.p_double[state->factsparsekkt.didx.ptr.p_int[n+i]] = v;
37955 0 : state->facttmpdiag.ptr.p_double[n+i] = v;
37956 0 : ae_assert(ae_fp_greater(v,(double)(0)), "VIPMFactorize: integrity check failed, degenerate diagonal matrix", _state);
37957 : }
37958 :
37959 : /*
37960 : * Perform factorization
37961 : * Perform additional integrity check: LDLT should reproduce diagonal of initial KKT system with good precision
37962 : */
37963 0 : spsymmreload(&state->ldltanalysis, &state->factsparsekkt, _state);
37964 0 : spsymmsetmodificationstrategy(&state->ldltanalysis, 1, modeps, badchol, 0.0, 0.0, _state);
37965 0 : if( !spsymmfactorize(&state->ldltanalysis, &state->factsparsekkt, &state->factsparsediagd, &state->factsparsekktpivp, _state) )
37966 : {
37967 0 : result = ae_false;
37968 0 : return result;
37969 : }
37970 0 : for(i=0; i<=n+m-1; i++)
37971 : {
37972 0 : v = state->facttmpdiag.ptr.p_double[i];
37973 0 : state->facttmpdiag.ptr.p_double[i] = state->facttmpdiag.ptr.p_double[state->factsparsekktpivp.ptr.p_int[i]];
37974 0 : state->facttmpdiag.ptr.p_double[state->factsparsekktpivp.ptr.p_int[i]] = v;
37975 : }
37976 0 : sumsq = rdotv2(n+m, &state->facttmpdiag, _state);
37977 0 : errsq = (double)(0);
37978 0 : for(i=0; i<=n+m-1; i++)
37979 : {
37980 0 : v = (double)(0);
37981 0 : k0 = state->factsparsekkt.ridx.ptr.p_int[i];
37982 0 : k1 = state->factsparsekkt.didx.ptr.p_int[i];
37983 0 : for(k=k0; k<=k1; k++)
37984 : {
37985 0 : vv = state->factsparsekkt.vals.ptr.p_double[k];
37986 0 : v = v+state->factsparsediagd.ptr.p_double[state->factsparsekkt.idx.ptr.p_int[k]]*vv*vv;
37987 : }
37988 0 : errsq = errsq+ae_sqr(v-state->facttmpdiag.ptr.p_double[i], _state);
37989 : }
37990 0 : if( ae_fp_greater(ae_sqrt(errsq/(1+sumsq), _state),ae_sqrt(ae_machineepsilon, _state)) )
37991 : {
37992 0 : if( state->dotrace )
37993 : {
37994 0 : ae_trace("LDLT-diag-err= %0.3e (diagonal reproduction error)\n",
37995 0 : (double)(ae_sqrt(errsq/(1+sumsq), _state)));
37996 : }
37997 0 : result = ae_false;
37998 0 : return result;
37999 : }
38000 0 : state->factorizationpresent = ae_true;
38001 :
38002 : /*
38003 : * Trace
38004 : */
38005 0 : if( state->dotrace )
38006 : {
38007 0 : ae_trace("--- sparse KKT factorization report ----------------------------------------------------------------\n");
38008 0 : ae_trace("> diagonal terms D and E\n");
38009 0 : if( ae_fp_neq(alpha0,(double)(0)) )
38010 : {
38011 0 : v = ae_fabs(d->ptr.p_double[0], _state);
38012 0 : vv = ae_fabs(d->ptr.p_double[0], _state);
38013 0 : for(i=1; i<=n-1; i++)
38014 : {
38015 0 : v = ae_minreal(v, ae_fabs(d->ptr.p_double[i], _state), _state);
38016 0 : vv = ae_maxreal(vv, ae_fabs(d->ptr.p_double[i], _state), _state);
38017 : }
38018 0 : ae_trace("diagD = %0.3e (min) ... %0.3e (max)\n",
38019 : (double)(v),
38020 : (double)(vv));
38021 : }
38022 0 : if( m>0&&ae_fp_neq(beta0,(double)(0)) )
38023 : {
38024 0 : v = ae_fabs(e->ptr.p_double[0], _state);
38025 0 : vv = ae_fabs(e->ptr.p_double[0], _state);
38026 0 : for(i=1; i<=m-1; i++)
38027 : {
38028 0 : v = ae_minreal(v, ae_fabs(e->ptr.p_double[i], _state), _state);
38029 0 : vv = ae_maxreal(vv, ae_fabs(e->ptr.p_double[i], _state), _state);
38030 : }
38031 0 : ae_trace("diagE = %0.3e (min) ... %0.3e (max)\n",
38032 : (double)(v),
38033 : (double)(vv));
38034 : }
38035 0 : ae_trace("> LDLT factorization of entire KKT matrix\n");
38036 0 : v = ae_fabs(state->factsparsediagd.ptr.p_double[0], _state);
38037 0 : vv = ae_fabs(state->factsparsediagd.ptr.p_double[0], _state);
38038 0 : for(i=0; i<=n+m-1; i++)
38039 : {
38040 0 : v = ae_maxreal(v, ae_fabs(state->factsparsediagd.ptr.p_double[i], _state), _state);
38041 0 : vv = ae_minreal(vv, ae_fabs(state->factsparsediagd.ptr.p_double[i], _state), _state);
38042 : }
38043 0 : ae_trace("|D| = %0.3e (min) ... %0.3e (max)\n",
38044 : (double)(vv),
38045 : (double)(v));
38046 0 : v = 0.0;
38047 0 : for(i=0; i<=n+m-1; i++)
38048 : {
38049 0 : k0 = state->factsparsekkt.ridx.ptr.p_int[i];
38050 0 : k1 = state->factsparsekkt.didx.ptr.p_int[i];
38051 0 : for(k=k0; k<=k1; k++)
38052 : {
38053 0 : v = ae_maxreal(v, ae_fabs(state->factsparsekkt.vals.ptr.p_double[k], _state), _state);
38054 : }
38055 : }
38056 0 : ae_trace("max(|L|) = %0.3e\n",
38057 : (double)(v));
38058 0 : ae_trace("diag-err = %0.3e (diagonal reproduction error)\n",
38059 0 : (double)(ae_sqrt(errsq/(1+sumsq), _state)));
38060 : }
38061 : }
38062 :
38063 : /*
38064 : * Done, integrity control
38065 : */
38066 0 : ae_assert(state->factorizationpresent, "VIPMFactorize: integrity check failed", _state);
38067 0 : inc(&state->repncholesky, _state);
38068 0 : return result;
38069 : }
38070 :
38071 :
38072 : /*************************************************************************
38073 : A low-level function which solves KKT system whose regularized (!)
38074 : factorization was prepared by VIPMFactorize(). No iterative refinement is
38075 : performed.
38076 :
38077 : On input, right-hand-side is stored in DeltaXY; on output, solution replaces
38078 : DeltaXY.
38079 :
38080 : -- ALGLIB --
38081 : Copyright 01.11.2019 by Bochkanov Sergey
38082 : *************************************************************************/
38083 0 : static void vipmsolver_solvereducedkktsystem(vipmstate* state,
38084 : /* Real */ ae_vector* deltaxy,
38085 : ae_state *_state)
38086 : {
38087 : ae_int_t n;
38088 : ae_int_t nmain;
38089 : ae_int_t nslack;
38090 : ae_int_t m;
38091 : ae_int_t mdense;
38092 : ae_int_t msparse;
38093 : ae_int_t i;
38094 : ae_int_t j;
38095 : double v;
38096 :
38097 :
38098 0 : ae_assert(state->factorizationpresent, "VIPMSolve: integrity check failed - factorization is not present", _state);
38099 0 : ae_assert(state->factorizationtype==0||state->factorizationtype==1, "VIPMSolve: unexpected factorization type", _state);
38100 0 : n = state->n;
38101 0 : nmain = state->nmain;
38102 0 : nslack = n-nmain;
38103 0 : m = state->mdense+state->msparse;
38104 0 : mdense = state->mdense;
38105 0 : msparse = state->msparse;
38106 :
38107 : /*
38108 : * Dense solving
38109 : */
38110 0 : if( state->factorizationtype==0 )
38111 : {
38112 :
38113 : /*
38114 : * Compute
38115 : *
38116 : * BzWave = inv(Dz+Rz)*Bz
38117 : * ByWave = By+Az*BzWave
38118 : * BhWave = Bh-Ah'*inv(EWave)*ByWave
38119 : */
38120 0 : for(i=0; i<=nslack-1; i++)
38121 : {
38122 0 : deltaxy->ptr.p_double[nmain+i] = deltaxy->ptr.p_double[nmain+i]*state->factinvregdzrz.ptr.p_double[i];
38123 : }
38124 0 : sparsegemv(&state->combinedaslack, 1.0, 0, deltaxy, nmain, 1.0, deltaxy, n, _state);
38125 0 : rvectorsetlengthatleast(&state->tmp1, m, _state);
38126 0 : for(i=0; i<=m-1; i++)
38127 : {
38128 0 : state->tmp1.ptr.p_double[i] = deltaxy->ptr.p_double[n+i]/state->factregewave.ptr.p_double[i];
38129 : }
38130 0 : sparsegemv(&state->sparseamain, -1.0, 1, &state->tmp1, 0, 1.0, deltaxy, 0, _state);
38131 0 : rmatrixgemv(nmain, mdense, -1.0, &state->denseamain, 0, 0, 1, &state->tmp1, msparse, 1.0, deltaxy, 0, _state);
38132 :
38133 : /*
38134 : * Compute Xh = -inv(HWave)*BhWave.
38135 : * Zero out components corresponding to frozen variables.
38136 : */
38137 0 : for(i=0; i<=nmain-1; i++)
38138 : {
38139 0 : deltaxy->ptr.p_double[i] = -deltaxy->ptr.p_double[i];
38140 : }
38141 0 : rmatrixtrsv(nmain, &state->factdensehaug, 0, 0, ae_false, ae_false, 0, deltaxy, 0, _state);
38142 0 : rmatrixtrsv(nmain, &state->factdensehaug, 0, 0, ae_false, ae_false, 1, deltaxy, 0, _state);
38143 0 : for(i=0; i<=n-1; i++)
38144 : {
38145 0 : if( state->isfrozen.ptr.p_bool[i] )
38146 : {
38147 0 : deltaxy->ptr.p_double[i] = (double)(0);
38148 : }
38149 : }
38150 :
38151 : /*
38152 : * Compute Y = inv(EWave)*(ByWave-Ah*Xh)
38153 : */
38154 0 : sparsegemv(&state->sparseamain, -1.0, 0, deltaxy, 0, 1.0, deltaxy, n, _state);
38155 0 : rmatrixgemv(mdense, nmain, -1.0, &state->denseamain, 0, 0, 0, deltaxy, 0, 1.0, deltaxy, n+msparse, _state);
38156 0 : for(i=0; i<=m-1; i++)
38157 : {
38158 0 : deltaxy->ptr.p_double[n+i] = deltaxy->ptr.p_double[n+i]/state->factregewave.ptr.p_double[i];
38159 : }
38160 :
38161 : /*
38162 : * Compute Xz = -(BzWave - inv(Dz+Rz)*Az'*y)
38163 : */
38164 0 : rvectorsetlengthatleast(&state->tmp0, nslack, _state);
38165 0 : for(i=0; i<=nslack-1; i++)
38166 : {
38167 0 : state->tmp0.ptr.p_double[i] = (double)(0);
38168 : }
38169 0 : sparsegemv(&state->combinedaslack, 1.0, 1, deltaxy, n, 1.0, &state->tmp0, 0, _state);
38170 0 : for(i=0; i<=nslack-1; i++)
38171 : {
38172 0 : deltaxy->ptr.p_double[nmain+i] = -(deltaxy->ptr.p_double[nmain+i]-state->factinvregdzrz.ptr.p_double[i]*state->tmp0.ptr.p_double[i]);
38173 : }
38174 :
38175 : /*
38176 : * Done
38177 : */
38178 0 : return;
38179 : }
38180 :
38181 : /*
38182 : * Sparse solving
38183 : */
38184 0 : if( state->factorizationtype==1 )
38185 : {
38186 :
38187 : /*
38188 : * Solve sparse KKT system given by its triangular factorization
38189 : */
38190 0 : for(i=0; i<=n-1; i++)
38191 : {
38192 0 : ae_assert(state->factsparsekkt.didx.ptr.p_int[i]+1==state->factsparsekkt.uidx.ptr.p_int[i]&&state->factsparsekkt.vals.ptr.p_double[state->factsparsekkt.didx.ptr.p_int[i]]!=0.0, "VIPMSolve: degenerate KKT system encountered", _state);
38193 : }
38194 0 : for(i=0; i<=n+m-1; i++)
38195 : {
38196 0 : j = state->factsparsekktpivp.ptr.p_int[i];
38197 0 : v = deltaxy->ptr.p_double[i];
38198 0 : deltaxy->ptr.p_double[i] = deltaxy->ptr.p_double[j];
38199 0 : deltaxy->ptr.p_double[j] = v;
38200 : }
38201 0 : sparsetrsv(&state->factsparsekkt, ae_false, ae_false, 0, deltaxy, _state);
38202 0 : for(i=0; i<=n+m-1; i++)
38203 : {
38204 0 : if( ae_fp_neq(state->factsparsediagd.ptr.p_double[i],(double)(0)) )
38205 : {
38206 0 : deltaxy->ptr.p_double[i] = deltaxy->ptr.p_double[i]/state->factsparsediagd.ptr.p_double[i];
38207 : }
38208 : else
38209 : {
38210 0 : deltaxy->ptr.p_double[i] = 0.0;
38211 : }
38212 : }
38213 0 : sparsetrsv(&state->factsparsekkt, ae_false, ae_false, 1, deltaxy, _state);
38214 0 : for(i=n+m-1; i>=0; i--)
38215 : {
38216 0 : j = state->factsparsekktpivp.ptr.p_int[i];
38217 0 : v = deltaxy->ptr.p_double[i];
38218 0 : deltaxy->ptr.p_double[i] = deltaxy->ptr.p_double[j];
38219 0 : deltaxy->ptr.p_double[j] = v;
38220 : }
38221 0 : for(i=0; i<=n-1; i++)
38222 : {
38223 0 : if( state->isfrozen.ptr.p_bool[i] )
38224 : {
38225 0 : deltaxy->ptr.p_double[i] = (double)(0);
38226 : }
38227 : }
38228 :
38229 : /*
38230 : * Done
38231 : */
38232 0 : return;
38233 : }
38234 :
38235 : /*
38236 : *
38237 : */
38238 0 : ae_assert(ae_false, "VIPMSolve: integrity check failed - unexpected factorization", _state);
38239 : }
38240 :
38241 :
38242 : /*************************************************************************
38243 : Generates precomputed temporary vectors and KKT factorization at the
38244 : beginning of the current iteration.
38245 :
38246 : This function uses representation of KKT system inspired by Vanderbei
38247 : slack variable approach, but with additional regularization being applied
38248 : all along computations.
38249 :
38250 : On successful factorization returns True; on failure returns False - it is
38251 : recommended to increase regularization parameter and try one more time.
38252 :
38253 : --- DESCRIPTION ----------------------------------------------------------
38254 :
38255 : Initial KKT system proposed by Vanderbei has following structure:
38256 :
38257 : (1) -DS*deltaT - I*deltaS = -mu/T + s + DELTAT*DELTAS/T = -GammaS
38258 : (2) -DZ*deltaG - I*deltaZ = -mu/G + z + DELTAG*DELTAZ/G = -GammaZ
38259 : (3) -DQ*deltaP - I*deltaQ = -mu/P + q + DELTAP*DELTAQ/P = -GammaQ
38260 : (4) -DW*deltaV - I*deltaW = -mu/V + w + DELTAV*DELTAW/V = -GammaW
38261 : (5) -I*deltaY - I*deltaQ + I*deltaV = y-q+v = Beta
38262 : (6) -H*deltaX +A'*deltaY + I*deltaZ - I*deltaS = c-A'*y-z+s+H*x = Sigma
38263 : (7) A*deltaX - I*deltaW = b-A*x+w = Rho
38264 : (8) I*deltaX - I*deltaG = l-x+g = Nu
38265 : (9) -I*deltaX - I*deltaT = -u+x+t = -Tau
38266 : (10) -I*deltaW - I*deltaP = -r+w+p = -Alpha
38267 :
38268 : where
38269 :
38270 : DS = diag(S/T)
38271 : DZ = diag(Z/G)
38272 : DQ = diag(Q/P)
38273 : DW = diag(W/V)
38274 :
38275 : This linear system is actually symmetric indefinite one, that can be
38276 : regularized by modifying equations (5), (6), (7), (8), (9), (10):
38277 :
38278 : (5) -I*deltaY - I*deltaQ + I*deltaV -REG*deltaW= y+q-v+REG*w = Beta
38279 : (6) -(H+REG)*deltaX +A'*deltaY + I*deltaZ - I*deltaS = c-A'*y-z+s+(H+REG)*x = Sigma
38280 : (7) A*deltaX - I*deltaW +REG*deltaY= b-A*x+w-REG*y = Rho
38281 : (8) I*deltaX - I*deltaG +REG*deltaZ= l-x+g-REG*z = Nu
38282 : (9) -I*deltaX - I*deltaT +REG*deltaS= -u+x+t-REG*s = -Tau
38283 : (10) -I*deltaW - I*deltaP +REG*deltaQ= -r+w+p-REG*q = -Alpha
38284 :
38285 : NOTE: regularizing equations (5)-(10) seems to be beneficial because their
38286 : coefficients are well-normalized, usually having unit scale. Contrary
38287 : to that, equations (1)-(4) are wildly nonnormalized, and regularization
38288 : ruins algorithm convergence.
38289 :
38290 : From (1), (2), (3) and (4) we obtain
38291 :
38292 : deltaT = (GammaS-I*deltaS)/DS
38293 : deltaG = (GammaZ-I*deltaZ)/DZ
38294 : deltaP = (GammaQ-I*deltaQ)/DQ
38295 : deltaV = (GammaW-I*deltaW)/DW
38296 :
38297 : and substitute them to equations to obtain
38298 :
38299 : (5) -I*deltaY - I*deltaQ - (inv(DW)+REG)*deltaW = Beta-inv(DW)*GammaW = BetaCap
38300 : (8) I*deltaX + (inv(DZ)+REG)*deltaZ = Nu+inv(DZ)*GammaZ = NuCap
38301 : (9) -I*deltaX + (inv(DS)+REG)*deltaS = -(Tau-inv(DS)*GammaS) = -TauCap
38302 : (10) -I*deltaW + (inv(DQ)+REG)*deltaQ = -(Alpha-inv(DQ)*GammaQ) = -AlphaCap
38303 : (6) A'*deltaY + I*deltaZ - I*deltaS - (H+REG)*deltaX = c-A'*y-z+s+(H+REG)*x = Sigma
38304 : (7) REG*deltaY + A*deltaX - I*deltaW = b-A*x+w-REG*y = Rho
38305 :
38306 : then, we obtain (here IRI stands for Invert-Regularize-Invert)
38307 :
38308 : DQIRI = inv(inv(DQ)+REG)
38309 : DZIRI = inv(inv(DZ)+REG)
38310 : DSIRI = inv(inv(DS)+REG)
38311 :
38312 : deltaQ = (I*deltaW-AlphaCap)*DQIRI
38313 : deltaZ = (NuCap-I*deltaX)*DZIRI
38314 : deltaS = (I*deltaX-TauCap)*DSIRI
38315 :
38316 : DWIR = inv(DW)+REG
38317 :
38318 : and after substitution
38319 :
38320 : (5) -I*deltaY - (DQIRI+DWIR)*deltaW = BetaCap-DQIRI*AlphaCap
38321 : (6) A'*deltaY - (H+REG+DSIRI+DZIRI)*deltaX = Sigma-DSIRI*TauCap-DZIRI*NuCap
38322 : (7) REG*deltaY + A*deltaX - I*deltaW = Rho
38323 :
38324 : finally, we obtain
38325 :
38326 : DE = inv(DQIRI+DWIR)
38327 : DER = DE+REG
38328 : DDR = DSIRI+DZIRI+REG
38329 : deltaW = -(BetaCap-DQIRI*AlphaCap+I*deltaY)*DE
38330 :
38331 : and after substitution
38332 :
38333 : (6) -(H+DDR)*deltaX + A'*deltaY = Sigma-DSIRI*TauCap-DZIRI*NuCap
38334 : (7) A*deltaX + DER*deltaY = Rho-DE*(BetaCap-DQIRI*AlphaCap)
38335 :
38336 : -- ALGLIB --
38337 : Copyright 01.11.2020 by Bochkanov Sergey
38338 : *************************************************************************/
38339 0 : static ae_bool vipmsolver_vipmprecomputenewtonfactorization(vipmstate* state,
38340 : vipmvars* v0,
38341 : double regeps,
38342 : double modeps,
38343 : double dampeps,
38344 : double dampfree,
38345 : ae_state *_state)
38346 : {
38347 : ae_int_t n;
38348 : ae_int_t m;
38349 : ae_int_t i;
38350 : ae_bool result;
38351 :
38352 :
38353 0 : n = state->n;
38354 0 : m = state->mdense+state->msparse;
38355 0 : rsetallocv(n, 0.0, &state->diagdz, _state);
38356 0 : rsetallocv(n, 0.0, &state->diagdzi, _state);
38357 0 : rsetallocv(n, 0.0, &state->diagdziri, _state);
38358 0 : rsetallocv(n, 0.0, &state->diagds, _state);
38359 0 : rsetallocv(n, 0.0, &state->diagdsi, _state);
38360 0 : rsetallocv(n, 0.0, &state->diagdsiri, _state);
38361 0 : rsetallocv(m, 0.0, &state->diagdw, _state);
38362 0 : rsetallocv(m, 0.0, &state->diagdwi, _state);
38363 0 : rsetallocv(m, 0.0, &state->diagdwir, _state);
38364 0 : rsetallocv(m, 0.0, &state->diagdq, _state);
38365 0 : rsetallocv(m, 0.0, &state->diagdqi, _state);
38366 0 : rsetallocv(m, 0.0, &state->diagdqiri, _state);
38367 0 : rallocv(n, &state->diagddr, _state);
38368 0 : rallocv(m, &state->diagde, _state);
38369 0 : rallocv(m, &state->diagder, _state);
38370 :
38371 : /*
38372 : * Handle temporary matrices arising due to box constraints
38373 : */
38374 0 : for(i=0; i<=n-1; i++)
38375 : {
38376 :
38377 : /*
38378 : * Lower bound: G*inv(Z) and Z*inv(G)
38379 : */
38380 0 : if( state->hasgz.ptr.p_bool[i] )
38381 : {
38382 0 : ae_assert(v0->g.ptr.p_double[i]>0.0&&v0->z.ptr.p_double[i]>0.0, "VIPMPrecomputeNewtonFactorization: integrity failure - G[i]<=0 or Z[i]<=0", _state);
38383 0 : state->diagdz.ptr.p_double[i] = v0->z.ptr.p_double[i]/v0->g.ptr.p_double[i];
38384 0 : state->diagdzi.ptr.p_double[i] = 1/state->diagdz.ptr.p_double[i];
38385 0 : state->diagdziri.ptr.p_double[i] = 1/(state->diagdzi.ptr.p_double[i]+regeps);
38386 : }
38387 : else
38388 : {
38389 0 : ae_assert(v0->g.ptr.p_double[i]==0.0&&v0->z.ptr.p_double[i]==0.0, "VIPMPrecomputeNewtonFactorization: integrity failure - G[i]<>0 or Z[i]<>0 for absent lower bound", _state);
38390 : }
38391 :
38392 : /*
38393 : * Upper bound: T*inv(S) and S*inv(T)
38394 : */
38395 0 : if( state->hasts.ptr.p_bool[i] )
38396 : {
38397 0 : ae_assert(v0->t.ptr.p_double[i]>0.0&&v0->s.ptr.p_double[i]>0.0, "VIPMPrecomputeNewtonFactorization: integrity failure - T[i]<=0 or S[i]<=0", _state);
38398 0 : state->diagds.ptr.p_double[i] = v0->s.ptr.p_double[i]/v0->t.ptr.p_double[i];
38399 0 : state->diagdsi.ptr.p_double[i] = 1/state->diagds.ptr.p_double[i];
38400 0 : state->diagdsiri.ptr.p_double[i] = 1/(state->diagdsi.ptr.p_double[i]+regeps);
38401 : }
38402 : else
38403 : {
38404 0 : ae_assert(v0->t.ptr.p_double[i]==0.0&&v0->s.ptr.p_double[i]==0.0, "VIPMPrecomputeNewtonFactorization: integrity failure - T[i]<>0 or S[i]<>0 for absent upper bound", _state);
38405 : }
38406 :
38407 : /*
38408 : * Diagonal term D
38409 : */
38410 0 : state->diagddr.ptr.p_double[i] = state->diagdziri.ptr.p_double[i]+state->diagdsiri.ptr.p_double[i]+regeps;
38411 0 : if( !state->hasgz.ptr.p_bool[i]&&!state->hasts.ptr.p_bool[i] )
38412 : {
38413 0 : state->diagddr.ptr.p_double[i] = state->diagddr.ptr.p_double[i]+dampfree;
38414 : }
38415 : }
38416 :
38417 : /*
38418 : * Handle temporary matrices arising due to linear constraints: with lower bound B[]
38419 : * or with lower and upper bounds.
38420 : */
38421 0 : for(i=0; i<=m-1; i++)
38422 : {
38423 :
38424 : /*
38425 : * Lower bound
38426 : */
38427 0 : if( state->haswv.ptr.p_bool[i] )
38428 : {
38429 0 : ae_assert(v0->v.ptr.p_double[i]>0.0&&v0->w.ptr.p_double[i]>0.0, "VIPMPrecomputeNewtonFactorization: integrity failure - V[i]<=0 or W[i]<=0", _state);
38430 0 : state->diagdw.ptr.p_double[i] = v0->w.ptr.p_double[i]/v0->v.ptr.p_double[i];
38431 0 : state->diagdwi.ptr.p_double[i] = 1/state->diagdw.ptr.p_double[i];
38432 0 : state->diagdwir.ptr.p_double[i] = state->diagdwi.ptr.p_double[i]+regeps;
38433 : }
38434 : else
38435 : {
38436 0 : ae_assert(v0->v.ptr.p_double[i]==0.0&&v0->w.ptr.p_double[i]==0.0, "VIPMPrecomputeNewtonFactorization: integrity failure - V[i]<>0 or W[i]<>0 for linear equality constraint", _state);
38437 : }
38438 :
38439 : /*
38440 : * Upper bound
38441 : */
38442 0 : if( state->haspq.ptr.p_bool[i] )
38443 : {
38444 0 : ae_assert(v0->p.ptr.p_double[i]>0.0&&v0->q.ptr.p_double[i]>0.0, "VIPMPrecomputeNewtonFactorization: integrity failure - P[i]<=0 or Q[i]<=0", _state);
38445 0 : state->diagdq.ptr.p_double[i] = v0->q.ptr.p_double[i]/v0->p.ptr.p_double[i];
38446 0 : state->diagdqi.ptr.p_double[i] = 1/state->diagdq.ptr.p_double[i];
38447 0 : state->diagdqiri.ptr.p_double[i] = 1/(state->diagdqi.ptr.p_double[i]+regeps);
38448 : }
38449 : else
38450 : {
38451 0 : ae_assert(v0->p.ptr.p_double[i]==0.0&&v0->q.ptr.p_double[i]==0.0, "VIPMPrecomputeNewtonFactorization: integrity failure - P[i]<>0 or Q[i]<>0 for absent linear constraint", _state);
38452 : }
38453 :
38454 : /*
38455 : * Diagonal term E
38456 : */
38457 0 : if( state->haswv.ptr.p_bool[i]||state->haspq.ptr.p_bool[i] )
38458 : {
38459 0 : state->diagde.ptr.p_double[i] = 1/(state->diagdwir.ptr.p_double[i]+state->diagdqiri.ptr.p_double[i]);
38460 : }
38461 : else
38462 : {
38463 0 : state->diagde.ptr.p_double[i] = 0.0;
38464 : }
38465 0 : state->diagder.ptr.p_double[i] = state->diagde.ptr.p_double[i]+regeps;
38466 : }
38467 :
38468 : /*
38469 : * Perform factorization
38470 : */
38471 0 : result = vipmsolver_vipmfactorize(state, 1.0, &state->diagddr, 1.0, &state->diagder, 0.0, 0.0, modeps, dampeps, _state);
38472 0 : return result;
38473 : }
38474 :
38475 :
38476 : /*************************************************************************
38477 : Solves KKT system stored in VIPMState with user-passed RHS. The solution
38478 : X is either copied to Sol (AlphaSol=0) or added Sol:=AlphaSol*Sol+X.
38479 :
38480 : -- ALGLIB --
38481 : Copyright 01.11.2019 by Bochkanov Sergey
38482 : *************************************************************************/
38483 0 : static void vipmsolver_solvekktsystem(vipmstate* state,
38484 : vipmrighthandside* rhs,
38485 : vipmvars* sol,
38486 : ae_state *_state)
38487 : {
38488 : ae_int_t n;
38489 : ae_int_t m;
38490 : ae_int_t i;
38491 :
38492 :
38493 0 : n = state->n;
38494 0 : m = state->mdense+state->msparse;
38495 :
38496 : /*
38497 : * Compute elimination temporaries
38498 : *
38499 : * RhsAlphaCap = RhsAlpha - InvDQ*GammaQ
38500 : * RhsNuCap = RhsNu + InvDZ*GammaZ
38501 : * RhsTauCap = RhsTau - InvDS*GammaS
38502 : * RhsBetaCap = RhsBeta - InvDW*GammaW
38503 : */
38504 0 : rallocv(n, &state->rhsnucap, _state);
38505 0 : rallocv(n, &state->rhstaucap, _state);
38506 0 : rallocv(m, &state->rhsbetacap, _state);
38507 0 : rallocv(m, &state->rhsalphacap, _state);
38508 0 : for(i=0; i<=m-1; i++)
38509 : {
38510 0 : state->rhsalphacap.ptr.p_double[i] = rhs->alpha.ptr.p_double[i]-state->diagdqi.ptr.p_double[i]*rhs->gammaq.ptr.p_double[i];
38511 : }
38512 0 : for(i=0; i<=n-1; i++)
38513 : {
38514 0 : state->rhsnucap.ptr.p_double[i] = rhs->nu.ptr.p_double[i]+state->diagdzi.ptr.p_double[i]*rhs->gammaz.ptr.p_double[i];
38515 : }
38516 0 : for(i=0; i<=n-1; i++)
38517 : {
38518 0 : state->rhstaucap.ptr.p_double[i] = rhs->tau.ptr.p_double[i]-state->diagdsi.ptr.p_double[i]*rhs->gammas.ptr.p_double[i];
38519 : }
38520 0 : for(i=0; i<=m-1; i++)
38521 : {
38522 0 : state->rhsbetacap.ptr.p_double[i] = rhs->beta.ptr.p_double[i]-state->diagdwi.ptr.p_double[i]*rhs->gammaw.ptr.p_double[i];
38523 : }
38524 :
38525 : /*
38526 : * Solve reduced KKT system
38527 : */
38528 0 : rvectorsetlengthatleast(&state->deltaxy, n+m, _state);
38529 0 : for(i=0; i<=n-1; i++)
38530 : {
38531 0 : state->deltaxy.ptr.p_double[i] = rhs->sigma.ptr.p_double[i]-state->diagdziri.ptr.p_double[i]*state->rhsnucap.ptr.p_double[i]-state->diagdsiri.ptr.p_double[i]*state->rhstaucap.ptr.p_double[i];
38532 : }
38533 0 : for(i=0; i<=m-1; i++)
38534 : {
38535 0 : state->deltaxy.ptr.p_double[n+i] = rhs->rho.ptr.p_double[i]-state->diagde.ptr.p_double[i]*(state->rhsbetacap.ptr.p_double[i]-state->diagdqiri.ptr.p_double[i]*state->rhsalphacap.ptr.p_double[i]);
38536 : }
38537 0 : vipmsolver_solvereducedkktsystem(state, &state->deltaxy, _state);
38538 :
38539 : /*
38540 : * Perform backsubstitution
38541 : */
38542 0 : for(i=0; i<=n-1; i++)
38543 : {
38544 0 : sol->x.ptr.p_double[i] = state->deltaxy.ptr.p_double[i];
38545 0 : sol->s.ptr.p_double[i] = state->diagdsiri.ptr.p_double[i]*(sol->x.ptr.p_double[i]-state->rhstaucap.ptr.p_double[i]);
38546 0 : sol->z.ptr.p_double[i] = state->diagdziri.ptr.p_double[i]*(state->rhsnucap.ptr.p_double[i]-sol->x.ptr.p_double[i]);
38547 0 : sol->g.ptr.p_double[i] = state->diagdzi.ptr.p_double[i]*(rhs->gammaz.ptr.p_double[i]-sol->z.ptr.p_double[i]);
38548 0 : sol->t.ptr.p_double[i] = state->diagdsi.ptr.p_double[i]*(rhs->gammas.ptr.p_double[i]-sol->s.ptr.p_double[i]);
38549 : }
38550 0 : for(i=0; i<=m-1; i++)
38551 : {
38552 0 : sol->y.ptr.p_double[i] = state->deltaxy.ptr.p_double[n+i];
38553 0 : sol->w.ptr.p_double[i] = -state->diagde.ptr.p_double[i]*(state->rhsbetacap.ptr.p_double[i]-state->diagdqiri.ptr.p_double[i]*state->rhsalphacap.ptr.p_double[i]+sol->y.ptr.p_double[i]);
38554 0 : sol->q.ptr.p_double[i] = state->diagdqiri.ptr.p_double[i]*(sol->w.ptr.p_double[i]-state->rhsalphacap.ptr.p_double[i]);
38555 0 : sol->v.ptr.p_double[i] = state->diagdwi.ptr.p_double[i]*(rhs->gammaw.ptr.p_double[i]-sol->w.ptr.p_double[i]);
38556 0 : sol->p.ptr.p_double[i] = state->diagdqi.ptr.p_double[i]*(rhs->gammaq.ptr.p_double[i]-sol->q.ptr.p_double[i]);
38557 : }
38558 0 : }
38559 :
38560 :
38561 : /*************************************************************************
38562 : Compute VIPM step by solving KKT system.
38563 :
38564 : Returns False on failure to compute step direction with reasonable accuracy
38565 : (it is advised to terminate iterations immediately).
38566 :
38567 : -- ALGLIB --
38568 : Copyright 01.11.2019 by Bochkanov Sergey
38569 : *************************************************************************/
38570 0 : static ae_bool vipmsolver_vipmcomputestepdirection(vipmstate* state,
38571 : vipmvars* v0,
38572 : double muestimate,
38573 : vipmvars* vdestimate,
38574 : vipmvars* vdresult,
38575 : double reg,
38576 : ae_bool isdampepslarge,
38577 : ae_state *_state)
38578 : {
38579 : ae_int_t n;
38580 : ae_int_t m;
38581 : double vrhsprim2;
38582 : double vrhsdual2;
38583 : double vrhscmpl2;
38584 : double vresprim2;
38585 : double vresdual2;
38586 : double vrescmpl2;
38587 : double vrhspriminf;
38588 : double vrhsdualinf;
38589 : double vrespriminf;
38590 : double vresdualinf;
38591 : double badres;
38592 : double verybadres;
38593 : double residualgrowth;
38594 : ae_bool primaldestabilized;
38595 : ae_bool dualdestabilized;
38596 : ae_bool result;
38597 :
38598 :
38599 0 : n = state->n;
38600 0 : m = state->mdense+state->msparse;
38601 0 : badres = 1.01;
38602 0 : verybadres = 1.0E3;
38603 0 : result = ae_true;
38604 :
38605 : /*
38606 : * Initial solver report
38607 : */
38608 0 : if( state->dotrace )
38609 : {
38610 0 : ae_trace("--- detailed KKT solver report ---------------------------------------------------------------------\n");
38611 : }
38612 :
38613 : /*
38614 : * Solve KKT system with right-hand sides coming from primal, dual
38615 : * and complementary slackness conditions. Analyze solution,
38616 : * terminate immediately if primal/dual residuals are way too high.
38617 : */
38618 0 : vipmsolver_varsinitbyzero(vdresult, n, m, _state);
38619 0 : vipmsolver_rhscompute(state, v0, muestimate, vdestimate, &state->rhs, reg, _state);
38620 0 : vrhsprim2 = vipmsolver_rhsprimal2(&state->rhs, n, m, _state);
38621 0 : vrhsdual2 = vipmsolver_rhsdual2(&state->rhs, n, m, _state);
38622 0 : vrhscmpl2 = vipmsolver_rhscompl2(&state->rhs, n, m, _state);
38623 0 : vrhspriminf = vipmsolver_rhsprimalinf(&state->rhs, n, m, _state);
38624 0 : vrhsdualinf = vipmsolver_rhsdualinf(&state->rhs, n, m, _state);
38625 0 : if( state->dotrace )
38626 : {
38627 0 : ae_trace("> primal/dual/complementarity right-hand-side\n");
38628 0 : ae_trace("rhs-prim = %0.3e (2-norm)\n",
38629 : (double)(ae_sqrt(vrhsprim2, _state)));
38630 0 : ae_trace("rhs-dual = %0.3e (2-norm)\n",
38631 : (double)(ae_sqrt(vrhsdual2, _state)));
38632 0 : ae_trace("rhs-cmpl = %0.3e (2-norm)\n",
38633 : (double)(ae_sqrt(vrhscmpl2, _state)));
38634 : }
38635 0 : vipmsolver_solvekktsystem(state, &state->rhs, vdresult, _state);
38636 0 : vipmsolver_rhssubtract(state, &state->rhs, v0, vdresult, reg, _state);
38637 0 : vresprim2 = vipmsolver_rhsprimal2(&state->rhs, n, m, _state);
38638 0 : vresdual2 = vipmsolver_rhsdual2(&state->rhs, n, m, _state);
38639 0 : vrescmpl2 = vipmsolver_rhscompl2(&state->rhs, n, m, _state);
38640 0 : vrespriminf = vipmsolver_rhsprimalinf(&state->rhs, n, m, _state);
38641 0 : vresdualinf = vipmsolver_rhsdualinf(&state->rhs, n, m, _state);
38642 0 : if( state->dotrace )
38643 : {
38644 0 : ae_trace("> primal/dual/complementarity residuals compared with RHS\n");
38645 0 : ae_trace("res/rhs prim = %0.3e\n",
38646 0 : (double)(ae_sqrt(vresprim2/coalesce(vrhsprim2, (double)(1), _state), _state)));
38647 0 : ae_trace("res/rhs dual = %0.3e\n",
38648 0 : (double)(ae_sqrt(vresdual2/coalesce(vrhsdual2, (double)(1), _state), _state)));
38649 0 : ae_trace("res/rhs cmpl = %0.3e\n",
38650 0 : (double)(ae_sqrt(vrescmpl2/coalesce(vrhscmpl2, (double)(1), _state), _state)));
38651 0 : ae_trace("res/rhs all = %0.3e\n",
38652 0 : (double)(ae_sqrt((vresprim2+vresdual2+vrescmpl2)/coalesce(vrhsprim2+vrhsdual2+vrhscmpl2, (double)(1), _state), _state)));
38653 : }
38654 0 : primaldestabilized = ae_fp_less_eq(vrhspriminf,state->epsp)&&ae_fp_greater_eq(vrespriminf,ae_maxreal(verybadres*vrhspriminf, state->epsp, _state));
38655 0 : dualdestabilized = ae_fp_less_eq(vrhsdualinf,state->epsd)&&ae_fp_greater_eq(vresdualinf,ae_maxreal(verybadres*vrhsdualinf, state->epsd, _state));
38656 0 : residualgrowth = ae_sqrt((vresprim2+vresdual2+vrescmpl2)/coalesce(vrhsprim2+vrhsdual2+vrhscmpl2, (double)(1), _state), _state);
38657 0 : if( ((primaldestabilized||dualdestabilized)&&ae_fp_greater(residualgrowth,0.01*ae_sqrt(ae_machineepsilon, _state)))&&!isdampepslarge )
38658 : {
38659 0 : if( state->dotrace )
38660 : {
38661 0 : ae_trace("> primal/dual residual growth is too high, signaling presence of numerical errors\n");
38662 : }
38663 0 : result = ae_false;
38664 0 : return result;
38665 : }
38666 0 : if( ae_fp_greater(residualgrowth,badres) )
38667 : {
38668 0 : if( state->dotrace )
38669 : {
38670 0 : ae_trace("> total residual is too high, signaling presence of numerical errors\n");
38671 : }
38672 0 : result = ae_false;
38673 0 : return result;
38674 : }
38675 0 : return result;
38676 : }
38677 :
38678 :
38679 : /*************************************************************************
38680 : This function estimates primal and dual step lengths (subject to step
38681 : decay parameter, which should be in [0,1] range).
38682 :
38683 : Current version returns same step lengths for primal and dual steps.
38684 :
38685 : INPUT PARAMETERS:
38686 : State - solver state
38687 : V0 - current point (we ignore one stored in State.Current)
38688 : VS - step direction
38689 : StepDecay - decay parameter, the step is multiplied by this
38690 : coefficient. 1.0 corresponds to full step
38691 : length being returned. Values in (0,1] range.
38692 :
38693 : OUTPUT PARAMETERS:
38694 : AlphaP - primal step (after applying decay coefficient)
38695 : AlphaD - dual step (after applying decay coefficient)
38696 :
38697 : -- ALGLIB --
38698 : Copyright 01.11.2019 by Bochkanov Sergey
38699 : *************************************************************************/
38700 0 : static void vipmsolver_vipmcomputesteplength(vipmstate* state,
38701 : vipmvars* v0,
38702 : vipmvars* vs,
38703 : double stepdecay,
38704 : double* alphap,
38705 : double* alphad,
38706 : ae_state *_state)
38707 : {
38708 : ae_int_t n;
38709 : ae_int_t m;
38710 : ae_int_t i;
38711 : double alpha;
38712 :
38713 0 : *alphap = 0;
38714 0 : *alphad = 0;
38715 :
38716 0 : n = state->n;
38717 0 : m = state->mdense+state->msparse;
38718 0 : ae_assert(n==v0->n&&m==v0->m, "VIPMComputeStepLength: sizes mismatch", _state);
38719 0 : *alphap = (double)(1);
38720 0 : *alphad = (double)(1);
38721 0 : for(i=0; i<=n-1; i++)
38722 : {
38723 :
38724 : /*
38725 : * Primal
38726 : */
38727 0 : if( vs->g.ptr.p_double[i]<0.0 )
38728 : {
38729 0 : *alphap = safeminposrv(v0->g.ptr.p_double[i], -vs->g.ptr.p_double[i], *alphap, _state);
38730 : }
38731 0 : if( vs->t.ptr.p_double[i]<0.0 )
38732 : {
38733 0 : *alphap = safeminposrv(v0->t.ptr.p_double[i], -vs->t.ptr.p_double[i], *alphap, _state);
38734 : }
38735 :
38736 : /*
38737 : * Dual
38738 : */
38739 0 : if( vs->z.ptr.p_double[i]<0.0 )
38740 : {
38741 0 : *alphad = safeminposrv(v0->z.ptr.p_double[i], -vs->z.ptr.p_double[i], *alphad, _state);
38742 : }
38743 0 : if( vs->s.ptr.p_double[i]<0.0 )
38744 : {
38745 0 : *alphad = safeminposrv(v0->s.ptr.p_double[i], -vs->s.ptr.p_double[i], *alphad, _state);
38746 : }
38747 : }
38748 0 : for(i=0; i<=m-1; i++)
38749 : {
38750 :
38751 : /*
38752 : * Primal
38753 : */
38754 0 : if( vs->w.ptr.p_double[i]<0.0 )
38755 : {
38756 0 : *alphap = safeminposrv(v0->w.ptr.p_double[i], -vs->w.ptr.p_double[i], *alphap, _state);
38757 : }
38758 0 : if( vs->p.ptr.p_double[i]<0.0 )
38759 : {
38760 0 : *alphap = safeminposrv(v0->p.ptr.p_double[i], -vs->p.ptr.p_double[i], *alphap, _state);
38761 : }
38762 :
38763 : /*
38764 : * Dual
38765 : */
38766 0 : if( vs->v.ptr.p_double[i]<0.0 )
38767 : {
38768 0 : *alphad = safeminposrv(v0->v.ptr.p_double[i], -vs->v.ptr.p_double[i], *alphad, _state);
38769 : }
38770 0 : if( vs->q.ptr.p_double[i]<0.0 )
38771 : {
38772 0 : *alphad = safeminposrv(v0->q.ptr.p_double[i], -vs->q.ptr.p_double[i], *alphad, _state);
38773 : }
38774 : }
38775 :
38776 : /*
38777 : * Because we may solve QP problem, step length has to be same for primal and dual variables
38778 : */
38779 0 : alpha = ae_minreal(*alphap, *alphad, _state);
38780 :
38781 : /*
38782 : * Apply decay
38783 : */
38784 0 : *alphap = stepdecay*alpha;
38785 0 : *alphad = stepdecay*alpha;
38786 0 : }
38787 :
38788 :
38789 : /*************************************************************************
38790 : This function performs IPM step, updates iteration counts and performs
38791 : following additional checks:
38792 : * it monitors status of box/linear constraints and smoothly drops ones
38793 : with too large bounds (a variable or linear sum is well below constraint
38794 : bound for several iterations)
38795 :
38796 : INPUT PARAMETERS:
38797 : State - solver state
38798 : AlphaP - primal step to perform
38799 : AlphaD - dual step to perform
38800 :
38801 : OUTPUT PARAMETERS:
38802 :
38803 : -- ALGLIB --
38804 : Copyright 01.08.2020 by Bochkanov Sergey
38805 : *************************************************************************/
38806 0 : static void vipmsolver_vipmperformstep(vipmstate* state,
38807 : double alphap,
38808 : double alphad,
38809 : ae_state *_state)
38810 : {
38811 :
38812 :
38813 :
38814 : /*
38815 : * Perform step
38816 : */
38817 0 : vipmsolver_varsaddstep(&state->current, &state->deltacorr, alphap, alphad, _state);
38818 :
38819 : /*
38820 : * Update iterations count
38821 : */
38822 0 : inc(&state->repiterationscount, _state);
38823 0 : }
38824 :
38825 :
38826 : /*************************************************************************
38827 : Compute primal/dual errors and complementarity gap
38828 :
38829 : -- ALGLIB --
38830 : Copyright 01.11.2019 by Bochkanov Sergey
38831 : *************************************************************************/
38832 0 : static void vipmsolver_computeerrors(vipmstate* state,
38833 : double* errp2,
38834 : double* errd2,
38835 : double* errpinf,
38836 : double* errdinf,
38837 : double* egap,
38838 : ae_state *_state)
38839 : {
38840 : ae_int_t n;
38841 : ae_int_t m;
38842 : ae_int_t i;
38843 : ae_int_t cntp2;
38844 : ae_int_t cntd2;
38845 : double v;
38846 :
38847 0 : *errp2 = 0;
38848 0 : *errd2 = 0;
38849 0 : *errpinf = 0;
38850 0 : *errdinf = 0;
38851 0 : *egap = 0;
38852 :
38853 0 : n = state->n;
38854 0 : m = state->mdense+state->msparse;
38855 :
38856 : /*
38857 : * Compute primal and dual infeasibilities
38858 : */
38859 0 : vipmsolver_vipmmultiply(state, &state->current.x, &state->current.y, &state->tmphx, &state->tmpax, &state->tmpaty, _state);
38860 0 : cntp2 = 0;
38861 0 : *errp2 = (double)(0);
38862 0 : *errpinf = (double)(0);
38863 0 : for(i=0; i<=m-1; i++)
38864 : {
38865 0 : v = state->tmpax.ptr.p_double[i]-state->current.w.ptr.p_double[i]-state->b.ptr.p_double[i];
38866 0 : *errp2 = *errp2+v*v;
38867 0 : *errpinf = ae_maxreal(*errpinf, ae_fabs(v, _state), _state);
38868 0 : inc(&cntp2, _state);
38869 0 : if( state->haspq.ptr.p_bool[i] )
38870 : {
38871 0 : v = state->current.w.ptr.p_double[i]+state->current.p.ptr.p_double[i]-state->r.ptr.p_double[i];
38872 0 : *errp2 = *errp2+v*v;
38873 0 : *errpinf = ae_maxreal(*errpinf, ae_fabs(v, _state), _state);
38874 0 : inc(&cntp2, _state);
38875 : }
38876 : }
38877 0 : for(i=0; i<=n-1; i++)
38878 : {
38879 0 : if( state->hasgz.ptr.p_bool[i] )
38880 : {
38881 0 : v = state->current.x.ptr.p_double[i]-state->current.g.ptr.p_double[i]-state->bndl.ptr.p_double[i];
38882 0 : *errp2 = *errp2+v*v;
38883 0 : *errpinf = ae_maxreal(*errpinf, ae_fabs(v, _state), _state);
38884 0 : inc(&cntp2, _state);
38885 : }
38886 0 : if( state->hasts.ptr.p_bool[i] )
38887 : {
38888 0 : v = state->current.x.ptr.p_double[i]+state->current.t.ptr.p_double[i]-state->bndu.ptr.p_double[i];
38889 0 : *errp2 = *errp2+v*v;
38890 0 : *errpinf = ae_maxreal(*errpinf, ae_fabs(v, _state), _state);
38891 0 : inc(&cntp2, _state);
38892 : }
38893 : }
38894 0 : *errp2 = ae_sqrt(*errp2/coalesce((double)(cntp2), (double)(1), _state), _state);
38895 0 : cntd2 = 0;
38896 0 : *errd2 = (double)(0);
38897 0 : *errdinf = (double)(0);
38898 0 : for(i=0; i<=n-1; i++)
38899 : {
38900 0 : if( !state->isfrozen.ptr.p_bool[i] )
38901 : {
38902 0 : v = state->tmphx.ptr.p_double[i]+state->c.ptr.p_double[i]-state->tmpaty.ptr.p_double[i];
38903 0 : if( state->hasgz.ptr.p_bool[i] )
38904 : {
38905 0 : v = v-state->current.z.ptr.p_double[i];
38906 : }
38907 0 : if( state->hasts.ptr.p_bool[i] )
38908 : {
38909 0 : v = v+state->current.s.ptr.p_double[i];
38910 : }
38911 0 : *errd2 = *errd2+v*v;
38912 0 : *errdinf = ae_maxreal(*errdinf, ae_fabs(v, _state), _state);
38913 0 : inc(&cntd2, _state);
38914 : }
38915 : }
38916 0 : for(i=0; i<=m-1; i++)
38917 : {
38918 0 : v = (double)(0);
38919 0 : if( state->haswv.ptr.p_bool[i] )
38920 : {
38921 0 : v = state->current.y.ptr.p_double[i]-state->current.v.ptr.p_double[i];
38922 : }
38923 0 : if( state->haspq.ptr.p_bool[i] )
38924 : {
38925 0 : v = v+state->current.q.ptr.p_double[i];
38926 : }
38927 0 : *errd2 = *errd2+v*v;
38928 0 : *errdinf = ae_maxreal(*errdinf, ae_fabs(v, _state), _state);
38929 0 : if( state->haswv.ptr.p_bool[i]||state->haspq.ptr.p_bool[i] )
38930 : {
38931 0 : inc(&cntd2, _state);
38932 : }
38933 : }
38934 0 : *errd2 = ae_sqrt(*errd2/coalesce((double)(cntd2), (double)(1), _state), _state);
38935 0 : *egap = vipmsolver_varscomputecomplementaritygap(&state->current, _state)/(1.0+ae_fabs(vipmsolver_vipmtarget(state, &state->current.x, _state), _state));
38936 0 : }
38937 :
38938 :
38939 : /*************************************************************************
38940 : Performs integrity checks for current point and step
38941 :
38942 : -- ALGLIB --
38943 : Copyright 01.11.2020 by Bochkanov Sergey
38944 : *************************************************************************/
38945 0 : static void vipmsolver_runintegritychecks(vipmstate* state,
38946 : vipmvars* v0,
38947 : vipmvars* vd,
38948 : double alphap,
38949 : double alphad,
38950 : ae_state *_state)
38951 : {
38952 : ae_int_t n;
38953 : ae_int_t m;
38954 : ae_int_t i;
38955 :
38956 :
38957 0 : n = state->n;
38958 0 : m = state->mdense+state->msparse;
38959 0 : ae_assert(ae_isfinite(alphap, _state)&&ae_fp_greater_eq(alphap,(double)(0)), "[VIPM]RunIntegrityChecks: bad AlphaP", _state);
38960 0 : ae_assert(ae_isfinite(alphad, _state)&&ae_fp_greater_eq(alphad,(double)(0)), "[VIPM]RunIntegrityChecks: bad AlphaD", _state);
38961 0 : for(i=0; i<=n-1; i++)
38962 : {
38963 0 : if( state->hasgz.ptr.p_bool[i] )
38964 : {
38965 0 : ae_assert(!state->isfrozen.ptr.p_bool[i], "[VIPM]RunIntegrityChecks: integrity failure - X[I] is frozen", _state);
38966 0 : ae_assert(v0->g.ptr.p_double[i]>0.0&&v0->z.ptr.p_double[i]>0.0, "[VIPM]RunIntegrityChecks: integrity failure - G[i]<=0 or Z[i]<=0", _state);
38967 : }
38968 : else
38969 : {
38970 0 : ae_assert(v0->g.ptr.p_double[i]==0.0&&v0->z.ptr.p_double[i]==0.0, "[VIPM]RunIntegrityChecks: integrity failure - G[i]<>0 or Z[i]<>0 for absent lower bound", _state);
38971 0 : ae_assert(vd->g.ptr.p_double[i]==0.0&&vd->z.ptr.p_double[i]==0.0, "[VIPM]RunIntegrityChecks: integrity failure - G[i]<>0 or Z[i]<>0 for absent lower bound", _state);
38972 : }
38973 0 : if( state->hasts.ptr.p_bool[i] )
38974 : {
38975 0 : ae_assert(!state->isfrozen.ptr.p_bool[i], "[VIPM]RunIntegrityChecks: integrity failure - X[I] is frozen", _state);
38976 0 : ae_assert(v0->t.ptr.p_double[i]>0.0&&v0->s.ptr.p_double[i]>0.0, "[VIPM]RunIntegrityChecks: integrity failure - T[i]<=0 or S[i]<=0", _state);
38977 : }
38978 : else
38979 : {
38980 0 : ae_assert(v0->t.ptr.p_double[i]==0.0&&v0->s.ptr.p_double[i]==0.0, "[VIPM]RunIntegrityChecks: integrity failure - T[i]<>0 or S[i]<>0 for absent upper bound", _state);
38981 0 : ae_assert(vd->t.ptr.p_double[i]==0.0&&vd->s.ptr.p_double[i]==0.0, "[VIPM]RunIntegrityChecks: integrity failure - T[i]<>0 or S[i]<>0 for absent upper bound", _state);
38982 : }
38983 : }
38984 0 : for(i=0; i<=m-1; i++)
38985 : {
38986 0 : ae_assert(state->haswv.ptr.p_bool[i]||!state->haspq.ptr.p_bool[i], "[VIPM]RunIntegrityChecks: inconsistent HasWV/HasPQ", _state);
38987 0 : if( state->haswv.ptr.p_bool[i] )
38988 : {
38989 0 : ae_assert(v0->v.ptr.p_double[i]>0.0&&v0->w.ptr.p_double[i]>0.0, "[VIPM]RunIntegrityChecks: integrity failure - V[i]<=0 or W[i]<=0", _state);
38990 : }
38991 : else
38992 : {
38993 0 : ae_assert(v0->v.ptr.p_double[i]==0.0&&v0->w.ptr.p_double[i]==0.0, "[VIPM]RunIntegrityChecks: integrity failure - V[i]<>0 or W[i]<>0 for linear equality constraint", _state);
38994 0 : ae_assert(vd->v.ptr.p_double[i]==0.0&&vd->w.ptr.p_double[i]==0.0, "[VIPM]RunIntegrityChecks: integrity failure - V[i]<>0 or W[i]<>0 for linear equality constraint", _state);
38995 : }
38996 0 : if( state->haspq.ptr.p_bool[i] )
38997 : {
38998 0 : ae_assert(v0->p.ptr.p_double[i]>0.0&&v0->q.ptr.p_double[i]>0.0, "[VIPM]RunIntegrityChecks: integrity failure - P[i]<=0 or Q[i]<=0", _state);
38999 : }
39000 : else
39001 : {
39002 0 : ae_assert(v0->p.ptr.p_double[i]==0.0&&v0->q.ptr.p_double[i]==0.0, "[VIPM]RunIntegrityChecks: integrity failure - P[i]<>0 or Q[i]<>0 for absent range of linear constraint", _state);
39003 0 : ae_assert(vd->p.ptr.p_double[i]==0.0&&vd->q.ptr.p_double[i]==0.0, "[VIPM]RunIntegrityChecks: integrity failure - P[i]<>0 or Q[i]<>0 for absent range of linear constraint", _state);
39004 : }
39005 : }
39006 0 : }
39007 :
39008 :
39009 : /*************************************************************************
39010 : Evaluate progress so far, outputs trace data, if requested to do so.
39011 :
39012 : -- ALGLIB --
39013 : Copyright 01.11.2019 by Bochkanov Sergey
39014 : *************************************************************************/
39015 0 : static void vipmsolver_traceprogress(vipmstate* state,
39016 : double mu,
39017 : double muaff,
39018 : double sigma,
39019 : double alphap,
39020 : double alphad,
39021 : ae_state *_state)
39022 : {
39023 : ae_int_t n;
39024 : ae_int_t m;
39025 : ae_int_t i;
39026 : double v;
39027 : double errp2;
39028 : double errd2;
39029 : double errpinf;
39030 : double errdinf;
39031 : double errgap;
39032 :
39033 :
39034 0 : n = state->n;
39035 0 : m = state->mdense+state->msparse;
39036 0 : if( !state->dotrace )
39037 : {
39038 0 : return;
39039 : }
39040 :
39041 : /*
39042 : * Print high-level information
39043 : */
39044 0 : vipmsolver_computeerrors(state, &errp2, &errd2, &errpinf, &errdinf, &errgap, _state);
39045 0 : ae_trace("--- step report ------------------------------------------------------------------------------------\n");
39046 0 : ae_trace("> step information\n");
39047 0 : ae_trace("mu_init = %0.3e (at the beginning)\n",
39048 : (double)(mu));
39049 0 : ae_trace("mu_aff = %0.3e (by affine scaling step)\n",
39050 : (double)(muaff));
39051 0 : ae_trace("sigma = %0.3e (centering parameter)\n",
39052 : (double)(sigma));
39053 0 : ae_trace("alphaP = %0.3e (primal step)\n",
39054 : (double)(alphap));
39055 0 : ae_trace("alphaD = %0.3e (dual step)\n",
39056 : (double)(alphad));
39057 0 : ae_trace("mu_cur = %0.3e (after the step)\n",
39058 : (double)(vipmsolver_varscomputemu(&state->current, _state)));
39059 0 : ae_trace("> errors\n");
39060 0 : ae_trace("errP = %0.3e (primal infeasibility, inf-norm)\n",
39061 : (double)(errpinf));
39062 0 : ae_trace("errD = %0.3e (dual infeasibility, inf-norm)\n",
39063 : (double)(errdinf));
39064 0 : ae_trace("errGap = %0.3e (complementarity gap)\n",
39065 : (double)(errgap));
39066 0 : ae_trace("> current point information (inf-norm)\n");
39067 0 : ae_trace("|X|=%8.1e, |G|=%8.1e, |T|=%8.1e, |W|=%8.1e, |P|=%8.1e\n",
39068 : (double)(rmaxabsv(n, &state->current.x, _state)),
39069 : (double)(rmaxabsv(n, &state->current.g, _state)),
39070 : (double)(rmaxabsv(n, &state->current.t, _state)),
39071 : (double)(rmaxabsv(m, &state->current.w, _state)),
39072 : (double)(rmaxabsv(m, &state->current.p, _state)));
39073 0 : ae_trace("|Y|=%8.1e, |Z|=%8.1e, |S|=%8.1e, |V|=%8.1e, |Q|=%8.1e\n",
39074 : (double)(rmaxabsv(m, &state->current.y, _state)),
39075 : (double)(rmaxabsv(n, &state->current.z, _state)),
39076 : (double)(rmaxabsv(n, &state->current.s, _state)),
39077 : (double)(rmaxabsv(m, &state->current.v, _state)),
39078 : (double)(rmaxabsv(m, &state->current.q, _state)));
39079 :
39080 : /*
39081 : * Print variable stats, if required
39082 : */
39083 0 : if( state->dotrace )
39084 : {
39085 0 : ae_trace("--- variable statistics ----------------------------------------------------------------------------\n");
39086 0 : ae_trace("> smallest values for nonnegative vars\n");
39087 0 : ae_trace("primal: minG=%8.1e minT=%8.1e minW=%8.1e minP=%8.1e\n",
39088 : (double)(vipmsolver_minnz(&state->current.g, n, _state)),
39089 : (double)(vipmsolver_minnz(&state->current.t, n, _state)),
39090 : (double)(vipmsolver_minnz(&state->current.w, m, _state)),
39091 : (double)(vipmsolver_minnz(&state->current.p, m, _state)));
39092 0 : ae_trace("dual: minZ=%8.1e minS=%8.1e minV=%8.1e minQ=%8.1e\n",
39093 : (double)(vipmsolver_minnz(&state->current.z, n, _state)),
39094 : (double)(vipmsolver_minnz(&state->current.s, n, _state)),
39095 : (double)(vipmsolver_minnz(&state->current.v, m, _state)),
39096 : (double)(vipmsolver_minnz(&state->current.q, m, _state)));
39097 0 : ae_trace("> min and max complementary slackness\n");
39098 0 : ae_trace("min: GZ=%8.1e TS=%8.1e WV=%8.1e PQ=%8.1e\n",
39099 : (double)(vipmsolver_minprodnz(&state->current.g, &state->current.z, n, _state)),
39100 : (double)(vipmsolver_minprodnz(&state->current.t, &state->current.s, n, _state)),
39101 : (double)(vipmsolver_minprodnz(&state->current.w, &state->current.v, m, _state)),
39102 : (double)(vipmsolver_minprodnz(&state->current.p, &state->current.q, m, _state)));
39103 0 : ae_trace("max: GZ=%8.1e TS=%8.1e WV=%8.1e PQ=%8.1e\n",
39104 : (double)(vipmsolver_maxprodnz(&state->current.g, &state->current.z, n, _state)),
39105 : (double)(vipmsolver_maxprodnz(&state->current.t, &state->current.s, n, _state)),
39106 : (double)(vipmsolver_maxprodnz(&state->current.w, &state->current.v, m, _state)),
39107 : (double)(vipmsolver_maxprodnz(&state->current.p, &state->current.q, m, _state)));
39108 : }
39109 :
39110 : /*
39111 : * Detailed output (all variables values, not suited for high-dimensional problems)
39112 : */
39113 0 : if( state->dodetailedtrace )
39114 : {
39115 0 : vipmsolver_vipmmultiply(state, &state->current.x, &state->current.y, &state->tmphx, &state->tmpax, &state->tmpaty, _state);
39116 0 : rsetallocv(n, 0.0, &state->tmplaggrad, _state);
39117 0 : for(i=0; i<=n-1; i++)
39118 : {
39119 0 : if( !state->isfrozen.ptr.p_bool[i] )
39120 : {
39121 0 : v = state->tmphx.ptr.p_double[i]+state->c.ptr.p_double[i]-state->tmpaty.ptr.p_double[i];
39122 0 : if( state->hasgz.ptr.p_bool[i] )
39123 : {
39124 0 : v = v-state->current.z.ptr.p_double[i];
39125 : }
39126 0 : if( state->hasts.ptr.p_bool[i] )
39127 : {
39128 0 : v = v+state->current.s.ptr.p_double[i];
39129 : }
39130 0 : state->tmplaggrad.ptr.p_double[i] = v;
39131 : }
39132 : }
39133 0 : ae_trace("--- printing raw data (prior to applying variable scales and shifting by XOrigin) ------------------\n");
39134 0 : ae_trace("X (raw) = ");
39135 0 : tracevectorunscaledunshiftedautoprec(&state->current.x, n, &state->scl, ae_true, &state->xorigin, ae_true, _state);
39136 0 : ae_trace("\n");
39137 0 : ae_trace("--- printing scaled data (after applying variable scales and shifting by XOrigin) ------------------\n");
39138 0 : ae_trace("> reporting X, Lagrangian gradient\n");
39139 0 : ae_trace("Xnew = ");
39140 0 : tracevectorautoprec(&state->current.x, 0, n, _state);
39141 0 : ae_trace("\n");
39142 0 : ae_trace("Lag-grad = ");
39143 0 : tracevectorautoprec(&state->tmplaggrad, 0, n, _state);
39144 0 : ae_trace("\n");
39145 0 : ae_trace("--- printing new point -----------------------------------------------------------------------------\n");
39146 0 : ae_trace("> primal slacks and dual multipliers for box constraints\n");
39147 0 : ae_trace("G (L prim slck) = ");
39148 0 : tracevectorautoprec(&state->current.g, 0, n, _state);
39149 0 : ae_trace("\n");
39150 0 : ae_trace("Z (L dual mult) = ");
39151 0 : tracevectorautoprec(&state->current.z, 0, n, _state);
39152 0 : ae_trace("\n");
39153 0 : ae_trace("T (U prim slck) = ");
39154 0 : tracevectorautoprec(&state->current.t, 0, n, _state);
39155 0 : ae_trace("\n");
39156 0 : ae_trace("S (U dual mult) = ");
39157 0 : tracevectorautoprec(&state->current.s, 0, n, _state);
39158 0 : ae_trace("\n");
39159 0 : ae_trace("> primal slacks and dual multipliers for linear constraints, B/R stand for B<=Ax<=B+R\n");
39160 0 : ae_trace("Y (lag mult) = ");
39161 0 : tracevectorautoprec(&state->current.y, 0, m, _state);
39162 0 : ae_trace("\n");
39163 0 : ae_trace("W (B prim slck) = ");
39164 0 : tracevectorautoprec(&state->current.w, 0, m, _state);
39165 0 : ae_trace("\n");
39166 0 : ae_trace("V (B dual mult) = ");
39167 0 : tracevectorautoprec(&state->current.v, 0, m, _state);
39168 0 : ae_trace("\n");
39169 0 : ae_trace("P (R prim slck) = ");
39170 0 : tracevectorautoprec(&state->current.p, 0, m, _state);
39171 0 : ae_trace("\n");
39172 0 : ae_trace("Q (R dual mult) = ");
39173 0 : tracevectorautoprec(&state->current.q, 0, m, _state);
39174 0 : ae_trace("\n");
39175 : }
39176 0 : ae_trace("\n");
39177 : }
39178 :
39179 :
39180 : /*************************************************************************
39181 : Compute right-hand side for KKT system.
39182 :
39183 : INPUT PARAMETERS:
39184 : State - IPM state
39185 : V0 - current point (used to compute RHS)
39186 : MuEstimate - estimate of Mu (can be zero)
39187 : DirEstimate - estimate of delta's (can be zero)
39188 :
39189 : OUTPUT PARAMETERS:
39190 : Rhs - RHS
39191 :
39192 : -- ALGLIB --
39193 : Copyright 01.11.2019 by Bochkanov Sergey
39194 : *************************************************************************/
39195 0 : static void vipmsolver_rhscompute(vipmstate* state,
39196 : vipmvars* v0,
39197 : double muestimate,
39198 : vipmvars* direstimate,
39199 : vipmrighthandside* rhs,
39200 : double reg,
39201 : ae_state *_state)
39202 : {
39203 : ae_int_t n;
39204 : ae_int_t m;
39205 : ae_int_t i;
39206 :
39207 :
39208 0 : n = state->n;
39209 0 : m = state->mdense+state->msparse;
39210 :
39211 : /*
39212 : * Allocate
39213 : */
39214 0 : rvectorsetlengthatleast(&rhs->sigma, n, _state);
39215 0 : rvectorsetlengthatleast(&rhs->nu, n, _state);
39216 0 : rvectorsetlengthatleast(&rhs->tau, n, _state);
39217 0 : rvectorsetlengthatleast(&rhs->gammaz, n, _state);
39218 0 : rvectorsetlengthatleast(&rhs->gammas, n, _state);
39219 0 : rvectorsetlengthatleast(&rhs->gammaw, m, _state);
39220 0 : rvectorsetlengthatleast(&rhs->gammaq, m, _state);
39221 0 : rsetallocv(m, 0.0, &rhs->beta, _state);
39222 0 : rsetallocv(m, 0.0, &rhs->rho, _state);
39223 0 : rsetallocv(m, 0.0, &rhs->alpha, _state);
39224 :
39225 : /*
39226 : * Compute products H*x, A*x, A^T*y
39227 : * We compute these products in one location for the sake of simplicity.
39228 : */
39229 0 : vipmsolver_vipmmultiply(state, &v0->x, &v0->y, &state->tmphx, &state->tmpax, &state->tmpaty, _state);
39230 :
39231 : /*
39232 : * Compute right-hand side:
39233 : * Rho = b - A*x + w
39234 : * Nu = l - x + g
39235 : * Tau = u - x - t
39236 : * Alpha = r - w - p
39237 : * Sigma = c - A^T*y - z + s + (H+REG)*x
39238 : * Beta = y + q - v
39239 : */
39240 0 : for(i=0; i<=m-1; i++)
39241 : {
39242 0 : rhs->rho.ptr.p_double[i] = state->b.ptr.p_double[i]-state->tmpax.ptr.p_double[i]-reg*v0->y.ptr.p_double[i];
39243 0 : if( state->haswv.ptr.p_bool[i] )
39244 : {
39245 :
39246 : /*
39247 : * Inequality/range constraint
39248 : */
39249 0 : rhs->rho.ptr.p_double[i] = rhs->rho.ptr.p_double[i]+v0->w.ptr.p_double[i];
39250 : }
39251 : else
39252 : {
39253 :
39254 : /*
39255 : * Equality constraint without slack variables, W[i]=0
39256 : */
39257 0 : ae_assert(v0->w.ptr.p_double[i]==0.0, "RhsCompute: W[i]<>0 for linear equality constraint", _state);
39258 : }
39259 : }
39260 0 : for(i=0; i<=n-1; i++)
39261 : {
39262 0 : if( state->hasgz.ptr.p_bool[i] )
39263 : {
39264 :
39265 : /*
39266 : * Lower bound is present
39267 : */
39268 0 : rhs->nu.ptr.p_double[i] = state->bndl.ptr.p_double[i]-v0->x.ptr.p_double[i]+v0->g.ptr.p_double[i]-reg*v0->z.ptr.p_double[i];
39269 : }
39270 : else
39271 : {
39272 :
39273 : /*
39274 : * Lower bound is absent, g[i] = 0
39275 : */
39276 0 : ae_assert(v0->g.ptr.p_double[i]==0.0, "RhsCompute: G[i]<>0 for absent constraint", _state);
39277 0 : rhs->nu.ptr.p_double[i] = (double)(0);
39278 : }
39279 : }
39280 0 : for(i=0; i<=n-1; i++)
39281 : {
39282 0 : if( state->hasts.ptr.p_bool[i] )
39283 : {
39284 :
39285 : /*
39286 : * Upper bound is present
39287 : */
39288 0 : rhs->tau.ptr.p_double[i] = state->bndu.ptr.p_double[i]-v0->x.ptr.p_double[i]-v0->t.ptr.p_double[i]+reg*v0->s.ptr.p_double[i];
39289 : }
39290 : else
39291 : {
39292 :
39293 : /*
39294 : * Upper bound is absent, t[i] = 0
39295 : */
39296 0 : ae_assert(v0->t.ptr.p_double[i]==0.0, "RhsCompute: T[i]<>0 for absent constraint", _state);
39297 0 : rhs->tau.ptr.p_double[i] = (double)(0);
39298 : }
39299 : }
39300 0 : for(i=0; i<=m-1; i++)
39301 : {
39302 0 : if( state->haspq.ptr.p_bool[i] )
39303 : {
39304 0 : rhs->alpha.ptr.p_double[i] = state->r.ptr.p_double[i]-v0->w.ptr.p_double[i]-v0->p.ptr.p_double[i]+reg*v0->q.ptr.p_double[i];
39305 : }
39306 : }
39307 0 : for(i=0; i<=n-1; i++)
39308 : {
39309 0 : if( !state->isfrozen.ptr.p_bool[i] )
39310 : {
39311 0 : rhs->sigma.ptr.p_double[i] = state->c.ptr.p_double[i]-state->tmpaty.ptr.p_double[i]+state->tmphx.ptr.p_double[i]+reg*v0->x.ptr.p_double[i];
39312 0 : if( state->hasgz.ptr.p_bool[i] )
39313 : {
39314 0 : rhs->sigma.ptr.p_double[i] = rhs->sigma.ptr.p_double[i]-v0->z.ptr.p_double[i];
39315 : }
39316 0 : if( state->hasts.ptr.p_bool[i] )
39317 : {
39318 0 : rhs->sigma.ptr.p_double[i] = rhs->sigma.ptr.p_double[i]+v0->s.ptr.p_double[i];
39319 : }
39320 : }
39321 : else
39322 : {
39323 0 : rhs->sigma.ptr.p_double[i] = (double)(0);
39324 : }
39325 : }
39326 0 : for(i=0; i<=m-1; i++)
39327 : {
39328 0 : if( state->haswv.ptr.p_bool[i] )
39329 : {
39330 0 : rhs->beta.ptr.p_double[i] = rhs->beta.ptr.p_double[i]+v0->y.ptr.p_double[i]-v0->v.ptr.p_double[i]+reg*v0->w.ptr.p_double[i];
39331 : }
39332 0 : if( state->haspq.ptr.p_bool[i] )
39333 : {
39334 0 : rhs->beta.ptr.p_double[i] = rhs->beta.ptr.p_double[i]+v0->q.ptr.p_double[i];
39335 : }
39336 : }
39337 :
39338 : /*
39339 : * Compute right-hand side:
39340 : * GammaZ = mu*inv(G)*e - z - inv(G)*DELTAG*deltaZ
39341 : * GammaW = mu*inv(V)*e - w - inv(V)*DELTAV*deltaW
39342 : * GammaS = mu*inv(T)*e - s - inv(T)*DELTAT*deltaS
39343 : * GammaQ = mu*inv(P)*e - q - inv(P)*DELTAP*deltaQ
39344 : */
39345 0 : for(i=0; i<=n-1; i++)
39346 : {
39347 0 : if( state->hasgz.ptr.p_bool[i] )
39348 : {
39349 0 : ae_assert(v0->g.ptr.p_double[i]>0.0, "RhsCompute: G[i]<=0", _state);
39350 0 : rhs->gammaz.ptr.p_double[i] = muestimate/v0->g.ptr.p_double[i]-v0->z.ptr.p_double[i]-direstimate->g.ptr.p_double[i]*direstimate->z.ptr.p_double[i]/v0->g.ptr.p_double[i];
39351 : }
39352 : else
39353 : {
39354 0 : ae_assert(v0->g.ptr.p_double[i]==0.0, "RhsCompute: G[i]<>0 for absent constraint", _state);
39355 0 : ae_assert(v0->z.ptr.p_double[i]==0.0, "RhsCompute: Z[i]<>0 for absent constraint", _state);
39356 0 : rhs->gammaz.ptr.p_double[i] = (double)(0);
39357 : }
39358 : }
39359 0 : for(i=0; i<=m-1; i++)
39360 : {
39361 0 : if( state->haswv.ptr.p_bool[i] )
39362 : {
39363 :
39364 : /*
39365 : * Inequality/range constraint
39366 : */
39367 0 : ae_assert(v0->v.ptr.p_double[i]>0.0, "RhsCompute: V[i]<=0", _state);
39368 0 : rhs->gammaw.ptr.p_double[i] = muestimate/v0->v.ptr.p_double[i]-v0->w.ptr.p_double[i]-direstimate->v.ptr.p_double[i]*direstimate->w.ptr.p_double[i]/v0->v.ptr.p_double[i];
39369 : }
39370 : else
39371 : {
39372 :
39373 : /*
39374 : * Equality constraint
39375 : */
39376 0 : ae_assert(v0->v.ptr.p_double[i]==0.0, "RhsCompute: V[i]<>0 for equality constraint", _state);
39377 0 : ae_assert(v0->w.ptr.p_double[i]==0.0, "RhsCompute: W[i]<>0 for equality constraint", _state);
39378 0 : rhs->gammaw.ptr.p_double[i] = (double)(0);
39379 : }
39380 : }
39381 0 : for(i=0; i<=n-1; i++)
39382 : {
39383 0 : if( state->hasts.ptr.p_bool[i] )
39384 : {
39385 :
39386 : /*
39387 : * Upper bound is present
39388 : */
39389 0 : ae_assert(v0->t.ptr.p_double[i]>0.0, "RhsCompute: T[i]<=0", _state);
39390 0 : rhs->gammas.ptr.p_double[i] = muestimate/v0->t.ptr.p_double[i]-v0->s.ptr.p_double[i]-direstimate->t.ptr.p_double[i]*direstimate->s.ptr.p_double[i]/v0->t.ptr.p_double[i];
39391 : }
39392 : else
39393 : {
39394 :
39395 : /*
39396 : * Upper bound is absent
39397 : */
39398 0 : ae_assert(v0->t.ptr.p_double[i]==0.0, "RhsCompute: T[i]<>0 for absent constraint", _state);
39399 0 : ae_assert(v0->s.ptr.p_double[i]==0.0, "RhsCompute: S[i]<>0 for absent constraint", _state);
39400 0 : rhs->gammas.ptr.p_double[i] = (double)(0);
39401 : }
39402 : }
39403 0 : for(i=0; i<=m-1; i++)
39404 : {
39405 0 : if( state->haspq.ptr.p_bool[i] )
39406 : {
39407 0 : ae_assert(v0->p.ptr.p_double[i]>0.0, "RhsCompute: P[i]<=0", _state);
39408 0 : rhs->gammaq.ptr.p_double[i] = muestimate/v0->p.ptr.p_double[i]-v0->q.ptr.p_double[i]-direstimate->p.ptr.p_double[i]*direstimate->q.ptr.p_double[i]/v0->p.ptr.p_double[i];
39409 : }
39410 : else
39411 : {
39412 0 : ae_assert(v0->p.ptr.p_double[i]==0.0, "RhsCompute: P[i]<>0 for absent range", _state);
39413 0 : ae_assert(v0->q.ptr.p_double[i]==0.0, "RhsCompute: Q[i]<>0 for absent range", _state);
39414 0 : rhs->gammaq.ptr.p_double[i] = (double)(0);
39415 : }
39416 : }
39417 0 : }
39418 :
39419 :
39420 : /*************************************************************************
39421 : Subtracts KKT*cand from already computed RHS.
39422 :
39423 : A pair of RhsCompute/RhsSubtract calls results in residual being loaded
39424 : into the RHS structure.
39425 :
39426 : INPUT PARAMETERS:
39427 : State - IPM state
39428 : V0 - current point (used to compute RHS)
39429 : MuEstimate - estimate of Mu (can be zero)
39430 : DirEstimate - estimate of delta's (can be zero)
39431 : ResidualFrom - whether we want to compute RHS or residual computed
39432 : using VDCandidate
39433 : VDCandidate - solution candidate
39434 :
39435 : OUTPUT PARAMETERS:
39436 : Rhs - either RHS or residual RHS-KKT*Cand
39437 :
39438 : -- ALGLIB --
39439 : Copyright 01.11.2019 by Bochkanov Sergey
39440 : *************************************************************************/
39441 0 : static void vipmsolver_rhssubtract(vipmstate* state,
39442 : vipmrighthandside* rhs,
39443 : vipmvars* v0,
39444 : vipmvars* vdcandidate,
39445 : double reg,
39446 : ae_state *_state)
39447 : {
39448 : ae_int_t n;
39449 : ae_int_t m;
39450 : ae_int_t i;
39451 :
39452 :
39453 0 : n = state->n;
39454 0 : m = state->mdense+state->msparse;
39455 0 : vipmsolver_vipmmultiply(state, &vdcandidate->x, &vdcandidate->y, &state->tmphx, &state->tmpax, &state->tmpaty, _state);
39456 :
39457 : /*
39458 : * Residual for Rho, Nu, Tau, Alpha, Sigma, Beta
39459 : */
39460 0 : for(i=0; i<=m-1; i++)
39461 : {
39462 0 : if( state->haswv.ptr.p_bool[i] )
39463 : {
39464 0 : rhs->rho.ptr.p_double[i] = rhs->rho.ptr.p_double[i]-(state->tmpax.ptr.p_double[i]-vdcandidate->w.ptr.p_double[i]+reg*vdcandidate->y.ptr.p_double[i]);
39465 : }
39466 : else
39467 : {
39468 0 : rhs->rho.ptr.p_double[i] = rhs->rho.ptr.p_double[i]-(state->tmpax.ptr.p_double[i]+reg*vdcandidate->y.ptr.p_double[i]);
39469 : }
39470 : }
39471 0 : for(i=0; i<=n-1; i++)
39472 : {
39473 0 : if( state->hasgz.ptr.p_bool[i] )
39474 : {
39475 0 : rhs->nu.ptr.p_double[i] = rhs->nu.ptr.p_double[i]-(vdcandidate->x.ptr.p_double[i]-vdcandidate->g.ptr.p_double[i]+reg*vdcandidate->z.ptr.p_double[i]);
39476 : }
39477 : }
39478 0 : for(i=0; i<=n-1; i++)
39479 : {
39480 0 : if( state->hasts.ptr.p_bool[i] )
39481 : {
39482 0 : rhs->tau.ptr.p_double[i] = rhs->tau.ptr.p_double[i]-(vdcandidate->x.ptr.p_double[i]+vdcandidate->t.ptr.p_double[i]-reg*vdcandidate->s.ptr.p_double[i]);
39483 : }
39484 : }
39485 0 : for(i=0; i<=m-1; i++)
39486 : {
39487 0 : if( state->haspq.ptr.p_bool[i] )
39488 : {
39489 0 : rhs->alpha.ptr.p_double[i] = rhs->alpha.ptr.p_double[i]-(vdcandidate->w.ptr.p_double[i]+vdcandidate->p.ptr.p_double[i]-reg*vdcandidate->q.ptr.p_double[i]);
39490 : }
39491 : }
39492 0 : for(i=0; i<=n-1; i++)
39493 : {
39494 0 : if( !state->isfrozen.ptr.p_bool[i] )
39495 : {
39496 0 : rhs->sigma.ptr.p_double[i] = rhs->sigma.ptr.p_double[i]-(state->tmpaty.ptr.p_double[i]-state->tmphx.ptr.p_double[i]-reg*vdcandidate->x.ptr.p_double[i]);
39497 0 : if( state->hasgz.ptr.p_bool[i] )
39498 : {
39499 0 : rhs->sigma.ptr.p_double[i] = rhs->sigma.ptr.p_double[i]-vdcandidate->z.ptr.p_double[i];
39500 : }
39501 0 : if( state->hasts.ptr.p_bool[i] )
39502 : {
39503 0 : rhs->sigma.ptr.p_double[i] = rhs->sigma.ptr.p_double[i]+vdcandidate->s.ptr.p_double[i];
39504 : }
39505 : }
39506 : }
39507 0 : for(i=0; i<=m-1; i++)
39508 : {
39509 0 : if( state->haswv.ptr.p_bool[i] )
39510 : {
39511 0 : rhs->beta.ptr.p_double[i] = rhs->beta.ptr.p_double[i]-(-vdcandidate->y.ptr.p_double[i]+vdcandidate->v.ptr.p_double[i]-reg*vdcandidate->w.ptr.p_double[i]);
39512 : }
39513 0 : if( state->haspq.ptr.p_bool[i] )
39514 : {
39515 0 : rhs->beta.ptr.p_double[i] = rhs->beta.ptr.p_double[i]+vdcandidate->q.ptr.p_double[i];
39516 : }
39517 : }
39518 :
39519 : /*
39520 : * Residual for GammaZ, GammaW, GammaS, GammaQ
39521 : */
39522 0 : for(i=0; i<=n-1; i++)
39523 : {
39524 0 : if( state->hasgz.ptr.p_bool[i] )
39525 : {
39526 0 : rhs->gammaz.ptr.p_double[i] = rhs->gammaz.ptr.p_double[i]-(v0->z.ptr.p_double[i]/v0->g.ptr.p_double[i]*vdcandidate->g.ptr.p_double[i]+vdcandidate->z.ptr.p_double[i]);
39527 : }
39528 : }
39529 0 : for(i=0; i<=m-1; i++)
39530 : {
39531 0 : if( state->haswv.ptr.p_bool[i] )
39532 : {
39533 0 : rhs->gammaw.ptr.p_double[i] = rhs->gammaw.ptr.p_double[i]-(v0->w.ptr.p_double[i]/v0->v.ptr.p_double[i]*vdcandidate->v.ptr.p_double[i]+vdcandidate->w.ptr.p_double[i]);
39534 : }
39535 : }
39536 0 : for(i=0; i<=n-1; i++)
39537 : {
39538 0 : if( state->hasts.ptr.p_bool[i] )
39539 : {
39540 0 : rhs->gammas.ptr.p_double[i] = rhs->gammas.ptr.p_double[i]-(v0->s.ptr.p_double[i]/v0->t.ptr.p_double[i]*vdcandidate->t.ptr.p_double[i]+vdcandidate->s.ptr.p_double[i]);
39541 : }
39542 : }
39543 0 : for(i=0; i<=m-1; i++)
39544 : {
39545 0 : if( state->haspq.ptr.p_bool[i] )
39546 : {
39547 0 : rhs->gammaq.ptr.p_double[i] = rhs->gammaq.ptr.p_double[i]-(v0->q.ptr.p_double[i]/v0->p.ptr.p_double[i]*vdcandidate->p.ptr.p_double[i]+vdcandidate->q.ptr.p_double[i]);
39548 : }
39549 : }
39550 0 : }
39551 :
39552 :
39553 : /*************************************************************************
39554 : Computes sum of squared primal terms of RHS
39555 :
39556 : INPUT PARAMETERS:
39557 : Rhs - RHS structure
39558 : N, M - problem metrics
39559 :
39560 : RESULT:
39561 : sum(sqr()) computed over primal terms (Rho, Nu, Tau, Alpha)
39562 :
39563 : -- ALGLIB --
39564 : Copyright 01.11.2020 by Bochkanov Sergey
39565 : *************************************************************************/
39566 0 : static double vipmsolver_rhsprimal2(vipmrighthandside* rhs,
39567 : ae_int_t n,
39568 : ae_int_t m,
39569 : ae_state *_state)
39570 : {
39571 : double result;
39572 :
39573 :
39574 0 : result = (double)(0);
39575 0 : result = result+rdotv2(m, &rhs->rho, _state);
39576 0 : result = result+rdotv2(n, &rhs->nu, _state);
39577 0 : result = result+rdotv2(n, &rhs->tau, _state);
39578 0 : result = result+rdotv2(m, &rhs->alpha, _state);
39579 0 : return result;
39580 : }
39581 :
39582 :
39583 : /*************************************************************************
39584 : Computes sum of squared dual terms of RHS
39585 :
39586 : INPUT PARAMETERS:
39587 : Rhs - RHS structure
39588 : N, M - problem metrics
39589 :
39590 : RESULT:
39591 : sum(sqr()) computed over dual terms (Sigma, Beta)
39592 :
39593 : -- ALGLIB --
39594 : Copyright 01.11.2020 by Bochkanov Sergey
39595 : *************************************************************************/
39596 0 : static double vipmsolver_rhsdual2(vipmrighthandside* rhs,
39597 : ae_int_t n,
39598 : ae_int_t m,
39599 : ae_state *_state)
39600 : {
39601 : double result;
39602 :
39603 :
39604 0 : result = (double)(0);
39605 0 : result = result+rdotv2(n, &rhs->sigma, _state);
39606 0 : result = result+rdotv2(m, &rhs->beta, _state);
39607 0 : return result;
39608 : }
39609 :
39610 :
39611 : /*************************************************************************
39612 : Computes inf-norm of primal terms of RHS
39613 :
39614 : INPUT PARAMETERS:
39615 : Rhs - RHS structure
39616 : N, M - problem metrics
39617 :
39618 : RESULT:
39619 : max(abs()) computed over primal terms (Rho, Nu, Tau, Alpha)
39620 :
39621 : -- ALGLIB --
39622 : Copyright 01.11.2020 by Bochkanov Sergey
39623 : *************************************************************************/
39624 0 : static double vipmsolver_rhsprimalinf(vipmrighthandside* rhs,
39625 : ae_int_t n,
39626 : ae_int_t m,
39627 : ae_state *_state)
39628 : {
39629 : double result;
39630 :
39631 :
39632 0 : result = (double)(0);
39633 0 : result = ae_maxreal(result, rmaxabsv(m, &rhs->rho, _state), _state);
39634 0 : result = ae_maxreal(result, rmaxabsv(n, &rhs->nu, _state), _state);
39635 0 : result = ae_maxreal(result, rmaxabsv(n, &rhs->tau, _state), _state);
39636 0 : result = ae_maxreal(result, rmaxabsv(m, &rhs->alpha, _state), _state);
39637 0 : return result;
39638 : }
39639 :
39640 :
39641 : /*************************************************************************
39642 : Computes inf-norm of dual terms of RHS
39643 :
39644 : INPUT PARAMETERS:
39645 : Rhs - RHS structure
39646 : N, M - problem metrics
39647 :
39648 : RESULT:
39649 : max(abs()) computed over dual terms (Sigma, Beta)
39650 :
39651 : -- ALGLIB --
39652 : Copyright 01.11.2020 by Bochkanov Sergey
39653 : *************************************************************************/
39654 0 : static double vipmsolver_rhsdualinf(vipmrighthandside* rhs,
39655 : ae_int_t n,
39656 : ae_int_t m,
39657 : ae_state *_state)
39658 : {
39659 : double result;
39660 :
39661 :
39662 0 : result = (double)(0);
39663 0 : result = ae_maxreal(result, rmaxabsv(n, &rhs->sigma, _state), _state);
39664 0 : result = ae_maxreal(result, rmaxabsv(m, &rhs->beta, _state), _state);
39665 0 : return result;
39666 : }
39667 :
39668 :
39669 : /*************************************************************************
39670 : Computes maximum over complementarity slackness terms of RHS
39671 :
39672 : INPUT PARAMETERS:
39673 : Rhs - RHS structure
39674 : N, M - problem metrics
39675 :
39676 : RESULT:
39677 : max(abs()) computed over complementarity terms (GammaZ, GammaS, GammaW, GammaQ)
39678 :
39679 : -- ALGLIB --
39680 : Copyright 01.11.2020 by Bochkanov Sergey
39681 : *************************************************************************/
39682 0 : static double vipmsolver_rhscompl2(vipmrighthandside* rhs,
39683 : ae_int_t n,
39684 : ae_int_t m,
39685 : ae_state *_state)
39686 : {
39687 : double result;
39688 :
39689 :
39690 0 : result = (double)(0);
39691 0 : result = result+rdotv2(n, &rhs->gammaz, _state);
39692 0 : result = result+rdotv2(n, &rhs->gammas, _state);
39693 0 : result = result+rdotv2(m, &rhs->gammaw, _state);
39694 0 : result = result+rdotv2(m, &rhs->gammaq, _state);
39695 0 : return result;
39696 : }
39697 :
39698 :
39699 : /*************************************************************************
39700 : Computes minimum nonzero value of the vector. Returns 0 if all components
39701 : are nonpositive.
39702 :
39703 : INPUT PARAMETERS:
39704 : X - vector
39705 : N - length
39706 :
39707 : -- ALGLIB --
39708 : Copyright 01.11.2020 by Bochkanov Sergey
39709 : *************************************************************************/
39710 0 : static double vipmsolver_minnz(/* Real */ ae_vector* x,
39711 : ae_int_t n,
39712 : ae_state *_state)
39713 : {
39714 : ae_int_t i;
39715 : ae_bool nz;
39716 : double result;
39717 :
39718 :
39719 0 : result = (double)(0);
39720 0 : nz = ae_false;
39721 0 : for(i=0; i<=n-1; i++)
39722 : {
39723 0 : if( ae_fp_greater(x->ptr.p_double[i],(double)(0)) )
39724 : {
39725 0 : if( !nz )
39726 : {
39727 0 : result = x->ptr.p_double[i];
39728 0 : nz = ae_true;
39729 : }
39730 : else
39731 : {
39732 0 : result = ae_minreal(result, x->ptr.p_double[i], _state);
39733 : }
39734 : }
39735 : }
39736 0 : return result;
39737 : }
39738 :
39739 :
39740 : /*************************************************************************
39741 : Computes minimum product of nonzero components.
39742 : Returns 0 if all components are nonpositive.
39743 :
39744 : INPUT PARAMETERS:
39745 : X - vector
39746 : Y - vector
39747 : N - length
39748 :
39749 : -- ALGLIB --
39750 : Copyright 01.11.2020 by Bochkanov Sergey
39751 : *************************************************************************/
39752 0 : static double vipmsolver_minprodnz(/* Real */ ae_vector* x,
39753 : /* Real */ ae_vector* y,
39754 : ae_int_t n,
39755 : ae_state *_state)
39756 : {
39757 : ae_int_t i;
39758 : ae_bool nz;
39759 : double result;
39760 :
39761 :
39762 0 : result = (double)(0);
39763 0 : nz = ae_false;
39764 0 : for(i=0; i<=n-1; i++)
39765 : {
39766 0 : if( ae_fp_greater(x->ptr.p_double[i],(double)(0))&&ae_fp_greater(y->ptr.p_double[i],(double)(0)) )
39767 : {
39768 0 : if( !nz )
39769 : {
39770 0 : result = x->ptr.p_double[i]*y->ptr.p_double[i];
39771 0 : nz = ae_true;
39772 : }
39773 : else
39774 : {
39775 0 : result = ae_minreal(result, x->ptr.p_double[i]*y->ptr.p_double[i], _state);
39776 : }
39777 : }
39778 : }
39779 0 : return result;
39780 : }
39781 :
39782 :
39783 : /*************************************************************************
39784 : Computes maximum product of nonzero components.
39785 : Returns 0 if all components are nonpositive.
39786 :
39787 : INPUT PARAMETERS:
39788 : X - vector
39789 : Y - vector
39790 : N - length
39791 :
39792 : -- ALGLIB --
39793 : Copyright 01.11.2020 by Bochkanov Sergey
39794 : *************************************************************************/
39795 0 : static double vipmsolver_maxprodnz(/* Real */ ae_vector* x,
39796 : /* Real */ ae_vector* y,
39797 : ae_int_t n,
39798 : ae_state *_state)
39799 : {
39800 : ae_int_t i;
39801 : ae_bool nz;
39802 : double result;
39803 :
39804 :
39805 0 : result = (double)(0);
39806 0 : nz = ae_false;
39807 0 : for(i=0; i<=n-1; i++)
39808 : {
39809 0 : if( ae_fp_greater(x->ptr.p_double[i],(double)(0))&&ae_fp_greater(y->ptr.p_double[i],(double)(0)) )
39810 : {
39811 0 : if( !nz )
39812 : {
39813 0 : result = x->ptr.p_double[i]*y->ptr.p_double[i];
39814 0 : nz = ae_true;
39815 : }
39816 : else
39817 : {
39818 0 : result = ae_maxreal(result, x->ptr.p_double[i]*y->ptr.p_double[i], _state);
39819 : }
39820 : }
39821 : }
39822 0 : return result;
39823 : }
39824 :
39825 :
39826 0 : void _vipmvars_init(void* _p, ae_state *_state, ae_bool make_automatic)
39827 : {
39828 0 : vipmvars *p = (vipmvars*)_p;
39829 0 : ae_touch_ptr((void*)p);
39830 0 : ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
39831 0 : ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic);
39832 0 : ae_vector_init(&p->w, 0, DT_REAL, _state, make_automatic);
39833 0 : ae_vector_init(&p->t, 0, DT_REAL, _state, make_automatic);
39834 0 : ae_vector_init(&p->p, 0, DT_REAL, _state, make_automatic);
39835 0 : ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic);
39836 0 : ae_vector_init(&p->z, 0, DT_REAL, _state, make_automatic);
39837 0 : ae_vector_init(&p->v, 0, DT_REAL, _state, make_automatic);
39838 0 : ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic);
39839 0 : ae_vector_init(&p->q, 0, DT_REAL, _state, make_automatic);
39840 0 : }
39841 :
39842 :
39843 0 : void _vipmvars_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
39844 : {
39845 0 : vipmvars *dst = (vipmvars*)_dst;
39846 0 : vipmvars *src = (vipmvars*)_src;
39847 0 : dst->n = src->n;
39848 0 : dst->m = src->m;
39849 0 : ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
39850 0 : ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic);
39851 0 : ae_vector_init_copy(&dst->w, &src->w, _state, make_automatic);
39852 0 : ae_vector_init_copy(&dst->t, &src->t, _state, make_automatic);
39853 0 : ae_vector_init_copy(&dst->p, &src->p, _state, make_automatic);
39854 0 : ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic);
39855 0 : ae_vector_init_copy(&dst->z, &src->z, _state, make_automatic);
39856 0 : ae_vector_init_copy(&dst->v, &src->v, _state, make_automatic);
39857 0 : ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic);
39858 0 : ae_vector_init_copy(&dst->q, &src->q, _state, make_automatic);
39859 0 : }
39860 :
39861 :
39862 0 : void _vipmvars_clear(void* _p)
39863 : {
39864 0 : vipmvars *p = (vipmvars*)_p;
39865 0 : ae_touch_ptr((void*)p);
39866 0 : ae_vector_clear(&p->x);
39867 0 : ae_vector_clear(&p->g);
39868 0 : ae_vector_clear(&p->w);
39869 0 : ae_vector_clear(&p->t);
39870 0 : ae_vector_clear(&p->p);
39871 0 : ae_vector_clear(&p->y);
39872 0 : ae_vector_clear(&p->z);
39873 0 : ae_vector_clear(&p->v);
39874 0 : ae_vector_clear(&p->s);
39875 0 : ae_vector_clear(&p->q);
39876 0 : }
39877 :
39878 :
39879 0 : void _vipmvars_destroy(void* _p)
39880 : {
39881 0 : vipmvars *p = (vipmvars*)_p;
39882 0 : ae_touch_ptr((void*)p);
39883 0 : ae_vector_destroy(&p->x);
39884 0 : ae_vector_destroy(&p->g);
39885 0 : ae_vector_destroy(&p->w);
39886 0 : ae_vector_destroy(&p->t);
39887 0 : ae_vector_destroy(&p->p);
39888 0 : ae_vector_destroy(&p->y);
39889 0 : ae_vector_destroy(&p->z);
39890 0 : ae_vector_destroy(&p->v);
39891 0 : ae_vector_destroy(&p->s);
39892 0 : ae_vector_destroy(&p->q);
39893 0 : }
39894 :
39895 :
39896 0 : void _vipmrighthandside_init(void* _p, ae_state *_state, ae_bool make_automatic)
39897 : {
39898 0 : vipmrighthandside *p = (vipmrighthandside*)_p;
39899 0 : ae_touch_ptr((void*)p);
39900 0 : ae_vector_init(&p->sigma, 0, DT_REAL, _state, make_automatic);
39901 0 : ae_vector_init(&p->beta, 0, DT_REAL, _state, make_automatic);
39902 0 : ae_vector_init(&p->rho, 0, DT_REAL, _state, make_automatic);
39903 0 : ae_vector_init(&p->nu, 0, DT_REAL, _state, make_automatic);
39904 0 : ae_vector_init(&p->tau, 0, DT_REAL, _state, make_automatic);
39905 0 : ae_vector_init(&p->alpha, 0, DT_REAL, _state, make_automatic);
39906 0 : ae_vector_init(&p->gammaz, 0, DT_REAL, _state, make_automatic);
39907 0 : ae_vector_init(&p->gammas, 0, DT_REAL, _state, make_automatic);
39908 0 : ae_vector_init(&p->gammaw, 0, DT_REAL, _state, make_automatic);
39909 0 : ae_vector_init(&p->gammaq, 0, DT_REAL, _state, make_automatic);
39910 0 : }
39911 :
39912 :
39913 0 : void _vipmrighthandside_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
39914 : {
39915 0 : vipmrighthandside *dst = (vipmrighthandside*)_dst;
39916 0 : vipmrighthandside *src = (vipmrighthandside*)_src;
39917 0 : ae_vector_init_copy(&dst->sigma, &src->sigma, _state, make_automatic);
39918 0 : ae_vector_init_copy(&dst->beta, &src->beta, _state, make_automatic);
39919 0 : ae_vector_init_copy(&dst->rho, &src->rho, _state, make_automatic);
39920 0 : ae_vector_init_copy(&dst->nu, &src->nu, _state, make_automatic);
39921 0 : ae_vector_init_copy(&dst->tau, &src->tau, _state, make_automatic);
39922 0 : ae_vector_init_copy(&dst->alpha, &src->alpha, _state, make_automatic);
39923 0 : ae_vector_init_copy(&dst->gammaz, &src->gammaz, _state, make_automatic);
39924 0 : ae_vector_init_copy(&dst->gammas, &src->gammas, _state, make_automatic);
39925 0 : ae_vector_init_copy(&dst->gammaw, &src->gammaw, _state, make_automatic);
39926 0 : ae_vector_init_copy(&dst->gammaq, &src->gammaq, _state, make_automatic);
39927 0 : }
39928 :
39929 :
39930 0 : void _vipmrighthandside_clear(void* _p)
39931 : {
39932 0 : vipmrighthandside *p = (vipmrighthandside*)_p;
39933 0 : ae_touch_ptr((void*)p);
39934 0 : ae_vector_clear(&p->sigma);
39935 0 : ae_vector_clear(&p->beta);
39936 0 : ae_vector_clear(&p->rho);
39937 0 : ae_vector_clear(&p->nu);
39938 0 : ae_vector_clear(&p->tau);
39939 0 : ae_vector_clear(&p->alpha);
39940 0 : ae_vector_clear(&p->gammaz);
39941 0 : ae_vector_clear(&p->gammas);
39942 0 : ae_vector_clear(&p->gammaw);
39943 0 : ae_vector_clear(&p->gammaq);
39944 0 : }
39945 :
39946 :
39947 0 : void _vipmrighthandside_destroy(void* _p)
39948 : {
39949 0 : vipmrighthandside *p = (vipmrighthandside*)_p;
39950 0 : ae_touch_ptr((void*)p);
39951 0 : ae_vector_destroy(&p->sigma);
39952 0 : ae_vector_destroy(&p->beta);
39953 0 : ae_vector_destroy(&p->rho);
39954 0 : ae_vector_destroy(&p->nu);
39955 0 : ae_vector_destroy(&p->tau);
39956 0 : ae_vector_destroy(&p->alpha);
39957 0 : ae_vector_destroy(&p->gammaz);
39958 0 : ae_vector_destroy(&p->gammas);
39959 0 : ae_vector_destroy(&p->gammaw);
39960 0 : ae_vector_destroy(&p->gammaq);
39961 0 : }
39962 :
39963 :
39964 0 : void _vipmstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
39965 : {
39966 0 : vipmstate *p = (vipmstate*)_p;
39967 0 : ae_touch_ptr((void*)p);
39968 0 : ae_vector_init(&p->scl, 0, DT_REAL, _state, make_automatic);
39969 0 : ae_vector_init(&p->invscl, 0, DT_REAL, _state, make_automatic);
39970 0 : ae_vector_init(&p->xorigin, 0, DT_REAL, _state, make_automatic);
39971 0 : ae_vector_init(&p->c, 0, DT_REAL, _state, make_automatic);
39972 0 : ae_matrix_init(&p->denseh, 0, 0, DT_REAL, _state, make_automatic);
39973 0 : _sparsematrix_init(&p->sparseh, _state, make_automatic);
39974 0 : ae_vector_init(&p->diagr, 0, DT_REAL, _state, make_automatic);
39975 0 : ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic);
39976 0 : ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic);
39977 0 : ae_vector_init(&p->rawbndl, 0, DT_REAL, _state, make_automatic);
39978 0 : ae_vector_init(&p->rawbndu, 0, DT_REAL, _state, make_automatic);
39979 0 : ae_vector_init(&p->hasbndl, 0, DT_BOOL, _state, make_automatic);
39980 0 : ae_vector_init(&p->hasbndu, 0, DT_BOOL, _state, make_automatic);
39981 0 : ae_matrix_init(&p->denseafull, 0, 0, DT_REAL, _state, make_automatic);
39982 0 : ae_matrix_init(&p->denseamain, 0, 0, DT_REAL, _state, make_automatic);
39983 0 : _sparsematrix_init(&p->sparseafull, _state, make_automatic);
39984 0 : _sparsematrix_init(&p->sparseamain, _state, make_automatic);
39985 0 : _sparsematrix_init(&p->combinedaslack, _state, make_automatic);
39986 0 : ae_vector_init(&p->ascales, 0, DT_REAL, _state, make_automatic);
39987 0 : ae_vector_init(&p->aflips, 0, DT_BOOL, _state, make_automatic);
39988 0 : ae_vector_init(&p->b, 0, DT_REAL, _state, make_automatic);
39989 0 : ae_vector_init(&p->r, 0, DT_REAL, _state, make_automatic);
39990 0 : ae_vector_init(&p->hasr, 0, DT_BOOL, _state, make_automatic);
39991 0 : _vipmvars_init(&p->x0, _state, make_automatic);
39992 0 : _vipmvars_init(&p->current, _state, make_automatic);
39993 0 : _vipmvars_init(&p->best, _state, make_automatic);
39994 0 : _vipmvars_init(&p->trial, _state, make_automatic);
39995 0 : _vipmvars_init(&p->deltaaff, _state, make_automatic);
39996 0 : _vipmvars_init(&p->deltacorr, _state, make_automatic);
39997 0 : ae_vector_init(&p->isfrozen, 0, DT_BOOL, _state, make_automatic);
39998 0 : ae_vector_init(&p->hasgz, 0, DT_BOOL, _state, make_automatic);
39999 0 : ae_vector_init(&p->hasts, 0, DT_BOOL, _state, make_automatic);
40000 0 : ae_vector_init(&p->haswv, 0, DT_BOOL, _state, make_automatic);
40001 0 : ae_vector_init(&p->haspq, 0, DT_BOOL, _state, make_automatic);
40002 0 : ae_vector_init(&p->diagdz, 0, DT_REAL, _state, make_automatic);
40003 0 : ae_vector_init(&p->diagdzi, 0, DT_REAL, _state, make_automatic);
40004 0 : ae_vector_init(&p->diagdziri, 0, DT_REAL, _state, make_automatic);
40005 0 : ae_vector_init(&p->diagds, 0, DT_REAL, _state, make_automatic);
40006 0 : ae_vector_init(&p->diagdsi, 0, DT_REAL, _state, make_automatic);
40007 0 : ae_vector_init(&p->diagdsiri, 0, DT_REAL, _state, make_automatic);
40008 0 : ae_vector_init(&p->diagdw, 0, DT_REAL, _state, make_automatic);
40009 0 : ae_vector_init(&p->diagdwi, 0, DT_REAL, _state, make_automatic);
40010 0 : ae_vector_init(&p->diagdwir, 0, DT_REAL, _state, make_automatic);
40011 0 : ae_vector_init(&p->diagdq, 0, DT_REAL, _state, make_automatic);
40012 0 : ae_vector_init(&p->diagdqi, 0, DT_REAL, _state, make_automatic);
40013 0 : ae_vector_init(&p->diagdqiri, 0, DT_REAL, _state, make_automatic);
40014 0 : ae_vector_init(&p->diagddr, 0, DT_REAL, _state, make_automatic);
40015 0 : ae_vector_init(&p->diagde, 0, DT_REAL, _state, make_automatic);
40016 0 : ae_vector_init(&p->diagder, 0, DT_REAL, _state, make_automatic);
40017 0 : ae_matrix_init(&p->factdensehaug, 0, 0, DT_REAL, _state, make_automatic);
40018 0 : ae_vector_init(&p->factregdhrh, 0, DT_REAL, _state, make_automatic);
40019 0 : ae_vector_init(&p->factinvregdzrz, 0, DT_REAL, _state, make_automatic);
40020 0 : ae_vector_init(&p->factregewave, 0, DT_REAL, _state, make_automatic);
40021 0 : _sparsematrix_init(&p->factsparsekkttmpl, _state, make_automatic);
40022 0 : _sparsematrix_init(&p->factsparsekkt, _state, make_automatic);
40023 0 : ae_vector_init(&p->factsparsekktpivp, 0, DT_INT, _state, make_automatic);
40024 0 : ae_vector_init(&p->facttmpdiag, 0, DT_REAL, _state, make_automatic);
40025 0 : _spcholanalysis_init(&p->ldltanalysis, _state, make_automatic);
40026 0 : ae_vector_init(&p->factsparsediagd, 0, DT_REAL, _state, make_automatic);
40027 0 : _vipmrighthandside_init(&p->rhs, _state, make_automatic);
40028 0 : ae_vector_init(&p->rhsalphacap, 0, DT_REAL, _state, make_automatic);
40029 0 : ae_vector_init(&p->rhsbetacap, 0, DT_REAL, _state, make_automatic);
40030 0 : ae_vector_init(&p->rhsnucap, 0, DT_REAL, _state, make_automatic);
40031 0 : ae_vector_init(&p->rhstaucap, 0, DT_REAL, _state, make_automatic);
40032 0 : ae_vector_init(&p->deltaxy, 0, DT_REAL, _state, make_automatic);
40033 0 : ae_vector_init(&p->tmphx, 0, DT_REAL, _state, make_automatic);
40034 0 : ae_vector_init(&p->tmpax, 0, DT_REAL, _state, make_automatic);
40035 0 : ae_vector_init(&p->tmpaty, 0, DT_REAL, _state, make_automatic);
40036 0 : _vipmvars_init(&p->zerovars, _state, make_automatic);
40037 0 : ae_vector_init(&p->dummyr, 0, DT_REAL, _state, make_automatic);
40038 0 : ae_vector_init(&p->tmpy, 0, DT_REAL, _state, make_automatic);
40039 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
40040 0 : ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic);
40041 0 : ae_vector_init(&p->tmp2, 0, DT_REAL, _state, make_automatic);
40042 0 : ae_matrix_init(&p->tmpr2, 0, 0, DT_REAL, _state, make_automatic);
40043 0 : ae_vector_init(&p->tmplaggrad, 0, DT_REAL, _state, make_automatic);
40044 0 : ae_vector_init(&p->tmpi, 0, DT_INT, _state, make_automatic);
40045 0 : _sparsematrix_init(&p->tmpsparse0, _state, make_automatic);
40046 0 : }
40047 :
40048 :
40049 0 : void _vipmstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
40050 : {
40051 0 : vipmstate *dst = (vipmstate*)_dst;
40052 0 : vipmstate *src = (vipmstate*)_src;
40053 0 : dst->slacksforequalityconstraints = src->slacksforequalityconstraints;
40054 0 : dst->n = src->n;
40055 0 : dst->nmain = src->nmain;
40056 0 : dst->epsp = src->epsp;
40057 0 : dst->epsd = src->epsd;
40058 0 : dst->epsgap = src->epsgap;
40059 0 : dst->islinear = src->islinear;
40060 0 : ae_vector_init_copy(&dst->scl, &src->scl, _state, make_automatic);
40061 0 : ae_vector_init_copy(&dst->invscl, &src->invscl, _state, make_automatic);
40062 0 : ae_vector_init_copy(&dst->xorigin, &src->xorigin, _state, make_automatic);
40063 0 : dst->targetscale = src->targetscale;
40064 0 : ae_vector_init_copy(&dst->c, &src->c, _state, make_automatic);
40065 0 : ae_matrix_init_copy(&dst->denseh, &src->denseh, _state, make_automatic);
40066 0 : _sparsematrix_init_copy(&dst->sparseh, &src->sparseh, _state, make_automatic);
40067 0 : ae_vector_init_copy(&dst->diagr, &src->diagr, _state, make_automatic);
40068 0 : dst->hkind = src->hkind;
40069 0 : ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic);
40070 0 : ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic);
40071 0 : ae_vector_init_copy(&dst->rawbndl, &src->rawbndl, _state, make_automatic);
40072 0 : ae_vector_init_copy(&dst->rawbndu, &src->rawbndu, _state, make_automatic);
40073 0 : ae_vector_init_copy(&dst->hasbndl, &src->hasbndl, _state, make_automatic);
40074 0 : ae_vector_init_copy(&dst->hasbndu, &src->hasbndu, _state, make_automatic);
40075 0 : ae_matrix_init_copy(&dst->denseafull, &src->denseafull, _state, make_automatic);
40076 0 : ae_matrix_init_copy(&dst->denseamain, &src->denseamain, _state, make_automatic);
40077 0 : _sparsematrix_init_copy(&dst->sparseafull, &src->sparseafull, _state, make_automatic);
40078 0 : _sparsematrix_init_copy(&dst->sparseamain, &src->sparseamain, _state, make_automatic);
40079 0 : _sparsematrix_init_copy(&dst->combinedaslack, &src->combinedaslack, _state, make_automatic);
40080 0 : ae_vector_init_copy(&dst->ascales, &src->ascales, _state, make_automatic);
40081 0 : ae_vector_init_copy(&dst->aflips, &src->aflips, _state, make_automatic);
40082 0 : ae_vector_init_copy(&dst->b, &src->b, _state, make_automatic);
40083 0 : ae_vector_init_copy(&dst->r, &src->r, _state, make_automatic);
40084 0 : ae_vector_init_copy(&dst->hasr, &src->hasr, _state, make_automatic);
40085 0 : dst->mdense = src->mdense;
40086 0 : dst->msparse = src->msparse;
40087 0 : _vipmvars_init_copy(&dst->x0, &src->x0, _state, make_automatic);
40088 0 : _vipmvars_init_copy(&dst->current, &src->current, _state, make_automatic);
40089 0 : _vipmvars_init_copy(&dst->best, &src->best, _state, make_automatic);
40090 0 : _vipmvars_init_copy(&dst->trial, &src->trial, _state, make_automatic);
40091 0 : _vipmvars_init_copy(&dst->deltaaff, &src->deltaaff, _state, make_automatic);
40092 0 : _vipmvars_init_copy(&dst->deltacorr, &src->deltacorr, _state, make_automatic);
40093 0 : ae_vector_init_copy(&dst->isfrozen, &src->isfrozen, _state, make_automatic);
40094 0 : ae_vector_init_copy(&dst->hasgz, &src->hasgz, _state, make_automatic);
40095 0 : ae_vector_init_copy(&dst->hasts, &src->hasts, _state, make_automatic);
40096 0 : ae_vector_init_copy(&dst->haswv, &src->haswv, _state, make_automatic);
40097 0 : ae_vector_init_copy(&dst->haspq, &src->haspq, _state, make_automatic);
40098 0 : dst->repiterationscount = src->repiterationscount;
40099 0 : dst->repncholesky = src->repncholesky;
40100 0 : dst->dotrace = src->dotrace;
40101 0 : dst->dodetailedtrace = src->dodetailedtrace;
40102 0 : dst->factorizationtype = src->factorizationtype;
40103 0 : dst->factorizationpoweredup = src->factorizationpoweredup;
40104 0 : dst->factorizationpresent = src->factorizationpresent;
40105 0 : ae_vector_init_copy(&dst->diagdz, &src->diagdz, _state, make_automatic);
40106 0 : ae_vector_init_copy(&dst->diagdzi, &src->diagdzi, _state, make_automatic);
40107 0 : ae_vector_init_copy(&dst->diagdziri, &src->diagdziri, _state, make_automatic);
40108 0 : ae_vector_init_copy(&dst->diagds, &src->diagds, _state, make_automatic);
40109 0 : ae_vector_init_copy(&dst->diagdsi, &src->diagdsi, _state, make_automatic);
40110 0 : ae_vector_init_copy(&dst->diagdsiri, &src->diagdsiri, _state, make_automatic);
40111 0 : ae_vector_init_copy(&dst->diagdw, &src->diagdw, _state, make_automatic);
40112 0 : ae_vector_init_copy(&dst->diagdwi, &src->diagdwi, _state, make_automatic);
40113 0 : ae_vector_init_copy(&dst->diagdwir, &src->diagdwir, _state, make_automatic);
40114 0 : ae_vector_init_copy(&dst->diagdq, &src->diagdq, _state, make_automatic);
40115 0 : ae_vector_init_copy(&dst->diagdqi, &src->diagdqi, _state, make_automatic);
40116 0 : ae_vector_init_copy(&dst->diagdqiri, &src->diagdqiri, _state, make_automatic);
40117 0 : ae_vector_init_copy(&dst->diagddr, &src->diagddr, _state, make_automatic);
40118 0 : ae_vector_init_copy(&dst->diagde, &src->diagde, _state, make_automatic);
40119 0 : ae_vector_init_copy(&dst->diagder, &src->diagder, _state, make_automatic);
40120 0 : ae_matrix_init_copy(&dst->factdensehaug, &src->factdensehaug, _state, make_automatic);
40121 0 : ae_vector_init_copy(&dst->factregdhrh, &src->factregdhrh, _state, make_automatic);
40122 0 : ae_vector_init_copy(&dst->factinvregdzrz, &src->factinvregdzrz, _state, make_automatic);
40123 0 : ae_vector_init_copy(&dst->factregewave, &src->factregewave, _state, make_automatic);
40124 0 : _sparsematrix_init_copy(&dst->factsparsekkttmpl, &src->factsparsekkttmpl, _state, make_automatic);
40125 0 : _sparsematrix_init_copy(&dst->factsparsekkt, &src->factsparsekkt, _state, make_automatic);
40126 0 : ae_vector_init_copy(&dst->factsparsekktpivp, &src->factsparsekktpivp, _state, make_automatic);
40127 0 : ae_vector_init_copy(&dst->facttmpdiag, &src->facttmpdiag, _state, make_automatic);
40128 0 : _spcholanalysis_init_copy(&dst->ldltanalysis, &src->ldltanalysis, _state, make_automatic);
40129 0 : ae_vector_init_copy(&dst->factsparsediagd, &src->factsparsediagd, _state, make_automatic);
40130 0 : _vipmrighthandside_init_copy(&dst->rhs, &src->rhs, _state, make_automatic);
40131 0 : ae_vector_init_copy(&dst->rhsalphacap, &src->rhsalphacap, _state, make_automatic);
40132 0 : ae_vector_init_copy(&dst->rhsbetacap, &src->rhsbetacap, _state, make_automatic);
40133 0 : ae_vector_init_copy(&dst->rhsnucap, &src->rhsnucap, _state, make_automatic);
40134 0 : ae_vector_init_copy(&dst->rhstaucap, &src->rhstaucap, _state, make_automatic);
40135 0 : ae_vector_init_copy(&dst->deltaxy, &src->deltaxy, _state, make_automatic);
40136 0 : ae_vector_init_copy(&dst->tmphx, &src->tmphx, _state, make_automatic);
40137 0 : ae_vector_init_copy(&dst->tmpax, &src->tmpax, _state, make_automatic);
40138 0 : ae_vector_init_copy(&dst->tmpaty, &src->tmpaty, _state, make_automatic);
40139 0 : _vipmvars_init_copy(&dst->zerovars, &src->zerovars, _state, make_automatic);
40140 0 : ae_vector_init_copy(&dst->dummyr, &src->dummyr, _state, make_automatic);
40141 0 : ae_vector_init_copy(&dst->tmpy, &src->tmpy, _state, make_automatic);
40142 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
40143 0 : ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic);
40144 0 : ae_vector_init_copy(&dst->tmp2, &src->tmp2, _state, make_automatic);
40145 0 : ae_matrix_init_copy(&dst->tmpr2, &src->tmpr2, _state, make_automatic);
40146 0 : ae_vector_init_copy(&dst->tmplaggrad, &src->tmplaggrad, _state, make_automatic);
40147 0 : ae_vector_init_copy(&dst->tmpi, &src->tmpi, _state, make_automatic);
40148 0 : _sparsematrix_init_copy(&dst->tmpsparse0, &src->tmpsparse0, _state, make_automatic);
40149 0 : }
40150 :
40151 :
40152 0 : void _vipmstate_clear(void* _p)
40153 : {
40154 0 : vipmstate *p = (vipmstate*)_p;
40155 0 : ae_touch_ptr((void*)p);
40156 0 : ae_vector_clear(&p->scl);
40157 0 : ae_vector_clear(&p->invscl);
40158 0 : ae_vector_clear(&p->xorigin);
40159 0 : ae_vector_clear(&p->c);
40160 0 : ae_matrix_clear(&p->denseh);
40161 0 : _sparsematrix_clear(&p->sparseh);
40162 0 : ae_vector_clear(&p->diagr);
40163 0 : ae_vector_clear(&p->bndl);
40164 0 : ae_vector_clear(&p->bndu);
40165 0 : ae_vector_clear(&p->rawbndl);
40166 0 : ae_vector_clear(&p->rawbndu);
40167 0 : ae_vector_clear(&p->hasbndl);
40168 0 : ae_vector_clear(&p->hasbndu);
40169 0 : ae_matrix_clear(&p->denseafull);
40170 0 : ae_matrix_clear(&p->denseamain);
40171 0 : _sparsematrix_clear(&p->sparseafull);
40172 0 : _sparsematrix_clear(&p->sparseamain);
40173 0 : _sparsematrix_clear(&p->combinedaslack);
40174 0 : ae_vector_clear(&p->ascales);
40175 0 : ae_vector_clear(&p->aflips);
40176 0 : ae_vector_clear(&p->b);
40177 0 : ae_vector_clear(&p->r);
40178 0 : ae_vector_clear(&p->hasr);
40179 0 : _vipmvars_clear(&p->x0);
40180 0 : _vipmvars_clear(&p->current);
40181 0 : _vipmvars_clear(&p->best);
40182 0 : _vipmvars_clear(&p->trial);
40183 0 : _vipmvars_clear(&p->deltaaff);
40184 0 : _vipmvars_clear(&p->deltacorr);
40185 0 : ae_vector_clear(&p->isfrozen);
40186 0 : ae_vector_clear(&p->hasgz);
40187 0 : ae_vector_clear(&p->hasts);
40188 0 : ae_vector_clear(&p->haswv);
40189 0 : ae_vector_clear(&p->haspq);
40190 0 : ae_vector_clear(&p->diagdz);
40191 0 : ae_vector_clear(&p->diagdzi);
40192 0 : ae_vector_clear(&p->diagdziri);
40193 0 : ae_vector_clear(&p->diagds);
40194 0 : ae_vector_clear(&p->diagdsi);
40195 0 : ae_vector_clear(&p->diagdsiri);
40196 0 : ae_vector_clear(&p->diagdw);
40197 0 : ae_vector_clear(&p->diagdwi);
40198 0 : ae_vector_clear(&p->diagdwir);
40199 0 : ae_vector_clear(&p->diagdq);
40200 0 : ae_vector_clear(&p->diagdqi);
40201 0 : ae_vector_clear(&p->diagdqiri);
40202 0 : ae_vector_clear(&p->diagddr);
40203 0 : ae_vector_clear(&p->diagde);
40204 0 : ae_vector_clear(&p->diagder);
40205 0 : ae_matrix_clear(&p->factdensehaug);
40206 0 : ae_vector_clear(&p->factregdhrh);
40207 0 : ae_vector_clear(&p->factinvregdzrz);
40208 0 : ae_vector_clear(&p->factregewave);
40209 0 : _sparsematrix_clear(&p->factsparsekkttmpl);
40210 0 : _sparsematrix_clear(&p->factsparsekkt);
40211 0 : ae_vector_clear(&p->factsparsekktpivp);
40212 0 : ae_vector_clear(&p->facttmpdiag);
40213 0 : _spcholanalysis_clear(&p->ldltanalysis);
40214 0 : ae_vector_clear(&p->factsparsediagd);
40215 0 : _vipmrighthandside_clear(&p->rhs);
40216 0 : ae_vector_clear(&p->rhsalphacap);
40217 0 : ae_vector_clear(&p->rhsbetacap);
40218 0 : ae_vector_clear(&p->rhsnucap);
40219 0 : ae_vector_clear(&p->rhstaucap);
40220 0 : ae_vector_clear(&p->deltaxy);
40221 0 : ae_vector_clear(&p->tmphx);
40222 0 : ae_vector_clear(&p->tmpax);
40223 0 : ae_vector_clear(&p->tmpaty);
40224 0 : _vipmvars_clear(&p->zerovars);
40225 0 : ae_vector_clear(&p->dummyr);
40226 0 : ae_vector_clear(&p->tmpy);
40227 0 : ae_vector_clear(&p->tmp0);
40228 0 : ae_vector_clear(&p->tmp1);
40229 0 : ae_vector_clear(&p->tmp2);
40230 0 : ae_matrix_clear(&p->tmpr2);
40231 0 : ae_vector_clear(&p->tmplaggrad);
40232 0 : ae_vector_clear(&p->tmpi);
40233 0 : _sparsematrix_clear(&p->tmpsparse0);
40234 0 : }
40235 :
40236 :
40237 0 : void _vipmstate_destroy(void* _p)
40238 : {
40239 0 : vipmstate *p = (vipmstate*)_p;
40240 0 : ae_touch_ptr((void*)p);
40241 0 : ae_vector_destroy(&p->scl);
40242 0 : ae_vector_destroy(&p->invscl);
40243 0 : ae_vector_destroy(&p->xorigin);
40244 0 : ae_vector_destroy(&p->c);
40245 0 : ae_matrix_destroy(&p->denseh);
40246 0 : _sparsematrix_destroy(&p->sparseh);
40247 0 : ae_vector_destroy(&p->diagr);
40248 0 : ae_vector_destroy(&p->bndl);
40249 0 : ae_vector_destroy(&p->bndu);
40250 0 : ae_vector_destroy(&p->rawbndl);
40251 0 : ae_vector_destroy(&p->rawbndu);
40252 0 : ae_vector_destroy(&p->hasbndl);
40253 0 : ae_vector_destroy(&p->hasbndu);
40254 0 : ae_matrix_destroy(&p->denseafull);
40255 0 : ae_matrix_destroy(&p->denseamain);
40256 0 : _sparsematrix_destroy(&p->sparseafull);
40257 0 : _sparsematrix_destroy(&p->sparseamain);
40258 0 : _sparsematrix_destroy(&p->combinedaslack);
40259 0 : ae_vector_destroy(&p->ascales);
40260 0 : ae_vector_destroy(&p->aflips);
40261 0 : ae_vector_destroy(&p->b);
40262 0 : ae_vector_destroy(&p->r);
40263 0 : ae_vector_destroy(&p->hasr);
40264 0 : _vipmvars_destroy(&p->x0);
40265 0 : _vipmvars_destroy(&p->current);
40266 0 : _vipmvars_destroy(&p->best);
40267 0 : _vipmvars_destroy(&p->trial);
40268 0 : _vipmvars_destroy(&p->deltaaff);
40269 0 : _vipmvars_destroy(&p->deltacorr);
40270 0 : ae_vector_destroy(&p->isfrozen);
40271 0 : ae_vector_destroy(&p->hasgz);
40272 0 : ae_vector_destroy(&p->hasts);
40273 0 : ae_vector_destroy(&p->haswv);
40274 0 : ae_vector_destroy(&p->haspq);
40275 0 : ae_vector_destroy(&p->diagdz);
40276 0 : ae_vector_destroy(&p->diagdzi);
40277 0 : ae_vector_destroy(&p->diagdziri);
40278 0 : ae_vector_destroy(&p->diagds);
40279 0 : ae_vector_destroy(&p->diagdsi);
40280 0 : ae_vector_destroy(&p->diagdsiri);
40281 0 : ae_vector_destroy(&p->diagdw);
40282 0 : ae_vector_destroy(&p->diagdwi);
40283 0 : ae_vector_destroy(&p->diagdwir);
40284 0 : ae_vector_destroy(&p->diagdq);
40285 0 : ae_vector_destroy(&p->diagdqi);
40286 0 : ae_vector_destroy(&p->diagdqiri);
40287 0 : ae_vector_destroy(&p->diagddr);
40288 0 : ae_vector_destroy(&p->diagde);
40289 0 : ae_vector_destroy(&p->diagder);
40290 0 : ae_matrix_destroy(&p->factdensehaug);
40291 0 : ae_vector_destroy(&p->factregdhrh);
40292 0 : ae_vector_destroy(&p->factinvregdzrz);
40293 0 : ae_vector_destroy(&p->factregewave);
40294 0 : _sparsematrix_destroy(&p->factsparsekkttmpl);
40295 0 : _sparsematrix_destroy(&p->factsparsekkt);
40296 0 : ae_vector_destroy(&p->factsparsekktpivp);
40297 0 : ae_vector_destroy(&p->facttmpdiag);
40298 0 : _spcholanalysis_destroy(&p->ldltanalysis);
40299 0 : ae_vector_destroy(&p->factsparsediagd);
40300 0 : _vipmrighthandside_destroy(&p->rhs);
40301 0 : ae_vector_destroy(&p->rhsalphacap);
40302 0 : ae_vector_destroy(&p->rhsbetacap);
40303 0 : ae_vector_destroy(&p->rhsnucap);
40304 0 : ae_vector_destroy(&p->rhstaucap);
40305 0 : ae_vector_destroy(&p->deltaxy);
40306 0 : ae_vector_destroy(&p->tmphx);
40307 0 : ae_vector_destroy(&p->tmpax);
40308 0 : ae_vector_destroy(&p->tmpaty);
40309 0 : _vipmvars_destroy(&p->zerovars);
40310 0 : ae_vector_destroy(&p->dummyr);
40311 0 : ae_vector_destroy(&p->tmpy);
40312 0 : ae_vector_destroy(&p->tmp0);
40313 0 : ae_vector_destroy(&p->tmp1);
40314 0 : ae_vector_destroy(&p->tmp2);
40315 0 : ae_matrix_destroy(&p->tmpr2);
40316 0 : ae_vector_destroy(&p->tmplaggrad);
40317 0 : ae_vector_destroy(&p->tmpi);
40318 0 : _sparsematrix_destroy(&p->tmpsparse0);
40319 0 : }
40320 :
40321 :
40322 : #endif
40323 : #if defined(AE_COMPILE_NLCSQP) || !defined(AE_PARTIAL_BUILD)
40324 :
40325 :
40326 0 : void minsqpinitbuf(/* Real */ ae_vector* bndl,
40327 : /* Real */ ae_vector* bndu,
40328 : /* Real */ ae_vector* s,
40329 : /* Real */ ae_vector* x0,
40330 : ae_int_t n,
40331 : /* Real */ ae_matrix* cleic,
40332 : /* Integer */ ae_vector* lcsrcidx,
40333 : ae_int_t nec,
40334 : ae_int_t nic,
40335 : ae_int_t nlec,
40336 : ae_int_t nlic,
40337 : double epsx,
40338 : ae_int_t maxits,
40339 : minsqpstate* state,
40340 : ae_state *_state)
40341 : {
40342 : ae_int_t i;
40343 : ae_int_t j;
40344 : double v;
40345 : double vv;
40346 :
40347 :
40348 0 : state->n = n;
40349 0 : state->nec = nec;
40350 0 : state->nic = nic;
40351 0 : state->nlec = nlec;
40352 0 : state->nlic = nlic;
40353 :
40354 : /*
40355 : * Prepare RCOMM state
40356 : */
40357 0 : ae_vector_set_length(&state->rstate.ia, 9+1, _state);
40358 0 : ae_vector_set_length(&state->rstate.ba, 3+1, _state);
40359 0 : ae_vector_set_length(&state->rstate.ra, 6+1, _state);
40360 0 : state->rstate.stage = -1;
40361 0 : state->needfij = ae_false;
40362 0 : state->xupdated = ae_false;
40363 0 : ae_vector_set_length(&state->x, n, _state);
40364 0 : ae_vector_set_length(&state->fi, 1+nlec+nlic, _state);
40365 0 : ae_matrix_set_length(&state->j, 1+nlec+nlic, n, _state);
40366 :
40367 : /*
40368 : * Allocate memory.
40369 : */
40370 0 : rvectorsetlengthatleast(&state->s, n, _state);
40371 0 : rvectorsetlengthatleast(&state->step0x, n, _state);
40372 0 : rvectorsetlengthatleast(&state->stepkx, n, _state);
40373 0 : rvectorsetlengthatleast(&state->backupx, n, _state);
40374 0 : rvectorsetlengthatleast(&state->step0fi, 1+nlec+nlic, _state);
40375 0 : rvectorsetlengthatleast(&state->stepkfi, 1+nlec+nlic, _state);
40376 0 : rvectorsetlengthatleast(&state->backupfi, 1+nlec+nlic, _state);
40377 0 : rmatrixsetlengthatleast(&state->step0j, 1+nlec+nlic, n, _state);
40378 0 : rmatrixsetlengthatleast(&state->stepkj, 1+nlec+nlic, n, _state);
40379 0 : rvectorsetlengthatleast(&state->fscales, 1+nlec+nlic, _state);
40380 0 : rvectorsetlengthatleast(&state->tracegamma, 1+nlec+nlic, _state);
40381 0 : rvectorsetlengthatleast(&state->dummylagmult, nec+nic+nlec+nlic, _state);
40382 0 : bvectorsetlengthatleast(&state->hasbndl, n, _state);
40383 0 : bvectorsetlengthatleast(&state->hasbndu, n, _state);
40384 0 : rvectorsetlengthatleast(&state->scaledbndl, n, _state);
40385 0 : rvectorsetlengthatleast(&state->scaledbndu, n, _state);
40386 0 : rmatrixsetlengthatleast(&state->scaledcleic, nec+nic, n+1, _state);
40387 0 : ivectorsetlengthatleast(&state->lcsrcidx, nec+nic, _state);
40388 0 : rallocv(nec+nic+nlec+nlic, &state->meritlagmult, _state);
40389 0 : rsetallocm(nlcsqp_penaltymemlen, nec+nic+nlec+nlic, 0.0, &state->abslagmemory, _state);
40390 :
40391 : /*
40392 : * Prepare scaled problem
40393 : */
40394 0 : for(i=0; i<=n-1; i++)
40395 : {
40396 0 : state->hasbndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state);
40397 0 : state->hasbndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state);
40398 0 : if( state->hasbndl.ptr.p_bool[i] )
40399 : {
40400 0 : state->scaledbndl.ptr.p_double[i] = bndl->ptr.p_double[i]/s->ptr.p_double[i];
40401 : }
40402 0 : if( state->hasbndu.ptr.p_bool[i] )
40403 : {
40404 0 : state->scaledbndu.ptr.p_double[i] = bndu->ptr.p_double[i]/s->ptr.p_double[i];
40405 : }
40406 0 : if( state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i] )
40407 : {
40408 0 : ae_assert(ae_fp_less_eq(bndl->ptr.p_double[i],bndu->ptr.p_double[i]), "SQP: integrity check failed, box constraints are inconsistent", _state);
40409 : }
40410 0 : state->step0x.ptr.p_double[i] = x0->ptr.p_double[i]/s->ptr.p_double[i];
40411 0 : state->s.ptr.p_double[i] = s->ptr.p_double[i];
40412 : }
40413 0 : for(i=0; i<=nec+nic-1; i++)
40414 : {
40415 :
40416 : /*
40417 : * Permutation
40418 : */
40419 0 : state->lcsrcidx.ptr.p_int[i] = lcsrcidx->ptr.p_int[i];
40420 :
40421 : /*
40422 : * Scale and normalize linear constraints
40423 : */
40424 0 : vv = 0.0;
40425 0 : for(j=0; j<=n-1; j++)
40426 : {
40427 0 : v = cleic->ptr.pp_double[i][j]*s->ptr.p_double[j];
40428 0 : state->scaledcleic.ptr.pp_double[i][j] = v;
40429 0 : vv = vv+v*v;
40430 : }
40431 0 : vv = ae_sqrt(vv, _state);
40432 0 : state->scaledcleic.ptr.pp_double[i][n] = cleic->ptr.pp_double[i][n];
40433 0 : if( ae_fp_greater(vv,(double)(0)) )
40434 : {
40435 0 : for(j=0; j<=n; j++)
40436 : {
40437 0 : state->scaledcleic.ptr.pp_double[i][j] = state->scaledcleic.ptr.pp_double[i][j]/vv;
40438 : }
40439 : }
40440 : }
40441 :
40442 : /*
40443 : * Initial enforcement of box constraints
40444 : */
40445 0 : for(i=0; i<=n-1; i++)
40446 : {
40447 0 : if( state->hasbndl.ptr.p_bool[i] )
40448 : {
40449 0 : state->step0x.ptr.p_double[i] = ae_maxreal(state->step0x.ptr.p_double[i], state->scaledbndl.ptr.p_double[i], _state);
40450 : }
40451 0 : if( state->hasbndu.ptr.p_bool[i] )
40452 : {
40453 0 : state->step0x.ptr.p_double[i] = ae_minreal(state->step0x.ptr.p_double[i], state->scaledbndu.ptr.p_double[i], _state);
40454 : }
40455 : }
40456 :
40457 : /*
40458 : * Stopping criteria
40459 : */
40460 0 : state->epsx = epsx;
40461 0 : state->maxits = maxits;
40462 :
40463 : /*
40464 : * Report fields
40465 : */
40466 0 : state->repsimplexiterations = 0;
40467 0 : state->repsimplexiterations1 = 0;
40468 0 : state->repsimplexiterations2 = 0;
40469 0 : state->repsimplexiterations3 = 0;
40470 0 : state->repterminationtype = 0;
40471 0 : state->repbcerr = (double)(0);
40472 0 : state->repbcidx = -1;
40473 0 : state->replcerr = (double)(0);
40474 0 : state->replcidx = -1;
40475 0 : state->repnlcerr = (double)(0);
40476 0 : state->repnlcidx = -1;
40477 0 : state->repiterationscount = 0;
40478 :
40479 : /*
40480 : * Integrity checks
40481 : */
40482 0 : ae_assert(ae_fp_less(nlcsqp_sqpdeltadecrease,nlcsqp_sqpdeltaincrease), "MinSQP: integrity check failed", _state);
40483 0 : }
40484 :
40485 :
40486 : /*************************************************************************
40487 : This function performs actual processing for SQP algorithm. It expects
40488 : that caller redirects its reverse communication requests NeedFiJ/XUpdated
40489 : to external user who will provide analytic derivative (or handle reports
40490 : about progress).
40491 :
40492 : In case external user does not have analytic derivative, it is responsibility
40493 : of caller to intercept NeedFiJ request and replace it with appropriate
40494 : numerical differentiation scheme.
40495 :
40496 : Results are stored:
40497 : * point - in State.StepKX
40498 :
40499 : IMPORTANT: this function works with scaled problem formulation; it is
40500 : responsibility of the caller to unscale request and scale
40501 : Jacobian.
40502 :
40503 : NOTE: SMonitor is expected to be correctly initialized smoothness monitor.
40504 :
40505 : -- ALGLIB --
40506 : Copyright 05.03.2018 by Bochkanov Sergey
40507 : *************************************************************************/
40508 0 : ae_bool minsqpiteration(minsqpstate* state,
40509 : smoothnessmonitor* smonitor,
40510 : ae_bool userterminationneeded,
40511 : ae_state *_state)
40512 : {
40513 : ae_int_t n;
40514 : ae_int_t nslack;
40515 : ae_int_t nec;
40516 : ae_int_t nic;
40517 : ae_int_t nlec;
40518 : ae_int_t nlic;
40519 : ae_int_t i;
40520 : ae_int_t j;
40521 : double v;
40522 : double vv;
40523 : double mx;
40524 : ae_int_t status;
40525 : double deltamax;
40526 : double multiplyby;
40527 : double setscaleto;
40528 : double prevtrustrad;
40529 : ae_int_t subiterationidx;
40530 : ae_bool trustradstagnated;
40531 : ae_bool dotrace;
40532 : ae_bool dodetailedtrace;
40533 : ae_bool increasebigc;
40534 : ae_bool result;
40535 :
40536 :
40537 :
40538 : /*
40539 : * Reverse communication preparations
40540 : * I know it looks ugly, but it works the same way
40541 : * anywhere from C++ to Python.
40542 : *
40543 : * This code initializes locals by:
40544 : * * random values determined during code
40545 : * generation - on first subroutine call
40546 : * * values from previous call - on subsequent calls
40547 : */
40548 0 : if( state->rstate.stage>=0 )
40549 : {
40550 0 : n = state->rstate.ia.ptr.p_int[0];
40551 0 : nslack = state->rstate.ia.ptr.p_int[1];
40552 0 : nec = state->rstate.ia.ptr.p_int[2];
40553 0 : nic = state->rstate.ia.ptr.p_int[3];
40554 0 : nlec = state->rstate.ia.ptr.p_int[4];
40555 0 : nlic = state->rstate.ia.ptr.p_int[5];
40556 0 : i = state->rstate.ia.ptr.p_int[6];
40557 0 : j = state->rstate.ia.ptr.p_int[7];
40558 0 : status = state->rstate.ia.ptr.p_int[8];
40559 0 : subiterationidx = state->rstate.ia.ptr.p_int[9];
40560 0 : trustradstagnated = state->rstate.ba.ptr.p_bool[0];
40561 0 : dotrace = state->rstate.ba.ptr.p_bool[1];
40562 0 : dodetailedtrace = state->rstate.ba.ptr.p_bool[2];
40563 0 : increasebigc = state->rstate.ba.ptr.p_bool[3];
40564 0 : v = state->rstate.ra.ptr.p_double[0];
40565 0 : vv = state->rstate.ra.ptr.p_double[1];
40566 0 : mx = state->rstate.ra.ptr.p_double[2];
40567 0 : deltamax = state->rstate.ra.ptr.p_double[3];
40568 0 : multiplyby = state->rstate.ra.ptr.p_double[4];
40569 0 : setscaleto = state->rstate.ra.ptr.p_double[5];
40570 0 : prevtrustrad = state->rstate.ra.ptr.p_double[6];
40571 : }
40572 : else
40573 : {
40574 0 : n = 359;
40575 0 : nslack = -58;
40576 0 : nec = -919;
40577 0 : nic = -909;
40578 0 : nlec = 81;
40579 0 : nlic = 255;
40580 0 : i = 74;
40581 0 : j = -788;
40582 0 : status = 809;
40583 0 : subiterationidx = 205;
40584 0 : trustradstagnated = ae_false;
40585 0 : dotrace = ae_true;
40586 0 : dodetailedtrace = ae_false;
40587 0 : increasebigc = ae_true;
40588 0 : v = -541;
40589 0 : vv = -698;
40590 0 : mx = -900;
40591 0 : deltamax = -318;
40592 0 : multiplyby = -940;
40593 0 : setscaleto = 1016;
40594 0 : prevtrustrad = -229;
40595 : }
40596 0 : if( state->rstate.stage==0 )
40597 : {
40598 0 : goto lbl_0;
40599 : }
40600 0 : if( state->rstate.stage==1 )
40601 : {
40602 0 : goto lbl_1;
40603 : }
40604 0 : if( state->rstate.stage==2 )
40605 : {
40606 0 : goto lbl_2;
40607 : }
40608 :
40609 : /*
40610 : * Routine body
40611 : */
40612 0 : n = state->n;
40613 0 : nec = state->nec;
40614 0 : nic = state->nic;
40615 0 : nlec = state->nlec;
40616 0 : nlic = state->nlic;
40617 0 : nslack = n+2*(nec+nlec)+(nic+nlic);
40618 0 : dotrace = ae_is_trace_enabled("SQP");
40619 0 : dodetailedtrace = dotrace&&ae_is_trace_enabled("SQP.DETAILED");
40620 :
40621 : /*
40622 : * Prepare rcomm interface
40623 : */
40624 0 : state->needfij = ae_false;
40625 0 : state->xupdated = ae_false;
40626 :
40627 : /*
40628 : * Initialize algorithm data:
40629 : * * Lagrangian and "Big C" estimates
40630 : * * trust region
40631 : * * initial function scales (vector of 1's)
40632 : * * current approximation of the Hessian matrix H (unit matrix)
40633 : * * initial linearized constraints
40634 : * * initial violation of linear/nonlinear constraints
40635 : */
40636 0 : state->fstagnationcnt = 0;
40637 0 : state->trustradstagnationcnt = 0;
40638 0 : state->trustrad = nlcsqp_inittrustrad;
40639 0 : for(i=0; i<=nlec+nlic; i++)
40640 : {
40641 0 : state->fscales.ptr.p_double[i] = 1.0;
40642 0 : state->tracegamma.ptr.p_double[i] = 0.0;
40643 : }
40644 0 : state->haslagmult = ae_false;
40645 :
40646 : /*
40647 : * Avoid spurious warnings about possibly uninitialized vars
40648 : */
40649 0 : status = 0;
40650 :
40651 : /*
40652 : * Evaluate function vector and Jacobian at Step0X, send first location report.
40653 : * Compute initial violation of constraints.
40654 : */
40655 0 : nlcsqp_sqpsendx(state, &state->step0x, _state);
40656 0 : state->needfij = ae_true;
40657 0 : state->rstate.stage = 0;
40658 0 : goto lbl_rcomm;
40659 0 : lbl_0:
40660 0 : state->needfij = ae_false;
40661 0 : if( !nlcsqp_sqpretrievefij(state, &state->step0fi, &state->step0j, _state) )
40662 : {
40663 :
40664 : /*
40665 : * Failed to retrieve function/Jaconian, infinities detected!
40666 : */
40667 0 : for(i=0; i<=n-1; i++)
40668 : {
40669 0 : state->stepkx.ptr.p_double[i] = state->step0x.ptr.p_double[i];
40670 : }
40671 0 : state->repterminationtype = -8;
40672 0 : result = ae_false;
40673 0 : return result;
40674 : }
40675 0 : nlcsqp_sqpcopystate(state, &state->step0x, &state->step0fi, &state->step0j, &state->stepkx, &state->stepkfi, &state->stepkj, _state);
40676 0 : nlcsqp_sqpsendx(state, &state->stepkx, _state);
40677 0 : state->f = state->stepkfi.ptr.p_double[0]*state->fscales.ptr.p_double[0];
40678 0 : state->xupdated = ae_true;
40679 0 : state->rstate.stage = 1;
40680 0 : goto lbl_rcomm;
40681 0 : lbl_1:
40682 0 : state->xupdated = ae_false;
40683 0 : checklcviolation(&state->scaledcleic, &state->lcsrcidx, nec, nic, &state->stepkx, n, &state->replcerr, &state->replcidx, _state);
40684 0 : unscaleandchecknlcviolation(&state->stepkfi, &state->fscales, nlec, nlic, &state->repnlcerr, &state->repnlcidx, _state);
40685 :
40686 : /*
40687 : * Trace output (if needed)
40688 : */
40689 0 : if( dotrace )
40690 : {
40691 0 : ae_trace("\n\n");
40692 0 : ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n");
40693 0 : ae_trace("// SQP SOLVER STARTED //\n");
40694 0 : ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n");
40695 : }
40696 :
40697 : /*
40698 : * Perform outer (NLC) iterations
40699 : */
40700 0 : state->bigc = (double)(500);
40701 0 : nlcsqp_initqpsubsolver(state, &state->subsolver, _state);
40702 0 : lbl_3:
40703 : if( ae_false )
40704 : {
40705 : goto lbl_4;
40706 : }
40707 :
40708 : /*
40709 : * Before beginning new outer iteration:
40710 : * * renormalize target function and/or constraints, if some of them have too large magnitudes
40711 : * * save initial point for the outer iteration
40712 : */
40713 0 : for(i=0; i<=nlec+nlic; i++)
40714 : {
40715 :
40716 : /*
40717 : * Determine (a) multiplicative coefficient applied to function value
40718 : * and Jacobian row, and (b) new value of the function scale.
40719 : */
40720 0 : mx = (double)(0);
40721 0 : for(j=0; j<=n-1; j++)
40722 : {
40723 0 : mx = ae_maxreal(mx, ae_fabs(state->stepkj.ptr.pp_double[i][j], _state), _state);
40724 : }
40725 0 : multiplyby = 1.0;
40726 0 : setscaleto = state->fscales.ptr.p_double[i];
40727 0 : if( ae_fp_greater_eq(mx,nlcsqp_sqpbigscale) )
40728 : {
40729 0 : multiplyby = 1/mx;
40730 0 : setscaleto = state->fscales.ptr.p_double[i]*mx;
40731 : }
40732 0 : if( ae_fp_less_eq(mx,nlcsqp_sqpsmallscale)&&ae_fp_greater(state->fscales.ptr.p_double[i],1.0) )
40733 : {
40734 0 : if( ae_fp_greater(state->fscales.ptr.p_double[i]*mx,(double)(1)) )
40735 : {
40736 0 : multiplyby = 1/mx;
40737 0 : setscaleto = state->fscales.ptr.p_double[i]*mx;
40738 : }
40739 : else
40740 : {
40741 0 : multiplyby = state->fscales.ptr.p_double[i];
40742 0 : setscaleto = 1.0;
40743 : }
40744 : }
40745 0 : if( ae_fp_neq(multiplyby,1.0) )
40746 : {
40747 :
40748 : /*
40749 : * Function #I needs renormalization:
40750 : * * update function vector element and Jacobian matrix row
40751 : * * update FScales[] and TraceGamma[] arrays
40752 : */
40753 0 : state->stepkfi.ptr.p_double[i] = state->stepkfi.ptr.p_double[i]*multiplyby;
40754 0 : for(j=0; j<=n-1; j++)
40755 : {
40756 0 : state->stepkj.ptr.pp_double[i][j] = state->stepkj.ptr.pp_double[i][j]*multiplyby;
40757 : }
40758 0 : state->fscales.ptr.p_double[i] = setscaleto;
40759 0 : state->tracegamma.ptr.p_double[i] = state->tracegamma.ptr.p_double[i]*multiplyby;
40760 : }
40761 : }
40762 :
40763 : /*
40764 : * Trace output (if needed)
40765 : */
40766 0 : if( dotrace )
40767 : {
40768 0 : ae_trace("\n=== OUTER ITERATION %5d STARTED ==================================================================\n",
40769 0 : (int)(state->repiterationscount));
40770 0 : if( dodetailedtrace )
40771 : {
40772 0 : ae_trace("> printing raw data (prior to applying variable and function scales)\n");
40773 0 : ae_trace("X (raw) = ");
40774 0 : tracevectorunscaledunshiftedautoprec(&state->step0x, n, &state->s, ae_true, &state->s, ae_false, _state);
40775 0 : ae_trace("\n");
40776 0 : ae_trace("> printing scaled data (after applying variable and function scales)\n");
40777 0 : ae_trace("X (scaled) = ");
40778 0 : tracevectorautoprec(&state->step0x, 0, n, _state);
40779 0 : ae_trace("\n");
40780 0 : ae_trace("FScales = ");
40781 0 : tracevectorautoprec(&state->fscales, 0, 1+nlec+nlic, _state);
40782 0 : ae_trace("\n");
40783 0 : ae_trace("GammaScl = ");
40784 0 : tracevectorautoprec(&state->tracegamma, 0, 1+nlec+nlic, _state);
40785 0 : ae_trace("\n");
40786 0 : ae_trace("Fi (scaled) = ");
40787 0 : tracevectorautoprec(&state->stepkfi, 0, 1+nlec+nlic, _state);
40788 0 : ae_trace("\n");
40789 0 : ae_trace("|Ji| (scaled) = ");
40790 0 : tracerownrm1autoprec(&state->stepkj, 0, 1+nlec+nlic, 0, n, _state);
40791 0 : ae_trace("\n");
40792 : }
40793 0 : mx = (double)(0);
40794 0 : for(i=1; i<=nlec; i++)
40795 : {
40796 0 : mx = ae_maxreal(mx, ae_fabs(state->stepkfi.ptr.p_double[i], _state), _state);
40797 : }
40798 0 : for(i=nlec+1; i<=nlec+nlic; i++)
40799 : {
40800 0 : mx = ae_maxreal(mx, state->stepkfi.ptr.p_double[i], _state);
40801 : }
40802 0 : ae_trace("trustRad = %0.3e\n",
40803 0 : (double)(state->trustrad));
40804 0 : ae_trace("lin.violation = %0.3e (scaled violation of linear constraints)\n",
40805 0 : (double)(state->replcerr));
40806 0 : ae_trace("nlc.violation = %0.3e (scaled violation of nonlinear constraints)\n",
40807 : (double)(mx));
40808 0 : ae_trace("gamma0 = %0.3e (Hessian 2-norm estimate for target)\n",
40809 0 : (double)(state->tracegamma.ptr.p_double[0]));
40810 0 : j = 0;
40811 0 : for(i=0; i<=nlec+nlic; i++)
40812 : {
40813 0 : if( ae_fp_greater(state->tracegamma.ptr.p_double[i],state->tracegamma.ptr.p_double[j]) )
40814 : {
40815 0 : j = i;
40816 : }
40817 : }
40818 0 : ae_trace("gammaMax = %0.3e (maximum over Hessian 2-norm estimates for target/constraints)\n",
40819 0 : (double)(state->tracegamma.ptr.p_double[j]));
40820 0 : ae_trace("arg(gammaMax) = %0d (function index; 0 for target, >0 for nonlinear constraints)\n",
40821 : (int)(j));
40822 : }
40823 :
40824 : /*
40825 : * PHASE 2
40826 : *
40827 : * This phase is a primary part of the algorithm which is responsible for its
40828 : * convergence properties.
40829 : *
40830 : * It solves QP subproblem with possible activation and deactivation of constraints
40831 : * and then starts backtracking (step length is bounded by 1.0) merit function search
40832 : * (with second-order correction to deal with Maratos effect) on the direction produced
40833 : * by QP subproblem.
40834 : *
40835 : * This phase is everything we need to in order to have convergence; however,
40836 : * it has one performance-related issue: using "general" interior point QP solver
40837 : * results in slow solution times. Fast equality-constrained phase is essential for
40838 : * the quick convergence.
40839 : */
40840 0 : nlcsqp_qpsubsolversetalgoipm(&state->subsolver, _state);
40841 0 : nlcsqp_sqpcopystate(state, &state->stepkx, &state->stepkfi, &state->stepkj, &state->step0x, &state->step0fi, &state->step0j, _state);
40842 0 : nlcsqp_meritphaseinit(&state->meritstate, &state->stepkx, &state->stepkfi, &state->stepkj, n, nec, nic, nlec, nlic, &state->abslagmemory, nlcsqp_penaltymemlen, _state);
40843 0 : lbl_5:
40844 0 : if( !nlcsqp_meritphaseiteration(state, &state->meritstate, smonitor, userterminationneeded, _state) )
40845 : {
40846 0 : goto lbl_6;
40847 : }
40848 0 : state->rstate.stage = 2;
40849 0 : goto lbl_rcomm;
40850 0 : lbl_2:
40851 0 : goto lbl_5;
40852 0 : lbl_6:
40853 0 : nlcsqp_meritphaseresults(&state->meritstate, &state->stepkx, &state->stepkfi, &state->stepkj, &state->meritlagmult, &increasebigc, &status, _state);
40854 0 : if( status==0 )
40855 : {
40856 0 : goto lbl_4;
40857 : }
40858 0 : ae_assert(status>0, "MinSQPIteration: integrity check failed", _state);
40859 0 : state->haslagmult = ae_true;
40860 0 : for(i=nlcsqp_penaltymemlen-1; i>=1; i--)
40861 : {
40862 0 : rcopyrr(nec+nic+nlec+nlic, &state->abslagmemory, i-1, &state->abslagmemory, i, _state);
40863 : }
40864 0 : for(i=0; i<=nec+nic+nlec+nlic-1; i++)
40865 : {
40866 0 : state->abslagmemory.ptr.pp_double[0][i] = ae_fabs(state->meritlagmult.ptr.p_double[i], _state);
40867 : }
40868 :
40869 : /*
40870 : * Caller requested to update BigC - L1 penalty coefficient for linearized constraint violation
40871 : */
40872 0 : if( increasebigc )
40873 : {
40874 0 : state->bigc = ae_minreal(10*state->bigc, nlcsqp_maxbigc, _state);
40875 : }
40876 :
40877 : /*
40878 : * Update trust region.
40879 : *
40880 : * NOTE: when trust region radius remains fixed for a long time it may mean that we
40881 : * stagnated in eternal loop. In such cases we decrease it slightly in order
40882 : * to break possible loop. If such decrease was unnecessary, it may be easily
40883 : * fixed within few iterations.
40884 : */
40885 0 : deltamax = (double)(0);
40886 0 : for(i=0; i<=n-1; i++)
40887 : {
40888 0 : deltamax = ae_maxreal(deltamax, ae_fabs(state->step0x.ptr.p_double[i]-state->stepkx.ptr.p_double[i], _state)/state->trustrad, _state);
40889 : }
40890 0 : trustradstagnated = ae_false;
40891 0 : inc(&state->trustradstagnationcnt, _state);
40892 0 : prevtrustrad = state->trustrad;
40893 0 : if( ae_fp_less_eq(deltamax,nlcsqp_sqpdeltadecrease) )
40894 : {
40895 0 : state->trustrad = state->trustrad*ae_maxreal(deltamax/nlcsqp_sqpdeltadecrease, nlcsqp_maxtrustraddecay, _state);
40896 0 : state->trustradstagnationcnt = 0;
40897 : }
40898 0 : if( ae_fp_greater_eq(deltamax,nlcsqp_sqpdeltaincrease) )
40899 : {
40900 0 : state->trustrad = state->trustrad*ae_minreal(deltamax/nlcsqp_sqpdeltaincrease, nlcsqp_maxtrustradgrowth, _state);
40901 0 : state->trustradstagnationcnt = 0;
40902 : }
40903 0 : if( state->trustradstagnationcnt>=nlcsqp_trustradstagnationlimit )
40904 : {
40905 0 : state->trustrad = 0.5*state->trustrad;
40906 0 : state->trustradstagnationcnt = 0;
40907 0 : trustradstagnated = ae_true;
40908 : }
40909 :
40910 : /*
40911 : * Trace
40912 : */
40913 0 : if( dotrace )
40914 : {
40915 0 : ae_trace("\n--- outer iteration ends ---------------------------------------------------------------------------\n");
40916 0 : ae_trace("deltaMax = %0.3f (ratio of step length to trust radius)\n",
40917 : (double)(deltamax));
40918 0 : ae_trace("newTrustRad = %0.3e",
40919 0 : (double)(state->trustrad));
40920 0 : if( !trustradstagnated )
40921 : {
40922 0 : if( ae_fp_greater(state->trustrad,prevtrustrad) )
40923 : {
40924 0 : ae_trace(", trust radius increased");
40925 : }
40926 0 : if( ae_fp_less(state->trustrad,prevtrustrad) )
40927 : {
40928 0 : ae_trace(", trust radius decreased");
40929 : }
40930 : }
40931 : else
40932 : {
40933 0 : ae_trace(", trust radius forcibly decreased due to stagnation for %0d iterations",
40934 : (int)(nlcsqp_trustradstagnationlimit));
40935 : }
40936 0 : ae_trace("\n");
40937 0 : if( increasebigc )
40938 : {
40939 0 : ae_trace("BigC = %0.3e (short step was performed, but some constraints are still infeasible - increasing)\n",
40940 0 : (double)(state->bigc));
40941 : }
40942 : }
40943 :
40944 : /*
40945 : * Advance outer iteration counter, test stopping criteria
40946 : */
40947 0 : inc(&state->repiterationscount, _state);
40948 0 : if( ae_fp_less_eq(ae_fabs(state->stepkfi.ptr.p_double[0]-state->step0fi.ptr.p_double[0], _state),nlcsqp_stagnationepsf*ae_fabs(state->step0fi.ptr.p_double[0], _state)) )
40949 : {
40950 0 : inc(&state->fstagnationcnt, _state);
40951 : }
40952 : else
40953 : {
40954 0 : state->fstagnationcnt = 0;
40955 : }
40956 0 : if( ae_fp_less_eq(state->trustrad,state->epsx) )
40957 : {
40958 0 : state->repterminationtype = 2;
40959 0 : if( dotrace )
40960 : {
40961 0 : ae_trace("> stopping condition met: trust radius is smaller than %0.3e\n",
40962 0 : (double)(state->epsx));
40963 : }
40964 0 : goto lbl_4;
40965 : }
40966 0 : if( state->maxits>0&&state->repiterationscount>=state->maxits )
40967 : {
40968 0 : state->repterminationtype = 5;
40969 0 : if( dotrace )
40970 : {
40971 0 : ae_trace("> stopping condition met: %0d iterations performed\n",
40972 0 : (int)(state->repiterationscount));
40973 : }
40974 0 : goto lbl_4;
40975 : }
40976 0 : if( state->fstagnationcnt>=nlcsqp_fstagnationlimit )
40977 : {
40978 0 : state->repterminationtype = 7;
40979 0 : if( dotrace )
40980 : {
40981 0 : ae_trace("> stopping criteria are too stringent: F stagnated for %0d its, stopping\n",
40982 0 : (int)(state->fstagnationcnt));
40983 : }
40984 0 : goto lbl_4;
40985 : }
40986 0 : goto lbl_3;
40987 0 : lbl_4:
40988 0 : smoothnessmonitortracestatus(smonitor, dotrace, _state);
40989 0 : result = ae_false;
40990 0 : return result;
40991 :
40992 : /*
40993 : * Saving state
40994 : */
40995 0 : lbl_rcomm:
40996 0 : result = ae_true;
40997 0 : state->rstate.ia.ptr.p_int[0] = n;
40998 0 : state->rstate.ia.ptr.p_int[1] = nslack;
40999 0 : state->rstate.ia.ptr.p_int[2] = nec;
41000 0 : state->rstate.ia.ptr.p_int[3] = nic;
41001 0 : state->rstate.ia.ptr.p_int[4] = nlec;
41002 0 : state->rstate.ia.ptr.p_int[5] = nlic;
41003 0 : state->rstate.ia.ptr.p_int[6] = i;
41004 0 : state->rstate.ia.ptr.p_int[7] = j;
41005 0 : state->rstate.ia.ptr.p_int[8] = status;
41006 0 : state->rstate.ia.ptr.p_int[9] = subiterationidx;
41007 0 : state->rstate.ba.ptr.p_bool[0] = trustradstagnated;
41008 0 : state->rstate.ba.ptr.p_bool[1] = dotrace;
41009 0 : state->rstate.ba.ptr.p_bool[2] = dodetailedtrace;
41010 0 : state->rstate.ba.ptr.p_bool[3] = increasebigc;
41011 0 : state->rstate.ra.ptr.p_double[0] = v;
41012 0 : state->rstate.ra.ptr.p_double[1] = vv;
41013 0 : state->rstate.ra.ptr.p_double[2] = mx;
41014 0 : state->rstate.ra.ptr.p_double[3] = deltamax;
41015 0 : state->rstate.ra.ptr.p_double[4] = multiplyby;
41016 0 : state->rstate.ra.ptr.p_double[5] = setscaleto;
41017 0 : state->rstate.ra.ptr.p_double[6] = prevtrustrad;
41018 0 : return result;
41019 : }
41020 :
41021 :
41022 : /*************************************************************************
41023 : This function initializes SQP subproblem.
41024 : Should be called once in the beginning of the optimization.
41025 :
41026 : INPUT PARAMETERS:
41027 : SState - solver state
41028 : Subsolver - SQP subproblem to initialize
41029 :
41030 :
41031 : RETURN VALUE:
41032 : True on success
41033 : False on failure of the QP solver (unexpected... but possible due to numerical errors)
41034 :
41035 :
41036 : -- ALGLIB --
41037 : Copyright 05.03.2018 by Bochkanov Sergey
41038 : *************************************************************************/
41039 0 : static void nlcsqp_initqpsubsolver(minsqpstate* sstate,
41040 : minsqpsubsolver* subsolver,
41041 : ae_state *_state)
41042 : {
41043 : ae_int_t n;
41044 : ae_int_t nslack;
41045 : ae_int_t nec;
41046 : ae_int_t nic;
41047 : ae_int_t nlec;
41048 : ae_int_t nlic;
41049 : ae_int_t lccnt;
41050 : ae_int_t nnz;
41051 : ae_int_t offs;
41052 : ae_int_t i;
41053 : ae_int_t j;
41054 :
41055 :
41056 0 : n = sstate->n;
41057 0 : nec = sstate->nec;
41058 0 : nic = sstate->nic;
41059 0 : nlec = sstate->nlec;
41060 0 : nlic = sstate->nlic;
41061 0 : nslack = n+2*(nec+nlec)+(nic+nlic);
41062 0 : lccnt = nec+nic+nlec+nlic;
41063 :
41064 : /*
41065 : * Allocate temporaries
41066 : */
41067 0 : rvectorsetlengthatleast(&subsolver->cural, lccnt, _state);
41068 0 : rvectorsetlengthatleast(&subsolver->curau, lccnt, _state);
41069 0 : rvectorsetlengthatleast(&subsolver->curbndl, nslack, _state);
41070 0 : rvectorsetlengthatleast(&subsolver->curbndu, nslack, _state);
41071 0 : rvectorsetlengthatleast(&subsolver->curb, nslack, _state);
41072 0 : rvectorsetlengthatleast(&subsolver->sk, n, _state);
41073 0 : rvectorsetlengthatleast(&subsolver->yk, n, _state);
41074 :
41075 : /*
41076 : * Initial state
41077 : */
41078 0 : subsolver->algokind = 0;
41079 0 : rmatrixsetlengthatleast(&subsolver->h, n, n, _state);
41080 0 : for(i=0; i<=n-1; i++)
41081 : {
41082 0 : for(j=0; j<=n-1; j++)
41083 : {
41084 0 : subsolver->h.ptr.pp_double[i][j] = (double)(0);
41085 : }
41086 0 : subsolver->h.ptr.pp_double[i][i] = (double)(1);
41087 : }
41088 :
41089 : /*
41090 : * Linear constraints do not change across subiterations, that's
41091 : * why we allocate storage for them at the start of the program.
41092 : *
41093 : * A full set of "raw" constraints is stored; later we will filter
41094 : * out inequality ones which are inactive anywhere in the current
41095 : * trust region.
41096 : *
41097 : * NOTE: because sparserawlc object stores only linear constraint
41098 : * (linearizations of nonlinear ones are not stored) we
41099 : * allocate only minimum necessary space.
41100 : */
41101 0 : nnz = 0;
41102 0 : for(i=0; i<=nec+nic-1; i++)
41103 : {
41104 0 : for(j=0; j<=n-1; j++)
41105 : {
41106 0 : if( sstate->scaledcleic.ptr.pp_double[i][j]!=0.0 )
41107 : {
41108 0 : nnz = nnz+1;
41109 : }
41110 : }
41111 : }
41112 0 : ivectorsetlengthatleast(&subsolver->sparserawlc.ridx, nec+nic+1, _state);
41113 0 : rvectorsetlengthatleast(&subsolver->sparserawlc.vals, nnz, _state);
41114 0 : ivectorsetlengthatleast(&subsolver->sparserawlc.idx, nnz, _state);
41115 0 : ivectorsetlengthatleast(&subsolver->sparserawlc.didx, nec+nic, _state);
41116 0 : ivectorsetlengthatleast(&subsolver->sparserawlc.uidx, nec+nic, _state);
41117 0 : offs = 0;
41118 0 : subsolver->sparserawlc.ridx.ptr.p_int[0] = 0;
41119 0 : for(i=0; i<=nec+nic-1; i++)
41120 : {
41121 0 : for(j=0; j<=n-1; j++)
41122 : {
41123 0 : if( sstate->scaledcleic.ptr.pp_double[i][j]!=0.0 )
41124 : {
41125 :
41126 : /*
41127 : * Primary part of the matrix
41128 : */
41129 0 : subsolver->sparserawlc.vals.ptr.p_double[offs] = sstate->scaledcleic.ptr.pp_double[i][j];
41130 0 : subsolver->sparserawlc.idx.ptr.p_int[offs] = j;
41131 0 : offs = offs+1;
41132 : }
41133 : }
41134 0 : subsolver->sparserawlc.ridx.ptr.p_int[i+1] = offs;
41135 : }
41136 0 : subsolver->sparserawlc.matrixtype = 1;
41137 0 : subsolver->sparserawlc.ninitialized = subsolver->sparserawlc.ridx.ptr.p_int[nec+nic];
41138 0 : subsolver->sparserawlc.m = nec+nic;
41139 0 : subsolver->sparserawlc.n = n;
41140 0 : sparseinitduidx(&subsolver->sparserawlc, _state);
41141 0 : }
41142 :
41143 :
41144 : /*************************************************************************
41145 : This function sets subsolver algorithm to interior point method (IPM)
41146 :
41147 : -- ALGLIB --
41148 : Copyright 05.03.2018 by Bochkanov Sergey
41149 : *************************************************************************/
41150 0 : static void nlcsqp_qpsubsolversetalgoipm(minsqpsubsolver* subsolver,
41151 : ae_state *_state)
41152 : {
41153 :
41154 :
41155 0 : subsolver->algokind = 0;
41156 0 : }
41157 :
41158 :
41159 : /*************************************************************************
41160 : Updates Hessian estimate, uses regularized formula which prevents Hessian
41161 : eigenvalues from decreasing below sqrt(Eps) and rejects updates larger
41162 : than 1/sqrt(Eps) in magnitude.
41163 :
41164 : INPUT PARAMETERS:
41165 : SState - solver state
41166 : Subsolver - SQP subproblem to initialize
41167 : X0, G0 - point #0 and gradient at #0, array[N]
41168 : X1, G1 - point #1 and gradient at #1, array[N]
41169 :
41170 :
41171 : -- ALGLIB --
41172 : Copyright 05.03.2018 by Bochkanov Sergey
41173 : *************************************************************************/
41174 0 : static ae_bool nlcsqp_qpsubproblemupdatehessian(minsqpstate* sstate,
41175 : minsqpsubsolver* subsolver,
41176 : /* Real */ ae_vector* x0,
41177 : /* Real */ ae_vector* g0,
41178 : /* Real */ ae_vector* x1,
41179 : /* Real */ ae_vector* g1,
41180 : ae_state *_state)
41181 : {
41182 : ae_int_t i;
41183 : ae_int_t n;
41184 : double shs;
41185 : double rawsy;
41186 : double sy;
41187 : double snrm2;
41188 : double ynrm2;
41189 : double v2;
41190 : double gk;
41191 : double sk;
41192 : double yk;
41193 : double mxs;
41194 : double mxy;
41195 : double mxhs;
41196 : double reg;
41197 : double big;
41198 : double growth;
41199 : double eigold;
41200 : double eignew;
41201 : double eigcorrection;
41202 : ae_bool result;
41203 :
41204 :
41205 :
41206 : /*
41207 : * Algorithm parameters
41208 : */
41209 0 : reg = 100*ae_sqrt(ae_machineepsilon, _state);
41210 0 : big = 1/reg;
41211 0 : growth = 100.0;
41212 :
41213 : /*
41214 : * Proceed
41215 : */
41216 0 : result = ae_false;
41217 0 : n = sstate->n;
41218 0 : rvectorsetlengthatleast(&subsolver->tmp0, n, _state);
41219 0 : rawsy = (double)(0);
41220 0 : sy = (double)(0);
41221 0 : snrm2 = (double)(0);
41222 0 : ynrm2 = (double)(0);
41223 0 : v2 = (double)(0);
41224 0 : mxs = (double)(0);
41225 0 : mxy = (double)(0);
41226 0 : for(i=0; i<=n-1; i++)
41227 : {
41228 :
41229 : /*
41230 : * Fetch components
41231 : */
41232 0 : sk = x1->ptr.p_double[i]-x0->ptr.p_double[i];
41233 0 : yk = g1->ptr.p_double[i]-g0->ptr.p_double[i];
41234 0 : gk = g0->ptr.p_double[i];
41235 :
41236 : /*
41237 : * Compute raw (S,Y) without regularization (to be used later
41238 : * during comparison with zero)
41239 : */
41240 0 : rawsy = rawsy+sk*yk;
41241 :
41242 : /*
41243 : * Convexify Y
41244 : */
41245 0 : yk = yk+reg*sk;
41246 :
41247 : /*
41248 : * Compute various coefficients using regularized values
41249 : */
41250 0 : sy = sy+sk*yk;
41251 0 : snrm2 = snrm2+sk*sk;
41252 0 : ynrm2 = ynrm2+yk*yk;
41253 0 : v2 = v2+gk*gk;
41254 0 : mxs = ae_maxreal(mxs, ae_fabs(sk, _state), _state);
41255 0 : mxy = ae_maxreal(mxy, ae_fabs(yk, _state), _state);
41256 0 : subsolver->sk.ptr.p_double[i] = sk;
41257 0 : subsolver->yk.ptr.p_double[i] = yk;
41258 : }
41259 0 : shs = rmatrixsyvmv(n, &subsolver->h, 0, 0, ae_true, &subsolver->sk, 0, &subsolver->tmp0, _state);
41260 0 : rmatrixgemv(n, n, 1.0, &subsolver->h, 0, 0, 0, &subsolver->sk, 0, 0.0, &subsolver->tmp0, 0, _state);
41261 0 : mxhs = (double)(0);
41262 0 : for(i=0; i<=n-1; i++)
41263 : {
41264 0 : mxhs = ae_maxreal(mxhs, ae_fabs(subsolver->tmp0.ptr.p_double[i], _state), _state);
41265 : }
41266 :
41267 : /*
41268 : * Skip updates if (Sk,Yk)<=0 or Sk*H*Sk<=0
41269 : *
41270 : * NOTE: we use 0.5*(SY+RawSY) in place of (Sk,Yk) which allows us to have slight
41271 : * nonconvexity due to numerical noise.
41272 : */
41273 0 : if( ae_fp_less_eq(0.5*(sy+rawsy),(double)(0)) )
41274 : {
41275 0 : return result;
41276 : }
41277 0 : if( ae_fp_less_eq(shs,(double)(0)) )
41278 : {
41279 0 : return result;
41280 : }
41281 0 : if( ae_fp_less_eq(snrm2,(double)(0)) )
41282 : {
41283 0 : return result;
41284 : }
41285 0 : ae_assert(ae_fp_greater(sy,(double)(0)), "UpdateHessian: integrity check failed", _state);
41286 :
41287 : /*
41288 : * Skip updates with too short steps
41289 : *
41290 : * NOTE: may prevent us from updating Hessian near the solution
41291 : */
41292 0 : if( ae_fp_less_eq(mxs,coalesce(sstate->epsx, ae_sqrt(ae_machineepsilon, _state), _state)) )
41293 : {
41294 0 : return result;
41295 : }
41296 :
41297 : /*
41298 : * Too large Hessian updates sometimes may come from noisy or nonsmooth problems.
41299 : *
41300 : * Skip updates with max(Yk)^2/(Yk,Sk)>=BIG or max(H*Sk)^2/(Sk*H*Sk)>=BIG
41301 : */
41302 0 : if( ae_fp_greater_eq(ae_sqr(mxy, _state)/sy,big) )
41303 : {
41304 0 : return result;
41305 : }
41306 0 : if( ae_fp_greater_eq(ae_sqr(mxhs, _state)/shs,big) )
41307 : {
41308 0 : return result;
41309 : }
41310 :
41311 : /*
41312 : * Compare eigenvalues of H: old one removed by update, and new one.
41313 : * We require that new eigenvalue is not much larger/smaller than the old one.
41314 : * In order to enforce this condition we compute correction coefficient and
41315 : * multiply one of the rank-1 updates by this coefficient.
41316 : */
41317 0 : eigold = shs/snrm2;
41318 0 : eignew = ynrm2/sy;
41319 0 : eigcorrection = 1.0;
41320 0 : if( ae_fp_greater(eignew,eigold*growth) )
41321 : {
41322 0 : eigcorrection = 1/(eignew/(eigold*growth));
41323 : }
41324 0 : if( ae_fp_less(eignew,eigold/growth) )
41325 : {
41326 0 : eigcorrection = 1/(eignew/(eigold/growth));
41327 : }
41328 :
41329 : /*
41330 : * Update Hessian
41331 : */
41332 0 : rmatrixger(n, n, &subsolver->h, 0, 0, -1/shs, &subsolver->tmp0, 0, &subsolver->tmp0, 0, _state);
41333 0 : rmatrixger(n, n, &subsolver->h, 0, 0, eigcorrection*(1/sy), &subsolver->yk, 0, &subsolver->yk, 0, _state);
41334 0 : result = ae_true;
41335 0 : return result;
41336 : }
41337 :
41338 :
41339 : /*************************************************************************
41340 : This function solves QP subproblem given by initial point X, function vector Fi
41341 : and Jacobian Jac, and returns estimates of Lagrangian multipliers and search direction D[].
41342 :
41343 : -- ALGLIB --
41344 : Copyright 05.03.2018 by Bochkanov Sergey
41345 : *************************************************************************/
41346 0 : static void nlcsqp_fassolve(minsqpsubsolver* subsolver,
41347 : /* Real */ ae_vector* d0,
41348 : /* Real */ ae_matrix* h,
41349 : ae_int_t nq,
41350 : /* Real */ ae_vector* b,
41351 : ae_int_t n,
41352 : /* Real */ ae_vector* bndl,
41353 : /* Real */ ae_vector* bndu,
41354 : sparsematrix* a,
41355 : ae_int_t m,
41356 : /* Real */ ae_vector* al,
41357 : /* Real */ ae_vector* au,
41358 : double trustrad,
41359 : ae_int_t* terminationtype,
41360 : /* Real */ ae_vector* d,
41361 : /* Real */ ae_vector* lagmult,
41362 : ae_state *_state)
41363 : {
41364 : ae_int_t i;
41365 :
41366 :
41367 0 : *terminationtype = 1;
41368 :
41369 : /*
41370 : * Initial point, integrity check for constraints
41371 : */
41372 0 : bvectorsetlengthatleast(&subsolver->hasbndl, n, _state);
41373 0 : bvectorsetlengthatleast(&subsolver->hasbndu, n, _state);
41374 0 : for(i=0; i<=n-1; i++)
41375 : {
41376 0 : subsolver->hasbndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state);
41377 0 : subsolver->hasbndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state);
41378 0 : ae_assert(!subsolver->hasbndl.ptr.p_bool[i]||ae_fp_less_eq(bndl->ptr.p_double[i],d0->ptr.p_double[i]), "FASSolve: integrity check failed", _state);
41379 0 : ae_assert(!subsolver->hasbndu.ptr.p_bool[i]||ae_fp_greater_eq(bndu->ptr.p_double[i],d0->ptr.p_double[i]), "FASSolve: integrity check failed", _state);
41380 0 : d->ptr.p_double[i] = d0->ptr.p_double[i];
41381 : }
41382 0 : bvectorsetlengthatleast(&subsolver->hasal, m, _state);
41383 0 : bvectorsetlengthatleast(&subsolver->hasau, m, _state);
41384 0 : for(i=0; i<=m-1; i++)
41385 : {
41386 0 : subsolver->hasal.ptr.p_bool[i] = ae_isfinite(al->ptr.p_double[i], _state);
41387 0 : subsolver->hasau.ptr.p_bool[i] = ae_isfinite(au->ptr.p_double[i], _state);
41388 0 : if( subsolver->hasal.ptr.p_bool[i]&&subsolver->hasau.ptr.p_bool[i] )
41389 : {
41390 0 : ae_assert(ae_fp_less_eq(al->ptr.p_double[i],au->ptr.p_double[i]), "FASSolve: integrity check failed", _state);
41391 : }
41392 : }
41393 0 : rmatrixsetlengthatleast(&subsolver->activea, n, n, _state);
41394 0 : rvectorsetlengthatleast(&subsolver->activerhs, n, _state);
41395 0 : ivectorsetlengthatleast(&subsolver->activeidx, n, _state);
41396 0 : subsolver->activesetsize = 0;
41397 :
41398 : /*
41399 : * Activate equality constraints (at most N)
41400 : */
41401 0 : for(i=0; i<=m-1; i++)
41402 : {
41403 0 : if( (subsolver->hasal.ptr.p_bool[i]&&subsolver->hasau.ptr.p_bool[i])&&ae_fp_eq(al->ptr.p_double[i],au->ptr.p_double[i]) )
41404 : {
41405 :
41406 : /*
41407 : * Stop if full set of constraints is activated
41408 : */
41409 0 : if( subsolver->activesetsize>=n )
41410 : {
41411 0 : break;
41412 : }
41413 : }
41414 : }
41415 0 : rvectorsetlengthatleast(&subsolver->tmp0, n, _state);
41416 0 : rvectorsetlengthatleast(&subsolver->tmp1, n, _state);
41417 0 : for(i=0; i<=n-1; i++)
41418 : {
41419 0 : subsolver->tmp0.ptr.p_double[i] = trustrad;
41420 0 : subsolver->tmp1.ptr.p_double[i] = 0.0;
41421 : }
41422 0 : vipminitdensewithslacks(&subsolver->ipmsolver, &subsolver->tmp0, &subsolver->tmp1, nq, n, _state);
41423 0 : vipmsetquadraticlinear(&subsolver->ipmsolver, h, &subsolver->sparsedummy, 0, ae_true, b, _state);
41424 0 : vipmsetconstraints(&subsolver->ipmsolver, bndl, bndu, a, m, &subsolver->densedummy, 0, al, au, _state);
41425 0 : vipmoptimize(&subsolver->ipmsolver, ae_false, &subsolver->tmp0, &subsolver->tmp1, &subsolver->tmp2, terminationtype, _state);
41426 0 : if( *terminationtype<=0 )
41427 : {
41428 0 : return;
41429 : }
41430 0 : for(i=0; i<=n-1; i++)
41431 : {
41432 0 : d->ptr.p_double[i] = subsolver->tmp0.ptr.p_double[i];
41433 : }
41434 0 : for(i=0; i<=m-1; i++)
41435 : {
41436 0 : lagmult->ptr.p_double[i] = subsolver->tmp2.ptr.p_double[i];
41437 : }
41438 : }
41439 :
41440 :
41441 : /*************************************************************************
41442 : This function solves QP subproblem given by initial point X, function vector Fi
41443 : and Jacobian Jac, and returns estimates of Lagrangian multipliers and search direction D[].
41444 :
41445 : -- ALGLIB --
41446 : Copyright 05.03.2018 by Bochkanov Sergey
41447 : *************************************************************************/
41448 0 : static ae_bool nlcsqp_qpsubproblemsolve(minsqpstate* state,
41449 : minsqpsubsolver* subsolver,
41450 : /* Real */ ae_vector* x,
41451 : /* Real */ ae_vector* fi,
41452 : /* Real */ ae_matrix* jac,
41453 : /* Real */ ae_vector* d,
41454 : /* Real */ ae_vector* lagmult,
41455 : ae_int_t* terminationtype,
41456 : ae_state *_state)
41457 : {
41458 : ae_int_t n;
41459 : ae_int_t nslack;
41460 : ae_int_t nec;
41461 : ae_int_t nic;
41462 : ae_int_t nlec;
41463 : ae_int_t nlic;
41464 : ae_int_t i;
41465 : ae_int_t j;
41466 : ae_int_t k;
41467 : double v;
41468 : double vv;
41469 : double vright;
41470 : double vmax;
41471 : ae_int_t lccnt;
41472 : ae_int_t offsslackec;
41473 : ae_int_t offsslacknlec;
41474 : ae_int_t offsslackic;
41475 : ae_int_t offsslacknlic;
41476 : ae_int_t offs;
41477 : ae_int_t nnz;
41478 : ae_int_t j0;
41479 : ae_int_t j1;
41480 : ae_bool result;
41481 :
41482 0 : *terminationtype = 0;
41483 :
41484 0 : n = state->n;
41485 0 : nec = state->nec;
41486 0 : nic = state->nic;
41487 0 : nlec = state->nlec;
41488 0 : nlic = state->nlic;
41489 0 : nslack = n+2*(nec+nlec)+(nic+nlic);
41490 0 : lccnt = nec+nic+nlec+nlic;
41491 :
41492 : /*
41493 : * Locations of slack variables
41494 : */
41495 0 : offsslackec = n;
41496 0 : offsslacknlec = n+2*nec;
41497 0 : offsslackic = n+2*nec+2*nlec;
41498 0 : offsslacknlic = n+2*(nec+nlec)+nic;
41499 :
41500 : /*
41501 : * Prepare temporary structures
41502 : */
41503 0 : rvectorgrowto(&subsolver->cural, lccnt, _state);
41504 0 : rvectorgrowto(&subsolver->curau, lccnt, _state);
41505 0 : rvectorsetlengthatleast(&subsolver->d0, nslack, _state);
41506 :
41507 : /*
41508 : * Prepare default solution: all zeros
41509 : */
41510 0 : result = ae_true;
41511 0 : *terminationtype = 0;
41512 0 : for(i=0; i<=nslack-1; i++)
41513 : {
41514 0 : d->ptr.p_double[i] = 0.0;
41515 0 : subsolver->d0.ptr.p_double[i] = (double)(0);
41516 : }
41517 0 : for(i=0; i<=lccnt-1; i++)
41518 : {
41519 0 : lagmult->ptr.p_double[i] = (double)(0);
41520 : }
41521 :
41522 : /*
41523 : * Linear term B
41524 : *
41525 : * NOTE: elements [N,NSlack) are equal to bigC + perturbation to improve numeric properties of QP problem
41526 : */
41527 0 : for(i=0; i<=n-1; i++)
41528 : {
41529 0 : subsolver->curb.ptr.p_double[i] = jac->ptr.pp_double[0][i];
41530 : }
41531 0 : v = (double)(0);
41532 0 : for(i=0; i<=n-1; i++)
41533 : {
41534 0 : v = v+ae_sqr(jac->ptr.pp_double[0][i], _state);
41535 : }
41536 0 : v = coalesce(ae_sqrt(v, _state), 1.0, _state);
41537 0 : for(i=n; i<=nslack-1; i++)
41538 : {
41539 0 : subsolver->curb.ptr.p_double[i] = (state->bigc+1.0/(1+i))*v;
41540 : }
41541 :
41542 : /*
41543 : * Trust radius constraints for primary variables
41544 : */
41545 0 : for(i=0; i<=n-1; i++)
41546 : {
41547 0 : subsolver->curbndl.ptr.p_double[i] = -state->trustrad;
41548 0 : subsolver->curbndu.ptr.p_double[i] = state->trustrad;
41549 0 : if( state->hasbndl.ptr.p_bool[i] )
41550 : {
41551 0 : subsolver->curbndl.ptr.p_double[i] = ae_maxreal(subsolver->curbndl.ptr.p_double[i], state->scaledbndl.ptr.p_double[i]-x->ptr.p_double[i], _state);
41552 : }
41553 0 : if( state->hasbndu.ptr.p_bool[i] )
41554 : {
41555 0 : subsolver->curbndu.ptr.p_double[i] = ae_minreal(subsolver->curbndu.ptr.p_double[i], state->scaledbndu.ptr.p_double[i]-x->ptr.p_double[i], _state);
41556 : }
41557 : }
41558 :
41559 : /*
41560 : * Prepare storage for "effective" constraining matrix
41561 : */
41562 0 : nnz = subsolver->sparserawlc.ridx.ptr.p_int[nec+nic];
41563 0 : for(i=0; i<=nlec+nlic-1; i++)
41564 : {
41565 0 : for(j=0; j<=n-1; j++)
41566 : {
41567 0 : if( jac->ptr.pp_double[1+i][j]!=0.0 )
41568 : {
41569 0 : nnz = nnz+1;
41570 : }
41571 : }
41572 : }
41573 0 : nnz = nnz+2*nec+nic;
41574 0 : nnz = nnz+2*nlec+nlic;
41575 0 : ivectorgrowto(&subsolver->sparseefflc.ridx, lccnt+1, _state);
41576 0 : rvectorgrowto(&subsolver->sparseefflc.vals, nnz, _state);
41577 0 : ivectorgrowto(&subsolver->sparseefflc.idx, nnz, _state);
41578 0 : ivectorsetlengthatleast(&subsolver->sparseefflc.didx, lccnt, _state);
41579 0 : ivectorsetlengthatleast(&subsolver->sparseefflc.uidx, lccnt, _state);
41580 0 : subsolver->sparseefflc.m = 0;
41581 0 : subsolver->sparseefflc.n = nslack;
41582 0 : subsolver->sparseefflc.matrixtype = 1;
41583 :
41584 : /*
41585 : * Append linear equality/inequality constraints
41586 : *
41587 : * Scan sparsified linear constraints stored in sparserawlc[], skip ones
41588 : * which are inactive anywhere in the trust region.
41589 : */
41590 0 : rvectorsetlengthatleast(&subsolver->tmp0, nslack, _state);
41591 0 : for(i=0; i<=n-1; i++)
41592 : {
41593 0 : subsolver->tmp0.ptr.p_double[i] = x->ptr.p_double[i];
41594 : }
41595 0 : for(i=n; i<=nslack-1; i++)
41596 : {
41597 0 : subsolver->tmp0.ptr.p_double[i] = (double)(0);
41598 : }
41599 0 : for(i=0; i<=nec+nic-1; i++)
41600 : {
41601 :
41602 : /*
41603 : * Calculate:
41604 : * * VRight - product of X[] (extended with zeros up to NSlack elements)
41605 : * and AR[i] - Ith row of sparserawlc matrix.
41606 : * * VMax - maximum value of X*ARi computed over trust region
41607 : */
41608 0 : vright = (double)(0);
41609 0 : vmax = (double)(0);
41610 0 : j0 = subsolver->sparserawlc.ridx.ptr.p_int[i];
41611 0 : j1 = subsolver->sparserawlc.ridx.ptr.p_int[i+1]-1;
41612 0 : for(k=j0; k<=j1; k++)
41613 : {
41614 0 : j = subsolver->sparserawlc.idx.ptr.p_int[k];
41615 0 : v = subsolver->tmp0.ptr.p_double[j];
41616 0 : vv = subsolver->sparserawlc.vals.ptr.p_double[k];
41617 0 : vright = vright+vv*v;
41618 0 : if( vv>=0 )
41619 : {
41620 0 : vmax = vmax+vv*(v+subsolver->curbndu.ptr.p_double[j]);
41621 : }
41622 : else
41623 : {
41624 0 : vmax = vmax+vv*(v+subsolver->curbndl.ptr.p_double[j]);
41625 : }
41626 : }
41627 :
41628 : /*
41629 : * If constraint is an inequality one and guaranteed to be inactive
41630 : * within trust region, it is skipped (row itself is retained but
41631 : * filled by zeros).
41632 : */
41633 0 : if( i>=nec&&vmax<=state->scaledcleic.ptr.pp_double[i][n] )
41634 : {
41635 0 : offs = subsolver->sparseefflc.ridx.ptr.p_int[i];
41636 0 : subsolver->sparseefflc.vals.ptr.p_double[offs] = (double)(-1);
41637 0 : subsolver->sparseefflc.idx.ptr.p_int[offs] = offsslackic+(i-nec);
41638 0 : subsolver->sparseefflc.ridx.ptr.p_int[i+1] = offs+1;
41639 0 : subsolver->cural.ptr.p_double[i] = 0.0;
41640 0 : subsolver->curau.ptr.p_double[i] = 0.0;
41641 0 : subsolver->curbndl.ptr.p_double[offsslackic+(i-nec)] = (double)(0);
41642 0 : subsolver->curbndu.ptr.p_double[offsslackic+(i-nec)] = (double)(0);
41643 0 : continue;
41644 : }
41645 :
41646 : /*
41647 : * Start working on row I
41648 : */
41649 0 : offs = subsolver->sparseefflc.ridx.ptr.p_int[i];
41650 :
41651 : /*
41652 : * Copy constraint from sparserawlc[] to sparseefflc[]
41653 : */
41654 0 : j0 = subsolver->sparserawlc.ridx.ptr.p_int[i];
41655 0 : j1 = subsolver->sparserawlc.ridx.ptr.p_int[i+1]-1;
41656 0 : for(k=j0; k<=j1; k++)
41657 : {
41658 0 : subsolver->sparseefflc.idx.ptr.p_int[offs] = subsolver->sparserawlc.idx.ptr.p_int[k];
41659 0 : subsolver->sparseefflc.vals.ptr.p_double[offs] = subsolver->sparserawlc.vals.ptr.p_double[k];
41660 0 : offs = offs+1;
41661 : }
41662 :
41663 : /*
41664 : * Set up slack variables
41665 : */
41666 0 : if( i<nec )
41667 : {
41668 0 : subsolver->sparseefflc.vals.ptr.p_double[offs+0] = (double)(-1);
41669 0 : subsolver->sparseefflc.vals.ptr.p_double[offs+1] = (double)(1);
41670 0 : subsolver->sparseefflc.idx.ptr.p_int[offs+0] = offsslackec+2*i+0;
41671 0 : subsolver->sparseefflc.idx.ptr.p_int[offs+1] = offsslackec+2*i+1;
41672 0 : offs = offs+2;
41673 : }
41674 : else
41675 : {
41676 :
41677 : /*
41678 : * Slack variables for inequality constraints
41679 : */
41680 0 : subsolver->sparseefflc.vals.ptr.p_double[offs] = (double)(-1);
41681 0 : subsolver->sparseefflc.idx.ptr.p_int[offs] = offsslackic+(i-nec);
41682 0 : offs = offs+1;
41683 : }
41684 :
41685 : /*
41686 : * Finalize row
41687 : */
41688 0 : subsolver->sparseefflc.ridx.ptr.p_int[i+1] = offs;
41689 :
41690 : /*
41691 : * Set up bounds and slack part of D0.
41692 : *
41693 : * NOTE: bounds for equality and inequality constraints are
41694 : * handled differently
41695 : */
41696 0 : v = vright-state->scaledcleic.ptr.pp_double[i][n];
41697 0 : if( i<nec )
41698 : {
41699 0 : subsolver->cural.ptr.p_double[i] = -v;
41700 0 : subsolver->curau.ptr.p_double[i] = -v;
41701 0 : subsolver->curbndl.ptr.p_double[offsslackec+2*i+0] = (double)(0);
41702 0 : subsolver->curbndl.ptr.p_double[offsslackec+2*i+1] = (double)(0);
41703 0 : subsolver->curbndu.ptr.p_double[offsslackec+2*i+0] = ae_fabs(v, _state);
41704 0 : subsolver->curbndu.ptr.p_double[offsslackec+2*i+1] = ae_fabs(v, _state);
41705 0 : if( ae_fp_greater_eq(v,(double)(0)) )
41706 : {
41707 0 : subsolver->d0.ptr.p_double[offsslackec+2*i+0] = ae_fabs(v, _state);
41708 0 : subsolver->d0.ptr.p_double[offsslackec+2*i+1] = (double)(0);
41709 : }
41710 : else
41711 : {
41712 0 : subsolver->d0.ptr.p_double[offsslackec+2*i+0] = (double)(0);
41713 0 : subsolver->d0.ptr.p_double[offsslackec+2*i+1] = ae_fabs(v, _state);
41714 : }
41715 : }
41716 : else
41717 : {
41718 0 : subsolver->cural.ptr.p_double[i] = _state->v_neginf;
41719 0 : subsolver->curau.ptr.p_double[i] = -v;
41720 0 : subsolver->curbndl.ptr.p_double[offsslackic+(i-nec)] = (double)(0);
41721 0 : subsolver->curbndu.ptr.p_double[offsslackic+(i-nec)] = ae_maxreal(v, (double)(0), _state);
41722 0 : subsolver->d0.ptr.p_double[offsslackic+(i-nec)] = ae_maxreal(v, (double)(0), _state);
41723 : }
41724 : }
41725 0 : subsolver->sparseefflc.m = subsolver->sparseefflc.m+(nec+nic);
41726 :
41727 : /*
41728 : * Append nonlinear equality/inequality constraints
41729 : */
41730 0 : for(i=0; i<=nlec+nlic-1; i++)
41731 : {
41732 :
41733 : /*
41734 : * Calculate scale coefficient
41735 : */
41736 0 : vv = (double)(0);
41737 0 : for(j=0; j<=n-1; j++)
41738 : {
41739 0 : v = jac->ptr.pp_double[1+i][j];
41740 0 : vv = vv+v*v;
41741 : }
41742 0 : vv = 1/coalesce(ae_sqrt(vv, _state), (double)(1), _state);
41743 :
41744 : /*
41745 : * Copy scaled row
41746 : */
41747 0 : offs = subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m+i];
41748 0 : for(j=0; j<=n-1; j++)
41749 : {
41750 0 : if( jac->ptr.pp_double[1+i][j]!=0.0 )
41751 : {
41752 0 : subsolver->sparseefflc.vals.ptr.p_double[offs] = vv*jac->ptr.pp_double[1+i][j];
41753 0 : subsolver->sparseefflc.idx.ptr.p_int[offs] = j;
41754 0 : offs = offs+1;
41755 : }
41756 : }
41757 0 : if( i<nlec )
41758 : {
41759 :
41760 : /*
41761 : * Add slack terms for equality constraints
41762 : */
41763 0 : subsolver->sparseefflc.vals.ptr.p_double[offs+0] = (double)(-1);
41764 0 : subsolver->sparseefflc.vals.ptr.p_double[offs+1] = (double)(1);
41765 0 : subsolver->sparseefflc.idx.ptr.p_int[offs+0] = offsslacknlec+2*i+0;
41766 0 : subsolver->sparseefflc.idx.ptr.p_int[offs+1] = offsslacknlec+2*i+1;
41767 0 : offs = offs+2;
41768 : }
41769 : else
41770 : {
41771 :
41772 : /*
41773 : * Add slack terms for inequality constraints
41774 : */
41775 0 : subsolver->sparseefflc.vals.ptr.p_double[offs] = (double)(-1);
41776 0 : subsolver->sparseefflc.idx.ptr.p_int[offs] = offsslacknlic+(i-nlec);
41777 0 : offs = offs+1;
41778 : }
41779 0 : subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m+i+1] = offs;
41780 :
41781 : /*
41782 : * Set box constraints on slack variables and bounds on linear equality/inequality constraints
41783 : */
41784 0 : v = vv*fi->ptr.p_double[1+i];
41785 0 : if( i<nlec )
41786 : {
41787 :
41788 : /*
41789 : * Equality constraint
41790 : */
41791 0 : subsolver->cural.ptr.p_double[subsolver->sparseefflc.m+i] = -v;
41792 0 : subsolver->curau.ptr.p_double[subsolver->sparseefflc.m+i] = -v;
41793 0 : subsolver->curbndl.ptr.p_double[offsslacknlec+2*i+0] = (double)(0);
41794 0 : subsolver->curbndl.ptr.p_double[offsslacknlec+2*i+1] = (double)(0);
41795 0 : subsolver->curbndu.ptr.p_double[offsslacknlec+2*i+0] = ae_fabs(v, _state);
41796 0 : subsolver->curbndu.ptr.p_double[offsslacknlec+2*i+1] = ae_fabs(v, _state);
41797 0 : if( ae_fp_greater_eq(v,(double)(0)) )
41798 : {
41799 0 : subsolver->d0.ptr.p_double[offsslacknlec+2*i+0] = ae_fabs(v, _state);
41800 0 : subsolver->d0.ptr.p_double[offsslacknlec+2*i+1] = (double)(0);
41801 : }
41802 : else
41803 : {
41804 0 : subsolver->d0.ptr.p_double[offsslacknlec+2*i+0] = (double)(0);
41805 0 : subsolver->d0.ptr.p_double[offsslacknlec+2*i+1] = ae_fabs(v, _state);
41806 : }
41807 : }
41808 : else
41809 : {
41810 :
41811 : /*
41812 : * Inequality constraint
41813 : */
41814 0 : subsolver->cural.ptr.p_double[subsolver->sparseefflc.m+i] = _state->v_neginf;
41815 0 : subsolver->curau.ptr.p_double[subsolver->sparseefflc.m+i] = -v;
41816 0 : subsolver->curbndl.ptr.p_double[offsslacknlic+(i-nlec)] = (double)(0);
41817 0 : subsolver->curbndu.ptr.p_double[offsslacknlic+(i-nlec)] = ae_maxreal(v, (double)(0), _state);
41818 0 : subsolver->d0.ptr.p_double[offsslacknlic+(i-nlec)] = ae_maxreal(v, (double)(0), _state);
41819 : }
41820 : }
41821 0 : subsolver->sparseefflc.m = subsolver->sparseefflc.m+(nlec+nlic);
41822 :
41823 : /*
41824 : * Finalize sparse matrix structure
41825 : */
41826 0 : ae_assert(subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m]<=subsolver->sparseefflc.idx.cnt, "QPSubproblemSolve: critical integrity check failed", _state);
41827 0 : ae_assert(subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m]<=subsolver->sparseefflc.vals.cnt, "QPSubproblemSolve: critical integrity check failed", _state);
41828 0 : subsolver->sparseefflc.ninitialized = subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m];
41829 0 : sparseinitduidx(&subsolver->sparseefflc, _state);
41830 :
41831 : /*
41832 : * Solve quadratic program
41833 : */
41834 0 : if( subsolver->algokind==0 )
41835 : {
41836 :
41837 : /*
41838 : * Use dense IPM.
41839 : *
41840 : * We always treat its result as a valid solution, even for TerminationType<=0.
41841 : * In case anything is wrong with solution vector, we will detect it during line
41842 : * search phase (merit function does not increase).
41843 : *
41844 : * NOTE: because we cleaned up constraints that are DEFINITELY inactive within
41845 : * trust region, we do not have to worry about StopOnExcessiveBounds option.
41846 : */
41847 0 : rvectorsetlengthatleast(&subsolver->tmp0, nslack, _state);
41848 0 : rvectorsetlengthatleast(&subsolver->tmp1, nslack, _state);
41849 0 : for(i=0; i<=nslack-1; i++)
41850 : {
41851 0 : subsolver->tmp0.ptr.p_double[i] = state->trustrad;
41852 0 : subsolver->tmp1.ptr.p_double[i] = 0.0;
41853 : }
41854 0 : vipminitdensewithslacks(&subsolver->ipmsolver, &subsolver->tmp0, &subsolver->tmp1, n, nslack, _state);
41855 0 : vipmsetquadraticlinear(&subsolver->ipmsolver, &subsolver->h, &subsolver->sparsedummy, 0, ae_true, &subsolver->curb, _state);
41856 0 : vipmsetconstraints(&subsolver->ipmsolver, &subsolver->curbndl, &subsolver->curbndu, &subsolver->sparseefflc, subsolver->sparseefflc.m, &subsolver->densedummy, 0, &subsolver->cural, &subsolver->curau, _state);
41857 0 : vipmoptimize(&subsolver->ipmsolver, ae_false, &subsolver->tmp0, &subsolver->tmp1, &subsolver->tmp2, terminationtype, _state);
41858 0 : for(i=0; i<=nslack-1; i++)
41859 : {
41860 0 : d->ptr.p_double[i] = subsolver->tmp0.ptr.p_double[i];
41861 : }
41862 0 : for(i=0; i<=lccnt-1; i++)
41863 : {
41864 0 : lagmult->ptr.p_double[i] = subsolver->tmp2.ptr.p_double[i];
41865 : }
41866 0 : return result;
41867 : }
41868 0 : if( subsolver->algokind==1 )
41869 : {
41870 :
41871 : /*
41872 : * Use fast active set
41873 : */
41874 0 : nlcsqp_fassolve(subsolver, &subsolver->d0, &subsolver->h, n, &subsolver->curb, nslack, &subsolver->curbndl, &subsolver->curbndu, &subsolver->sparseefflc, subsolver->sparseefflc.m, &subsolver->cural, &subsolver->curau, state->trustrad, terminationtype, d, lagmult, _state);
41875 0 : if( *terminationtype<=0 )
41876 : {
41877 :
41878 : /*
41879 : * QP solver failed due to numerical errors; exit
41880 : */
41881 0 : result = ae_false;
41882 0 : return result;
41883 : }
41884 0 : return result;
41885 : }
41886 :
41887 : /*
41888 : * Unexpected
41889 : */
41890 0 : ae_assert(ae_false, "SQP: unexpected subsolver type", _state);
41891 0 : return result;
41892 : }
41893 :
41894 :
41895 : /*************************************************************************
41896 : This function initializes MeritPhase temporaries. It should be called before
41897 : beginning of each new iteration. You may call it multiple times for the
41898 : same instance of MeritPhase temporaries.
41899 :
41900 : INPUT PARAMETERS:
41901 : MeritState - instance to be initialized.
41902 : N - problem dimensionality
41903 : NEC, NIC - linear equality/inequality constraint count
41904 : NLEC, NLIC - nonlinear equality/inequality constraint count
41905 : AbsLagMemory - array[MemLen,NEC+NIC+NLEC+NLIC], stores absolute
41906 : values of Lagrange multipliers for the last MemLen
41907 : iterations
41908 : MemLen - memory length
41909 :
41910 : OUTPUT PARAMETERS:
41911 : MeritState - instance being initialized
41912 :
41913 : -- ALGLIB --
41914 : Copyright 05.02.2019 by Bochkanov Sergey
41915 : *************************************************************************/
41916 0 : static void nlcsqp_meritphaseinit(minsqpmeritphasestate* meritstate,
41917 : /* Real */ ae_vector* curx,
41918 : /* Real */ ae_vector* curfi,
41919 : /* Real */ ae_matrix* curj,
41920 : ae_int_t n,
41921 : ae_int_t nec,
41922 : ae_int_t nic,
41923 : ae_int_t nlec,
41924 : ae_int_t nlic,
41925 : /* Real */ ae_matrix* abslagmemory,
41926 : ae_int_t memlen,
41927 : ae_state *_state)
41928 : {
41929 : ae_int_t i;
41930 : ae_int_t nslack;
41931 :
41932 :
41933 0 : nslack = n+2*(nec+nlec)+(nic+nlic);
41934 0 : meritstate->n = n;
41935 0 : meritstate->nec = nec;
41936 0 : meritstate->nic = nic;
41937 0 : meritstate->nlec = nlec;
41938 0 : meritstate->nlic = nlic;
41939 0 : rvectorsetlengthatleast(&meritstate->d, nslack, _state);
41940 0 : rvectorsetlengthatleast(&meritstate->dx, nslack, _state);
41941 0 : rvectorsetlengthatleast(&meritstate->stepkx, n, _state);
41942 0 : rvectorsetlengthatleast(&meritstate->stepkxc, n, _state);
41943 0 : rvectorsetlengthatleast(&meritstate->stepkxn, n, _state);
41944 0 : rvectorsetlengthatleast(&meritstate->stepkfi, 1+nlec+nlic, _state);
41945 0 : rvectorsetlengthatleast(&meritstate->stepkfic, 1+nlec+nlic, _state);
41946 0 : rvectorsetlengthatleast(&meritstate->stepkfin, 1+nlec+nlic, _state);
41947 0 : rmatrixsetlengthatleast(&meritstate->stepkj, 1+nlec+nlic, n, _state);
41948 0 : rmatrixsetlengthatleast(&meritstate->stepkjc, 1+nlec+nlic, n, _state);
41949 0 : rmatrixsetlengthatleast(&meritstate->stepkjn, 1+nlec+nlic, n, _state);
41950 0 : rvectorsetlengthatleast(&meritstate->stepklaggrad, n, _state);
41951 0 : rvectorsetlengthatleast(&meritstate->stepknlaggrad, n, _state);
41952 0 : rvectorsetlengthatleast(&meritstate->lagmult, nec+nic+nlec+nlic, _state);
41953 0 : rvectorsetlengthatleast(&meritstate->dummylagmult, nec+nic+nlec+nlic, _state);
41954 0 : rsetallocv(nec+nic+nlec+nlic, 0.0, &meritstate->penalties, _state);
41955 0 : for(i=0; i<=memlen-1; i++)
41956 : {
41957 0 : rmergemaxrv(nec+nic+nlec+nlic, abslagmemory, i, &meritstate->penalties, _state);
41958 : }
41959 0 : rcopyv(n, curx, &meritstate->stepkx, _state);
41960 0 : rcopyv(1+nlec+nlic, curfi, &meritstate->stepkfi, _state);
41961 0 : for(i=0; i<=nlec+nlic; i++)
41962 : {
41963 0 : rcopyrr(n, curj, i, &meritstate->stepkj, i, _state);
41964 : }
41965 0 : ae_vector_set_length(&meritstate->rmeritphasestate.ia, 7+1, _state);
41966 0 : ae_vector_set_length(&meritstate->rmeritphasestate.ba, 3+1, _state);
41967 0 : ae_vector_set_length(&meritstate->rmeritphasestate.ra, 9+1, _state);
41968 0 : meritstate->rmeritphasestate.stage = -1;
41969 0 : }
41970 :
41971 :
41972 : /*************************************************************************
41973 : This function tries to perform either phase #1 or phase #3 step.
41974 :
41975 : Former corresponds to linear model step (without conjugacy constraints) with
41976 : correction for nonlinearity ("second order correction"). Such correction
41977 : helps to overcome Maratos effect (a tendency of L1 penalized merit
41978 : functions to reject nonzero steps).
41979 :
41980 : Latter is a step using linear model with no second order correction.
41981 :
41982 : INPUT PARAMETERS:
41983 : State - SQP solver state
41984 : SMonitor - smoothness monitor
41985 : UserTerminationNeeded-True if user requested termination
41986 :
41987 : OUTPUT PARAMETERS:
41988 : State - RepTerminationType is set to current termination code (if Status=0).
41989 : Status - when reverse communication is done, Status is set to:
41990 : * positive value, if we can proceed to the next stage
41991 : of the outer iteration
41992 : * zero, if algorithm is terminated (RepTerminationType
41993 : is set to appropriate value)
41994 :
41995 : -- ALGLIB --
41996 : Copyright 05.02.2019 by Bochkanov Sergey
41997 : *************************************************************************/
41998 0 : static ae_bool nlcsqp_meritphaseiteration(minsqpstate* state,
41999 : minsqpmeritphasestate* meritstate,
42000 : smoothnessmonitor* smonitor,
42001 : ae_bool userterminationneeded,
42002 : ae_state *_state)
42003 : {
42004 : ae_int_t n;
42005 : ae_int_t nslack;
42006 : ae_int_t nec;
42007 : ae_int_t nic;
42008 : ae_int_t nlec;
42009 : ae_int_t nlic;
42010 : ae_int_t i;
42011 : ae_int_t j;
42012 : double v;
42013 : double vv;
42014 : double mx;
42015 : double f0;
42016 : double f1;
42017 : double nu;
42018 : double localstp;
42019 : double stepklagval;
42020 : double stepknlagval;
42021 : ae_bool hessianupdateperformed;
42022 : ae_bool dotrace;
42023 : ae_bool doprobing;
42024 : ae_bool dotracexd;
42025 : double stp;
42026 : ae_bool result;
42027 :
42028 :
42029 :
42030 : /*
42031 : * Reverse communication preparations
42032 : * I know it looks ugly, but it works the same way
42033 : * anywhere from C++ to Python.
42034 : *
42035 : * This code initializes locals by:
42036 : * * random values determined during code
42037 : * generation - on first subroutine call
42038 : * * values from previous call - on subsequent calls
42039 : */
42040 0 : if( meritstate->rmeritphasestate.stage>=0 )
42041 : {
42042 0 : n = meritstate->rmeritphasestate.ia.ptr.p_int[0];
42043 0 : nslack = meritstate->rmeritphasestate.ia.ptr.p_int[1];
42044 0 : nec = meritstate->rmeritphasestate.ia.ptr.p_int[2];
42045 0 : nic = meritstate->rmeritphasestate.ia.ptr.p_int[3];
42046 0 : nlec = meritstate->rmeritphasestate.ia.ptr.p_int[4];
42047 0 : nlic = meritstate->rmeritphasestate.ia.ptr.p_int[5];
42048 0 : i = meritstate->rmeritphasestate.ia.ptr.p_int[6];
42049 0 : j = meritstate->rmeritphasestate.ia.ptr.p_int[7];
42050 0 : hessianupdateperformed = meritstate->rmeritphasestate.ba.ptr.p_bool[0];
42051 0 : dotrace = meritstate->rmeritphasestate.ba.ptr.p_bool[1];
42052 0 : doprobing = meritstate->rmeritphasestate.ba.ptr.p_bool[2];
42053 0 : dotracexd = meritstate->rmeritphasestate.ba.ptr.p_bool[3];
42054 0 : v = meritstate->rmeritphasestate.ra.ptr.p_double[0];
42055 0 : vv = meritstate->rmeritphasestate.ra.ptr.p_double[1];
42056 0 : mx = meritstate->rmeritphasestate.ra.ptr.p_double[2];
42057 0 : f0 = meritstate->rmeritphasestate.ra.ptr.p_double[3];
42058 0 : f1 = meritstate->rmeritphasestate.ra.ptr.p_double[4];
42059 0 : nu = meritstate->rmeritphasestate.ra.ptr.p_double[5];
42060 0 : localstp = meritstate->rmeritphasestate.ra.ptr.p_double[6];
42061 0 : stepklagval = meritstate->rmeritphasestate.ra.ptr.p_double[7];
42062 0 : stepknlagval = meritstate->rmeritphasestate.ra.ptr.p_double[8];
42063 0 : stp = meritstate->rmeritphasestate.ra.ptr.p_double[9];
42064 : }
42065 : else
42066 : {
42067 0 : n = -536;
42068 0 : nslack = 487;
42069 0 : nec = -115;
42070 0 : nic = 886;
42071 0 : nlec = 346;
42072 0 : nlic = -722;
42073 0 : i = -413;
42074 0 : j = -461;
42075 0 : hessianupdateperformed = ae_true;
42076 0 : dotrace = ae_true;
42077 0 : doprobing = ae_false;
42078 0 : dotracexd = ae_false;
42079 0 : v = 306;
42080 0 : vv = -1011;
42081 0 : mx = 951;
42082 0 : f0 = -463;
42083 0 : f1 = 88;
42084 0 : nu = -861;
42085 0 : localstp = -678;
42086 0 : stepklagval = -731;
42087 0 : stepknlagval = -675;
42088 0 : stp = -763;
42089 : }
42090 0 : if( meritstate->rmeritphasestate.stage==0 )
42091 : {
42092 0 : goto lbl_0;
42093 : }
42094 0 : if( meritstate->rmeritphasestate.stage==1 )
42095 : {
42096 0 : goto lbl_1;
42097 : }
42098 0 : if( meritstate->rmeritphasestate.stage==2 )
42099 : {
42100 0 : goto lbl_2;
42101 : }
42102 0 : if( meritstate->rmeritphasestate.stage==3 )
42103 : {
42104 0 : goto lbl_3;
42105 : }
42106 :
42107 : /*
42108 : * Routine body
42109 : */
42110 0 : n = state->n;
42111 0 : nec = state->nec;
42112 0 : nic = state->nic;
42113 0 : nlec = state->nlec;
42114 0 : nlic = state->nlic;
42115 0 : nslack = n+2*(nec+nlec)+(nic+nlic);
42116 0 : dotrace = ae_is_trace_enabled("SQP");
42117 0 : dotracexd = dotrace&&ae_is_trace_enabled("SQP.DETAILED");
42118 0 : doprobing = ae_is_trace_enabled("SQP.PROBING");
42119 0 : ae_assert(meritstate->lagmult.cnt>=nec+nic+nlec+nlic, "MeritPhaseIteration: integrity check failed", _state);
42120 :
42121 : /*
42122 : * Report iteration beginning
42123 : */
42124 0 : if( dotrace )
42125 : {
42126 0 : ae_trace("\n--- quadratic step ---------------------------------------------------------------------------------\n");
42127 : }
42128 :
42129 : /*
42130 : * Default decision is to continue algorithm
42131 : */
42132 0 : meritstate->status = 1;
42133 0 : meritstate->increasebigc = ae_false;
42134 0 : stp = (double)(0);
42135 :
42136 : /*
42137 : * Determine step direction using initial quadratic model.
42138 : * Update penalties vector with current Lagrange multipliers.
42139 : */
42140 0 : if( !nlcsqp_qpsubproblemsolve(state, &state->subsolver, &meritstate->stepkx, &meritstate->stepkfi, &meritstate->stepkj, &meritstate->d, &meritstate->lagmult, &j, _state) )
42141 : {
42142 0 : if( dotrace )
42143 : {
42144 0 : ae_trace("> [WARNING] QP subproblem failed with TerminationType=%0d\n",
42145 : (int)(j));
42146 : }
42147 0 : result = ae_false;
42148 0 : return result;
42149 : }
42150 0 : if( dotrace )
42151 : {
42152 0 : ae_trace("> QP subproblem solved with TerminationType=%0d\n",
42153 : (int)(j));
42154 : }
42155 0 : for(i=0; i<=nec+nic+nlec+nlic-1; i++)
42156 : {
42157 0 : meritstate->penalties.ptr.p_double[i] = ae_maxreal(meritstate->penalties.ptr.p_double[i], ae_fabs(meritstate->lagmult.ptr.p_double[i], _state), _state);
42158 : }
42159 :
42160 : /*
42161 : * Perform merit function line search.
42162 : *
42163 : * First, we try unit step. If it does not decrease merit function,
42164 : * a second-order correction is tried (helps to combat Maratos effect).
42165 : */
42166 0 : localstp = 1.0;
42167 0 : f0 = nlcsqp_meritfunction(state, &meritstate->stepkx, &meritstate->stepkfi, &meritstate->lagmult, &meritstate->penalties, &meritstate->tmpmerit, _state);
42168 0 : for(i=0; i<=n-1; i++)
42169 : {
42170 0 : meritstate->stepkxn.ptr.p_double[i] = meritstate->stepkx.ptr.p_double[i]+localstp*meritstate->d.ptr.p_double[i];
42171 : }
42172 0 : nlcsqp_sqpsendx(state, &meritstate->stepkxn, _state);
42173 0 : state->needfij = ae_true;
42174 0 : meritstate->rmeritphasestate.stage = 0;
42175 0 : goto lbl_rcomm;
42176 0 : lbl_0:
42177 0 : state->needfij = ae_false;
42178 0 : if( !nlcsqp_sqpretrievefij(state, &meritstate->stepkfin, &meritstate->stepkjn, _state) )
42179 : {
42180 :
42181 : /*
42182 : * Failed to retrieve func/Jac, infinities detected
42183 : */
42184 0 : state->repterminationtype = -8;
42185 0 : meritstate->status = 0;
42186 0 : if( dotrace )
42187 : {
42188 0 : ae_trace("[ERROR] infinities in target/constraints are detected\n");
42189 : }
42190 0 : result = ae_false;
42191 0 : return result;
42192 : }
42193 0 : f1 = nlcsqp_meritfunction(state, &meritstate->stepkxn, &meritstate->stepkfin, &meritstate->lagmult, &meritstate->penalties, &meritstate->tmpmerit, _state);
42194 0 : if( ae_fp_less(f1,f0) )
42195 : {
42196 0 : goto lbl_4;
42197 : }
42198 :
42199 : /*
42200 : * Full step increases merit function. Let's compute second order
42201 : * correction to the constraint model and recompute trial step D:
42202 : * * use original model of the target
42203 : * * extrapolate model of nonlinear constraints at StepKX+D back to origin
42204 : *
42205 : */
42206 0 : if( dotrace )
42207 : {
42208 0 : ae_trace("> preparing second-order correction\n");
42209 : }
42210 0 : meritstate->stepkfic.ptr.p_double[0] = meritstate->stepkfi.ptr.p_double[0];
42211 0 : for(j=0; j<=n-1; j++)
42212 : {
42213 0 : meritstate->stepkjc.ptr.pp_double[0][j] = meritstate->stepkj.ptr.pp_double[0][j];
42214 : }
42215 0 : for(i=1; i<=nlec+nlic; i++)
42216 : {
42217 0 : v = (double)(0);
42218 0 : for(j=0; j<=n-1; j++)
42219 : {
42220 0 : v = v+meritstate->d.ptr.p_double[j]*meritstate->stepkj.ptr.pp_double[i][j];
42221 0 : meritstate->stepkjc.ptr.pp_double[i][j] = meritstate->stepkj.ptr.pp_double[i][j];
42222 : }
42223 0 : meritstate->stepkfic.ptr.p_double[i] = meritstate->stepkfin.ptr.p_double[i]-v;
42224 : }
42225 0 : if( !nlcsqp_qpsubproblemsolve(state, &state->subsolver, &meritstate->stepkx, &meritstate->stepkfic, &meritstate->stepkjc, &meritstate->dx, &meritstate->dummylagmult, &j, _state) )
42226 : {
42227 0 : if( dotrace )
42228 : {
42229 0 : ae_trace("> [WARNING] second-order QP subproblem failed\n");
42230 : }
42231 0 : result = ae_false;
42232 0 : return result;
42233 : }
42234 0 : if( dotrace )
42235 : {
42236 0 : ae_trace("> second-order QP subproblem solved with TerminationType=%0d\n",
42237 : (int)(j));
42238 : }
42239 0 : for(i=0; i<=n-1; i++)
42240 : {
42241 0 : meritstate->d.ptr.p_double[i] = meritstate->dx.ptr.p_double[i];
42242 : }
42243 :
42244 : /*
42245 : * Perform line search, we again try full step (maybe it will work after SOC)
42246 : */
42247 0 : localstp = 1.0;
42248 0 : nu = 0.5;
42249 0 : f1 = f0;
42250 0 : smoothnessmonitorstartlinesearch(smonitor, &meritstate->stepkx, &meritstate->stepkfi, &meritstate->stepkj, _state);
42251 0 : lbl_6:
42252 : if( ae_false )
42253 : {
42254 : goto lbl_7;
42255 : }
42256 0 : for(i=0; i<=n-1; i++)
42257 : {
42258 0 : meritstate->stepkxn.ptr.p_double[i] = meritstate->stepkx.ptr.p_double[i]+localstp*meritstate->d.ptr.p_double[i];
42259 : }
42260 0 : nlcsqp_sqpsendx(state, &meritstate->stepkxn, _state);
42261 0 : state->needfij = ae_true;
42262 0 : meritstate->rmeritphasestate.stage = 1;
42263 0 : goto lbl_rcomm;
42264 0 : lbl_1:
42265 0 : state->needfij = ae_false;
42266 0 : if( !nlcsqp_sqpretrievefij(state, &meritstate->stepkfin, &meritstate->stepkjn, _state) )
42267 : {
42268 :
42269 : /*
42270 : * Failed to retrieve func/Jac, infinities detected
42271 : */
42272 0 : state->repterminationtype = -8;
42273 0 : meritstate->status = 0;
42274 0 : if( dotrace )
42275 : {
42276 0 : ae_trace("[ERROR] infinities in target/constraints are detected\n");
42277 : }
42278 0 : result = ae_false;
42279 0 : return result;
42280 : }
42281 0 : smoothnessmonitorenqueuepoint(smonitor, &meritstate->d, localstp, &meritstate->stepkxn, &meritstate->stepkfin, &meritstate->stepkjn, _state);
42282 0 : f1 = nlcsqp_meritfunction(state, &meritstate->stepkxn, &meritstate->stepkfin, &meritstate->lagmult, &meritstate->penalties, &meritstate->tmpmerit, _state);
42283 0 : if( ae_fp_less(f1,f0) )
42284 : {
42285 :
42286 : /*
42287 : * Step is found!
42288 : */
42289 0 : goto lbl_7;
42290 : }
42291 0 : if( ae_fp_less(localstp,0.001) )
42292 : {
42293 :
42294 : /*
42295 : * Step is shorter than 0.001 times current search direction,
42296 : * it means that no good step can be found.
42297 : */
42298 0 : localstp = (double)(0);
42299 0 : nlcsqp_sqpcopystate(state, &meritstate->stepkx, &meritstate->stepkfi, &meritstate->stepkj, &meritstate->stepkxn, &meritstate->stepkfin, &meritstate->stepkjn, _state);
42300 0 : goto lbl_7;
42301 : }
42302 0 : localstp = nu*localstp;
42303 0 : nu = ae_maxreal(0.1, 0.5*nu, _state);
42304 0 : goto lbl_6;
42305 0 : lbl_7:
42306 0 : smoothnessmonitorfinalizelinesearch(smonitor, _state);
42307 0 : lbl_4:
42308 0 : for(i=0; i<=n-1; i++)
42309 : {
42310 0 : if( state->hasbndl.ptr.p_bool[i] )
42311 : {
42312 0 : meritstate->stepkxn.ptr.p_double[i] = ae_maxreal(meritstate->stepkxn.ptr.p_double[i], state->scaledbndl.ptr.p_double[i], _state);
42313 : }
42314 0 : if( state->hasbndu.ptr.p_bool[i] )
42315 : {
42316 0 : meritstate->stepkxn.ptr.p_double[i] = ae_minreal(meritstate->stepkxn.ptr.p_double[i], state->scaledbndu.ptr.p_double[i], _state);
42317 : }
42318 : }
42319 0 : if( userterminationneeded )
42320 : {
42321 :
42322 : /*
42323 : * User requested termination, break before we move to new point
42324 : */
42325 0 : state->repterminationtype = 8;
42326 0 : meritstate->status = 0;
42327 0 : if( dotrace )
42328 : {
42329 0 : ae_trace("> user requested termination\n");
42330 : }
42331 0 : result = ae_false;
42332 0 : return result;
42333 : }
42334 0 : nlcsqp_lagrangianfg(state, &meritstate->stepkx, state->trustrad, &meritstate->stepkfi, &meritstate->stepkj, &meritstate->lagmult, &meritstate->tmplagrangianfg, &stepklagval, &meritstate->stepklaggrad, _state);
42335 0 : nlcsqp_lagrangianfg(state, &meritstate->stepkxn, state->trustrad, &meritstate->stepkfin, &meritstate->stepkjn, &meritstate->lagmult, &meritstate->tmplagrangianfg, &stepknlagval, &meritstate->stepknlaggrad, _state);
42336 :
42337 : /*
42338 : * Decide whether we want to request increase BigC (a constraint enforcing multiplier for L1 penalized
42339 : * QP subproblem) or not.
42340 : *
42341 : * An increase is NOT needed if at least one of the following holds:
42342 : * * a long step was performed
42343 : * * any single constraint can be made feasible within trust region
42344 : *
42345 : * Thus, BigC is requested to be increased if a short step was made, but there are some
42346 : * constraints that are infeasible within trust region.
42347 : */
42348 0 : if( ae_fp_less(rmaxabsv(n, &meritstate->d, _state),0.9*state->trustrad) )
42349 : {
42350 0 : for(i=0; i<=nec+nic-1; i++)
42351 : {
42352 0 : v = (double)(0);
42353 0 : vv = (double)(0);
42354 0 : for(j=0; j<=n-1; j++)
42355 : {
42356 0 : v = v+state->scaledcleic.ptr.pp_double[i][j]*state->stepkx.ptr.p_double[j];
42357 0 : vv = vv+ae_fabs(state->scaledcleic.ptr.pp_double[i][j]*state->trustrad, _state);
42358 : }
42359 0 : v = v-state->scaledcleic.ptr.pp_double[i][n];
42360 0 : if( i>=nec )
42361 : {
42362 0 : v = ae_maxreal(v, 0.0, _state);
42363 : }
42364 0 : meritstate->increasebigc = meritstate->increasebigc||ae_fp_greater(ae_fabs(v, _state),vv);
42365 : }
42366 0 : for(i=1; i<=nlec+nlic-1; i++)
42367 : {
42368 0 : v = state->stepkfi.ptr.p_double[i];
42369 0 : vv = (double)(0);
42370 0 : for(j=0; j<=n-1; j++)
42371 : {
42372 0 : vv = vv+ae_fabs(state->stepkj.ptr.pp_double[i][j]*state->trustrad, _state);
42373 : }
42374 0 : if( i>=nlec+1 )
42375 : {
42376 0 : v = ae_maxreal(v, 0.0, _state);
42377 : }
42378 0 : meritstate->increasebigc = meritstate->increasebigc||ae_fp_greater(ae_fabs(v, _state),vv);
42379 : }
42380 : }
42381 :
42382 : /*
42383 : * Trace
42384 : */
42385 0 : if( !dotrace )
42386 : {
42387 0 : goto lbl_8;
42388 : }
42389 :
42390 : /*
42391 : * Perform agressive probing of the search direction - additional function evaluations
42392 : * which help us to determine possible discontinuity and nonsmoothness of the problem
42393 : */
42394 0 : if( !doprobing )
42395 : {
42396 0 : goto lbl_10;
42397 : }
42398 0 : smoothnessmonitorstartprobing(smonitor, 1.0, 2, state->trustrad, _state);
42399 0 : smoothnessmonitorstartlinesearch(smonitor, &meritstate->stepkx, &meritstate->stepkfi, &meritstate->stepkj, _state);
42400 0 : lbl_12:
42401 0 : if( !smoothnessmonitorprobe(smonitor, _state) )
42402 : {
42403 0 : goto lbl_13;
42404 : }
42405 0 : for(j=0; j<=n-1; j++)
42406 : {
42407 0 : meritstate->stepkxc.ptr.p_double[j] = meritstate->stepkx.ptr.p_double[j]+smonitor->probingstp*meritstate->d.ptr.p_double[j];
42408 0 : if( state->hasbndl.ptr.p_bool[j] )
42409 : {
42410 0 : meritstate->stepkxc.ptr.p_double[j] = ae_maxreal(meritstate->stepkxc.ptr.p_double[j], state->scaledbndl.ptr.p_double[j], _state);
42411 : }
42412 0 : if( state->hasbndu.ptr.p_bool[j] )
42413 : {
42414 0 : meritstate->stepkxc.ptr.p_double[j] = ae_minreal(meritstate->stepkxc.ptr.p_double[j], state->scaledbndu.ptr.p_double[j], _state);
42415 : }
42416 : }
42417 0 : nlcsqp_sqpsendx(state, &meritstate->stepkxc, _state);
42418 0 : state->needfij = ae_true;
42419 0 : meritstate->rmeritphasestate.stage = 2;
42420 0 : goto lbl_rcomm;
42421 0 : lbl_2:
42422 0 : state->needfij = ae_false;
42423 0 : if( !nlcsqp_sqpretrievefij(state, &meritstate->stepkfic, &meritstate->stepkjc, _state) )
42424 : {
42425 0 : goto lbl_13;
42426 : }
42427 0 : smonitor->probingf.ptr.p_double[0] = nlcsqp_rawlagrangian(state, &meritstate->stepkxc, &meritstate->stepkfic, &meritstate->lagmult, &meritstate->penalties, &meritstate->tmpmerit, _state);
42428 0 : smonitor->probingf.ptr.p_double[1] = meritstate->stepkfic.ptr.p_double[0];
42429 0 : smoothnessmonitorenqueuepoint(smonitor, &meritstate->d, smonitor->probingstp, &meritstate->stepkxc, &meritstate->stepkfic, &meritstate->stepkjc, _state);
42430 0 : goto lbl_12;
42431 0 : lbl_13:
42432 0 : smoothnessmonitorfinalizelinesearch(smonitor, _state);
42433 0 : ae_trace("*** ------------------------------------------------------------\n");
42434 0 : ae_trace("*** | probing search direction suggested by QP subproblem |\n");
42435 0 : ae_trace("*** ------------------------------------------------------------\n");
42436 0 : ae_trace("*** | Step | Lagrangian (unaugmentd)| Target function |\n");
42437 0 : ae_trace("*** |along D| must be smooth | must be smooth |\n");
42438 0 : ae_trace("*** | | function | slope | function | slope |\n");
42439 0 : smoothnessmonitortraceprobingresults(smonitor, _state);
42440 0 : lbl_10:
42441 :
42442 : /*
42443 : * Update debug curvature information - TraceGamma[]
42444 : */
42445 0 : v = (double)(0);
42446 0 : mx = (double)(0);
42447 0 : for(j=0; j<=n-1; j++)
42448 : {
42449 0 : vv = meritstate->stepkxn.ptr.p_double[j]-meritstate->stepkx.ptr.p_double[j];
42450 0 : mx = ae_maxreal(mx, ae_fabs(vv, _state), _state);
42451 0 : v = v+vv*vv;
42452 : }
42453 0 : if( ae_fp_greater(v,(double)(0)) )
42454 : {
42455 :
42456 : /*
42457 : * Step is long enough, update curvature information (used for debugging)
42458 : */
42459 0 : for(i=0; i<=nlec+nlic; i++)
42460 : {
42461 0 : vv = (double)(0);
42462 0 : for(j=0; j<=n-1; j++)
42463 : {
42464 0 : vv = vv+(meritstate->stepkjn.ptr.pp_double[i][j]-meritstate->stepkj.ptr.pp_double[i][j])*(meritstate->stepkxn.ptr.p_double[j]-meritstate->stepkx.ptr.p_double[j]);
42465 : }
42466 0 : state->tracegamma.ptr.p_double[i] = ae_maxreal(state->tracegamma.ptr.p_double[i], ae_fabs(vv/(v+100*n*ae_machineepsilon*ae_machineepsilon), _state), _state);
42467 : }
42468 : }
42469 :
42470 : /*
42471 : * Output other information
42472 : */
42473 0 : mx = (double)(0);
42474 0 : for(i=0; i<=n-1; i++)
42475 : {
42476 0 : mx = ae_maxreal(mx, ae_fabs(meritstate->d.ptr.p_double[i], _state)/state->trustrad, _state);
42477 : }
42478 0 : if( ae_fp_greater(localstp,(double)(0)) )
42479 : {
42480 0 : ae_trace("> nonzero linear step was performed\n");
42481 : }
42482 : else
42483 : {
42484 0 : ae_trace("> zero linear step was performed\n");
42485 : }
42486 0 : ae_trace("max(|Di|)/TrustRad = %0.6f\n",
42487 : (double)(mx));
42488 0 : ae_trace("stp = %0.6f\n",
42489 : (double)(localstp));
42490 0 : if( dotracexd )
42491 : {
42492 0 : ae_trace("X0 (scaled) = ");
42493 0 : tracevectorautoprec(&meritstate->stepkx, 0, n, _state);
42494 0 : ae_trace("\n");
42495 0 : ae_trace("D (scaled) = ");
42496 0 : tracevectorautoprec(&meritstate->d, 0, n, _state);
42497 0 : ae_trace("\n");
42498 0 : ae_trace("X1 (scaled) = ");
42499 0 : tracevectorautoprec(&meritstate->stepkxn, 0, n, _state);
42500 0 : ae_trace("\n");
42501 : }
42502 0 : ae_trace("meritF: %14.6e -> %14.6e (delta=%11.3e)\n",
42503 : (double)(f0),
42504 : (double)(f1),
42505 : (double)(f1-f0));
42506 0 : ae_trace("scaled-targetF: %14.6e -> %14.6e (delta=%11.3e)\n",
42507 0 : (double)(meritstate->stepkfi.ptr.p_double[0]),
42508 0 : (double)(meritstate->stepkfin.ptr.p_double[0]),
42509 0 : (double)(meritstate->stepkfin.ptr.p_double[0]-meritstate->stepkfi.ptr.p_double[0]));
42510 0 : ae_trace("> evaluating possible Hessian update\n");
42511 0 : v = (double)(0);
42512 0 : for(i=0; i<=n-1; i++)
42513 : {
42514 0 : v = v+(meritstate->stepkxn.ptr.p_double[i]-meritstate->stepkx.ptr.p_double[i])*(meritstate->stepknlaggrad.ptr.p_double[i]-meritstate->stepklaggrad.ptr.p_double[i]);
42515 : }
42516 0 : ae_trace("(Sk,Yk) = %0.3e\n",
42517 : (double)(v));
42518 0 : v = (double)(0);
42519 0 : for(i=0; i<=n-1; i++)
42520 : {
42521 0 : v = v+ae_sqr(meritstate->stepkxn.ptr.p_double[i]-meritstate->stepkx.ptr.p_double[i], _state);
42522 : }
42523 0 : ae_trace("(Sk,Sk) = %0.3e\n",
42524 : (double)(v));
42525 0 : v = (double)(0);
42526 0 : for(i=0; i<=n-1; i++)
42527 : {
42528 0 : v = v+ae_sqr(meritstate->stepknlaggrad.ptr.p_double[i]-meritstate->stepklaggrad.ptr.p_double[i], _state);
42529 : }
42530 0 : ae_trace("(Yk,Yk) = %0.3e\n",
42531 : (double)(v));
42532 0 : v = (double)(0);
42533 0 : for(i=0; i<=n-1; i++)
42534 : {
42535 0 : v = v+ae_sqr(meritstate->stepkxn.ptr.p_double[i]-meritstate->stepkx.ptr.p_double[i], _state)*state->subsolver.h.ptr.pp_double[i][i];
42536 0 : for(j=i+1; j<=n-1; j++)
42537 : {
42538 0 : v = v+2*(meritstate->stepkxn.ptr.p_double[i]-meritstate->stepkx.ptr.p_double[i])*state->subsolver.h.ptr.pp_double[i][j]*(meritstate->stepkxn.ptr.p_double[j]-meritstate->stepkx.ptr.p_double[j]);
42539 : }
42540 : }
42541 0 : ae_trace("Sk*Bk*Sk = %0.3e\n",
42542 : (double)(v));
42543 0 : v = state->subsolver.h.ptr.pp_double[0][0];
42544 0 : for(i=0; i<=n-1; i++)
42545 : {
42546 0 : v = ae_minreal(v, state->subsolver.h.ptr.pp_double[i][i], _state);
42547 : }
42548 0 : ae_trace("mindiag(Bk) = %0.3e\n",
42549 : (double)(v));
42550 0 : v = state->subsolver.h.ptr.pp_double[0][0];
42551 0 : for(i=0; i<=n-1; i++)
42552 : {
42553 0 : v = ae_maxreal(v, state->subsolver.h.ptr.pp_double[i][i], _state);
42554 : }
42555 0 : ae_trace("maxdiag(Bk) = %0.3e\n",
42556 : (double)(v));
42557 0 : lbl_8:
42558 :
42559 : /*
42560 : * Perform Hessian update
42561 : */
42562 0 : hessianupdateperformed = ae_false;
42563 0 : if( ae_fp_greater(localstp,(double)(0)) )
42564 : {
42565 0 : hessianupdateperformed = nlcsqp_qpsubproblemupdatehessian(state, &state->subsolver, &meritstate->stepkx, &meritstate->stepklaggrad, &meritstate->stepkxn, &meritstate->stepknlaggrad, _state);
42566 : }
42567 0 : if( dotrace )
42568 : {
42569 0 : if( hessianupdateperformed )
42570 : {
42571 0 : ae_trace("> Hessian updated\n");
42572 0 : v = state->subsolver.h.ptr.pp_double[0][0];
42573 0 : for(i=0; i<=n-1; i++)
42574 : {
42575 0 : v = ae_minreal(v, state->subsolver.h.ptr.pp_double[i][i], _state);
42576 : }
42577 0 : ae_trace("mindiag(Bk) = %0.3e\n",
42578 : (double)(v));
42579 0 : v = state->subsolver.h.ptr.pp_double[0][0];
42580 0 : for(i=0; i<=n-1; i++)
42581 : {
42582 0 : v = ae_maxreal(v, state->subsolver.h.ptr.pp_double[i][i], _state);
42583 : }
42584 0 : ae_trace("maxdiag(Bk) = %0.3e\n",
42585 : (double)(v));
42586 : }
42587 : else
42588 : {
42589 0 : ae_trace("> skipping Hessian update\n");
42590 : }
42591 : }
42592 :
42593 : /*
42594 : * Move to new point
42595 : */
42596 0 : stp = localstp;
42597 0 : nlcsqp_sqpcopystate(state, &meritstate->stepkxn, &meritstate->stepkfin, &meritstate->stepkjn, &meritstate->stepkx, &meritstate->stepkfi, &meritstate->stepkj, _state);
42598 0 : if( ae_fp_less_eq(localstp,(double)(0)) )
42599 : {
42600 0 : goto lbl_14;
42601 : }
42602 :
42603 : /*
42604 : * Report one more inner iteration
42605 : */
42606 0 : nlcsqp_sqpsendx(state, &meritstate->stepkx, _state);
42607 0 : state->f = meritstate->stepkfi.ptr.p_double[0]*state->fscales.ptr.p_double[0];
42608 0 : state->xupdated = ae_true;
42609 0 : meritstate->rmeritphasestate.stage = 3;
42610 0 : goto lbl_rcomm;
42611 0 : lbl_3:
42612 0 : state->xupdated = ae_false;
42613 :
42614 : /*
42615 : * Update constraint violations
42616 : */
42617 0 : checklcviolation(&state->scaledcleic, &state->lcsrcidx, nec, nic, &meritstate->stepkx, n, &state->replcerr, &state->replcidx, _state);
42618 0 : unscaleandchecknlcviolation(&meritstate->stepkfi, &state->fscales, nlec, nlic, &state->repnlcerr, &state->repnlcidx, _state);
42619 0 : lbl_14:
42620 0 : result = ae_false;
42621 0 : return result;
42622 :
42623 : /*
42624 : * Saving state
42625 : */
42626 0 : lbl_rcomm:
42627 0 : result = ae_true;
42628 0 : meritstate->rmeritphasestate.ia.ptr.p_int[0] = n;
42629 0 : meritstate->rmeritphasestate.ia.ptr.p_int[1] = nslack;
42630 0 : meritstate->rmeritphasestate.ia.ptr.p_int[2] = nec;
42631 0 : meritstate->rmeritphasestate.ia.ptr.p_int[3] = nic;
42632 0 : meritstate->rmeritphasestate.ia.ptr.p_int[4] = nlec;
42633 0 : meritstate->rmeritphasestate.ia.ptr.p_int[5] = nlic;
42634 0 : meritstate->rmeritphasestate.ia.ptr.p_int[6] = i;
42635 0 : meritstate->rmeritphasestate.ia.ptr.p_int[7] = j;
42636 0 : meritstate->rmeritphasestate.ba.ptr.p_bool[0] = hessianupdateperformed;
42637 0 : meritstate->rmeritphasestate.ba.ptr.p_bool[1] = dotrace;
42638 0 : meritstate->rmeritphasestate.ba.ptr.p_bool[2] = doprobing;
42639 0 : meritstate->rmeritphasestate.ba.ptr.p_bool[3] = dotracexd;
42640 0 : meritstate->rmeritphasestate.ra.ptr.p_double[0] = v;
42641 0 : meritstate->rmeritphasestate.ra.ptr.p_double[1] = vv;
42642 0 : meritstate->rmeritphasestate.ra.ptr.p_double[2] = mx;
42643 0 : meritstate->rmeritphasestate.ra.ptr.p_double[3] = f0;
42644 0 : meritstate->rmeritphasestate.ra.ptr.p_double[4] = f1;
42645 0 : meritstate->rmeritphasestate.ra.ptr.p_double[5] = nu;
42646 0 : meritstate->rmeritphasestate.ra.ptr.p_double[6] = localstp;
42647 0 : meritstate->rmeritphasestate.ra.ptr.p_double[7] = stepklagval;
42648 0 : meritstate->rmeritphasestate.ra.ptr.p_double[8] = stepknlagval;
42649 0 : meritstate->rmeritphasestate.ra.ptr.p_double[9] = stp;
42650 0 : return result;
42651 : }
42652 :
42653 :
42654 : /*************************************************************************
42655 : This function initializes MeritPhase temporaries. It should be called before
42656 : beginning of each new iteration. You may call it multiple times for the
42657 : same instance of MeritPhase temporaries.
42658 :
42659 : INPUT PARAMETERS:
42660 : MeritState - instance to be initialized.
42661 : N - problem dimensionality
42662 : NEC, NIC - linear equality/inequality constraint count
42663 : NLEC, NLIC - nonlinear equality/inequality constraint count
42664 :
42665 : OUTPUT PARAMETERS:
42666 : IncreaseBigC - whether increasing BigC is suggested (we detected
42667 : infeasible constraints that are NOT improved)
42668 : or not.
42669 : MeritState - instance being initialized
42670 :
42671 : -- ALGLIB --
42672 : Copyright 05.02.2019 by Bochkanov Sergey
42673 : *************************************************************************/
42674 0 : static void nlcsqp_meritphaseresults(minsqpmeritphasestate* meritstate,
42675 : /* Real */ ae_vector* curx,
42676 : /* Real */ ae_vector* curfi,
42677 : /* Real */ ae_matrix* curj,
42678 : /* Real */ ae_vector* lagmult,
42679 : ae_bool* increasebigc,
42680 : ae_int_t* status,
42681 : ae_state *_state)
42682 : {
42683 : ae_int_t i;
42684 : ae_int_t j;
42685 :
42686 :
42687 0 : *increasebigc = meritstate->increasebigc;
42688 0 : *status = meritstate->status;
42689 0 : for(i=0; i<=meritstate->n-1; i++)
42690 : {
42691 0 : curx->ptr.p_double[i] = meritstate->stepkx.ptr.p_double[i];
42692 : }
42693 0 : for(i=0; i<=meritstate->nlec+meritstate->nlic; i++)
42694 : {
42695 0 : curfi->ptr.p_double[i] = meritstate->stepkfi.ptr.p_double[i];
42696 0 : for(j=0; j<=meritstate->n-1; j++)
42697 : {
42698 0 : curj->ptr.pp_double[i][j] = meritstate->stepkj.ptr.pp_double[i][j];
42699 : }
42700 : }
42701 0 : ae_assert(lagmult->cnt>=meritstate->nec+meritstate->nic+meritstate->nlec+meritstate->nlic, "MeritPhaseResults: LagMult too short", _state);
42702 0 : for(i=0; i<=meritstate->nec+meritstate->nic+meritstate->nlec+meritstate->nlic-1; i++)
42703 : {
42704 0 : lagmult->ptr.p_double[i] = meritstate->lagmult.ptr.p_double[i];
42705 : }
42706 0 : }
42707 :
42708 :
42709 : /*************************************************************************
42710 : Copies X to State.X
42711 : *************************************************************************/
42712 0 : static void nlcsqp_sqpsendx(minsqpstate* state,
42713 : /* Real */ ae_vector* xs,
42714 : ae_state *_state)
42715 : {
42716 : ae_int_t i;
42717 : ae_int_t n;
42718 :
42719 :
42720 0 : n = state->n;
42721 0 : for(i=0; i<=n-1; i++)
42722 : {
42723 0 : if( state->hasbndl.ptr.p_bool[i]&&xs->ptr.p_double[i]<=state->scaledbndl.ptr.p_double[i] )
42724 : {
42725 0 : state->x.ptr.p_double[i] = state->scaledbndl.ptr.p_double[i];
42726 0 : continue;
42727 : }
42728 0 : if( state->hasbndu.ptr.p_bool[i]&&xs->ptr.p_double[i]>=state->scaledbndu.ptr.p_double[i] )
42729 : {
42730 0 : state->x.ptr.p_double[i] = state->scaledbndu.ptr.p_double[i];
42731 0 : continue;
42732 : }
42733 0 : state->x.ptr.p_double[i] = xs->ptr.p_double[i];
42734 : }
42735 0 : }
42736 :
42737 :
42738 : /*************************************************************************
42739 : Retrieves F-vector and scaled Jacobian, copies them to FiS and JS.
42740 :
42741 : Returns True on success, False on failure (when F or J are not finite numbers).
42742 : *************************************************************************/
42743 0 : static ae_bool nlcsqp_sqpretrievefij(minsqpstate* state,
42744 : /* Real */ ae_vector* fis,
42745 : /* Real */ ae_matrix* js,
42746 : ae_state *_state)
42747 : {
42748 : ae_int_t nlec;
42749 : ae_int_t nlic;
42750 : ae_int_t n;
42751 : ae_int_t i;
42752 : ae_int_t j;
42753 : double v;
42754 : double vv;
42755 : ae_bool result;
42756 :
42757 :
42758 0 : n = state->n;
42759 0 : nlec = state->nlec;
42760 0 : nlic = state->nlic;
42761 0 : v = (double)(0);
42762 0 : for(i=0; i<=nlec+nlic; i++)
42763 : {
42764 0 : vv = 1/state->fscales.ptr.p_double[i];
42765 0 : fis->ptr.p_double[i] = vv*state->fi.ptr.p_double[i];
42766 0 : v = 0.1*v+fis->ptr.p_double[i];
42767 0 : for(j=0; j<=n-1; j++)
42768 : {
42769 0 : js->ptr.pp_double[i][j] = vv*state->j.ptr.pp_double[i][j];
42770 0 : v = 0.1*v+js->ptr.pp_double[i][j];
42771 : }
42772 : }
42773 0 : result = ae_isfinite(v, _state);
42774 0 : return result;
42775 : }
42776 :
42777 :
42778 : /*************************************************************************
42779 : Copies state (X point, Fi vector, J jacobian) to preallocated storage.
42780 : *************************************************************************/
42781 0 : static void nlcsqp_sqpcopystate(minsqpstate* state,
42782 : /* Real */ ae_vector* x0,
42783 : /* Real */ ae_vector* fi0,
42784 : /* Real */ ae_matrix* j0,
42785 : /* Real */ ae_vector* x1,
42786 : /* Real */ ae_vector* fi1,
42787 : /* Real */ ae_matrix* j1,
42788 : ae_state *_state)
42789 : {
42790 : ae_int_t nlec;
42791 : ae_int_t nlic;
42792 : ae_int_t n;
42793 : ae_int_t i;
42794 : ae_int_t j;
42795 :
42796 :
42797 0 : n = state->n;
42798 0 : nlec = state->nlec;
42799 0 : nlic = state->nlic;
42800 0 : for(i=0; i<=n-1; i++)
42801 : {
42802 0 : x1->ptr.p_double[i] = x0->ptr.p_double[i];
42803 : }
42804 0 : for(i=0; i<=nlec+nlic; i++)
42805 : {
42806 0 : fi1->ptr.p_double[i] = fi0->ptr.p_double[i];
42807 0 : for(j=0; j<=n-1; j++)
42808 : {
42809 0 : j1->ptr.pp_double[i][j] = j0->ptr.pp_double[i][j];
42810 : }
42811 : }
42812 0 : }
42813 :
42814 :
42815 : /*************************************************************************
42816 : This function calculates Lagrangian of the problem (in scaled variables):
42817 : its value and gradient.
42818 :
42819 : Additionally it also estimates violation of linear constraints at the point
42820 : as well as index of the most violated constraint
42821 : *************************************************************************/
42822 0 : static void nlcsqp_lagrangianfg(minsqpstate* state,
42823 : /* Real */ ae_vector* x,
42824 : double trustrad,
42825 : /* Real */ ae_vector* fi,
42826 : /* Real */ ae_matrix* j,
42827 : /* Real */ ae_vector* lagmult,
42828 : minsqptmplagrangian* tmp,
42829 : double* f,
42830 : /* Real */ ae_vector* g,
42831 : ae_state *_state)
42832 : {
42833 : ae_int_t i;
42834 : ae_int_t n;
42835 : ae_int_t nec;
42836 : ae_int_t nic;
42837 : ae_int_t nlec;
42838 : ae_int_t nlic;
42839 : double v;
42840 : double vlag;
42841 : double vact;
42842 : double vd;
42843 : ae_bool usesparsegemv;
42844 :
42845 0 : *f = 0;
42846 :
42847 0 : n = state->n;
42848 0 : nec = state->nec;
42849 0 : nic = state->nic;
42850 0 : nlec = state->nlec;
42851 0 : nlic = state->nlic;
42852 :
42853 : /*
42854 : * Target function
42855 : */
42856 0 : *f = fi->ptr.p_double[0];
42857 0 : for(i=0; i<=n-1; i++)
42858 : {
42859 0 : g->ptr.p_double[i] = j->ptr.pp_double[0][i];
42860 : }
42861 :
42862 : /*
42863 : * Lagrangian terms for linear constraints, constraint violations
42864 : */
42865 0 : if( nec+nic>0 )
42866 : {
42867 0 : usesparsegemv = state->subsolver.sparserawlc.ridx.ptr.p_int[nec+nic]<sparselevel2density(_state)*n*(nec+nic);
42868 0 : rvectorsetlengthatleast(&tmp->sclagtmp0, ae_maxint(nec+nic, n, _state), _state);
42869 0 : rvectorsetlengthatleast(&tmp->sclagtmp1, ae_maxint(nec+nic, n, _state), _state);
42870 0 : if( usesparsegemv )
42871 : {
42872 0 : sparsemv(&state->subsolver.sparserawlc, x, &tmp->sclagtmp0, _state);
42873 : }
42874 : else
42875 : {
42876 0 : rmatrixgemv(nec+nic, n, 1.0, &state->scaledcleic, 0, 0, 0, x, 0, 0.0, &tmp->sclagtmp0, 0, _state);
42877 : }
42878 0 : for(i=0; i<=nec+nic-1; i++)
42879 : {
42880 :
42881 : /*
42882 : * Prepare
42883 : */
42884 0 : v = tmp->sclagtmp0.ptr.p_double[i]-state->scaledcleic.ptr.pp_double[i][n];
42885 0 : vlag = lagmult->ptr.p_double[i];
42886 0 : tmp->sclagtmp1.ptr.p_double[i] = (double)(0);
42887 :
42888 : /*
42889 : * Primary Lagrangian term
42890 : */
42891 0 : vact = v;
42892 0 : vd = (double)(1);
42893 0 : *f = *f+vlag*vact;
42894 0 : tmp->sclagtmp1.ptr.p_double[i] = tmp->sclagtmp1.ptr.p_double[i]+vlag*vd;
42895 :
42896 : /*
42897 : * Quadratic augmentation term
42898 : */
42899 0 : if( i<nec||v>0 )
42900 : {
42901 0 : vact = v;
42902 : }
42903 : else
42904 : {
42905 0 : vact = (double)(0);
42906 : }
42907 0 : *f = *f+0.5*nlcsqp_augmentationfactor*vact*vact;
42908 0 : tmp->sclagtmp1.ptr.p_double[i] = tmp->sclagtmp1.ptr.p_double[i]+nlcsqp_augmentationfactor*vact;
42909 : }
42910 0 : if( usesparsegemv )
42911 : {
42912 0 : sparsemtv(&state->subsolver.sparserawlc, &tmp->sclagtmp1, &tmp->sclagtmp0, _state);
42913 0 : for(i=0; i<=n-1; i++)
42914 : {
42915 0 : g->ptr.p_double[i] = g->ptr.p_double[i]+tmp->sclagtmp0.ptr.p_double[i];
42916 : }
42917 : }
42918 : else
42919 : {
42920 0 : rmatrixgemv(n, nec+nic, 1.0, &state->scaledcleic, 0, 0, 1, &tmp->sclagtmp1, 0, 1.0, g, 0, _state);
42921 : }
42922 : }
42923 :
42924 : /*
42925 : * Lagrangian terms for nonlinear constraints
42926 : */
42927 0 : rvectorsetlengthatleast(&tmp->sclagtmp1, nlec+nlic, _state);
42928 0 : for(i=0; i<=nlec+nlic-1; i++)
42929 : {
42930 0 : v = fi->ptr.p_double[1+i];
42931 0 : vlag = lagmult->ptr.p_double[nec+nic+i];
42932 0 : tmp->sclagtmp1.ptr.p_double[i] = (double)(0);
42933 :
42934 : /*
42935 : * Lagrangian term
42936 : */
42937 0 : vact = v;
42938 0 : vd = (double)(1);
42939 0 : *f = *f+vlag*vact;
42940 0 : tmp->sclagtmp1.ptr.p_double[i] = tmp->sclagtmp1.ptr.p_double[i]+vlag*vd;
42941 :
42942 : /*
42943 : * Augmentation term
42944 : */
42945 0 : if( i<nlec||v>0 )
42946 : {
42947 0 : vact = v;
42948 : }
42949 : else
42950 : {
42951 0 : vact = (double)(0);
42952 : }
42953 0 : *f = *f+0.5*nlcsqp_augmentationfactor*vact*vact;
42954 0 : tmp->sclagtmp1.ptr.p_double[i] = tmp->sclagtmp1.ptr.p_double[i]+nlcsqp_augmentationfactor*vact;
42955 : }
42956 0 : rmatrixgemv(n, nlec+nlic, 1.0, j, 1, 0, 1, &tmp->sclagtmp1, 0, 1.0, g, 0, _state);
42957 0 : }
42958 :
42959 :
42960 : /*************************************************************************
42961 : This function calculates L1-penalized merit function
42962 : *************************************************************************/
42963 0 : static double nlcsqp_meritfunction(minsqpstate* state,
42964 : /* Real */ ae_vector* x,
42965 : /* Real */ ae_vector* fi,
42966 : /* Real */ ae_vector* lagmult,
42967 : /* Real */ ae_vector* penalties,
42968 : minsqptmpmerit* tmp,
42969 : ae_state *_state)
42970 : {
42971 : double tmp0;
42972 : double tmp1;
42973 : double result;
42974 :
42975 :
42976 0 : nlcsqp_meritfunctionandrawlagrangian(state, x, fi, lagmult, penalties, tmp, &tmp0, &tmp1, _state);
42977 0 : result = tmp0;
42978 0 : return result;
42979 : }
42980 :
42981 :
42982 : /*************************************************************************
42983 : This function calculates raw (unaugmented and smooth) Lagrangian
42984 : *************************************************************************/
42985 0 : static double nlcsqp_rawlagrangian(minsqpstate* state,
42986 : /* Real */ ae_vector* x,
42987 : /* Real */ ae_vector* fi,
42988 : /* Real */ ae_vector* lagmult,
42989 : /* Real */ ae_vector* penalties,
42990 : minsqptmpmerit* tmp,
42991 : ae_state *_state)
42992 : {
42993 : double tmp0;
42994 : double tmp1;
42995 : double result;
42996 :
42997 :
42998 0 : nlcsqp_meritfunctionandrawlagrangian(state, x, fi, lagmult, penalties, tmp, &tmp0, &tmp1, _state);
42999 0 : result = tmp1;
43000 0 : return result;
43001 : }
43002 :
43003 :
43004 : /*************************************************************************
43005 : This function calculates L1-penalized merit function and raw (smooth and
43006 : un-augmented) Lagrangian
43007 : *************************************************************************/
43008 0 : static void nlcsqp_meritfunctionandrawlagrangian(minsqpstate* state,
43009 : /* Real */ ae_vector* x,
43010 : /* Real */ ae_vector* fi,
43011 : /* Real */ ae_vector* lagmult,
43012 : /* Real */ ae_vector* penalties,
43013 : minsqptmpmerit* tmp,
43014 : double* meritf,
43015 : double* rawlag,
43016 : ae_state *_state)
43017 : {
43018 : ae_int_t i;
43019 : ae_int_t n;
43020 : ae_int_t nec;
43021 : ae_int_t nic;
43022 : ae_int_t nlec;
43023 : ae_int_t nlic;
43024 : double v;
43025 :
43026 0 : *meritf = 0;
43027 0 : *rawlag = 0;
43028 :
43029 0 : n = state->n;
43030 0 : nec = state->nec;
43031 0 : nic = state->nic;
43032 0 : nlec = state->nlec;
43033 0 : nlic = state->nlic;
43034 :
43035 : /*
43036 : * Merit function and Lagrangian: primary term
43037 : */
43038 0 : *meritf = fi->ptr.p_double[0];
43039 0 : *rawlag = fi->ptr.p_double[0];
43040 :
43041 : /*
43042 : * Merit function: augmentation and penalty for linear constraints
43043 : */
43044 0 : rvectorsetlengthatleast(&tmp->mftmp0, nec+nic, _state);
43045 0 : rmatrixgemv(nec+nic, n, 1.0, &state->scaledcleic, 0, 0, 0, x, 0, 0.0, &tmp->mftmp0, 0, _state);
43046 0 : for(i=0; i<=nec+nic-1; i++)
43047 : {
43048 0 : v = tmp->mftmp0.ptr.p_double[i]-state->scaledcleic.ptr.pp_double[i][n];
43049 0 : if( i<nec )
43050 : {
43051 :
43052 : /*
43053 : * Merit function: augmentation term + L1 penalty term
43054 : */
43055 0 : *meritf = *meritf+0.5*nlcsqp_augmentationfactor*v*v;
43056 0 : *meritf = *meritf+nlcsqp_meritfunctionbase*ae_fabs(v, _state)+nlcsqp_meritfunctiongain*ae_fabs(1+penalties->ptr.p_double[i], _state)*ae_fabs(v, _state);
43057 :
43058 : /*
43059 : * Raw Lagrangian
43060 : */
43061 0 : *rawlag = *rawlag+lagmult->ptr.p_double[i]*v;
43062 : }
43063 : else
43064 : {
43065 :
43066 : /*
43067 : * Merit function: augmentation term + L1 penalty term
43068 : */
43069 0 : *meritf = *meritf+0.5*nlcsqp_augmentationfactor*ae_sqr(ae_maxreal(v, (double)(0), _state), _state);
43070 0 : *meritf = *meritf+nlcsqp_meritfunctionbase*ae_maxreal(v, (double)(0), _state)+nlcsqp_meritfunctiongain*ae_fabs(1+penalties->ptr.p_double[i], _state)*ae_maxreal(v, (double)(0), _state);
43071 :
43072 : /*
43073 : * Raw Lagrangian
43074 : */
43075 0 : *rawlag = *rawlag+lagmult->ptr.p_double[i]*v;
43076 : }
43077 : }
43078 :
43079 : /*
43080 : * Merit function: augmentation and penalty for nonlinear constraints
43081 : */
43082 0 : for(i=0; i<=nlec+nlic-1; i++)
43083 : {
43084 0 : v = fi->ptr.p_double[1+i];
43085 0 : if( i<nlec )
43086 : {
43087 :
43088 : /*
43089 : * Merit function: augmentation term + L1 penalty term
43090 : */
43091 0 : *meritf = *meritf+0.5*nlcsqp_augmentationfactor*v*v;
43092 0 : *meritf = *meritf+nlcsqp_meritfunctionbase*ae_fabs(v, _state)+nlcsqp_meritfunctiongain*ae_fabs(1+penalties->ptr.p_double[nec+nic+i], _state)*ae_fabs(v, _state);
43093 :
43094 : /*
43095 : * Raw Lagrangian
43096 : */
43097 0 : *rawlag = *rawlag+lagmult->ptr.p_double[nec+nic+i]*v;
43098 : }
43099 : else
43100 : {
43101 :
43102 : /*
43103 : * Merit function: augmentation term + L1 penalty term
43104 : */
43105 0 : *meritf = *meritf+0.5*nlcsqp_augmentationfactor*ae_sqr(ae_maxreal(v, (double)(0), _state), _state);
43106 0 : *meritf = *meritf+nlcsqp_meritfunctionbase*ae_maxreal(v, (double)(0), _state)+nlcsqp_meritfunctiongain*ae_fabs(1+penalties->ptr.p_double[nec+nic+i], _state)*ae_maxreal(v, (double)(0), _state);
43107 :
43108 : /*
43109 : * Raw Lagrangian
43110 : */
43111 0 : *rawlag = *rawlag+lagmult->ptr.p_double[nec+nic+i]*v;
43112 : }
43113 : }
43114 0 : }
43115 :
43116 :
43117 0 : void _minsqpsubsolver_init(void* _p, ae_state *_state, ae_bool make_automatic)
43118 : {
43119 0 : minsqpsubsolver *p = (minsqpsubsolver*)_p;
43120 0 : ae_touch_ptr((void*)p);
43121 0 : _vipmstate_init(&p->ipmsolver, _state, make_automatic);
43122 0 : ae_vector_init(&p->curb, 0, DT_REAL, _state, make_automatic);
43123 0 : ae_vector_init(&p->curbndl, 0, DT_REAL, _state, make_automatic);
43124 0 : ae_vector_init(&p->curbndu, 0, DT_REAL, _state, make_automatic);
43125 0 : ae_vector_init(&p->cural, 0, DT_REAL, _state, make_automatic);
43126 0 : ae_vector_init(&p->curau, 0, DT_REAL, _state, make_automatic);
43127 0 : _sparsematrix_init(&p->sparserawlc, _state, make_automatic);
43128 0 : _sparsematrix_init(&p->sparseefflc, _state, make_automatic);
43129 0 : ae_vector_init(&p->d0, 0, DT_REAL, _state, make_automatic);
43130 0 : ae_matrix_init(&p->h, 0, 0, DT_REAL, _state, make_automatic);
43131 0 : ae_matrix_init(&p->densedummy, 0, 0, DT_REAL, _state, make_automatic);
43132 0 : _sparsematrix_init(&p->sparsedummy, _state, make_automatic);
43133 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
43134 0 : ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic);
43135 0 : ae_vector_init(&p->tmp2, 0, DT_REAL, _state, make_automatic);
43136 0 : ae_vector_init(&p->sk, 0, DT_REAL, _state, make_automatic);
43137 0 : ae_vector_init(&p->yk, 0, DT_REAL, _state, make_automatic);
43138 0 : ae_vector_init(&p->hasbndl, 0, DT_BOOL, _state, make_automatic);
43139 0 : ae_vector_init(&p->hasbndu, 0, DT_BOOL, _state, make_automatic);
43140 0 : ae_vector_init(&p->hasal, 0, DT_BOOL, _state, make_automatic);
43141 0 : ae_vector_init(&p->hasau, 0, DT_BOOL, _state, make_automatic);
43142 0 : ae_matrix_init(&p->activea, 0, 0, DT_REAL, _state, make_automatic);
43143 0 : ae_vector_init(&p->activerhs, 0, DT_REAL, _state, make_automatic);
43144 0 : ae_vector_init(&p->activeidx, 0, DT_INT, _state, make_automatic);
43145 0 : }
43146 :
43147 :
43148 0 : void _minsqpsubsolver_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
43149 : {
43150 0 : minsqpsubsolver *dst = (minsqpsubsolver*)_dst;
43151 0 : minsqpsubsolver *src = (minsqpsubsolver*)_src;
43152 0 : dst->algokind = src->algokind;
43153 0 : _vipmstate_init_copy(&dst->ipmsolver, &src->ipmsolver, _state, make_automatic);
43154 0 : ae_vector_init_copy(&dst->curb, &src->curb, _state, make_automatic);
43155 0 : ae_vector_init_copy(&dst->curbndl, &src->curbndl, _state, make_automatic);
43156 0 : ae_vector_init_copy(&dst->curbndu, &src->curbndu, _state, make_automatic);
43157 0 : ae_vector_init_copy(&dst->cural, &src->cural, _state, make_automatic);
43158 0 : ae_vector_init_copy(&dst->curau, &src->curau, _state, make_automatic);
43159 0 : _sparsematrix_init_copy(&dst->sparserawlc, &src->sparserawlc, _state, make_automatic);
43160 0 : _sparsematrix_init_copy(&dst->sparseefflc, &src->sparseefflc, _state, make_automatic);
43161 0 : ae_vector_init_copy(&dst->d0, &src->d0, _state, make_automatic);
43162 0 : ae_matrix_init_copy(&dst->h, &src->h, _state, make_automatic);
43163 0 : ae_matrix_init_copy(&dst->densedummy, &src->densedummy, _state, make_automatic);
43164 0 : _sparsematrix_init_copy(&dst->sparsedummy, &src->sparsedummy, _state, make_automatic);
43165 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
43166 0 : ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic);
43167 0 : ae_vector_init_copy(&dst->tmp2, &src->tmp2, _state, make_automatic);
43168 0 : ae_vector_init_copy(&dst->sk, &src->sk, _state, make_automatic);
43169 0 : ae_vector_init_copy(&dst->yk, &src->yk, _state, make_automatic);
43170 0 : ae_vector_init_copy(&dst->hasbndl, &src->hasbndl, _state, make_automatic);
43171 0 : ae_vector_init_copy(&dst->hasbndu, &src->hasbndu, _state, make_automatic);
43172 0 : ae_vector_init_copy(&dst->hasal, &src->hasal, _state, make_automatic);
43173 0 : ae_vector_init_copy(&dst->hasau, &src->hasau, _state, make_automatic);
43174 0 : ae_matrix_init_copy(&dst->activea, &src->activea, _state, make_automatic);
43175 0 : ae_vector_init_copy(&dst->activerhs, &src->activerhs, _state, make_automatic);
43176 0 : ae_vector_init_copy(&dst->activeidx, &src->activeidx, _state, make_automatic);
43177 0 : dst->activesetsize = src->activesetsize;
43178 0 : }
43179 :
43180 :
43181 0 : void _minsqpsubsolver_clear(void* _p)
43182 : {
43183 0 : minsqpsubsolver *p = (minsqpsubsolver*)_p;
43184 0 : ae_touch_ptr((void*)p);
43185 0 : _vipmstate_clear(&p->ipmsolver);
43186 0 : ae_vector_clear(&p->curb);
43187 0 : ae_vector_clear(&p->curbndl);
43188 0 : ae_vector_clear(&p->curbndu);
43189 0 : ae_vector_clear(&p->cural);
43190 0 : ae_vector_clear(&p->curau);
43191 0 : _sparsematrix_clear(&p->sparserawlc);
43192 0 : _sparsematrix_clear(&p->sparseefflc);
43193 0 : ae_vector_clear(&p->d0);
43194 0 : ae_matrix_clear(&p->h);
43195 0 : ae_matrix_clear(&p->densedummy);
43196 0 : _sparsematrix_clear(&p->sparsedummy);
43197 0 : ae_vector_clear(&p->tmp0);
43198 0 : ae_vector_clear(&p->tmp1);
43199 0 : ae_vector_clear(&p->tmp2);
43200 0 : ae_vector_clear(&p->sk);
43201 0 : ae_vector_clear(&p->yk);
43202 0 : ae_vector_clear(&p->hasbndl);
43203 0 : ae_vector_clear(&p->hasbndu);
43204 0 : ae_vector_clear(&p->hasal);
43205 0 : ae_vector_clear(&p->hasau);
43206 0 : ae_matrix_clear(&p->activea);
43207 0 : ae_vector_clear(&p->activerhs);
43208 0 : ae_vector_clear(&p->activeidx);
43209 0 : }
43210 :
43211 :
43212 0 : void _minsqpsubsolver_destroy(void* _p)
43213 : {
43214 0 : minsqpsubsolver *p = (minsqpsubsolver*)_p;
43215 0 : ae_touch_ptr((void*)p);
43216 0 : _vipmstate_destroy(&p->ipmsolver);
43217 0 : ae_vector_destroy(&p->curb);
43218 0 : ae_vector_destroy(&p->curbndl);
43219 0 : ae_vector_destroy(&p->curbndu);
43220 0 : ae_vector_destroy(&p->cural);
43221 0 : ae_vector_destroy(&p->curau);
43222 0 : _sparsematrix_destroy(&p->sparserawlc);
43223 0 : _sparsematrix_destroy(&p->sparseefflc);
43224 0 : ae_vector_destroy(&p->d0);
43225 0 : ae_matrix_destroy(&p->h);
43226 0 : ae_matrix_destroy(&p->densedummy);
43227 0 : _sparsematrix_destroy(&p->sparsedummy);
43228 0 : ae_vector_destroy(&p->tmp0);
43229 0 : ae_vector_destroy(&p->tmp1);
43230 0 : ae_vector_destroy(&p->tmp2);
43231 0 : ae_vector_destroy(&p->sk);
43232 0 : ae_vector_destroy(&p->yk);
43233 0 : ae_vector_destroy(&p->hasbndl);
43234 0 : ae_vector_destroy(&p->hasbndu);
43235 0 : ae_vector_destroy(&p->hasal);
43236 0 : ae_vector_destroy(&p->hasau);
43237 0 : ae_matrix_destroy(&p->activea);
43238 0 : ae_vector_destroy(&p->activerhs);
43239 0 : ae_vector_destroy(&p->activeidx);
43240 0 : }
43241 :
43242 :
43243 0 : void _minsqptmplagrangian_init(void* _p, ae_state *_state, ae_bool make_automatic)
43244 : {
43245 0 : minsqptmplagrangian *p = (minsqptmplagrangian*)_p;
43246 0 : ae_touch_ptr((void*)p);
43247 0 : ae_vector_init(&p->sclagtmp0, 0, DT_REAL, _state, make_automatic);
43248 0 : ae_vector_init(&p->sclagtmp1, 0, DT_REAL, _state, make_automatic);
43249 0 : }
43250 :
43251 :
43252 0 : void _minsqptmplagrangian_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
43253 : {
43254 0 : minsqptmplagrangian *dst = (minsqptmplagrangian*)_dst;
43255 0 : minsqptmplagrangian *src = (minsqptmplagrangian*)_src;
43256 0 : ae_vector_init_copy(&dst->sclagtmp0, &src->sclagtmp0, _state, make_automatic);
43257 0 : ae_vector_init_copy(&dst->sclagtmp1, &src->sclagtmp1, _state, make_automatic);
43258 0 : }
43259 :
43260 :
43261 0 : void _minsqptmplagrangian_clear(void* _p)
43262 : {
43263 0 : minsqptmplagrangian *p = (minsqptmplagrangian*)_p;
43264 0 : ae_touch_ptr((void*)p);
43265 0 : ae_vector_clear(&p->sclagtmp0);
43266 0 : ae_vector_clear(&p->sclagtmp1);
43267 0 : }
43268 :
43269 :
43270 0 : void _minsqptmplagrangian_destroy(void* _p)
43271 : {
43272 0 : minsqptmplagrangian *p = (minsqptmplagrangian*)_p;
43273 0 : ae_touch_ptr((void*)p);
43274 0 : ae_vector_destroy(&p->sclagtmp0);
43275 0 : ae_vector_destroy(&p->sclagtmp1);
43276 0 : }
43277 :
43278 :
43279 0 : void _minsqptmpmerit_init(void* _p, ae_state *_state, ae_bool make_automatic)
43280 : {
43281 0 : minsqptmpmerit *p = (minsqptmpmerit*)_p;
43282 0 : ae_touch_ptr((void*)p);
43283 0 : ae_vector_init(&p->mftmp0, 0, DT_REAL, _state, make_automatic);
43284 0 : }
43285 :
43286 :
43287 0 : void _minsqptmpmerit_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
43288 : {
43289 0 : minsqptmpmerit *dst = (minsqptmpmerit*)_dst;
43290 0 : minsqptmpmerit *src = (minsqptmpmerit*)_src;
43291 0 : ae_vector_init_copy(&dst->mftmp0, &src->mftmp0, _state, make_automatic);
43292 0 : }
43293 :
43294 :
43295 0 : void _minsqptmpmerit_clear(void* _p)
43296 : {
43297 0 : minsqptmpmerit *p = (minsqptmpmerit*)_p;
43298 0 : ae_touch_ptr((void*)p);
43299 0 : ae_vector_clear(&p->mftmp0);
43300 0 : }
43301 :
43302 :
43303 0 : void _minsqptmpmerit_destroy(void* _p)
43304 : {
43305 0 : minsqptmpmerit *p = (minsqptmpmerit*)_p;
43306 0 : ae_touch_ptr((void*)p);
43307 0 : ae_vector_destroy(&p->mftmp0);
43308 0 : }
43309 :
43310 :
43311 0 : void _minsqpmeritphasestate_init(void* _p, ae_state *_state, ae_bool make_automatic)
43312 : {
43313 0 : minsqpmeritphasestate *p = (minsqpmeritphasestate*)_p;
43314 0 : ae_touch_ptr((void*)p);
43315 0 : ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic);
43316 0 : ae_vector_init(&p->dx, 0, DT_REAL, _state, make_automatic);
43317 0 : ae_vector_init(&p->stepkx, 0, DT_REAL, _state, make_automatic);
43318 0 : ae_vector_init(&p->stepkxc, 0, DT_REAL, _state, make_automatic);
43319 0 : ae_vector_init(&p->stepkxn, 0, DT_REAL, _state, make_automatic);
43320 0 : ae_vector_init(&p->stepkfi, 0, DT_REAL, _state, make_automatic);
43321 0 : ae_vector_init(&p->stepkfic, 0, DT_REAL, _state, make_automatic);
43322 0 : ae_vector_init(&p->stepkfin, 0, DT_REAL, _state, make_automatic);
43323 0 : ae_matrix_init(&p->stepkj, 0, 0, DT_REAL, _state, make_automatic);
43324 0 : ae_matrix_init(&p->stepkjc, 0, 0, DT_REAL, _state, make_automatic);
43325 0 : ae_matrix_init(&p->stepkjn, 0, 0, DT_REAL, _state, make_automatic);
43326 0 : ae_vector_init(&p->lagmult, 0, DT_REAL, _state, make_automatic);
43327 0 : ae_vector_init(&p->dummylagmult, 0, DT_REAL, _state, make_automatic);
43328 0 : ae_vector_init(&p->penalties, 0, DT_REAL, _state, make_automatic);
43329 0 : _minsqptmpmerit_init(&p->tmpmerit, _state, make_automatic);
43330 0 : _minsqptmplagrangian_init(&p->tmplagrangianfg, _state, make_automatic);
43331 0 : ae_vector_init(&p->stepklaggrad, 0, DT_REAL, _state, make_automatic);
43332 0 : ae_vector_init(&p->stepknlaggrad, 0, DT_REAL, _state, make_automatic);
43333 0 : _rcommstate_init(&p->rmeritphasestate, _state, make_automatic);
43334 0 : }
43335 :
43336 :
43337 0 : void _minsqpmeritphasestate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
43338 : {
43339 0 : minsqpmeritphasestate *dst = (minsqpmeritphasestate*)_dst;
43340 0 : minsqpmeritphasestate *src = (minsqpmeritphasestate*)_src;
43341 0 : dst->n = src->n;
43342 0 : dst->nec = src->nec;
43343 0 : dst->nic = src->nic;
43344 0 : dst->nlec = src->nlec;
43345 0 : dst->nlic = src->nlic;
43346 0 : ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic);
43347 0 : ae_vector_init_copy(&dst->dx, &src->dx, _state, make_automatic);
43348 0 : ae_vector_init_copy(&dst->stepkx, &src->stepkx, _state, make_automatic);
43349 0 : ae_vector_init_copy(&dst->stepkxc, &src->stepkxc, _state, make_automatic);
43350 0 : ae_vector_init_copy(&dst->stepkxn, &src->stepkxn, _state, make_automatic);
43351 0 : ae_vector_init_copy(&dst->stepkfi, &src->stepkfi, _state, make_automatic);
43352 0 : ae_vector_init_copy(&dst->stepkfic, &src->stepkfic, _state, make_automatic);
43353 0 : ae_vector_init_copy(&dst->stepkfin, &src->stepkfin, _state, make_automatic);
43354 0 : ae_matrix_init_copy(&dst->stepkj, &src->stepkj, _state, make_automatic);
43355 0 : ae_matrix_init_copy(&dst->stepkjc, &src->stepkjc, _state, make_automatic);
43356 0 : ae_matrix_init_copy(&dst->stepkjn, &src->stepkjn, _state, make_automatic);
43357 0 : ae_vector_init_copy(&dst->lagmult, &src->lagmult, _state, make_automatic);
43358 0 : ae_vector_init_copy(&dst->dummylagmult, &src->dummylagmult, _state, make_automatic);
43359 0 : ae_vector_init_copy(&dst->penalties, &src->penalties, _state, make_automatic);
43360 0 : _minsqptmpmerit_init_copy(&dst->tmpmerit, &src->tmpmerit, _state, make_automatic);
43361 0 : _minsqptmplagrangian_init_copy(&dst->tmplagrangianfg, &src->tmplagrangianfg, _state, make_automatic);
43362 0 : ae_vector_init_copy(&dst->stepklaggrad, &src->stepklaggrad, _state, make_automatic);
43363 0 : ae_vector_init_copy(&dst->stepknlaggrad, &src->stepknlaggrad, _state, make_automatic);
43364 0 : dst->status = src->status;
43365 0 : dst->increasebigc = src->increasebigc;
43366 0 : _rcommstate_init_copy(&dst->rmeritphasestate, &src->rmeritphasestate, _state, make_automatic);
43367 0 : }
43368 :
43369 :
43370 0 : void _minsqpmeritphasestate_clear(void* _p)
43371 : {
43372 0 : minsqpmeritphasestate *p = (minsqpmeritphasestate*)_p;
43373 0 : ae_touch_ptr((void*)p);
43374 0 : ae_vector_clear(&p->d);
43375 0 : ae_vector_clear(&p->dx);
43376 0 : ae_vector_clear(&p->stepkx);
43377 0 : ae_vector_clear(&p->stepkxc);
43378 0 : ae_vector_clear(&p->stepkxn);
43379 0 : ae_vector_clear(&p->stepkfi);
43380 0 : ae_vector_clear(&p->stepkfic);
43381 0 : ae_vector_clear(&p->stepkfin);
43382 0 : ae_matrix_clear(&p->stepkj);
43383 0 : ae_matrix_clear(&p->stepkjc);
43384 0 : ae_matrix_clear(&p->stepkjn);
43385 0 : ae_vector_clear(&p->lagmult);
43386 0 : ae_vector_clear(&p->dummylagmult);
43387 0 : ae_vector_clear(&p->penalties);
43388 0 : _minsqptmpmerit_clear(&p->tmpmerit);
43389 0 : _minsqptmplagrangian_clear(&p->tmplagrangianfg);
43390 0 : ae_vector_clear(&p->stepklaggrad);
43391 0 : ae_vector_clear(&p->stepknlaggrad);
43392 0 : _rcommstate_clear(&p->rmeritphasestate);
43393 0 : }
43394 :
43395 :
43396 0 : void _minsqpmeritphasestate_destroy(void* _p)
43397 : {
43398 0 : minsqpmeritphasestate *p = (minsqpmeritphasestate*)_p;
43399 0 : ae_touch_ptr((void*)p);
43400 0 : ae_vector_destroy(&p->d);
43401 0 : ae_vector_destroy(&p->dx);
43402 0 : ae_vector_destroy(&p->stepkx);
43403 0 : ae_vector_destroy(&p->stepkxc);
43404 0 : ae_vector_destroy(&p->stepkxn);
43405 0 : ae_vector_destroy(&p->stepkfi);
43406 0 : ae_vector_destroy(&p->stepkfic);
43407 0 : ae_vector_destroy(&p->stepkfin);
43408 0 : ae_matrix_destroy(&p->stepkj);
43409 0 : ae_matrix_destroy(&p->stepkjc);
43410 0 : ae_matrix_destroy(&p->stepkjn);
43411 0 : ae_vector_destroy(&p->lagmult);
43412 0 : ae_vector_destroy(&p->dummylagmult);
43413 0 : ae_vector_destroy(&p->penalties);
43414 0 : _minsqptmpmerit_destroy(&p->tmpmerit);
43415 0 : _minsqptmplagrangian_destroy(&p->tmplagrangianfg);
43416 0 : ae_vector_destroy(&p->stepklaggrad);
43417 0 : ae_vector_destroy(&p->stepknlaggrad);
43418 0 : _rcommstate_destroy(&p->rmeritphasestate);
43419 0 : }
43420 :
43421 :
43422 0 : void _minsqpstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
43423 : {
43424 0 : minsqpstate *p = (minsqpstate*)_p;
43425 0 : ae_touch_ptr((void*)p);
43426 0 : ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic);
43427 0 : ae_matrix_init(&p->scaledcleic, 0, 0, DT_REAL, _state, make_automatic);
43428 0 : ae_vector_init(&p->lcsrcidx, 0, DT_INT, _state, make_automatic);
43429 0 : ae_vector_init(&p->hasbndl, 0, DT_BOOL, _state, make_automatic);
43430 0 : ae_vector_init(&p->hasbndu, 0, DT_BOOL, _state, make_automatic);
43431 0 : ae_vector_init(&p->scaledbndl, 0, DT_REAL, _state, make_automatic);
43432 0 : ae_vector_init(&p->scaledbndu, 0, DT_REAL, _state, make_automatic);
43433 0 : ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
43434 0 : ae_vector_init(&p->fi, 0, DT_REAL, _state, make_automatic);
43435 0 : ae_matrix_init(&p->j, 0, 0, DT_REAL, _state, make_automatic);
43436 0 : _minsqpmeritphasestate_init(&p->meritstate, _state, make_automatic);
43437 0 : ae_vector_init(&p->step0x, 0, DT_REAL, _state, make_automatic);
43438 0 : ae_vector_init(&p->stepkx, 0, DT_REAL, _state, make_automatic);
43439 0 : ae_vector_init(&p->backupx, 0, DT_REAL, _state, make_automatic);
43440 0 : ae_vector_init(&p->step0fi, 0, DT_REAL, _state, make_automatic);
43441 0 : ae_vector_init(&p->stepkfi, 0, DT_REAL, _state, make_automatic);
43442 0 : ae_vector_init(&p->backupfi, 0, DT_REAL, _state, make_automatic);
43443 0 : ae_matrix_init(&p->step0j, 0, 0, DT_REAL, _state, make_automatic);
43444 0 : ae_matrix_init(&p->stepkj, 0, 0, DT_REAL, _state, make_automatic);
43445 0 : ae_vector_init(&p->meritlagmult, 0, DT_REAL, _state, make_automatic);
43446 0 : ae_vector_init(&p->dummylagmult, 0, DT_REAL, _state, make_automatic);
43447 0 : ae_matrix_init(&p->abslagmemory, 0, 0, DT_REAL, _state, make_automatic);
43448 0 : ae_vector_init(&p->fscales, 0, DT_REAL, _state, make_automatic);
43449 0 : ae_vector_init(&p->tracegamma, 0, DT_REAL, _state, make_automatic);
43450 0 : _minsqpsubsolver_init(&p->subsolver, _state, make_automatic);
43451 0 : _minsqptmpmerit_init(&p->tmpmerit, _state, make_automatic);
43452 0 : _rcommstate_init(&p->rstate, _state, make_automatic);
43453 0 : }
43454 :
43455 :
43456 0 : void _minsqpstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
43457 : {
43458 0 : minsqpstate *dst = (minsqpstate*)_dst;
43459 0 : minsqpstate *src = (minsqpstate*)_src;
43460 0 : dst->n = src->n;
43461 0 : dst->nec = src->nec;
43462 0 : dst->nic = src->nic;
43463 0 : dst->nlec = src->nlec;
43464 0 : dst->nlic = src->nlic;
43465 0 : ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic);
43466 0 : ae_matrix_init_copy(&dst->scaledcleic, &src->scaledcleic, _state, make_automatic);
43467 0 : ae_vector_init_copy(&dst->lcsrcidx, &src->lcsrcidx, _state, make_automatic);
43468 0 : ae_vector_init_copy(&dst->hasbndl, &src->hasbndl, _state, make_automatic);
43469 0 : ae_vector_init_copy(&dst->hasbndu, &src->hasbndu, _state, make_automatic);
43470 0 : ae_vector_init_copy(&dst->scaledbndl, &src->scaledbndl, _state, make_automatic);
43471 0 : ae_vector_init_copy(&dst->scaledbndu, &src->scaledbndu, _state, make_automatic);
43472 0 : dst->epsx = src->epsx;
43473 0 : dst->maxits = src->maxits;
43474 0 : ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
43475 0 : ae_vector_init_copy(&dst->fi, &src->fi, _state, make_automatic);
43476 0 : ae_matrix_init_copy(&dst->j, &src->j, _state, make_automatic);
43477 0 : dst->f = src->f;
43478 0 : dst->needfij = src->needfij;
43479 0 : dst->xupdated = src->xupdated;
43480 0 : _minsqpmeritphasestate_init_copy(&dst->meritstate, &src->meritstate, _state, make_automatic);
43481 0 : dst->bigc = src->bigc;
43482 0 : dst->trustrad = src->trustrad;
43483 0 : dst->trustradstagnationcnt = src->trustradstagnationcnt;
43484 0 : dst->fstagnationcnt = src->fstagnationcnt;
43485 0 : ae_vector_init_copy(&dst->step0x, &src->step0x, _state, make_automatic);
43486 0 : ae_vector_init_copy(&dst->stepkx, &src->stepkx, _state, make_automatic);
43487 0 : ae_vector_init_copy(&dst->backupx, &src->backupx, _state, make_automatic);
43488 0 : ae_vector_init_copy(&dst->step0fi, &src->step0fi, _state, make_automatic);
43489 0 : ae_vector_init_copy(&dst->stepkfi, &src->stepkfi, _state, make_automatic);
43490 0 : ae_vector_init_copy(&dst->backupfi, &src->backupfi, _state, make_automatic);
43491 0 : ae_matrix_init_copy(&dst->step0j, &src->step0j, _state, make_automatic);
43492 0 : ae_matrix_init_copy(&dst->stepkj, &src->stepkj, _state, make_automatic);
43493 0 : dst->haslagmult = src->haslagmult;
43494 0 : ae_vector_init_copy(&dst->meritlagmult, &src->meritlagmult, _state, make_automatic);
43495 0 : ae_vector_init_copy(&dst->dummylagmult, &src->dummylagmult, _state, make_automatic);
43496 0 : ae_matrix_init_copy(&dst->abslagmemory, &src->abslagmemory, _state, make_automatic);
43497 0 : ae_vector_init_copy(&dst->fscales, &src->fscales, _state, make_automatic);
43498 0 : ae_vector_init_copy(&dst->tracegamma, &src->tracegamma, _state, make_automatic);
43499 0 : _minsqpsubsolver_init_copy(&dst->subsolver, &src->subsolver, _state, make_automatic);
43500 0 : _minsqptmpmerit_init_copy(&dst->tmpmerit, &src->tmpmerit, _state, make_automatic);
43501 0 : dst->repsimplexiterations = src->repsimplexiterations;
43502 0 : dst->repsimplexiterations1 = src->repsimplexiterations1;
43503 0 : dst->repsimplexiterations2 = src->repsimplexiterations2;
43504 0 : dst->repsimplexiterations3 = src->repsimplexiterations3;
43505 0 : dst->repiterationscount = src->repiterationscount;
43506 0 : dst->repterminationtype = src->repterminationtype;
43507 0 : dst->repbcerr = src->repbcerr;
43508 0 : dst->repbcidx = src->repbcidx;
43509 0 : dst->replcerr = src->replcerr;
43510 0 : dst->replcidx = src->replcidx;
43511 0 : dst->repnlcerr = src->repnlcerr;
43512 0 : dst->repnlcidx = src->repnlcidx;
43513 0 : _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic);
43514 0 : }
43515 :
43516 :
43517 0 : void _minsqpstate_clear(void* _p)
43518 : {
43519 0 : minsqpstate *p = (minsqpstate*)_p;
43520 0 : ae_touch_ptr((void*)p);
43521 0 : ae_vector_clear(&p->s);
43522 0 : ae_matrix_clear(&p->scaledcleic);
43523 0 : ae_vector_clear(&p->lcsrcidx);
43524 0 : ae_vector_clear(&p->hasbndl);
43525 0 : ae_vector_clear(&p->hasbndu);
43526 0 : ae_vector_clear(&p->scaledbndl);
43527 0 : ae_vector_clear(&p->scaledbndu);
43528 0 : ae_vector_clear(&p->x);
43529 0 : ae_vector_clear(&p->fi);
43530 0 : ae_matrix_clear(&p->j);
43531 0 : _minsqpmeritphasestate_clear(&p->meritstate);
43532 0 : ae_vector_clear(&p->step0x);
43533 0 : ae_vector_clear(&p->stepkx);
43534 0 : ae_vector_clear(&p->backupx);
43535 0 : ae_vector_clear(&p->step0fi);
43536 0 : ae_vector_clear(&p->stepkfi);
43537 0 : ae_vector_clear(&p->backupfi);
43538 0 : ae_matrix_clear(&p->step0j);
43539 0 : ae_matrix_clear(&p->stepkj);
43540 0 : ae_vector_clear(&p->meritlagmult);
43541 0 : ae_vector_clear(&p->dummylagmult);
43542 0 : ae_matrix_clear(&p->abslagmemory);
43543 0 : ae_vector_clear(&p->fscales);
43544 0 : ae_vector_clear(&p->tracegamma);
43545 0 : _minsqpsubsolver_clear(&p->subsolver);
43546 0 : _minsqptmpmerit_clear(&p->tmpmerit);
43547 0 : _rcommstate_clear(&p->rstate);
43548 0 : }
43549 :
43550 :
43551 0 : void _minsqpstate_destroy(void* _p)
43552 : {
43553 0 : minsqpstate *p = (minsqpstate*)_p;
43554 0 : ae_touch_ptr((void*)p);
43555 0 : ae_vector_destroy(&p->s);
43556 0 : ae_matrix_destroy(&p->scaledcleic);
43557 0 : ae_vector_destroy(&p->lcsrcidx);
43558 0 : ae_vector_destroy(&p->hasbndl);
43559 0 : ae_vector_destroy(&p->hasbndu);
43560 0 : ae_vector_destroy(&p->scaledbndl);
43561 0 : ae_vector_destroy(&p->scaledbndu);
43562 0 : ae_vector_destroy(&p->x);
43563 0 : ae_vector_destroy(&p->fi);
43564 0 : ae_matrix_destroy(&p->j);
43565 0 : _minsqpmeritphasestate_destroy(&p->meritstate);
43566 0 : ae_vector_destroy(&p->step0x);
43567 0 : ae_vector_destroy(&p->stepkx);
43568 0 : ae_vector_destroy(&p->backupx);
43569 0 : ae_vector_destroy(&p->step0fi);
43570 0 : ae_vector_destroy(&p->stepkfi);
43571 0 : ae_vector_destroy(&p->backupfi);
43572 0 : ae_matrix_destroy(&p->step0j);
43573 0 : ae_matrix_destroy(&p->stepkj);
43574 0 : ae_vector_destroy(&p->meritlagmult);
43575 0 : ae_vector_destroy(&p->dummylagmult);
43576 0 : ae_matrix_destroy(&p->abslagmemory);
43577 0 : ae_vector_destroy(&p->fscales);
43578 0 : ae_vector_destroy(&p->tracegamma);
43579 0 : _minsqpsubsolver_destroy(&p->subsolver);
43580 0 : _minsqptmpmerit_destroy(&p->tmpmerit);
43581 0 : _rcommstate_destroy(&p->rstate);
43582 0 : }
43583 :
43584 :
43585 : #endif
43586 : #if defined(AE_COMPILE_QPDENSEAULSOLVER) || !defined(AE_PARTIAL_BUILD)
43587 :
43588 :
43589 : /*************************************************************************
43590 : This function initializes QPDENSEAULSettings structure with default settings.
43591 :
43592 : Newly created structure MUST be initialized by default settings - or by
43593 : copy of the already initialized structure.
43594 :
43595 : -- ALGLIB --
43596 : Copyright 14.05.2011 by Bochkanov Sergey
43597 : *************************************************************************/
43598 0 : void qpdenseaulloaddefaults(ae_int_t nmain,
43599 : qpdenseaulsettings* s,
43600 : ae_state *_state)
43601 : {
43602 :
43603 :
43604 0 : s->epsx = 1.0E-6;
43605 0 : s->outerits = 5;
43606 0 : s->rho = 100.0;
43607 0 : }
43608 :
43609 :
43610 : /*************************************************************************
43611 : This function runs Dense-AUL solver; it returns after optimization process
43612 : was completed. Following QP problem is solved:
43613 :
43614 : min(0.5*(x-x_origin)'*A*(x-x_origin)+b'*(x-x_origin))
43615 :
43616 : subject to combination of box and general linear dense/sparse constraints.
43617 :
43618 : INPUT PARAMETERS:
43619 : DenseA - for dense problems (AKind=0), A-term of CQM object
43620 : contains system matrix. Other terms are unspecified
43621 : and should not be referenced.
43622 : SparseA - for sparse problems (AKind=1), CRS format
43623 : AKind - sparse matrix format:
43624 : * 0 for dense matrix
43625 : * 1 for sparse matrix
43626 : SparseUpper - which triangle of SparseAC stores matrix - upper or
43627 : lower one (for dense matrices this parameter is not
43628 : actual).
43629 : B - linear term, array[N]
43630 : BndL - lower bound, array[N]
43631 : BndU - upper bound, array[N]
43632 : S - scale vector, array[NC]:
43633 : * I-th element contains scale of I-th variable,
43634 : * SC[I]>0
43635 : XOrigin - origin term, array[NC]. Can be zero.
43636 : N - number of variables in the original formulation (no
43637 : slack variables).
43638 : CLEIC - dense linear equality/inequality constraints. Equality
43639 : constraints come first.
43640 : NEC, NIC - number of dense equality/inequality constraints.
43641 : SCLEIC - sparse linear equality/inequality constraints. Equality
43642 : constraints come first.
43643 : SNEC, SNIC - number of sparse equality/inequality constraints.
43644 : RenormLC - whether constraints should be renormalized (recommended)
43645 : or used "as is".
43646 : Settings - QPDENSEAULSettings object initialized by one of the initialization
43647 : functions.
43648 : State - object which stores temporaries
43649 : XS - initial point, array[NC]
43650 :
43651 :
43652 : OUTPUT PARAMETERS:
43653 : XS - last point
43654 : TerminationType-termination type:
43655 : *
43656 : *
43657 : *
43658 :
43659 : -- ALGLIB --
43660 : Copyright 2017 by Bochkanov Sergey
43661 : *************************************************************************/
43662 0 : void qpdenseauloptimize(convexquadraticmodel* a,
43663 : sparsematrix* sparsea,
43664 : ae_int_t akind,
43665 : ae_bool sparseaupper,
43666 : /* Real */ ae_vector* b,
43667 : /* Real */ ae_vector* bndl,
43668 : /* Real */ ae_vector* bndu,
43669 : /* Real */ ae_vector* s,
43670 : /* Real */ ae_vector* xorigin,
43671 : ae_int_t nn,
43672 : /* Real */ ae_matrix* cleic,
43673 : ae_int_t dnec,
43674 : ae_int_t dnic,
43675 : sparsematrix* scleic,
43676 : ae_int_t snec,
43677 : ae_int_t snic,
43678 : ae_bool renormlc,
43679 : qpdenseaulsettings* settings,
43680 : qpdenseaulbuffers* state,
43681 : /* Real */ ae_vector* xs,
43682 : /* Real */ ae_vector* lagbc,
43683 : /* Real */ ae_vector* laglc,
43684 : ae_int_t* terminationtype,
43685 : ae_state *_state)
43686 : {
43687 : ae_int_t i;
43688 : ae_int_t j;
43689 : ae_int_t k;
43690 : double v;
43691 : double vv;
43692 : double rho;
43693 : double epsx;
43694 : ae_int_t outeridx;
43695 : ae_int_t nmain;
43696 : ae_int_t nslack;
43697 : ae_int_t ntotal;
43698 : ae_int_t ktotal;
43699 : double maxrho;
43700 : double feaserr;
43701 : double feaserrprev;
43702 : double requestedfeasdecrease;
43703 : ae_int_t goodcounter;
43704 : ae_int_t stagnationcounter;
43705 : ae_int_t nectotal;
43706 : ae_int_t nictotal;
43707 : ae_int_t nicwork;
43708 : ae_int_t kwork;
43709 : ae_int_t nwork;
43710 : ae_bool allowwseviction;
43711 : ae_bool workingsetextended;
43712 : double targetscale;
43713 :
43714 0 : *terminationtype = 0;
43715 :
43716 0 : nmain = nn;
43717 0 : nslack = dnic+snic;
43718 0 : ntotal = nmain+nslack;
43719 0 : nectotal = dnec+snec;
43720 0 : nictotal = dnic+snic;
43721 0 : ktotal = dnec+dnic+snec+snic;
43722 0 : rho = settings->rho;
43723 0 : epsx = settings->epsx;
43724 0 : requestedfeasdecrease = 0.33;
43725 0 : maxrho = 1.0E12;
43726 0 : if( ae_fp_less_eq(epsx,(double)(0)) )
43727 : {
43728 0 : epsx = 1.0E-9;
43729 : }
43730 :
43731 : /*
43732 : * Integrity checks
43733 : */
43734 0 : if( snec+snic>0 )
43735 : {
43736 0 : ae_assert(scleic->matrixtype==1, "QPDENSEAULOptimize: unexpected sparse matrix format", _state);
43737 0 : ae_assert(scleic->m==snec+snic, "QPDENSEAULOptimize: unexpected sparse matrix size", _state);
43738 0 : ae_assert(scleic->n==nmain+1, "QPDENSEAULOptimize: unexpected sparse matrix size", _state);
43739 : }
43740 :
43741 : /*
43742 : * Prepare
43743 : */
43744 0 : state->repinneriterationscount = 0;
43745 0 : state->repouteriterationscount = 0;
43746 0 : state->repncholesky = 0;
43747 0 : state->repnmv = 0;
43748 0 : state->repnwrkchanges = 0;
43749 0 : state->repnwrk0 = 0;
43750 0 : state->repnwrk1 = 0;
43751 0 : state->repnwrkf = 0;
43752 0 : *terminationtype = 0;
43753 0 : ivectorsetlengthatleast(&state->cidx, ktotal, _state);
43754 0 : rvectorsetlengthatleast(&state->nulc, ktotal, _state);
43755 0 : rvectorsetlengthatleast(&state->nulcest, ktotal, _state);
43756 0 : rvectorsetlengthatleast(&state->exb, ntotal, _state);
43757 0 : rvectorsetlengthatleast(&state->exxc, ntotal, _state);
43758 0 : rvectorsetlengthatleast(&state->exxorigin, ntotal, _state);
43759 0 : rvectorsetlengthatleast(&state->exbndl, ntotal, _state);
43760 0 : rvectorsetlengthatleast(&state->exbndu, ntotal, _state);
43761 0 : rvectorsetlengthatleast(&state->exscale, ntotal, _state);
43762 0 : rvectorsetlengthatleast(&state->tmp0, ntotal, _state);
43763 0 : rvectorsetlengthatleast(&state->nicerr, nictotal, _state);
43764 0 : ivectorsetlengthatleast(&state->nicnact, nictotal, _state);
43765 :
43766 : /*
43767 : * Allocate Lagrange multipliers, fill by default values (zeros)
43768 : */
43769 0 : rvectorsetlengthatleast(lagbc, nmain, _state);
43770 0 : rvectorsetlengthatleast(laglc, ktotal, _state);
43771 0 : for(i=0; i<=nmain-1; i++)
43772 : {
43773 0 : lagbc->ptr.p_double[i] = 0.0;
43774 : }
43775 0 : for(i=0; i<=ktotal-1; i++)
43776 : {
43777 0 : laglc->ptr.p_double[i] = 0.0;
43778 : }
43779 :
43780 : /*
43781 : * Prepare scaled/shifted model in dense format - input parameters
43782 : * are converted and stored in State.SclSftA/B/HasBndL/HasBndU/BndL/BndU/CLEIC/XC/CScales
43783 : */
43784 0 : qpdenseaulsolver_scaleshiftoriginalproblem(a, sparsea, akind, sparseaupper, b, bndl, bndu, s, xorigin, nmain, cleic, dnec, dnic, scleic, snec, snic, renormlc, state, xs, _state);
43785 :
43786 : /*
43787 : * Normalize model in such way that norm(A)~1 (very roughly)
43788 : *
43789 : * We have two lower bounds for sigma_max(A):
43790 : * * first estimate is provided by Frobenius norm, it is equal to ANorm/NMain
43791 : * * second estimate is provided by max(CAC)
43792 : *
43793 : * We select largest one of these estimates, because using just one
43794 : * of them is prone to different failure modes. Then, we divide A and B
43795 : * by this estimate.
43796 : */
43797 0 : targetscale = qpdenseaulsolver_normalizequadraticterm(&state->sclsfta, &state->sclsftb, nmain, &state->sclsftcleic, nectotal, nictotal, renormlc, &state->tmp2, _state);
43798 :
43799 : /*
43800 : * Select working set of inequality constraints.
43801 : *
43802 : * Although it is possible to process all inequality constraints
43803 : * at once, in one large batch, some QP problems have NIC>>N constraints,
43804 : * but only minor fraction of them is inactive in the solution.
43805 : *
43806 : * Because algorithm running time is O((N+NEC+NIC)^3), we can
43807 : * save a lot of time if we process only those inequality constraints
43808 : * which need activation. Generally, NEC<N, and only O(N) inequality
43809 : * constraints are active in the solution.
43810 : *
43811 : * We can do so by solving problem first without general inequality
43812 : * constraints at all (box and general equality constraints are added),
43813 : * and by iteratively adding more and more inequality constraints in
43814 : * order to get feasible solution. Such set of inequality constraints
43815 : * is called "working set".
43816 : *
43817 : * NOTE: such approach works reliably only for convex QP problems; non-convex
43818 : * QP problem can be unbounded when some constraints are dropped.
43819 : *
43820 : * NOTE: we can also remove some constraints from working set, but eviction
43821 : * can be performed only limited amount of times (at most once); if
43822 : * constraint is added to working set second time, it is never removed.
43823 : *
43824 : * NOTE: we do not perform constraint eviction on non-convex problems
43825 : */
43826 0 : qpdenseaulsolver_selectinitialworkingset(&state->sclsfta, nmain, &state->sclsftcleic, nectotal, nictotal, &state->tmp0, &state->tmp2, &nicwork, &allowwseviction, _state);
43827 0 : kwork = nectotal+nicwork;
43828 0 : nwork = nmain+nicwork;
43829 0 : state->repnwrk0 = nicwork;
43830 0 : for(i=0; i<=nicwork-1; i++)
43831 : {
43832 0 : state->nicnact.ptr.p_int[i] = 1;
43833 : }
43834 0 : for(i=nicwork; i<=nictotal-1; i++)
43835 : {
43836 0 : state->nicnact.ptr.p_int[i] = 0;
43837 : }
43838 0 : for(i=0; i<=ktotal-1; i++)
43839 : {
43840 0 : state->cidx.ptr.p_int[i] = i;
43841 : }
43842 :
43843 : /*
43844 : * Perform outer iteration
43845 : */
43846 0 : for(i=0; i<=ktotal-1; i++)
43847 : {
43848 0 : state->nulc.ptr.p_double[i] = (double)(0);
43849 : }
43850 0 : for(i=0; i<=ntotal-1; i++)
43851 : {
43852 0 : state->exscale.ptr.p_double[i] = 1.0;
43853 0 : state->exxorigin.ptr.p_double[i] = 0.0;
43854 : }
43855 0 : qpdenseaulsolver_generateexinitialpoint(&state->sclsftxc, nmain, nslack, &state->exxc, _state);
43856 0 : goodcounter = 0;
43857 0 : stagnationcounter = 0;
43858 0 : feaserr = ae_maxrealnumber;
43859 0 : for(outeridx=0; outeridx<=settings->outerits-1; outeridx++)
43860 : {
43861 :
43862 : /*
43863 : * Repeat loop until working set stabilizes.
43864 : */
43865 0 : do
43866 : {
43867 :
43868 : /*
43869 : * Preallocate space for ExA and for QQP solver; we do not allocate
43870 : * array[NTotal,NTotal] from the start because NTotal can be much
43871 : * larger than NMain for problems with large amount of inequality
43872 : * constraints, and we usually need NWork=O(NMain).
43873 : *
43874 : * NOTE: for the sake of simplicity, 1-dimensional arrays were
43875 : * preallocated to the maximum size required (NTotal).
43876 : */
43877 0 : if( state->exa.rows<nwork||state->exa.cols<nwork )
43878 : {
43879 0 : i = nwork+nwork/3+1;
43880 0 : rmatrixsetlengthatleast(&state->exa, i, i, _state);
43881 : }
43882 0 : qqppreallocategrowdense(&state->qqpbuf, nwork, i, _state);
43883 :
43884 : /*
43885 : * Generate penalized quadratic model
43886 : */
43887 0 : qpdenseaulsolver_generateexmodel(&state->sclsfta, &state->sclsftb, nmain, &state->sclsftbndl, &state->sclsfthasbndl, &state->sclsftbndu, &state->sclsfthasbndu, &state->sclsftcleic, nectotal, nicwork, &state->nulc, rho, &state->exa, &state->exb, &state->exbndl, &state->exbndu, &state->tmp2, _state);
43888 :
43889 : /*
43890 : * Solve extended QP problem subject to current working set of general
43891 : * inequality constraints.
43892 : */
43893 0 : qqploaddefaults(nwork, &state->qqpsettingsuser, _state);
43894 0 : state->qqpsettingsuser.maxouterits = 50;
43895 0 : state->qqpsettingsuser.epsg = 0.0;
43896 0 : state->qqpsettingsuser.epsf = 0.0;
43897 0 : state->qqpsettingsuser.epsx = 0.01*epsx;
43898 0 : state->qqpsettingsuser.cnphase = ae_true;
43899 0 : qqpoptimize(&state->dummycqm, &state->dummysparse, &state->exa, 2, ae_true, &state->exb, &state->exbndl, &state->exbndu, &state->exscale, &state->exxorigin, nwork, &state->qqpsettingsuser, &state->qqpbuf, &state->exxc, &k, _state);
43900 0 : state->repncholesky = state->repncholesky+state->qqpbuf.repncholesky;
43901 :
43902 : /*
43903 : * Evaluate violation of constraints
43904 : */
43905 0 : for(i=0; i<=nictotal-1; i++)
43906 : {
43907 0 : v = ae_v_dotproduct(&state->sclsftcleic.ptr.pp_double[nectotal+i][0], 1, &state->exxc.ptr.p_double[0], 1, ae_v_len(0,nmain-1));
43908 0 : v = v-state->sclsftcleic.ptr.pp_double[nectotal+i][nmain];
43909 0 : state->nicerr.ptr.p_double[i] = v;
43910 : }
43911 :
43912 : /*
43913 : * Working set expansion:
43914 : * * select limited amount of most violated constraints
43915 : * * perform permutation of non-work constraints such that
43916 : * candidate constraint is first the list (update XC and NuLC)
43917 : * * increase working set size by 1
43918 : * * increase activation count for new constraint by 1 (this count
43919 : * is used later by working set eviction phase)
43920 : * * repeat
43921 : *
43922 : * NOTE: we use selection sort algorithm because its O(NAdded*NWork) cost
43923 : * is still comparable to the cost of constraints evaluation
43924 : */
43925 0 : workingsetextended = ae_false;
43926 0 : i = 0;
43927 0 : while(ae_fp_less((double)(i),1+qpdenseaulsolver_expansionratio*nmain)&&nicwork<nictotal)
43928 : {
43929 :
43930 : /*
43931 : * Select most violated constraint
43932 : */
43933 0 : k = nicwork;
43934 0 : for(j=nicwork; j<=nictotal-1; j++)
43935 : {
43936 0 : if( ae_fp_greater(state->nicerr.ptr.p_double[j],state->nicerr.ptr.p_double[k]) )
43937 : {
43938 0 : k = j;
43939 : }
43940 : }
43941 :
43942 : /*
43943 : * If violation is positive, add it
43944 : */
43945 0 : if( ae_fp_greater(state->nicerr.ptr.p_double[k],(double)(0)) )
43946 : {
43947 0 : swaprows(&state->sclsftcleic, nectotal+nicwork, nectotal+k, -1, _state);
43948 0 : swapelements(&state->nicerr, nicwork, k, _state);
43949 0 : swapelementsi(&state->nicnact, nicwork, k, _state);
43950 0 : swapelementsi(&state->cidx, nectotal+nicwork, nectotal+k, _state);
43951 0 : swapelements(&state->cscales, nectotal+nicwork, nectotal+k, _state);
43952 0 : state->exxc.ptr.p_double[nmain+nicwork] = 0.0;
43953 0 : state->nulc.ptr.p_double[nectotal+nicwork] = 0.0;
43954 0 : state->nicnact.ptr.p_int[nicwork] = state->nicnact.ptr.p_int[nicwork]+1;
43955 0 : inc(&nicwork, _state);
43956 0 : inc(&nwork, _state);
43957 0 : inc(&kwork, _state);
43958 0 : inc(&i, _state);
43959 0 : workingsetextended = ae_true;
43960 : }
43961 : else
43962 : {
43963 0 : break;
43964 : }
43965 : }
43966 :
43967 : /*
43968 : * Working set eviction:
43969 : * * select constraints which are (1) far away from the
43970 : * boundary, AND (2) has less than two activation attempts
43971 : * (if constraint is regularly activated/deactivated, we keep
43972 : * it in the working set no matter what)
43973 : * * remove such constraints from the working set one by one
43974 : */
43975 0 : if( allowwseviction )
43976 : {
43977 0 : for(k=nicwork-1; k>=0; k--)
43978 : {
43979 0 : if( ae_fp_less(state->nicerr.ptr.p_double[k],qpdenseaulsolver_evictionlevel)&&state->nicnact.ptr.p_int[k]<=1 )
43980 : {
43981 0 : swaprows(&state->sclsftcleic, nectotal+nicwork-1, nectotal+k, -1, _state);
43982 0 : swapelementsi(&state->cidx, nectotal+nicwork-1, nectotal+k, _state);
43983 0 : swapelements(&state->cscales, nectotal+nicwork-1, nectotal+k, _state);
43984 0 : swapelements(&state->nicerr, nicwork-1, k, _state);
43985 0 : swapelementsi(&state->nicnact, nicwork-1, k, _state);
43986 0 : swapelements(&state->exxc, nmain+nicwork-1, nmain+k, _state);
43987 0 : swapelements(&state->nulc, nectotal+nicwork-1, nectotal+k, _state);
43988 0 : dec(&nicwork, _state);
43989 0 : dec(&nwork, _state);
43990 0 : dec(&kwork, _state);
43991 : }
43992 : }
43993 : }
43994 :
43995 : /*
43996 : * Report working set statistics
43997 : */
43998 0 : if( state->repnwrk1==0 )
43999 : {
44000 0 : state->repnwrk1 = nicwork;
44001 : }
44002 0 : state->repnwrkf = nicwork;
44003 0 : if( workingsetextended )
44004 : {
44005 0 : inc(&state->repnwrkchanges, _state);
44006 : }
44007 : }
44008 : while(workingsetextended);
44009 :
44010 : /*
44011 : * Estimate Lagrange multipliers using alternative algorithm
44012 : */
44013 0 : ae_v_move(&state->nulcest.ptr.p_double[0], 1, &state->nulc.ptr.p_double[0], 1, ae_v_len(0,kwork-1));
44014 0 : qpdenseaulsolver_updatelagrangemultipliers(&state->sclsfta, &state->sclsftb, nmain, &state->sclsftbndl, &state->sclsfthasbndl, &state->sclsftbndu, &state->sclsfthasbndu, &state->sclsftcleic, nectotal, nicwork, &state->exxc, &state->nulcest, state, _state);
44015 :
44016 : /*
44017 : * Update XC and Lagrange multipliers
44018 : */
44019 0 : feaserrprev = feaserr;
44020 0 : feaserr = (double)(0);
44021 0 : for(i=0; i<=kwork-1; i++)
44022 : {
44023 :
44024 : /*
44025 : * Calculate I-th feasibility error in V using formula for distance
44026 : * between point and line (here we calculate actual distance between
44027 : * XN and hyperplane Ci'*XN=Bi, which is different from error Ci'*XN-Bi).
44028 : */
44029 0 : v = (double)(0);
44030 0 : vv = (double)(0);
44031 0 : for(j=0; j<=nmain-1; j++)
44032 : {
44033 0 : v = v+state->sclsftcleic.ptr.pp_double[i][j]*state->exxc.ptr.p_double[j];
44034 0 : vv = vv+ae_sqr(state->sclsftcleic.ptr.pp_double[i][j], _state);
44035 : }
44036 0 : if( i>=nectotal )
44037 : {
44038 0 : v = v+state->exxc.ptr.p_double[nmain+(i-nectotal)];
44039 0 : vv = vv+ae_sqr((double)(1), _state);
44040 : }
44041 0 : v = v-state->sclsftcleic.ptr.pp_double[i][nmain];
44042 0 : vv = coalesce(vv, (double)(1), _state);
44043 0 : v = v/ae_sqrt(vv, _state);
44044 :
44045 : /*
44046 : * Calculate magnitude of Lagrangian update (and Lagrangian parameters themselves)
44047 : */
44048 0 : feaserr = feaserr+ae_sqr(v, _state);
44049 0 : state->nulc.ptr.p_double[i] = state->nulcest.ptr.p_double[i];
44050 : }
44051 0 : feaserr = ae_sqrt(feaserr, _state);
44052 0 : if( ae_fp_less(feaserr,epsx) )
44053 : {
44054 0 : inc(&goodcounter, _state);
44055 : }
44056 : else
44057 : {
44058 0 : goodcounter = 0;
44059 : }
44060 0 : if( ae_fp_greater(feaserr,feaserrprev*requestedfeasdecrease) )
44061 : {
44062 0 : inc(&stagnationcounter, _state);
44063 : }
44064 : else
44065 : {
44066 0 : stagnationcounter = 0;
44067 : }
44068 0 : if( goodcounter>=2 )
44069 : {
44070 0 : break;
44071 : }
44072 0 : if( stagnationcounter>=2 )
44073 : {
44074 0 : rho = ae_minreal(rho*10.0, maxrho, _state);
44075 : }
44076 : else
44077 : {
44078 0 : rho = ae_minreal(rho*1.41, maxrho, _state);
44079 : }
44080 : }
44081 :
44082 : /*
44083 : * Convert Lagrange multipliers from internal format to one expected
44084 : * by caller:
44085 : * * reorder multipliers for linear constraints
44086 : * * compute residual from gradient+linearconstraints
44087 : * * compute multipliers for box constraints from residual
44088 : * * rescale everything
44089 : */
44090 0 : for(i=0; i<=nectotal+nicwork-1; i++)
44091 : {
44092 0 : laglc->ptr.p_double[state->cidx.ptr.p_int[i]] = -state->nulc.ptr.p_double[i]*targetscale/state->cscales.ptr.p_double[i];
44093 : }
44094 0 : rvectorsetlengthatleast(&state->tmpg, nmain, _state);
44095 0 : for(i=0; i<=nmain-1; i++)
44096 : {
44097 0 : v = state->sclsftb.ptr.p_double[i];
44098 0 : for(j=0; j<=nmain-1; j++)
44099 : {
44100 0 : v = v+state->sclsfta.ptr.pp_double[i][j]*state->exxc.ptr.p_double[j];
44101 : }
44102 0 : state->tmpg.ptr.p_double[i] = v;
44103 : }
44104 0 : rmatrixgemv(nmain, nectotal+nicwork, -1.0, &state->sclsftcleic, 0, 0, 1, &state->nulc, 0, 1.0, &state->tmpg, 0, _state);
44105 0 : for(i=0; i<=nmain-1; i++)
44106 : {
44107 0 : if( (state->sclsfthasbndl.ptr.p_bool[i]&&ae_fp_eq(state->exxc.ptr.p_double[i],state->sclsftbndl.ptr.p_double[i]))||(state->sclsfthasbndu.ptr.p_bool[i]&&ae_fp_eq(state->exxc.ptr.p_double[i],state->sclsftbndu.ptr.p_double[i])) )
44108 : {
44109 0 : lagbc->ptr.p_double[i] = -state->tmpg.ptr.p_double[i];
44110 : }
44111 : }
44112 0 : for(i=0; i<=nmain-1; i++)
44113 : {
44114 0 : lagbc->ptr.p_double[i] = lagbc->ptr.p_double[i]*targetscale/s->ptr.p_double[i];
44115 : }
44116 :
44117 : /*
44118 : * Unpack results.
44119 : *
44120 : * Add XOrigin to XC and make sure that boundary constraints are
44121 : * satisfied.
44122 : */
44123 0 : for(i=0; i<=nmain-1; i++)
44124 : {
44125 :
44126 : /*
44127 : * Unscale/unshift
44128 : */
44129 0 : xs->ptr.p_double[i] = s->ptr.p_double[i]*state->exxc.ptr.p_double[i]+xorigin->ptr.p_double[i];
44130 :
44131 : /*
44132 : * Make sure that point is feasible w.r.t. box constraints.
44133 : * Enforce box constraints which were active in the scaled/shifted solution.
44134 : */
44135 0 : if( state->sclsfthasbndl.ptr.p_bool[i] )
44136 : {
44137 0 : if( ae_fp_less(xs->ptr.p_double[i],bndl->ptr.p_double[i]) )
44138 : {
44139 0 : xs->ptr.p_double[i] = bndl->ptr.p_double[i];
44140 : }
44141 0 : if( ae_fp_eq(state->exxc.ptr.p_double[i],state->sclsftbndl.ptr.p_double[i]) )
44142 : {
44143 0 : xs->ptr.p_double[i] = bndl->ptr.p_double[i];
44144 : }
44145 : }
44146 0 : if( state->sclsfthasbndu.ptr.p_bool[i] )
44147 : {
44148 0 : if( ae_fp_greater(xs->ptr.p_double[i],bndu->ptr.p_double[i]) )
44149 : {
44150 0 : xs->ptr.p_double[i] = bndu->ptr.p_double[i];
44151 : }
44152 0 : if( ae_fp_eq(state->exxc.ptr.p_double[i],state->sclsftbndu.ptr.p_double[i]) )
44153 : {
44154 0 : xs->ptr.p_double[i] = bndu->ptr.p_double[i];
44155 : }
44156 : }
44157 : }
44158 0 : *terminationtype = 2;
44159 0 : }
44160 :
44161 :
44162 : /*************************************************************************
44163 : This function generates box-constrained QP problem, which is penalized and
44164 : augmented formulation of original linearly constrained problem
44165 :
44166 : -- ALGLIB --
44167 : Copyright 23.02.2017 by Bochkanov Sergey
44168 : *************************************************************************/
44169 0 : static void qpdenseaulsolver_generateexmodel(/* Real */ ae_matrix* sclsfta,
44170 : /* Real */ ae_vector* sclsftb,
44171 : ae_int_t nmain,
44172 : /* Real */ ae_vector* sclsftbndl,
44173 : /* Boolean */ ae_vector* sclsfthasbndl,
44174 : /* Real */ ae_vector* sclsftbndu,
44175 : /* Boolean */ ae_vector* sclsfthasbndu,
44176 : /* Real */ ae_matrix* sclsftcleic,
44177 : ae_int_t sclsftnec,
44178 : ae_int_t sclsftnic,
44179 : /* Real */ ae_vector* nulc,
44180 : double rho,
44181 : /* Real */ ae_matrix* exa,
44182 : /* Real */ ae_vector* exb,
44183 : /* Real */ ae_vector* exbndl,
44184 : /* Real */ ae_vector* exbndu,
44185 : /* Real */ ae_matrix* tmp2,
44186 : ae_state *_state)
44187 : {
44188 : ae_int_t nslack;
44189 : ae_int_t ntotal;
44190 : ae_int_t i;
44191 : ae_int_t j;
44192 : double v;
44193 :
44194 :
44195 0 : nslack = sclsftnic;
44196 0 : ntotal = nmain+nslack;
44197 :
44198 : /*
44199 : * Integrity check for properly preallocated storage
44200 : */
44201 0 : ae_assert(exa->rows>=ntotal&&exa->cols>=ntotal, "QPDenseAUL.GenerateExModel - integrity check failed", _state);
44202 0 : ae_assert((exb->cnt>=ntotal&&exbndl->cnt>=ntotal)&&exbndu->cnt>=ntotal, "QPDenseAUL.GenerateExModel - integrity check failed", _state);
44203 :
44204 : /*
44205 : * Primary quadratic term
44206 : */
44207 0 : for(i=0; i<=ntotal-1; i++)
44208 : {
44209 0 : for(j=i; j<=ntotal-1; j++)
44210 : {
44211 0 : exa->ptr.pp_double[i][j] = (double)(0);
44212 : }
44213 : }
44214 0 : for(i=0; i<=nmain-1; i++)
44215 : {
44216 0 : for(j=i; j<=nmain-1; j++)
44217 : {
44218 0 : exa->ptr.pp_double[i][j] = sclsfta->ptr.pp_double[i][j];
44219 : }
44220 : }
44221 :
44222 : /*
44223 : * Primary linear term
44224 : */
44225 0 : for(i=0; i<=ntotal-1; i++)
44226 : {
44227 0 : exb->ptr.p_double[i] = (double)(0);
44228 : }
44229 0 : for(i=0; i<=nmain-1; i++)
44230 : {
44231 0 : exb->ptr.p_double[i] = sclsftb->ptr.p_double[i];
44232 : }
44233 :
44234 : /*
44235 : * Box constraints - move primary, add slack
44236 : */
44237 0 : for(i=0; i<=nmain-1; i++)
44238 : {
44239 0 : if( sclsfthasbndl->ptr.p_bool[i] )
44240 : {
44241 0 : exbndl->ptr.p_double[i] = sclsftbndl->ptr.p_double[i];
44242 : }
44243 : else
44244 : {
44245 0 : exbndl->ptr.p_double[i] = _state->v_neginf;
44246 : }
44247 0 : if( sclsfthasbndu->ptr.p_bool[i] )
44248 : {
44249 0 : exbndu->ptr.p_double[i] = sclsftbndu->ptr.p_double[i];
44250 : }
44251 : else
44252 : {
44253 0 : exbndu->ptr.p_double[i] = _state->v_posinf;
44254 : }
44255 : }
44256 0 : for(i=nmain; i<=ntotal-1; i++)
44257 : {
44258 0 : exbndl->ptr.p_double[i] = (double)(0);
44259 0 : exbndu->ptr.p_double[i] = _state->v_posinf;
44260 : }
44261 :
44262 : /*
44263 : * Handle equality constraints:
44264 : * * modify quadratic term
44265 : * * modify linear term
44266 : * * add Lagrangian term
44267 : */
44268 0 : rmatrixsetlengthatleast(tmp2, sclsftnec+sclsftnic, ntotal, _state);
44269 0 : for(i=0; i<=sclsftnec+sclsftnic-1; i++)
44270 : {
44271 :
44272 : /*
44273 : * Given constraint row ci and right hand side ri,
44274 : * I-th quadratic constraint adds penalty term
44275 : *
44276 : * 0.5*Rho*(ci'*x-ri)^2 =
44277 : * = 0.5*Rho*(ci'*x-ri)^T*(ci'*x-ri) =
44278 : * = 0.5*Rho*(x'*ci-ri')*(ci'*x-ri) =
44279 : * = 0.5*Rho*(x'*ci*ci'*x - ri'*ci'*x - x'*ci*ri + ri'*ri )
44280 : * = 0.5*Rho*(x'*(ci*ci')*x - 2*ri*(ci'*x) + ri^2 )
44281 : *
44282 : * Thus, quadratic term is updated by
44283 : *
44284 : * 0.5*Rho*(ci*ci')
44285 : *
44286 : * (with actual update to ExA being performed without 0.5
44287 : * multiplier because entire matrix is post-multipliead by 0.5)
44288 : * and linear term receives update
44289 : *
44290 : * -Rho*ri*ci
44291 : *
44292 : * Similaryly, lagrangian term is -NUi*(ci'*x-ri),
44293 : * so linear term is updated by
44294 : *
44295 : * -NUi*ci
44296 : *
44297 : * Because our model does not take into account constant term,
44298 : * we calculate just quadratic and linear terms.
44299 : */
44300 0 : ae_v_move(&tmp2->ptr.pp_double[i][0], 1, &sclsftcleic->ptr.pp_double[i][0], 1, ae_v_len(0,nmain-1));
44301 0 : for(j=nmain; j<=ntotal-1; j++)
44302 : {
44303 0 : tmp2->ptr.pp_double[i][j] = (double)(0);
44304 : }
44305 0 : if( i>=sclsftnec )
44306 : {
44307 0 : tmp2->ptr.pp_double[i][nmain+i-sclsftnec] = 1.0;
44308 : }
44309 0 : v = -rho*sclsftcleic->ptr.pp_double[i][nmain];
44310 0 : ae_v_addd(&exb->ptr.p_double[0], 1, &tmp2->ptr.pp_double[i][0], 1, ae_v_len(0,ntotal-1), v);
44311 0 : v = -nulc->ptr.p_double[i];
44312 0 : ae_v_addd(&exb->ptr.p_double[0], 1, &tmp2->ptr.pp_double[i][0], 1, ae_v_len(0,ntotal-1), v);
44313 : }
44314 0 : rmatrixsyrk(ntotal, sclsftnec+sclsftnic, rho, tmp2, 0, 0, 2, 1.0, exa, 0, 0, ae_true, _state);
44315 0 : }
44316 :
44317 :
44318 : /*************************************************************************
44319 : This function generates initial point for "extended" box-constrained QP
44320 : problem.
44321 :
44322 : -- ALGLIB --
44323 : Copyright 23.02.2017 by Bochkanov Sergey
44324 : *************************************************************************/
44325 0 : static void qpdenseaulsolver_generateexinitialpoint(/* Real */ ae_vector* sclsftxc,
44326 : ae_int_t nmain,
44327 : ae_int_t nslack,
44328 : /* Real */ ae_vector* exxc,
44329 : ae_state *_state)
44330 : {
44331 : ae_int_t ntotal;
44332 : ae_int_t i;
44333 :
44334 :
44335 0 : ntotal = nmain+nslack;
44336 0 : for(i=0; i<=ntotal-1; i++)
44337 : {
44338 0 : exxc->ptr.p_double[i] = (double)(0);
44339 : }
44340 0 : for(i=0; i<=nmain-1; i++)
44341 : {
44342 0 : exxc->ptr.p_double[i] = sclsftxc->ptr.p_double[i];
44343 : }
44344 0 : }
44345 :
44346 :
44347 : /*************************************************************************
44348 : This function estimates Lagrange multipliers for scaled-shifted QP problem
44349 : (here "scaled-shifted" means that we performed variable scaling and
44350 : subtracted origin) given by quadratic term A, linear term B, box constraints
44351 : and linear constraint matrix.
44352 :
44353 : It is assumed that all linear constraints are equality ones, with first
44354 : NEC ones being constraints without slack variables, and next NIC ones
44355 : having slack variables. The only inequality constraints we have are box
44356 : ones, with first NMain ones being "general" box constraints, and next NIC
44357 : ones being non-negativity constraints (not specified explicitly).
44358 :
44359 : We also make use of the current point XC, which is used to determine active
44360 : box constraints.
44361 :
44362 : Actual QP problem size is NMain+NIC, but some parameters have lower
44363 : dimensionality.
44364 :
44365 : Parameters sizes are:
44366 : * A is assumed to be array[NMain,NMain]
44367 : * B is assumed to be array[NMain]
44368 : * BndL, BndU are array[NMain]
44369 : * CLEIC is array[NEC+NIC,NMain+1] (last item in a row containts right part)
44370 : * ExXC is array[NMain+NIC], holds current point
44371 : * NuLCEst is array[NEC+NIC], holds initial values of Lagrange coeffs
44372 :
44373 : On exit NuLCEst is updated with new estimate of Lagrange multipliers.
44374 :
44375 : -- ALGLIB --
44376 : Copyright 23.02.2017 by Bochkanov Sergey
44377 : *************************************************************************/
44378 0 : static void qpdenseaulsolver_updatelagrangemultipliers(/* Real */ ae_matrix* sclsfta,
44379 : /* Real */ ae_vector* sclsftb,
44380 : ae_int_t nmain,
44381 : /* Real */ ae_vector* sclsftbndl,
44382 : /* Boolean */ ae_vector* sclsfthasbndl,
44383 : /* Real */ ae_vector* sclsftbndu,
44384 : /* Boolean */ ae_vector* sclsfthasbndu,
44385 : /* Real */ ae_matrix* sclsftcleic,
44386 : ae_int_t sclsftnec,
44387 : ae_int_t sclsftnic,
44388 : /* Real */ ae_vector* exxc,
44389 : /* Real */ ae_vector* nulcest,
44390 : qpdenseaulbuffers* buffers,
44391 : ae_state *_state)
44392 : {
44393 : ae_int_t nslack;
44394 : ae_int_t ntotal;
44395 : ae_int_t ktotal;
44396 : ae_int_t nqrrows;
44397 : ae_int_t nqrcols;
44398 : ae_int_t i;
44399 : ae_int_t j;
44400 : double lambdareg;
44401 : double mxdiag;
44402 : double v;
44403 : ae_bool isactive;
44404 :
44405 :
44406 0 : nslack = sclsftnic;
44407 0 : ntotal = nmain+nslack;
44408 0 : ktotal = sclsftnec+sclsftnic;
44409 :
44410 : /*
44411 : * Given current point ExXC, we can determine active and inactive
44412 : * constraints. After we drop inactive inequality constraints, we
44413 : * have equality-only constrained QP problem, with mix of general
44414 : * linear equality constraints and "simple" constraints Xi=Ci.
44415 : *
44416 : * Problem min(0.5*x'*A*x + b'*x) s.t. C*x=d (general linear
44417 : * constraints) can be solved by explicitly writing out Lagrange
44418 : * equations:
44419 : *
44420 : * [ A C' ] [ X ] [ -b]
44421 : * [ ] [ ] = [ ]
44422 : * [ C ] [ L ] [ d ]
44423 : *
44424 : * or
44425 : *
44426 : * [ X ]
44427 : * A1* [ ] = b1
44428 : * [ L ]
44429 : *
44430 : * where X stands for solution itself, and L stands for Lagrange
44431 : * multipliers. It can be easily solved with direct linear solver.
44432 : * However, such formulation does not account for "simple" equality
44433 : * constraints on variables. It is possible to include "simple"
44434 : * constraints into "general" ones (i.e. append (0 ... 0 -1 0 ... 0)'
44435 : * to the constraint matrix), but it will increase problem
44436 : * size.
44437 : *
44438 : * Another approach is to use initial values of X and L (X0 and L0)
44439 : * as starting point, and to solve for "offset" from (X0, L0):
44440 : *
44441 : * [ X0+X1 ]
44442 : * A1*[ ] = b1
44443 : * [ L0+L1 ]
44444 : *
44445 : * or
44446 : *
44447 : * [ X1 ] [ X0 ]
44448 : * A1*[ ] = b1 - A1*[ ]
44449 : * [ L1 ] [ L0 ]
44450 : *
44451 : * In such formulation components of X1 which correspond to active
44452 : * constraints on variables are "frozen" at value 0 (because we have
44453 : * equality constraint, offset from constrained value have to be zero).
44454 : *
44455 : * Thus, we can rewrite corresponding columns of A1 with zeros - and
44456 : * use this space to store (0 ... 0 -1 0 ... 0)', which is used to
44457 : * account for Lagrange multipliers for "simple" constraints.
44458 : */
44459 0 : nqrcols = ntotal+ktotal;
44460 0 : nqrrows = nqrcols;
44461 0 : rvectorsetlengthatleast(&buffers->qrsv0, nqrcols, _state);
44462 0 : rvectorsetlengthatleast(&buffers->qrsvx1, nqrcols, _state);
44463 0 : for(i=0; i<=ntotal-1; i++)
44464 : {
44465 0 : buffers->qrsv0.ptr.p_double[i] = exxc->ptr.p_double[i];
44466 : }
44467 0 : for(i=0; i<=ktotal-1; i++)
44468 : {
44469 0 : buffers->qrsv0.ptr.p_double[ntotal+i] = nulcest->ptr.p_double[i];
44470 : }
44471 0 : rmatrixsetlengthatleast(&buffers->qrkkt, nqrcols+nqrcols, nqrcols+1, _state);
44472 0 : rvectorsetlengthatleast(&buffers->qrrightpart, nqrcols+nqrcols, _state);
44473 0 : lambdareg = 1.0E-8;
44474 : for(;;)
44475 : {
44476 :
44477 : /*
44478 : * Initialize matrix A1 and right part b1 with zeros
44479 : */
44480 0 : for(i=0; i<=buffers->qrkkt.rows-1; i++)
44481 : {
44482 0 : for(j=0; j<=buffers->qrkkt.cols-1; j++)
44483 : {
44484 0 : buffers->qrkkt.ptr.pp_double[i][j] = (double)(0);
44485 : }
44486 0 : buffers->qrrightpart.ptr.p_double[i] = (double)(0);
44487 : }
44488 :
44489 : /*
44490 : * Append quadratic term (note: we implicitly add NSlack zeros to
44491 : * A and b).
44492 : */
44493 0 : mxdiag = (double)(0);
44494 0 : for(i=0; i<=nmain-1; i++)
44495 : {
44496 0 : for(j=0; j<=nmain-1; j++)
44497 : {
44498 0 : buffers->qrkkt.ptr.pp_double[i][j] = sclsfta->ptr.pp_double[i][j];
44499 : }
44500 0 : buffers->qrrightpart.ptr.p_double[i] = -sclsftb->ptr.p_double[i];
44501 0 : mxdiag = ae_maxreal(mxdiag, ae_fabs(sclsfta->ptr.pp_double[i][i], _state), _state);
44502 : }
44503 0 : mxdiag = coalesce(mxdiag, (double)(1), _state);
44504 :
44505 : /*
44506 : * Append general linear constraints
44507 : */
44508 0 : for(i=0; i<=ktotal-1; i++)
44509 : {
44510 0 : for(j=0; j<=nmain-1; j++)
44511 : {
44512 0 : buffers->qrkkt.ptr.pp_double[ntotal+i][j] = -sclsftcleic->ptr.pp_double[i][j];
44513 0 : buffers->qrkkt.ptr.pp_double[j][ntotal+i] = -sclsftcleic->ptr.pp_double[i][j];
44514 : }
44515 0 : if( i>=sclsftnec )
44516 : {
44517 0 : buffers->qrkkt.ptr.pp_double[ntotal+i][nmain+(i-sclsftnec)] = (double)(-1);
44518 0 : buffers->qrkkt.ptr.pp_double[nmain+(i-sclsftnec)][ntotal+i] = (double)(-1);
44519 : }
44520 0 : buffers->qrrightpart.ptr.p_double[ntotal+i] = -sclsftcleic->ptr.pp_double[i][nmain];
44521 : }
44522 :
44523 : /*
44524 : * Append regularizer to the bottom of the matrix
44525 : * (it will be factored in during QR decomposition)
44526 : */
44527 0 : if( ae_fp_greater(lambdareg,(double)(0)) )
44528 : {
44529 0 : nqrrows = nqrcols+nqrcols;
44530 0 : for(i=0; i<=nqrcols-1; i++)
44531 : {
44532 0 : buffers->qrkkt.ptr.pp_double[nqrcols+i][i] = lambdareg*mxdiag;
44533 : }
44534 : }
44535 :
44536 : /*
44537 : * Subtract reference point (X0,L0) from the system
44538 : */
44539 0 : for(i=0; i<=nqrcols-1; i++)
44540 : {
44541 0 : v = ae_v_dotproduct(&buffers->qrkkt.ptr.pp_double[i][0], 1, &buffers->qrsv0.ptr.p_double[0], 1, ae_v_len(0,nqrcols-1));
44542 0 : buffers->qrrightpart.ptr.p_double[i] = buffers->qrrightpart.ptr.p_double[i]-v;
44543 : }
44544 :
44545 : /*
44546 : * Handle active "simple" equality constraints
44547 : */
44548 0 : for(i=0; i<=ntotal-1; i++)
44549 : {
44550 0 : isactive = ae_false;
44551 0 : if( i<nmain&&((sclsfthasbndl->ptr.p_bool[i]&&ae_fp_eq(exxc->ptr.p_double[i],sclsftbndl->ptr.p_double[i]))||(sclsfthasbndu->ptr.p_bool[i]&&ae_fp_eq(exxc->ptr.p_double[i],sclsftbndu->ptr.p_double[i]))) )
44552 : {
44553 0 : isactive = ae_true;
44554 : }
44555 0 : if( i>=nmain&&ae_fp_eq(exxc->ptr.p_double[i],0.0) )
44556 : {
44557 0 : isactive = ae_true;
44558 : }
44559 0 : if( !isactive )
44560 : {
44561 0 : continue;
44562 : }
44563 0 : for(j=0; j<=nqrrows-1; j++)
44564 : {
44565 0 : buffers->qrkkt.ptr.pp_double[j][i] = (double)(0);
44566 : }
44567 0 : buffers->qrkkt.ptr.pp_double[i][i] = (double)(-1);
44568 : }
44569 :
44570 : /*
44571 : * Solve via QR decomposition:
44572 : * * append right part to the system matrix
44573 : * * perform QR decomposition of the extended matrix (right part is implicitly
44574 : * multiplied by Q during decomposition; believe me, it works!)
44575 : * * check condition number, increase regularization value if necessary and retry
44576 : * * solve triangular system, break iteration
44577 : */
44578 0 : for(i=0; i<=nqrrows-1; i++)
44579 : {
44580 0 : buffers->qrkkt.ptr.pp_double[i][nqrcols] = buffers->qrrightpart.ptr.p_double[i];
44581 : }
44582 0 : rmatrixqr(&buffers->qrkkt, nqrrows, nqrcols+1, &buffers->qrtau, _state);
44583 0 : if( ae_fp_less_eq(rmatrixtrrcond1(&buffers->qrkkt, nqrcols, ae_true, ae_false, _state),1000*ae_machineepsilon) )
44584 : {
44585 0 : lambdareg = coalesce(10*lambdareg, 1.0E-13, _state);
44586 0 : continue;
44587 : }
44588 0 : for(i=nqrcols-1; i>=0; i--)
44589 : {
44590 0 : v = buffers->qrkkt.ptr.pp_double[i][nqrcols];
44591 0 : for(j=i+1; j<=nqrcols-1; j++)
44592 : {
44593 0 : v = v-buffers->qrkkt.ptr.pp_double[i][j]*buffers->qrsvx1.ptr.p_double[j];
44594 : }
44595 0 : buffers->qrsvx1.ptr.p_double[i] = v/buffers->qrkkt.ptr.pp_double[i][i];
44596 : }
44597 0 : break;
44598 : }
44599 :
44600 : /*
44601 : * Update Lagrange coefficients
44602 : */
44603 0 : for(i=0; i<=ktotal-1; i++)
44604 : {
44605 0 : nulcest->ptr.p_double[i] = buffers->qrsv0.ptr.p_double[ntotal+i]+buffers->qrsvx1.ptr.p_double[ntotal+i];
44606 : }
44607 0 : }
44608 :
44609 :
44610 : /*************************************************************************
44611 : This function generates scaled (by S) and shifted (by XC) reformulation of
44612 : the original problem.
44613 :
44614 : INPUT PARAMETERS:
44615 : DenseA - for dense problems (AKind=0), A-term of CQM object
44616 : contains system matrix. Other terms are unspecified
44617 : and should not be referenced.
44618 : SparseA - for sparse problems (AKind=1), CRS format
44619 : AKind - sparse matrix format:
44620 : * 0 for dense matrix
44621 : * 1 for sparse matrix
44622 : SparseUpper - which triangle of SparseAC stores matrix - upper or
44623 : lower one (for dense matrices this parameter is not
44624 : actual).
44625 : B - linear term, array[N]
44626 : BndL - lower bound, array[N]
44627 : BndU - upper bound, array[N]
44628 : S - scale vector, array[NC]:
44629 : * I-th element contains scale of I-th variable,
44630 : * SC[I]>0
44631 : XOrigin - origin term, array[NC]. Can be zero.
44632 : N - number of variables in the original formulation (no
44633 : slack variables).
44634 : CLEIC - dense linear equality/inequality constraints. Equality
44635 : constraints come first.
44636 : NEC, NIC - number of dense equality/inequality constraints.
44637 : SCLEIC - sparse linear equality/inequality constraints. Equality
44638 : constraints come first.
44639 : SNEC, SNIC - number of sparse equality/inequality constraints.
44640 : RenormLC - whether constraints should be renormalized (recommended)
44641 : or used "as is".
44642 : Settings - QPDENSEAULSettings object initialized by one of the initialization
44643 : functions.
44644 : State - object which stores temporaries
44645 : XS - initial point, array[NC]
44646 :
44647 :
44648 : On output, following fields of the State structure are modified:
44649 : * SclSftA - array[NMain,NMain], quadratic term, both triangles
44650 : * SclSftB - array[NMain], linear term
44651 : * SclSftXC - array[NMain], initial point
44652 : * SclSftHasBndL,
44653 : SclSftHasBndU,
44654 : SclSftBndL,
44655 : SclSftBndU - array[NMain], lower/upper bounds
44656 : * SclSftCLEIC - array[KTotal,NMain+1], general linear constraints
44657 :
44658 : NOTE: State.Tmp2 is used to store temporary array[NMain,NMain]
44659 :
44660 : -- ALGLIB --
44661 : Copyright 01.10.2017 by Bochkanov Sergey
44662 : *************************************************************************/
44663 0 : static void qpdenseaulsolver_scaleshiftoriginalproblem(convexquadraticmodel* a,
44664 : sparsematrix* sparsea,
44665 : ae_int_t akind,
44666 : ae_bool sparseaupper,
44667 : /* Real */ ae_vector* b,
44668 : /* Real */ ae_vector* bndl,
44669 : /* Real */ ae_vector* bndu,
44670 : /* Real */ ae_vector* s,
44671 : /* Real */ ae_vector* xorigin,
44672 : ae_int_t nmain,
44673 : /* Real */ ae_matrix* cleic,
44674 : ae_int_t dnec,
44675 : ae_int_t dnic,
44676 : sparsematrix* scleic,
44677 : ae_int_t snec,
44678 : ae_int_t snic,
44679 : ae_bool renormlc,
44680 : qpdenseaulbuffers* state,
44681 : /* Real */ ae_vector* xs,
44682 : ae_state *_state)
44683 : {
44684 : ae_int_t i;
44685 : ae_int_t j;
44686 : ae_int_t k;
44687 : ae_int_t j0;
44688 : ae_int_t j1;
44689 : double v;
44690 : double vv;
44691 : ae_int_t ktotal;
44692 :
44693 :
44694 0 : ae_assert(akind==0||akind==1, "QPDENSEAULOptimize: unexpected AKind", _state);
44695 0 : ktotal = dnec+dnic+snec+snic;
44696 0 : rmatrixsetlengthatleast(&state->sclsfta, nmain, nmain, _state);
44697 0 : rvectorsetlengthatleast(&state->sclsftb, nmain, _state);
44698 0 : rvectorsetlengthatleast(&state->sclsftxc, nmain, _state);
44699 0 : rvectorsetlengthatleast(&state->sclsftbndl, nmain, _state);
44700 0 : rvectorsetlengthatleast(&state->sclsftbndu, nmain, _state);
44701 0 : bvectorsetlengthatleast(&state->sclsfthasbndl, nmain, _state);
44702 0 : bvectorsetlengthatleast(&state->sclsfthasbndu, nmain, _state);
44703 0 : rmatrixsetlengthatleast(&state->sclsftcleic, ktotal, nmain+1, _state);
44704 0 : rvectorsetlengthatleast(&state->cscales, ktotal, _state);
44705 0 : if( akind==0 )
44706 : {
44707 :
44708 : /*
44709 : * Extract dense A and scale
44710 : */
44711 0 : cqmgeta(a, &state->tmp2, _state);
44712 0 : for(i=0; i<=nmain-1; i++)
44713 : {
44714 0 : for(j=0; j<=nmain-1; j++)
44715 : {
44716 0 : state->sclsfta.ptr.pp_double[i][j] = (double)(0);
44717 : }
44718 : }
44719 0 : for(i=0; i<=nmain-1; i++)
44720 : {
44721 0 : for(j=i; j<=nmain-1; j++)
44722 : {
44723 0 : v = state->tmp2.ptr.pp_double[i][j]*s->ptr.p_double[i]*s->ptr.p_double[j];
44724 0 : state->sclsfta.ptr.pp_double[i][j] = v;
44725 0 : state->sclsfta.ptr.pp_double[j][i] = v;
44726 : }
44727 : }
44728 : }
44729 0 : if( akind==1 )
44730 : {
44731 :
44732 : /*
44733 : * Extract sparse A and scale
44734 : */
44735 0 : ae_assert(sparsea->matrixtype==1, "QPDENSEAULOptimize: unexpected sparse matrix format", _state);
44736 0 : ae_assert(sparsea->m==nmain, "QPDENSEAULOptimize: unexpected sparse matrix size", _state);
44737 0 : ae_assert(sparsea->n==nmain, "QPDENSEAULOptimize: unexpected sparse matrix size", _state);
44738 0 : for(i=0; i<=nmain-1; i++)
44739 : {
44740 0 : for(j=0; j<=nmain-1; j++)
44741 : {
44742 0 : state->sclsfta.ptr.pp_double[i][j] = (double)(0);
44743 : }
44744 : }
44745 0 : if( sparseaupper )
44746 : {
44747 0 : for(i=0; i<=nmain-1; i++)
44748 : {
44749 0 : if( sparsea->didx.ptr.p_int[i]!=sparsea->uidx.ptr.p_int[i] )
44750 : {
44751 0 : state->sclsfta.ptr.pp_double[i][i] = sparsea->vals.ptr.p_double[sparsea->didx.ptr.p_int[i]]*s->ptr.p_double[i]*s->ptr.p_double[i];
44752 : }
44753 0 : j0 = sparsea->uidx.ptr.p_int[i];
44754 0 : j1 = sparsea->ridx.ptr.p_int[i+1]-1;
44755 0 : for(j=j0; j<=j1; j++)
44756 : {
44757 0 : k = sparsea->idx.ptr.p_int[j];
44758 0 : v = sparsea->vals.ptr.p_double[j]*s->ptr.p_double[i]*s->ptr.p_double[k];
44759 0 : state->sclsfta.ptr.pp_double[i][k] = v;
44760 0 : state->sclsfta.ptr.pp_double[k][i] = v;
44761 : }
44762 : }
44763 : }
44764 : else
44765 : {
44766 0 : for(i=0; i<=nmain-1; i++)
44767 : {
44768 0 : if( sparsea->didx.ptr.p_int[i]!=sparsea->uidx.ptr.p_int[i] )
44769 : {
44770 0 : state->sclsfta.ptr.pp_double[i][i] = sparsea->vals.ptr.p_double[sparsea->didx.ptr.p_int[i]]*s->ptr.p_double[i]*s->ptr.p_double[i];
44771 : }
44772 0 : j0 = sparsea->ridx.ptr.p_int[i];
44773 0 : j1 = sparsea->didx.ptr.p_int[i]-1;
44774 0 : for(j=j0; j<=j1; j++)
44775 : {
44776 0 : k = sparsea->idx.ptr.p_int[j];
44777 0 : v = sparsea->vals.ptr.p_double[j]*s->ptr.p_double[i]*s->ptr.p_double[k];
44778 0 : state->sclsfta.ptr.pp_double[i][k] = v;
44779 0 : state->sclsfta.ptr.pp_double[k][i] = v;
44780 : }
44781 : }
44782 : }
44783 : }
44784 0 : for(i=0; i<=nmain-1; i++)
44785 : {
44786 0 : state->sclsftb.ptr.p_double[i] = b->ptr.p_double[i]*s->ptr.p_double[i];
44787 0 : state->sclsftxc.ptr.p_double[i] = (xs->ptr.p_double[i]-xorigin->ptr.p_double[i])/s->ptr.p_double[i];
44788 0 : state->sclsfthasbndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state);
44789 0 : state->sclsfthasbndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state);
44790 0 : state->sclsftbndl.ptr.p_double[i] = bndl->ptr.p_double[i];
44791 0 : state->sclsftbndu.ptr.p_double[i] = bndu->ptr.p_double[i];
44792 : }
44793 0 : scaleshiftbcinplace(s, xorigin, &state->sclsftbndl, &state->sclsftbndu, nmain, _state);
44794 0 : for(i=0; i<=ktotal-1; i++)
44795 : {
44796 0 : for(j=0; j<=nmain; j++)
44797 : {
44798 0 : state->sclsftcleic.ptr.pp_double[i][j] = (double)(0);
44799 : }
44800 : }
44801 0 : for(i=0; i<=dnec-1; i++)
44802 : {
44803 0 : for(j=0; j<=nmain-1; j++)
44804 : {
44805 0 : v = cleic->ptr.pp_double[i][j]*s->ptr.p_double[j];
44806 0 : state->sclsftcleic.ptr.pp_double[i][j] = v;
44807 : }
44808 0 : state->sclsftcleic.ptr.pp_double[i][nmain] = cleic->ptr.pp_double[i][nmain];
44809 : }
44810 0 : for(i=0; i<=dnic-1; i++)
44811 : {
44812 0 : for(j=0; j<=nmain-1; j++)
44813 : {
44814 0 : v = cleic->ptr.pp_double[dnec+i][j]*s->ptr.p_double[j];
44815 0 : state->sclsftcleic.ptr.pp_double[dnec+snec+i][j] = v;
44816 : }
44817 0 : state->sclsftcleic.ptr.pp_double[dnec+snec+i][nmain] = cleic->ptr.pp_double[dnec+i][nmain];
44818 : }
44819 0 : for(i=0; i<=snec-1; i++)
44820 : {
44821 :
44822 : /*
44823 : * Because constraints are sparse, everything is a bit tricky -
44824 : * it is possible that N-th element of the row is zero and not
44825 : * stored; it is also possible that entire row is empty.
44826 : */
44827 0 : j0 = scleic->ridx.ptr.p_int[i];
44828 0 : j1 = scleic->ridx.ptr.p_int[i+1]-1;
44829 0 : if( j1>=j0&&scleic->idx.ptr.p_int[j1]==nmain )
44830 : {
44831 0 : state->sclsftcleic.ptr.pp_double[dnec+i][nmain] = scleic->vals.ptr.p_double[j1];
44832 0 : j1 = j1-1;
44833 : }
44834 0 : for(j=j0; j<=j1; j++)
44835 : {
44836 0 : k = scleic->idx.ptr.p_int[j];
44837 0 : v = scleic->vals.ptr.p_double[j]*s->ptr.p_double[k];
44838 0 : state->sclsftcleic.ptr.pp_double[dnec+i][k] = v;
44839 : }
44840 : }
44841 0 : for(i=0; i<=snic-1; i++)
44842 : {
44843 :
44844 : /*
44845 : * Because constraints are sparse, everything is a bit tricky -
44846 : * it is possible that N-th element of the row is zero and not
44847 : * stored; it is also possible that entire row is empty.
44848 : */
44849 0 : j0 = scleic->ridx.ptr.p_int[snec+i];
44850 0 : j1 = scleic->ridx.ptr.p_int[snec+i+1]-1;
44851 0 : if( j1>=j0&&scleic->idx.ptr.p_int[j1]==nmain )
44852 : {
44853 0 : state->sclsftcleic.ptr.pp_double[dnec+snec+dnic+i][nmain] = scleic->vals.ptr.p_double[j1];
44854 0 : j1 = j1-1;
44855 : }
44856 0 : for(j=j0; j<=j1; j++)
44857 : {
44858 0 : k = scleic->idx.ptr.p_int[j];
44859 0 : v = scleic->vals.ptr.p_double[j]*s->ptr.p_double[k];
44860 0 : state->sclsftcleic.ptr.pp_double[dnec+snec+dnic+i][k] = v;
44861 : }
44862 : }
44863 0 : if( renormlc&&ktotal>0 )
44864 : {
44865 :
44866 : /*
44867 : * Normalize linear constraints in such way that they have unit norm
44868 : * (after variable scaling)
44869 : */
44870 0 : for(i=0; i<=ktotal-1; i++)
44871 : {
44872 0 : vv = 0.0;
44873 0 : for(j=0; j<=nmain-1; j++)
44874 : {
44875 0 : v = state->sclsftcleic.ptr.pp_double[i][j];
44876 0 : vv = vv+v*v;
44877 : }
44878 0 : vv = ae_sqrt(vv, _state);
44879 0 : state->cscales.ptr.p_double[i] = vv;
44880 0 : if( ae_fp_greater(vv,(double)(0)) )
44881 : {
44882 0 : vv = 1/vv;
44883 0 : for(j=0; j<=nmain; j++)
44884 : {
44885 0 : state->sclsftcleic.ptr.pp_double[i][j] = state->sclsftcleic.ptr.pp_double[i][j]*vv;
44886 : }
44887 : }
44888 : }
44889 : }
44890 : else
44891 : {
44892 :
44893 : /*
44894 : * Load unit scales
44895 : */
44896 0 : for(i=0; i<=ktotal-1; i++)
44897 : {
44898 0 : state->cscales.ptr.p_double[i] = 1.0;
44899 : }
44900 : }
44901 0 : for(i=0; i<=ktotal-1; i++)
44902 : {
44903 :
44904 : /*
44905 : * Apply XOrigin
44906 : */
44907 0 : v = 0.0;
44908 0 : for(j=0; j<=nmain-1; j++)
44909 : {
44910 0 : v = v+state->sclsftcleic.ptr.pp_double[i][j]*(xorigin->ptr.p_double[j]/s->ptr.p_double[j]);
44911 : }
44912 0 : state->sclsftcleic.ptr.pp_double[i][nmain] = state->sclsftcleic.ptr.pp_double[i][nmain]-v;
44913 : }
44914 0 : }
44915 :
44916 :
44917 : /*************************************************************************
44918 : Normalize model in such way that norm(A)~1 (very roughly)
44919 :
44920 : We have two lower bounds for sigma_max(A):
44921 : * first estimate is provided by Frobenius norm, it is equal to ANorm/NMain
44922 : * second estimate is provided by max(CAC)
44923 :
44924 : We select largest one of these estimates, because using just one
44925 : of them is prone to different failure modes. Then, we divide A and B
44926 : by this estimate.
44927 :
44928 : INPUT PARAMETERS:
44929 : A - array[N,N], quadratic term, full triangle is given
44930 : B - array[N], linear term
44931 : N - problem size
44932 : CLEIC- array[NEC+NIC,N+1], linear equality/inequality constraints
44933 : NEC - number of equality constraints
44934 : NIC - number of inequality constraints
44935 : UseCLEIC- additional normalization of A in such way that CLEIC*A*CLEIC'~1:
44936 : * if False, CLEIC is ignored
44937 : * if True, CLEIC rows MUST have unit norm (we check it)
44938 : Tmp2- additional buffer, possibly preallocated
44939 :
44940 : OUTPUT PARAMETERS:
44941 : A, B - appropriately rescaled by 1/SCL
44942 :
44943 : RESULT:
44944 : multiplier SCL
44945 :
44946 : -- ALGLIB --
44947 : Copyright 01.10.2017 by Bochkanov Sergey
44948 : *************************************************************************/
44949 0 : static double qpdenseaulsolver_normalizequadraticterm(/* Real */ ae_matrix* a,
44950 : /* Real */ ae_vector* b,
44951 : ae_int_t n,
44952 : /* Real */ ae_matrix* cleic,
44953 : ae_int_t nec,
44954 : ae_int_t nic,
44955 : ae_bool usecleic,
44956 : /* Real */ ae_matrix* tmp2,
44957 : ae_state *_state)
44958 : {
44959 : ae_int_t i;
44960 : ae_int_t j;
44961 : double anorm;
44962 : double maxcac;
44963 : double v;
44964 : double vv;
44965 : ae_int_t ktotal;
44966 : ae_int_t nmain;
44967 : double result;
44968 :
44969 :
44970 0 : nmain = n;
44971 0 : ktotal = nec+nic;
44972 0 : anorm = (double)(0);
44973 0 : for(i=0; i<=nmain-1; i++)
44974 : {
44975 0 : for(j=0; j<=nmain-1; j++)
44976 : {
44977 0 : anorm = anorm+ae_sqr(a->ptr.pp_double[i][j], _state);
44978 : }
44979 : }
44980 0 : anorm = ae_sqrt(anorm, _state);
44981 0 : if( usecleic&&ktotal>0 )
44982 : {
44983 :
44984 : /*
44985 : * Calculate max(|diag(C*A*C')|), where C is constraint matrix
44986 : */
44987 0 : rmatrixsetlengthatleast(tmp2, ktotal, nmain, _state);
44988 0 : rmatrixgemm(ktotal, nmain, nmain, 1.0, cleic, 0, 0, 0, a, 0, 0, 0, 0.0, tmp2, 0, 0, _state);
44989 0 : maxcac = 0.0;
44990 0 : for(i=0; i<=ktotal-1; i++)
44991 : {
44992 0 : v = (double)(0);
44993 0 : vv = (double)(0);
44994 0 : for(j=0; j<=nmain-1; j++)
44995 : {
44996 0 : v = v+tmp2->ptr.pp_double[i][j]*cleic->ptr.pp_double[i][j];
44997 0 : vv = vv+ae_sqr(cleic->ptr.pp_double[i][j], _state);
44998 : }
44999 0 : ae_assert(ae_fp_less(ae_fabs(vv-1, _state),1.0E-9)||ae_fp_eq(vv,(double)(0)), "DENSE-AUL: integrity check failed", _state);
45000 0 : maxcac = ae_maxreal(maxcac, ae_fabs(v, _state), _state);
45001 : }
45002 : }
45003 : else
45004 : {
45005 0 : maxcac = (double)(0);
45006 : }
45007 0 : result = coalesce(ae_maxreal(maxcac, anorm/nmain, _state), (double)(1), _state);
45008 0 : v = 1/result;
45009 0 : for(i=0; i<=nmain-1; i++)
45010 : {
45011 0 : for(j=0; j<=nmain-1; j++)
45012 : {
45013 0 : a->ptr.pp_double[i][j] = a->ptr.pp_double[i][j]*v;
45014 : }
45015 : }
45016 0 : for(i=0; i<=nmain-1; i++)
45017 : {
45018 0 : b->ptr.p_double[i] = b->ptr.p_double[i]*v;
45019 : }
45020 0 : return result;
45021 : }
45022 :
45023 :
45024 : /*************************************************************************
45025 : This function selects initial working set of general inequality constraints
45026 : for QP problem:
45027 : * for non-convex QP problems - NICWork=NIC is returned
45028 : * otherwise - NICWork=0 is returned (we have to
45029 : determine working set iteratively)
45030 :
45031 : INPUT PARAMETERS:
45032 : A - array[NMain], quadratic term, full matrix is stored
45033 : NMain - number of variables in the "original" QP problem
45034 : CLEIC - array[NEC+NIC,NMain+1], constraint matrix
45035 : NEC - number of equality constraints
45036 : NIC - number of inequality constraints
45037 :
45038 : OUTPUT PARAMETERS:
45039 : NICWork - recommended size of working set; in current version
45040 : either all (NICWork=NIC) or none (NICWork=0) constraints
45041 : are included.
45042 : AllowWSEviction-whether problem properties allow eviction of constraints
45043 : from working set or not. Non-convex problems do not
45044 : allow eviction, convex ones do.
45045 :
45046 : -- ALGLIB --
45047 : Copyright 02.10.2017 by Bochkanov Sergey
45048 : *************************************************************************/
45049 0 : static void qpdenseaulsolver_selectinitialworkingset(/* Real */ ae_matrix* a,
45050 : ae_int_t nmain,
45051 : /* Real */ ae_matrix* cleic,
45052 : ae_int_t nec,
45053 : ae_int_t nic,
45054 : /* Real */ ae_vector* tmp0,
45055 : /* Real */ ae_matrix* tmp2,
45056 : ae_int_t* nicwork,
45057 : ae_bool* allowwseviction,
45058 : ae_state *_state)
45059 : {
45060 : ae_int_t i;
45061 : ae_int_t j;
45062 :
45063 0 : *nicwork = 0;
45064 0 : *allowwseviction = ae_false;
45065 :
45066 0 : rmatrixsetlengthatleast(tmp2, nmain, nmain, _state);
45067 0 : rvectorsetlengthatleast(tmp0, nmain, _state);
45068 0 : for(i=0; i<=nmain-1; i++)
45069 : {
45070 0 : for(j=i; j<=nmain-1; j++)
45071 : {
45072 0 : tmp2->ptr.pp_double[i][j] = a->ptr.pp_double[i][j];
45073 : }
45074 : }
45075 0 : if( !spdmatrixcholeskyrec(tmp2, 0, nmain, ae_true, tmp0, _state) )
45076 : {
45077 :
45078 : /*
45079 : * Matrix is indefinite.
45080 : *
45081 : * We have to select full working set, otherwise algorithm may fail
45082 : * because problem with reduced working set can be unbounded from below.
45083 : */
45084 0 : *nicwork = nic;
45085 0 : *allowwseviction = ae_false;
45086 : }
45087 : else
45088 : {
45089 :
45090 : /*
45091 : * Positive definite matrix.
45092 : *
45093 : * We can select zero initial working set and expand it later.
45094 : */
45095 0 : *nicwork = 0;
45096 0 : *allowwseviction = ae_true;
45097 : }
45098 0 : }
45099 :
45100 :
45101 0 : void _qpdenseaulsettings_init(void* _p, ae_state *_state, ae_bool make_automatic)
45102 : {
45103 0 : qpdenseaulsettings *p = (qpdenseaulsettings*)_p;
45104 0 : ae_touch_ptr((void*)p);
45105 0 : }
45106 :
45107 :
45108 0 : void _qpdenseaulsettings_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
45109 : {
45110 0 : qpdenseaulsettings *dst = (qpdenseaulsettings*)_dst;
45111 0 : qpdenseaulsettings *src = (qpdenseaulsettings*)_src;
45112 0 : dst->epsx = src->epsx;
45113 0 : dst->outerits = src->outerits;
45114 0 : dst->rho = src->rho;
45115 0 : }
45116 :
45117 :
45118 0 : void _qpdenseaulsettings_clear(void* _p)
45119 : {
45120 0 : qpdenseaulsettings *p = (qpdenseaulsettings*)_p;
45121 0 : ae_touch_ptr((void*)p);
45122 0 : }
45123 :
45124 :
45125 0 : void _qpdenseaulsettings_destroy(void* _p)
45126 : {
45127 0 : qpdenseaulsettings *p = (qpdenseaulsettings*)_p;
45128 0 : ae_touch_ptr((void*)p);
45129 0 : }
45130 :
45131 :
45132 0 : void _qpdenseaulbuffers_init(void* _p, ae_state *_state, ae_bool make_automatic)
45133 : {
45134 0 : qpdenseaulbuffers *p = (qpdenseaulbuffers*)_p;
45135 0 : ae_touch_ptr((void*)p);
45136 0 : ae_vector_init(&p->nulc, 0, DT_REAL, _state, make_automatic);
45137 0 : ae_matrix_init(&p->sclsfta, 0, 0, DT_REAL, _state, make_automatic);
45138 0 : ae_vector_init(&p->sclsftb, 0, DT_REAL, _state, make_automatic);
45139 0 : ae_vector_init(&p->sclsfthasbndl, 0, DT_BOOL, _state, make_automatic);
45140 0 : ae_vector_init(&p->sclsfthasbndu, 0, DT_BOOL, _state, make_automatic);
45141 0 : ae_vector_init(&p->sclsftbndl, 0, DT_REAL, _state, make_automatic);
45142 0 : ae_vector_init(&p->sclsftbndu, 0, DT_REAL, _state, make_automatic);
45143 0 : ae_vector_init(&p->sclsftxc, 0, DT_REAL, _state, make_automatic);
45144 0 : ae_matrix_init(&p->sclsftcleic, 0, 0, DT_REAL, _state, make_automatic);
45145 0 : ae_vector_init(&p->cidx, 0, DT_INT, _state, make_automatic);
45146 0 : ae_vector_init(&p->cscales, 0, DT_REAL, _state, make_automatic);
45147 0 : ae_matrix_init(&p->exa, 0, 0, DT_REAL, _state, make_automatic);
45148 0 : ae_vector_init(&p->exb, 0, DT_REAL, _state, make_automatic);
45149 0 : ae_vector_init(&p->exxc, 0, DT_REAL, _state, make_automatic);
45150 0 : ae_vector_init(&p->exbndl, 0, DT_REAL, _state, make_automatic);
45151 0 : ae_vector_init(&p->exbndu, 0, DT_REAL, _state, make_automatic);
45152 0 : ae_vector_init(&p->exscale, 0, DT_REAL, _state, make_automatic);
45153 0 : ae_vector_init(&p->exxorigin, 0, DT_REAL, _state, make_automatic);
45154 0 : _qqpsettings_init(&p->qqpsettingsuser, _state, make_automatic);
45155 0 : _qqpbuffers_init(&p->qqpbuf, _state, make_automatic);
45156 0 : ae_vector_init(&p->nulcest, 0, DT_REAL, _state, make_automatic);
45157 0 : ae_vector_init(&p->tmpg, 0, DT_REAL, _state, make_automatic);
45158 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
45159 0 : ae_matrix_init(&p->tmp2, 0, 0, DT_REAL, _state, make_automatic);
45160 0 : ae_vector_init(&p->modelg, 0, DT_REAL, _state, make_automatic);
45161 0 : ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic);
45162 0 : ae_vector_init(&p->deltax, 0, DT_REAL, _state, make_automatic);
45163 0 : _convexquadraticmodel_init(&p->dummycqm, _state, make_automatic);
45164 0 : _sparsematrix_init(&p->dummysparse, _state, make_automatic);
45165 0 : ae_matrix_init(&p->qrkkt, 0, 0, DT_REAL, _state, make_automatic);
45166 0 : ae_vector_init(&p->qrrightpart, 0, DT_REAL, _state, make_automatic);
45167 0 : ae_vector_init(&p->qrtau, 0, DT_REAL, _state, make_automatic);
45168 0 : ae_vector_init(&p->qrsv0, 0, DT_REAL, _state, make_automatic);
45169 0 : ae_vector_init(&p->qrsvx1, 0, DT_REAL, _state, make_automatic);
45170 0 : ae_vector_init(&p->nicerr, 0, DT_REAL, _state, make_automatic);
45171 0 : ae_vector_init(&p->nicnact, 0, DT_INT, _state, make_automatic);
45172 0 : }
45173 :
45174 :
45175 0 : void _qpdenseaulbuffers_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
45176 : {
45177 0 : qpdenseaulbuffers *dst = (qpdenseaulbuffers*)_dst;
45178 0 : qpdenseaulbuffers *src = (qpdenseaulbuffers*)_src;
45179 0 : ae_vector_init_copy(&dst->nulc, &src->nulc, _state, make_automatic);
45180 0 : ae_matrix_init_copy(&dst->sclsfta, &src->sclsfta, _state, make_automatic);
45181 0 : ae_vector_init_copy(&dst->sclsftb, &src->sclsftb, _state, make_automatic);
45182 0 : ae_vector_init_copy(&dst->sclsfthasbndl, &src->sclsfthasbndl, _state, make_automatic);
45183 0 : ae_vector_init_copy(&dst->sclsfthasbndu, &src->sclsfthasbndu, _state, make_automatic);
45184 0 : ae_vector_init_copy(&dst->sclsftbndl, &src->sclsftbndl, _state, make_automatic);
45185 0 : ae_vector_init_copy(&dst->sclsftbndu, &src->sclsftbndu, _state, make_automatic);
45186 0 : ae_vector_init_copy(&dst->sclsftxc, &src->sclsftxc, _state, make_automatic);
45187 0 : ae_matrix_init_copy(&dst->sclsftcleic, &src->sclsftcleic, _state, make_automatic);
45188 0 : ae_vector_init_copy(&dst->cidx, &src->cidx, _state, make_automatic);
45189 0 : ae_vector_init_copy(&dst->cscales, &src->cscales, _state, make_automatic);
45190 0 : ae_matrix_init_copy(&dst->exa, &src->exa, _state, make_automatic);
45191 0 : ae_vector_init_copy(&dst->exb, &src->exb, _state, make_automatic);
45192 0 : ae_vector_init_copy(&dst->exxc, &src->exxc, _state, make_automatic);
45193 0 : ae_vector_init_copy(&dst->exbndl, &src->exbndl, _state, make_automatic);
45194 0 : ae_vector_init_copy(&dst->exbndu, &src->exbndu, _state, make_automatic);
45195 0 : ae_vector_init_copy(&dst->exscale, &src->exscale, _state, make_automatic);
45196 0 : ae_vector_init_copy(&dst->exxorigin, &src->exxorigin, _state, make_automatic);
45197 0 : _qqpsettings_init_copy(&dst->qqpsettingsuser, &src->qqpsettingsuser, _state, make_automatic);
45198 0 : _qqpbuffers_init_copy(&dst->qqpbuf, &src->qqpbuf, _state, make_automatic);
45199 0 : ae_vector_init_copy(&dst->nulcest, &src->nulcest, _state, make_automatic);
45200 0 : ae_vector_init_copy(&dst->tmpg, &src->tmpg, _state, make_automatic);
45201 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
45202 0 : ae_matrix_init_copy(&dst->tmp2, &src->tmp2, _state, make_automatic);
45203 0 : ae_vector_init_copy(&dst->modelg, &src->modelg, _state, make_automatic);
45204 0 : ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic);
45205 0 : ae_vector_init_copy(&dst->deltax, &src->deltax, _state, make_automatic);
45206 0 : _convexquadraticmodel_init_copy(&dst->dummycqm, &src->dummycqm, _state, make_automatic);
45207 0 : _sparsematrix_init_copy(&dst->dummysparse, &src->dummysparse, _state, make_automatic);
45208 0 : ae_matrix_init_copy(&dst->qrkkt, &src->qrkkt, _state, make_automatic);
45209 0 : ae_vector_init_copy(&dst->qrrightpart, &src->qrrightpart, _state, make_automatic);
45210 0 : ae_vector_init_copy(&dst->qrtau, &src->qrtau, _state, make_automatic);
45211 0 : ae_vector_init_copy(&dst->qrsv0, &src->qrsv0, _state, make_automatic);
45212 0 : ae_vector_init_copy(&dst->qrsvx1, &src->qrsvx1, _state, make_automatic);
45213 0 : ae_vector_init_copy(&dst->nicerr, &src->nicerr, _state, make_automatic);
45214 0 : ae_vector_init_copy(&dst->nicnact, &src->nicnact, _state, make_automatic);
45215 0 : dst->repinneriterationscount = src->repinneriterationscount;
45216 0 : dst->repouteriterationscount = src->repouteriterationscount;
45217 0 : dst->repncholesky = src->repncholesky;
45218 0 : dst->repnwrkchanges = src->repnwrkchanges;
45219 0 : dst->repnwrk0 = src->repnwrk0;
45220 0 : dst->repnwrk1 = src->repnwrk1;
45221 0 : dst->repnwrkf = src->repnwrkf;
45222 0 : dst->repnmv = src->repnmv;
45223 0 : }
45224 :
45225 :
45226 0 : void _qpdenseaulbuffers_clear(void* _p)
45227 : {
45228 0 : qpdenseaulbuffers *p = (qpdenseaulbuffers*)_p;
45229 0 : ae_touch_ptr((void*)p);
45230 0 : ae_vector_clear(&p->nulc);
45231 0 : ae_matrix_clear(&p->sclsfta);
45232 0 : ae_vector_clear(&p->sclsftb);
45233 0 : ae_vector_clear(&p->sclsfthasbndl);
45234 0 : ae_vector_clear(&p->sclsfthasbndu);
45235 0 : ae_vector_clear(&p->sclsftbndl);
45236 0 : ae_vector_clear(&p->sclsftbndu);
45237 0 : ae_vector_clear(&p->sclsftxc);
45238 0 : ae_matrix_clear(&p->sclsftcleic);
45239 0 : ae_vector_clear(&p->cidx);
45240 0 : ae_vector_clear(&p->cscales);
45241 0 : ae_matrix_clear(&p->exa);
45242 0 : ae_vector_clear(&p->exb);
45243 0 : ae_vector_clear(&p->exxc);
45244 0 : ae_vector_clear(&p->exbndl);
45245 0 : ae_vector_clear(&p->exbndu);
45246 0 : ae_vector_clear(&p->exscale);
45247 0 : ae_vector_clear(&p->exxorigin);
45248 0 : _qqpsettings_clear(&p->qqpsettingsuser);
45249 0 : _qqpbuffers_clear(&p->qqpbuf);
45250 0 : ae_vector_clear(&p->nulcest);
45251 0 : ae_vector_clear(&p->tmpg);
45252 0 : ae_vector_clear(&p->tmp0);
45253 0 : ae_matrix_clear(&p->tmp2);
45254 0 : ae_vector_clear(&p->modelg);
45255 0 : ae_vector_clear(&p->d);
45256 0 : ae_vector_clear(&p->deltax);
45257 0 : _convexquadraticmodel_clear(&p->dummycqm);
45258 0 : _sparsematrix_clear(&p->dummysparse);
45259 0 : ae_matrix_clear(&p->qrkkt);
45260 0 : ae_vector_clear(&p->qrrightpart);
45261 0 : ae_vector_clear(&p->qrtau);
45262 0 : ae_vector_clear(&p->qrsv0);
45263 0 : ae_vector_clear(&p->qrsvx1);
45264 0 : ae_vector_clear(&p->nicerr);
45265 0 : ae_vector_clear(&p->nicnact);
45266 0 : }
45267 :
45268 :
45269 0 : void _qpdenseaulbuffers_destroy(void* _p)
45270 : {
45271 0 : qpdenseaulbuffers *p = (qpdenseaulbuffers*)_p;
45272 0 : ae_touch_ptr((void*)p);
45273 0 : ae_vector_destroy(&p->nulc);
45274 0 : ae_matrix_destroy(&p->sclsfta);
45275 0 : ae_vector_destroy(&p->sclsftb);
45276 0 : ae_vector_destroy(&p->sclsfthasbndl);
45277 0 : ae_vector_destroy(&p->sclsfthasbndu);
45278 0 : ae_vector_destroy(&p->sclsftbndl);
45279 0 : ae_vector_destroy(&p->sclsftbndu);
45280 0 : ae_vector_destroy(&p->sclsftxc);
45281 0 : ae_matrix_destroy(&p->sclsftcleic);
45282 0 : ae_vector_destroy(&p->cidx);
45283 0 : ae_vector_destroy(&p->cscales);
45284 0 : ae_matrix_destroy(&p->exa);
45285 0 : ae_vector_destroy(&p->exb);
45286 0 : ae_vector_destroy(&p->exxc);
45287 0 : ae_vector_destroy(&p->exbndl);
45288 0 : ae_vector_destroy(&p->exbndu);
45289 0 : ae_vector_destroy(&p->exscale);
45290 0 : ae_vector_destroy(&p->exxorigin);
45291 0 : _qqpsettings_destroy(&p->qqpsettingsuser);
45292 0 : _qqpbuffers_destroy(&p->qqpbuf);
45293 0 : ae_vector_destroy(&p->nulcest);
45294 0 : ae_vector_destroy(&p->tmpg);
45295 0 : ae_vector_destroy(&p->tmp0);
45296 0 : ae_matrix_destroy(&p->tmp2);
45297 0 : ae_vector_destroy(&p->modelg);
45298 0 : ae_vector_destroy(&p->d);
45299 0 : ae_vector_destroy(&p->deltax);
45300 0 : _convexquadraticmodel_destroy(&p->dummycqm);
45301 0 : _sparsematrix_destroy(&p->dummysparse);
45302 0 : ae_matrix_destroy(&p->qrkkt);
45303 0 : ae_vector_destroy(&p->qrrightpart);
45304 0 : ae_vector_destroy(&p->qrtau);
45305 0 : ae_vector_destroy(&p->qrsv0);
45306 0 : ae_vector_destroy(&p->qrsvx1);
45307 0 : ae_vector_destroy(&p->nicerr);
45308 0 : ae_vector_destroy(&p->nicnact);
45309 0 : }
45310 :
45311 :
45312 : #endif
45313 : #if defined(AE_COMPILE_MINBLEIC) || !defined(AE_PARTIAL_BUILD)
45314 :
45315 :
45316 : /*************************************************************************
45317 : BOUND CONSTRAINED OPTIMIZATION
45318 : WITH ADDITIONAL LINEAR EQUALITY AND INEQUALITY CONSTRAINTS
45319 :
45320 : DESCRIPTION:
45321 : The subroutine minimizes function F(x) of N arguments subject to any
45322 : combination of:
45323 : * bound constraints
45324 : * linear inequality constraints
45325 : * linear equality constraints
45326 :
45327 : REQUIREMENTS:
45328 : * user must provide function value and gradient
45329 : * starting point X0 must be feasible or
45330 : not too far away from the feasible set
45331 : * grad(f) must be Lipschitz continuous on a level set:
45332 : L = { x : f(x)<=f(x0) }
45333 : * function must be defined everywhere on the feasible set F
45334 :
45335 : USAGE:
45336 :
45337 : Constrained optimization if far more complex than the unconstrained one.
45338 : Here we give very brief outline of the BLEIC optimizer. We strongly recommend
45339 : you to read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide
45340 : on optimization, which is available at http://www.alglib.net/optimization/
45341 :
45342 : 1. User initializes algorithm state with MinBLEICCreate() call
45343 :
45344 : 2. USer adds boundary and/or linear constraints by calling
45345 : MinBLEICSetBC() and MinBLEICSetLC() functions.
45346 :
45347 : 3. User sets stopping conditions with MinBLEICSetCond().
45348 :
45349 : 4. User calls MinBLEICOptimize() function which takes algorithm state and
45350 : pointer (delegate, etc.) to callback function which calculates F/G.
45351 :
45352 : 5. User calls MinBLEICResults() to get solution
45353 :
45354 : 6. Optionally user may call MinBLEICRestartFrom() to solve another problem
45355 : with same N but another starting point.
45356 : MinBLEICRestartFrom() allows to reuse already initialized structure.
45357 :
45358 : NOTE: if you have box-only constraints (no general linear constraints),
45359 : then MinBC optimizer can be better option. It uses special, faster
45360 : constraint activation method, which performs better on problems with
45361 : multiple constraints active at the solution.
45362 :
45363 : On small-scale problems performance of MinBC is similar to that of
45364 : MinBLEIC, but on large-scale ones (hundreds and thousands of active
45365 : constraints) it can be several times faster than MinBLEIC.
45366 :
45367 : INPUT PARAMETERS:
45368 : N - problem dimension, N>0:
45369 : * if given, only leading N elements of X are used
45370 : * if not given, automatically determined from size ofX
45371 : X - starting point, array[N]:
45372 : * it is better to set X to a feasible point
45373 : * but X can be infeasible, in which case algorithm will try
45374 : to find feasible point first, using X as initial
45375 : approximation.
45376 :
45377 : OUTPUT PARAMETERS:
45378 : State - structure stores algorithm state
45379 :
45380 : -- ALGLIB --
45381 : Copyright 28.11.2010 by Bochkanov Sergey
45382 : *************************************************************************/
45383 0 : void minbleiccreate(ae_int_t n,
45384 : /* Real */ ae_vector* x,
45385 : minbleicstate* state,
45386 : ae_state *_state)
45387 : {
45388 : ae_frame _frame_block;
45389 : ae_matrix c;
45390 : ae_vector ct;
45391 :
45392 0 : ae_frame_make(_state, &_frame_block);
45393 0 : memset(&c, 0, sizeof(c));
45394 0 : memset(&ct, 0, sizeof(ct));
45395 0 : _minbleicstate_clear(state);
45396 0 : ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
45397 0 : ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
45398 :
45399 0 : ae_assert(n>=1, "MinBLEICCreate: N<1", _state);
45400 0 : ae_assert(x->cnt>=n, "MinBLEICCreate: Length(X)<N", _state);
45401 0 : ae_assert(isfinitevector(x, n, _state), "MinBLEICCreate: X contains infinite or NaN values!", _state);
45402 0 : minbleic_minbleicinitinternal(n, x, 0.0, state, _state);
45403 0 : ae_frame_leave(_state);
45404 0 : }
45405 :
45406 :
45407 : /*************************************************************************
45408 : The subroutine is finite difference variant of MinBLEICCreate(). It uses
45409 : finite differences in order to differentiate target function.
45410 :
45411 : Description below contains information which is specific to this function
45412 : only. We recommend to read comments on MinBLEICCreate() in order to get
45413 : more information about creation of BLEIC optimizer.
45414 :
45415 : INPUT PARAMETERS:
45416 : N - problem dimension, N>0:
45417 : * if given, only leading N elements of X are used
45418 : * if not given, automatically determined from size of X
45419 : X - starting point, array[0..N-1].
45420 : DiffStep- differentiation step, >0
45421 :
45422 : OUTPUT PARAMETERS:
45423 : State - structure which stores algorithm state
45424 :
45425 : NOTES:
45426 : 1. algorithm uses 4-point central formula for differentiation.
45427 : 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
45428 : S[] is scaling vector which can be set by MinBLEICSetScale() call.
45429 : 3. we recommend you to use moderate values of differentiation step. Too
45430 : large step will result in too large truncation errors, while too small
45431 : step will result in too large numerical errors. 1.0E-6 can be good
45432 : value to start with.
45433 : 4. Numerical differentiation is very inefficient - one gradient
45434 : calculation needs 4*N function evaluations. This function will work for
45435 : any N - either small (1...10), moderate (10...100) or large (100...).
45436 : However, performance penalty will be too severe for any N's except for
45437 : small ones.
45438 : We should also say that code which relies on numerical differentiation
45439 : is less robust and precise. CG needs exact gradient values. Imprecise
45440 : gradient may slow down convergence, especially on highly nonlinear
45441 : problems.
45442 : Thus we recommend to use this function for fast prototyping on small-
45443 : dimensional problems only, and to implement analytical gradient as soon
45444 : as possible.
45445 :
45446 : -- ALGLIB --
45447 : Copyright 16.05.2011 by Bochkanov Sergey
45448 : *************************************************************************/
45449 0 : void minbleiccreatef(ae_int_t n,
45450 : /* Real */ ae_vector* x,
45451 : double diffstep,
45452 : minbleicstate* state,
45453 : ae_state *_state)
45454 : {
45455 : ae_frame _frame_block;
45456 : ae_matrix c;
45457 : ae_vector ct;
45458 :
45459 0 : ae_frame_make(_state, &_frame_block);
45460 0 : memset(&c, 0, sizeof(c));
45461 0 : memset(&ct, 0, sizeof(ct));
45462 0 : _minbleicstate_clear(state);
45463 0 : ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
45464 0 : ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
45465 :
45466 0 : ae_assert(n>=1, "MinBLEICCreateF: N<1", _state);
45467 0 : ae_assert(x->cnt>=n, "MinBLEICCreateF: Length(X)<N", _state);
45468 0 : ae_assert(isfinitevector(x, n, _state), "MinBLEICCreateF: X contains infinite or NaN values!", _state);
45469 0 : ae_assert(ae_isfinite(diffstep, _state), "MinBLEICCreateF: DiffStep is infinite or NaN!", _state);
45470 0 : ae_assert(ae_fp_greater(diffstep,(double)(0)), "MinBLEICCreateF: DiffStep is non-positive!", _state);
45471 0 : minbleic_minbleicinitinternal(n, x, diffstep, state, _state);
45472 0 : ae_frame_leave(_state);
45473 0 : }
45474 :
45475 :
45476 : /*************************************************************************
45477 : This function sets boundary constraints for BLEIC optimizer.
45478 :
45479 : Boundary constraints are inactive by default (after initial creation).
45480 : They are preserved after algorithm restart with MinBLEICRestartFrom().
45481 :
45482 : NOTE: if you have box-only constraints (no general linear constraints),
45483 : then MinBC optimizer can be better option. It uses special, faster
45484 : constraint activation method, which performs better on problems with
45485 : multiple constraints active at the solution.
45486 :
45487 : On small-scale problems performance of MinBC is similar to that of
45488 : MinBLEIC, but on large-scale ones (hundreds and thousands of active
45489 : constraints) it can be several times faster than MinBLEIC.
45490 :
45491 : INPUT PARAMETERS:
45492 : State - structure stores algorithm state
45493 : BndL - lower bounds, array[N].
45494 : If some (all) variables are unbounded, you may specify
45495 : very small number or -INF.
45496 : BndU - upper bounds, array[N].
45497 : If some (all) variables are unbounded, you may specify
45498 : very large number or +INF.
45499 :
45500 : NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th
45501 : variable will be "frozen" at X[i]=BndL[i]=BndU[i].
45502 :
45503 : NOTE 2: this solver has following useful properties:
45504 : * bound constraints are always satisfied exactly
45505 : * function is evaluated only INSIDE area specified by bound constraints,
45506 : even when numerical differentiation is used (algorithm adjusts nodes
45507 : according to boundary constraints)
45508 :
45509 : -- ALGLIB --
45510 : Copyright 28.11.2010 by Bochkanov Sergey
45511 : *************************************************************************/
45512 0 : void minbleicsetbc(minbleicstate* state,
45513 : /* Real */ ae_vector* bndl,
45514 : /* Real */ ae_vector* bndu,
45515 : ae_state *_state)
45516 : {
45517 : ae_int_t i;
45518 : ae_int_t n;
45519 :
45520 :
45521 0 : n = state->nmain;
45522 0 : ae_assert(bndl->cnt>=n, "MinBLEICSetBC: Length(BndL)<N", _state);
45523 0 : ae_assert(bndu->cnt>=n, "MinBLEICSetBC: Length(BndU)<N", _state);
45524 0 : for(i=0; i<=n-1; i++)
45525 : {
45526 0 : 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);
45527 0 : 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);
45528 0 : state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i];
45529 0 : state->hasbndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state);
45530 0 : state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i];
45531 0 : state->hasbndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state);
45532 : }
45533 0 : sassetbc(&state->sas, bndl, bndu, _state);
45534 0 : }
45535 :
45536 :
45537 : /*************************************************************************
45538 : This function sets linear constraints for BLEIC optimizer.
45539 :
45540 : Linear constraints are inactive by default (after initial creation).
45541 : They are preserved after algorithm restart with MinBLEICRestartFrom().
45542 :
45543 : INPUT PARAMETERS:
45544 : State - structure previously allocated with MinBLEICCreate call.
45545 : C - linear constraints, array[K,N+1].
45546 : Each row of C represents one constraint, either equality
45547 : or inequality (see below):
45548 : * first N elements correspond to coefficients,
45549 : * last element corresponds to the right part.
45550 : All elements of C (including right part) must be finite.
45551 : CT - type of constraints, array[K]:
45552 : * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n]
45553 : * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n]
45554 : * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n]
45555 : K - number of equality/inequality constraints, K>=0:
45556 : * if given, only leading K elements of C/CT are used
45557 : * if not given, automatically determined from sizes of C/CT
45558 :
45559 : NOTE 1: linear (non-bound) constraints are satisfied only approximately:
45560 : * there always exists some minor violation (about Epsilon in magnitude)
45561 : due to rounding errors
45562 : * numerical differentiation, if used, may lead to function evaluations
45563 : outside of the feasible area, because algorithm does NOT change
45564 : numerical differentiation formula according to linear constraints.
45565 : If you want constraints to be satisfied exactly, try to reformulate your
45566 : problem in such manner that all constraints will become boundary ones
45567 : (this kind of constraints is always satisfied exactly, both in the final
45568 : solution and in all intermediate points).
45569 :
45570 : -- ALGLIB --
45571 : Copyright 28.11.2010 by Bochkanov Sergey
45572 : *************************************************************************/
45573 0 : void minbleicsetlc(minbleicstate* state,
45574 : /* Real */ ae_matrix* c,
45575 : /* Integer */ ae_vector* ct,
45576 : ae_int_t k,
45577 : ae_state *_state)
45578 : {
45579 : ae_int_t n;
45580 : ae_int_t i;
45581 : ae_int_t j;
45582 : double v;
45583 :
45584 :
45585 0 : n = state->nmain;
45586 :
45587 : /*
45588 : * First, check for errors in the inputs
45589 : */
45590 0 : ae_assert(k>=0, "MinBLEICSetLC: K<0", _state);
45591 0 : ae_assert(c->cols>=n+1||k==0, "MinBLEICSetLC: Cols(C)<N+1", _state);
45592 0 : ae_assert(c->rows>=k, "MinBLEICSetLC: Rows(C)<K", _state);
45593 0 : ae_assert(ct->cnt>=k, "MinBLEICSetLC: Length(CT)<K", _state);
45594 0 : ae_assert(apservisfinitematrix(c, k, n+1, _state), "MinBLEICSetLC: C contains infinite or NaN values!", _state);
45595 :
45596 : /*
45597 : * Handle zero K
45598 : */
45599 0 : if( k==0 )
45600 : {
45601 0 : state->nec = 0;
45602 0 : state->nic = 0;
45603 0 : sassetlc(&state->sas, c, ct, 0, _state);
45604 0 : return;
45605 : }
45606 :
45607 : /*
45608 : * Equality constraints are stored first, in the upper
45609 : * NEC rows of State.CLEIC matrix. Inequality constraints
45610 : * are stored in the next NIC rows.
45611 : *
45612 : * NOTE: we convert inequality constraints to the form
45613 : * A*x<=b before copying them.
45614 : */
45615 0 : rmatrixsetlengthatleast(&state->cleic, k, n+1, _state);
45616 0 : state->nec = 0;
45617 0 : state->nic = 0;
45618 0 : for(i=0; i<=k-1; i++)
45619 : {
45620 0 : if( ct->ptr.p_int[i]==0 )
45621 : {
45622 0 : ae_v_move(&state->cleic.ptr.pp_double[state->nec][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n));
45623 0 : state->nec = state->nec+1;
45624 : }
45625 : }
45626 0 : for(i=0; i<=k-1; i++)
45627 : {
45628 0 : if( ct->ptr.p_int[i]!=0 )
45629 : {
45630 0 : if( ct->ptr.p_int[i]>0 )
45631 : {
45632 0 : 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));
45633 : }
45634 : else
45635 : {
45636 0 : 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));
45637 : }
45638 0 : state->nic = state->nic+1;
45639 : }
45640 : }
45641 :
45642 : /*
45643 : * Normalize rows of State.CLEIC: each row must have unit norm.
45644 : * Norm is calculated using first N elements (i.e. right part is
45645 : * not counted when we calculate norm).
45646 : */
45647 0 : for(i=0; i<=k-1; i++)
45648 : {
45649 0 : v = (double)(0);
45650 0 : for(j=0; j<=n-1; j++)
45651 : {
45652 0 : v = v+ae_sqr(state->cleic.ptr.pp_double[i][j], _state);
45653 : }
45654 0 : if( ae_fp_eq(v,(double)(0)) )
45655 : {
45656 0 : continue;
45657 : }
45658 0 : v = 1/ae_sqrt(v, _state);
45659 0 : ae_v_muld(&state->cleic.ptr.pp_double[i][0], 1, ae_v_len(0,n), v);
45660 : }
45661 0 : sassetlc(&state->sas, c, ct, k, _state);
45662 : }
45663 :
45664 :
45665 : /*************************************************************************
45666 : This function sets stopping conditions for the optimizer.
45667 :
45668 : INPUT PARAMETERS:
45669 : State - structure which stores algorithm state
45670 : EpsG - >=0
45671 : The subroutine finishes its work if the condition
45672 : |v|<EpsG is satisfied, where:
45673 : * |.| means Euclidian norm
45674 : * v - scaled gradient vector, v[i]=g[i]*s[i]
45675 : * g - gradient
45676 : * s - scaling coefficients set by MinBLEICSetScale()
45677 : EpsF - >=0
45678 : The subroutine finishes its work if on k+1-th iteration
45679 : the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
45680 : is satisfied.
45681 : EpsX - >=0
45682 : The subroutine finishes its work if on k+1-th iteration
45683 : the condition |v|<=EpsX is fulfilled, where:
45684 : * |.| means Euclidian norm
45685 : * v - scaled step vector, v[i]=dx[i]/s[i]
45686 : * dx - step vector, dx=X(k+1)-X(k)
45687 : * s - scaling coefficients set by MinBLEICSetScale()
45688 : MaxIts - maximum number of iterations. If MaxIts=0, the number of
45689 : iterations is unlimited.
45690 :
45691 : Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead
45692 : to automatic stopping criterion selection.
45693 :
45694 : NOTE: when SetCond() called with non-zero MaxIts, BLEIC solver may perform
45695 : slightly more than MaxIts iterations. I.e., MaxIts sets non-strict
45696 : limit on iterations count.
45697 :
45698 : -- ALGLIB --
45699 : Copyright 28.11.2010 by Bochkanov Sergey
45700 : *************************************************************************/
45701 0 : void minbleicsetcond(minbleicstate* state,
45702 : double epsg,
45703 : double epsf,
45704 : double epsx,
45705 : ae_int_t maxits,
45706 : ae_state *_state)
45707 : {
45708 :
45709 :
45710 0 : ae_assert(ae_isfinite(epsg, _state), "MinBLEICSetCond: EpsG is not finite number", _state);
45711 0 : ae_assert(ae_fp_greater_eq(epsg,(double)(0)), "MinBLEICSetCond: negative EpsG", _state);
45712 0 : ae_assert(ae_isfinite(epsf, _state), "MinBLEICSetCond: EpsF is not finite number", _state);
45713 0 : ae_assert(ae_fp_greater_eq(epsf,(double)(0)), "MinBLEICSetCond: negative EpsF", _state);
45714 0 : ae_assert(ae_isfinite(epsx, _state), "MinBLEICSetCond: EpsX is not finite number", _state);
45715 0 : ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "MinBLEICSetCond: negative EpsX", _state);
45716 0 : ae_assert(maxits>=0, "MinBLEICSetCond: negative MaxIts!", _state);
45717 0 : if( ((ae_fp_eq(epsg,(double)(0))&&ae_fp_eq(epsf,(double)(0)))&&ae_fp_eq(epsx,(double)(0)))&&maxits==0 )
45718 : {
45719 0 : epsx = 1.0E-6;
45720 : }
45721 0 : state->epsg = epsg;
45722 0 : state->epsf = epsf;
45723 0 : state->epsx = epsx;
45724 0 : state->maxits = maxits;
45725 0 : }
45726 :
45727 :
45728 : /*************************************************************************
45729 : This function sets scaling coefficients for BLEIC optimizer.
45730 :
45731 : ALGLIB optimizers use scaling matrices to test stopping conditions (step
45732 : size and gradient are scaled before comparison with tolerances). Scale of
45733 : the I-th variable is a translation invariant measure of:
45734 : a) "how large" the variable is
45735 : b) how large the step should be to make significant changes in the function
45736 :
45737 : Scaling is also used by finite difference variant of the optimizer - step
45738 : along I-th axis is equal to DiffStep*S[I].
45739 :
45740 : In most optimizers (and in the BLEIC too) scaling is NOT a form of
45741 : preconditioning. It just affects stopping conditions. You should set
45742 : preconditioner by separate call to one of the MinBLEICSetPrec...()
45743 : functions.
45744 :
45745 : There is a special preconditioning mode, however, which uses scaling
45746 : coefficients to form diagonal preconditioning matrix. You can turn this
45747 : mode on, if you want. But you should understand that scaling is not the
45748 : same thing as preconditioning - these are two different, although related
45749 : forms of tuning solver.
45750 :
45751 : INPUT PARAMETERS:
45752 : State - structure stores algorithm state
45753 : S - array[N], non-zero scaling coefficients
45754 : S[i] may be negative, sign doesn't matter.
45755 :
45756 : -- ALGLIB --
45757 : Copyright 14.01.2011 by Bochkanov Sergey
45758 : *************************************************************************/
45759 0 : void minbleicsetscale(minbleicstate* state,
45760 : /* Real */ ae_vector* s,
45761 : ae_state *_state)
45762 : {
45763 : ae_int_t i;
45764 :
45765 :
45766 0 : ae_assert(s->cnt>=state->nmain, "MinBLEICSetScale: Length(S)<N", _state);
45767 0 : for(i=0; i<=state->nmain-1; i++)
45768 : {
45769 0 : ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "MinBLEICSetScale: S contains infinite or NAN elements", _state);
45770 0 : ae_assert(ae_fp_neq(s->ptr.p_double[i],(double)(0)), "MinBLEICSetScale: S contains zero elements", _state);
45771 0 : state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state);
45772 : }
45773 0 : sassetscale(&state->sas, s, _state);
45774 0 : }
45775 :
45776 :
45777 : /*************************************************************************
45778 : Modification of the preconditioner: preconditioning is turned off.
45779 :
45780 : INPUT PARAMETERS:
45781 : State - structure which stores algorithm state
45782 :
45783 : -- ALGLIB --
45784 : Copyright 13.10.2010 by Bochkanov Sergey
45785 : *************************************************************************/
45786 0 : void minbleicsetprecdefault(minbleicstate* state, ae_state *_state)
45787 : {
45788 :
45789 :
45790 0 : state->prectype = 0;
45791 0 : }
45792 :
45793 :
45794 : /*************************************************************************
45795 : Modification of the preconditioner: diagonal of approximate Hessian is
45796 : used.
45797 :
45798 : INPUT PARAMETERS:
45799 : State - structure which stores algorithm state
45800 : D - diagonal of the approximate Hessian, array[0..N-1],
45801 : (if larger, only leading N elements are used).
45802 :
45803 : NOTE 1: D[i] should be positive. Exception will be thrown otherwise.
45804 :
45805 : NOTE 2: you should pass diagonal of approximate Hessian - NOT ITS INVERSE.
45806 :
45807 : -- ALGLIB --
45808 : Copyright 13.10.2010 by Bochkanov Sergey
45809 : *************************************************************************/
45810 0 : void minbleicsetprecdiag(minbleicstate* state,
45811 : /* Real */ ae_vector* d,
45812 : ae_state *_state)
45813 : {
45814 : ae_int_t i;
45815 :
45816 :
45817 0 : ae_assert(d->cnt>=state->nmain, "MinBLEICSetPrecDiag: D is too short", _state);
45818 0 : for(i=0; i<=state->nmain-1; i++)
45819 : {
45820 0 : ae_assert(ae_isfinite(d->ptr.p_double[i], _state), "MinBLEICSetPrecDiag: D contains infinite or NAN elements", _state);
45821 0 : ae_assert(ae_fp_greater(d->ptr.p_double[i],(double)(0)), "MinBLEICSetPrecDiag: D contains non-positive elements", _state);
45822 : }
45823 0 : rvectorsetlengthatleast(&state->diagh, state->nmain, _state);
45824 0 : state->prectype = 2;
45825 0 : for(i=0; i<=state->nmain-1; i++)
45826 : {
45827 0 : state->diagh.ptr.p_double[i] = d->ptr.p_double[i];
45828 : }
45829 0 : }
45830 :
45831 :
45832 : /*************************************************************************
45833 : Modification of the preconditioner: scale-based diagonal preconditioning.
45834 :
45835 : This preconditioning mode can be useful when you don't have approximate
45836 : diagonal of Hessian, but you know that your variables are badly scaled
45837 : (for example, one variable is in [1,10], and another in [1000,100000]),
45838 : and most part of the ill-conditioning comes from different scales of vars.
45839 :
45840 : In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2),
45841 : can greatly improve convergence.
45842 :
45843 : IMPRTANT: you should set scale of your variables with MinBLEICSetScale()
45844 : call (before or after MinBLEICSetPrecScale() call). Without knowledge of
45845 : the scale of your variables scale-based preconditioner will be just unit
45846 : matrix.
45847 :
45848 : INPUT PARAMETERS:
45849 : State - structure which stores algorithm state
45850 :
45851 : -- ALGLIB --
45852 : Copyright 13.10.2010 by Bochkanov Sergey
45853 : *************************************************************************/
45854 0 : void minbleicsetprecscale(minbleicstate* state, ae_state *_state)
45855 : {
45856 :
45857 :
45858 0 : state->prectype = 3;
45859 0 : }
45860 :
45861 :
45862 : /*************************************************************************
45863 : This function turns on/off reporting.
45864 :
45865 : INPUT PARAMETERS:
45866 : State - structure which stores algorithm state
45867 : NeedXRep- whether iteration reports are needed or not
45868 :
45869 : If NeedXRep is True, algorithm will call rep() callback function if it is
45870 : provided to MinBLEICOptimize().
45871 :
45872 : -- ALGLIB --
45873 : Copyright 28.11.2010 by Bochkanov Sergey
45874 : *************************************************************************/
45875 0 : void minbleicsetxrep(minbleicstate* state,
45876 : ae_bool needxrep,
45877 : ae_state *_state)
45878 : {
45879 :
45880 :
45881 0 : state->xrep = needxrep;
45882 0 : }
45883 :
45884 :
45885 : /*************************************************************************
45886 : This function turns on/off line search reports.
45887 : These reports are described in more details in developer-only comments on
45888 : MinBLEICState object.
45889 :
45890 : INPUT PARAMETERS:
45891 : State - structure which stores algorithm state
45892 : NeedDRep- whether line search reports are needed or not
45893 :
45894 : This function is intended for private use only. Turning it on artificially
45895 : may cause program failure.
45896 :
45897 : -- ALGLIB --
45898 : Copyright 02.04.2010 by Bochkanov Sergey
45899 : *************************************************************************/
45900 0 : void minbleicsetdrep(minbleicstate* state,
45901 : ae_bool needdrep,
45902 : ae_state *_state)
45903 : {
45904 :
45905 :
45906 0 : state->drep = needdrep;
45907 0 : }
45908 :
45909 :
45910 : /*************************************************************************
45911 : This function sets maximum step length
45912 :
45913 : IMPORTANT: this feature is hard to combine with preconditioning. You can't
45914 : set upper limit on step length, when you solve optimization problem with
45915 : linear (non-boundary) constraints AND preconditioner turned on.
45916 :
45917 : When non-boundary constraints are present, you have to either a) use
45918 : preconditioner, or b) use upper limit on step length. YOU CAN'T USE BOTH!
45919 : In this case algorithm will terminate with appropriate error code.
45920 :
45921 : INPUT PARAMETERS:
45922 : State - structure which stores algorithm state
45923 : StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't
45924 : want to limit step length.
45925 :
45926 : Use this subroutine when you optimize target function which contains exp()
45927 : or other fast growing functions, and optimization algorithm makes too
45928 : large steps which lead to overflow. This function allows us to reject
45929 : steps that are too large (and therefore expose us to the possible
45930 : overflow) without actually calculating function value at the x+stp*d.
45931 :
45932 : -- ALGLIB --
45933 : Copyright 02.04.2010 by Bochkanov Sergey
45934 : *************************************************************************/
45935 0 : void minbleicsetstpmax(minbleicstate* state,
45936 : double stpmax,
45937 : ae_state *_state)
45938 : {
45939 :
45940 :
45941 0 : ae_assert(ae_isfinite(stpmax, _state), "MinBLEICSetStpMax: StpMax is not finite!", _state);
45942 0 : ae_assert(ae_fp_greater_eq(stpmax,(double)(0)), "MinBLEICSetStpMax: StpMax<0!", _state);
45943 0 : state->stpmax = stpmax;
45944 0 : }
45945 :
45946 :
45947 : /*************************************************************************
45948 : NOTES:
45949 :
45950 : 1. This function has two different implementations: one which uses exact
45951 : (analytical) user-supplied gradient, and one which uses function value
45952 : only and numerically differentiates function in order to obtain
45953 : gradient.
45954 :
45955 : Depending on the specific function used to create optimizer object
45956 : (either MinBLEICCreate() for analytical gradient or MinBLEICCreateF()
45957 : for numerical differentiation) you should choose appropriate variant of
45958 : MinBLEICOptimize() - one which accepts function AND gradient or one
45959 : which accepts function ONLY.
45960 :
45961 : Be careful to choose variant of MinBLEICOptimize() which corresponds to
45962 : your optimization scheme! Table below lists different combinations of
45963 : callback (function/gradient) passed to MinBLEICOptimize() and specific
45964 : function used to create optimizer.
45965 :
45966 :
45967 : | USER PASSED TO MinBLEICOptimize()
45968 : CREATED WITH | function only | function and gradient
45969 : ------------------------------------------------------------
45970 : MinBLEICCreateF() | work FAIL
45971 : MinBLEICCreate() | FAIL work
45972 :
45973 : Here "FAIL" denotes inappropriate combinations of optimizer creation
45974 : function and MinBLEICOptimize() version. Attemps to use such
45975 : combination (for example, to create optimizer with MinBLEICCreateF()
45976 : and to pass gradient information to MinBLEICOptimize()) will lead to
45977 : exception being thrown. Either you did not pass gradient when it WAS
45978 : needed or you passed gradient when it was NOT needed.
45979 :
45980 : -- ALGLIB --
45981 : Copyright 28.11.2010 by Bochkanov Sergey
45982 : *************************************************************************/
45983 0 : ae_bool minbleiciteration(minbleicstate* state, ae_state *_state)
45984 : {
45985 : ae_int_t n;
45986 : ae_int_t m;
45987 : ae_int_t i;
45988 : ae_int_t j;
45989 : double v;
45990 : double vv;
45991 : double v0;
45992 : ae_bool b;
45993 : ae_int_t mcinfo;
45994 : ae_int_t actstatus;
45995 : ae_int_t itidx;
45996 : double penalty;
45997 : double ginit;
45998 : double gdecay;
45999 : ae_bool result;
46000 :
46001 :
46002 :
46003 : /*
46004 : * Reverse communication preparations
46005 : * I know it looks ugly, but it works the same way
46006 : * anywhere from C++ to Python.
46007 : *
46008 : * This code initializes locals by:
46009 : * * random values determined during code
46010 : * generation - on first subroutine call
46011 : * * values from previous call - on subsequent calls
46012 : */
46013 0 : if( state->rstate.stage>=0 )
46014 : {
46015 0 : n = state->rstate.ia.ptr.p_int[0];
46016 0 : m = state->rstate.ia.ptr.p_int[1];
46017 0 : i = state->rstate.ia.ptr.p_int[2];
46018 0 : j = state->rstate.ia.ptr.p_int[3];
46019 0 : mcinfo = state->rstate.ia.ptr.p_int[4];
46020 0 : actstatus = state->rstate.ia.ptr.p_int[5];
46021 0 : itidx = state->rstate.ia.ptr.p_int[6];
46022 0 : b = state->rstate.ba.ptr.p_bool[0];
46023 0 : v = state->rstate.ra.ptr.p_double[0];
46024 0 : vv = state->rstate.ra.ptr.p_double[1];
46025 0 : v0 = state->rstate.ra.ptr.p_double[2];
46026 0 : penalty = state->rstate.ra.ptr.p_double[3];
46027 0 : ginit = state->rstate.ra.ptr.p_double[4];
46028 0 : gdecay = state->rstate.ra.ptr.p_double[5];
46029 : }
46030 : else
46031 : {
46032 0 : n = 359;
46033 0 : m = -58;
46034 0 : i = -919;
46035 0 : j = -909;
46036 0 : mcinfo = 81;
46037 0 : actstatus = 255;
46038 0 : itidx = 74;
46039 0 : b = ae_false;
46040 0 : v = 809;
46041 0 : vv = 205;
46042 0 : v0 = -838;
46043 0 : penalty = 939;
46044 0 : ginit = -526;
46045 0 : gdecay = 763;
46046 : }
46047 0 : if( state->rstate.stage==0 )
46048 : {
46049 0 : goto lbl_0;
46050 : }
46051 0 : if( state->rstate.stage==1 )
46052 : {
46053 0 : goto lbl_1;
46054 : }
46055 0 : if( state->rstate.stage==2 )
46056 : {
46057 0 : goto lbl_2;
46058 : }
46059 0 : if( state->rstate.stage==3 )
46060 : {
46061 0 : goto lbl_3;
46062 : }
46063 0 : if( state->rstate.stage==4 )
46064 : {
46065 0 : goto lbl_4;
46066 : }
46067 0 : if( state->rstate.stage==5 )
46068 : {
46069 0 : goto lbl_5;
46070 : }
46071 0 : if( state->rstate.stage==6 )
46072 : {
46073 0 : goto lbl_6;
46074 : }
46075 0 : if( state->rstate.stage==7 )
46076 : {
46077 0 : goto lbl_7;
46078 : }
46079 0 : if( state->rstate.stage==8 )
46080 : {
46081 0 : goto lbl_8;
46082 : }
46083 0 : if( state->rstate.stage==9 )
46084 : {
46085 0 : goto lbl_9;
46086 : }
46087 0 : if( state->rstate.stage==10 )
46088 : {
46089 0 : goto lbl_10;
46090 : }
46091 0 : if( state->rstate.stage==11 )
46092 : {
46093 0 : goto lbl_11;
46094 : }
46095 0 : if( state->rstate.stage==12 )
46096 : {
46097 0 : goto lbl_12;
46098 : }
46099 0 : if( state->rstate.stage==13 )
46100 : {
46101 0 : goto lbl_13;
46102 : }
46103 0 : if( state->rstate.stage==14 )
46104 : {
46105 0 : goto lbl_14;
46106 : }
46107 0 : if( state->rstate.stage==15 )
46108 : {
46109 0 : goto lbl_15;
46110 : }
46111 0 : if( state->rstate.stage==16 )
46112 : {
46113 0 : goto lbl_16;
46114 : }
46115 0 : if( state->rstate.stage==17 )
46116 : {
46117 0 : goto lbl_17;
46118 : }
46119 0 : if( state->rstate.stage==18 )
46120 : {
46121 0 : goto lbl_18;
46122 : }
46123 0 : if( state->rstate.stage==19 )
46124 : {
46125 0 : goto lbl_19;
46126 : }
46127 0 : if( state->rstate.stage==20 )
46128 : {
46129 0 : goto lbl_20;
46130 : }
46131 0 : if( state->rstate.stage==21 )
46132 : {
46133 0 : goto lbl_21;
46134 : }
46135 :
46136 : /*
46137 : * Routine body
46138 : */
46139 :
46140 : /*
46141 : * Algorithm parameters:
46142 : * * M number of L-BFGS corrections.
46143 : * This coefficient remains fixed during iterations.
46144 : * * GDecay desired decrease of constrained gradient during L-BFGS iterations.
46145 : * This coefficient is decreased after each L-BFGS round until
46146 : * it reaches minimum decay.
46147 : */
46148 0 : m = ae_minint(5, state->nmain, _state);
46149 0 : gdecay = minbleic_initialdecay;
46150 :
46151 : /*
46152 : * Init
46153 : */
46154 0 : n = state->nmain;
46155 0 : state->steepestdescentstep = ae_false;
46156 0 : state->userterminationneeded = ae_false;
46157 0 : state->repterminationtype = 0;
46158 0 : state->repinneriterationscount = 0;
46159 0 : state->repouteriterationscount = 0;
46160 0 : state->repnfev = 0;
46161 0 : state->repvaridx = -1;
46162 0 : state->repdebugeqerr = 0.0;
46163 0 : state->repdebugfs = _state->v_nan;
46164 0 : state->repdebugff = _state->v_nan;
46165 0 : state->repdebugdx = _state->v_nan;
46166 0 : if( ae_fp_neq(state->stpmax,(double)(0))&&state->prectype!=0 )
46167 : {
46168 0 : state->repterminationtype = -10;
46169 0 : result = ae_false;
46170 0 : return result;
46171 : }
46172 0 : rmatrixsetlengthatleast(&state->bufyk, m+1, n, _state);
46173 0 : rmatrixsetlengthatleast(&state->bufsk, m+1, n, _state);
46174 0 : rvectorsetlengthatleast(&state->bufrho, m, _state);
46175 0 : rvectorsetlengthatleast(&state->buftheta, m, _state);
46176 0 : rvectorsetlengthatleast(&state->tmp0, n, _state);
46177 0 : smoothnessmonitorinit(&state->smonitor, &state->s, n, 1, state->smoothnessguardlevel>0, _state);
46178 0 : for(i=0; i<=n-1; i++)
46179 : {
46180 0 : state->lastscaleused.ptr.p_double[i] = state->s.ptr.p_double[i];
46181 0 : state->invs.ptr.p_double[i] = 1/state->s.ptr.p_double[i];
46182 : }
46183 :
46184 : /*
46185 : * Check analytic derivative
46186 : */
46187 0 : minbleic_clearrequestfields(state, _state);
46188 0 : if( !(ae_fp_eq(state->diffstep,(double)(0))&&ae_fp_greater(state->teststep,(double)(0))) )
46189 : {
46190 0 : goto lbl_22;
46191 : }
46192 0 : lbl_24:
46193 0 : if( !smoothnessmonitorcheckgradientatx0(&state->smonitor, &state->xstart, &state->s, &state->bndl, &state->bndu, ae_true, state->teststep, _state) )
46194 : {
46195 0 : goto lbl_25;
46196 : }
46197 0 : for(i=0; i<=n-1; i++)
46198 : {
46199 0 : state->x.ptr.p_double[i] = state->smonitor.x.ptr.p_double[i];
46200 : }
46201 0 : state->needfg = ae_true;
46202 0 : state->rstate.stage = 0;
46203 0 : goto lbl_rcomm;
46204 0 : lbl_0:
46205 0 : state->needfg = ae_false;
46206 0 : state->smonitor.fi.ptr.p_double[0] = state->f;
46207 0 : for(i=0; i<=n-1; i++)
46208 : {
46209 0 : state->smonitor.j.ptr.pp_double[0][i] = state->g.ptr.p_double[i];
46210 : }
46211 0 : goto lbl_24;
46212 0 : lbl_25:
46213 0 : lbl_22:
46214 :
46215 : /*
46216 : * Fill TmpPrec with current preconditioner
46217 : */
46218 0 : rvectorsetlengthatleast(&state->tmpprec, n, _state);
46219 0 : for(i=0; i<=n-1; i++)
46220 : {
46221 0 : if( state->prectype==2 )
46222 : {
46223 0 : state->tmpprec.ptr.p_double[i] = state->diagh.ptr.p_double[i];
46224 0 : continue;
46225 : }
46226 0 : if( state->prectype==3 )
46227 : {
46228 0 : state->tmpprec.ptr.p_double[i] = 1/ae_sqr(state->s.ptr.p_double[i], _state);
46229 0 : continue;
46230 : }
46231 0 : state->tmpprec.ptr.p_double[i] = (double)(1);
46232 : }
46233 0 : sassetprecdiag(&state->sas, &state->tmpprec, _state);
46234 :
46235 : /*
46236 : * Start optimization
46237 : */
46238 0 : if( !sasstartoptimization(&state->sas, &state->xstart, _state) )
46239 : {
46240 0 : state->repterminationtype = -3;
46241 0 : result = ae_false;
46242 0 : return result;
46243 : }
46244 :
46245 : /*
46246 : * Main cycle of BLEIC-PG algorithm
46247 : */
46248 0 : state->repterminationtype = 0;
46249 0 : state->lastgoodstep = (double)(0);
46250 0 : state->lastscaledgoodstep = (double)(0);
46251 0 : state->maxscaledgrad = (double)(0);
46252 0 : state->nonmonotoniccnt = ae_round(1.5*(n+state->nic), _state)+5;
46253 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
46254 0 : minbleic_clearrequestfields(state, _state);
46255 0 : if( ae_fp_neq(state->diffstep,(double)(0)) )
46256 : {
46257 0 : goto lbl_26;
46258 : }
46259 0 : state->needfg = ae_true;
46260 0 : state->rstate.stage = 1;
46261 0 : goto lbl_rcomm;
46262 0 : lbl_1:
46263 0 : state->needfg = ae_false;
46264 0 : goto lbl_27;
46265 0 : lbl_26:
46266 0 : state->needf = ae_true;
46267 0 : state->rstate.stage = 2;
46268 0 : goto lbl_rcomm;
46269 0 : lbl_2:
46270 0 : state->needf = ae_false;
46271 0 : lbl_27:
46272 0 : state->fc = state->f;
46273 0 : trimprepare(state->f, &state->trimthreshold, _state);
46274 0 : state->repnfev = state->repnfev+1;
46275 0 : if( !state->xrep )
46276 : {
46277 0 : goto lbl_28;
46278 : }
46279 :
46280 : /*
46281 : * Report current point
46282 : */
46283 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
46284 0 : state->f = state->fc;
46285 0 : state->xupdated = ae_true;
46286 0 : state->rstate.stage = 3;
46287 0 : goto lbl_rcomm;
46288 0 : lbl_3:
46289 0 : state->xupdated = ae_false;
46290 0 : lbl_28:
46291 0 : if( state->userterminationneeded )
46292 : {
46293 :
46294 : /*
46295 : * User requested termination
46296 : */
46297 0 : sasstopoptimization(&state->sas, _state);
46298 0 : state->repterminationtype = 8;
46299 0 : result = ae_false;
46300 0 : return result;
46301 : }
46302 0 : lbl_30:
46303 : if( ae_false )
46304 : {
46305 : goto lbl_31;
46306 : }
46307 :
46308 : /*
46309 : * Preparations
46310 : *
46311 : * (a) calculate unconstrained gradient
46312 : * (b) determine initial active set
46313 : * (c) update MaxScaledGrad
46314 : * (d) check F/G for NAN/INF, abnormally terminate algorithm if needed
46315 : */
46316 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
46317 0 : minbleic_clearrequestfields(state, _state);
46318 0 : if( ae_fp_neq(state->diffstep,(double)(0)) )
46319 : {
46320 0 : goto lbl_32;
46321 : }
46322 :
46323 : /*
46324 : * Analytic gradient
46325 : */
46326 0 : state->needfg = ae_true;
46327 0 : state->rstate.stage = 4;
46328 0 : goto lbl_rcomm;
46329 0 : lbl_4:
46330 0 : state->needfg = ae_false;
46331 0 : goto lbl_33;
46332 0 : lbl_32:
46333 :
46334 : /*
46335 : * Numerical differentiation
46336 : */
46337 0 : state->needf = ae_true;
46338 0 : state->rstate.stage = 5;
46339 0 : goto lbl_rcomm;
46340 0 : lbl_5:
46341 0 : state->fbase = state->f;
46342 0 : i = 0;
46343 0 : lbl_34:
46344 0 : if( i>n-1 )
46345 : {
46346 0 : goto lbl_36;
46347 : }
46348 0 : v = state->x.ptr.p_double[i];
46349 0 : b = ae_false;
46350 0 : if( state->hasbndl.ptr.p_bool[i] )
46351 : {
46352 0 : b = b||ae_fp_less(v-state->diffstep*state->s.ptr.p_double[i],state->bndl.ptr.p_double[i]);
46353 : }
46354 0 : if( state->hasbndu.ptr.p_bool[i] )
46355 : {
46356 0 : b = b||ae_fp_greater(v+state->diffstep*state->s.ptr.p_double[i],state->bndu.ptr.p_double[i]);
46357 : }
46358 0 : if( b )
46359 : {
46360 0 : goto lbl_37;
46361 : }
46362 0 : state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i];
46363 0 : state->rstate.stage = 6;
46364 0 : goto lbl_rcomm;
46365 0 : lbl_6:
46366 0 : state->fm2 = state->f;
46367 0 : state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i];
46368 0 : state->rstate.stage = 7;
46369 0 : goto lbl_rcomm;
46370 0 : lbl_7:
46371 0 : state->fm1 = state->f;
46372 0 : state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i];
46373 0 : state->rstate.stage = 8;
46374 0 : goto lbl_rcomm;
46375 0 : lbl_8:
46376 0 : state->fp1 = state->f;
46377 0 : state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i];
46378 0 : state->rstate.stage = 9;
46379 0 : goto lbl_rcomm;
46380 0 : lbl_9:
46381 0 : state->fp2 = state->f;
46382 0 : state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]);
46383 0 : goto lbl_38;
46384 0 : lbl_37:
46385 0 : state->xm1 = v-state->diffstep*state->s.ptr.p_double[i];
46386 0 : state->xp1 = v+state->diffstep*state->s.ptr.p_double[i];
46387 0 : if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less(state->xm1,state->bndl.ptr.p_double[i]) )
46388 : {
46389 0 : state->xm1 = state->bndl.ptr.p_double[i];
46390 : }
46391 0 : if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater(state->xp1,state->bndu.ptr.p_double[i]) )
46392 : {
46393 0 : state->xp1 = state->bndu.ptr.p_double[i];
46394 : }
46395 0 : state->x.ptr.p_double[i] = state->xm1;
46396 0 : state->rstate.stage = 10;
46397 0 : goto lbl_rcomm;
46398 0 : lbl_10:
46399 0 : state->fm1 = state->f;
46400 0 : state->x.ptr.p_double[i] = state->xp1;
46401 0 : state->rstate.stage = 11;
46402 0 : goto lbl_rcomm;
46403 0 : lbl_11:
46404 0 : state->fp1 = state->f;
46405 0 : if( ae_fp_neq(state->xm1,state->xp1) )
46406 : {
46407 0 : state->g.ptr.p_double[i] = (state->fp1-state->fm1)/(state->xp1-state->xm1);
46408 : }
46409 : else
46410 : {
46411 0 : state->g.ptr.p_double[i] = (double)(0);
46412 : }
46413 0 : lbl_38:
46414 0 : state->x.ptr.p_double[i] = v;
46415 0 : i = i+1;
46416 0 : goto lbl_34;
46417 0 : lbl_36:
46418 0 : state->f = state->fbase;
46419 0 : state->needf = ae_false;
46420 0 : lbl_33:
46421 0 : state->fc = state->f;
46422 0 : ae_v_move(&state->ugc.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
46423 0 : ae_v_move(&state->cgc.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
46424 0 : sasreactivateconstraintsprec(&state->sas, &state->ugc, _state);
46425 0 : sasconstraineddirection(&state->sas, &state->cgc, _state);
46426 0 : ginit = 0.0;
46427 0 : for(i=0; i<=n-1; i++)
46428 : {
46429 0 : ginit = ginit+ae_sqr(state->cgc.ptr.p_double[i]*state->s.ptr.p_double[i], _state);
46430 : }
46431 0 : ginit = ae_sqrt(ginit, _state);
46432 0 : state->maxscaledgrad = ae_maxreal(state->maxscaledgrad, ginit, _state);
46433 0 : if( !ae_isfinite(ginit, _state)||!ae_isfinite(state->fc, _state) )
46434 : {
46435 :
46436 : /*
46437 : * Abnormal termination - infinities in function/gradient
46438 : */
46439 0 : sasstopoptimization(&state->sas, _state);
46440 0 : state->repterminationtype = -8;
46441 0 : result = ae_false;
46442 0 : return result;
46443 : }
46444 0 : if( state->userterminationneeded )
46445 : {
46446 :
46447 : /*
46448 : * User requested termination
46449 : */
46450 0 : sasstopoptimization(&state->sas, _state);
46451 0 : state->repterminationtype = 8;
46452 0 : result = ae_false;
46453 0 : return result;
46454 : }
46455 :
46456 : /*
46457 : * LBFGS stage:
46458 : * * during LBFGS iterations we activate new constraints, but never
46459 : * deactivate already active ones.
46460 : * * we perform at most N iterations of LBFGS before re-evaluating
46461 : * active set and restarting LBFGS.
46462 : * * first iteration of LBFGS is a special - it is performed with
46463 : * minimum set of active constraints, algorithm termination can
46464 : * be performed only at this state. We call this iteration
46465 : * "steepest descent step".
46466 : *
46467 : * About termination:
46468 : * * LBFGS iterations can be terminated because of two reasons:
46469 : * * "termination" - non-zero termination code in RepTerminationType,
46470 : * which means that optimization is done
46471 : * * "restart" - zero RepTerminationType, which means that we
46472 : * have to re-evaluate active set and resume LBFGS stage.
46473 : * * one more option is "refresh" - to continue LBFGS iterations,
46474 : * but with all BFGS updates (Sk/Yk pairs) being dropped;
46475 : * it happens after changes in active set
46476 : */
46477 0 : state->bufsize = 0;
46478 0 : state->steepestdescentstep = ae_true;
46479 0 : itidx = -1;
46480 0 : lbl_39:
46481 0 : if( itidx>=n-1 )
46482 : {
46483 0 : goto lbl_40;
46484 : }
46485 :
46486 : /*
46487 : * Increment iterations counter
46488 : *
46489 : * NOTE: we have strong reasons to use such complex scheme
46490 : * instead of just for() loop - this counter may be
46491 : * decreased at some occasions to perform "restart"
46492 : * of an iteration.
46493 : */
46494 0 : itidx = itidx+1;
46495 :
46496 : /*
46497 : * At the beginning of each iteration:
46498 : * * SAS.XC stores current point
46499 : * * FC stores current function value
46500 : * * UGC stores current unconstrained gradient
46501 : * * CGC stores current constrained gradient
46502 : * * D stores constrained step direction (calculated at this block)
46503 : *
46504 : *
46505 : * Check gradient-based stopping criteria
46506 : *
46507 : * This stopping condition is tested only for step which is the
46508 : * first step of LBFGS (subsequent steps may accumulate active
46509 : * constraints thus they should NOT be used for stopping - gradient
46510 : * may be small when constrained, but these constraints may be
46511 : * deactivated by the subsequent steps)
46512 : */
46513 0 : if( state->steepestdescentstep&&ae_fp_less_eq(sasscaledconstrainednorm(&state->sas, &state->ugc, _state),state->epsg) )
46514 : {
46515 :
46516 : /*
46517 : * Gradient is small enough.
46518 : * Optimization is terminated
46519 : */
46520 0 : state->repterminationtype = 4;
46521 0 : goto lbl_40;
46522 : }
46523 :
46524 : /*
46525 : * 1. Calculate search direction D according to L-BFGS algorithm
46526 : * using constrained preconditioner to perform inner multiplication.
46527 : * 2. Evaluate scaled length of direction D; restart LBFGS if D is zero
46528 : * (it may be possible that we found minimum, but it is also possible
46529 : * that some constraints need deactivation)
46530 : * 3. If D is non-zero, try to use previous scaled step length as initial estimate for new step.
46531 : */
46532 0 : ae_v_move(&state->work.ptr.p_double[0], 1, &state->cgc.ptr.p_double[0], 1, ae_v_len(0,n-1));
46533 0 : for(i=state->bufsize-1; i>=0; i--)
46534 : {
46535 0 : v = ae_v_dotproduct(&state->bufsk.ptr.pp_double[i][0], 1, &state->work.ptr.p_double[0], 1, ae_v_len(0,n-1));
46536 0 : state->buftheta.ptr.p_double[i] = v;
46537 0 : vv = v*state->bufrho.ptr.p_double[i];
46538 0 : ae_v_subd(&state->work.ptr.p_double[0], 1, &state->bufyk.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), vv);
46539 : }
46540 0 : sasconstraineddirectionprec(&state->sas, &state->work, _state);
46541 0 : for(i=0; i<=state->bufsize-1; i++)
46542 : {
46543 0 : v = ae_v_dotproduct(&state->bufyk.ptr.pp_double[i][0], 1, &state->work.ptr.p_double[0], 1, ae_v_len(0,n-1));
46544 0 : vv = state->bufrho.ptr.p_double[i]*(-v+state->buftheta.ptr.p_double[i]);
46545 0 : ae_v_addd(&state->work.ptr.p_double[0], 1, &state->bufsk.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), vv);
46546 : }
46547 0 : sasconstraineddirection(&state->sas, &state->work, _state);
46548 0 : ae_v_moveneg(&state->d.ptr.p_double[0], 1, &state->work.ptr.p_double[0], 1, ae_v_len(0,n-1));
46549 0 : v = (double)(0);
46550 0 : for(i=0; i<=n-1; i++)
46551 : {
46552 0 : v = v+ae_sqr(state->d.ptr.p_double[i]/state->s.ptr.p_double[i], _state);
46553 : }
46554 0 : v = ae_sqrt(v, _state);
46555 0 : if( ae_fp_eq(v,(double)(0)) )
46556 : {
46557 :
46558 : /*
46559 : * Search direction is zero.
46560 : * If we perform "steepest descent step", algorithm is terminated.
46561 : * Otherwise we just restart LBFGS.
46562 : */
46563 0 : if( state->steepestdescentstep )
46564 : {
46565 0 : state->repterminationtype = 4;
46566 : }
46567 0 : goto lbl_40;
46568 : }
46569 0 : ae_assert(ae_fp_greater(v,(double)(0)), "MinBLEIC: internal error", _state);
46570 0 : if( ae_fp_greater(state->lastscaledgoodstep,(double)(0))&&ae_fp_greater(v,(double)(0)) )
46571 : {
46572 0 : state->stp = state->lastscaledgoodstep/v;
46573 : }
46574 : else
46575 : {
46576 0 : state->stp = 1.0/v;
46577 : }
46578 :
46579 : /*
46580 : * Calculate bound on step length.
46581 : * Step direction is stored
46582 : */
46583 0 : sasexploredirection(&state->sas, &state->d, &state->curstpmax, &state->cidx, &state->cval, _state);
46584 0 : state->activationstep = state->curstpmax;
46585 0 : if( state->cidx>=0&&ae_fp_eq(state->activationstep,(double)(0)) )
46586 : {
46587 :
46588 : /*
46589 : * We are exactly at the boundary, immediate activation
46590 : * of constraint is required. LBFGS stage is continued
46591 : * with "refreshed" model.
46592 : *
46593 : * ! IMPORTANT: we do not clear SteepestDescent flag here,
46594 : * ! it is very important for correct stopping
46595 : * ! of algorithm.
46596 : *
46597 : * ! IMPORTANT: we decrease iteration counter in order to
46598 : * preserve computational budget for iterations.
46599 : */
46600 0 : sasimmediateactivation(&state->sas, state->cidx, state->cval, _state);
46601 0 : state->bufsize = 0;
46602 0 : itidx = itidx-1;
46603 0 : goto lbl_39;
46604 : }
46605 0 : if( ae_fp_greater(state->stpmax,(double)(0)) )
46606 : {
46607 0 : v = ae_v_dotproduct(&state->d.ptr.p_double[0], 1, &state->d.ptr.p_double[0], 1, ae_v_len(0,n-1));
46608 0 : v = ae_sqrt(v, _state);
46609 0 : if( ae_fp_greater(v,(double)(0)) )
46610 : {
46611 0 : state->curstpmax = ae_minreal(state->curstpmax, state->stpmax/v, _state);
46612 : }
46613 : }
46614 :
46615 : /*
46616 : * Report beginning of line search (if requested by caller).
46617 : * See description of the MinBLEICState for more information
46618 : * about fields accessible to caller.
46619 : *
46620 : * Caller may do following:
46621 : * * change State.Stp and load better initial estimate of
46622 : * the step length.
46623 : * Caller may not terminate algorithm.
46624 : */
46625 0 : if( !state->drep )
46626 : {
46627 0 : goto lbl_41;
46628 : }
46629 0 : minbleic_clearrequestfields(state, _state);
46630 0 : state->lsstart = ae_true;
46631 0 : state->boundedstep = state->cidx>=0;
46632 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
46633 0 : state->rstate.stage = 12;
46634 0 : goto lbl_rcomm;
46635 0 : lbl_12:
46636 0 : state->lsstart = ae_false;
46637 0 : lbl_41:
46638 :
46639 : /*
46640 : * Minimize F(x+alpha*d)
46641 : */
46642 0 : ae_v_move(&state->xn.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
46643 0 : ae_v_move(&state->cgn.ptr.p_double[0], 1, &state->cgc.ptr.p_double[0], 1, ae_v_len(0,n-1));
46644 0 : ae_v_move(&state->ugn.ptr.p_double[0], 1, &state->ugc.ptr.p_double[0], 1, ae_v_len(0,n-1));
46645 0 : state->fn = state->fc;
46646 0 : state->mcstage = 0;
46647 0 : smoothnessmonitorstartlinesearch1u(&state->smonitor, &state->s, &state->invs, &state->xn, state->fn, &state->ugn, _state);
46648 0 : mcsrch(n, &state->xn, &state->fn, &state->ugn, &state->d, &state->stp, state->curstpmax, minbleic_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state);
46649 0 : lbl_43:
46650 0 : if( state->mcstage==0 )
46651 : {
46652 0 : goto lbl_44;
46653 : }
46654 :
46655 : /*
46656 : * Perform correction (constraints are enforced)
46657 : * Copy XN to X
46658 : */
46659 0 : sascorrection(&state->sas, &state->xn, &penalty, _state);
46660 0 : for(i=0; i<=n-1; i++)
46661 : {
46662 0 : state->x.ptr.p_double[i] = state->xn.ptr.p_double[i];
46663 : }
46664 :
46665 : /*
46666 : * Gradient, either user-provided or numerical differentiation
46667 : */
46668 0 : minbleic_clearrequestfields(state, _state);
46669 0 : if( ae_fp_neq(state->diffstep,(double)(0)) )
46670 : {
46671 0 : goto lbl_45;
46672 : }
46673 :
46674 : /*
46675 : * Analytic gradient
46676 : */
46677 0 : state->needfg = ae_true;
46678 0 : state->rstate.stage = 13;
46679 0 : goto lbl_rcomm;
46680 0 : lbl_13:
46681 0 : state->needfg = ae_false;
46682 0 : state->repnfev = state->repnfev+1;
46683 0 : goto lbl_46;
46684 0 : lbl_45:
46685 :
46686 : /*
46687 : * Numerical differentiation
46688 : */
46689 0 : state->needf = ae_true;
46690 0 : state->rstate.stage = 14;
46691 0 : goto lbl_rcomm;
46692 0 : lbl_14:
46693 0 : state->fbase = state->f;
46694 0 : i = 0;
46695 0 : lbl_47:
46696 0 : if( i>n-1 )
46697 : {
46698 0 : goto lbl_49;
46699 : }
46700 0 : v = state->x.ptr.p_double[i];
46701 0 : b = ae_false;
46702 0 : if( state->hasbndl.ptr.p_bool[i] )
46703 : {
46704 0 : b = b||ae_fp_less(v-state->diffstep*state->s.ptr.p_double[i],state->bndl.ptr.p_double[i]);
46705 : }
46706 0 : if( state->hasbndu.ptr.p_bool[i] )
46707 : {
46708 0 : b = b||ae_fp_greater(v+state->diffstep*state->s.ptr.p_double[i],state->bndu.ptr.p_double[i]);
46709 : }
46710 0 : if( b )
46711 : {
46712 0 : goto lbl_50;
46713 : }
46714 0 : state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i];
46715 0 : state->rstate.stage = 15;
46716 0 : goto lbl_rcomm;
46717 0 : lbl_15:
46718 0 : state->fm2 = state->f;
46719 0 : state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i];
46720 0 : state->rstate.stage = 16;
46721 0 : goto lbl_rcomm;
46722 0 : lbl_16:
46723 0 : state->fm1 = state->f;
46724 0 : state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i];
46725 0 : state->rstate.stage = 17;
46726 0 : goto lbl_rcomm;
46727 0 : lbl_17:
46728 0 : state->fp1 = state->f;
46729 0 : state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i];
46730 0 : state->rstate.stage = 18;
46731 0 : goto lbl_rcomm;
46732 0 : lbl_18:
46733 0 : state->fp2 = state->f;
46734 0 : state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]);
46735 0 : state->repnfev = state->repnfev+4;
46736 0 : goto lbl_51;
46737 0 : lbl_50:
46738 0 : state->xm1 = v-state->diffstep*state->s.ptr.p_double[i];
46739 0 : state->xp1 = v+state->diffstep*state->s.ptr.p_double[i];
46740 0 : if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less(state->xm1,state->bndl.ptr.p_double[i]) )
46741 : {
46742 0 : state->xm1 = state->bndl.ptr.p_double[i];
46743 : }
46744 0 : if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater(state->xp1,state->bndu.ptr.p_double[i]) )
46745 : {
46746 0 : state->xp1 = state->bndu.ptr.p_double[i];
46747 : }
46748 0 : state->x.ptr.p_double[i] = state->xm1;
46749 0 : state->rstate.stage = 19;
46750 0 : goto lbl_rcomm;
46751 0 : lbl_19:
46752 0 : state->fm1 = state->f;
46753 0 : state->x.ptr.p_double[i] = state->xp1;
46754 0 : state->rstate.stage = 20;
46755 0 : goto lbl_rcomm;
46756 0 : lbl_20:
46757 0 : state->fp1 = state->f;
46758 0 : if( ae_fp_neq(state->xm1,state->xp1) )
46759 : {
46760 0 : state->g.ptr.p_double[i] = (state->fp1-state->fm1)/(state->xp1-state->xm1);
46761 : }
46762 : else
46763 : {
46764 0 : state->g.ptr.p_double[i] = (double)(0);
46765 : }
46766 0 : state->repnfev = state->repnfev+2;
46767 0 : lbl_51:
46768 0 : state->x.ptr.p_double[i] = v;
46769 0 : i = i+1;
46770 0 : goto lbl_47;
46771 0 : lbl_49:
46772 0 : state->f = state->fbase;
46773 0 : state->needf = ae_false;
46774 0 : lbl_46:
46775 :
46776 : /*
46777 : * Back to MCSRCH
46778 : *
46779 : * NOTE: penalty term from correction is added to FN in order
46780 : * to penalize increase in infeasibility.
46781 : */
46782 0 : smoothnessmonitorenqueuepoint1u(&state->smonitor, &state->s, &state->invs, &state->d, state->stp, &state->x, state->f, &state->g, _state);
46783 0 : state->fn = state->f+minbleic_penaltyfactor*state->maxscaledgrad*penalty;
46784 0 : ae_v_move(&state->cgn.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
46785 0 : ae_v_move(&state->ugn.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
46786 0 : sasconstraineddirection(&state->sas, &state->cgn, _state);
46787 0 : trimfunction(&state->fn, &state->cgn, n, state->trimthreshold, _state);
46788 0 : mcsrch(n, &state->xn, &state->fn, &state->ugn, &state->d, &state->stp, state->curstpmax, minbleic_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state);
46789 0 : goto lbl_43;
46790 0 : lbl_44:
46791 0 : ae_v_moveneg(&state->bufsk.ptr.pp_double[state->bufsize][0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
46792 0 : ae_v_moveneg(&state->bufyk.ptr.pp_double[state->bufsize][0], 1, &state->cgc.ptr.p_double[0], 1, ae_v_len(0,n-1));
46793 0 : ae_v_add(&state->bufsk.ptr.pp_double[state->bufsize][0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1));
46794 0 : ae_v_add(&state->bufyk.ptr.pp_double[state->bufsize][0], 1, &state->cgn.ptr.p_double[0], 1, ae_v_len(0,n-1));
46795 0 : smoothnessmonitorfinalizelinesearch(&state->smonitor, _state);
46796 :
46797 : /*
46798 : * Check for presence of NAN/INF in function/gradient
46799 : */
46800 0 : v = state->fn;
46801 0 : for(i=0; i<=n-1; i++)
46802 : {
46803 0 : v = 0.1*v+state->ugn.ptr.p_double[i];
46804 : }
46805 0 : if( !ae_isfinite(v, _state) )
46806 : {
46807 :
46808 : /*
46809 : * Abnormal termination - infinities in function/gradient
46810 : */
46811 0 : state->repterminationtype = -8;
46812 0 : goto lbl_40;
46813 : }
46814 :
46815 : /*
46816 : * Handle possible failure of the line search or request for termination
46817 : */
46818 0 : if( mcinfo!=1&&mcinfo!=5 )
46819 : {
46820 :
46821 : /*
46822 : * We can not find step which decreases function value. We have
46823 : * two possibilities:
46824 : * (a) numerical properties of the function do not allow us to
46825 : * find good step.
46826 : * (b) we are close to activation of some constraint, and it is
46827 : * so close that step which activates it leads to change in
46828 : * target function which is smaller than numerical noise.
46829 : *
46830 : * Optimization algorithm must be able to handle case (b), because
46831 : * inability to handle it will cause failure when algorithm
46832 : * started very close to boundary of the feasible area.
46833 : *
46834 : * In order to correctly handle such cases we allow limited amount
46835 : * of small steps which increase function value.
46836 : */
46837 0 : v = 0.0;
46838 0 : for(i=0; i<=n-1; i++)
46839 : {
46840 0 : v = v+ae_sqr(state->d.ptr.p_double[i]*state->curstpmax/state->s.ptr.p_double[i], _state);
46841 : }
46842 0 : v = ae_sqrt(v, _state);
46843 0 : b = ae_false;
46844 0 : if( (state->cidx>=0&&ae_fp_less_eq(v,minbleic_maxnonmonotoniclen))&&state->nonmonotoniccnt>0 )
46845 : {
46846 :
46847 : /*
46848 : * We try to enforce non-monotonic step:
46849 : * * Stp := CurStpMax
46850 : * * MCINFO := 5
46851 : * * XN := XC+CurStpMax*D
46852 : * * non-monotonic counter is decreased
46853 : *
46854 : * NOTE: UGN/CGN are not updated because step is so short that we assume that
46855 : * GN is approximately equal to GC.
46856 : *
46857 : * NOTE: prior to enforcing such step we check that it does not increase infeasibility
46858 : * of constraints beyond tolerable level
46859 : */
46860 0 : v = state->curstpmax;
46861 0 : ae_v_move(&state->tmp0.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
46862 0 : ae_v_addd(&state->tmp0.ptr.p_double[0], 1, &state->d.ptr.p_double[0], 1, ae_v_len(0,n-1), v);
46863 0 : if( ae_fp_less_eq(minbleic_feasibilityerror(&state->tmp0, &state->s, n, &state->cleic, state->nec, state->nic, _state),minbleic_nmstol*ae_sqrt((double)(n), _state)*ae_machineepsilon) )
46864 : {
46865 0 : state->stp = state->curstpmax;
46866 0 : mcinfo = 5;
46867 0 : ae_v_move(&state->xn.ptr.p_double[0], 1, &state->tmp0.ptr.p_double[0], 1, ae_v_len(0,n-1));
46868 0 : state->nonmonotoniccnt = state->nonmonotoniccnt-1;
46869 0 : b = ae_true;
46870 : }
46871 : }
46872 0 : if( !b )
46873 : {
46874 :
46875 : /*
46876 : * Numerical properties of the function do not allow
46877 : * us to solve problem. Here we have two possibilities:
46878 : * * if it is "steepest descent" step, we can terminate
46879 : * algorithm because we are close to minimum
46880 : * * if it is NOT "steepest descent" step, we should restart
46881 : * LBFGS iterations.
46882 : */
46883 0 : if( state->steepestdescentstep )
46884 : {
46885 :
46886 : /*
46887 : * Algorithm is terminated
46888 : */
46889 0 : state->repterminationtype = 7;
46890 0 : goto lbl_40;
46891 : }
46892 : else
46893 : {
46894 :
46895 : /*
46896 : * Re-evaluate active set and restart LBFGS
46897 : */
46898 0 : goto lbl_40;
46899 : }
46900 : }
46901 : }
46902 0 : if( state->userterminationneeded )
46903 : {
46904 0 : goto lbl_40;
46905 : }
46906 :
46907 : /*
46908 : * Current point is updated:
46909 : * * move XC/FC/GC to XP/FP/GP
46910 : * * change current point remembered by SAS structure
46911 : * * move XN/FN/GN to XC/FC/GC
46912 : * * report current point and update iterations counter
46913 : * * if MCINFO=1, push new pair SK/YK to LBFGS buffer
46914 : */
46915 0 : state->fp = state->fc;
46916 0 : ae_v_move(&state->xp.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
46917 0 : state->fc = state->fn;
46918 0 : ae_v_move(&state->cgc.ptr.p_double[0], 1, &state->cgn.ptr.p_double[0], 1, ae_v_len(0,n-1));
46919 0 : ae_v_move(&state->ugc.ptr.p_double[0], 1, &state->ugn.ptr.p_double[0], 1, ae_v_len(0,n-1));
46920 0 : actstatus = sasmoveto(&state->sas, &state->xn, state->cidx>=0&&ae_fp_greater_eq(state->stp,state->activationstep), state->cidx, state->cval, _state);
46921 0 : if( !state->xrep )
46922 : {
46923 0 : goto lbl_52;
46924 : }
46925 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
46926 0 : minbleic_clearrequestfields(state, _state);
46927 0 : state->xupdated = ae_true;
46928 0 : state->rstate.stage = 21;
46929 0 : goto lbl_rcomm;
46930 0 : lbl_21:
46931 0 : state->xupdated = ae_false;
46932 0 : lbl_52:
46933 0 : state->repinneriterationscount = state->repinneriterationscount+1;
46934 0 : if( mcinfo==1 )
46935 : {
46936 :
46937 : /*
46938 : * Accept new LBFGS update given by Sk,Yk
46939 : */
46940 0 : if( state->bufsize==m )
46941 : {
46942 :
46943 : /*
46944 : * Buffer is full, shift contents by one row
46945 : */
46946 0 : for(i=0; i<=state->bufsize-1; i++)
46947 : {
46948 0 : ae_v_move(&state->bufsk.ptr.pp_double[i][0], 1, &state->bufsk.ptr.pp_double[i+1][0], 1, ae_v_len(0,n-1));
46949 0 : ae_v_move(&state->bufyk.ptr.pp_double[i][0], 1, &state->bufyk.ptr.pp_double[i+1][0], 1, ae_v_len(0,n-1));
46950 : }
46951 0 : for(i=0; i<=state->bufsize-2; i++)
46952 : {
46953 0 : state->bufrho.ptr.p_double[i] = state->bufrho.ptr.p_double[i+1];
46954 0 : state->buftheta.ptr.p_double[i] = state->buftheta.ptr.p_double[i+1];
46955 : }
46956 : }
46957 : else
46958 : {
46959 :
46960 : /*
46961 : * Buffer is not full, increase buffer size by 1
46962 : */
46963 0 : state->bufsize = state->bufsize+1;
46964 : }
46965 0 : v = ae_v_dotproduct(&state->bufyk.ptr.pp_double[state->bufsize-1][0], 1, &state->bufsk.ptr.pp_double[state->bufsize-1][0], 1, ae_v_len(0,n-1));
46966 0 : vv = ae_v_dotproduct(&state->bufyk.ptr.pp_double[state->bufsize-1][0], 1, &state->bufyk.ptr.pp_double[state->bufsize-1][0], 1, ae_v_len(0,n-1));
46967 0 : if( ae_fp_eq(v,(double)(0))||ae_fp_eq(vv,(double)(0)) )
46968 : {
46969 :
46970 : /*
46971 : * Strange internal error in LBFGS - either YK=0
46972 : * (which should not have been) or (SK,YK)=0 (again,
46973 : * unexpected). It should not take place because
46974 : * MCINFO=1, which signals "good" step. But just
46975 : * to be sure we have special branch of code which
46976 : * restarts LBFGS
46977 : */
46978 0 : goto lbl_40;
46979 : }
46980 0 : state->bufrho.ptr.p_double[state->bufsize-1] = 1/v;
46981 0 : ae_assert(state->bufsize<=m, "MinBLEIC: internal error", _state);
46982 :
46983 : /*
46984 : * Update length of the good step
46985 : */
46986 0 : v = (double)(0);
46987 0 : vv = (double)(0);
46988 0 : for(i=0; i<=n-1; i++)
46989 : {
46990 0 : v = v+ae_sqr((state->sas.xc.ptr.p_double[i]-state->xp.ptr.p_double[i])/state->s.ptr.p_double[i], _state);
46991 0 : vv = vv+ae_sqr(state->sas.xc.ptr.p_double[i]-state->xp.ptr.p_double[i], _state);
46992 : }
46993 0 : state->lastgoodstep = ae_sqrt(vv, _state);
46994 0 : minbleic_updateestimateofgoodstep(&state->lastscaledgoodstep, ae_sqrt(v, _state), _state);
46995 : }
46996 :
46997 : /*
46998 : * Check stopping criteria
46999 : *
47000 : * Step size and function-based stopping criteria are tested only
47001 : * for step which satisfies Wolfe conditions and is the first step of
47002 : * LBFGS (subsequent steps may accumulate active constraints thus
47003 : * they should NOT be used for stopping; step size or function change
47004 : * may be small when constrained, but these constraints may be
47005 : * deactivated by the subsequent steps).
47006 : *
47007 : * MaxIts-based stopping condition is checked for all kinds of steps.
47008 : */
47009 0 : if( mcinfo==1&&state->steepestdescentstep )
47010 : {
47011 :
47012 : /*
47013 : * Step is small enough
47014 : */
47015 0 : v = (double)(0);
47016 0 : for(i=0; i<=n-1; i++)
47017 : {
47018 0 : v = v+ae_sqr((state->sas.xc.ptr.p_double[i]-state->xp.ptr.p_double[i])/state->s.ptr.p_double[i], _state);
47019 : }
47020 0 : v = ae_sqrt(v, _state);
47021 0 : if( ae_fp_less_eq(v,state->epsx) )
47022 : {
47023 0 : state->repterminationtype = 2;
47024 0 : goto lbl_40;
47025 : }
47026 :
47027 : /*
47028 : * Function change is small enough
47029 : */
47030 0 : 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)) )
47031 : {
47032 0 : state->repterminationtype = 1;
47033 0 : goto lbl_40;
47034 : }
47035 : }
47036 0 : if( state->maxits>0&&state->repinneriterationscount>=state->maxits )
47037 : {
47038 0 : state->repterminationtype = 5;
47039 0 : goto lbl_40;
47040 : }
47041 :
47042 : /*
47043 : * Clear "steepest descent" flag.
47044 : */
47045 0 : state->steepestdescentstep = ae_false;
47046 :
47047 : /*
47048 : * Smooth reset (LBFGS memory model is refreshed) or hard restart:
47049 : * * LBFGS model is refreshed, if line search was performed with activation of constraints
47050 : * * algorithm is restarted if scaled gradient decreased below GDecay
47051 : */
47052 0 : if( actstatus>=0 )
47053 : {
47054 0 : state->bufsize = 0;
47055 0 : goto lbl_39;
47056 : }
47057 0 : v = 0.0;
47058 0 : for(i=0; i<=n-1; i++)
47059 : {
47060 0 : v = v+ae_sqr(state->cgc.ptr.p_double[i]*state->s.ptr.p_double[i], _state);
47061 : }
47062 0 : if( ae_fp_less(ae_sqrt(v, _state),gdecay*ginit) )
47063 : {
47064 0 : goto lbl_40;
47065 : }
47066 0 : goto lbl_39;
47067 0 : lbl_40:
47068 0 : if( state->userterminationneeded )
47069 : {
47070 :
47071 : /*
47072 : * User requested termination
47073 : */
47074 0 : state->repterminationtype = 8;
47075 0 : goto lbl_31;
47076 : }
47077 0 : if( state->repterminationtype!=0 )
47078 : {
47079 :
47080 : /*
47081 : * Algorithm terminated
47082 : */
47083 0 : goto lbl_31;
47084 : }
47085 :
47086 : /*
47087 : * Decrease decay coefficient. Subsequent L-BFGS stages will
47088 : * have more stringent stopping criteria.
47089 : */
47090 0 : gdecay = ae_maxreal(gdecay*minbleic_decaycorrection, minbleic_mindecay, _state);
47091 0 : goto lbl_30;
47092 0 : lbl_31:
47093 0 : sasstopoptimization(&state->sas, _state);
47094 0 : state->repouteriterationscount = 1;
47095 0 : result = ae_false;
47096 0 : return result;
47097 :
47098 : /*
47099 : * Saving state
47100 : */
47101 0 : lbl_rcomm:
47102 0 : result = ae_true;
47103 0 : state->rstate.ia.ptr.p_int[0] = n;
47104 0 : state->rstate.ia.ptr.p_int[1] = m;
47105 0 : state->rstate.ia.ptr.p_int[2] = i;
47106 0 : state->rstate.ia.ptr.p_int[3] = j;
47107 0 : state->rstate.ia.ptr.p_int[4] = mcinfo;
47108 0 : state->rstate.ia.ptr.p_int[5] = actstatus;
47109 0 : state->rstate.ia.ptr.p_int[6] = itidx;
47110 0 : state->rstate.ba.ptr.p_bool[0] = b;
47111 0 : state->rstate.ra.ptr.p_double[0] = v;
47112 0 : state->rstate.ra.ptr.p_double[1] = vv;
47113 0 : state->rstate.ra.ptr.p_double[2] = v0;
47114 0 : state->rstate.ra.ptr.p_double[3] = penalty;
47115 0 : state->rstate.ra.ptr.p_double[4] = ginit;
47116 0 : state->rstate.ra.ptr.p_double[5] = gdecay;
47117 0 : return result;
47118 : }
47119 :
47120 :
47121 : /*************************************************************************
47122 : This function activates/deactivates verification of the user-supplied
47123 : analytic gradient.
47124 :
47125 : Upon activation of this option OptGuard integrity checker performs
47126 : numerical differentiation of your target function at the initial point
47127 : (note: future versions may also perform check at the final point) and
47128 : compares numerical gradient with analytic one provided by you.
47129 :
47130 : If difference is too large, an error flag is set and optimization session
47131 : continues. After optimization session is over, you can retrieve the report
47132 : which stores both gradients and specific components highlighted as
47133 : suspicious by the OptGuard.
47134 :
47135 : The primary OptGuard report can be retrieved with minbleicoptguardresults().
47136 :
47137 : IMPORTANT: gradient check is a high-overhead option which will cost you
47138 : about 3*N additional function evaluations. In many cases it may
47139 : cost as much as the rest of the optimization session.
47140 :
47141 : YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO
47142 : CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY.
47143 :
47144 : NOTE: unlike previous incarnation of the gradient checking code, OptGuard
47145 : does NOT interrupt optimization even if it discovers bad gradient.
47146 :
47147 : INPUT PARAMETERS:
47148 : State - structure used to store algorithm state
47149 : TestStep - verification step used for numerical differentiation:
47150 : * TestStep=0 turns verification off
47151 : * TestStep>0 activates verification
47152 : You should carefully choose TestStep. Value which is
47153 : too large (so large that function behavior is non-
47154 : cubic at this scale) will lead to false alarms. Too
47155 : short step will result in rounding errors dominating
47156 : numerical derivative.
47157 :
47158 : You may use different step for different parameters by
47159 : means of setting scale with minbleicsetscale().
47160 :
47161 : === EXPLANATION ==========================================================
47162 :
47163 : In order to verify gradient algorithm performs following steps:
47164 : * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i],
47165 : where X[i] is i-th component of the initial point and S[i] is a scale
47166 : of i-th parameter
47167 : * F(X) is evaluated at these trial points
47168 : * we perform one more evaluation in the middle point of the interval
47169 : * we build cubic model using function values and derivatives at trial
47170 : points and we compare its prediction with actual value in the middle
47171 : point
47172 :
47173 : -- ALGLIB --
47174 : Copyright 15.06.2014 by Bochkanov Sergey
47175 : *************************************************************************/
47176 0 : void minbleicoptguardgradient(minbleicstate* state,
47177 : double teststep,
47178 : ae_state *_state)
47179 : {
47180 :
47181 :
47182 0 : ae_assert(ae_isfinite(teststep, _state), "MinBLEICOptGuardGradient: TestStep contains NaN or INF", _state);
47183 0 : ae_assert(ae_fp_greater_eq(teststep,(double)(0)), "MinBLEICOptGuardGradient: invalid argument TestStep(TestStep<0)", _state);
47184 0 : state->teststep = teststep;
47185 0 : }
47186 :
47187 :
47188 : /*************************************************************************
47189 : This function activates/deactivates nonsmoothness monitoring option of
47190 : the OptGuard integrity checker. Smoothness monitor silently observes
47191 : solution process and tries to detect ill-posed problems, i.e. ones with:
47192 : a) discontinuous target function (non-C0)
47193 : b) nonsmooth target function (non-C1)
47194 :
47195 : Smoothness monitoring does NOT interrupt optimization even if it suspects
47196 : that your problem is nonsmooth. It just sets corresponding flags in the
47197 : OptGuard report which can be retrieved after optimization is over.
47198 :
47199 : Smoothness monitoring is a moderate overhead option which often adds less
47200 : than 1% to the optimizer running time. Thus, you can use it even for large
47201 : scale problems.
47202 :
47203 : NOTE: OptGuard does NOT guarantee that it will always detect C0/C1
47204 : continuity violations.
47205 :
47206 : First, minor errors are hard to catch - say, a 0.0001 difference in
47207 : the model values at two sides of the gap may be due to discontinuity
47208 : of the model - or simply because the model has changed.
47209 :
47210 : Second, C1-violations are especially difficult to detect in a
47211 : noninvasive way. The optimizer usually performs very short steps
47212 : near the nonsmoothness, and differentiation usually introduces a
47213 : lot of numerical noise. It is hard to tell whether some tiny
47214 : discontinuity in the slope is due to real nonsmoothness or just due
47215 : to numerical noise alone.
47216 :
47217 : Our top priority was to avoid false positives, so in some rare cases
47218 : minor errors may went unnoticed (however, in most cases they can be
47219 : spotted with restart from different initial point).
47220 :
47221 : INPUT PARAMETERS:
47222 : state - algorithm state
47223 : level - monitoring level:
47224 : * 0 - monitoring is disabled
47225 : * 1 - noninvasive low-overhead monitoring; function values
47226 : and/or gradients are recorded, but OptGuard does not
47227 : try to perform additional evaluations in order to
47228 : get more information about suspicious locations.
47229 :
47230 : === EXPLANATION ==========================================================
47231 :
47232 : One major source of headache during optimization is the possibility of
47233 : the coding errors in the target function/constraints (or their gradients).
47234 : Such errors most often manifest themselves as discontinuity or
47235 : nonsmoothness of the target/constraints.
47236 :
47237 : Another frequent situation is when you try to optimize something involving
47238 : lots of min() and max() operations, i.e. nonsmooth target. Although not a
47239 : coding error, it is nonsmoothness anyway - and smooth optimizers usually
47240 : stop right after encountering nonsmoothness, well before reaching solution.
47241 :
47242 : OptGuard integrity checker helps you to catch such situations: it monitors
47243 : function values/gradients being passed to the optimizer and tries to
47244 : errors. Upon discovering suspicious pair of points it raises appropriate
47245 : flag (and allows you to continue optimization). When optimization is done,
47246 : you can study OptGuard result.
47247 :
47248 : -- ALGLIB --
47249 : Copyright 21.11.2018 by Bochkanov Sergey
47250 : *************************************************************************/
47251 0 : void minbleicoptguardsmoothness(minbleicstate* state,
47252 : ae_int_t level,
47253 : ae_state *_state)
47254 : {
47255 :
47256 :
47257 0 : ae_assert(level==0||level==1, "MinBLEICOptGuardSmoothness: unexpected value of level parameter", _state);
47258 0 : state->smoothnessguardlevel = level;
47259 0 : }
47260 :
47261 :
47262 : /*************************************************************************
47263 : Results of OptGuard integrity check, should be called after optimization
47264 : session is over.
47265 :
47266 : === PRIMARY REPORT =======================================================
47267 :
47268 : OptGuard performs several checks which are intended to catch common errors
47269 : in the implementation of nonlinear function/gradient:
47270 : * incorrect analytic gradient
47271 : * discontinuous (non-C0) target functions (constraints)
47272 : * nonsmooth (non-C1) target functions (constraints)
47273 :
47274 : Each of these checks is activated with appropriate function:
47275 : * minbleicoptguardgradient() for gradient verification
47276 : * minbleicoptguardsmoothness() for C0/C1 checks
47277 :
47278 : Following flags are set when these errors are suspected:
47279 : * rep.badgradsuspected, and additionally:
47280 : * rep.badgradvidx for specific variable (gradient element) suspected
47281 : * rep.badgradxbase, a point where gradient is tested
47282 : * rep.badgraduser, user-provided gradient (stored as 2D matrix with
47283 : single row in order to make report structure compatible with more
47284 : complex optimizers like MinNLC or MinLM)
47285 : * rep.badgradnum, reference gradient obtained via numerical
47286 : differentiation (stored as 2D matrix with single row in order to make
47287 : report structure compatible with more complex optimizers like MinNLC
47288 : or MinLM)
47289 : * rep.nonc0suspected
47290 : * rep.nonc1suspected
47291 :
47292 : === ADDITIONAL REPORTS/LOGS ==============================================
47293 :
47294 : Several different tests are performed to catch C0/C1 errors, you can find
47295 : out specific test signaled error by looking to:
47296 : * rep.nonc0test0positive, for non-C0 test #0
47297 : * rep.nonc1test0positive, for non-C1 test #0
47298 : * rep.nonc1test1positive, for non-C1 test #1
47299 :
47300 : Additional information (including line search logs) can be obtained by
47301 : means of:
47302 : * minbleicoptguardnonc1test0results()
47303 : * minbleicoptguardnonc1test1results()
47304 : which return detailed error reports, specific points where discontinuities
47305 : were found, and so on.
47306 :
47307 : ==========================================================================
47308 :
47309 : INPUT PARAMETERS:
47310 : state - algorithm state
47311 :
47312 : OUTPUT PARAMETERS:
47313 : rep - generic OptGuard report; more detailed reports can be
47314 : retrieved with other functions.
47315 :
47316 : NOTE: false negatives (nonsmooth problems are not identified as nonsmooth
47317 : ones) are possible although unlikely.
47318 :
47319 : The reason is that you need to make several evaluations around
47320 : nonsmoothness in order to accumulate enough information about
47321 : function curvature. Say, if you start right from the nonsmooth point,
47322 : optimizer simply won't get enough data to understand what is going
47323 : wrong before it terminates due to abrupt changes in the derivative.
47324 : It is also possible that "unlucky" step will move us to the
47325 : termination too quickly.
47326 :
47327 : Our current approach is to have less than 0.1% false negatives in
47328 : our test examples (measured with multiple restarts from random
47329 : points), and to have exactly 0% false positives.
47330 :
47331 : -- ALGLIB --
47332 : Copyright 21.11.2018 by Bochkanov Sergey
47333 : *************************************************************************/
47334 0 : void minbleicoptguardresults(minbleicstate* state,
47335 : optguardreport* rep,
47336 : ae_state *_state)
47337 : {
47338 :
47339 0 : _optguardreport_clear(rep);
47340 :
47341 0 : smoothnessmonitorexportreport(&state->smonitor, rep, _state);
47342 0 : }
47343 :
47344 :
47345 : /*************************************************************************
47346 : Detailed results of the OptGuard integrity check for nonsmoothness test #0
47347 :
47348 : Nonsmoothness (non-C1) test #0 studies function values (not gradient!)
47349 : obtained during line searches and monitors behavior of the directional
47350 : derivative estimate.
47351 :
47352 : This test is less powerful than test #1, but it does not depend on the
47353 : gradient values and thus it is more robust against artifacts introduced by
47354 : numerical differentiation.
47355 :
47356 : Two reports are returned:
47357 : * a "strongest" one, corresponding to line search which had highest
47358 : value of the nonsmoothness indicator
47359 : * a "longest" one, corresponding to line search which had more function
47360 : evaluations, and thus is more detailed
47361 :
47362 : In both cases following fields are returned:
47363 :
47364 : * positive - is TRUE when test flagged suspicious point; FALSE if test
47365 : did not notice anything (in the latter cases fields below are empty).
47366 : * x0[], d[] - arrays of length N which store initial point and direction
47367 : for line search (d[] can be normalized, but does not have to)
47368 : * stp[], f[] - arrays of length CNT which store step lengths and function
47369 : values at these points; f[i] is evaluated in x0+stp[i]*d.
47370 : * stpidxa, stpidxb - we suspect that function violates C1 continuity
47371 : between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3,
47372 : with most likely position of the violation between stpidxa+1 and
47373 : stpidxa+2.
47374 :
47375 : ==========================================================================
47376 : = SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will
47377 : = see where C1 continuity is violated.
47378 : ==========================================================================
47379 :
47380 : INPUT PARAMETERS:
47381 : state - algorithm state
47382 :
47383 : OUTPUT PARAMETERS:
47384 : strrep - C1 test #0 "strong" report
47385 : lngrep - C1 test #0 "long" report
47386 :
47387 : -- ALGLIB --
47388 : Copyright 21.11.2018 by Bochkanov Sergey
47389 : *************************************************************************/
47390 0 : void minbleicoptguardnonc1test0results(minbleicstate* state,
47391 : optguardnonc1test0report* strrep,
47392 : optguardnonc1test0report* lngrep,
47393 : ae_state *_state)
47394 : {
47395 :
47396 0 : _optguardnonc1test0report_clear(strrep);
47397 0 : _optguardnonc1test0report_clear(lngrep);
47398 :
47399 0 : smoothnessmonitorexportc1test0report(&state->smonitor.nonc1test0strrep, &state->lastscaleused, strrep, _state);
47400 0 : smoothnessmonitorexportc1test0report(&state->smonitor.nonc1test0lngrep, &state->lastscaleused, lngrep, _state);
47401 0 : }
47402 :
47403 :
47404 : /*************************************************************************
47405 : Detailed results of the OptGuard integrity check for nonsmoothness test #1
47406 :
47407 : Nonsmoothness (non-C1) test #1 studies individual components of the
47408 : gradient computed during line search.
47409 :
47410 : When precise analytic gradient is provided this test is more powerful than
47411 : test #0 which works with function values and ignores user-provided
47412 : gradient. However, test #0 becomes more powerful when numerical
47413 : differentiation is employed (in such cases test #1 detects higher levels
47414 : of numerical noise and becomes too conservative).
47415 :
47416 : This test also tells specific components of the gradient which violate C1
47417 : continuity, which makes it more informative than #0, which just tells that
47418 : continuity is violated.
47419 :
47420 : Two reports are returned:
47421 : * a "strongest" one, corresponding to line search which had highest
47422 : value of the nonsmoothness indicator
47423 : * a "longest" one, corresponding to line search which had more function
47424 : evaluations, and thus is more detailed
47425 :
47426 : In both cases following fields are returned:
47427 :
47428 : * positive - is TRUE when test flagged suspicious point; FALSE if test
47429 : did not notice anything (in the latter cases fields below are empty).
47430 : * vidx - is an index of the variable in [0,N) with nonsmooth derivative
47431 : * x0[], d[] - arrays of length N which store initial point and direction
47432 : for line search (d[] can be normalized, but does not have to)
47433 : * stp[], g[] - arrays of length CNT which store step lengths and gradient
47434 : values at these points; g[i] is evaluated in x0+stp[i]*d and contains
47435 : vidx-th component of the gradient.
47436 : * stpidxa, stpidxb - we suspect that function violates C1 continuity
47437 : between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3,
47438 : with most likely position of the violation between stpidxa+1 and
47439 : stpidxa+2.
47440 :
47441 : ==========================================================================
47442 : = SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will
47443 : = see where C1 continuity is violated.
47444 : ==========================================================================
47445 :
47446 : INPUT PARAMETERS:
47447 : state - algorithm state
47448 :
47449 : OUTPUT PARAMETERS:
47450 : strrep - C1 test #1 "strong" report
47451 : lngrep - C1 test #1 "long" report
47452 :
47453 : -- ALGLIB --
47454 : Copyright 21.11.2018 by Bochkanov Sergey
47455 : *************************************************************************/
47456 0 : void minbleicoptguardnonc1test1results(minbleicstate* state,
47457 : optguardnonc1test1report* strrep,
47458 : optguardnonc1test1report* lngrep,
47459 : ae_state *_state)
47460 : {
47461 :
47462 0 : _optguardnonc1test1report_clear(strrep);
47463 0 : _optguardnonc1test1report_clear(lngrep);
47464 :
47465 0 : smoothnessmonitorexportc1test1report(&state->smonitor.nonc1test1strrep, &state->lastscaleused, strrep, _state);
47466 0 : smoothnessmonitorexportc1test1report(&state->smonitor.nonc1test1lngrep, &state->lastscaleused, lngrep, _state);
47467 0 : }
47468 :
47469 :
47470 : /*************************************************************************
47471 : BLEIC results
47472 :
47473 : INPUT PARAMETERS:
47474 : State - algorithm state
47475 :
47476 : OUTPUT PARAMETERS:
47477 : X - array[0..N-1], solution
47478 : Rep - optimization report. You should check Rep.TerminationType
47479 : in order to distinguish successful termination from
47480 : unsuccessful one:
47481 : * -8 internal integrity control detected infinite or
47482 : NAN values in function/gradient. Abnormal
47483 : termination signalled.
47484 : * -3 inconsistent constraints. Feasible point is
47485 : either nonexistent or too hard to find. Try to
47486 : restart optimizer with better initial approximation
47487 : * 1 relative function improvement is no more than EpsF.
47488 : * 2 scaled step is no more than EpsX.
47489 : * 4 scaled gradient norm is no more than EpsG.
47490 : * 5 MaxIts steps was taken
47491 : * 8 terminated by user who called minbleicrequesttermination().
47492 : X contains point which was "current accepted" when
47493 : termination request was submitted.
47494 : More information about fields of this structure can be
47495 : found in the comments on MinBLEICReport datatype.
47496 :
47497 : -- ALGLIB --
47498 : Copyright 28.11.2010 by Bochkanov Sergey
47499 : *************************************************************************/
47500 0 : void minbleicresults(minbleicstate* state,
47501 : /* Real */ ae_vector* x,
47502 : minbleicreport* rep,
47503 : ae_state *_state)
47504 : {
47505 :
47506 0 : ae_vector_clear(x);
47507 0 : _minbleicreport_clear(rep);
47508 :
47509 0 : minbleicresultsbuf(state, x, rep, _state);
47510 0 : }
47511 :
47512 :
47513 : /*************************************************************************
47514 : BLEIC results
47515 :
47516 : Buffered implementation of MinBLEICResults() which uses pre-allocated buffer
47517 : to store X[]. If buffer size is too small, it resizes buffer. It is
47518 : intended to be used in the inner cycles of performance critical algorithms
47519 : where array reallocation penalty is too large to be ignored.
47520 :
47521 : -- ALGLIB --
47522 : Copyright 28.11.2010 by Bochkanov Sergey
47523 : *************************************************************************/
47524 0 : void minbleicresultsbuf(minbleicstate* state,
47525 : /* Real */ ae_vector* x,
47526 : minbleicreport* rep,
47527 : ae_state *_state)
47528 : {
47529 : ae_int_t i;
47530 :
47531 :
47532 0 : if( x->cnt<state->nmain )
47533 : {
47534 0 : ae_vector_set_length(x, state->nmain, _state);
47535 : }
47536 0 : rep->iterationscount = state->repinneriterationscount;
47537 0 : rep->inneriterationscount = state->repinneriterationscount;
47538 0 : rep->outeriterationscount = state->repouteriterationscount;
47539 0 : rep->nfev = state->repnfev;
47540 0 : rep->varidx = state->repvaridx;
47541 0 : rep->terminationtype = state->repterminationtype;
47542 0 : if( state->repterminationtype>0 )
47543 : {
47544 0 : ae_v_move(&x->ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,state->nmain-1));
47545 : }
47546 : else
47547 : {
47548 0 : for(i=0; i<=state->nmain-1; i++)
47549 : {
47550 0 : x->ptr.p_double[i] = _state->v_nan;
47551 : }
47552 : }
47553 0 : rep->debugeqerr = state->repdebugeqerr;
47554 0 : rep->debugfs = state->repdebugfs;
47555 0 : rep->debugff = state->repdebugff;
47556 0 : rep->debugdx = state->repdebugdx;
47557 0 : rep->debugfeasqpits = state->repdebugfeasqpits;
47558 0 : rep->debugfeasgpaits = state->repdebugfeasgpaits;
47559 0 : }
47560 :
47561 :
47562 : /*************************************************************************
47563 : This subroutine restarts algorithm from new point.
47564 : All optimization parameters (including constraints) are left unchanged.
47565 :
47566 : This function allows to solve multiple optimization problems (which
47567 : must have same number of dimensions) without object reallocation penalty.
47568 :
47569 : INPUT PARAMETERS:
47570 : State - structure previously allocated with MinBLEICCreate call.
47571 : X - new starting point.
47572 :
47573 : -- ALGLIB --
47574 : Copyright 28.11.2010 by Bochkanov Sergey
47575 : *************************************************************************/
47576 0 : void minbleicrestartfrom(minbleicstate* state,
47577 : /* Real */ ae_vector* x,
47578 : ae_state *_state)
47579 : {
47580 : ae_int_t n;
47581 :
47582 :
47583 0 : n = state->nmain;
47584 :
47585 : /*
47586 : * First, check for errors in the inputs
47587 : */
47588 0 : ae_assert(x->cnt>=n, "MinBLEICRestartFrom: Length(X)<N", _state);
47589 0 : ae_assert(isfinitevector(x, n, _state), "MinBLEICRestartFrom: X contains infinite or NaN values!", _state);
47590 :
47591 : /*
47592 : * Set XC
47593 : */
47594 0 : ae_v_move(&state->xstart.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
47595 :
47596 : /*
47597 : * prepare RComm facilities
47598 : */
47599 0 : ae_vector_set_length(&state->rstate.ia, 6+1, _state);
47600 0 : ae_vector_set_length(&state->rstate.ba, 0+1, _state);
47601 0 : ae_vector_set_length(&state->rstate.ra, 5+1, _state);
47602 0 : state->rstate.stage = -1;
47603 0 : minbleic_clearrequestfields(state, _state);
47604 0 : sasstopoptimization(&state->sas, _state);
47605 0 : }
47606 :
47607 :
47608 : /*************************************************************************
47609 : This subroutine submits request for termination of running optimizer. It
47610 : should be called from user-supplied callback when user decides that it is
47611 : time to "smoothly" terminate optimization process. As result, optimizer
47612 : stops at point which was "current accepted" when termination request was
47613 : submitted and returns error code 8 (successful termination).
47614 :
47615 : INPUT PARAMETERS:
47616 : State - optimizer structure
47617 :
47618 : NOTE: after request for termination optimizer may perform several
47619 : additional calls to user-supplied callbacks. It does NOT guarantee
47620 : to stop immediately - it just guarantees that these additional calls
47621 : will be discarded later.
47622 :
47623 : NOTE: calling this function on optimizer which is NOT running will have no
47624 : effect.
47625 :
47626 : NOTE: multiple calls to this function are possible. First call is counted,
47627 : subsequent calls are silently ignored.
47628 :
47629 : -- ALGLIB --
47630 : Copyright 08.10.2014 by Bochkanov Sergey
47631 : *************************************************************************/
47632 0 : void minbleicrequesttermination(minbleicstate* state, ae_state *_state)
47633 : {
47634 :
47635 :
47636 0 : state->userterminationneeded = ae_true;
47637 0 : }
47638 :
47639 :
47640 : /*************************************************************************
47641 : This subroutine finalizes internal structures after emergency termination
47642 : from State.LSStart report (see comments on MinBLEICState for more information).
47643 :
47644 : INPUT PARAMETERS:
47645 : State - structure after exit from LSStart report
47646 :
47647 : -- ALGLIB --
47648 : Copyright 28.11.2010 by Bochkanov Sergey
47649 : *************************************************************************/
47650 0 : void minbleicemergencytermination(minbleicstate* state, ae_state *_state)
47651 : {
47652 :
47653 :
47654 0 : sasstopoptimization(&state->sas, _state);
47655 0 : }
47656 :
47657 :
47658 : /*************************************************************************
47659 : Clears request fileds (to be sure that we don't forget to clear something)
47660 : *************************************************************************/
47661 0 : static void minbleic_clearrequestfields(minbleicstate* state,
47662 : ae_state *_state)
47663 : {
47664 :
47665 :
47666 0 : state->needf = ae_false;
47667 0 : state->needfg = ae_false;
47668 0 : state->xupdated = ae_false;
47669 0 : state->lsstart = ae_false;
47670 0 : }
47671 :
47672 :
47673 : /*************************************************************************
47674 : Internal initialization subroutine
47675 : *************************************************************************/
47676 0 : static void minbleic_minbleicinitinternal(ae_int_t n,
47677 : /* Real */ ae_vector* x,
47678 : double diffstep,
47679 : minbleicstate* state,
47680 : ae_state *_state)
47681 : {
47682 : ae_frame _frame_block;
47683 : ae_int_t i;
47684 : ae_matrix c;
47685 : ae_vector ct;
47686 :
47687 0 : ae_frame_make(_state, &_frame_block);
47688 0 : memset(&c, 0, sizeof(c));
47689 0 : memset(&ct, 0, sizeof(ct));
47690 0 : ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
47691 0 : ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
47692 :
47693 :
47694 : /*
47695 : * Initialize
47696 : */
47697 0 : state->teststep = (double)(0);
47698 0 : state->smoothnessguardlevel = 0;
47699 0 : smoothnessmonitorinit(&state->smonitor, &state->s, 0, 0, ae_false, _state);
47700 0 : state->nmain = n;
47701 0 : state->diffstep = diffstep;
47702 0 : sasinit(n, &state->sas, _state);
47703 0 : ae_vector_set_length(&state->bndl, n, _state);
47704 0 : ae_vector_set_length(&state->hasbndl, n, _state);
47705 0 : ae_vector_set_length(&state->bndu, n, _state);
47706 0 : ae_vector_set_length(&state->hasbndu, n, _state);
47707 0 : ae_vector_set_length(&state->xstart, n, _state);
47708 0 : ae_vector_set_length(&state->cgc, n, _state);
47709 0 : ae_vector_set_length(&state->ugc, n, _state);
47710 0 : ae_vector_set_length(&state->xn, n, _state);
47711 0 : ae_vector_set_length(&state->cgn, n, _state);
47712 0 : ae_vector_set_length(&state->ugn, n, _state);
47713 0 : ae_vector_set_length(&state->xp, n, _state);
47714 0 : ae_vector_set_length(&state->d, n, _state);
47715 0 : ae_vector_set_length(&state->s, n, _state);
47716 0 : ae_vector_set_length(&state->invs, n, _state);
47717 0 : ae_vector_set_length(&state->lastscaleused, n, _state);
47718 0 : ae_vector_set_length(&state->x, n, _state);
47719 0 : ae_vector_set_length(&state->g, n, _state);
47720 0 : ae_vector_set_length(&state->work, n, _state);
47721 0 : for(i=0; i<=n-1; i++)
47722 : {
47723 0 : state->bndl.ptr.p_double[i] = _state->v_neginf;
47724 0 : state->hasbndl.ptr.p_bool[i] = ae_false;
47725 0 : state->bndu.ptr.p_double[i] = _state->v_posinf;
47726 0 : state->hasbndu.ptr.p_bool[i] = ae_false;
47727 0 : state->s.ptr.p_double[i] = 1.0;
47728 0 : state->invs.ptr.p_double[i] = 1.0;
47729 0 : state->lastscaleused.ptr.p_double[i] = 1.0;
47730 : }
47731 0 : minbleicsetlc(state, &c, &ct, 0, _state);
47732 0 : minbleicsetcond(state, 0.0, 0.0, 0.0, 0, _state);
47733 0 : minbleicsetxrep(state, ae_false, _state);
47734 0 : minbleicsetdrep(state, ae_false, _state);
47735 0 : minbleicsetstpmax(state, 0.0, _state);
47736 0 : minbleicsetprecdefault(state, _state);
47737 0 : minbleicrestartfrom(state, x, _state);
47738 0 : ae_frame_leave(_state);
47739 0 : }
47740 :
47741 :
47742 : /*************************************************************************
47743 : This subroutine updates estimate of the good step length given:
47744 : 1) previous estimate
47745 : 2) new length of the good step
47746 :
47747 : It makes sure that estimate does not change too rapidly - ratio of new and
47748 : old estimates will be at least 0.01, at most 100.0
47749 :
47750 : In case previous estimate of good step is zero (no estimate), new estimate
47751 : is used unconditionally.
47752 :
47753 : -- ALGLIB --
47754 : Copyright 16.01.2013 by Bochkanov Sergey
47755 : *************************************************************************/
47756 0 : static void minbleic_updateestimateofgoodstep(double* estimate,
47757 : double newstep,
47758 : ae_state *_state)
47759 : {
47760 :
47761 :
47762 0 : if( ae_fp_eq(*estimate,(double)(0)) )
47763 : {
47764 0 : *estimate = newstep;
47765 0 : return;
47766 : }
47767 0 : if( ae_fp_less(newstep,*estimate*0.01) )
47768 : {
47769 0 : *estimate = *estimate*0.01;
47770 0 : return;
47771 : }
47772 0 : if( ae_fp_greater(newstep,*estimate*100) )
47773 : {
47774 0 : *estimate = *estimate*100;
47775 0 : return;
47776 : }
47777 0 : *estimate = newstep;
47778 : }
47779 :
47780 :
47781 : /*************************************************************************
47782 : This subroutine estimates relative feasibility error of the point.
47783 :
47784 : INPUT PARAMETERS:
47785 : X - current point (unscaled)
47786 : S - scale vector
47787 : N - dimensionality
47788 : CLEIC - array[NEC+NIC,N+1], constraint matrix, may be unnormalized
47789 : NEC - number of equality constraints (come first)
47790 : NIC - number of inequality constraints (come last)
47791 :
47792 : RESULT
47793 : feasibility error, good value is ~1E-16...1E-14
47794 :
47795 : -- ALGLIB --
47796 : Copyright 16.01.2013 by Bochkanov Sergey
47797 : *************************************************************************/
47798 0 : static double minbleic_feasibilityerror(/* Real */ ae_vector* x,
47799 : /* Real */ ae_vector* s,
47800 : ae_int_t n,
47801 : /* Real */ ae_matrix* cleic,
47802 : ae_int_t nec,
47803 : ae_int_t nic,
47804 : ae_state *_state)
47805 : {
47806 : ae_int_t i;
47807 : ae_int_t j;
47808 : double v;
47809 : double v0;
47810 : double v1;
47811 : double vc;
47812 : double vx;
47813 : double result;
47814 :
47815 :
47816 0 : result = (double)(0);
47817 0 : for(i=0; i<=nec+nic-1; i++)
47818 : {
47819 0 : v = -cleic->ptr.pp_double[i][n];
47820 0 : v0 = (double)(0);
47821 0 : v1 = (double)(0);
47822 0 : for(j=0; j<=n-1; j++)
47823 : {
47824 0 : vc = cleic->ptr.pp_double[i][j]*s->ptr.p_double[j];
47825 0 : vx = x->ptr.p_double[j]/s->ptr.p_double[j];
47826 0 : v = v+vc*vx;
47827 0 : v0 = v0+ae_sqr(vc, _state);
47828 0 : v1 = v1+ae_sqr(vx, _state);
47829 : }
47830 0 : v0 = coalesce(ae_sqrt(v0, _state), (double)(1), _state);
47831 0 : v1 = ae_maxreal(ae_sqrt(v1, _state), (double)(1), _state);
47832 0 : if( i<nec )
47833 : {
47834 0 : v = ae_fabs(v, _state);
47835 : }
47836 : else
47837 : {
47838 0 : v = ae_maxreal(v, (double)(0), _state);
47839 : }
47840 0 : result = ae_maxreal(result, v/(v0*v1), _state);
47841 : }
47842 0 : return result;
47843 : }
47844 :
47845 :
47846 0 : void _minbleicstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
47847 : {
47848 0 : minbleicstate *p = (minbleicstate*)_p;
47849 0 : ae_touch_ptr((void*)p);
47850 0 : _sactiveset_init(&p->sas, _state, make_automatic);
47851 0 : ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic);
47852 0 : ae_vector_init(&p->diagh, 0, DT_REAL, _state, make_automatic);
47853 0 : ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
47854 0 : ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic);
47855 0 : _rcommstate_init(&p->rstate, _state, make_automatic);
47856 0 : ae_vector_init(&p->ugc, 0, DT_REAL, _state, make_automatic);
47857 0 : ae_vector_init(&p->cgc, 0, DT_REAL, _state, make_automatic);
47858 0 : ae_vector_init(&p->xn, 0, DT_REAL, _state, make_automatic);
47859 0 : ae_vector_init(&p->ugn, 0, DT_REAL, _state, make_automatic);
47860 0 : ae_vector_init(&p->cgn, 0, DT_REAL, _state, make_automatic);
47861 0 : ae_vector_init(&p->xp, 0, DT_REAL, _state, make_automatic);
47862 0 : ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic);
47863 0 : ae_matrix_init(&p->cleic, 0, 0, DT_REAL, _state, make_automatic);
47864 0 : ae_vector_init(&p->hasbndl, 0, DT_BOOL, _state, make_automatic);
47865 0 : ae_vector_init(&p->hasbndu, 0, DT_BOOL, _state, make_automatic);
47866 0 : ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic);
47867 0 : ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic);
47868 0 : ae_vector_init(&p->xstart, 0, DT_REAL, _state, make_automatic);
47869 0 : _snnlssolver_init(&p->solver, _state, make_automatic);
47870 0 : ae_vector_init(&p->tmpprec, 0, DT_REAL, _state, make_automatic);
47871 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
47872 0 : ae_vector_init(&p->work, 0, DT_REAL, _state, make_automatic);
47873 0 : _linminstate_init(&p->lstate, _state, make_automatic);
47874 0 : ae_matrix_init(&p->bufyk, 0, 0, DT_REAL, _state, make_automatic);
47875 0 : ae_matrix_init(&p->bufsk, 0, 0, DT_REAL, _state, make_automatic);
47876 0 : ae_vector_init(&p->bufrho, 0, DT_REAL, _state, make_automatic);
47877 0 : ae_vector_init(&p->buftheta, 0, DT_REAL, _state, make_automatic);
47878 0 : _smoothnessmonitor_init(&p->smonitor, _state, make_automatic);
47879 0 : ae_vector_init(&p->lastscaleused, 0, DT_REAL, _state, make_automatic);
47880 0 : ae_vector_init(&p->invs, 0, DT_REAL, _state, make_automatic);
47881 0 : }
47882 :
47883 :
47884 0 : void _minbleicstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
47885 : {
47886 0 : minbleicstate *dst = (minbleicstate*)_dst;
47887 0 : minbleicstate *src = (minbleicstate*)_src;
47888 0 : dst->nmain = src->nmain;
47889 0 : dst->nslack = src->nslack;
47890 0 : dst->epsg = src->epsg;
47891 0 : dst->epsf = src->epsf;
47892 0 : dst->epsx = src->epsx;
47893 0 : dst->maxits = src->maxits;
47894 0 : dst->xrep = src->xrep;
47895 0 : dst->drep = src->drep;
47896 0 : dst->stpmax = src->stpmax;
47897 0 : dst->diffstep = src->diffstep;
47898 0 : _sactiveset_init_copy(&dst->sas, &src->sas, _state, make_automatic);
47899 0 : ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic);
47900 0 : dst->prectype = src->prectype;
47901 0 : ae_vector_init_copy(&dst->diagh, &src->diagh, _state, make_automatic);
47902 0 : ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
47903 0 : dst->f = src->f;
47904 0 : ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic);
47905 0 : dst->needf = src->needf;
47906 0 : dst->needfg = src->needfg;
47907 0 : dst->xupdated = src->xupdated;
47908 0 : dst->lsstart = src->lsstart;
47909 0 : dst->steepestdescentstep = src->steepestdescentstep;
47910 0 : dst->boundedstep = src->boundedstep;
47911 0 : dst->userterminationneeded = src->userterminationneeded;
47912 0 : _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic);
47913 0 : ae_vector_init_copy(&dst->ugc, &src->ugc, _state, make_automatic);
47914 0 : ae_vector_init_copy(&dst->cgc, &src->cgc, _state, make_automatic);
47915 0 : ae_vector_init_copy(&dst->xn, &src->xn, _state, make_automatic);
47916 0 : ae_vector_init_copy(&dst->ugn, &src->ugn, _state, make_automatic);
47917 0 : ae_vector_init_copy(&dst->cgn, &src->cgn, _state, make_automatic);
47918 0 : ae_vector_init_copy(&dst->xp, &src->xp, _state, make_automatic);
47919 0 : dst->fc = src->fc;
47920 0 : dst->fn = src->fn;
47921 0 : dst->fp = src->fp;
47922 0 : ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic);
47923 0 : ae_matrix_init_copy(&dst->cleic, &src->cleic, _state, make_automatic);
47924 0 : dst->nec = src->nec;
47925 0 : dst->nic = src->nic;
47926 0 : dst->lastgoodstep = src->lastgoodstep;
47927 0 : dst->lastscaledgoodstep = src->lastscaledgoodstep;
47928 0 : dst->maxscaledgrad = src->maxscaledgrad;
47929 0 : ae_vector_init_copy(&dst->hasbndl, &src->hasbndl, _state, make_automatic);
47930 0 : ae_vector_init_copy(&dst->hasbndu, &src->hasbndu, _state, make_automatic);
47931 0 : ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic);
47932 0 : ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic);
47933 0 : dst->repinneriterationscount = src->repinneriterationscount;
47934 0 : dst->repouteriterationscount = src->repouteriterationscount;
47935 0 : dst->repnfev = src->repnfev;
47936 0 : dst->repvaridx = src->repvaridx;
47937 0 : dst->repterminationtype = src->repterminationtype;
47938 0 : dst->repdebugeqerr = src->repdebugeqerr;
47939 0 : dst->repdebugfs = src->repdebugfs;
47940 0 : dst->repdebugff = src->repdebugff;
47941 0 : dst->repdebugdx = src->repdebugdx;
47942 0 : dst->repdebugfeasqpits = src->repdebugfeasqpits;
47943 0 : dst->repdebugfeasgpaits = src->repdebugfeasgpaits;
47944 0 : ae_vector_init_copy(&dst->xstart, &src->xstart, _state, make_automatic);
47945 0 : _snnlssolver_init_copy(&dst->solver, &src->solver, _state, make_automatic);
47946 0 : dst->fbase = src->fbase;
47947 0 : dst->fm2 = src->fm2;
47948 0 : dst->fm1 = src->fm1;
47949 0 : dst->fp1 = src->fp1;
47950 0 : dst->fp2 = src->fp2;
47951 0 : dst->xm1 = src->xm1;
47952 0 : dst->xp1 = src->xp1;
47953 0 : dst->gm1 = src->gm1;
47954 0 : dst->gp1 = src->gp1;
47955 0 : dst->cidx = src->cidx;
47956 0 : dst->cval = src->cval;
47957 0 : ae_vector_init_copy(&dst->tmpprec, &src->tmpprec, _state, make_automatic);
47958 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
47959 0 : dst->nfev = src->nfev;
47960 0 : dst->mcstage = src->mcstage;
47961 0 : dst->stp = src->stp;
47962 0 : dst->curstpmax = src->curstpmax;
47963 0 : dst->activationstep = src->activationstep;
47964 0 : ae_vector_init_copy(&dst->work, &src->work, _state, make_automatic);
47965 0 : _linminstate_init_copy(&dst->lstate, &src->lstate, _state, make_automatic);
47966 0 : dst->trimthreshold = src->trimthreshold;
47967 0 : dst->nonmonotoniccnt = src->nonmonotoniccnt;
47968 0 : ae_matrix_init_copy(&dst->bufyk, &src->bufyk, _state, make_automatic);
47969 0 : ae_matrix_init_copy(&dst->bufsk, &src->bufsk, _state, make_automatic);
47970 0 : ae_vector_init_copy(&dst->bufrho, &src->bufrho, _state, make_automatic);
47971 0 : ae_vector_init_copy(&dst->buftheta, &src->buftheta, _state, make_automatic);
47972 0 : dst->bufsize = src->bufsize;
47973 0 : dst->teststep = src->teststep;
47974 0 : dst->smoothnessguardlevel = src->smoothnessguardlevel;
47975 0 : _smoothnessmonitor_init_copy(&dst->smonitor, &src->smonitor, _state, make_automatic);
47976 0 : ae_vector_init_copy(&dst->lastscaleused, &src->lastscaleused, _state, make_automatic);
47977 0 : ae_vector_init_copy(&dst->invs, &src->invs, _state, make_automatic);
47978 0 : }
47979 :
47980 :
47981 0 : void _minbleicstate_clear(void* _p)
47982 : {
47983 0 : minbleicstate *p = (minbleicstate*)_p;
47984 0 : ae_touch_ptr((void*)p);
47985 0 : _sactiveset_clear(&p->sas);
47986 0 : ae_vector_clear(&p->s);
47987 0 : ae_vector_clear(&p->diagh);
47988 0 : ae_vector_clear(&p->x);
47989 0 : ae_vector_clear(&p->g);
47990 0 : _rcommstate_clear(&p->rstate);
47991 0 : ae_vector_clear(&p->ugc);
47992 0 : ae_vector_clear(&p->cgc);
47993 0 : ae_vector_clear(&p->xn);
47994 0 : ae_vector_clear(&p->ugn);
47995 0 : ae_vector_clear(&p->cgn);
47996 0 : ae_vector_clear(&p->xp);
47997 0 : ae_vector_clear(&p->d);
47998 0 : ae_matrix_clear(&p->cleic);
47999 0 : ae_vector_clear(&p->hasbndl);
48000 0 : ae_vector_clear(&p->hasbndu);
48001 0 : ae_vector_clear(&p->bndl);
48002 0 : ae_vector_clear(&p->bndu);
48003 0 : ae_vector_clear(&p->xstart);
48004 0 : _snnlssolver_clear(&p->solver);
48005 0 : ae_vector_clear(&p->tmpprec);
48006 0 : ae_vector_clear(&p->tmp0);
48007 0 : ae_vector_clear(&p->work);
48008 0 : _linminstate_clear(&p->lstate);
48009 0 : ae_matrix_clear(&p->bufyk);
48010 0 : ae_matrix_clear(&p->bufsk);
48011 0 : ae_vector_clear(&p->bufrho);
48012 0 : ae_vector_clear(&p->buftheta);
48013 0 : _smoothnessmonitor_clear(&p->smonitor);
48014 0 : ae_vector_clear(&p->lastscaleused);
48015 0 : ae_vector_clear(&p->invs);
48016 0 : }
48017 :
48018 :
48019 0 : void _minbleicstate_destroy(void* _p)
48020 : {
48021 0 : minbleicstate *p = (minbleicstate*)_p;
48022 0 : ae_touch_ptr((void*)p);
48023 0 : _sactiveset_destroy(&p->sas);
48024 0 : ae_vector_destroy(&p->s);
48025 0 : ae_vector_destroy(&p->diagh);
48026 0 : ae_vector_destroy(&p->x);
48027 0 : ae_vector_destroy(&p->g);
48028 0 : _rcommstate_destroy(&p->rstate);
48029 0 : ae_vector_destroy(&p->ugc);
48030 0 : ae_vector_destroy(&p->cgc);
48031 0 : ae_vector_destroy(&p->xn);
48032 0 : ae_vector_destroy(&p->ugn);
48033 0 : ae_vector_destroy(&p->cgn);
48034 0 : ae_vector_destroy(&p->xp);
48035 0 : ae_vector_destroy(&p->d);
48036 0 : ae_matrix_destroy(&p->cleic);
48037 0 : ae_vector_destroy(&p->hasbndl);
48038 0 : ae_vector_destroy(&p->hasbndu);
48039 0 : ae_vector_destroy(&p->bndl);
48040 0 : ae_vector_destroy(&p->bndu);
48041 0 : ae_vector_destroy(&p->xstart);
48042 0 : _snnlssolver_destroy(&p->solver);
48043 0 : ae_vector_destroy(&p->tmpprec);
48044 0 : ae_vector_destroy(&p->tmp0);
48045 0 : ae_vector_destroy(&p->work);
48046 0 : _linminstate_destroy(&p->lstate);
48047 0 : ae_matrix_destroy(&p->bufyk);
48048 0 : ae_matrix_destroy(&p->bufsk);
48049 0 : ae_vector_destroy(&p->bufrho);
48050 0 : ae_vector_destroy(&p->buftheta);
48051 0 : _smoothnessmonitor_destroy(&p->smonitor);
48052 0 : ae_vector_destroy(&p->lastscaleused);
48053 0 : ae_vector_destroy(&p->invs);
48054 0 : }
48055 :
48056 :
48057 0 : void _minbleicreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
48058 : {
48059 0 : minbleicreport *p = (minbleicreport*)_p;
48060 0 : ae_touch_ptr((void*)p);
48061 0 : }
48062 :
48063 :
48064 0 : void _minbleicreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
48065 : {
48066 0 : minbleicreport *dst = (minbleicreport*)_dst;
48067 0 : minbleicreport *src = (minbleicreport*)_src;
48068 0 : dst->iterationscount = src->iterationscount;
48069 0 : dst->nfev = src->nfev;
48070 0 : dst->varidx = src->varidx;
48071 0 : dst->terminationtype = src->terminationtype;
48072 0 : dst->debugeqerr = src->debugeqerr;
48073 0 : dst->debugfs = src->debugfs;
48074 0 : dst->debugff = src->debugff;
48075 0 : dst->debugdx = src->debugdx;
48076 0 : dst->debugfeasqpits = src->debugfeasqpits;
48077 0 : dst->debugfeasgpaits = src->debugfeasgpaits;
48078 0 : dst->inneriterationscount = src->inneriterationscount;
48079 0 : dst->outeriterationscount = src->outeriterationscount;
48080 0 : }
48081 :
48082 :
48083 0 : void _minbleicreport_clear(void* _p)
48084 : {
48085 0 : minbleicreport *p = (minbleicreport*)_p;
48086 0 : ae_touch_ptr((void*)p);
48087 0 : }
48088 :
48089 :
48090 0 : void _minbleicreport_destroy(void* _p)
48091 : {
48092 0 : minbleicreport *p = (minbleicreport*)_p;
48093 0 : ae_touch_ptr((void*)p);
48094 0 : }
48095 :
48096 :
48097 : #endif
48098 : #if defined(AE_COMPILE_QPBLEICSOLVER) || !defined(AE_PARTIAL_BUILD)
48099 :
48100 :
48101 : /*************************************************************************
48102 : This function initializes QPBLEICSettings structure with default settings.
48103 :
48104 : Newly created structure MUST be initialized by default settings - or by
48105 : copy of the already initialized structure.
48106 :
48107 : -- ALGLIB --
48108 : Copyright 14.05.2011 by Bochkanov Sergey
48109 : *************************************************************************/
48110 0 : void qpbleicloaddefaults(ae_int_t nmain,
48111 : qpbleicsettings* s,
48112 : ae_state *_state)
48113 : {
48114 :
48115 :
48116 0 : s->epsg = 0.0;
48117 0 : s->epsf = 0.0;
48118 0 : s->epsx = 1.0E-6;
48119 0 : s->maxits = 0;
48120 0 : }
48121 :
48122 :
48123 : /*************************************************************************
48124 : This function initializes QPBLEICSettings structure with copy of another,
48125 : already initialized structure.
48126 :
48127 : -- ALGLIB --
48128 : Copyright 14.05.2011 by Bochkanov Sergey
48129 : *************************************************************************/
48130 0 : void qpbleiccopysettings(qpbleicsettings* src,
48131 : qpbleicsettings* dst,
48132 : ae_state *_state)
48133 : {
48134 :
48135 :
48136 0 : dst->epsg = src->epsg;
48137 0 : dst->epsf = src->epsf;
48138 0 : dst->epsx = src->epsx;
48139 0 : dst->maxits = src->maxits;
48140 0 : }
48141 :
48142 :
48143 : /*************************************************************************
48144 : This function runs QPBLEIC solver; it returns after optimization process
48145 : was completed. Following QP problem is solved:
48146 :
48147 : min(0.5*(x-x_origin)'*A*(x-x_origin)+b'*(x-x_origin))
48148 :
48149 : subject to boundary constraints.
48150 :
48151 : INPUT PARAMETERS:
48152 : AC - for dense problems (AKind=0), A-term of CQM object
48153 : contains system matrix. Other terms are unspecified
48154 : and should not be referenced.
48155 : SparseAC - for sparse problems (AKind=1
48156 : AKind - sparse matrix format:
48157 : * 0 for dense matrix
48158 : * 1 for sparse matrix
48159 : SparseUpper - which triangle of SparseAC stores matrix - upper or
48160 : lower one (for dense matrices this parameter is not
48161 : actual).
48162 : AbsASum - SUM(|A[i,j]|)
48163 : AbsASum2 - SUM(A[i,j]^2)
48164 : BC - linear term, array[NC]
48165 : BndLC - lower bound, array[NC]
48166 : BndUC - upper bound, array[NC]
48167 : SC - scale vector, array[NC]:
48168 : * I-th element contains scale of I-th variable,
48169 : * SC[I]>0
48170 : XOriginC - origin term, array[NC]. Can be zero.
48171 : NC - number of variables in the original formulation (no
48172 : slack variables).
48173 : CLEICC - linear equality/inequality constraints. Present version
48174 : of this function does NOT provide publicly available
48175 : support for linear constraints. This feature will be
48176 : introduced in the future versions of the function.
48177 : NEC, NIC - number of equality/inequality constraints.
48178 : MUST BE ZERO IN THE CURRENT VERSION!!!
48179 : Settings - QPBLEICSettings object initialized by one of the initialization
48180 : functions.
48181 : SState - object which stores temporaries:
48182 : * if uninitialized object was passed, FirstCall parameter MUST
48183 : be set to True; object will be automatically initialized by the
48184 : function, and FirstCall will be set to False.
48185 : * if FirstCall=False, it is assumed that this parameter was already
48186 : initialized by previous call to this function with same
48187 : problem dimensions (variable count N).
48188 : FirstCall - whether it is first call of this function for this specific
48189 : instance of SState, with this number of variables N specified.
48190 : XS - initial point, array[NC]
48191 :
48192 :
48193 : OUTPUT PARAMETERS:
48194 : XS - last point
48195 : FirstCall - uncondtionally set to False
48196 : TerminationType-termination type:
48197 : *
48198 : *
48199 : *
48200 :
48201 : -- ALGLIB --
48202 : Copyright 14.05.2011 by Bochkanov Sergey
48203 : *************************************************************************/
48204 0 : void qpbleicoptimize(convexquadraticmodel* a,
48205 : sparsematrix* sparsea,
48206 : ae_int_t akind,
48207 : ae_bool sparseaupper,
48208 : double absasum,
48209 : double absasum2,
48210 : /* Real */ ae_vector* b,
48211 : /* Real */ ae_vector* bndl,
48212 : /* Real */ ae_vector* bndu,
48213 : /* Real */ ae_vector* s,
48214 : /* Real */ ae_vector* xorigin,
48215 : ae_int_t n,
48216 : /* Real */ ae_matrix* cleic,
48217 : ae_int_t nec,
48218 : ae_int_t nic,
48219 : qpbleicsettings* settings,
48220 : qpbleicbuffers* sstate,
48221 : ae_bool* firstcall,
48222 : /* Real */ ae_vector* xs,
48223 : ae_int_t* terminationtype,
48224 : ae_state *_state)
48225 : {
48226 : ae_int_t i;
48227 : double d2;
48228 : double d1;
48229 : double d0;
48230 : double v;
48231 : double v0;
48232 : double v1;
48233 : double md;
48234 : double mx;
48235 : double mb;
48236 : ae_int_t d1est;
48237 : ae_int_t d2est;
48238 :
48239 0 : *terminationtype = 0;
48240 :
48241 0 : ae_assert(akind==0||akind==1, "QPBLEICOptimize: unexpected AKind", _state);
48242 0 : sstate->repinneriterationscount = 0;
48243 0 : sstate->repouteriterationscount = 0;
48244 0 : *terminationtype = 0;
48245 :
48246 : /*
48247 : * Prepare solver object, if needed
48248 : */
48249 0 : if( *firstcall )
48250 : {
48251 0 : minbleiccreate(n, xs, &sstate->solver, _state);
48252 0 : *firstcall = ae_false;
48253 : }
48254 :
48255 : /*
48256 : * Prepare max(|B|)
48257 : */
48258 0 : mb = 0.0;
48259 0 : for(i=0; i<=n-1; i++)
48260 : {
48261 0 : mb = ae_maxreal(mb, ae_fabs(b->ptr.p_double[i], _state), _state);
48262 : }
48263 :
48264 : /*
48265 : * Temporaries
48266 : */
48267 0 : ivectorsetlengthatleast(&sstate->tmpi, nec+nic, _state);
48268 0 : rvectorsetlengthatleast(&sstate->tmp0, n, _state);
48269 0 : rvectorsetlengthatleast(&sstate->tmp1, n, _state);
48270 0 : for(i=0; i<=nec-1; i++)
48271 : {
48272 0 : sstate->tmpi.ptr.p_int[i] = 0;
48273 : }
48274 0 : for(i=0; i<=nic-1; i++)
48275 : {
48276 0 : sstate->tmpi.ptr.p_int[nec+i] = -1;
48277 : }
48278 0 : minbleicsetlc(&sstate->solver, cleic, &sstate->tmpi, nec+nic, _state);
48279 0 : minbleicsetbc(&sstate->solver, bndl, bndu, _state);
48280 0 : minbleicsetdrep(&sstate->solver, ae_true, _state);
48281 0 : minbleicsetcond(&sstate->solver, ae_minrealnumber, 0.0, 0.0, settings->maxits, _state);
48282 0 : minbleicsetscale(&sstate->solver, s, _state);
48283 0 : minbleicsetprecscale(&sstate->solver, _state);
48284 0 : minbleicrestartfrom(&sstate->solver, xs, _state);
48285 0 : while(minbleiciteration(&sstate->solver, _state))
48286 : {
48287 :
48288 : /*
48289 : * Line search started
48290 : */
48291 0 : if( sstate->solver.lsstart )
48292 : {
48293 :
48294 : /*
48295 : * Iteration counters:
48296 : * * inner iterations count is increased on every line search
48297 : * * outer iterations count is increased only at steepest descent line search
48298 : */
48299 0 : inc(&sstate->repinneriterationscount, _state);
48300 0 : if( sstate->solver.steepestdescentstep )
48301 : {
48302 0 : inc(&sstate->repouteriterationscount, _state);
48303 : }
48304 :
48305 : /*
48306 : * Build quadratic model of F along descent direction:
48307 : *
48308 : * F(x+alpha*d) = D2*alpha^2 + D1*alpha + D0
48309 : *
48310 : * Calculate estimates of linear and quadratic term
48311 : * (term magnitude is compared with magnitude of numerical errors)
48312 : */
48313 0 : d0 = sstate->solver.f;
48314 0 : d1 = ae_v_dotproduct(&sstate->solver.d.ptr.p_double[0], 1, &sstate->solver.g.ptr.p_double[0], 1, ae_v_len(0,n-1));
48315 0 : d2 = (double)(0);
48316 0 : if( akind==0 )
48317 : {
48318 0 : d2 = cqmxtadx2(a, &sstate->solver.d, &sstate->tmp0, _state);
48319 : }
48320 0 : if( akind==1 )
48321 : {
48322 0 : sparsesmv(sparsea, sparseaupper, &sstate->solver.d, &sstate->tmp0, _state);
48323 0 : d2 = 0.0;
48324 0 : for(i=0; i<=n-1; i++)
48325 : {
48326 0 : d2 = d2+sstate->solver.d.ptr.p_double[i]*sstate->tmp0.ptr.p_double[i];
48327 : }
48328 0 : d2 = 0.5*d2;
48329 : }
48330 0 : mx = 0.0;
48331 0 : md = 0.0;
48332 0 : for(i=0; i<=n-1; i++)
48333 : {
48334 0 : mx = ae_maxreal(mx, ae_fabs(sstate->solver.x.ptr.p_double[i], _state), _state);
48335 0 : md = ae_maxreal(md, ae_fabs(sstate->solver.d.ptr.p_double[i], _state), _state);
48336 : }
48337 0 : estimateparabolicmodel(absasum, absasum2, mx, mb, md, d1, d2, &d1est, &d2est, _state);
48338 :
48339 : /*
48340 : * Tests for "normal" convergence.
48341 : *
48342 : * This line search may be started from steepest descent
48343 : * stage (stage 2) or from L-BFGS stage (stage 3) of the
48344 : * BLEIC algorithm. Depending on stage type, different
48345 : * checks are performed.
48346 : *
48347 : * Say, L-BFGS stage is an equality-constrained refinement
48348 : * stage of BLEIC. This stage refines current iterate
48349 : * under "frozen" equality constraints. We can terminate
48350 : * iterations at this stage only when we encounter
48351 : * unconstrained direction of negative curvature. In all
48352 : * other cases (say, when constrained gradient is zero)
48353 : * we should not terminate algorithm because everything may
48354 : * change after de-activating presently active constraints.
48355 : *
48356 : * Tests for convergence are performed only at "steepest descent" stage
48357 : * of the BLEIC algorithm, and only when function is non-concave
48358 : * (D2 is positive or approximately zero) along direction D.
48359 : *
48360 : * NOTE: we do not test iteration count (MaxIts) here, because
48361 : * this stopping condition is tested by BLEIC itself.
48362 : */
48363 0 : if( sstate->solver.steepestdescentstep&&d2est>=0 )
48364 : {
48365 0 : if( d1est>=0 )
48366 : {
48367 :
48368 : /*
48369 : * "Emergency" stopping condition: D is non-descent direction.
48370 : * Sometimes it is possible because of numerical noise in the
48371 : * target function.
48372 : */
48373 0 : *terminationtype = 4;
48374 0 : for(i=0; i<=n-1; i++)
48375 : {
48376 0 : xs->ptr.p_double[i] = sstate->solver.x.ptr.p_double[i];
48377 : }
48378 0 : break;
48379 : }
48380 0 : if( d2est>0 )
48381 : {
48382 :
48383 : /*
48384 : * Stopping condition #4 - gradient norm is small:
48385 : *
48386 : * 1. rescale State.Solver.D and State.Solver.G according to
48387 : * current scaling, store results to Tmp0 and Tmp1.
48388 : * 2. Normalize Tmp0 (scaled direction vector).
48389 : * 3. compute directional derivative (in scaled variables),
48390 : * which is equal to DOTPRODUCT(Tmp0,Tmp1).
48391 : */
48392 0 : v = (double)(0);
48393 0 : for(i=0; i<=n-1; i++)
48394 : {
48395 0 : sstate->tmp0.ptr.p_double[i] = sstate->solver.d.ptr.p_double[i]/s->ptr.p_double[i];
48396 0 : sstate->tmp1.ptr.p_double[i] = sstate->solver.g.ptr.p_double[i]*s->ptr.p_double[i];
48397 0 : v = v+ae_sqr(sstate->tmp0.ptr.p_double[i], _state);
48398 : }
48399 0 : ae_assert(ae_fp_greater(v,(double)(0)), "QPBLEICOptimize: inernal errror (scaled direction is zero)", _state);
48400 0 : v = 1/ae_sqrt(v, _state);
48401 0 : ae_v_muld(&sstate->tmp0.ptr.p_double[0], 1, ae_v_len(0,n-1), v);
48402 0 : v = ae_v_dotproduct(&sstate->tmp0.ptr.p_double[0], 1, &sstate->tmp1.ptr.p_double[0], 1, ae_v_len(0,n-1));
48403 0 : if( ae_fp_less_eq(ae_fabs(v, _state),settings->epsg) )
48404 : {
48405 0 : *terminationtype = 4;
48406 0 : for(i=0; i<=n-1; i++)
48407 : {
48408 0 : xs->ptr.p_double[i] = sstate->solver.x.ptr.p_double[i];
48409 : }
48410 0 : break;
48411 : }
48412 :
48413 : /*
48414 : * Stopping condition #1 - relative function improvement is small:
48415 : *
48416 : * 1. calculate steepest descent step: V = -D1/(2*D2)
48417 : * 2. calculate function change: V1= D2*V^2 + D1*V
48418 : * 3. stop if function change is small enough
48419 : */
48420 0 : v = -d1/(2*d2);
48421 0 : v1 = d2*v*v+d1*v;
48422 0 : if( ae_fp_less_eq(ae_fabs(v1, _state),settings->epsf*ae_maxreal(d0, 1.0, _state)) )
48423 : {
48424 0 : *terminationtype = 1;
48425 0 : for(i=0; i<=n-1; i++)
48426 : {
48427 0 : xs->ptr.p_double[i] = sstate->solver.x.ptr.p_double[i];
48428 : }
48429 0 : break;
48430 : }
48431 :
48432 : /*
48433 : * Stopping condition #2 - scaled step is small:
48434 : *
48435 : * 1. calculate step multiplier V0 (step itself is D*V0)
48436 : * 2. calculate scaled step length V
48437 : * 3. stop if step is small enough
48438 : */
48439 0 : v0 = -d1/(2*d2);
48440 0 : v = (double)(0);
48441 0 : for(i=0; i<=n-1; i++)
48442 : {
48443 0 : v = v+ae_sqr(v0*sstate->solver.d.ptr.p_double[i]/s->ptr.p_double[i], _state);
48444 : }
48445 0 : if( ae_fp_less_eq(ae_sqrt(v, _state),settings->epsx) )
48446 : {
48447 0 : *terminationtype = 2;
48448 0 : for(i=0; i<=n-1; i++)
48449 : {
48450 0 : xs->ptr.p_double[i] = sstate->solver.x.ptr.p_double[i];
48451 : }
48452 0 : break;
48453 : }
48454 : }
48455 : }
48456 :
48457 : /*
48458 : * Test for unconstrained direction of negative curvature
48459 : */
48460 0 : if( (d2est<0||(d2est==0&&d1est<0))&&!sstate->solver.boundedstep )
48461 : {
48462 :
48463 : /*
48464 : * Function is unbounded from below:
48465 : * * function will decrease along D, i.e. either:
48466 : * * D2<0
48467 : * * D2=0 and D1<0
48468 : * * step is unconstrained
48469 : *
48470 : * If these conditions are true, we abnormally terminate QP
48471 : * algorithm with return code -4 (we can do so at any stage
48472 : * of BLEIC - whether it is L-BFGS or steepest descent one).
48473 : */
48474 0 : *terminationtype = -4;
48475 0 : for(i=0; i<=n-1; i++)
48476 : {
48477 0 : xs->ptr.p_double[i] = sstate->solver.x.ptr.p_double[i];
48478 : }
48479 0 : break;
48480 : }
48481 :
48482 : /*
48483 : * Suggest new step (only if D1 is negative far away from zero,
48484 : * D2 is positive far away from zero).
48485 : */
48486 0 : if( d1est<0&&d2est>0 )
48487 : {
48488 0 : sstate->solver.stp = safeminposrv(-d1, 2*d2, sstate->solver.curstpmax, _state);
48489 : }
48490 : }
48491 :
48492 : /*
48493 : * Gradient evaluation
48494 : */
48495 0 : if( sstate->solver.needfg )
48496 : {
48497 0 : for(i=0; i<=n-1; i++)
48498 : {
48499 0 : sstate->tmp0.ptr.p_double[i] = sstate->solver.x.ptr.p_double[i]-xorigin->ptr.p_double[i];
48500 : }
48501 0 : if( akind==0 )
48502 : {
48503 0 : cqmadx(a, &sstate->tmp0, &sstate->tmp1, _state);
48504 : }
48505 0 : if( akind==1 )
48506 : {
48507 0 : sparsesmv(sparsea, sparseaupper, &sstate->tmp0, &sstate->tmp1, _state);
48508 : }
48509 0 : v0 = ae_v_dotproduct(&sstate->tmp0.ptr.p_double[0], 1, &sstate->tmp1.ptr.p_double[0], 1, ae_v_len(0,n-1));
48510 0 : v1 = ae_v_dotproduct(&sstate->tmp0.ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,n-1));
48511 0 : sstate->solver.f = 0.5*v0+v1;
48512 0 : ae_v_move(&sstate->solver.g.ptr.p_double[0], 1, &sstate->tmp1.ptr.p_double[0], 1, ae_v_len(0,n-1));
48513 0 : ae_v_add(&sstate->solver.g.ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,n-1));
48514 : }
48515 : }
48516 0 : if( *terminationtype==0 )
48517 : {
48518 :
48519 : /*
48520 : * BLEIC optimizer was terminated by one of its inner stopping
48521 : * conditions. Usually it is iteration counter (if such
48522 : * stopping condition was specified by user).
48523 : */
48524 0 : minbleicresultsbuf(&sstate->solver, xs, &sstate->solverrep, _state);
48525 0 : *terminationtype = sstate->solverrep.terminationtype;
48526 : }
48527 : else
48528 : {
48529 :
48530 : /*
48531 : * BLEIC optimizer was terminated in "emergency" mode by QP
48532 : * solver.
48533 : *
48534 : * NOTE: such termination is "emergency" only when viewed from
48535 : * BLEIC's position. QP solver sees such termination as
48536 : * routine one, triggered by QP's stopping criteria.
48537 : */
48538 0 : minbleicemergencytermination(&sstate->solver, _state);
48539 : }
48540 0 : }
48541 :
48542 :
48543 0 : void _qpbleicsettings_init(void* _p, ae_state *_state, ae_bool make_automatic)
48544 : {
48545 0 : qpbleicsettings *p = (qpbleicsettings*)_p;
48546 0 : ae_touch_ptr((void*)p);
48547 0 : }
48548 :
48549 :
48550 0 : void _qpbleicsettings_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
48551 : {
48552 0 : qpbleicsettings *dst = (qpbleicsettings*)_dst;
48553 0 : qpbleicsettings *src = (qpbleicsettings*)_src;
48554 0 : dst->epsg = src->epsg;
48555 0 : dst->epsf = src->epsf;
48556 0 : dst->epsx = src->epsx;
48557 0 : dst->maxits = src->maxits;
48558 0 : }
48559 :
48560 :
48561 0 : void _qpbleicsettings_clear(void* _p)
48562 : {
48563 0 : qpbleicsettings *p = (qpbleicsettings*)_p;
48564 0 : ae_touch_ptr((void*)p);
48565 0 : }
48566 :
48567 :
48568 0 : void _qpbleicsettings_destroy(void* _p)
48569 : {
48570 0 : qpbleicsettings *p = (qpbleicsettings*)_p;
48571 0 : ae_touch_ptr((void*)p);
48572 0 : }
48573 :
48574 :
48575 0 : void _qpbleicbuffers_init(void* _p, ae_state *_state, ae_bool make_automatic)
48576 : {
48577 0 : qpbleicbuffers *p = (qpbleicbuffers*)_p;
48578 0 : ae_touch_ptr((void*)p);
48579 0 : _minbleicstate_init(&p->solver, _state, make_automatic);
48580 0 : _minbleicreport_init(&p->solverrep, _state, make_automatic);
48581 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
48582 0 : ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic);
48583 0 : ae_vector_init(&p->tmpi, 0, DT_INT, _state, make_automatic);
48584 0 : }
48585 :
48586 :
48587 0 : void _qpbleicbuffers_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
48588 : {
48589 0 : qpbleicbuffers *dst = (qpbleicbuffers*)_dst;
48590 0 : qpbleicbuffers *src = (qpbleicbuffers*)_src;
48591 0 : _minbleicstate_init_copy(&dst->solver, &src->solver, _state, make_automatic);
48592 0 : _minbleicreport_init_copy(&dst->solverrep, &src->solverrep, _state, make_automatic);
48593 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
48594 0 : ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic);
48595 0 : ae_vector_init_copy(&dst->tmpi, &src->tmpi, _state, make_automatic);
48596 0 : dst->repinneriterationscount = src->repinneriterationscount;
48597 0 : dst->repouteriterationscount = src->repouteriterationscount;
48598 0 : }
48599 :
48600 :
48601 0 : void _qpbleicbuffers_clear(void* _p)
48602 : {
48603 0 : qpbleicbuffers *p = (qpbleicbuffers*)_p;
48604 0 : ae_touch_ptr((void*)p);
48605 0 : _minbleicstate_clear(&p->solver);
48606 0 : _minbleicreport_clear(&p->solverrep);
48607 0 : ae_vector_clear(&p->tmp0);
48608 0 : ae_vector_clear(&p->tmp1);
48609 0 : ae_vector_clear(&p->tmpi);
48610 0 : }
48611 :
48612 :
48613 0 : void _qpbleicbuffers_destroy(void* _p)
48614 : {
48615 0 : qpbleicbuffers *p = (qpbleicbuffers*)_p;
48616 0 : ae_touch_ptr((void*)p);
48617 0 : _minbleicstate_destroy(&p->solver);
48618 0 : _minbleicreport_destroy(&p->solverrep);
48619 0 : ae_vector_destroy(&p->tmp0);
48620 0 : ae_vector_destroy(&p->tmp1);
48621 0 : ae_vector_destroy(&p->tmpi);
48622 0 : }
48623 :
48624 :
48625 : #endif
48626 : #if defined(AE_COMPILE_MINQP) || !defined(AE_PARTIAL_BUILD)
48627 :
48628 :
48629 : /*************************************************************************
48630 : CONSTRAINED QUADRATIC PROGRAMMING
48631 :
48632 : The subroutine creates QP optimizer. After initial creation, it contains
48633 : default optimization problem with zero quadratic and linear terms and no
48634 : constraints.
48635 :
48636 : In order to actually solve something you should:
48637 : * set cost vector with minqpsetlinearterm()
48638 : * set variable bounds with minqpsetbc() or minqpsetbcall()
48639 : * specify constraint matrix with one of the following functions:
48640 : * modern API:
48641 : * minqpsetlc2() for sparse two-sided constraints AL <= A*x <= AU
48642 : * minqpsetlc2dense() for dense two-sided constraints AL <= A*x <= AU
48643 : * minqpsetlc2mixed() for mixed two-sided constraints AL <= A*x <= AU
48644 : * minqpaddlc2dense() to add one dense row to dense constraint submatrix
48645 : * minqpaddlc2() to add one sparse row to sparse constraint submatrix
48646 : * legacy API:
48647 : * minqpsetlc() for dense one-sided equality/inequality constraints
48648 : * minqpsetlcsparse() for sparse one-sided equality/inequality constraints
48649 : * minqpsetlcmixed() for mixed dense/sparse one-sided equality/inequality constraints
48650 : * choose appropriate QP solver and set it and its stopping criteria by
48651 : means of minqpsetalgo??????() function
48652 : * call minqpoptimize() to run the solver and minqpresults() to get the
48653 : solution vector and additional information.
48654 :
48655 : Following solvers are recommended for convex and semidefinite problems:
48656 : * QuickQP for dense problems with box-only constraints (or no constraints
48657 : at all)
48658 : * DENSE-IPM-QP for convex or semidefinite problems with medium (up
48659 : to several thousands) variable count, dense/sparse quadratic term and
48660 : any number (up to many thousands) of dense/sparse general linear
48661 : constraints
48662 : * SPARSE-IPM-QP for convex or semidefinite problems with large (many
48663 : thousands) variable count, sparse quadratic term AND linear constraints.
48664 :
48665 : If your problem happens to be nonconvex, but either (a) is effectively
48666 : convexified under constraints, or (b) has unique solution even with
48667 : nonconvex target, then you can use:
48668 : * QuickQP for dense nonconvex problems with box-only constraints
48669 : * DENSE-AUL-QP for dense nonconvex problems which are effectively
48670 : convexified under constraints with up to several thousands of variables
48671 : and any (small or large) number of general linear constraints
48672 : * QP-BLEIC for dense/sparse problems with small (up to several hundreds)
48673 : number of general linear constraints and arbitrarily large variable
48674 : count.
48675 :
48676 : INPUT PARAMETERS:
48677 : N - problem size
48678 :
48679 : OUTPUT PARAMETERS:
48680 : State - optimizer with zero quadratic/linear terms
48681 : and no constraints
48682 :
48683 : -- ALGLIB --
48684 : Copyright 11.01.2011 by Bochkanov Sergey
48685 : *************************************************************************/
48686 0 : void minqpcreate(ae_int_t n, minqpstate* state, ae_state *_state)
48687 : {
48688 : ae_int_t i;
48689 :
48690 0 : _minqpstate_clear(state);
48691 :
48692 0 : ae_assert(n>=1, "MinQPCreate: N<1", _state);
48693 :
48694 : /*
48695 : * initialize QP solver
48696 : */
48697 0 : state->n = n;
48698 0 : state->mdense = 0;
48699 0 : state->msparse = 0;
48700 0 : state->repterminationtype = 0;
48701 0 : state->absamax = (double)(1);
48702 0 : state->absasum = (double)(1);
48703 0 : state->absasum2 = (double)(1);
48704 0 : state->akind = 0;
48705 0 : state->sparseaupper = ae_false;
48706 0 : cqminit(n, &state->a, _state);
48707 0 : ae_vector_set_length(&state->b, n, _state);
48708 0 : ae_vector_set_length(&state->bndl, n, _state);
48709 0 : ae_vector_set_length(&state->bndu, n, _state);
48710 0 : ae_vector_set_length(&state->havebndl, n, _state);
48711 0 : ae_vector_set_length(&state->havebndu, n, _state);
48712 0 : ae_vector_set_length(&state->s, n, _state);
48713 0 : ae_vector_set_length(&state->startx, n, _state);
48714 0 : ae_vector_set_length(&state->xorigin, n, _state);
48715 0 : ae_vector_set_length(&state->xs, n, _state);
48716 0 : rvectorsetlengthatleast(&state->replagbc, n, _state);
48717 0 : for(i=0; i<=n-1; i++)
48718 : {
48719 0 : state->bndl.ptr.p_double[i] = _state->v_neginf;
48720 0 : state->bndu.ptr.p_double[i] = _state->v_posinf;
48721 0 : state->havebndl.ptr.p_bool[i] = ae_false;
48722 0 : state->havebndu.ptr.p_bool[i] = ae_false;
48723 0 : state->b.ptr.p_double[i] = 0.0;
48724 0 : state->startx.ptr.p_double[i] = 0.0;
48725 0 : state->xorigin.ptr.p_double[i] = 0.0;
48726 0 : state->s.ptr.p_double[i] = 1.0;
48727 0 : state->replagbc.ptr.p_double[i] = 0.0;
48728 : }
48729 0 : state->stype = 0;
48730 0 : state->havex = ae_false;
48731 0 : minqpsetalgobleic(state, 0.0, 0.0, 0.0, 0, _state);
48732 0 : qqploaddefaults(n, &state->qqpsettingsuser, _state);
48733 0 : qpbleicloaddefaults(n, &state->qpbleicsettingsuser, _state);
48734 0 : qpdenseaulloaddefaults(n, &state->qpdenseaulsettingsuser, _state);
48735 0 : state->qpbleicfirstcall = ae_true;
48736 0 : state->dbgskipconstraintnormalization = ae_false;
48737 0 : state->veps = 0.0;
48738 0 : }
48739 :
48740 :
48741 : /*************************************************************************
48742 : This function sets linear term for QP solver.
48743 :
48744 : By default, linear term is zero.
48745 :
48746 : INPUT PARAMETERS:
48747 : State - structure which stores algorithm state
48748 : B - linear term, array[N].
48749 :
48750 : -- ALGLIB --
48751 : Copyright 11.01.2011 by Bochkanov Sergey
48752 : *************************************************************************/
48753 0 : void minqpsetlinearterm(minqpstate* state,
48754 : /* Real */ ae_vector* b,
48755 : ae_state *_state)
48756 : {
48757 : ae_int_t n;
48758 :
48759 :
48760 0 : n = state->n;
48761 0 : ae_assert(b->cnt>=n, "MinQPSetLinearTerm: Length(B)<N", _state);
48762 0 : ae_assert(isfinitevector(b, n, _state), "MinQPSetLinearTerm: B contains infinite or NaN elements", _state);
48763 0 : minqpsetlineartermfast(state, b, _state);
48764 0 : }
48765 :
48766 :
48767 : /*************************************************************************
48768 : This function sets dense quadratic term for QP solver. By default,
48769 : quadratic term is zero.
48770 :
48771 : IMPORTANT:
48772 :
48773 : This solver minimizes following function:
48774 : f(x) = 0.5*x'*A*x + b'*x.
48775 : Note that quadratic term has 0.5 before it. So if you want to minimize
48776 : f(x) = x^2 + x
48777 : you should rewrite your problem as follows:
48778 : f(x) = 0.5*(2*x^2) + x
48779 : and your matrix A will be equal to [[2.0]], not to [[1.0]]
48780 :
48781 : INPUT PARAMETERS:
48782 : State - structure which stores algorithm state
48783 : A - matrix, array[N,N]
48784 : IsUpper - (optional) storage type:
48785 : * if True, symmetric matrix A is given by its upper
48786 : triangle, and the lower triangle isn't used
48787 : * if False, symmetric matrix A is given by its lower
48788 : triangle, and the upper triangle isn't used
48789 : * if not given, both lower and upper triangles must be
48790 : filled.
48791 :
48792 : -- ALGLIB --
48793 : Copyright 11.01.2011 by Bochkanov Sergey
48794 : *************************************************************************/
48795 0 : void minqpsetquadraticterm(minqpstate* state,
48796 : /* Real */ ae_matrix* a,
48797 : ae_bool isupper,
48798 : ae_state *_state)
48799 : {
48800 : ae_int_t n;
48801 :
48802 :
48803 0 : n = state->n;
48804 0 : ae_assert(a->rows>=n, "MinQPSetQuadraticTerm: Rows(A)<N", _state);
48805 0 : ae_assert(a->cols>=n, "MinQPSetQuadraticTerm: Cols(A)<N", _state);
48806 0 : ae_assert(isfinitertrmatrix(a, n, isupper, _state), "MinQPSetQuadraticTerm: A contains infinite or NaN elements", _state);
48807 0 : minqpsetquadratictermfast(state, a, isupper, 0.0, _state);
48808 0 : }
48809 :
48810 :
48811 : /*************************************************************************
48812 : This function sets sparse quadratic term for QP solver. By default,
48813 : quadratic term is zero. This function overrides previous calls to
48814 : minqpsetquadraticterm() or minqpsetquadratictermsparse().
48815 :
48816 : NOTE: dense solvers like DENSE-AUL-QP or DENSE-IPM-QP will convert this
48817 : matrix to dense storage anyway.
48818 :
48819 : IMPORTANT:
48820 :
48821 : This solver minimizes following function:
48822 : f(x) = 0.5*x'*A*x + b'*x.
48823 : Note that quadratic term has 0.5 before it. So if you want to minimize
48824 : f(x) = x^2 + x
48825 : you should rewrite your problem as follows:
48826 : f(x) = 0.5*(2*x^2) + x
48827 : and your matrix A will be equal to [[2.0]], not to [[1.0]]
48828 :
48829 : INPUT PARAMETERS:
48830 : State - structure which stores algorithm state
48831 : A - matrix, array[N,N]
48832 : IsUpper - (optional) storage type:
48833 : * if True, symmetric matrix A is given by its upper
48834 : triangle, and the lower triangle isn't used
48835 : * if False, symmetric matrix A is given by its lower
48836 : triangle, and the upper triangle isn't used
48837 : * if not given, both lower and upper triangles must be
48838 : filled.
48839 :
48840 : -- ALGLIB --
48841 : Copyright 11.01.2011 by Bochkanov Sergey
48842 : *************************************************************************/
48843 0 : void minqpsetquadratictermsparse(minqpstate* state,
48844 : sparsematrix* a,
48845 : ae_bool isupper,
48846 : ae_state *_state)
48847 : {
48848 : ae_int_t n;
48849 : ae_int_t t0;
48850 : ae_int_t t1;
48851 : ae_int_t i;
48852 : ae_int_t j;
48853 : double v;
48854 :
48855 :
48856 0 : n = state->n;
48857 0 : ae_assert(sparsegetnrows(a, _state)==n, "MinQPSetQuadraticTermSparse: Rows(A)<>N", _state);
48858 0 : ae_assert(sparsegetncols(a, _state)==n, "MinQPSetQuadraticTermSparse: Cols(A)<>N", _state);
48859 0 : sparsecopytocrsbuf(a, &state->sparsea, _state);
48860 0 : state->sparseaupper = isupper;
48861 0 : state->akind = 1;
48862 :
48863 : /*
48864 : * Estimate norm of A
48865 : * (it will be used later in the quadratic penalty function)
48866 : */
48867 0 : state->absamax = (double)(0);
48868 0 : state->absasum = (double)(0);
48869 0 : state->absasum2 = (double)(0);
48870 0 : t0 = 0;
48871 0 : t1 = 0;
48872 0 : while(sparseenumerate(a, &t0, &t1, &i, &j, &v, _state))
48873 : {
48874 0 : if( i==j )
48875 : {
48876 :
48877 : /*
48878 : * Diagonal terms are counted only once
48879 : */
48880 0 : state->absamax = ae_maxreal(state->absamax, v, _state);
48881 0 : state->absasum = state->absasum+v;
48882 0 : state->absasum2 = state->absasum2+v*v;
48883 : }
48884 0 : if( (j>i&&isupper)||(j<i&&!isupper) )
48885 : {
48886 :
48887 : /*
48888 : * Offdiagonal terms are counted twice
48889 : */
48890 0 : state->absamax = ae_maxreal(state->absamax, v, _state);
48891 0 : state->absasum = state->absasum+2*v;
48892 0 : state->absasum2 = state->absasum2+2*v*v;
48893 : }
48894 : }
48895 0 : }
48896 :
48897 :
48898 : /*************************************************************************
48899 : This function sets starting point for QP solver. It is useful to have good
48900 : initial approximation to the solution, because it will increase speed of
48901 : convergence and identification of active constraints.
48902 :
48903 : NOTE: interior point solvers ignore initial point provided by user.
48904 :
48905 : INPUT PARAMETERS:
48906 : State - structure which stores algorithm state
48907 : X - starting point, array[N].
48908 :
48909 : -- ALGLIB --
48910 : Copyright 11.01.2011 by Bochkanov Sergey
48911 : *************************************************************************/
48912 0 : void minqpsetstartingpoint(minqpstate* state,
48913 : /* Real */ ae_vector* x,
48914 : ae_state *_state)
48915 : {
48916 : ae_int_t n;
48917 :
48918 :
48919 0 : n = state->n;
48920 0 : ae_assert(x->cnt>=n, "MinQPSetStartingPoint: Length(B)<N", _state);
48921 0 : ae_assert(isfinitevector(x, n, _state), "MinQPSetStartingPoint: X contains infinite or NaN elements", _state);
48922 0 : minqpsetstartingpointfast(state, x, _state);
48923 0 : }
48924 :
48925 :
48926 : /*************************************************************************
48927 : This function sets origin for QP solver. By default, following QP program
48928 : is solved:
48929 :
48930 : min(0.5*x'*A*x+b'*x)
48931 :
48932 : This function allows to solve different problem:
48933 :
48934 : min(0.5*(x-x_origin)'*A*(x-x_origin)+b'*(x-x_origin))
48935 :
48936 : Specification of non-zero origin affects function being minimized, but not
48937 : constraints. Box and linear constraints are still calculated without
48938 : origin.
48939 :
48940 : INPUT PARAMETERS:
48941 : State - structure which stores algorithm state
48942 : XOrigin - origin, array[N].
48943 :
48944 : -- ALGLIB --
48945 : Copyright 11.01.2011 by Bochkanov Sergey
48946 : *************************************************************************/
48947 0 : void minqpsetorigin(minqpstate* state,
48948 : /* Real */ ae_vector* xorigin,
48949 : ae_state *_state)
48950 : {
48951 : ae_int_t n;
48952 :
48953 :
48954 0 : n = state->n;
48955 0 : ae_assert(xorigin->cnt>=n, "MinQPSetOrigin: Length(B)<N", _state);
48956 0 : ae_assert(isfinitevector(xorigin, n, _state), "MinQPSetOrigin: B contains infinite or NaN elements", _state);
48957 0 : minqpsetoriginfast(state, xorigin, _state);
48958 0 : }
48959 :
48960 :
48961 : /*************************************************************************
48962 : This function sets scaling coefficients.
48963 :
48964 : ALGLIB optimizers use scaling matrices to test stopping conditions (step
48965 : size and gradient are scaled before comparison with tolerances) and as
48966 : preconditioner.
48967 :
48968 : Scale of the I-th variable is a translation invariant measure of:
48969 : a) "how large" the variable is
48970 : b) how large the step should be to make significant changes in the
48971 : function
48972 :
48973 : If you do not know how to choose scales of your variables, you can:
48974 : * read www.alglib.net/optimization/scaling.php article
48975 : * use minqpsetscaleautodiag(), which calculates scale using diagonal of
48976 : the quadratic term: S is set to 1/sqrt(diag(A)), which works well
48977 : sometimes.
48978 :
48979 : INPUT PARAMETERS:
48980 : State - structure stores algorithm state
48981 : S - array[N], non-zero scaling coefficients
48982 : S[i] may be negative, sign doesn't matter.
48983 :
48984 : -- ALGLIB --
48985 : Copyright 14.01.2011 by Bochkanov Sergey
48986 : *************************************************************************/
48987 0 : void minqpsetscale(minqpstate* state,
48988 : /* Real */ ae_vector* s,
48989 : ae_state *_state)
48990 : {
48991 : ae_int_t i;
48992 :
48993 :
48994 0 : ae_assert(s->cnt>=state->n, "MinQPSetScale: Length(S)<N", _state);
48995 0 : for(i=0; i<=state->n-1; i++)
48996 : {
48997 0 : ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "MinQPSetScale: S contains infinite or NAN elements", _state);
48998 0 : ae_assert(ae_fp_neq(s->ptr.p_double[i],(double)(0)), "MinQPSetScale: S contains zero elements", _state);
48999 : }
49000 0 : for(i=0; i<=state->n-1; i++)
49001 : {
49002 0 : state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state);
49003 : }
49004 0 : state->stype = 0;
49005 0 : }
49006 :
49007 :
49008 : /*************************************************************************
49009 : This function sets automatic evaluation of variable scaling.
49010 :
49011 : IMPORTANT: this function works only for matrices with positive diagonal
49012 : elements! Zero or negative elements will result in -9 error
49013 : code being returned. Specify scale vector manually with
49014 : minqpsetscale() in such cases.
49015 :
49016 : ALGLIB optimizers use scaling matrices to test stopping conditions (step
49017 : size and gradient are scaled before comparison with tolerances) and as
49018 : preconditioner.
49019 :
49020 : The best way to set scaling is to manually specify variable scales.
49021 : However, sometimes you just need quick-and-dirty solution - either when
49022 : you perform fast prototyping, or when you know your problem well and you
49023 : are 100% sure that this quick solution is robust enough in your case.
49024 :
49025 : One such solution is to evaluate scale of I-th variable as 1/Sqrt(A[i,i]),
49026 : where A[i,i] is an I-th diagonal element of the quadratic term.
49027 :
49028 : Such approach works well sometimes, but you have to be careful here.
49029 :
49030 : INPUT PARAMETERS:
49031 : State - structure stores algorithm state
49032 :
49033 : -- ALGLIB --
49034 : Copyright 26.12.2017 by Bochkanov Sergey
49035 : *************************************************************************/
49036 0 : void minqpsetscaleautodiag(minqpstate* state, ae_state *_state)
49037 : {
49038 :
49039 :
49040 0 : state->stype = 1;
49041 0 : }
49042 :
49043 :
49044 : /*************************************************************************
49045 : This function tells solver to use BLEIC-based algorithm and sets stopping
49046 : criteria for the algorithm.
49047 :
49048 : This algorithm is intended for large-scale problems, possibly nonconvex,
49049 : with small number of general linear constraints. Feasible initial point is
49050 : essential for good performance.
49051 :
49052 : IMPORTANT: when DENSE-IPM (or DENSE-AUL for nonconvex problems) solvers
49053 : are applicable, their performance is much better than that of
49054 : BLEIC-QP.
49055 : We recommend you to use BLEIC only when other solvers can not
49056 : be used.
49057 :
49058 : ALGORITHM FEATURES:
49059 :
49060 : * supports dense and sparse QP problems
49061 : * supports box and general linear equality/inequality constraints
49062 : * can solve all types of problems (convex, semidefinite, nonconvex) as
49063 : long as they are bounded from below under constraints.
49064 : Say, it is possible to solve "min{-x^2} subject to -1<=x<=+1".
49065 : Of course, global minimum is found only for positive definite and
49066 : semidefinite problems. As for indefinite ones - only local minimum is
49067 : found.
49068 :
49069 : ALGORITHM OUTLINE:
49070 :
49071 : * BLEIC-QP solver is just a driver function for MinBLEIC solver; it solves
49072 : quadratic programming problem as general linearly constrained
49073 : optimization problem, which is solved by means of BLEIC solver (part of
49074 : ALGLIB, active set method).
49075 :
49076 : ALGORITHM LIMITATIONS:
49077 : * This algorithm is inefficient on problems with hundreds and thousands
49078 : of general inequality constraints and infeasible initial point. Initial
49079 : feasibility detection stage may take too long on such constraint sets.
49080 : Consider using DENSE-IPM or DENSE-AUL instead.
49081 : * unlike QuickQP solver, this algorithm does not perform Newton steps and
49082 : does not use Level 3 BLAS. Being general-purpose active set method, it
49083 : can activate constraints only one-by-one. Thus, its performance is lower
49084 : than that of QuickQP.
49085 : * its precision is also a bit inferior to that of QuickQP. BLEIC-QP
49086 : performs only LBFGS steps (no Newton steps), which are good at detecting
49087 : neighborhood of the solution, buy needs many iterations to find solution
49088 : with more than 6 digits of precision.
49089 :
49090 : INPUT PARAMETERS:
49091 : State - structure which stores algorithm state
49092 : EpsG - >=0
49093 : The subroutine finishes its work if the condition
49094 : |v|<EpsG is satisfied, where:
49095 : * |.| means Euclidian norm
49096 : * v - scaled constrained gradient vector, v[i]=g[i]*s[i]
49097 : * g - gradient
49098 : * s - scaling coefficients set by MinQPSetScale()
49099 : EpsF - >=0
49100 : The subroutine finishes its work if exploratory steepest
49101 : descent step on k+1-th iteration satisfies following
49102 : condition: |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
49103 : EpsX - >=0
49104 : The subroutine finishes its work if exploratory steepest
49105 : descent step on k+1-th iteration satisfies following
49106 : condition:
49107 : * |.| means Euclidian norm
49108 : * v - scaled step vector, v[i]=dx[i]/s[i]
49109 : * dx - step vector, dx=X(k+1)-X(k)
49110 : * s - scaling coefficients set by MinQPSetScale()
49111 : MaxIts - maximum number of iterations. If MaxIts=0, the number of
49112 : iterations is unlimited. NOTE: this algorithm uses LBFGS
49113 : iterations, which are relatively cheap, but improve
49114 : function value only a bit. So you will need many iterations
49115 : to converge - from 0.1*N to 10*N, depending on problem's
49116 : condition number.
49117 :
49118 : IT IS VERY IMPORTANT TO CALL MinQPSetScale() WHEN YOU USE THIS ALGORITHM
49119 : BECAUSE ITS STOPPING CRITERIA ARE SCALE-DEPENDENT!
49120 :
49121 : Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead
49122 : to automatic stopping criterion selection (presently it is small step
49123 : length, but it may change in the future versions of ALGLIB).
49124 :
49125 : -- ALGLIB --
49126 : Copyright 11.01.2011 by Bochkanov Sergey
49127 : *************************************************************************/
49128 0 : void minqpsetalgobleic(minqpstate* state,
49129 : double epsg,
49130 : double epsf,
49131 : double epsx,
49132 : ae_int_t maxits,
49133 : ae_state *_state)
49134 : {
49135 :
49136 :
49137 0 : ae_assert(ae_isfinite(epsg, _state), "MinQPSetAlgoBLEIC: EpsG is not finite number", _state);
49138 0 : ae_assert(ae_fp_greater_eq(epsg,(double)(0)), "MinQPSetAlgoBLEIC: negative EpsG", _state);
49139 0 : ae_assert(ae_isfinite(epsf, _state), "MinQPSetAlgoBLEIC: EpsF is not finite number", _state);
49140 0 : ae_assert(ae_fp_greater_eq(epsf,(double)(0)), "MinQPSetAlgoBLEIC: negative EpsF", _state);
49141 0 : ae_assert(ae_isfinite(epsx, _state), "MinQPSetAlgoBLEIC: EpsX is not finite number", _state);
49142 0 : ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "MinQPSetAlgoBLEIC: negative EpsX", _state);
49143 0 : ae_assert(maxits>=0, "MinQPSetAlgoBLEIC: negative MaxIts!", _state);
49144 0 : state->algokind = 2;
49145 0 : if( ((ae_fp_eq(epsg,(double)(0))&&ae_fp_eq(epsf,(double)(0)))&&ae_fp_eq(epsx,(double)(0)))&&maxits==0 )
49146 : {
49147 0 : epsx = 1.0E-6;
49148 : }
49149 0 : state->qpbleicsettingsuser.epsg = epsg;
49150 0 : state->qpbleicsettingsuser.epsf = epsf;
49151 0 : state->qpbleicsettingsuser.epsx = epsx;
49152 0 : state->qpbleicsettingsuser.maxits = maxits;
49153 0 : }
49154 :
49155 :
49156 : /*************************************************************************
49157 : This function tells QP solver to use DENSE-AUL algorithm and sets stopping
49158 : criteria for the algorithm.
49159 :
49160 : This algorithm is intended for non-convex problems with moderate (up
49161 : to several thousands) variable count and arbitrary number of constraints
49162 : which are either (a) effectively convexified under constraints or (b) have
49163 : unique solution even with nonconvex target.
49164 :
49165 : IMPORTANT: when DENSE-IPM solver is applicable, its performance is usually
49166 : much better than that of DENSE-AUL.
49167 : We recommend you to use DENSE-AUL only when other solvers can
49168 : not be used.
49169 :
49170 : ALGORITHM FEATURES:
49171 :
49172 : * supports box and dense/sparse general linear equality/inequality
49173 : constraints
49174 : * convergence is theoretically proved for positive-definite (convex) QP
49175 : problems. Semidefinite and non-convex problems can be solved as long as
49176 : they are bounded from below under constraints, although without
49177 : theoretical guarantees.
49178 :
49179 : ALGORITHM OUTLINE:
49180 :
49181 : * this algorithm is an augmented Lagrangian method with dense
49182 : preconditioner (hence its name).
49183 : * it performs several outer iterations in order to refine values of the
49184 : Lagrange multipliers. Single outer iteration is a solution of some
49185 : unconstrained optimization problem: first it performs dense Cholesky
49186 : factorization of the Hessian in order to build preconditioner (adaptive
49187 : regularization is applied to enforce positive definiteness), and then
49188 : it uses L-BFGS optimizer to solve optimization problem.
49189 : * typically you need about 5-10 outer iterations to converge to solution
49190 :
49191 : ALGORITHM LIMITATIONS:
49192 :
49193 : * because dense Cholesky driver is used, this algorithm has O(N^2) memory
49194 : requirements and O(OuterIterations*N^3) minimum running time. From the
49195 : practical point of view, it limits its applicability by several
49196 : thousands of variables.
49197 : From the other side, variables count is the most limiting factor,
49198 : and dependence on constraint count is much more lower. Assuming that
49199 : constraint matrix is sparse, it may handle tens of thousands of general
49200 : linear constraints.
49201 :
49202 : INPUT PARAMETERS:
49203 : State - structure which stores algorithm state
49204 : EpsX - >=0, stopping criteria for inner optimizer.
49205 : Inner iterations are stopped when step length (with
49206 : variable scaling being applied) is less than EpsX.
49207 : See minqpsetscale() for more information on variable
49208 : scaling.
49209 : Rho - penalty coefficient, Rho>0:
49210 : * large enough that algorithm converges with desired
49211 : precision.
49212 : * not TOO large to prevent ill-conditioning
49213 : * recommended values are 100, 1000 or 10000
49214 : ItsCnt - number of outer iterations:
49215 : * recommended values: 10-15 (although in most cases it
49216 : converges within 5 iterations, you may need a few more
49217 : to be sure).
49218 : * ItsCnt=0 means that small number of outer iterations is
49219 : automatically chosen (10 iterations in current version).
49220 : * ItsCnt=1 means that AUL algorithm performs just as usual
49221 : penalty method.
49222 : * ItsCnt>1 means that AUL algorithm performs specified
49223 : number of outer iterations
49224 :
49225 : IT IS VERY IMPORTANT TO CALL minqpsetscale() WHEN YOU USE THIS ALGORITHM
49226 : BECAUSE ITS CONVERGENCE PROPERTIES AND STOPPING CRITERIA ARE SCALE-DEPENDENT!
49227 :
49228 : NOTE: Passing EpsX=0 will lead to automatic step length selection
49229 : (specific step length chosen may change in the future versions of
49230 : ALGLIB, so it is better to specify step length explicitly).
49231 :
49232 : -- ALGLIB --
49233 : Copyright 20.08.2016 by Bochkanov Sergey
49234 : *************************************************************************/
49235 0 : void minqpsetalgodenseaul(minqpstate* state,
49236 : double epsx,
49237 : double rho,
49238 : ae_int_t itscnt,
49239 : ae_state *_state)
49240 : {
49241 :
49242 :
49243 0 : ae_assert(ae_isfinite(epsx, _state), "MinQPSetAlgoDenseAUL: EpsX is not finite number", _state);
49244 0 : ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "MinQPSetAlgoDenseAUL: negative EpsX", _state);
49245 0 : ae_assert(ae_isfinite(rho, _state), "MinQPSetAlgoDenseAUL: Rho is not finite number", _state);
49246 0 : ae_assert(ae_fp_greater(rho,(double)(0)), "MinQPSetAlgoDenseAUL: non-positive Rho", _state);
49247 0 : ae_assert(itscnt>=0, "MinQPSetAlgoDenseAUL: negative ItsCnt!", _state);
49248 0 : state->algokind = 4;
49249 0 : if( ae_fp_eq(epsx,(double)(0)) )
49250 : {
49251 0 : epsx = 1.0E-8;
49252 : }
49253 0 : if( itscnt==0 )
49254 : {
49255 0 : itscnt = 10;
49256 : }
49257 0 : state->qpdenseaulsettingsuser.epsx = epsx;
49258 0 : state->qpdenseaulsettingsuser.outerits = itscnt;
49259 0 : state->qpdenseaulsettingsuser.rho = rho;
49260 0 : }
49261 :
49262 :
49263 : /*************************************************************************
49264 : This function tells QP solver to use DENSE-IPM QP algorithm and sets
49265 : stopping criteria for the algorithm.
49266 :
49267 : This algorithm is intended for convex and semidefinite problems with
49268 : moderate (up to several thousands) variable count and arbitrary number of
49269 : constraints.
49270 :
49271 : IMPORTANT: this algorithm won't work for nonconvex problems, use DENSE-AUL
49272 : or BLEIC-QP instead. If you try to run DENSE-IPM on problem
49273 : with indefinite matrix (matrix having at least one negative
49274 : eigenvalue) then depending on circumstances it may either (a)
49275 : stall at some arbitrary point, or (b) throw exception on
49276 : failure of Cholesky decomposition.
49277 :
49278 : ALGORITHM FEATURES:
49279 :
49280 : * supports box and dense/sparse general linear equality/inequality
49281 : constraints
49282 :
49283 : ALGORITHM OUTLINE:
49284 :
49285 : * this algorithm is our implementation of interior point method as
49286 : formulated by R.J.Vanderbei, with minor modifications to the algorithm
49287 : (damped Newton directions are extensively used)
49288 : * like all interior point methods, this algorithm tends to converge in
49289 : roughly same number of iterations (between 15 and 50) independently from
49290 : the problem dimensionality
49291 :
49292 : ALGORITHM LIMITATIONS:
49293 :
49294 : * because dense Cholesky driver is used, for N-dimensional problem with
49295 : M dense constaints this algorithm has O(N^2+N*M) memory requirements and
49296 : O(N^3+N*M^2) running time.
49297 : Having sparse constraints with Z nonzeros per row relaxes storage and
49298 : running time down to O(N^2+M*Z) and O(N^3+N*Z^2)
49299 : From the practical point of view, it limits its applicability by
49300 : several thousands of variables.
49301 : From the other side, variables count is the most limiting factor,
49302 : and dependence on constraint count is much more lower. Assuming that
49303 : constraint matrix is sparse, it may handle tens of thousands of general
49304 : linear constraints.
49305 :
49306 : INPUT PARAMETERS:
49307 : State - structure which stores algorithm state
49308 : Eps - >=0, stopping criteria. The algorithm stops when primal
49309 : and dual infeasiblities as well as complementarity gap are
49310 : less than Eps.
49311 :
49312 : IT IS VERY IMPORTANT TO CALL minqpsetscale() WHEN YOU USE THIS ALGORITHM
49313 : BECAUSE ITS CONVERGENCE PROPERTIES AND STOPPING CRITERIA ARE SCALE-DEPENDENT!
49314 :
49315 : NOTE: Passing EpsX=0 will lead to automatic selection of small epsilon.
49316 :
49317 : ===== TRACING IPM SOLVER =================================================
49318 :
49319 : IPM solver supports advanced tracing capabilities. You can trace algorithm
49320 : output by specifying following trace symbols (case-insensitive) by means
49321 : of trace_file() call:
49322 : * 'IPM' - for basic trace of algorithm steps and decisions. Only
49323 : short scalars (function values and deltas) are printed.
49324 : N-dimensional quantities like search directions are NOT
49325 : printed.
49326 : * 'IPM.DETAILED'- for output of points being visited and search directions
49327 : This symbol also implicitly defines 'IPM'. You can
49328 : control output format by additionally specifying:
49329 : * nothing to output in 6-digit exponential format
49330 : * 'PREC.E15' to output in 15-digit exponential format
49331 : * 'PREC.F6' to output in 6-digit fixed-point format
49332 :
49333 : By default trace is disabled and adds no overhead to the optimization
49334 : process. However, specifying any of the symbols adds some formatting and
49335 : output-related overhead.
49336 :
49337 : You may specify multiple symbols by separating them with commas:
49338 : >
49339 : > alglib::trace_file("IPM,PREC.F6", "path/to/trace.log")
49340 : >
49341 :
49342 : -- ALGLIB --
49343 : Copyright 01.11.2019 by Bochkanov Sergey
49344 : *************************************************************************/
49345 0 : void minqpsetalgodenseipm(minqpstate* state, double eps, ae_state *_state)
49346 : {
49347 :
49348 :
49349 0 : ae_assert(ae_isfinite(eps, _state), "MinQPSetAlgoDenseIPM: Eps is not finite number", _state);
49350 0 : ae_assert(ae_fp_greater_eq(eps,(double)(0)), "MinQPSetAlgoDenseIPM: negative Eps", _state);
49351 0 : state->algokind = 5;
49352 0 : state->veps = eps;
49353 0 : }
49354 :
49355 :
49356 : /*************************************************************************
49357 : This function tells QP solver to use SPARSE-IPM QP algorithm and sets
49358 : stopping criteria for the algorithm.
49359 :
49360 : This algorithm is intended for convex and semidefinite problems with
49361 : large variable and constraint count and sparse quadratic term and
49362 : constraints. It is possible to have some limited set of dense linear
49363 : constraints - they will be handled separately by dense BLAS - but the more
49364 : dense constraints you have, the more time solver needs.
49365 :
49366 : IMPORTANT: internally this solver performs large and sparse (N+M)x(N+M)
49367 : triangular factorization. So it expects both quadratic term and
49368 : constraints to be highly sparse. However, its running time is
49369 : influenced by BOTH fill factor and sparsity pattern.
49370 :
49371 : Generally we expect that no more than few nonzero elements per
49372 : row are present. However different sparsity patterns may result
49373 : in completely different running times even given same fill
49374 : factor.
49375 :
49376 : In many cases this algorithm outperforms DENSE-IPM by order of
49377 : magnitude. However, in some cases you may get better results
49378 : with DENSE-IPM even when solving sparse task.
49379 :
49380 : IMPORTANT: this algorithm won't work for nonconvex problems, use DENSE-AUL
49381 : or BLEIC-QP instead. If you try to run DENSE-IPM on problem
49382 : with indefinite matrix (matrix having at least one negative
49383 : eigenvalue) then depending on circumstances it may either (a)
49384 : stall at some arbitrary point, or (b) throw exception on
49385 : failure of Cholesky decomposition.
49386 :
49387 : ALGORITHM FEATURES:
49388 :
49389 : * supports box and dense/sparse general linear equality/inequality
49390 : constraints
49391 : * specializes on large-scale sparse problems
49392 :
49393 : ALGORITHM OUTLINE:
49394 :
49395 : * this algorithm is our implementation of interior point method as
49396 : formulated by R.J.Vanderbei, with minor modifications to the algorithm
49397 : (damped Newton directions are extensively used)
49398 : * like all interior point methods, this algorithm tends to converge in
49399 : roughly same number of iterations (between 15 and 50) independently from
49400 : the problem dimensionality
49401 :
49402 : ALGORITHM LIMITATIONS:
49403 :
49404 : * this algorithm may handle moderate number of dense constraints, usually
49405 : no more than a thousand of dense ones without losing its efficiency.
49406 :
49407 : INPUT PARAMETERS:
49408 : State - structure which stores algorithm state
49409 : Eps - >=0, stopping criteria. The algorithm stops when primal
49410 : and dual infeasiblities as well as complementarity gap are
49411 : less than Eps.
49412 :
49413 : IT IS VERY IMPORTANT TO CALL minqpsetscale() WHEN YOU USE THIS ALGORITHM
49414 : BECAUSE ITS CONVERGENCE PROPERTIES AND STOPPING CRITERIA ARE SCALE-DEPENDENT!
49415 :
49416 : NOTE: Passing EpsX=0 will lead to automatic selection of small epsilon.
49417 :
49418 : ===== TRACING IPM SOLVER =================================================
49419 :
49420 : IPM solver supports advanced tracing capabilities. You can trace algorithm
49421 : output by specifying following trace symbols (case-insensitive) by means
49422 : of trace_file() call:
49423 : * 'IPM' - for basic trace of algorithm steps and decisions. Only
49424 : short scalars (function values and deltas) are printed.
49425 : N-dimensional quantities like search directions are NOT
49426 : printed.
49427 : * 'IPM.DETAILED'- for output of points being visited and search directions
49428 : This symbol also implicitly defines 'IPM'. You can
49429 : control output format by additionally specifying:
49430 : * nothing to output in 6-digit exponential format
49431 : * 'PREC.E15' to output in 15-digit exponential format
49432 : * 'PREC.F6' to output in 6-digit fixed-point format
49433 :
49434 : By default trace is disabled and adds no overhead to the optimization
49435 : process. However, specifying any of the symbols adds some formatting and
49436 : output-related overhead.
49437 :
49438 : You may specify multiple symbols by separating them with commas:
49439 : >
49440 : > alglib::trace_file("IPM,PREC.F6", "path/to/trace.log")
49441 : >
49442 :
49443 : -- ALGLIB --
49444 : Copyright 01.11.2019 by Bochkanov Sergey
49445 : *************************************************************************/
49446 0 : void minqpsetalgosparseipm(minqpstate* state,
49447 : double eps,
49448 : ae_state *_state)
49449 : {
49450 :
49451 :
49452 0 : ae_assert(ae_isfinite(eps, _state), "MinQPSetAlgoSparseIPM: Eps is not finite number", _state);
49453 0 : ae_assert(ae_fp_greater_eq(eps,(double)(0)), "MinQPSetAlgoSparseIPM: negative Eps", _state);
49454 0 : state->algokind = 6;
49455 0 : state->veps = eps;
49456 0 : }
49457 :
49458 :
49459 : /*************************************************************************
49460 : This function tells solver to use QuickQP algorithm: special extra-fast
49461 : algorithm for problems with box-only constrants. It may solve non-convex
49462 : problems as long as they are bounded from below under constraints.
49463 :
49464 : ALGORITHM FEATURES:
49465 : * several times faster than DENSE-IPM when running on box-only problem
49466 : * utilizes accelerated methods for activation of constraints.
49467 : * supports dense and sparse QP problems
49468 : * supports ONLY box constraints; general linear constraints are NOT
49469 : supported by this solver
49470 : * can solve all types of problems (convex, semidefinite, nonconvex) as
49471 : long as they are bounded from below under constraints.
49472 : Say, it is possible to solve "min{-x^2} subject to -1<=x<=+1".
49473 : In convex/semidefinite case global minimum is returned, in nonconvex
49474 : case - algorithm returns one of the local minimums.
49475 :
49476 : ALGORITHM OUTLINE:
49477 :
49478 : * algorithm performs two kinds of iterations: constrained CG iterations
49479 : and constrained Newton iterations
49480 : * initially it performs small number of constrained CG iterations, which
49481 : can efficiently activate/deactivate multiple constraints
49482 : * after CG phase algorithm tries to calculate Cholesky decomposition and
49483 : to perform several constrained Newton steps. If Cholesky decomposition
49484 : failed (matrix is indefinite even under constraints), we perform more
49485 : CG iterations until we converge to such set of constraints that system
49486 : matrix becomes positive definite. Constrained Newton steps greatly
49487 : increase convergence speed and precision.
49488 : * algorithm interleaves CG and Newton iterations which allows to handle
49489 : indefinite matrices (CG phase) and quickly converge after final set of
49490 : constraints is found (Newton phase). Combination of CG and Newton phases
49491 : is called "outer iteration".
49492 : * it is possible to turn off Newton phase (beneficial for semidefinite
49493 : problems - Cholesky decomposition will fail too often)
49494 :
49495 : ALGORITHM LIMITATIONS:
49496 :
49497 : * algorithm does not support general linear constraints; only box ones
49498 : are supported
49499 : * Cholesky decomposition for sparse problems is performed with Skyline
49500 : Cholesky solver, which is intended for low-profile matrices. No profile-
49501 : reducing reordering of variables is performed in this version of ALGLIB.
49502 : * problems with near-zero negative eigenvalues (or exacty zero ones) may
49503 : experience about 2-3x performance penalty. The reason is that Cholesky
49504 : decomposition can not be performed until we identify directions of zero
49505 : and negative curvature and activate corresponding boundary constraints -
49506 : but we need a lot of trial and errors because these directions are hard
49507 : to notice in the matrix spectrum.
49508 : In this case you may turn off Newton phase of algorithm.
49509 : Large negative eigenvalues are not an issue, so highly non-convex
49510 : problems can be solved very efficiently.
49511 :
49512 : INPUT PARAMETERS:
49513 : State - structure which stores algorithm state
49514 : EpsG - >=0
49515 : The subroutine finishes its work if the condition
49516 : |v|<EpsG is satisfied, where:
49517 : * |.| means Euclidian norm
49518 : * v - scaled constrained gradient vector, v[i]=g[i]*s[i]
49519 : * g - gradient
49520 : * s - scaling coefficients set by MinQPSetScale()
49521 : EpsF - >=0
49522 : The subroutine finishes its work if exploratory steepest
49523 : descent step on k+1-th iteration satisfies following
49524 : condition: |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
49525 : EpsX - >=0
49526 : The subroutine finishes its work if exploratory steepest
49527 : descent step on k+1-th iteration satisfies following
49528 : condition:
49529 : * |.| means Euclidian norm
49530 : * v - scaled step vector, v[i]=dx[i]/s[i]
49531 : * dx - step vector, dx=X(k+1)-X(k)
49532 : * s - scaling coefficients set by MinQPSetScale()
49533 : MaxOuterIts-maximum number of OUTER iterations. One outer iteration
49534 : includes some amount of CG iterations (from 5 to ~N) and
49535 : one or several (usually small amount) Newton steps. Thus,
49536 : one outer iteration has high cost, but can greatly reduce
49537 : funcation value.
49538 : Use 0 if you do not want to limit number of outer iterations.
49539 : UseNewton- use Newton phase or not:
49540 : * Newton phase improves performance of positive definite
49541 : dense problems (about 2 times improvement can be observed)
49542 : * can result in some performance penalty on semidefinite
49543 : or slightly negative definite problems - each Newton
49544 : phase will bring no improvement (Cholesky failure), but
49545 : still will require computational time.
49546 : * if you doubt, you can turn off this phase - optimizer
49547 : will retain its most of its high speed.
49548 :
49549 : IT IS VERY IMPORTANT TO CALL MinQPSetScale() WHEN YOU USE THIS ALGORITHM
49550 : BECAUSE ITS STOPPING CRITERIA ARE SCALE-DEPENDENT!
49551 :
49552 : Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead
49553 : to automatic stopping criterion selection (presently it is small step
49554 : length, but it may change in the future versions of ALGLIB).
49555 :
49556 : -- ALGLIB --
49557 : Copyright 22.05.2014 by Bochkanov Sergey
49558 : *************************************************************************/
49559 0 : void minqpsetalgoquickqp(minqpstate* state,
49560 : double epsg,
49561 : double epsf,
49562 : double epsx,
49563 : ae_int_t maxouterits,
49564 : ae_bool usenewton,
49565 : ae_state *_state)
49566 : {
49567 :
49568 :
49569 0 : ae_assert(ae_isfinite(epsg, _state), "MinQPSetAlgoQuickQP: EpsG is not finite number", _state);
49570 0 : ae_assert(ae_fp_greater_eq(epsg,(double)(0)), "MinQPSetAlgoQuickQP: negative EpsG", _state);
49571 0 : ae_assert(ae_isfinite(epsf, _state), "MinQPSetAlgoQuickQP: EpsF is not finite number", _state);
49572 0 : ae_assert(ae_fp_greater_eq(epsf,(double)(0)), "MinQPSetAlgoQuickQP: negative EpsF", _state);
49573 0 : ae_assert(ae_isfinite(epsx, _state), "MinQPSetAlgoQuickQP: EpsX is not finite number", _state);
49574 0 : ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "MinQPSetAlgoQuickQP: negative EpsX", _state);
49575 0 : ae_assert(maxouterits>=0, "MinQPSetAlgoQuickQP: negative MaxOuterIts!", _state);
49576 0 : state->algokind = 3;
49577 0 : if( ((ae_fp_eq(epsg,(double)(0))&&ae_fp_eq(epsf,(double)(0)))&&ae_fp_eq(epsx,(double)(0)))&&maxouterits==0 )
49578 : {
49579 0 : epsx = 1.0E-6;
49580 : }
49581 0 : state->qqpsettingsuser.maxouterits = maxouterits;
49582 0 : state->qqpsettingsuser.epsg = epsg;
49583 0 : state->qqpsettingsuser.epsf = epsf;
49584 0 : state->qqpsettingsuser.epsx = epsx;
49585 0 : state->qqpsettingsuser.cnphase = usenewton;
49586 0 : }
49587 :
49588 :
49589 : /*************************************************************************
49590 : This function sets box constraints for QP solver
49591 :
49592 : Box constraints are inactive by default (after initial creation). After
49593 : being set, they are preserved until explicitly overwritten with another
49594 : minqpsetbc() or minqpsetbcall() call, or partially overwritten with
49595 : minqpsetbci() call.
49596 :
49597 : Following types of constraints are supported:
49598 :
49599 : DESCRIPTION CONSTRAINT HOW TO SPECIFY
49600 : fixed variable x[i]=Bnd[i] BndL[i]=BndU[i]
49601 : lower bound BndL[i]<=x[i] BndU[i]=+INF
49602 : upper bound x[i]<=BndU[i] BndL[i]=-INF
49603 : range BndL[i]<=x[i]<=BndU[i] ...
49604 : free variable - BndL[I]=-INF, BndU[I]+INF
49605 :
49606 : INPUT PARAMETERS:
49607 : State - structure stores algorithm state
49608 : BndL - lower bounds, array[N].
49609 : If some (all) variables are unbounded, you may specify
49610 : very small number or -INF (latter is recommended because
49611 : it will allow solver to use better algorithm).
49612 : BndU - upper bounds, array[N].
49613 : If some (all) variables are unbounded, you may specify
49614 : very large number or +INF (latter is recommended because
49615 : it will allow solver to use better algorithm).
49616 :
49617 : NOTE: infinite values can be specified by means of Double.PositiveInfinity
49618 : and Double.NegativeInfinity (in C#) and alglib::fp_posinf and
49619 : alglib::fp_neginf (in C++).
49620 :
49621 : NOTE: you may replace infinities by very small/very large values, but it
49622 : is not recommended because large numbers may introduce large numerical
49623 : errors in the algorithm.
49624 :
49625 : NOTE: if constraints for all variables are same you may use minqpsetbcall()
49626 : which allows to specify constraints without using arrays.
49627 :
49628 : NOTE: BndL>BndU will result in QP problem being recognized as infeasible.
49629 :
49630 : -- ALGLIB --
49631 : Copyright 11.01.2011 by Bochkanov Sergey
49632 : *************************************************************************/
49633 0 : void minqpsetbc(minqpstate* state,
49634 : /* Real */ ae_vector* bndl,
49635 : /* Real */ ae_vector* bndu,
49636 : ae_state *_state)
49637 : {
49638 : ae_int_t i;
49639 : ae_int_t n;
49640 :
49641 :
49642 0 : n = state->n;
49643 0 : ae_assert(bndl->cnt>=n, "MinQPSetBC: Length(BndL)<N", _state);
49644 0 : ae_assert(bndu->cnt>=n, "MinQPSetBC: Length(BndU)<N", _state);
49645 0 : for(i=0; i<=n-1; i++)
49646 : {
49647 0 : 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);
49648 0 : 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);
49649 0 : state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i];
49650 0 : state->havebndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state);
49651 0 : state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i];
49652 0 : state->havebndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state);
49653 : }
49654 0 : }
49655 :
49656 :
49657 : /*************************************************************************
49658 : This function sets box constraints for QP solver (all variables at once,
49659 : same constraints for all variables)
49660 :
49661 : Box constraints are inactive by default (after initial creation). After
49662 : being set, they are preserved until explicitly overwritten with another
49663 : minqpsetbc() or minqpsetbcall() call, or partially overwritten with
49664 : minqpsetbci() call.
49665 :
49666 : Following types of constraints are supported:
49667 :
49668 : DESCRIPTION CONSTRAINT HOW TO SPECIFY
49669 : fixed variable x[i]=Bnd BndL=BndU
49670 : lower bound BndL<=x[i] BndU=+INF
49671 : upper bound x[i]<=BndU BndL=-INF
49672 : range BndL<=x[i]<=BndU ...
49673 : free variable - BndL=-INF, BndU+INF
49674 :
49675 : INPUT PARAMETERS:
49676 : State - structure stores algorithm state
49677 : BndL - lower bound, same for all variables
49678 : BndU - upper bound, same for all variables
49679 :
49680 : NOTE: infinite values can be specified by means of Double.PositiveInfinity
49681 : and Double.NegativeInfinity (in C#) and alglib::fp_posinf and
49682 : alglib::fp_neginf (in C++).
49683 :
49684 : NOTE: you may replace infinities by very small/very large values, but it
49685 : is not recommended because large numbers may introduce large numerical
49686 : errors in the algorithm.
49687 :
49688 : NOTE: BndL>BndU will result in QP problem being recognized as infeasible.
49689 :
49690 : -- ALGLIB --
49691 : Copyright 11.01.2011 by Bochkanov Sergey
49692 : *************************************************************************/
49693 0 : void minqpsetbcall(minqpstate* state,
49694 : double bndl,
49695 : double bndu,
49696 : ae_state *_state)
49697 : {
49698 : ae_int_t i;
49699 : ae_int_t n;
49700 :
49701 :
49702 0 : n = state->n;
49703 0 : ae_assert(ae_isfinite(bndl, _state)||ae_isneginf(bndl, _state), "MinQPSetBCAll: BndL is NAN or +INF", _state);
49704 0 : ae_assert(ae_isfinite(bndu, _state)||ae_isposinf(bndu, _state), "MinQPSetBCAll: BndU is NAN or -INF", _state);
49705 0 : for(i=0; i<=n-1; i++)
49706 : {
49707 0 : state->bndl.ptr.p_double[i] = bndl;
49708 0 : state->bndu.ptr.p_double[i] = bndu;
49709 0 : state->havebndl.ptr.p_bool[i] = ae_isfinite(bndl, _state);
49710 0 : state->havebndu.ptr.p_bool[i] = ae_isfinite(bndu, _state);
49711 : }
49712 0 : }
49713 :
49714 :
49715 : /*************************************************************************
49716 : This function sets box constraints for I-th variable (other variables are
49717 : not modified).
49718 :
49719 : Following types of constraints are supported:
49720 :
49721 : DESCRIPTION CONSTRAINT HOW TO SPECIFY
49722 : fixed variable x[i]=Bnd BndL=BndU
49723 : lower bound BndL<=x[i] BndU=+INF
49724 : upper bound x[i]<=BndU BndL=-INF
49725 : range BndL<=x[i]<=BndU ...
49726 : free variable - BndL=-INF, BndU+INF
49727 :
49728 : INPUT PARAMETERS:
49729 : State - structure stores algorithm state
49730 : BndL - lower bound
49731 : BndU - upper bound
49732 :
49733 : NOTE: infinite values can be specified by means of Double.PositiveInfinity
49734 : and Double.NegativeInfinity (in C#) and alglib::fp_posinf and
49735 : alglib::fp_neginf (in C++).
49736 :
49737 : NOTE: you may replace infinities by very small/very large values, but it
49738 : is not recommended because large numbers may introduce large numerical
49739 : errors in the algorithm.
49740 :
49741 : NOTE: BndL>BndU will result in QP problem being recognized as infeasible.
49742 :
49743 : -- ALGLIB --
49744 : Copyright 11.01.2011 by Bochkanov Sergey
49745 : *************************************************************************/
49746 0 : void minqpsetbci(minqpstate* state,
49747 : ae_int_t i,
49748 : double bndl,
49749 : double bndu,
49750 : ae_state *_state)
49751 : {
49752 :
49753 :
49754 0 : ae_assert(i>=0&&i<state->n, "MinQPSetBCi: I is outside of [0,N)", _state);
49755 0 : ae_assert(ae_isfinite(bndl, _state)||ae_isneginf(bndl, _state), "MinQPSetBCi: BndL is NAN or +INF", _state);
49756 0 : ae_assert(ae_isfinite(bndu, _state)||ae_isposinf(bndu, _state), "MinQPSetBCi: BndU is NAN or -INF", _state);
49757 0 : state->bndl.ptr.p_double[i] = bndl;
49758 0 : state->bndu.ptr.p_double[i] = bndu;
49759 0 : state->havebndl.ptr.p_bool[i] = ae_isfinite(bndl, _state);
49760 0 : state->havebndu.ptr.p_bool[i] = ae_isfinite(bndu, _state);
49761 0 : }
49762 :
49763 :
49764 : /*************************************************************************
49765 : This function sets dense linear constraints for QP optimizer.
49766 :
49767 : This function overrides results of previous calls to minqpsetlc(),
49768 : minqpsetlcsparse() and minqpsetlcmixed(). After call to this function
49769 : all non-box constraints are dropped, and you have only those constraints
49770 : which were specified in the present call.
49771 :
49772 : If you want to specify mixed (with dense and sparse terms) linear
49773 : constraints, you should call minqpsetlcmixed().
49774 :
49775 : INPUT PARAMETERS:
49776 : State - structure previously allocated with MinQPCreate call.
49777 : C - linear constraints, array[K,N+1].
49778 : Each row of C represents one constraint, either equality
49779 : or inequality (see below):
49780 : * first N elements correspond to coefficients,
49781 : * last element corresponds to the right part.
49782 : All elements of C (including right part) must be finite.
49783 : CT - type of constraints, array[K]:
49784 : * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
49785 : * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
49786 : * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
49787 : K - number of equality/inequality constraints, K>=0:
49788 : * if given, only leading K elements of C/CT are used
49789 : * if not given, automatically determined from sizes of C/CT
49790 :
49791 : NOTE 1: linear (non-bound) constraints are satisfied only approximately -
49792 : there always exists some violation due to numerical errors and
49793 : algorithmic limitations (BLEIC-QP solver is most precise, AUL-QP
49794 : solver is less precise).
49795 :
49796 : -- ALGLIB --
49797 : Copyright 19.06.2012 by Bochkanov Sergey
49798 : *************************************************************************/
49799 0 : void minqpsetlc(minqpstate* state,
49800 : /* Real */ ae_matrix* c,
49801 : /* Integer */ ae_vector* ct,
49802 : ae_int_t k,
49803 : ae_state *_state)
49804 : {
49805 : ae_frame _frame_block;
49806 : sparsematrix dummyc;
49807 : ae_vector dummyct;
49808 :
49809 0 : ae_frame_make(_state, &_frame_block);
49810 0 : memset(&dummyc, 0, sizeof(dummyc));
49811 0 : memset(&dummyct, 0, sizeof(dummyct));
49812 0 : _sparsematrix_init(&dummyc, _state, ae_true);
49813 0 : ae_vector_init(&dummyct, 0, DT_INT, _state, ae_true);
49814 :
49815 0 : minqpsetlcmixed(state, &dummyc, &dummyct, 0, c, ct, k, _state);
49816 0 : ae_frame_leave(_state);
49817 0 : }
49818 :
49819 :
49820 : /*************************************************************************
49821 : This function sets sparse linear constraints for QP optimizer.
49822 :
49823 : This function overrides results of previous calls to minqpsetlc(),
49824 : minqpsetlcsparse() and minqpsetlcmixed(). After call to this function
49825 : all non-box constraints are dropped, and you have only those constraints
49826 : which were specified in the present call.
49827 :
49828 : If you want to specify mixed (with dense and sparse terms) linear
49829 : constraints, you should call minqpsetlcmixed().
49830 :
49831 : INPUT PARAMETERS:
49832 : State - structure previously allocated with MinQPCreate call.
49833 : C - linear constraints, sparse matrix with dimensions at
49834 : least [K,N+1]. If matrix has larger size, only leading
49835 : Kx(N+1) rectangle is used.
49836 : Each row of C represents one constraint, either equality
49837 : or inequality (see below):
49838 : * first N elements correspond to coefficients,
49839 : * last element corresponds to the right part.
49840 : All elements of C (including right part) must be finite.
49841 : CT - type of constraints, array[K]:
49842 : * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
49843 : * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
49844 : * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
49845 : K - number of equality/inequality constraints, K>=0
49846 :
49847 : NOTE 1: linear (non-bound) constraints are satisfied only approximately -
49848 : there always exists some violation due to numerical errors and
49849 : algorithmic limitations (BLEIC-QP solver is most precise, AUL-QP
49850 : solver is less precise).
49851 :
49852 : -- ALGLIB --
49853 : Copyright 22.08.2016 by Bochkanov Sergey
49854 : *************************************************************************/
49855 0 : void minqpsetlcsparse(minqpstate* state,
49856 : sparsematrix* c,
49857 : /* Integer */ ae_vector* ct,
49858 : ae_int_t k,
49859 : ae_state *_state)
49860 : {
49861 : ae_frame _frame_block;
49862 : ae_matrix dummyc;
49863 : ae_vector dummyct;
49864 :
49865 0 : ae_frame_make(_state, &_frame_block);
49866 0 : memset(&dummyc, 0, sizeof(dummyc));
49867 0 : memset(&dummyct, 0, sizeof(dummyct));
49868 0 : ae_matrix_init(&dummyc, 0, 0, DT_REAL, _state, ae_true);
49869 0 : ae_vector_init(&dummyct, 0, DT_INT, _state, ae_true);
49870 :
49871 0 : minqpsetlcmixed(state, c, ct, k, &dummyc, &dummyct, 0, _state);
49872 0 : ae_frame_leave(_state);
49873 0 : }
49874 :
49875 :
49876 : /*************************************************************************
49877 : This function sets mixed linear constraints, which include a set of dense
49878 : rows, and a set of sparse rows.
49879 :
49880 : This function overrides results of previous calls to minqpsetlc(),
49881 : minqpsetlcsparse() and minqpsetlcmixed().
49882 :
49883 : This function may be useful if constraint matrix includes large number of
49884 : both types of rows - dense and sparse. If you have just a few sparse rows,
49885 : you may represent them in dense format without losing performance.
49886 : Similarly, if you have just a few dense rows, you may store them in sparse
49887 : format with almost same performance.
49888 :
49889 : INPUT PARAMETERS:
49890 : State - structure previously allocated with MinQPCreate call.
49891 : SparseC - linear constraints, sparse matrix with dimensions EXACTLY
49892 : EQUAL TO [SparseK,N+1]. Each row of C represents one
49893 : constraint, either equality or inequality (see below):
49894 : * first N elements correspond to coefficients,
49895 : * last element corresponds to the right part.
49896 : All elements of C (including right part) must be finite.
49897 : SparseCT- type of sparse constraints, array[K]:
49898 : * if SparseCT[i]>0, then I-th constraint is SparseC[i,*]*x >= SparseC[i,n+1]
49899 : * if SparseCT[i]=0, then I-th constraint is SparseC[i,*]*x = SparseC[i,n+1]
49900 : * if SparseCT[i]<0, then I-th constraint is SparseC[i,*]*x <= SparseC[i,n+1]
49901 : SparseK - number of sparse equality/inequality constraints, K>=0
49902 : DenseC - dense linear constraints, array[K,N+1].
49903 : Each row of DenseC represents one constraint, either equality
49904 : or inequality (see below):
49905 : * first N elements correspond to coefficients,
49906 : * last element corresponds to the right part.
49907 : All elements of DenseC (including right part) must be finite.
49908 : DenseCT - type of constraints, array[K]:
49909 : * if DenseCT[i]>0, then I-th constraint is DenseC[i,*]*x >= DenseC[i,n+1]
49910 : * if DenseCT[i]=0, then I-th constraint is DenseC[i,*]*x = DenseC[i,n+1]
49911 : * if DenseCT[i]<0, then I-th constraint is DenseC[i,*]*x <= DenseC[i,n+1]
49912 : DenseK - number of equality/inequality constraints, DenseK>=0
49913 :
49914 : NOTE 1: linear (non-box) constraints are satisfied only approximately -
49915 : there always exists some violation due to numerical errors and
49916 : algorithmic limitations (BLEIC-QP solver is most precise, AUL-QP
49917 : solver is less precise).
49918 :
49919 : NOTE 2: due to backward compatibility reasons SparseC can be larger than
49920 : [SparseK,N+1]. In this case only leading [SparseK,N+1] submatrix
49921 : will be used. However, the rest of ALGLIB has more strict
49922 : requirements on the input size, so we recommend you to pass sparse
49923 : term whose size exactly matches algorithm expectations.
49924 :
49925 : -- ALGLIB --
49926 : Copyright 22.08.2016 by Bochkanov Sergey
49927 : *************************************************************************/
49928 0 : void minqpsetlcmixed(minqpstate* state,
49929 : sparsematrix* sparsec,
49930 : /* Integer */ ae_vector* sparsect,
49931 : ae_int_t sparsek,
49932 : /* Real */ ae_matrix* densec,
49933 : /* Integer */ ae_vector* densect,
49934 : ae_int_t densek,
49935 : ae_state *_state)
49936 : {
49937 : ae_frame _frame_block;
49938 : ae_int_t n;
49939 : ae_int_t i;
49940 : ae_int_t j;
49941 : ae_int_t j0;
49942 : double v;
49943 : ae_vector srcidx;
49944 : ae_vector dstidx;
49945 : ae_vector s;
49946 : ae_vector rs;
49947 : ae_vector eoffs;
49948 : ae_vector roffs;
49949 : ae_vector v2;
49950 : ae_vector eidx;
49951 : ae_vector eval;
49952 : ae_int_t t0;
49953 : ae_int_t t1;
49954 : ae_int_t nnz;
49955 :
49956 0 : ae_frame_make(_state, &_frame_block);
49957 0 : memset(&srcidx, 0, sizeof(srcidx));
49958 0 : memset(&dstidx, 0, sizeof(dstidx));
49959 0 : memset(&s, 0, sizeof(s));
49960 0 : memset(&rs, 0, sizeof(rs));
49961 0 : memset(&eoffs, 0, sizeof(eoffs));
49962 0 : memset(&roffs, 0, sizeof(roffs));
49963 0 : memset(&v2, 0, sizeof(v2));
49964 0 : memset(&eidx, 0, sizeof(eidx));
49965 0 : memset(&eval, 0, sizeof(eval));
49966 0 : ae_vector_init(&srcidx, 0, DT_INT, _state, ae_true);
49967 0 : ae_vector_init(&dstidx, 0, DT_INT, _state, ae_true);
49968 0 : ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
49969 0 : ae_vector_init(&rs, 0, DT_INT, _state, ae_true);
49970 0 : ae_vector_init(&eoffs, 0, DT_INT, _state, ae_true);
49971 0 : ae_vector_init(&roffs, 0, DT_INT, _state, ae_true);
49972 0 : ae_vector_init(&v2, 0, DT_REAL, _state, ae_true);
49973 0 : ae_vector_init(&eidx, 0, DT_INT, _state, ae_true);
49974 0 : ae_vector_init(&eval, 0, DT_REAL, _state, ae_true);
49975 :
49976 0 : n = state->n;
49977 :
49978 : /*
49979 : * First, check for errors in the inputs
49980 : */
49981 0 : ae_assert(densek>=0, "MinQPSetLCMixed: K<0", _state);
49982 0 : ae_assert(densek==0||densec->cols>=n+1, "MinQPSetLCMixed: Cols(C)<N+1", _state);
49983 0 : ae_assert(densec->rows>=densek, "MinQPSetLCMixed: Rows(DenseC)<DenseK", _state);
49984 0 : ae_assert(densect->cnt>=densek, "MinQPSetLCMixed: Length(DenseCT)<DenseK", _state);
49985 0 : ae_assert(apservisfinitematrix(densec, densek, n+1, _state), "MinQPSetLCMixed: C contains infinite or NaN values!", _state);
49986 0 : ae_assert(sparsek>=0, "MinQPSetLCMixed: SparseK<0", _state);
49987 0 : ae_assert(sparsek==0||sparsegetncols(sparsec, _state)>=n+1, "MinQPSetLCMixed: Cols(SparseC)<N+1", _state);
49988 0 : ae_assert(sparsek==0||sparsegetnrows(sparsec, _state)>=sparsek, "MinQPSetLCMixed: Rows(SparseC)<SparseK", _state);
49989 0 : ae_assert(sparsect->cnt>=sparsek, "MinQPSetLCMixed: Length(SparseCT)<SparseK", _state);
49990 :
49991 : /*
49992 : * Allocate place for Lagrange multipliers, fill by zero
49993 : */
49994 0 : rvectorsetlengthatleast(&state->replaglc, densek+sparsek, _state);
49995 0 : for(i=0; i<=densek+sparsek-1; i++)
49996 : {
49997 0 : state->replaglc.ptr.p_double[i] = 0.0;
49998 : }
49999 :
50000 : /*
50001 : * Init
50002 : */
50003 0 : ae_vector_set_length(&state->cl, densek+sparsek, _state);
50004 0 : ae_vector_set_length(&state->cu, densek+sparsek, _state);
50005 0 : state->mdense = densek;
50006 0 : state->msparse = sparsek;
50007 0 : if( sparsek>0 )
50008 : {
50009 :
50010 : /*
50011 : * Evaluate row sizes for new storage
50012 : */
50013 0 : ae_vector_set_length(&rs, sparsek, _state);
50014 0 : for(i=0; i<=sparsek-1; i++)
50015 : {
50016 0 : rs.ptr.p_int[i] = 0;
50017 : }
50018 0 : t0 = 0;
50019 0 : t1 = 0;
50020 0 : nnz = 0;
50021 0 : while(sparseenumerate(sparsec, &t0, &t1, &i, &j, &v, _state))
50022 : {
50023 0 : if( i>sparsek-1||j>n-1 )
50024 : {
50025 0 : continue;
50026 : }
50027 0 : ae_assert(ae_isfinite(v, _state), "MinQPSetLCSparse: C contains infinite or NAN values", _state);
50028 0 : nnz = nnz+1;
50029 0 : rs.ptr.p_int[i] = rs.ptr.p_int[i]+1;
50030 : }
50031 :
50032 : /*
50033 : * Prepare new sparse CRS storage, copy leading SparseK*N submatrix into the storage
50034 : */
50035 0 : for(i=0; i<=sparsek-1; i++)
50036 : {
50037 0 : state->cl.ptr.p_double[i] = (double)(0);
50038 0 : state->cu.ptr.p_double[i] = (double)(0);
50039 : }
50040 0 : state->sparsec.m = sparsek;
50041 0 : state->sparsec.n = n;
50042 0 : ivectorsetlengthatleast(&state->sparsec.ridx, sparsek+1, _state);
50043 0 : ivectorsetlengthatleast(&state->sparsec.idx, nnz, _state);
50044 0 : rvectorsetlengthatleast(&state->sparsec.vals, nnz, _state);
50045 0 : ae_vector_set_length(&eoffs, sparsek+1, _state);
50046 0 : state->sparsec.ridx.ptr.p_int[0] = 0;
50047 0 : eoffs.ptr.p_int[0] = 0;
50048 0 : for(i=1; i<=sparsek; i++)
50049 : {
50050 0 : state->sparsec.ridx.ptr.p_int[i] = state->sparsec.ridx.ptr.p_int[i-1]+rs.ptr.p_int[i-1];
50051 0 : eoffs.ptr.p_int[i] = state->sparsec.ridx.ptr.p_int[i];
50052 : }
50053 0 : t0 = 0;
50054 0 : t1 = 0;
50055 0 : while(sparseenumerate(sparsec, &t0, &t1, &i, &j, &v, _state))
50056 : {
50057 0 : if( i>sparsek-1||j>n )
50058 : {
50059 0 : continue;
50060 : }
50061 0 : if( j<n )
50062 : {
50063 :
50064 : /*
50065 : * Copy left part of constraint
50066 : */
50067 0 : j0 = eoffs.ptr.p_int[i];
50068 0 : state->sparsec.idx.ptr.p_int[j0] = j;
50069 0 : state->sparsec.vals.ptr.p_double[j0] = v;
50070 0 : eoffs.ptr.p_int[i] = j0+1;
50071 : }
50072 : else
50073 : {
50074 :
50075 : /*
50076 : * Handle right part of the constraint
50077 : */
50078 0 : state->cl.ptr.p_double[i] = v;
50079 0 : state->cu.ptr.p_double[i] = v;
50080 : }
50081 : }
50082 0 : for(i=0; i<=sparsek-1; i++)
50083 : {
50084 0 : ae_assert(eoffs.ptr.p_int[i]==state->sparsec.ridx.ptr.p_int[i+1], "MinQP: critical integrity check failed (sparse copying)", _state);
50085 : }
50086 0 : sparsecreatecrsinplace(&state->sparsec, _state);
50087 0 : for(i=0; i<=sparsek-1; i++)
50088 : {
50089 0 : if( sparsect->ptr.p_int[i]>0 )
50090 : {
50091 0 : state->cu.ptr.p_double[i] = _state->v_posinf;
50092 : }
50093 0 : if( sparsect->ptr.p_int[i]<0 )
50094 : {
50095 0 : state->cl.ptr.p_double[i] = _state->v_neginf;
50096 : }
50097 : }
50098 : }
50099 0 : if( densek>0 )
50100 : {
50101 :
50102 : /*
50103 : * Copy dense constraints
50104 : */
50105 0 : rmatrixsetlengthatleast(&state->densec, densek, n, _state);
50106 0 : for(i=0; i<=densek-1; i++)
50107 : {
50108 0 : for(j=0; j<=n-1; j++)
50109 : {
50110 0 : state->densec.ptr.pp_double[i][j] = densec->ptr.pp_double[i][j];
50111 : }
50112 0 : if( densect->ptr.p_int[i]>0 )
50113 : {
50114 0 : state->cl.ptr.p_double[sparsek+i] = densec->ptr.pp_double[i][n];
50115 0 : state->cu.ptr.p_double[sparsek+i] = _state->v_posinf;
50116 0 : continue;
50117 : }
50118 0 : if( densect->ptr.p_int[i]<0 )
50119 : {
50120 0 : state->cl.ptr.p_double[sparsek+i] = _state->v_neginf;
50121 0 : state->cu.ptr.p_double[sparsek+i] = densec->ptr.pp_double[i][n];
50122 0 : continue;
50123 : }
50124 0 : state->cl.ptr.p_double[sparsek+i] = densec->ptr.pp_double[i][n];
50125 0 : state->cu.ptr.p_double[sparsek+i] = densec->ptr.pp_double[i][n];
50126 : }
50127 : }
50128 0 : ae_frame_leave(_state);
50129 0 : }
50130 :
50131 :
50132 : /*************************************************************************
50133 : This function provides legacy API for specification of mixed dense/sparse
50134 : linear constraints.
50135 :
50136 : New conventions used by ALGLIB since release 3.16.0 state that set of
50137 : sparse constraints comes first, followed by set of dense ones. This
50138 : convention is essential when you talk about things like order of Lagrange
50139 : multipliers.
50140 :
50141 : However, legacy API accepted mixed constraints in reverse order. This
50142 : function is here to simplify situation with code relying on legacy API. It
50143 : simply accepts constraints in one order (old) and passes them to new API,
50144 : now in correct order.
50145 :
50146 : -- ALGLIB --
50147 : Copyright 01.11.2019 by Bochkanov Sergey
50148 : *************************************************************************/
50149 0 : void minqpsetlcmixedlegacy(minqpstate* state,
50150 : /* Real */ ae_matrix* densec,
50151 : /* Integer */ ae_vector* densect,
50152 : ae_int_t densek,
50153 : sparsematrix* sparsec,
50154 : /* Integer */ ae_vector* sparsect,
50155 : ae_int_t sparsek,
50156 : ae_state *_state)
50157 : {
50158 :
50159 :
50160 0 : minqpsetlcmixed(state, sparsec, sparsect, sparsek, densec, densect, densek, _state);
50161 0 : }
50162 :
50163 :
50164 : /*************************************************************************
50165 : This function sets two-sided linear constraints AL <= A*x <= AU with dense
50166 : constraint matrix A.
50167 :
50168 : NOTE: knowing that constraint matrix is dense helps some QP solvers
50169 : (especially modern IPM method) to utilize efficient dense Level 3
50170 : BLAS for dense parts of the problem. If your problem has both dense
50171 : and sparse constraints, you can use minqpsetlc2mixed() function,
50172 : which will result in dense algebra being applied to dense terms, and
50173 : sparse sparse linear algebra applied to sparse terms.
50174 :
50175 : INPUT PARAMETERS:
50176 : State - structure previously allocated with minqpcreate() call.
50177 : A - linear constraints, array[K,N]. Each row of A represents
50178 : one constraint. One-sided inequality constraints, two-
50179 : sided inequality constraints, equality constraints are
50180 : supported (see below)
50181 : AL, AU - lower and upper bounds, array[K];
50182 : * AL[i]=AU[i] => equality constraint Ai*x
50183 : * AL[i]<AU[i] => two-sided constraint AL[i]<=Ai*x<=AU[i]
50184 : * AL[i]=-INF => one-sided constraint Ai*x<=AU[i]
50185 : * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x
50186 : * AL[i]=-INF, AU[i]=+INF => constraint is ignored
50187 : K - number of equality/inequality constraints, K>=0; if not
50188 : given, inferred from sizes of A, AL, AU.
50189 :
50190 : -- ALGLIB --
50191 : Copyright 01.11.2019 by Bochkanov Sergey
50192 : *************************************************************************/
50193 0 : void minqpsetlc2dense(minqpstate* state,
50194 : /* Real */ ae_matrix* a,
50195 : /* Real */ ae_vector* al,
50196 : /* Real */ ae_vector* au,
50197 : ae_int_t k,
50198 : ae_state *_state)
50199 : {
50200 :
50201 :
50202 0 : minqpsetlc2mixed(state, &state->dummysparse, 0, a, k, al, au, _state);
50203 0 : }
50204 :
50205 :
50206 : /*************************************************************************
50207 : This function sets two-sided linear constraints AL <= A*x <= AU with
50208 : sparse constraining matrix A. Recommended for large-scale problems.
50209 :
50210 : This function overwrites linear (non-box) constraints set by previous
50211 : calls (if such calls were made).
50212 :
50213 : INPUT PARAMETERS:
50214 : State - structure previously allocated with minqpcreate() call.
50215 : A - sparse matrix with size [K,N] (exactly!).
50216 : Each row of A represents one general linear constraint.
50217 : A can be stored in any sparse storage format.
50218 : AL, AU - lower and upper bounds, array[K];
50219 : * AL[i]=AU[i] => equality constraint Ai*x
50220 : * AL[i]<AU[i] => two-sided constraint AL[i]<=Ai*x<=AU[i]
50221 : * AL[i]=-INF => one-sided constraint Ai*x<=AU[i]
50222 : * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x
50223 : * AL[i]=-INF, AU[i]=+INF => constraint is ignored
50224 : K - number of equality/inequality constraints, K>=0. If K=0
50225 : is specified, A, AL, AU are ignored.
50226 :
50227 : -- ALGLIB --
50228 : Copyright 01.11.2019 by Bochkanov Sergey
50229 : *************************************************************************/
50230 0 : void minqpsetlc2(minqpstate* state,
50231 : sparsematrix* a,
50232 : /* Real */ ae_vector* al,
50233 : /* Real */ ae_vector* au,
50234 : ae_int_t k,
50235 : ae_state *_state)
50236 : {
50237 :
50238 :
50239 0 : minqpsetlc2mixed(state, a, k, &state->dummyr2, 0, al, au, _state);
50240 0 : }
50241 :
50242 :
50243 : /*************************************************************************
50244 : This function sets two-sided linear constraints AL <= A*x <= AU with
50245 : mixed constraining matrix A including sparse part (first SparseK rows) and
50246 : dense part (last DenseK rows). Recommended for large-scale problems.
50247 :
50248 : This function overwrites linear (non-box) constraints set by previous
50249 : calls (if such calls were made).
50250 :
50251 : This function may be useful if constraint matrix includes large number of
50252 : both types of rows - dense and sparse. If you have just a few sparse rows,
50253 : you may represent them in dense format without losing performance.
50254 : Similarly, if you have just a few dense rows, you may store them in sparse
50255 : format with almost same performance.
50256 :
50257 : INPUT PARAMETERS:
50258 : State - structure previously allocated with minqpcreate() call.
50259 : SparseA - sparse matrix with size [K,N] (exactly!).
50260 : Each row of A represents one general linear constraint.
50261 : A can be stored in any sparse storage format.
50262 : SparseK - number of sparse constraints, SparseK>=0
50263 : DenseA - linear constraints, array[K,N], set of dense constraints.
50264 : Each row of A represents one general linear constraint.
50265 : DenseK - number of dense constraints, DenseK>=0
50266 : AL, AU - lower and upper bounds, array[SparseK+DenseK], with former
50267 : SparseK elements corresponding to sparse constraints, and
50268 : latter DenseK elements corresponding to dense constraints;
50269 : * AL[i]=AU[i] => equality constraint Ai*x
50270 : * AL[i]<AU[i] => two-sided constraint AL[i]<=Ai*x<=AU[i]
50271 : * AL[i]=-INF => one-sided constraint Ai*x<=AU[i]
50272 : * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x
50273 : * AL[i]=-INF, AU[i]=+INF => constraint is ignored
50274 : K - number of equality/inequality constraints, K>=0. If K=0
50275 : is specified, A, AL, AU are ignored.
50276 :
50277 : -- ALGLIB --
50278 : Copyright 01.11.2019 by Bochkanov Sergey
50279 : *************************************************************************/
50280 0 : void minqpsetlc2mixed(minqpstate* state,
50281 : sparsematrix* sparsea,
50282 : ae_int_t ksparse,
50283 : /* Real */ ae_matrix* densea,
50284 : ae_int_t kdense,
50285 : /* Real */ ae_vector* al,
50286 : /* Real */ ae_vector* au,
50287 : ae_state *_state)
50288 : {
50289 : ae_int_t n;
50290 : ae_int_t m;
50291 : ae_int_t i;
50292 :
50293 :
50294 0 : n = state->n;
50295 0 : m = kdense+ksparse;
50296 :
50297 : /*
50298 : * Check input arguments
50299 : */
50300 0 : ae_assert(ksparse>=0, "MinQPSetLC2Mixed: KSparse<0", _state);
50301 0 : ae_assert(ksparse==0||sparsegetncols(sparsea, _state)==n, "MinQPSetLC2: Cols(SparseA)<>N", _state);
50302 0 : ae_assert(ksparse==0||sparsegetnrows(sparsea, _state)==ksparse, "MinQPSetLC2: Rows(SparseA)<>K", _state);
50303 0 : ae_assert(kdense>=0, "MinQPSetLC2Mixed: KDense<0", _state);
50304 0 : ae_assert(kdense==0||densea->cols>=n, "MinQPSetLC2Mixed: Cols(DenseA)<N", _state);
50305 0 : ae_assert(kdense==0||densea->rows>=kdense, "MinQPSetLC2Mixed: Rows(DenseA)<K", _state);
50306 0 : ae_assert(apservisfinitematrix(densea, kdense, n, _state), "MinQPSetLC2Mixed: DenseA contains infinite or NaN values!", _state);
50307 0 : ae_assert(al->cnt>=kdense+ksparse, "MinQPSetLC2Mixed: Length(AL)<K", _state);
50308 0 : ae_assert(au->cnt>=kdense+ksparse, "MinQPSetLC2Mixed: Length(AU)<K", _state);
50309 0 : for(i=0; i<=m-1; i++)
50310 : {
50311 0 : ae_assert(ae_isfinite(al->ptr.p_double[i], _state)||ae_isneginf(al->ptr.p_double[i], _state), "MinQPSetLC2Mixed: AL contains NAN or +INF", _state);
50312 0 : ae_assert(ae_isfinite(au->ptr.p_double[i], _state)||ae_isposinf(au->ptr.p_double[i], _state), "MinQPSetLC2Mixed: AU contains NAN or -INF", _state);
50313 : }
50314 :
50315 : /*
50316 : * Allocate place for Lagrange multipliers, fill by zero
50317 : */
50318 0 : rvectorsetlengthatleast(&state->replaglc, kdense+ksparse, _state);
50319 0 : for(i=0; i<=kdense+ksparse-1; i++)
50320 : {
50321 0 : state->replaglc.ptr.p_double[i] = 0.0;
50322 : }
50323 :
50324 : /*
50325 : * Quick exit if needed
50326 : */
50327 0 : if( m==0 )
50328 : {
50329 0 : state->mdense = 0;
50330 0 : state->msparse = 0;
50331 0 : return;
50332 : }
50333 :
50334 : /*
50335 : * Prepare
50336 : */
50337 0 : rvectorsetlengthatleast(&state->cl, m, _state);
50338 0 : rvectorsetlengthatleast(&state->cu, m, _state);
50339 0 : for(i=0; i<=m-1; i++)
50340 : {
50341 0 : state->cl.ptr.p_double[i] = al->ptr.p_double[i];
50342 0 : state->cu.ptr.p_double[i] = au->ptr.p_double[i];
50343 : }
50344 0 : state->mdense = kdense;
50345 0 : state->msparse = ksparse;
50346 :
50347 : /*
50348 : * Copy dense and sparse terms
50349 : */
50350 0 : if( ksparse>0 )
50351 : {
50352 0 : sparsecopytocrsbuf(sparsea, &state->sparsec, _state);
50353 : }
50354 0 : if( kdense>0 )
50355 : {
50356 0 : rmatrixsetlengthatleast(&state->densec, kdense, n, _state);
50357 0 : rmatrixcopy(kdense, n, densea, 0, 0, &state->densec, 0, 0, _state);
50358 : }
50359 : }
50360 :
50361 :
50362 : /*************************************************************************
50363 : This function appends two-sided linear constraint AL <= A*x <= AU to the
50364 : list of currently present dense constraints.
50365 :
50366 : INPUT PARAMETERS:
50367 : State - structure previously allocated with minqpcreate() call.
50368 : A - linear constraint coefficient, array[N], right side is NOT
50369 : included.
50370 : AL, AU - lower and upper bounds;
50371 : * AL=AU => equality constraint Ai*x
50372 : * AL<AU => two-sided constraint AL<=A*x<=AU
50373 : * AL=-INF => one-sided constraint Ai*x<=AU
50374 : * AU=+INF => one-sided constraint AL<=Ai*x
50375 : * AL=-INF, AU=+INF => constraint is ignored
50376 :
50377 : -- ALGLIB --
50378 : Copyright 19.07.2018 by Bochkanov Sergey
50379 : *************************************************************************/
50380 0 : void minqpaddlc2dense(minqpstate* state,
50381 : /* Real */ ae_vector* a,
50382 : double al,
50383 : double au,
50384 : ae_state *_state)
50385 : {
50386 : ae_int_t i;
50387 : ae_int_t n;
50388 :
50389 :
50390 0 : n = state->n;
50391 0 : ae_assert(a->cnt>=n, "MinQPAddLC2Dense: Length(A)<N", _state);
50392 0 : ae_assert(isfinitevector(a, n, _state), "MinQPAddLC2Dense: A contains infinite or NaN values!", _state);
50393 0 : ae_assert(ae_isfinite(al, _state)||ae_isneginf(al, _state), "MinQPAddLC2Dense: AL is NAN or +INF", _state);
50394 0 : ae_assert(ae_isfinite(au, _state)||ae_isposinf(au, _state), "MinQPAddLC2Dense: AU is NAN or -INF", _state);
50395 0 : rvectorgrowto(&state->cl, state->msparse+state->mdense+1, _state);
50396 0 : rvectorgrowto(&state->cu, state->msparse+state->mdense+1, _state);
50397 0 : rvectorgrowto(&state->replaglc, state->msparse+state->mdense+1, _state);
50398 0 : rmatrixgrowrowsto(&state->densec, state->mdense+1, n, _state);
50399 0 : for(i=0; i<=n-1; i++)
50400 : {
50401 0 : state->densec.ptr.pp_double[state->mdense][i] = a->ptr.p_double[i];
50402 : }
50403 0 : state->cl.ptr.p_double[state->msparse+state->mdense] = al;
50404 0 : state->cu.ptr.p_double[state->msparse+state->mdense] = au;
50405 0 : state->replaglc.ptr.p_double[state->msparse+state->mdense] = 0.0;
50406 0 : inc(&state->mdense, _state);
50407 0 : }
50408 :
50409 :
50410 : /*************************************************************************
50411 : This function appends two-sided linear constraint AL <= A*x <= AU to the
50412 : list of currently present sparse constraints.
50413 :
50414 : Constraint is passed in compressed format: as list of non-zero entries of
50415 : coefficient vector A. Such approach is more efficient than dense storage
50416 : for highly sparse constraint vectors.
50417 :
50418 : INPUT PARAMETERS:
50419 : State - structure previously allocated with minqpcreate() call.
50420 : IdxA - array[NNZ], indexes of non-zero elements of A:
50421 : * can be unsorted
50422 : * can include duplicate indexes (corresponding entries of
50423 : ValA[] will be summed)
50424 : ValA - array[NNZ], values of non-zero elements of A
50425 : NNZ - number of non-zero coefficients in A
50426 : AL, AU - lower and upper bounds;
50427 : * AL=AU => equality constraint A*x
50428 : * AL<AU => two-sided constraint AL<=A*x<=AU
50429 : * AL=-INF => one-sided constraint A*x<=AU
50430 : * AU=+INF => one-sided constraint AL<=A*x
50431 : * AL=-INF, AU=+INF => constraint is ignored
50432 :
50433 : -- ALGLIB --
50434 : Copyright 19.07.2018 by Bochkanov Sergey
50435 : *************************************************************************/
50436 0 : void minqpaddlc2(minqpstate* state,
50437 : /* Integer */ ae_vector* idxa,
50438 : /* Real */ ae_vector* vala,
50439 : ae_int_t nnz,
50440 : double al,
50441 : double au,
50442 : ae_state *_state)
50443 : {
50444 : ae_int_t i;
50445 : ae_int_t j;
50446 : ae_int_t k;
50447 : ae_int_t offs;
50448 : ae_int_t offsdst;
50449 : ae_int_t n;
50450 : ae_int_t didx;
50451 : ae_int_t uidx;
50452 :
50453 :
50454 0 : n = state->n;
50455 :
50456 : /*
50457 : * Check inputs
50458 : */
50459 0 : ae_assert(nnz>=0, "MinQPAddLC2: NNZ<0", _state);
50460 0 : ae_assert(idxa->cnt>=nnz, "MinQPAddLC2: Length(IdxA)<NNZ", _state);
50461 0 : ae_assert(vala->cnt>=nnz, "MinQPAddLC2: Length(ValA)<NNZ", _state);
50462 0 : for(i=0; i<=nnz-1; i++)
50463 : {
50464 0 : ae_assert(idxa->ptr.p_int[i]>=0&&idxa->ptr.p_int[i]<n, "MinQPAddLC2: IdxA contains indexes outside of [0,N) range", _state);
50465 : }
50466 0 : ae_assert(isfinitevector(vala, nnz, _state), "MinQPAddLC2: ValA contains infinite or NaN values!", _state);
50467 0 : ae_assert(ae_isfinite(al, _state)||ae_isneginf(al, _state), "MinQPAddLC2Dense: AL is NAN or +INF", _state);
50468 0 : ae_assert(ae_isfinite(au, _state)||ae_isposinf(au, _state), "MinQPAddLC2Dense: AU is NAN or -INF", _state);
50469 :
50470 : /*
50471 : * If M=0, it means that A is uninitialized.
50472 : * Prepare sparse matrix structure
50473 : */
50474 0 : if( state->msparse==0 )
50475 : {
50476 0 : state->sparsec.matrixtype = 1;
50477 0 : state->sparsec.m = 0;
50478 0 : state->sparsec.n = n;
50479 0 : state->sparsec.ninitialized = 0;
50480 0 : ivectorsetlengthatleast(&state->sparsec.ridx, 1, _state);
50481 0 : state->sparsec.ridx.ptr.p_int[0] = 0;
50482 : }
50483 0 : ae_assert(state->sparsec.matrixtype==1&&state->sparsec.m==state->msparse, "MinQPAddLC2Dense: integrity check failed!", _state);
50484 :
50485 : /*
50486 : * Reallocate inequality bounds
50487 : */
50488 0 : rvectorgrowto(&state->cl, state->msparse+state->mdense+1, _state);
50489 0 : rvectorgrowto(&state->cu, state->msparse+state->mdense+1, _state);
50490 0 : rvectorgrowto(&state->replaglc, state->msparse+state->mdense+1, _state);
50491 0 : for(i=state->msparse+state->mdense; i>=state->msparse+1; i--)
50492 : {
50493 0 : state->cl.ptr.p_double[i] = state->cl.ptr.p_double[i-1];
50494 0 : state->cu.ptr.p_double[i] = state->cu.ptr.p_double[i-1];
50495 0 : state->replaglc.ptr.p_double[i] = state->replaglc.ptr.p_double[i-1];
50496 : }
50497 0 : state->cl.ptr.p_double[state->msparse] = al;
50498 0 : state->cu.ptr.p_double[state->msparse] = au;
50499 0 : state->replaglc.ptr.p_double[state->msparse] = 0.0;
50500 :
50501 : /*
50502 : * Reallocate sparse storage
50503 : */
50504 0 : offs = state->sparsec.ridx.ptr.p_int[state->msparse];
50505 0 : ivectorgrowto(&state->sparsec.idx, offs+nnz, _state);
50506 0 : rvectorgrowto(&state->sparsec.vals, offs+nnz, _state);
50507 0 : ivectorgrowto(&state->sparsec.didx, state->msparse+1, _state);
50508 0 : ivectorgrowto(&state->sparsec.uidx, state->msparse+1, _state);
50509 0 : ivectorgrowto(&state->sparsec.ridx, state->msparse+2, _state);
50510 :
50511 : /*
50512 : * If NNZ=0, perform quick and simple row append.
50513 : */
50514 0 : if( nnz==0 )
50515 : {
50516 0 : state->sparsec.didx.ptr.p_int[state->msparse] = state->sparsec.ridx.ptr.p_int[state->msparse];
50517 0 : state->sparsec.uidx.ptr.p_int[state->msparse] = state->sparsec.ridx.ptr.p_int[state->msparse];
50518 0 : state->sparsec.ridx.ptr.p_int[state->msparse+1] = state->sparsec.ridx.ptr.p_int[state->msparse];
50519 0 : inc(&state->sparsec.m, _state);
50520 0 : inc(&state->msparse, _state);
50521 0 : return;
50522 : }
50523 :
50524 : /*
50525 : * Now we are sure that SparseC contains properly initialized sparse
50526 : * matrix (or some appropriate dummy for M=0) and we have NNZ>0
50527 : * (no need to care about degenerate cases).
50528 : *
50529 : * Append rows to SparseC:
50530 : * * append data
50531 : * * sort in place
50532 : * * merge duplicate indexes
50533 : * * compute DIdx and UIdx
50534 : *
50535 : */
50536 0 : for(i=0; i<=nnz-1; i++)
50537 : {
50538 0 : state->sparsec.idx.ptr.p_int[offs+i] = idxa->ptr.p_int[i];
50539 0 : state->sparsec.vals.ptr.p_double[offs+i] = vala->ptr.p_double[i];
50540 : }
50541 0 : tagsortmiddleir(&state->sparsec.idx, &state->sparsec.vals, offs, nnz, _state);
50542 0 : offsdst = offs;
50543 0 : for(i=1; i<=nnz-1; i++)
50544 : {
50545 0 : if( state->sparsec.idx.ptr.p_int[offsdst]!=state->sparsec.idx.ptr.p_int[offs+i] )
50546 : {
50547 0 : offsdst = offsdst+1;
50548 0 : state->sparsec.idx.ptr.p_int[offsdst] = state->sparsec.idx.ptr.p_int[offs+i];
50549 0 : state->sparsec.vals.ptr.p_double[offsdst] = state->sparsec.vals.ptr.p_double[offs+i];
50550 : }
50551 : else
50552 : {
50553 0 : state->sparsec.vals.ptr.p_double[offsdst] = state->sparsec.vals.ptr.p_double[offsdst]+state->sparsec.vals.ptr.p_double[offs+i];
50554 : }
50555 : }
50556 0 : nnz = offsdst-offs+1;
50557 0 : uidx = -1;
50558 0 : didx = -1;
50559 0 : for(j=offs; j<=offsdst; j++)
50560 : {
50561 0 : k = state->sparsec.idx.ptr.p_int[j];
50562 0 : if( k==state->msparse )
50563 : {
50564 0 : didx = j;
50565 : }
50566 : else
50567 : {
50568 0 : if( k>state->msparse&&uidx==-1 )
50569 : {
50570 0 : uidx = j;
50571 0 : break;
50572 : }
50573 : }
50574 : }
50575 0 : if( uidx==-1 )
50576 : {
50577 0 : uidx = offsdst+1;
50578 : }
50579 0 : if( didx==-1 )
50580 : {
50581 0 : didx = uidx;
50582 : }
50583 0 : state->sparsec.didx.ptr.p_int[state->msparse] = didx;
50584 0 : state->sparsec.uidx.ptr.p_int[state->msparse] = uidx;
50585 0 : state->sparsec.ridx.ptr.p_int[state->msparse+1] = offsdst+1;
50586 0 : state->sparsec.ninitialized = state->sparsec.ridx.ptr.p_int[state->msparse+1];
50587 0 : inc(&state->sparsec.m, _state);
50588 0 : inc(&state->msparse, _state);
50589 : }
50590 :
50591 :
50592 : /*************************************************************************
50593 : This function solves quadratic programming problem.
50594 :
50595 : Prior to calling this function you should choose solver by means of one of
50596 : the following functions:
50597 :
50598 : * minqpsetalgoquickqp() - for QuickQP solver
50599 : * minqpsetalgobleic() - for BLEIC-QP solver
50600 : * minqpsetalgodenseaul() - for Dense-AUL-QP solver
50601 : * minqpsetalgodenseipm() - for Dense-IPM-QP solver
50602 :
50603 : These functions also allow you to control stopping criteria of the solver.
50604 : If you did not set solver, MinQP subpackage will automatically select
50605 : solver for your problem and will run it with default stopping criteria.
50606 :
50607 : However, it is better to set explicitly solver and its stopping criteria.
50608 :
50609 : INPUT PARAMETERS:
50610 : State - algorithm state
50611 :
50612 : You should use MinQPResults() function to access results after calls
50613 : to this function.
50614 :
50615 : -- ALGLIB --
50616 : Copyright 11.01.2011 by Bochkanov Sergey.
50617 : Special thanks to Elvira Illarionova for important suggestions on
50618 : the linearly constrained QP algorithm.
50619 : *************************************************************************/
50620 0 : void minqpoptimize(minqpstate* state, ae_state *_state)
50621 : {
50622 : ae_int_t n;
50623 : ae_int_t m;
50624 : ae_int_t i;
50625 : ae_int_t j;
50626 : ae_int_t j0;
50627 : ae_int_t j1;
50628 : ae_int_t nbc;
50629 : ae_int_t neq;
50630 : ae_int_t nineq;
50631 : ae_int_t curecpos;
50632 : ae_int_t curicpos;
50633 :
50634 :
50635 0 : n = state->n;
50636 0 : m = state->mdense+state->msparse;
50637 0 : state->repterminationtype = -5;
50638 0 : state->repinneriterationscount = 0;
50639 0 : state->repouteriterationscount = 0;
50640 0 : state->repncholesky = 0;
50641 0 : state->repnmv = 0;
50642 :
50643 : /*
50644 : * Zero-fill Lagrange multipliers (their initial value)
50645 : */
50646 0 : for(i=0; i<=n-1; i++)
50647 : {
50648 0 : state->replagbc.ptr.p_double[i] = 0.0;
50649 : }
50650 0 : for(i=0; i<=m-1; i++)
50651 : {
50652 0 : state->replaglc.ptr.p_double[i] = 0.0;
50653 : }
50654 :
50655 : /*
50656 : * Initial point:
50657 : * * if we have starting point in StartX, we just have to bound it
50658 : * * if we do not have StartX, deduce initial point from boundary constraints
50659 : */
50660 0 : if( state->havex )
50661 : {
50662 0 : for(i=0; i<=n-1; i++)
50663 : {
50664 0 : state->xs.ptr.p_double[i] = state->startx.ptr.p_double[i];
50665 0 : if( state->havebndl.ptr.p_bool[i]&&ae_fp_less(state->xs.ptr.p_double[i],state->bndl.ptr.p_double[i]) )
50666 : {
50667 0 : state->xs.ptr.p_double[i] = state->bndl.ptr.p_double[i];
50668 : }
50669 0 : if( state->havebndu.ptr.p_bool[i]&&ae_fp_greater(state->xs.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
50670 : {
50671 0 : state->xs.ptr.p_double[i] = state->bndu.ptr.p_double[i];
50672 : }
50673 : }
50674 : }
50675 : else
50676 : {
50677 0 : for(i=0; i<=n-1; i++)
50678 : {
50679 0 : if( state->havebndl.ptr.p_bool[i]&&state->havebndu.ptr.p_bool[i] )
50680 : {
50681 0 : state->xs.ptr.p_double[i] = 0.5*(state->bndl.ptr.p_double[i]+state->bndu.ptr.p_double[i]);
50682 0 : continue;
50683 : }
50684 0 : if( state->havebndl.ptr.p_bool[i] )
50685 : {
50686 0 : state->xs.ptr.p_double[i] = state->bndl.ptr.p_double[i];
50687 0 : continue;
50688 : }
50689 0 : if( state->havebndu.ptr.p_bool[i] )
50690 : {
50691 0 : state->xs.ptr.p_double[i] = state->bndu.ptr.p_double[i];
50692 0 : continue;
50693 : }
50694 0 : state->xs.ptr.p_double[i] = (double)(0);
50695 : }
50696 : }
50697 :
50698 : /*
50699 : * check correctness of constraints
50700 : */
50701 0 : for(i=0; i<=n-1; i++)
50702 : {
50703 0 : if( state->havebndl.ptr.p_bool[i]&&state->havebndu.ptr.p_bool[i] )
50704 : {
50705 0 : if( ae_fp_greater(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
50706 : {
50707 0 : state->repterminationtype = -3;
50708 0 : return;
50709 : }
50710 : }
50711 : }
50712 :
50713 : /*
50714 : * count number of bound and linear constraints
50715 : */
50716 0 : nbc = 0;
50717 0 : for(i=0; i<=n-1; i++)
50718 : {
50719 0 : if( state->havebndl.ptr.p_bool[i] )
50720 : {
50721 0 : nbc = nbc+1;
50722 : }
50723 0 : if( state->havebndu.ptr.p_bool[i] )
50724 : {
50725 0 : nbc = nbc+1;
50726 : }
50727 : }
50728 :
50729 : /*
50730 : * Effective scale
50731 : */
50732 0 : rvectorsetlengthatleast(&state->effectives, n, _state);
50733 0 : if( state->stype==0 )
50734 : {
50735 :
50736 : /*
50737 : * User scale (or default one)
50738 : */
50739 0 : for(i=0; i<=n-1; i++)
50740 : {
50741 0 : state->effectives.ptr.p_double[i] = state->s.ptr.p_double[i];
50742 : }
50743 : }
50744 : else
50745 : {
50746 0 : if( state->stype==1 )
50747 : {
50748 :
50749 : /*
50750 : * Diagonal is used for scaling:
50751 : * * unpack
50752 : * * convert to scale, return error on failure
50753 : */
50754 0 : if( state->akind==0 )
50755 : {
50756 :
50757 : /*
50758 : * Unpack CQM structure
50759 : */
50760 0 : cqmgetdiaga(&state->a, &state->effectives, _state);
50761 : }
50762 : else
50763 : {
50764 0 : if( state->akind==1 )
50765 : {
50766 0 : for(i=0; i<=n-1; i++)
50767 : {
50768 0 : state->effectives.ptr.p_double[i] = sparseget(&state->sparsea, i, i, _state);
50769 : }
50770 : }
50771 : else
50772 : {
50773 0 : ae_assert(ae_false, "MinQPOptimize: integrity check failed", _state);
50774 : }
50775 : }
50776 0 : for(i=0; i<=n-1; i++)
50777 : {
50778 0 : if( ae_fp_less_eq(state->effectives.ptr.p_double[i],(double)(0)) )
50779 : {
50780 0 : state->repterminationtype = -9;
50781 0 : return;
50782 : }
50783 0 : state->effectives.ptr.p_double[i] = 1/ae_sqrt(state->effectives.ptr.p_double[i], _state);
50784 : }
50785 : }
50786 : else
50787 : {
50788 0 : ae_assert(ae_false, "MinQPOptimize: integrity check failed", _state);
50789 : }
50790 : }
50791 :
50792 : /*
50793 : * Solvers which can not handle new two-sided constraints need them to be
50794 : * converted into legacy equality/inequality one-sided format
50795 : */
50796 0 : if( state->algokind==2||state->algokind==4 )
50797 : {
50798 :
50799 : /*
50800 : * Scan constraint left/right sides, count equality ones and one/two-sided inequality ones
50801 : */
50802 0 : neq = 0;
50803 0 : nineq = 0;
50804 0 : for(i=0; i<=m-1; i++)
50805 : {
50806 0 : if( (ae_isfinite(state->cl.ptr.p_double[i], _state)&&ae_isfinite(state->cu.ptr.p_double[i], _state))&&ae_fp_eq(state->cl.ptr.p_double[i],state->cu.ptr.p_double[i]) )
50807 : {
50808 0 : inc(&neq, _state);
50809 0 : continue;
50810 : }
50811 0 : if( ae_isfinite(state->cl.ptr.p_double[i], _state) )
50812 : {
50813 0 : inc(&nineq, _state);
50814 : }
50815 0 : if( ae_isfinite(state->cu.ptr.p_double[i], _state) )
50816 : {
50817 0 : inc(&nineq, _state);
50818 : }
50819 : }
50820 :
50821 : /*
50822 : * Perform conversion
50823 : */
50824 0 : rmatrixsetlengthatleast(&state->ecleic, neq+nineq, n+1, _state);
50825 0 : rvectorsetlengthatleast(&state->elagmlt, neq+nineq, _state);
50826 0 : ivectorsetlengthatleast(&state->elagidx, neq+nineq, _state);
50827 0 : curecpos = 0;
50828 0 : curicpos = neq;
50829 0 : for(i=0; i<=m-1; i++)
50830 : {
50831 0 : if( (ae_isfinite(state->cl.ptr.p_double[i], _state)&&ae_isfinite(state->cu.ptr.p_double[i], _state))&&ae_fp_eq(state->cl.ptr.p_double[i],state->cu.ptr.p_double[i]) )
50832 : {
50833 :
50834 : /*
50835 : * Offload equality constraint
50836 : */
50837 0 : if( i<state->msparse )
50838 : {
50839 0 : for(j=0; j<=n-1; j++)
50840 : {
50841 0 : state->ecleic.ptr.pp_double[curecpos][j] = (double)(0);
50842 : }
50843 0 : j0 = state->sparsec.ridx.ptr.p_int[i];
50844 0 : j1 = state->sparsec.ridx.ptr.p_int[i+1]-1;
50845 0 : for(j=j0; j<=j1; j++)
50846 : {
50847 0 : state->ecleic.ptr.pp_double[curecpos][state->sparsec.idx.ptr.p_int[j]] = state->sparsec.vals.ptr.p_double[j];
50848 : }
50849 : }
50850 : else
50851 : {
50852 0 : for(j=0; j<=n-1; j++)
50853 : {
50854 0 : state->ecleic.ptr.pp_double[curecpos][j] = state->densec.ptr.pp_double[i-state->msparse][j];
50855 : }
50856 : }
50857 0 : state->ecleic.ptr.pp_double[curecpos][n] = state->cu.ptr.p_double[i];
50858 0 : state->elagidx.ptr.p_int[curecpos] = i;
50859 0 : state->elagmlt.ptr.p_double[curecpos] = 1.0;
50860 0 : inc(&curecpos, _state);
50861 0 : continue;
50862 : }
50863 0 : if( ae_isfinite(state->cl.ptr.p_double[i], _state) )
50864 : {
50865 :
50866 : /*
50867 : * Offload inequality constraint of the form CL<=C*x, convert it to -C*x<=-CL
50868 : */
50869 0 : if( i<state->msparse )
50870 : {
50871 0 : for(j=0; j<=n-1; j++)
50872 : {
50873 0 : state->ecleic.ptr.pp_double[curicpos][j] = (double)(0);
50874 : }
50875 0 : j0 = state->sparsec.ridx.ptr.p_int[i];
50876 0 : j1 = state->sparsec.ridx.ptr.p_int[i+1]-1;
50877 0 : for(j=j0; j<=j1; j++)
50878 : {
50879 0 : state->ecleic.ptr.pp_double[curicpos][state->sparsec.idx.ptr.p_int[j]] = -state->sparsec.vals.ptr.p_double[j];
50880 : }
50881 : }
50882 : else
50883 : {
50884 0 : for(j=0; j<=n-1; j++)
50885 : {
50886 0 : state->ecleic.ptr.pp_double[curicpos][j] = -state->densec.ptr.pp_double[i-state->msparse][j];
50887 : }
50888 : }
50889 0 : state->ecleic.ptr.pp_double[curicpos][n] = -state->cl.ptr.p_double[i];
50890 0 : state->elagidx.ptr.p_int[curicpos] = i;
50891 0 : state->elagmlt.ptr.p_double[curicpos] = -1.0;
50892 0 : inc(&curicpos, _state);
50893 : }
50894 0 : if( ae_isfinite(state->cu.ptr.p_double[i], _state) )
50895 : {
50896 :
50897 : /*
50898 : * Offload inequality constraint of the form C*x<=CU
50899 : */
50900 0 : if( i<state->msparse )
50901 : {
50902 0 : for(j=0; j<=n-1; j++)
50903 : {
50904 0 : state->ecleic.ptr.pp_double[curicpos][j] = (double)(0);
50905 : }
50906 0 : j0 = state->sparsec.ridx.ptr.p_int[i];
50907 0 : j1 = state->sparsec.ridx.ptr.p_int[i+1]-1;
50908 0 : for(j=j0; j<=j1; j++)
50909 : {
50910 0 : state->ecleic.ptr.pp_double[curicpos][state->sparsec.idx.ptr.p_int[j]] = state->sparsec.vals.ptr.p_double[j];
50911 : }
50912 : }
50913 : else
50914 : {
50915 0 : for(j=0; j<=n-1; j++)
50916 : {
50917 0 : state->ecleic.ptr.pp_double[curicpos][j] = state->densec.ptr.pp_double[i-state->msparse][j];
50918 : }
50919 : }
50920 0 : state->ecleic.ptr.pp_double[curicpos][n] = state->cu.ptr.p_double[i];
50921 0 : state->elagidx.ptr.p_int[curicpos] = i;
50922 0 : state->elagmlt.ptr.p_double[curicpos] = 1.0;
50923 0 : inc(&curicpos, _state);
50924 : }
50925 : }
50926 0 : ae_assert(curecpos==neq&&curicpos==neq+nineq, "MinQPOptimize: critical integrity check failed (ECLEIC conversion)", _state);
50927 :
50928 : /*
50929 : * Run solvers
50930 : */
50931 0 : if( state->algokind==2 )
50932 : {
50933 0 : qpbleicoptimize(&state->a, &state->sparsea, state->akind, state->sparseaupper, state->absasum, state->absasum2, &state->b, &state->bndl, &state->bndu, &state->effectives, &state->xorigin, n, &state->ecleic, neq, nineq, &state->qpbleicsettingsuser, &state->qpbleicbuf, &state->qpbleicfirstcall, &state->xs, &state->repterminationtype, _state);
50934 0 : state->repinneriterationscount = state->qpbleicbuf.repinneriterationscount;
50935 0 : state->repouteriterationscount = state->qpbleicbuf.repouteriterationscount;
50936 0 : return;
50937 : }
50938 0 : if( state->algokind==4 )
50939 : {
50940 0 : qpdenseauloptimize(&state->a, &state->sparsea, state->akind, state->sparseaupper, &state->b, &state->bndl, &state->bndu, &state->effectives, &state->xorigin, n, &state->ecleic, neq, nineq, &state->dummysparse, 0, 0, !state->dbgskipconstraintnormalization, &state->qpdenseaulsettingsuser, &state->qpdenseaulbuf, &state->xs, &state->replagbc, &state->elaglc, &state->repterminationtype, _state);
50941 0 : for(i=0; i<=neq+nineq-1; i++)
50942 : {
50943 0 : state->replaglc.ptr.p_double[state->elagidx.ptr.p_int[i]] = state->replaglc.ptr.p_double[state->elagidx.ptr.p_int[i]]+state->elaglc.ptr.p_double[i]*state->elagmlt.ptr.p_double[i];
50944 : }
50945 0 : state->repinneriterationscount = state->qpdenseaulbuf.repinneriterationscount;
50946 0 : state->repouteriterationscount = state->qpdenseaulbuf.repouteriterationscount;
50947 0 : state->repncholesky = state->qpdenseaulbuf.repncholesky;
50948 0 : return;
50949 : }
50950 0 : ae_assert(ae_false, "MinQPOptimize: integrity check failed - unknown solver", _state);
50951 : }
50952 :
50953 : /*
50954 : * QuickQP solver
50955 : */
50956 0 : if( state->algokind==3 )
50957 : {
50958 0 : if( state->mdense+state->msparse>0 )
50959 : {
50960 0 : state->repterminationtype = -5;
50961 0 : return;
50962 : }
50963 0 : qqpoptimize(&state->a, &state->sparsea, &state->dummyr2, state->akind, state->sparseaupper, &state->b, &state->bndl, &state->bndu, &state->effectives, &state->xorigin, n, &state->qqpsettingsuser, &state->qqpbuf, &state->xs, &state->repterminationtype, _state);
50964 0 : state->repinneriterationscount = state->qqpbuf.repinneriterationscount;
50965 0 : state->repouteriterationscount = state->qqpbuf.repouteriterationscount;
50966 0 : state->repncholesky = state->qqpbuf.repncholesky;
50967 0 : return;
50968 : }
50969 :
50970 : /*
50971 : * QP-DENSE-IPM and QP-SPARSE-IPM solvers
50972 : */
50973 0 : if( state->algokind==5||state->algokind==6 )
50974 : {
50975 :
50976 : /*
50977 : * Prepare working versions of constraints; these versions may be modified
50978 : * when we detect that some bounds are irrelevant.
50979 : */
50980 0 : rcopyallocv(n, &state->bndl, &state->wrkbndl, _state);
50981 0 : rcopyallocv(n, &state->bndu, &state->wrkbndu, _state);
50982 0 : if( state->msparse>0 )
50983 : {
50984 0 : sparsecopybuf(&state->sparsec, &state->wrksparsec, _state);
50985 : }
50986 0 : if( state->mdense>0 )
50987 : {
50988 0 : rcopyallocm(state->mdense, n, &state->densec, &state->wrkdensec, _state);
50989 : }
50990 0 : rcopyallocv(m, &state->cl, &state->wrkcl, _state);
50991 0 : rcopyallocv(m, &state->cu, &state->wrkcu, _state);
50992 :
50993 : /*
50994 : * Solve
50995 : */
50996 0 : ae_assert(state->akind==0||state->akind==1, "MinQPOptimize: unexpected AKind", _state);
50997 0 : if( state->akind==0 )
50998 : {
50999 0 : cqmgeta(&state->a, &state->tmpr2, _state);
51000 : }
51001 0 : if( state->algokind==5 )
51002 : {
51003 0 : vipminitdense(&state->vsolver, &state->effectives, &state->xorigin, n, _state);
51004 : }
51005 0 : if( state->algokind==6 )
51006 : {
51007 0 : vipminitsparse(&state->vsolver, &state->effectives, &state->xorigin, n, _state);
51008 : }
51009 0 : vipmsetquadraticlinear(&state->vsolver, &state->tmpr2, &state->sparsea, state->akind, state->sparseaupper, &state->b, _state);
51010 0 : vipmsetconstraints(&state->vsolver, &state->wrkbndl, &state->wrkbndu, &state->wrksparsec, state->msparse, &state->wrkdensec, state->mdense, &state->wrkcl, &state->wrkcu, _state);
51011 0 : vipmsetcond(&state->vsolver, state->veps, state->veps, state->veps, _state);
51012 0 : vipmoptimize(&state->vsolver, ae_true, &state->xs, &state->replagbc, &state->replaglc, &state->repterminationtype, _state);
51013 0 : state->repinneriterationscount = state->vsolver.repiterationscount;
51014 0 : state->repouteriterationscount = state->repinneriterationscount;
51015 0 : state->repncholesky = state->vsolver.repncholesky;
51016 0 : return;
51017 : }
51018 :
51019 : /*
51020 : * Integrity check failed - unknown solver
51021 : */
51022 0 : ae_assert(ae_false, "MinQPOptimize: integrity check failed - unknown solver", _state);
51023 : }
51024 :
51025 :
51026 : /*************************************************************************
51027 : QP solver results
51028 :
51029 : INPUT PARAMETERS:
51030 : State - algorithm state
51031 :
51032 : OUTPUT PARAMETERS:
51033 : X - array[0..N-1], solution (on failure - the best point found
51034 : so far).
51035 : Rep - optimization report, contains:
51036 : * completion code in Rep.TerminationType (positive values
51037 : denote some kind of success, negative - failures)
51038 : * Lagrange multipliers - for QP solvers which support them
51039 : * other statistics
51040 : See comments on minqpreport structure for more information
51041 :
51042 : Following completion codes are returned in Rep.TerminationType:
51043 : * -9 failure of the automatic scale evaluation: one of the diagonal
51044 : elements of the quadratic term is non-positive. Specify variable
51045 : scales manually!
51046 : * -5 inappropriate solver was used:
51047 : * QuickQP solver for problem with general linear constraints
51048 : * -4 the function is unbounded from below even under constraints,
51049 : no meaningful minimum can be found.
51050 : * -3 inconsistent constraints (or, maybe, feasible point is too hard to
51051 : find).
51052 : * -2 IPM solver has difficulty finding primal/dual feasible point.
51053 : It is likely that the problem is either infeasible or unbounded,
51054 : but it is difficult to determine exact reason for termination.
51055 : X contains best point found so far.
51056 : * >0 success
51057 : * 7 stopping conditions are too stringent,
51058 : further improvement is impossible,
51059 : X contains best point found so far.
51060 :
51061 : -- ALGLIB --
51062 : Copyright 11.01.2011 by Bochkanov Sergey
51063 : *************************************************************************/
51064 0 : void minqpresults(minqpstate* state,
51065 : /* Real */ ae_vector* x,
51066 : minqpreport* rep,
51067 : ae_state *_state)
51068 : {
51069 :
51070 0 : ae_vector_clear(x);
51071 0 : _minqpreport_clear(rep);
51072 :
51073 0 : minqpresultsbuf(state, x, rep, _state);
51074 0 : }
51075 :
51076 :
51077 : /*************************************************************************
51078 : QP results
51079 :
51080 : Buffered implementation of MinQPResults() which uses pre-allocated buffer
51081 : to store X[]. If buffer size is too small, it resizes buffer. It is
51082 : intended to be used in the inner cycles of performance critical algorithms
51083 : where array reallocation penalty is too large to be ignored.
51084 :
51085 : -- ALGLIB --
51086 : Copyright 11.01.2011 by Bochkanov Sergey
51087 : *************************************************************************/
51088 0 : void minqpresultsbuf(minqpstate* state,
51089 : /* Real */ ae_vector* x,
51090 : minqpreport* rep,
51091 : ae_state *_state)
51092 : {
51093 : ae_int_t i;
51094 :
51095 :
51096 0 : ae_assert(state->xs.cnt>=state->n, "MinQPResultsBuf: integrity check failed", _state);
51097 0 : ae_assert(state->replagbc.cnt>=state->n, "MinQPResultsBuf: integrity check failed", _state);
51098 0 : ae_assert(state->replaglc.cnt>=state->mdense+state->msparse, "MinQPResultsBuf: integrity check failed", _state);
51099 0 : rvectorsetlengthatleast(x, state->n, _state);
51100 0 : rvectorsetlengthatleast(&rep->lagbc, state->n, _state);
51101 0 : rvectorsetlengthatleast(&rep->laglc, state->mdense+state->msparse, _state);
51102 0 : for(i=0; i<=state->n-1; i++)
51103 : {
51104 0 : x->ptr.p_double[i] = state->xs.ptr.p_double[i];
51105 0 : rep->lagbc.ptr.p_double[i] = state->replagbc.ptr.p_double[i];
51106 : }
51107 0 : for(i=0; i<=state->mdense+state->msparse-1; i++)
51108 : {
51109 0 : rep->laglc.ptr.p_double[i] = state->replaglc.ptr.p_double[i];
51110 : }
51111 0 : rep->inneriterationscount = state->repinneriterationscount;
51112 0 : rep->outeriterationscount = state->repouteriterationscount;
51113 0 : rep->nmv = state->repnmv;
51114 0 : rep->ncholesky = state->repncholesky;
51115 0 : rep->terminationtype = state->repterminationtype;
51116 0 : }
51117 :
51118 :
51119 : /*************************************************************************
51120 : Fast version of MinQPSetLinearTerm(), which doesn't check its arguments.
51121 : For internal use only.
51122 :
51123 : -- ALGLIB --
51124 : Copyright 11.01.2011 by Bochkanov Sergey
51125 : *************************************************************************/
51126 0 : void minqpsetlineartermfast(minqpstate* state,
51127 : /* Real */ ae_vector* b,
51128 : ae_state *_state)
51129 : {
51130 :
51131 :
51132 0 : ae_v_move(&state->b.ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,state->n-1));
51133 0 : }
51134 :
51135 :
51136 : /*************************************************************************
51137 : Fast version of MinQPSetQuadraticTerm(), which doesn't check its arguments.
51138 :
51139 : It accepts additional parameter - shift S, which allows to "shift" matrix
51140 : A by adding s*I to A. S must be positive (although it is not checked).
51141 :
51142 : For internal use only.
51143 :
51144 : -- ALGLIB --
51145 : Copyright 11.01.2011 by Bochkanov Sergey
51146 : *************************************************************************/
51147 0 : void minqpsetquadratictermfast(minqpstate* state,
51148 : /* Real */ ae_matrix* a,
51149 : ae_bool isupper,
51150 : double s,
51151 : ae_state *_state)
51152 : {
51153 : ae_int_t i;
51154 : ae_int_t j;
51155 : ae_int_t n;
51156 : double v;
51157 : ae_int_t j0;
51158 : ae_int_t j1;
51159 :
51160 :
51161 0 : n = state->n;
51162 0 : state->akind = 0;
51163 0 : cqmseta(&state->a, a, isupper, 1.0, _state);
51164 0 : if( ae_fp_greater(s,(double)(0)) )
51165 : {
51166 0 : rvectorsetlengthatleast(&state->tmp0, n, _state);
51167 0 : for(i=0; i<=n-1; i++)
51168 : {
51169 0 : state->tmp0.ptr.p_double[i] = a->ptr.pp_double[i][i]+s;
51170 : }
51171 0 : cqmrewritedensediagonal(&state->a, &state->tmp0, _state);
51172 : }
51173 :
51174 : /*
51175 : * Estimate norm of A
51176 : * (it will be used later in the quadratic penalty function)
51177 : */
51178 0 : state->absamax = (double)(0);
51179 0 : state->absasum = (double)(0);
51180 0 : state->absasum2 = (double)(0);
51181 0 : for(i=0; i<=n-1; i++)
51182 : {
51183 0 : if( isupper )
51184 : {
51185 0 : j0 = i;
51186 0 : j1 = n-1;
51187 : }
51188 : else
51189 : {
51190 0 : j0 = 0;
51191 0 : j1 = i;
51192 : }
51193 0 : for(j=j0; j<=j1; j++)
51194 : {
51195 0 : v = ae_fabs(a->ptr.pp_double[i][j], _state);
51196 0 : state->absamax = ae_maxreal(state->absamax, v, _state);
51197 0 : state->absasum = state->absasum+v;
51198 0 : state->absasum2 = state->absasum2+v*v;
51199 : }
51200 : }
51201 0 : }
51202 :
51203 :
51204 : /*************************************************************************
51205 : Internal function which allows to rewrite diagonal of quadratic term.
51206 : For internal use only.
51207 :
51208 : This function can be used only when you have dense A and already made
51209 : MinQPSetQuadraticTerm(Fast) call.
51210 :
51211 : -- ALGLIB --
51212 : Copyright 16.01.2011 by Bochkanov Sergey
51213 : *************************************************************************/
51214 0 : void minqprewritediagonal(minqpstate* state,
51215 : /* Real */ ae_vector* s,
51216 : ae_state *_state)
51217 : {
51218 :
51219 :
51220 0 : cqmrewritedensediagonal(&state->a, s, _state);
51221 0 : }
51222 :
51223 :
51224 : /*************************************************************************
51225 : Fast version of MinQPSetStartingPoint(), which doesn't check its arguments.
51226 : For internal use only.
51227 :
51228 : -- ALGLIB --
51229 : Copyright 11.01.2011 by Bochkanov Sergey
51230 : *************************************************************************/
51231 0 : void minqpsetstartingpointfast(minqpstate* state,
51232 : /* Real */ ae_vector* x,
51233 : ae_state *_state)
51234 : {
51235 : ae_int_t n;
51236 :
51237 :
51238 0 : n = state->n;
51239 0 : ae_v_move(&state->startx.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
51240 0 : state->havex = ae_true;
51241 0 : }
51242 :
51243 :
51244 : /*************************************************************************
51245 : Fast version of MinQPSetOrigin(), which doesn't check its arguments.
51246 : For internal use only.
51247 :
51248 : -- ALGLIB --
51249 : Copyright 11.01.2011 by Bochkanov Sergey
51250 : *************************************************************************/
51251 0 : void minqpsetoriginfast(minqpstate* state,
51252 : /* Real */ ae_vector* xorigin,
51253 : ae_state *_state)
51254 : {
51255 : ae_int_t n;
51256 :
51257 :
51258 0 : n = state->n;
51259 0 : ae_v_move(&state->xorigin.ptr.p_double[0], 1, &xorigin->ptr.p_double[0], 1, ae_v_len(0,n-1));
51260 0 : }
51261 :
51262 :
51263 0 : void _minqpstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
51264 : {
51265 0 : minqpstate *p = (minqpstate*)_p;
51266 0 : ae_touch_ptr((void*)p);
51267 0 : _qqpsettings_init(&p->qqpsettingsuser, _state, make_automatic);
51268 0 : _qpbleicsettings_init(&p->qpbleicsettingsuser, _state, make_automatic);
51269 0 : _qpdenseaulsettings_init(&p->qpdenseaulsettingsuser, _state, make_automatic);
51270 0 : _convexquadraticmodel_init(&p->a, _state, make_automatic);
51271 0 : _sparsematrix_init(&p->sparsea, _state, make_automatic);
51272 0 : ae_vector_init(&p->b, 0, DT_REAL, _state, make_automatic);
51273 0 : ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic);
51274 0 : ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic);
51275 0 : ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic);
51276 0 : ae_vector_init(&p->havebndl, 0, DT_BOOL, _state, make_automatic);
51277 0 : ae_vector_init(&p->havebndu, 0, DT_BOOL, _state, make_automatic);
51278 0 : ae_vector_init(&p->xorigin, 0, DT_REAL, _state, make_automatic);
51279 0 : ae_vector_init(&p->startx, 0, DT_REAL, _state, make_automatic);
51280 0 : ae_matrix_init(&p->densec, 0, 0, DT_REAL, _state, make_automatic);
51281 0 : _sparsematrix_init(&p->sparsec, _state, make_automatic);
51282 0 : ae_vector_init(&p->cl, 0, DT_REAL, _state, make_automatic);
51283 0 : ae_vector_init(&p->cu, 0, DT_REAL, _state, make_automatic);
51284 0 : ae_vector_init(&p->xs, 0, DT_REAL, _state, make_automatic);
51285 0 : ae_vector_init(&p->replagbc, 0, DT_REAL, _state, make_automatic);
51286 0 : ae_vector_init(&p->replaglc, 0, DT_REAL, _state, make_automatic);
51287 0 : ae_vector_init(&p->effectives, 0, DT_REAL, _state, make_automatic);
51288 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
51289 0 : ae_matrix_init(&p->ecleic, 0, 0, DT_REAL, _state, make_automatic);
51290 0 : ae_vector_init(&p->elaglc, 0, DT_REAL, _state, make_automatic);
51291 0 : ae_vector_init(&p->elagmlt, 0, DT_REAL, _state, make_automatic);
51292 0 : ae_vector_init(&p->elagidx, 0, DT_INT, _state, make_automatic);
51293 0 : ae_matrix_init(&p->dummyr2, 0, 0, DT_REAL, _state, make_automatic);
51294 0 : _sparsematrix_init(&p->dummysparse, _state, make_automatic);
51295 0 : ae_matrix_init(&p->tmpr2, 0, 0, DT_REAL, _state, make_automatic);
51296 0 : ae_vector_init(&p->wrkbndl, 0, DT_REAL, _state, make_automatic);
51297 0 : ae_vector_init(&p->wrkbndu, 0, DT_REAL, _state, make_automatic);
51298 0 : ae_vector_init(&p->wrkcl, 0, DT_REAL, _state, make_automatic);
51299 0 : ae_vector_init(&p->wrkcu, 0, DT_REAL, _state, make_automatic);
51300 0 : ae_matrix_init(&p->wrkdensec, 0, 0, DT_REAL, _state, make_automatic);
51301 0 : _sparsematrix_init(&p->wrksparsec, _state, make_automatic);
51302 0 : _qpbleicbuffers_init(&p->qpbleicbuf, _state, make_automatic);
51303 0 : _qqpbuffers_init(&p->qqpbuf, _state, make_automatic);
51304 0 : _qpdenseaulbuffers_init(&p->qpdenseaulbuf, _state, make_automatic);
51305 0 : _vipmstate_init(&p->vsolver, _state, make_automatic);
51306 0 : }
51307 :
51308 :
51309 0 : void _minqpstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
51310 : {
51311 0 : minqpstate *dst = (minqpstate*)_dst;
51312 0 : minqpstate *src = (minqpstate*)_src;
51313 0 : dst->n = src->n;
51314 0 : _qqpsettings_init_copy(&dst->qqpsettingsuser, &src->qqpsettingsuser, _state, make_automatic);
51315 0 : _qpbleicsettings_init_copy(&dst->qpbleicsettingsuser, &src->qpbleicsettingsuser, _state, make_automatic);
51316 0 : _qpdenseaulsettings_init_copy(&dst->qpdenseaulsettingsuser, &src->qpdenseaulsettingsuser, _state, make_automatic);
51317 0 : dst->veps = src->veps;
51318 0 : dst->dbgskipconstraintnormalization = src->dbgskipconstraintnormalization;
51319 0 : dst->algokind = src->algokind;
51320 0 : dst->akind = src->akind;
51321 0 : _convexquadraticmodel_init_copy(&dst->a, &src->a, _state, make_automatic);
51322 0 : _sparsematrix_init_copy(&dst->sparsea, &src->sparsea, _state, make_automatic);
51323 0 : dst->sparseaupper = src->sparseaupper;
51324 0 : dst->absamax = src->absamax;
51325 0 : dst->absasum = src->absasum;
51326 0 : dst->absasum2 = src->absasum2;
51327 0 : ae_vector_init_copy(&dst->b, &src->b, _state, make_automatic);
51328 0 : ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic);
51329 0 : ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic);
51330 0 : dst->stype = src->stype;
51331 0 : ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic);
51332 0 : ae_vector_init_copy(&dst->havebndl, &src->havebndl, _state, make_automatic);
51333 0 : ae_vector_init_copy(&dst->havebndu, &src->havebndu, _state, make_automatic);
51334 0 : ae_vector_init_copy(&dst->xorigin, &src->xorigin, _state, make_automatic);
51335 0 : ae_vector_init_copy(&dst->startx, &src->startx, _state, make_automatic);
51336 0 : dst->havex = src->havex;
51337 0 : ae_matrix_init_copy(&dst->densec, &src->densec, _state, make_automatic);
51338 0 : _sparsematrix_init_copy(&dst->sparsec, &src->sparsec, _state, make_automatic);
51339 0 : ae_vector_init_copy(&dst->cl, &src->cl, _state, make_automatic);
51340 0 : ae_vector_init_copy(&dst->cu, &src->cu, _state, make_automatic);
51341 0 : dst->mdense = src->mdense;
51342 0 : dst->msparse = src->msparse;
51343 0 : ae_vector_init_copy(&dst->xs, &src->xs, _state, make_automatic);
51344 0 : dst->repinneriterationscount = src->repinneriterationscount;
51345 0 : dst->repouteriterationscount = src->repouteriterationscount;
51346 0 : dst->repncholesky = src->repncholesky;
51347 0 : dst->repnmv = src->repnmv;
51348 0 : dst->repterminationtype = src->repterminationtype;
51349 0 : ae_vector_init_copy(&dst->replagbc, &src->replagbc, _state, make_automatic);
51350 0 : ae_vector_init_copy(&dst->replaglc, &src->replaglc, _state, make_automatic);
51351 0 : ae_vector_init_copy(&dst->effectives, &src->effectives, _state, make_automatic);
51352 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
51353 0 : ae_matrix_init_copy(&dst->ecleic, &src->ecleic, _state, make_automatic);
51354 0 : ae_vector_init_copy(&dst->elaglc, &src->elaglc, _state, make_automatic);
51355 0 : ae_vector_init_copy(&dst->elagmlt, &src->elagmlt, _state, make_automatic);
51356 0 : ae_vector_init_copy(&dst->elagidx, &src->elagidx, _state, make_automatic);
51357 0 : ae_matrix_init_copy(&dst->dummyr2, &src->dummyr2, _state, make_automatic);
51358 0 : _sparsematrix_init_copy(&dst->dummysparse, &src->dummysparse, _state, make_automatic);
51359 0 : ae_matrix_init_copy(&dst->tmpr2, &src->tmpr2, _state, make_automatic);
51360 0 : ae_vector_init_copy(&dst->wrkbndl, &src->wrkbndl, _state, make_automatic);
51361 0 : ae_vector_init_copy(&dst->wrkbndu, &src->wrkbndu, _state, make_automatic);
51362 0 : ae_vector_init_copy(&dst->wrkcl, &src->wrkcl, _state, make_automatic);
51363 0 : ae_vector_init_copy(&dst->wrkcu, &src->wrkcu, _state, make_automatic);
51364 0 : ae_matrix_init_copy(&dst->wrkdensec, &src->wrkdensec, _state, make_automatic);
51365 0 : _sparsematrix_init_copy(&dst->wrksparsec, &src->wrksparsec, _state, make_automatic);
51366 0 : dst->qpbleicfirstcall = src->qpbleicfirstcall;
51367 0 : _qpbleicbuffers_init_copy(&dst->qpbleicbuf, &src->qpbleicbuf, _state, make_automatic);
51368 0 : _qqpbuffers_init_copy(&dst->qqpbuf, &src->qqpbuf, _state, make_automatic);
51369 0 : _qpdenseaulbuffers_init_copy(&dst->qpdenseaulbuf, &src->qpdenseaulbuf, _state, make_automatic);
51370 0 : _vipmstate_init_copy(&dst->vsolver, &src->vsolver, _state, make_automatic);
51371 0 : }
51372 :
51373 :
51374 0 : void _minqpstate_clear(void* _p)
51375 : {
51376 0 : minqpstate *p = (minqpstate*)_p;
51377 0 : ae_touch_ptr((void*)p);
51378 0 : _qqpsettings_clear(&p->qqpsettingsuser);
51379 0 : _qpbleicsettings_clear(&p->qpbleicsettingsuser);
51380 0 : _qpdenseaulsettings_clear(&p->qpdenseaulsettingsuser);
51381 0 : _convexquadraticmodel_clear(&p->a);
51382 0 : _sparsematrix_clear(&p->sparsea);
51383 0 : ae_vector_clear(&p->b);
51384 0 : ae_vector_clear(&p->bndl);
51385 0 : ae_vector_clear(&p->bndu);
51386 0 : ae_vector_clear(&p->s);
51387 0 : ae_vector_clear(&p->havebndl);
51388 0 : ae_vector_clear(&p->havebndu);
51389 0 : ae_vector_clear(&p->xorigin);
51390 0 : ae_vector_clear(&p->startx);
51391 0 : ae_matrix_clear(&p->densec);
51392 0 : _sparsematrix_clear(&p->sparsec);
51393 0 : ae_vector_clear(&p->cl);
51394 0 : ae_vector_clear(&p->cu);
51395 0 : ae_vector_clear(&p->xs);
51396 0 : ae_vector_clear(&p->replagbc);
51397 0 : ae_vector_clear(&p->replaglc);
51398 0 : ae_vector_clear(&p->effectives);
51399 0 : ae_vector_clear(&p->tmp0);
51400 0 : ae_matrix_clear(&p->ecleic);
51401 0 : ae_vector_clear(&p->elaglc);
51402 0 : ae_vector_clear(&p->elagmlt);
51403 0 : ae_vector_clear(&p->elagidx);
51404 0 : ae_matrix_clear(&p->dummyr2);
51405 0 : _sparsematrix_clear(&p->dummysparse);
51406 0 : ae_matrix_clear(&p->tmpr2);
51407 0 : ae_vector_clear(&p->wrkbndl);
51408 0 : ae_vector_clear(&p->wrkbndu);
51409 0 : ae_vector_clear(&p->wrkcl);
51410 0 : ae_vector_clear(&p->wrkcu);
51411 0 : ae_matrix_clear(&p->wrkdensec);
51412 0 : _sparsematrix_clear(&p->wrksparsec);
51413 0 : _qpbleicbuffers_clear(&p->qpbleicbuf);
51414 0 : _qqpbuffers_clear(&p->qqpbuf);
51415 0 : _qpdenseaulbuffers_clear(&p->qpdenseaulbuf);
51416 0 : _vipmstate_clear(&p->vsolver);
51417 0 : }
51418 :
51419 :
51420 0 : void _minqpstate_destroy(void* _p)
51421 : {
51422 0 : minqpstate *p = (minqpstate*)_p;
51423 0 : ae_touch_ptr((void*)p);
51424 0 : _qqpsettings_destroy(&p->qqpsettingsuser);
51425 0 : _qpbleicsettings_destroy(&p->qpbleicsettingsuser);
51426 0 : _qpdenseaulsettings_destroy(&p->qpdenseaulsettingsuser);
51427 0 : _convexquadraticmodel_destroy(&p->a);
51428 0 : _sparsematrix_destroy(&p->sparsea);
51429 0 : ae_vector_destroy(&p->b);
51430 0 : ae_vector_destroy(&p->bndl);
51431 0 : ae_vector_destroy(&p->bndu);
51432 0 : ae_vector_destroy(&p->s);
51433 0 : ae_vector_destroy(&p->havebndl);
51434 0 : ae_vector_destroy(&p->havebndu);
51435 0 : ae_vector_destroy(&p->xorigin);
51436 0 : ae_vector_destroy(&p->startx);
51437 0 : ae_matrix_destroy(&p->densec);
51438 0 : _sparsematrix_destroy(&p->sparsec);
51439 0 : ae_vector_destroy(&p->cl);
51440 0 : ae_vector_destroy(&p->cu);
51441 0 : ae_vector_destroy(&p->xs);
51442 0 : ae_vector_destroy(&p->replagbc);
51443 0 : ae_vector_destroy(&p->replaglc);
51444 0 : ae_vector_destroy(&p->effectives);
51445 0 : ae_vector_destroy(&p->tmp0);
51446 0 : ae_matrix_destroy(&p->ecleic);
51447 0 : ae_vector_destroy(&p->elaglc);
51448 0 : ae_vector_destroy(&p->elagmlt);
51449 0 : ae_vector_destroy(&p->elagidx);
51450 0 : ae_matrix_destroy(&p->dummyr2);
51451 0 : _sparsematrix_destroy(&p->dummysparse);
51452 0 : ae_matrix_destroy(&p->tmpr2);
51453 0 : ae_vector_destroy(&p->wrkbndl);
51454 0 : ae_vector_destroy(&p->wrkbndu);
51455 0 : ae_vector_destroy(&p->wrkcl);
51456 0 : ae_vector_destroy(&p->wrkcu);
51457 0 : ae_matrix_destroy(&p->wrkdensec);
51458 0 : _sparsematrix_destroy(&p->wrksparsec);
51459 0 : _qpbleicbuffers_destroy(&p->qpbleicbuf);
51460 0 : _qqpbuffers_destroy(&p->qqpbuf);
51461 0 : _qpdenseaulbuffers_destroy(&p->qpdenseaulbuf);
51462 0 : _vipmstate_destroy(&p->vsolver);
51463 0 : }
51464 :
51465 :
51466 0 : void _minqpreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
51467 : {
51468 0 : minqpreport *p = (minqpreport*)_p;
51469 0 : ae_touch_ptr((void*)p);
51470 0 : ae_vector_init(&p->lagbc, 0, DT_REAL, _state, make_automatic);
51471 0 : ae_vector_init(&p->laglc, 0, DT_REAL, _state, make_automatic);
51472 0 : }
51473 :
51474 :
51475 0 : void _minqpreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
51476 : {
51477 0 : minqpreport *dst = (minqpreport*)_dst;
51478 0 : minqpreport *src = (minqpreport*)_src;
51479 0 : dst->inneriterationscount = src->inneriterationscount;
51480 0 : dst->outeriterationscount = src->outeriterationscount;
51481 0 : dst->nmv = src->nmv;
51482 0 : dst->ncholesky = src->ncholesky;
51483 0 : dst->terminationtype = src->terminationtype;
51484 0 : ae_vector_init_copy(&dst->lagbc, &src->lagbc, _state, make_automatic);
51485 0 : ae_vector_init_copy(&dst->laglc, &src->laglc, _state, make_automatic);
51486 0 : }
51487 :
51488 :
51489 0 : void _minqpreport_clear(void* _p)
51490 : {
51491 0 : minqpreport *p = (minqpreport*)_p;
51492 0 : ae_touch_ptr((void*)p);
51493 0 : ae_vector_clear(&p->lagbc);
51494 0 : ae_vector_clear(&p->laglc);
51495 0 : }
51496 :
51497 :
51498 0 : void _minqpreport_destroy(void* _p)
51499 : {
51500 0 : minqpreport *p = (minqpreport*)_p;
51501 0 : ae_touch_ptr((void*)p);
51502 0 : ae_vector_destroy(&p->lagbc);
51503 0 : ae_vector_destroy(&p->laglc);
51504 0 : }
51505 :
51506 :
51507 : #endif
51508 : #if defined(AE_COMPILE_LPQPPRESOLVE) || !defined(AE_PARTIAL_BUILD)
51509 :
51510 :
51511 : /*************************************************************************
51512 : No presolve, just user-supplied scaling + constraint and cost vector
51513 : normalization.
51514 :
51515 : INPUT PARAMETERS:
51516 : S - array[N], user-supplied scale vector, S[I]>0
51517 : C - array[N], costs
51518 : BndL - array[N], lower bounds (may contain -INF)
51519 : BndU - array[N], upper bounds (may contain +INF)
51520 : N - variable count, N>0
51521 : SparseA - matrix[K,N], sparse constraints
51522 : AL - array[K], lower constraint bounds (may contain -INF)
51523 : AU - array[K], upper constraint bounds (may contain +INF)
51524 : K - constraint count, K>=0
51525 : Info - presolve info structure; temporaries allocated during
51526 : previous calls may be reused by this function.
51527 :
51528 : OUTPUT PARAMETERS:
51529 : Info - contains transformed C, BndL, bndU, SparseA, AL, AU
51530 : and information necessary to perform backward
51531 : transformation.
51532 : Following fields can be acessed:
51533 : * Info.NewN>0 for transformed problem size
51534 : * Info.NewM>=0 for transformed constraint count
51535 : * always: Info.C, Info.BndL, Info.BndU - array[NewN]
51536 : * for Info.NewM>0: Info.SparseA, Info.AL, Info.AU
51537 :
51538 : NOTE: this routine does not reallocate arrays if NNew<=NOld and/or KNew<=KOld.
51539 :
51540 : -- ALGLIB --
51541 : Copyright 01.07.2020 by Bochkanov Sergey
51542 : *************************************************************************/
51543 0 : void presolvenonescaleuser(/* Real */ ae_vector* s,
51544 : /* Real */ ae_vector* c,
51545 : /* Real */ ae_vector* bndl,
51546 : /* Real */ ae_vector* bndu,
51547 : ae_int_t n,
51548 : sparsematrix* sparsea,
51549 : /* Real */ ae_vector* al,
51550 : /* Real */ ae_vector* au,
51551 : ae_int_t k,
51552 : presolveinfo* info,
51553 : ae_state *_state)
51554 : {
51555 : ae_int_t i;
51556 : ae_int_t j;
51557 : ae_int_t j0;
51558 : ae_int_t j1;
51559 : double v;
51560 : double avgln;
51561 :
51562 :
51563 :
51564 : /*
51565 : * Integrity checks
51566 : */
51567 0 : ae_assert(bndl->cnt>=n, "PresolveNoneScaleUser: Length(BndL)<N", _state);
51568 0 : ae_assert(bndu->cnt>=n, "PresolveNoneScaleUser: Length(BndU)<N", _state);
51569 0 : ae_assert(s->cnt>=n, "PresolveNoneScaleUser: Length(S)<N", _state);
51570 0 : ae_assert(isfinitevector(s, n, _state), "PresolveNoneScaleUser: S contains infinite or NaN elements", _state);
51571 0 : ae_assert(c->cnt>=n, "PresolveNoneScaleUser: Length(C)<N", _state);
51572 0 : ae_assert(isfinitevector(c, n, _state), "PresolveNoneScaleUser: C contains infinite or NaN elements", _state);
51573 0 : ae_assert(k>=0, "PresolveNoneScaleUser: K<0", _state);
51574 0 : ae_assert(k==0||sparseiscrs(sparsea, _state), "PresolveNoneScaleUser: A is not CRS", _state);
51575 0 : ae_assert(k==0||sparsea->m==k, "PresolveNoneScaleUser: rows(A)<>K", _state);
51576 0 : ae_assert(k==0||sparsea->n==n, "PresolveNoneScaleUser: cols(A)<>N", _state);
51577 :
51578 : /*
51579 : * Reallocate storage
51580 : */
51581 0 : rvectorgrowto(&info->rawbndl, n, _state);
51582 0 : rvectorgrowto(&info->rawbndu, n, _state);
51583 0 : rvectorgrowto(&info->colscales, n, _state);
51584 0 : rvectorgrowto(&info->rowscales, k, _state);
51585 :
51586 : /*
51587 : * Save original problem formulation
51588 : */
51589 0 : info->newn = n;
51590 0 : info->oldn = n;
51591 0 : info->newm = k;
51592 0 : info->oldm = k;
51593 0 : for(i=0; i<=n-1; i++)
51594 : {
51595 0 : ae_assert(s->ptr.p_double[i]>0, "PresolveNoneScaleUser: S<=0", _state);
51596 0 : ae_assert(ae_isfinite(bndl->ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "PresolveNoneScaleUser: BndL contains NAN or +INF", _state);
51597 0 : ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "PresolveNoneScaleUser: BndU contains NAN or -INF", _state);
51598 0 : info->colscales.ptr.p_double[i] = s->ptr.p_double[i];
51599 0 : info->rawbndl.ptr.p_double[i] = bndl->ptr.p_double[i];
51600 0 : info->rawbndu.ptr.p_double[i] = bndu->ptr.p_double[i];
51601 : }
51602 :
51603 : /*
51604 : * Scale cost and box constraints
51605 : */
51606 0 : rvectorsetlengthatleast(&info->c, n, _state);
51607 0 : rvectorsetlengthatleast(&info->bndl, n, _state);
51608 0 : rvectorsetlengthatleast(&info->bndu, n, _state);
51609 0 : for(i=0; i<=n-1; i++)
51610 : {
51611 0 : info->c.ptr.p_double[i] = c->ptr.p_double[i]*s->ptr.p_double[i];
51612 0 : info->bndl.ptr.p_double[i] = bndl->ptr.p_double[i]/s->ptr.p_double[i];
51613 0 : info->bndu.ptr.p_double[i] = bndu->ptr.p_double[i]/s->ptr.p_double[i];
51614 : }
51615 0 : avgln = (double)(0);
51616 0 : for(i=0; i<=n-1; i++)
51617 : {
51618 0 : avgln = avgln+ae_log(1+ae_fabs(info->c.ptr.p_double[i], _state), _state);
51619 : }
51620 0 : info->costscale = ae_exp(avgln/n, _state);
51621 0 : rmulv(n, 1/info->costscale, &info->c, _state);
51622 :
51623 : /*
51624 : * Quick exit if no linear constraints is present
51625 : */
51626 0 : if( k==0 )
51627 : {
51628 0 : return;
51629 : }
51630 :
51631 : /*
51632 : * Scale constraint matrix
51633 : */
51634 0 : rcopyallocv(k, al, &info->al, _state);
51635 0 : rcopyallocv(k, au, &info->au, _state);
51636 0 : sparsecopybuf(sparsea, &info->sparsea, _state);
51637 0 : for(i=0; i<=k-1; i++)
51638 : {
51639 0 : ae_assert(ae_isfinite(info->al.ptr.p_double[i], _state)||ae_isneginf(info->al.ptr.p_double[i], _state), "PresolveNoneScaleUser: AL contains NAN or +INF", _state);
51640 0 : ae_assert(ae_isfinite(info->au.ptr.p_double[i], _state)||ae_isposinf(info->au.ptr.p_double[i], _state), "PresolveNoneScaleUser: AU contains NAN or -INF", _state);
51641 0 : info->rowscales.ptr.p_double[i] = (double)(0);
51642 0 : j0 = info->sparsea.ridx.ptr.p_int[i];
51643 0 : j1 = info->sparsea.ridx.ptr.p_int[i+1]-1;
51644 0 : for(j=j0; j<=j1; j++)
51645 : {
51646 0 : v = s->ptr.p_double[info->sparsea.idx.ptr.p_int[j]]*info->sparsea.vals.ptr.p_double[j];
51647 0 : info->sparsea.vals.ptr.p_double[j] = v;
51648 0 : info->rowscales.ptr.p_double[i] = ae_maxreal(info->rowscales.ptr.p_double[i], v, _state);
51649 : }
51650 0 : info->rowscales.ptr.p_double[i] = ae_maxreal(info->rowscales.ptr.p_double[i], 1.0, _state);
51651 0 : v = 1/info->rowscales.ptr.p_double[i];
51652 0 : for(j=j0; j<=j1; j++)
51653 : {
51654 0 : info->sparsea.vals.ptr.p_double[j] = v*info->sparsea.vals.ptr.p_double[j];
51655 : }
51656 0 : info->al.ptr.p_double[i] = info->al.ptr.p_double[i]*v;
51657 0 : info->au.ptr.p_double[i] = info->au.ptr.p_double[i]*v;
51658 : }
51659 : }
51660 :
51661 :
51662 : /*************************************************************************
51663 : Backward transformation which extracts original solution from that of the
51664 : converted problem.
51665 :
51666 : Below NNew/KNew correspond to transformed problem size (as returned by the
51667 : presolve routine) and NOld/KOld correspond to original problem size (as
51668 : specified by caller). We expect that caller knows these sizes, so this
51669 : routine does not report them.
51670 :
51671 : INPUT PARAMETERS:
51672 : Info - presolve info structure
51673 : X - array[NNew], transformed solution (primal variables)
51674 : Stats - array[NNew+MNew], transformed constraint status (negative -
51675 : at lower bound, positive - at upper bound, zero -
51676 : inactive).
51677 : LagBC - array[NNew], transformed Lagrange multipliers
51678 : LagLC - array[KNew], transformed Lagrange multipliers
51679 :
51680 : OUTPUT PARAMETERS:
51681 : X - array[NOld], original solution (primal variables)
51682 : Stats - array[NOld+MOld], original constraint status
51683 : LagBC - array[NOld], Lagrange multipliers
51684 : LagLC - array[KOld], Lagrange multipliers
51685 :
51686 : NOTE: this routine does not reallocate arrays if NOld<=NNew and/or KOld<=KNew.
51687 :
51688 : -- ALGLIB --
51689 : Copyright 01.07.2020 by Bochkanov Sergey
51690 : *************************************************************************/
51691 0 : void presolvebwd(presolveinfo* info,
51692 : /* Real */ ae_vector* x,
51693 : /* Integer */ ae_vector* stats,
51694 : /* Real */ ae_vector* lagbc,
51695 : /* Real */ ae_vector* laglc,
51696 : ae_state *_state)
51697 : {
51698 : ae_int_t n;
51699 : ae_int_t m;
51700 : ae_int_t i;
51701 :
51702 :
51703 0 : ae_assert(info->oldn==info->newn, "PresolveBwd: integrity check failed", _state);
51704 0 : ae_assert(info->oldm==info->newm, "PresolveBwd: integrity check failed", _state);
51705 0 : n = info->oldn;
51706 0 : m = info->oldm;
51707 0 : for(i=0; i<=n-1; i++)
51708 : {
51709 0 : if( stats->ptr.p_int[i]<0 )
51710 : {
51711 0 : x->ptr.p_double[i] = info->rawbndl.ptr.p_double[i];
51712 0 : continue;
51713 : }
51714 0 : if( stats->ptr.p_int[i]>0 )
51715 : {
51716 0 : x->ptr.p_double[i] = info->rawbndu.ptr.p_double[i];
51717 0 : continue;
51718 : }
51719 0 : x->ptr.p_double[i] = x->ptr.p_double[i]*info->colscales.ptr.p_double[i];
51720 0 : if( ae_isfinite(info->rawbndl.ptr.p_double[i], _state) )
51721 : {
51722 0 : x->ptr.p_double[i] = ae_maxreal(x->ptr.p_double[i], info->rawbndl.ptr.p_double[i], _state);
51723 : }
51724 0 : if( ae_isfinite(info->rawbndu.ptr.p_double[i], _state) )
51725 : {
51726 0 : x->ptr.p_double[i] = ae_minreal(x->ptr.p_double[i], info->rawbndu.ptr.p_double[i], _state);
51727 : }
51728 : }
51729 0 : for(i=0; i<=n-1; i++)
51730 : {
51731 0 : lagbc->ptr.p_double[i] = lagbc->ptr.p_double[i]*info->costscale/info->colscales.ptr.p_double[i];
51732 : }
51733 0 : for(i=0; i<=m-1; i++)
51734 : {
51735 0 : laglc->ptr.p_double[i] = laglc->ptr.p_double[i]*info->costscale/info->rowscales.ptr.p_double[i];
51736 : }
51737 0 : }
51738 :
51739 :
51740 0 : void _presolveinfo_init(void* _p, ae_state *_state, ae_bool make_automatic)
51741 : {
51742 0 : presolveinfo *p = (presolveinfo*)_p;
51743 0 : ae_touch_ptr((void*)p);
51744 0 : ae_vector_init(&p->rawbndl, 0, DT_REAL, _state, make_automatic);
51745 0 : ae_vector_init(&p->rawbndu, 0, DT_REAL, _state, make_automatic);
51746 0 : ae_vector_init(&p->colscales, 0, DT_REAL, _state, make_automatic);
51747 0 : ae_vector_init(&p->rowscales, 0, DT_REAL, _state, make_automatic);
51748 0 : ae_vector_init(&p->c, 0, DT_REAL, _state, make_automatic);
51749 0 : ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic);
51750 0 : ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic);
51751 0 : _sparsematrix_init(&p->sparsea, _state, make_automatic);
51752 0 : ae_vector_init(&p->al, 0, DT_REAL, _state, make_automatic);
51753 0 : ae_vector_init(&p->au, 0, DT_REAL, _state, make_automatic);
51754 0 : }
51755 :
51756 :
51757 0 : void _presolveinfo_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
51758 : {
51759 0 : presolveinfo *dst = (presolveinfo*)_dst;
51760 0 : presolveinfo *src = (presolveinfo*)_src;
51761 0 : dst->newn = src->newn;
51762 0 : dst->oldn = src->oldn;
51763 0 : dst->newm = src->newm;
51764 0 : dst->oldm = src->oldm;
51765 0 : ae_vector_init_copy(&dst->rawbndl, &src->rawbndl, _state, make_automatic);
51766 0 : ae_vector_init_copy(&dst->rawbndu, &src->rawbndu, _state, make_automatic);
51767 0 : ae_vector_init_copy(&dst->colscales, &src->colscales, _state, make_automatic);
51768 0 : ae_vector_init_copy(&dst->rowscales, &src->rowscales, _state, make_automatic);
51769 0 : dst->costscale = src->costscale;
51770 0 : ae_vector_init_copy(&dst->c, &src->c, _state, make_automatic);
51771 0 : ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic);
51772 0 : ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic);
51773 0 : _sparsematrix_init_copy(&dst->sparsea, &src->sparsea, _state, make_automatic);
51774 0 : ae_vector_init_copy(&dst->al, &src->al, _state, make_automatic);
51775 0 : ae_vector_init_copy(&dst->au, &src->au, _state, make_automatic);
51776 0 : }
51777 :
51778 :
51779 0 : void _presolveinfo_clear(void* _p)
51780 : {
51781 0 : presolveinfo *p = (presolveinfo*)_p;
51782 0 : ae_touch_ptr((void*)p);
51783 0 : ae_vector_clear(&p->rawbndl);
51784 0 : ae_vector_clear(&p->rawbndu);
51785 0 : ae_vector_clear(&p->colscales);
51786 0 : ae_vector_clear(&p->rowscales);
51787 0 : ae_vector_clear(&p->c);
51788 0 : ae_vector_clear(&p->bndl);
51789 0 : ae_vector_clear(&p->bndu);
51790 0 : _sparsematrix_clear(&p->sparsea);
51791 0 : ae_vector_clear(&p->al);
51792 0 : ae_vector_clear(&p->au);
51793 0 : }
51794 :
51795 :
51796 0 : void _presolveinfo_destroy(void* _p)
51797 : {
51798 0 : presolveinfo *p = (presolveinfo*)_p;
51799 0 : ae_touch_ptr((void*)p);
51800 0 : ae_vector_destroy(&p->rawbndl);
51801 0 : ae_vector_destroy(&p->rawbndu);
51802 0 : ae_vector_destroy(&p->colscales);
51803 0 : ae_vector_destroy(&p->rowscales);
51804 0 : ae_vector_destroy(&p->c);
51805 0 : ae_vector_destroy(&p->bndl);
51806 0 : ae_vector_destroy(&p->bndu);
51807 0 : _sparsematrix_destroy(&p->sparsea);
51808 0 : ae_vector_destroy(&p->al);
51809 0 : ae_vector_destroy(&p->au);
51810 0 : }
51811 :
51812 :
51813 : #endif
51814 : #if defined(AE_COMPILE_REVISEDDUALSIMPLEX) || !defined(AE_PARTIAL_BUILD)
51815 :
51816 :
51817 0 : void dsssettingsinit(dualsimplexsettings* settings, ae_state *_state)
51818 : {
51819 :
51820 :
51821 0 : settings->xtolabs = 1.0E-6;
51822 0 : settings->dtolabs = 1.0E-6;
51823 0 : settings->xtolrelabs = 0.01;
51824 0 : settings->pivottol = 10*ae_sqrt(ae_machineepsilon, _state);
51825 0 : settings->perturbmag = 10*settings->pivottol;
51826 0 : settings->maxtrfage = reviseddualsimplex_defaultmaxtrfage;
51827 0 : settings->trftype = 3;
51828 0 : settings->ratiotest = 1;
51829 0 : settings->pricing = 1;
51830 0 : settings->shifting = 2;
51831 0 : }
51832 :
51833 :
51834 : /*************************************************************************
51835 : This function initializes DSS structure. Previously allocated memory is
51836 : reused as much as possible.
51837 :
51838 : Default state of the problem is zero cost vector, all variables are fixed
51839 : at zero.
51840 :
51841 : -- ALGLIB --
51842 : Copyright 01.07.2018 by Bochkanov Sergey
51843 : *************************************************************************/
51844 0 : void dssinit(ae_int_t n, dualsimplexstate* s, ae_state *_state)
51845 : {
51846 : ae_int_t i;
51847 :
51848 :
51849 0 : ae_assert(n>0, "DSSInit: N<=0", _state);
51850 0 : s->ns = n;
51851 0 : s->m = 0;
51852 0 : rvectorgrowto(&s->rawbndl, n, _state);
51853 0 : rvectorgrowto(&s->rawbndu, n, _state);
51854 0 : for(i=0; i<=n-1; i++)
51855 : {
51856 0 : s->rawbndl.ptr.p_double[i] = 0.0;
51857 0 : s->rawbndu.ptr.p_double[i] = 0.0;
51858 : }
51859 0 : reviseddualsimplex_subprobleminit(n, &s->primary, _state);
51860 0 : reviseddualsimplex_basisinit(n, 0, &s->basis, _state);
51861 0 : rvectorgrowto(&s->repx, n, _state);
51862 0 : rvectorgrowto(&s->replagbc, n, _state);
51863 0 : ivectorgrowto(&s->repstats, n, _state);
51864 0 : for(i=0; i<=n-1; i++)
51865 : {
51866 0 : s->repx.ptr.p_double[i] = 0.0;
51867 0 : s->repstats.ptr.p_int[i] = 1;
51868 : }
51869 0 : s->dotrace = ae_false;
51870 0 : s->dodetailedtrace = ae_false;
51871 0 : s->dotimers = ae_false;
51872 0 : }
51873 :
51874 :
51875 : /*************************************************************************
51876 : This function specifies LP problem
51877 :
51878 : INPUT PARAMETERS:
51879 : State - structure previously allocated with minlpcreate() call.
51880 :
51881 : BndL - lower bounds, array[N].
51882 : BndU - upper bounds, array[N].
51883 :
51884 : DenseA - dense array[K,N], dense linear constraints (not supported
51885 : in present version)
51886 : SparseA - sparse linear constraints, sparsematrix[K,N] in CRS format
51887 : AKind - type of A: 0 for dense, 1 for sparse
51888 : AL, AU - lower and upper bounds, array[K]
51889 : K - number of equality/inequality constraints, K>=0.
51890 :
51891 : ProposedBasis- basis to import from (if BasisType=2)
51892 : BasisInitType- what to do with basis:
51893 : * 0 - set new basis to all-logicals
51894 : * 1 - try to reuse previous basis as much as possible
51895 : * 2 - try to import basis from ProposedBasis
51896 : Settings- algorithm settings
51897 :
51898 : -- ALGLIB --
51899 : Copyright 19.07.2018 by Bochkanov Sergey
51900 : *************************************************************************/
51901 0 : void dsssetproblem(dualsimplexstate* state,
51902 : /* Real */ ae_vector* c,
51903 : /* Real */ ae_vector* bndl,
51904 : /* Real */ ae_vector* bndu,
51905 : /* Real */ ae_matrix* densea,
51906 : sparsematrix* sparsea,
51907 : ae_int_t akind,
51908 : /* Real */ ae_vector* al,
51909 : /* Real */ ae_vector* au,
51910 : ae_int_t k,
51911 : dualsimplexbasis* proposedbasis,
51912 : ae_int_t basisinittype,
51913 : dualsimplexsettings* settings,
51914 : ae_state *_state)
51915 : {
51916 : ae_int_t i;
51917 : ae_int_t j;
51918 : ae_int_t jj;
51919 : ae_int_t offs;
51920 : ae_int_t ns;
51921 : ae_int_t j0;
51922 : ae_int_t j1;
51923 : ae_bool processed;
51924 : ae_int_t oldm;
51925 : ae_bool basisinitialized;
51926 : double v;
51927 :
51928 :
51929 0 : ns = state->primary.ns;
51930 0 : oldm = state->primary.m;
51931 :
51932 : /*
51933 : * Integrity checks
51934 : */
51935 0 : ae_assert(bndl->cnt>=ns, "DSSSetProblem: Length(BndL)<N", _state);
51936 0 : ae_assert(bndu->cnt>=ns, "DSSSetProblem: Length(BndU)<N", _state);
51937 0 : ae_assert(c->cnt>=ns, "SubproblemSetCost: Length(C)<N", _state);
51938 0 : ae_assert(isfinitevector(c, ns, _state), "SubproblemSetCost: C contains infinite or NaN elements", _state);
51939 0 : ae_assert(akind==0||akind==1, "DSSSetProblem: incorrect AKind", _state);
51940 0 : ae_assert((basisinittype==0||basisinittype==1)||basisinittype==2, "DSSSetProblem: incorrect BasisInitType", _state);
51941 0 : ae_assert(k>=0, "DSSSetProblem: K<0", _state);
51942 0 : if( k>0&&akind==1 )
51943 : {
51944 0 : ae_assert(sparsea->m==k, "DSSSetProblem: rows(A)<>K", _state);
51945 0 : ae_assert(sparsea->n==ns, "DSSSetProblem: cols(A)<>N", _state);
51946 : }
51947 :
51948 : /*
51949 : * Downgrade state
51950 : */
51951 0 : reviseddualsimplex_downgradestate(&state->primary, reviseddualsimplex_ssinvalid, _state);
51952 :
51953 : /*
51954 : * Reallocate storage
51955 : */
51956 0 : rvectorgrowto(&state->primary.bndl, ns+k, _state);
51957 0 : rvectorgrowto(&state->primary.bndu, ns+k, _state);
51958 0 : ivectorgrowto(&state->primary.bndt, ns+k, _state);
51959 0 : rvectorgrowto(&state->primary.rawc, ns+k, _state);
51960 0 : rvectorgrowto(&state->primary.effc, ns+k, _state);
51961 0 : rvectorgrowto(&state->primary.xa, ns+k, _state);
51962 0 : rvectorgrowto(&state->primary.d, ns+k, _state);
51963 0 : rvectorgrowto(&state->primary.xb, k, _state);
51964 0 : rvectorgrowto(&state->primary.bndlb, k, _state);
51965 0 : rvectorgrowto(&state->primary.bndub, k, _state);
51966 0 : ivectorgrowto(&state->primary.bndtb, k, _state);
51967 0 : rvectorgrowto(&state->primary.bndtollb, k, _state);
51968 0 : rvectorgrowto(&state->primary.bndtolub, k, _state);
51969 :
51970 : /*
51971 : * Save original problem formulation
51972 : */
51973 0 : state->ns = ns;
51974 0 : state->m = k;
51975 0 : for(i=0; i<=ns-1; i++)
51976 : {
51977 0 : state->rawbndl.ptr.p_double[i] = bndl->ptr.p_double[i];
51978 0 : state->rawbndu.ptr.p_double[i] = bndu->ptr.p_double[i];
51979 : }
51980 :
51981 : /*
51982 : * Setup cost, scale and box constraints
51983 : */
51984 0 : rsetv(ns+k, 0.0, &state->primary.rawc, _state);
51985 0 : rsetv(ns+k, 0.0, &state->primary.effc, _state);
51986 0 : for(i=0; i<=ns-1; i++)
51987 : {
51988 0 : state->primary.rawc.ptr.p_double[i] = c->ptr.p_double[i];
51989 0 : state->primary.effc.ptr.p_double[i] = c->ptr.p_double[i];
51990 : }
51991 0 : for(i=0; i<=ns-1; i++)
51992 : {
51993 0 : ae_assert(ae_isfinite(bndl->ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "DSSSetProblem: BndL contains NAN or +INF", _state);
51994 0 : ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "DSSSetProblem: BndU contains NAN or -INF", _state);
51995 0 : state->primary.bndl.ptr.p_double[i] = bndl->ptr.p_double[i];
51996 0 : state->primary.bndu.ptr.p_double[i] = bndu->ptr.p_double[i];
51997 :
51998 : /*
51999 : * Set bound type
52000 : */
52001 0 : if( ae_isfinite(bndl->ptr.p_double[i], _state)&&ae_isfinite(bndu->ptr.p_double[i], _state) )
52002 : {
52003 0 : if( ae_fp_greater(bndl->ptr.p_double[i],bndu->ptr.p_double[i]) )
52004 : {
52005 0 : state->primary.bndt.ptr.p_int[i] = reviseddualsimplex_ccinfeasible;
52006 : }
52007 0 : if( ae_fp_less(bndl->ptr.p_double[i],bndu->ptr.p_double[i]) )
52008 : {
52009 0 : state->primary.bndt.ptr.p_int[i] = reviseddualsimplex_ccrange;
52010 : }
52011 0 : if( ae_fp_eq(bndl->ptr.p_double[i],bndu->ptr.p_double[i]) )
52012 : {
52013 0 : state->primary.bndt.ptr.p_int[i] = reviseddualsimplex_ccfixed;
52014 : }
52015 0 : continue;
52016 : }
52017 0 : if( ae_isfinite(bndl->ptr.p_double[i], _state)&&!ae_isfinite(bndu->ptr.p_double[i], _state) )
52018 : {
52019 0 : state->primary.bndt.ptr.p_int[i] = reviseddualsimplex_cclower;
52020 0 : continue;
52021 : }
52022 0 : if( !ae_isfinite(bndl->ptr.p_double[i], _state)&&ae_isfinite(bndu->ptr.p_double[i], _state) )
52023 : {
52024 0 : state->primary.bndt.ptr.p_int[i] = reviseddualsimplex_ccupper;
52025 0 : continue;
52026 : }
52027 0 : ae_assert(ae_isneginf(bndl->ptr.p_double[i], _state)&&ae_isposinf(bndu->ptr.p_double[i], _state), "DSSSetProblem: integrity check failed", _state);
52028 0 : state->primary.bndt.ptr.p_int[i] = reviseddualsimplex_ccfree;
52029 : }
52030 :
52031 : /*
52032 : * Quick exit if no linear constraints is present
52033 : */
52034 0 : if( k==0 )
52035 : {
52036 0 : state->primary.m = 0;
52037 0 : reviseddualsimplex_basisinit(state->primary.ns, state->primary.m, &state->basis, _state);
52038 0 : return;
52039 : }
52040 :
52041 : /*
52042 : * Extend A with structural terms and transpose it:
52043 : * * allocate place for A^T extended with logical part.
52044 : * * copy with transposition
52045 : * * perform integrity check for array sizes
52046 : * * manually append new items
52047 : * * update DIdx/UIdx
52048 : */
52049 0 : processed = ae_false;
52050 0 : state->primary.m = k;
52051 0 : if( akind==0 )
52052 : {
52053 0 : ae_assert(ae_false, "DSSSetProblem: does not support dense inputs yet", _state);
52054 : }
52055 0 : if( akind==1 )
52056 : {
52057 :
52058 : /*
52059 : * Transpose constraints matrix, apply column and row scaling.
52060 : * Extend it with identity submatrix.
52061 : *
52062 : * NOTE: in order to improve stability of LU factorization we
52063 : * normalize rows using 2-norm, not INF-norm. Having rows
52064 : * normalized with 2-norm makes every element less than
52065 : * 1.0 in magnitude, which allows us later to move logical
52066 : * columns to the beginning of LU factors without loosing
52067 : * stability.
52068 : */
52069 0 : rvectorsetlengthatleast(&state->at.vals, sparsea->ridx.ptr.p_int[k]+k, _state);
52070 0 : ivectorsetlengthatleast(&state->at.idx, sparsea->ridx.ptr.p_int[k]+k, _state);
52071 0 : ivectorsetlengthatleast(&state->at.ridx, ns+k+1, _state);
52072 0 : ivectorsetlengthatleast(&state->at.didx, ns+k, _state);
52073 0 : ivectorsetlengthatleast(&state->at.uidx, ns+k, _state);
52074 0 : sparsecopytransposecrsbuf(sparsea, &state->at, _state);
52075 0 : rvectorsetlengthatleast(&state->rowscales, k, _state);
52076 0 : for(i=0; i<=k-1; i++)
52077 : {
52078 0 : state->rowscales.ptr.p_double[i] = (double)(0);
52079 : }
52080 0 : for(i=0; i<=ns-1; i++)
52081 : {
52082 0 : j0 = state->at.ridx.ptr.p_int[i];
52083 0 : j1 = state->at.ridx.ptr.p_int[i+1]-1;
52084 0 : for(j=j0; j<=j1; j++)
52085 : {
52086 0 : v = state->at.vals.ptr.p_double[j];
52087 0 : jj = state->at.idx.ptr.p_int[j];
52088 0 : state->at.vals.ptr.p_double[j] = v;
52089 0 : state->rowscales.ptr.p_double[jj] = state->rowscales.ptr.p_double[jj]+v*v;
52090 : }
52091 : }
52092 0 : rvectorsetlengthatleast(&state->tmp0, k, _state);
52093 0 : for(i=0; i<=k-1; i++)
52094 : {
52095 0 : state->rowscales.ptr.p_double[i] = coalesce(ae_sqrt(state->rowscales.ptr.p_double[i], _state), (double)(1), _state);
52096 0 : state->tmp0.ptr.p_double[i] = 1/state->rowscales.ptr.p_double[i];
52097 : }
52098 0 : for(i=0; i<=ns-1; i++)
52099 : {
52100 0 : j0 = state->at.ridx.ptr.p_int[i];
52101 0 : j1 = state->at.ridx.ptr.p_int[i+1]-1;
52102 0 : for(j=j0; j<=j1; j++)
52103 : {
52104 0 : state->at.vals.ptr.p_double[j] = state->at.vals.ptr.p_double[j]*state->tmp0.ptr.p_double[state->at.idx.ptr.p_int[j]];
52105 : }
52106 : }
52107 0 : ae_assert(state->at.vals.cnt>=sparsea->ridx.ptr.p_int[k]+k, "DSSSetProblem: integrity check failed", _state);
52108 0 : ae_assert(state->at.idx.cnt>=sparsea->ridx.ptr.p_int[k]+k, "DSSSetProblem: integrity check failed", _state);
52109 0 : ae_assert(state->at.ridx.cnt>=ns+k+1, "DSSSetProblem: integrity check failed", _state);
52110 0 : ae_assert(state->at.didx.cnt>=ns+k, "DSSSetProblem: integrity check failed", _state);
52111 0 : ae_assert(state->at.uidx.cnt>=ns+k, "DSSSetProblem: integrity check failed", _state);
52112 0 : offs = state->at.ridx.ptr.p_int[ns];
52113 0 : for(i=0; i<=k-1; i++)
52114 : {
52115 0 : state->at.vals.ptr.p_double[offs+i] = -1.0;
52116 0 : state->at.idx.ptr.p_int[offs+i] = i;
52117 0 : state->at.ridx.ptr.p_int[ns+i+1] = state->at.ridx.ptr.p_int[ns+i]+1;
52118 0 : state->at.ninitialized = state->at.ninitialized+1;
52119 : }
52120 0 : state->at.m = state->at.m+k;
52121 0 : sparseinitduidx(&state->at, _state);
52122 0 : sparsecopytransposecrsbuf(&state->at, &state->a, _state);
52123 0 : processed = ae_true;
52124 : }
52125 0 : ae_assert(processed, "DSSSetProblem: integrity check failed (akind)", _state);
52126 :
52127 : /*
52128 : * Copy AL, AU to BndL/BndT
52129 : */
52130 0 : for(i=0; i<=k-1; i++)
52131 : {
52132 0 : ae_assert(ae_isfinite(al->ptr.p_double[i], _state)||ae_isneginf(al->ptr.p_double[i], _state), "DSSSetProblem: AL contains NAN or +INF", _state);
52133 0 : ae_assert(ae_isfinite(au->ptr.p_double[i], _state)||ae_isposinf(au->ptr.p_double[i], _state), "DSSSetProblem: AU contains NAN or -INF", _state);
52134 0 : state->primary.bndl.ptr.p_double[ns+i] = al->ptr.p_double[i]/state->rowscales.ptr.p_double[i];
52135 0 : state->primary.bndu.ptr.p_double[ns+i] = au->ptr.p_double[i]/state->rowscales.ptr.p_double[i];
52136 :
52137 : /*
52138 : * Set bound type
52139 : */
52140 0 : if( ae_isfinite(al->ptr.p_double[i], _state)&&ae_isfinite(au->ptr.p_double[i], _state) )
52141 : {
52142 0 : if( ae_fp_greater(al->ptr.p_double[i],au->ptr.p_double[i]) )
52143 : {
52144 0 : state->primary.bndt.ptr.p_int[ns+i] = reviseddualsimplex_ccinfeasible;
52145 : }
52146 0 : if( ae_fp_less(al->ptr.p_double[i],au->ptr.p_double[i]) )
52147 : {
52148 0 : state->primary.bndt.ptr.p_int[ns+i] = reviseddualsimplex_ccrange;
52149 : }
52150 0 : if( ae_fp_eq(al->ptr.p_double[i],au->ptr.p_double[i]) )
52151 : {
52152 0 : state->primary.bndt.ptr.p_int[ns+i] = reviseddualsimplex_ccfixed;
52153 : }
52154 0 : continue;
52155 : }
52156 0 : if( ae_isfinite(al->ptr.p_double[i], _state)&&!ae_isfinite(au->ptr.p_double[i], _state) )
52157 : {
52158 0 : state->primary.bndt.ptr.p_int[ns+i] = reviseddualsimplex_cclower;
52159 0 : continue;
52160 : }
52161 0 : if( !ae_isfinite(al->ptr.p_double[i], _state)&&ae_isfinite(au->ptr.p_double[i], _state) )
52162 : {
52163 0 : state->primary.bndt.ptr.p_int[ns+i] = reviseddualsimplex_ccupper;
52164 0 : continue;
52165 : }
52166 0 : ae_assert(ae_isneginf(al->ptr.p_double[i], _state)&&ae_isposinf(au->ptr.p_double[i], _state), "DSSSetProblem: integrity check faoled", _state);
52167 0 : state->primary.bndt.ptr.p_int[ns+i] = reviseddualsimplex_ccfree;
52168 : }
52169 :
52170 : /*
52171 : * Depending on BasisInitType either start from all-logical basis
52172 : * or try to reuse already existing basis.
52173 : *
52174 : * NOTE: current version does not support basis shrinkage, only
52175 : * growing basis can be reused.
52176 : */
52177 0 : basisinitialized = ae_false;
52178 0 : if( basisinittype==2 )
52179 : {
52180 :
52181 : /*
52182 : * Import basis from one proposed by caller
52183 : */
52184 0 : ae_assert(proposedbasis->ns==state->primary.ns, "DSSSetProblemX: unable to import basis, sizes do not match", _state);
52185 0 : ae_assert(proposedbasis->m==state->primary.m, "DSSSetProblemX: unable to import basis, sizes do not match", _state);
52186 0 : basisinitialized = reviseddualsimplex_basistryimportfrom(&state->basis, proposedbasis, &state->at, settings, _state);
52187 : }
52188 0 : if( basisinittype==1&&state->primary.m>=oldm )
52189 : {
52190 :
52191 : /*
52192 : * New rows were added, try to reuse previous basis
52193 : */
52194 0 : for(i=oldm; i<=state->primary.m-1; i++)
52195 : {
52196 0 : state->primary.rawc.ptr.p_double[ns+i] = 0.0;
52197 0 : state->primary.effc.ptr.p_double[ns+i] = 0.0;
52198 0 : state->primary.xa.ptr.p_double[ns+i] = 0.0;
52199 0 : state->primary.d.ptr.p_double[ns+i] = 0.0;
52200 : }
52201 0 : basisinitialized = reviseddualsimplex_basistryresize(&state->basis, state->primary.m, &state->at, settings, _state);
52202 : }
52203 0 : if( !basisinitialized )
52204 : {
52205 :
52206 : /*
52207 : * Straightforward code for all-logicals basis
52208 : */
52209 0 : for(i=0; i<=k-1; i++)
52210 : {
52211 0 : state->primary.rawc.ptr.p_double[ns+i] = 0.0;
52212 0 : state->primary.effc.ptr.p_double[ns+i] = 0.0;
52213 0 : state->primary.xa.ptr.p_double[ns+i] = 0.0;
52214 0 : state->primary.d.ptr.p_double[ns+i] = 0.0;
52215 : }
52216 0 : reviseddualsimplex_basisinit(state->primary.ns, state->primary.m, &state->basis, _state);
52217 0 : reviseddualsimplex_basisfreshtrf(&state->basis, &state->at, settings, _state);
52218 : }
52219 0 : rvectorgrowto(&state->replaglc, state->primary.m, _state);
52220 0 : ivectorgrowto(&state->repstats, state->primary.ns+state->primary.m, _state);
52221 : }
52222 :
52223 :
52224 : /*************************************************************************
52225 : This function exports basis from the primary (phase II) subproblem.
52226 :
52227 : INPUT PARAMETERS:
52228 : State - structure
52229 :
52230 : OUTPUT PARAMETERS
52231 : Basis - current basis exported (no factorization, only set of
52232 : basis/nonbasic variables)
52233 :
52234 : -- ALGLIB --
52235 : Copyright 19.07.2018 by Bochkanov Sergey
52236 : *************************************************************************/
52237 0 : void dssexportbasis(dualsimplexstate* state,
52238 : dualsimplexbasis* basis,
52239 : ae_state *_state)
52240 : {
52241 :
52242 :
52243 0 : reviseddualsimplex_basisexportto(&state->basis, basis, _state);
52244 0 : }
52245 :
52246 :
52247 : /*************************************************************************
52248 : This function solves LP problem with dual simplex solver.
52249 :
52250 : INPUT PARAMETERS:
52251 : State - state
52252 :
52253 : Solution results can be found in fields of State which are explicitly
52254 : declared as accessible by external code.
52255 :
52256 : -- ALGLIB --
52257 : Copyright 19.07.2018 by Bochkanov Sergey
52258 : *************************************************************************/
52259 0 : void dssoptimize(dualsimplexstate* state,
52260 : dualsimplexsettings* settings,
52261 : ae_state *_state)
52262 : {
52263 : ae_int_t i;
52264 : ae_int_t nx;
52265 : double v;
52266 : ae_int_t cnt1;
52267 : ae_int_t cnt2;
52268 : ae_int_t cntfx;
52269 : ae_int_t cntfr;
52270 : ae_int_t cntif;
52271 : ae_int_t ttotal;
52272 :
52273 :
52274 0 : nx = state->primary.ns+state->primary.m;
52275 0 : ttotal = 0;
52276 :
52277 : /*
52278 : * Trace settings
52279 : */
52280 0 : state->dotrace = ae_is_trace_enabled("DUALSIMPLEX");
52281 0 : state->dodetailedtrace = state->dotrace&&ae_is_trace_enabled("DUALSIMPLEX.DETAILED");
52282 0 : state->dotimers = ae_is_trace_enabled("TIMERS.DUALSIMPLEX");
52283 :
52284 : /*
52285 : * Init report fields
52286 : */
52287 0 : state->repiterationscount = 0;
52288 0 : state->repiterationscount1 = 0;
52289 0 : state->repiterationscount2 = 0;
52290 0 : state->repiterationscount3 = 0;
52291 0 : state->repterminationtype = 1;
52292 0 : state->repphase1time = 0;
52293 0 : state->repphase2time = 0;
52294 0 : state->repphase3time = 0;
52295 0 : state->repdualpricingtime = 0;
52296 0 : state->repdualbtrantime = 0;
52297 0 : state->repdualpivotrowtime = 0;
52298 0 : state->repdualratiotesttime = 0;
52299 0 : state->repdualftrantime = 0;
52300 0 : state->repdualupdatesteptime = 0;
52301 0 : state->repfillpivotrow = (double)(0);
52302 0 : state->repfillpivotrowcnt = 0;
52303 0 : state->repfillrhor = (double)(0);
52304 0 : state->repfillrhorcnt = 0;
52305 0 : state->repfilldensemu = (double)(0);
52306 0 : state->repfilldensemucnt = 0;
52307 0 : reviseddualsimplex_basisclearstats(&state->basis, _state);
52308 :
52309 : /*
52310 : * Setup timer (if needed)
52311 : */
52312 0 : if( state->dotimers )
52313 : {
52314 0 : ttotal = ae_tickcount();
52315 : }
52316 :
52317 : /*
52318 : * Trace output (if needed)
52319 : */
52320 0 : if( state->dotrace||state->dotimers )
52321 : {
52322 0 : ae_trace("\n\n");
52323 0 : ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n");
52324 0 : ae_trace("// DUAL SIMPLEX SOLVER STARTED //\n");
52325 0 : ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n");
52326 0 : ae_trace("> problem size:\n");
52327 0 : ae_trace("N = %12d (variables)\n",
52328 0 : (int)(state->primary.ns));
52329 0 : ae_trace("M = %12d (constraints)\n",
52330 0 : (int)(state->primary.m));
52331 : }
52332 0 : if( state->dotrace )
52333 : {
52334 0 : ae_trace("> variable stats:\n");
52335 0 : if( state->dodetailedtrace )
52336 : {
52337 : }
52338 0 : cnt1 = 0;
52339 0 : cnt2 = 0;
52340 0 : cntfx = 0;
52341 0 : cntfr = 0;
52342 0 : cntif = 0;
52343 0 : for(i=0; i<=state->primary.ns-1; i++)
52344 : {
52345 0 : if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_cclower||state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccupper )
52346 : {
52347 0 : inc(&cnt1, _state);
52348 : }
52349 0 : if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccrange )
52350 : {
52351 0 : inc(&cnt2, _state);
52352 : }
52353 0 : if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccfixed )
52354 : {
52355 0 : inc(&cntfx, _state);
52356 : }
52357 0 : if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccfree )
52358 : {
52359 0 : inc(&cntfr, _state);
52360 : }
52361 0 : if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccinfeasible )
52362 : {
52363 0 : inc(&cntif, _state);
52364 : }
52365 : }
52366 0 : ae_trace("UBnd/LBnd = %12d\n",
52367 : (int)(cnt1));
52368 0 : ae_trace("Range = %12d\n",
52369 : (int)(cnt2));
52370 0 : ae_trace("Fixed = %12d\n",
52371 : (int)(cntfx));
52372 0 : ae_trace("Free = %12d\n",
52373 : (int)(cntfr));
52374 0 : ae_trace("Infeas = %12d\n",
52375 : (int)(cntif));
52376 0 : ae_trace("> constraint stats:\n");
52377 0 : if( state->dodetailedtrace )
52378 : {
52379 : }
52380 0 : cnt1 = 0;
52381 0 : cnt2 = 0;
52382 0 : cntfx = 0;
52383 0 : cntfr = 0;
52384 0 : cntif = 0;
52385 0 : for(i=state->primary.ns-1; i<=nx-1; i++)
52386 : {
52387 0 : if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_cclower||state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccupper )
52388 : {
52389 0 : inc(&cnt1, _state);
52390 : }
52391 0 : if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccrange )
52392 : {
52393 0 : inc(&cnt2, _state);
52394 : }
52395 0 : if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccfixed )
52396 : {
52397 0 : inc(&cntfx, _state);
52398 : }
52399 0 : if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccfree )
52400 : {
52401 0 : inc(&cntfr, _state);
52402 : }
52403 0 : if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccinfeasible )
52404 : {
52405 0 : inc(&cntif, _state);
52406 : }
52407 : }
52408 0 : ae_trace("ubnd/lbnd = %12d\n",
52409 : (int)(cnt1));
52410 0 : ae_trace("range = %12d\n",
52411 : (int)(cnt2));
52412 0 : ae_trace("fixed = %12d\n",
52413 : (int)(cntfx));
52414 0 : ae_trace("free = %12d\n",
52415 : (int)(cntfr));
52416 0 : ae_trace("infeas = %12d\n",
52417 : (int)(cntif));
52418 0 : v = (double)(0);
52419 0 : for(i=0; i<=state->primary.ns-1; i++)
52420 : {
52421 0 : if( ae_isfinite(state->primary.bndl.ptr.p_double[i], _state) )
52422 : {
52423 0 : v = ae_maxreal(v, ae_fabs(state->primary.bndl.ptr.p_double[i], _state), _state);
52424 : }
52425 : }
52426 0 : ae_trace("|BndL| = %0.3e\n",
52427 : (double)(v));
52428 0 : v = (double)(0);
52429 0 : for(i=0; i<=state->primary.ns-1; i++)
52430 : {
52431 0 : if( ae_isfinite(state->primary.bndu.ptr.p_double[i], _state) )
52432 : {
52433 0 : v = ae_maxreal(v, ae_fabs(state->primary.bndu.ptr.p_double[i], _state), _state);
52434 : }
52435 : }
52436 0 : ae_trace("|BndU| = %0.3e\n",
52437 : (double)(v));
52438 0 : v = (double)(0);
52439 0 : for(i=state->primary.ns; i<=nx-1; i++)
52440 : {
52441 0 : if( ae_isfinite(state->primary.bndl.ptr.p_double[i], _state) )
52442 : {
52443 0 : v = ae_maxreal(v, ae_fabs(state->primary.bndl.ptr.p_double[i], _state), _state);
52444 : }
52445 : }
52446 0 : ae_trace("|AL| = %0.3e\n",
52447 : (double)(v));
52448 0 : v = (double)(0);
52449 0 : for(i=state->primary.ns; i<=nx-1; i++)
52450 : {
52451 0 : if( ae_isfinite(state->primary.bndu.ptr.p_double[i], _state) )
52452 : {
52453 0 : v = ae_maxreal(v, ae_fabs(state->primary.bndu.ptr.p_double[i], _state), _state);
52454 : }
52455 : }
52456 0 : ae_trace("|AU| = %0.3e\n",
52457 : (double)(v));
52458 : }
52459 :
52460 : /*
52461 : * Call actual workhorse function
52462 : */
52463 0 : reviseddualsimplex_dssoptimizewrk(state, settings, _state);
52464 :
52465 : /*
52466 : * Print reports
52467 : */
52468 0 : if( state->dotrace )
52469 : {
52470 0 : ae_trace("\n");
52471 0 : ae_trace("****************************************************************************************************\n");
52472 0 : ae_trace("* PRINTING ITERATION STATISTICS *\n");
52473 0 : ae_trace("****************************************************************************************************\n");
52474 0 : ae_trace("> iteration counts:\n");
52475 0 : ae_trace("Phase 1 = %12d\n",
52476 0 : (int)(state->repiterationscount1));
52477 0 : ae_trace("Phase 2 = %12d\n",
52478 0 : (int)(state->repiterationscount2));
52479 0 : ae_trace("Phase 3 = %12d\n",
52480 0 : (int)(state->repiterationscount3));
52481 0 : ae_trace("> factorization statistics:\n");
52482 0 : ae_trace("FactCnt = %12d (LU factorizations)\n",
52483 0 : (int)(state->basis.statfact));
52484 0 : ae_trace("UpdtCnt = %12d (LU updates)\n",
52485 0 : (int)(state->basis.statupdt));
52486 0 : ae_trace("RefactPeriod= %12.1f (average refactorization interval)\n",
52487 0 : (double)((state->basis.statfact+state->basis.statupdt)/coalesce((double)(state->basis.statfact), (double)(1), _state)));
52488 0 : ae_trace("LU-NZR = %12.1f (average LU nonzeros per row)\n",
52489 0 : (double)(state->basis.statoffdiag/(coalesce((double)(state->m), (double)(1), _state)*coalesce((double)(state->basis.statfact+state->basis.statupdt), (double)(1), _state))));
52490 0 : ae_trace("> sparsity counters (average fill factors):\n");
52491 0 : if( state->dodetailedtrace )
52492 : {
52493 0 : ae_trace("RhoR = %12.4f (BTran result)\n",
52494 0 : (double)(state->repfillrhor/coalesce((double)(state->repfillrhorcnt), (double)(1), _state)));
52495 0 : ae_trace("AlphaR = %12.4f (pivot row)\n",
52496 0 : (double)(state->repfillpivotrow/coalesce((double)(state->repfillpivotrowcnt), (double)(1), _state)));
52497 0 : if( state->basis.trftype==3 )
52498 : {
52499 0 : ae_trace("Mu = %12.4f (Forest-Tomlin factor)\n",
52500 0 : (double)(state->repfilldensemu/coalesce((double)(state->repfilldensemucnt), (double)(1), _state)));
52501 : }
52502 : }
52503 : else
52504 : {
52505 0 : ae_trace("...skipped, need DUALSIMPLEX.DETAILED trace tag\n");
52506 : }
52507 : }
52508 0 : if( state->dotimers )
52509 : {
52510 0 : ttotal = ae_tickcount()-ttotal;
52511 0 : ae_trace("\n");
52512 0 : ae_trace("****************************************************************************************************\n");
52513 0 : ae_trace("* PRINTING DUAL SIMPLEX TIMERS *\n");
52514 0 : ae_trace("****************************************************************************************************\n");
52515 0 : ae_trace("> total time:\n");
52516 0 : ae_trace("Time = %12d ms\n",
52517 : (int)(ttotal));
52518 0 : ae_trace("> time by phase:\n");
52519 0 : ae_trace("Phase 1 = %12d ms\n",
52520 0 : (int)(state->repphase1time));
52521 0 : ae_trace("Phase 2 = %12d ms\n",
52522 0 : (int)(state->repphase2time));
52523 0 : ae_trace("Phase 3 = %12d ms\n",
52524 0 : (int)(state->repphase3time));
52525 0 : ae_trace("> time by step (dual phases 1 and 2):\n");
52526 0 : ae_trace("Pricing = %12d ms\n",
52527 0 : (int)(state->repdualpricingtime));
52528 0 : ae_trace("BTran = %12d ms\n",
52529 0 : (int)(state->repdualbtrantime));
52530 0 : ae_trace("PivotRow = %12d ms\n",
52531 0 : (int)(state->repdualpivotrowtime));
52532 0 : ae_trace("RatioTest = %12d ms\n",
52533 0 : (int)(state->repdualratiotesttime));
52534 0 : ae_trace("FTran = %12d ms\n",
52535 0 : (int)(state->repdualftrantime));
52536 0 : ae_trace("Update = %12d ms\n",
52537 0 : (int)(state->repdualupdatesteptime));
52538 : }
52539 0 : }
52540 :
52541 :
52542 : /*************************************************************************
52543 : This function initializes subproblem structure. Previously allocated memory
52544 : is reused as much as possible.
52545 :
52546 : Default state of the problem is zero cost vector, all variables are fixed
52547 : at zero, linear constraint matrix is zero.
52548 :
52549 : -- ALGLIB --
52550 : Copyright 01.07.2018 by Bochkanov Sergey
52551 : *************************************************************************/
52552 0 : static void reviseddualsimplex_subprobleminit(ae_int_t n,
52553 : dualsimplexsubproblem* s,
52554 : ae_state *_state)
52555 : {
52556 : ae_int_t i;
52557 :
52558 :
52559 0 : ae_assert(n>0, "SubproblemInit: N<=0", _state);
52560 0 : s->ns = n;
52561 0 : s->m = 0;
52562 0 : s->state = reviseddualsimplex_ssinvalid;
52563 0 : rvectorsetlengthatleast(&s->xa, n, _state);
52564 0 : rvectorsetlengthatleast(&s->xb, 0, _state);
52565 0 : rvectorsetlengthatleast(&s->d, n, _state);
52566 0 : rvectorsetlengthatleast(&s->rawc, n, _state);
52567 0 : rvectorsetlengthatleast(&s->effc, n, _state);
52568 0 : rvectorsetlengthatleast(&s->bndl, n, _state);
52569 0 : rvectorsetlengthatleast(&s->bndu, n, _state);
52570 0 : ivectorsetlengthatleast(&s->bndt, n, _state);
52571 0 : for(i=0; i<=n-1; i++)
52572 : {
52573 0 : s->rawc.ptr.p_double[i] = (double)(0);
52574 0 : s->effc.ptr.p_double[i] = (double)(0);
52575 0 : s->bndl.ptr.p_double[i] = (double)(0);
52576 0 : s->bndu.ptr.p_double[i] = (double)(0);
52577 0 : s->bndt.ptr.p_int[i] = reviseddualsimplex_ccfixed;
52578 0 : s->xa.ptr.p_double[i] = 0.0;
52579 0 : s->d.ptr.p_double[i] = 0.0;
52580 : }
52581 0 : }
52582 :
52583 :
52584 : /*************************************************************************
52585 : This function initializes phase #1 subproblem which minimizes sum of dual
52586 : infeasibilities. It is required that total count of non-boxed non-fixed
52587 : variables is at least M.
52588 :
52589 : It splits out basic components of XA[] to XB[]
52590 :
52591 : -- ALGLIB --
52592 : Copyright 01.07.2018 by Bochkanov Sergey
52593 : *************************************************************************/
52594 0 : static void reviseddualsimplex_subprobleminitphase1(dualsimplexsubproblem* s0,
52595 : dualsimplexbasis* basis,
52596 : dualsimplexsubproblem* s1,
52597 : ae_state *_state)
52598 : {
52599 : ae_int_t i;
52600 :
52601 :
52602 0 : s1->ns = s0->ns;
52603 0 : s1->m = s0->m;
52604 0 : copyrealarray(&s0->rawc, &s1->rawc, _state);
52605 0 : copyrealarray(&s0->effc, &s1->effc, _state);
52606 0 : copyrealarray(&s0->bndl, &s1->bndl, _state);
52607 0 : copyrealarray(&s0->bndu, &s1->bndu, _state);
52608 0 : copyintegerarray(&s0->bndt, &s1->bndt, _state);
52609 0 : copyrealarray(&s0->xa, &s1->xa, _state);
52610 0 : copyrealarray(&s0->xb, &s1->xb, _state);
52611 0 : copyrealarray(&s0->bndlb, &s1->bndlb, _state);
52612 0 : copyrealarray(&s0->bndub, &s1->bndub, _state);
52613 0 : copyintegerarray(&s0->bndtb, &s1->bndtb, _state);
52614 0 : copyrealarray(&s0->bndtollb, &s1->bndtollb, _state);
52615 0 : copyrealarray(&s0->bndtolub, &s1->bndtolub, _state);
52616 0 : copyrealarray(&s0->d, &s1->d, _state);
52617 0 : for(i=0; i<=s1->ns+s1->m-1; i++)
52618 : {
52619 0 : if( s1->bndt.ptr.p_int[i]==reviseddualsimplex_cclower )
52620 : {
52621 0 : s1->bndt.ptr.p_int[i] = reviseddualsimplex_ccrange;
52622 0 : s1->bndl.ptr.p_double[i] = (double)(0);
52623 0 : s1->bndu.ptr.p_double[i] = (double)(1);
52624 0 : s1->xa.ptr.p_double[i] = (double)(0);
52625 0 : continue;
52626 : }
52627 0 : if( s1->bndt.ptr.p_int[i]==reviseddualsimplex_ccupper )
52628 : {
52629 0 : s1->bndt.ptr.p_int[i] = reviseddualsimplex_ccrange;
52630 0 : s1->bndl.ptr.p_double[i] = (double)(-1);
52631 0 : s1->bndu.ptr.p_double[i] = (double)(0);
52632 0 : s1->xa.ptr.p_double[i] = (double)(0);
52633 0 : continue;
52634 : }
52635 0 : if( s1->bndt.ptr.p_int[i]==reviseddualsimplex_ccfree )
52636 : {
52637 0 : s1->bndt.ptr.p_int[i] = reviseddualsimplex_ccrange;
52638 0 : s1->bndl.ptr.p_double[i] = (double)(-1);
52639 0 : s1->bndu.ptr.p_double[i] = (double)(1);
52640 0 : if( ae_fp_greater_eq(s1->effc.ptr.p_double[i],(double)(0)) )
52641 : {
52642 0 : s1->xa.ptr.p_double[i] = (double)(-1);
52643 : }
52644 : else
52645 : {
52646 0 : s1->xa.ptr.p_double[i] = (double)(1);
52647 : }
52648 0 : continue;
52649 : }
52650 0 : s1->bndt.ptr.p_int[i] = reviseddualsimplex_ccfixed;
52651 0 : s1->bndl.ptr.p_double[i] = (double)(0);
52652 0 : s1->bndu.ptr.p_double[i] = (double)(0);
52653 0 : s1->xa.ptr.p_double[i] = (double)(0);
52654 : }
52655 0 : s1->state = reviseddualsimplex_ssvalidxn;
52656 0 : }
52657 :
52658 :
52659 : /*************************************************************************
52660 : This function initializes phase #3 subproblem which applies primal simplex
52661 : method to the result of the phase #2.
52662 :
52663 : It also performs modification of the subproblem in order to ensure that
52664 : initial point is primal feasible.
52665 :
52666 : NOTE: this function expects that all components (basic and nonbasic ones)
52667 : are stored in XA[]
52668 :
52669 : -- ALGLIB --
52670 : Copyright 01.07.2018 by Bochkanov Sergey
52671 : *************************************************************************/
52672 0 : static void reviseddualsimplex_subprobleminitphase3(dualsimplexsubproblem* s0,
52673 : dualsimplexsubproblem* s1,
52674 : ae_state *_state)
52675 : {
52676 :
52677 :
52678 0 : s1->ns = s0->ns;
52679 0 : s1->m = s0->m;
52680 0 : copyrealarray(&s0->rawc, &s1->rawc, _state);
52681 0 : copyrealarray(&s0->effc, &s1->effc, _state);
52682 0 : copyrealarray(&s0->bndl, &s1->bndl, _state);
52683 0 : copyrealarray(&s0->bndu, &s1->bndu, _state);
52684 0 : copyintegerarray(&s0->bndt, &s1->bndt, _state);
52685 0 : copyrealarray(&s0->xa, &s1->xa, _state);
52686 0 : copyrealarray(&s0->xb, &s1->xb, _state);
52687 0 : copyrealarray(&s0->bndlb, &s1->bndlb, _state);
52688 0 : copyrealarray(&s0->bndub, &s1->bndub, _state);
52689 0 : copyintegerarray(&s0->bndtb, &s1->bndtb, _state);
52690 0 : copyrealarray(&s0->bndtollb, &s1->bndtollb, _state);
52691 0 : copyrealarray(&s0->bndtolub, &s1->bndtolub, _state);
52692 0 : copyrealarray(&s0->d, &s1->d, _state);
52693 0 : s1->state = reviseddualsimplex_ssvalidxn;
52694 0 : }
52695 :
52696 :
52697 : /*************************************************************************
52698 : This function infers nonbasic variables of X using sign of effective C[].
52699 :
52700 : Only non-basic components of XN are changed; everything else is NOT updated.
52701 :
52702 : -- ALGLIB --
52703 : Copyright 19.07.2018 by Bochkanov Sergey
52704 : *************************************************************************/
52705 0 : static void reviseddualsimplex_subprobleminferinitialxn(dualsimplexstate* state,
52706 : dualsimplexsubproblem* s,
52707 : ae_state *_state)
52708 : {
52709 : ae_int_t i;
52710 : ae_int_t ii;
52711 : ae_int_t bndt;
52712 :
52713 :
52714 0 : for(ii=0; ii<=s->ns-1; ii++)
52715 : {
52716 0 : i = state->basis.nidx.ptr.p_int[ii];
52717 0 : bndt = s->bndt.ptr.p_int[i];
52718 0 : if( bndt==reviseddualsimplex_ccfixed||bndt==reviseddualsimplex_ccrange )
52719 : {
52720 0 : if( s->effc.ptr.p_double[i]>=0 )
52721 : {
52722 0 : s->xa.ptr.p_double[i] = s->bndl.ptr.p_double[i];
52723 : }
52724 : else
52725 : {
52726 0 : s->xa.ptr.p_double[i] = s->bndu.ptr.p_double[i];
52727 : }
52728 0 : continue;
52729 : }
52730 0 : if( bndt==reviseddualsimplex_cclower )
52731 : {
52732 0 : s->xa.ptr.p_double[i] = s->bndl.ptr.p_double[i];
52733 0 : continue;
52734 : }
52735 0 : if( bndt==reviseddualsimplex_ccupper )
52736 : {
52737 0 : s->xa.ptr.p_double[i] = s->bndu.ptr.p_double[i];
52738 0 : continue;
52739 : }
52740 0 : if( bndt==reviseddualsimplex_ccfree )
52741 : {
52742 0 : s->xa.ptr.p_double[i] = 0.0;
52743 0 : continue;
52744 : }
52745 0 : ae_assert(ae_false, "SubproblemInferInitialXN: integrity check failed (infeasible constraint)", _state);
52746 : }
52747 0 : s->state = reviseddualsimplex_ssvalidxn;
52748 0 : }
52749 :
52750 :
52751 : /*************************************************************************
52752 : This function infers basic variables of X using values of non-basic vars
52753 : and updates reduced cost vector D and target function Z. Sets state age
52754 : to zero.
52755 :
52756 : D[] is allocated during computations.
52757 :
52758 : Temporary vectors Tmp0 and Tmp1 are used (reallocated as needed).
52759 :
52760 : NOTE: this function expects that both nonbasic and basic components are
52761 : stored in XA[]. XB[] array is not referenced.
52762 :
52763 : -- ALGLIB --
52764 : Copyright 19.07.2018 by Bochkanov Sergey
52765 : *************************************************************************/
52766 0 : static void reviseddualsimplex_subproblemhandlexnupdate(dualsimplexstate* state,
52767 : dualsimplexsubproblem* s,
52768 : ae_state *_state)
52769 : {
52770 : ae_int_t i;
52771 : ae_int_t j;
52772 : ae_int_t m;
52773 : ae_int_t nn;
52774 :
52775 :
52776 0 : ae_assert(s->state>=reviseddualsimplex_ssvalidxn, "SubproblemHandleXNUpdate: integrity check failed (XN is not valid)", _state);
52777 0 : nn = s->ns;
52778 0 : m = s->m;
52779 :
52780 : /*
52781 : * Compute nonbasic components
52782 : */
52783 0 : reviseddualsimplex_computeanxn(state, s, &s->xa, &state->tmp0, _state);
52784 0 : reviseddualsimplex_basissolve(&state->basis, &state->tmp0, &state->tmp1, &state->tmp2, _state);
52785 0 : for(i=0; i<=m-1; i++)
52786 : {
52787 0 : s->xa.ptr.p_double[state->basis.idx.ptr.p_int[i]] = -state->tmp1.ptr.p_double[i];
52788 : }
52789 :
52790 : /*
52791 : * Compute D
52792 : */
52793 0 : for(i=0; i<=m-1; i++)
52794 : {
52795 0 : state->tmp0.ptr.p_double[i] = s->effc.ptr.p_double[state->basis.idx.ptr.p_int[i]];
52796 : }
52797 0 : reviseddualsimplex_basissolvet(&state->basis, &state->tmp0, &state->tmp1, &state->tmp2, _state);
52798 0 : reviseddualsimplex_computeantv(state, &state->tmp1, &s->d, _state);
52799 0 : for(i=0; i<=nn-1; i++)
52800 : {
52801 0 : j = state->basis.nidx.ptr.p_int[i];
52802 0 : s->d.ptr.p_double[j] = s->effc.ptr.p_double[j]-s->d.ptr.p_double[j];
52803 : }
52804 :
52805 : /*
52806 : * Update state validity/age
52807 : */
52808 0 : s->state = reviseddualsimplex_ssvalid;
52809 0 : }
52810 :
52811 :
52812 : /*************************************************************************
52813 : This function performs initial dual feasibility correction on the subproblem.
52814 : It assumes that problem state is at least ssValidXN. After call to this
52815 : function the problem state is set to ssValid.
52816 :
52817 : This function returns dual feasibility error after dual feasibility correction.
52818 :
52819 : NOTE: this function expects that both nonbasic and basic components are
52820 : stored in XA[]. XB[] array is not referenced.
52821 :
52822 : -- ALGLIB --
52823 : Copyright 19.07.2018 by Bochkanov Sergey
52824 : *************************************************************************/
52825 0 : static double reviseddualsimplex_initialdualfeasibilitycorrection(dualsimplexstate* state,
52826 : dualsimplexsubproblem* s,
52827 : dualsimplexsettings* settings,
52828 : ae_state *_state)
52829 : {
52830 : ae_frame _frame_block;
52831 : ae_vector dummy;
52832 : ae_int_t nn;
52833 : ae_int_t m;
52834 : ae_int_t ii;
52835 : ae_int_t i;
52836 : ae_int_t j;
52837 : ae_bool flipped;
52838 : double v;
52839 : double dj;
52840 : double xj;
52841 : ae_int_t bndt;
52842 : double result;
52843 :
52844 0 : ae_frame_make(_state, &_frame_block);
52845 0 : memset(&dummy, 0, sizeof(dummy));
52846 0 : ae_vector_init(&dummy, 0, DT_REAL, _state, ae_true);
52847 :
52848 0 : nn = s->ns;
52849 0 : m = s->m;
52850 0 : ae_assert(s->state>=reviseddualsimplex_ssvalidxn, "InitialDualFeasibilityCorrection: XN is invalid", _state);
52851 :
52852 : /*
52853 : * Prepare
52854 : */
52855 0 : rvectorsetlengthatleast(&state->dfctmp0, m, _state);
52856 0 : rvectorsetlengthatleast(&state->dfctmp1, m, _state);
52857 :
52858 : /*
52859 : * Recompute D[] using fresh factorization
52860 : */
52861 0 : reviseddualsimplex_basisfreshtrf(&state->basis, &state->at, settings, _state);
52862 0 : for(i=0; i<=m-1; i++)
52863 : {
52864 0 : state->dfctmp0.ptr.p_double[i] = s->effc.ptr.p_double[state->basis.idx.ptr.p_int[i]];
52865 : }
52866 0 : reviseddualsimplex_basissolvet(&state->basis, &state->dfctmp0, &state->dfctmp1, &state->dfctmp2, _state);
52867 0 : reviseddualsimplex_computeantv(state, &state->dfctmp1, &s->d, _state);
52868 0 : for(i=0; i<=nn-1; i++)
52869 : {
52870 0 : j = state->basis.nidx.ptr.p_int[i];
52871 0 : s->d.ptr.p_double[j] = s->effc.ptr.p_double[j]-s->d.ptr.p_double[j];
52872 : }
52873 :
52874 : /*
52875 : * Perform flips for dual-infeasible boxed variables
52876 : */
52877 0 : result = (double)(0);
52878 0 : flipped = ae_false;
52879 0 : for(ii=0; ii<=nn-1; ii++)
52880 : {
52881 0 : j = state->basis.nidx.ptr.p_int[ii];
52882 0 : bndt = s->bndt.ptr.p_int[j];
52883 :
52884 : /*
52885 : * Boxed variables, perform DFC
52886 : */
52887 0 : if( bndt==reviseddualsimplex_ccrange )
52888 : {
52889 0 : dj = s->d.ptr.p_double[j];
52890 0 : xj = s->xa.ptr.p_double[j];
52891 0 : if( xj==s->bndl.ptr.p_double[j]&&dj<0 )
52892 : {
52893 0 : s->xa.ptr.p_double[j] = s->bndu.ptr.p_double[j];
52894 0 : flipped = ae_true;
52895 0 : continue;
52896 : }
52897 0 : if( xj==s->bndu.ptr.p_double[j]&&dj>0 )
52898 : {
52899 0 : s->xa.ptr.p_double[j] = s->bndl.ptr.p_double[j];
52900 0 : flipped = ae_true;
52901 0 : continue;
52902 : }
52903 0 : continue;
52904 : }
52905 :
52906 : /*
52907 : * Non-boxed variables, compute dual feasibility error
52908 : */
52909 0 : if( bndt==reviseddualsimplex_ccfixed )
52910 : {
52911 0 : continue;
52912 : }
52913 0 : if( bndt==reviseddualsimplex_cclower )
52914 : {
52915 0 : v = -s->d.ptr.p_double[j];
52916 0 : if( v>result )
52917 : {
52918 0 : result = v;
52919 : }
52920 0 : continue;
52921 : }
52922 0 : if( bndt==reviseddualsimplex_ccupper )
52923 : {
52924 0 : v = s->d.ptr.p_double[j];
52925 0 : if( v>result )
52926 : {
52927 0 : result = v;
52928 : }
52929 0 : continue;
52930 : }
52931 0 : if( bndt==reviseddualsimplex_ccfree )
52932 : {
52933 0 : result = ae_maxreal(result, ae_fabs(s->d.ptr.p_double[j], _state), _state);
52934 0 : continue;
52935 : }
52936 : }
52937 :
52938 : /*
52939 : * Recompute basic components of X[]
52940 : */
52941 0 : if( flipped||s->state<reviseddualsimplex_ssvalid )
52942 : {
52943 0 : reviseddualsimplex_computeanxn(state, s, &s->xa, &state->dfctmp0, _state);
52944 0 : reviseddualsimplex_basissolve(&state->basis, &state->dfctmp0, &state->dfctmp1, &state->dfctmp2, _state);
52945 0 : for(i=0; i<=m-1; i++)
52946 : {
52947 0 : s->xa.ptr.p_double[state->basis.idx.ptr.p_int[i]] = -state->dfctmp1.ptr.p_double[i];
52948 : }
52949 : }
52950 :
52951 : /*
52952 : * Update state validity/age
52953 : */
52954 0 : s->state = reviseddualsimplex_ssvalid;
52955 0 : ae_frame_leave(_state);
52956 0 : return result;
52957 : }
52958 :
52959 :
52960 : /*************************************************************************
52961 : This function performs shifting using current algorithm as specified by
52962 : settings.shifting.
52963 :
52964 : It accepts following parameters:
52965 : * AlphaR - pivot row
52966 : * Delta - delta from pricing step
52967 : * Q - variable selected by ratio test
52968 : * AlphaRPiv - pivot element, Q-th element of AlphaR (because alphaR is
52969 : stored in compressed format, we can't extract it easily)
52970 : * ThetaD - dual step length
52971 :
52972 : If no shifts are necessary, it silently returns. If shifts are necessary,
52973 : it modifies ThetaD, S.D, S.EffC according to shifting algorithm.
52974 :
52975 : -- ALGLIB --
52976 : Copyright 19.07.2018 by Bochkanov Sergey
52977 : *************************************************************************/
52978 0 : static void reviseddualsimplex_shifting(dualsimplexstate* state,
52979 : dualsimplexsubproblem* s,
52980 : dssvector* alphar,
52981 : double delta,
52982 : ae_int_t q,
52983 : double alpharpiv,
52984 : double* thetad,
52985 : dualsimplexsettings* settings,
52986 : ae_state *_state)
52987 : {
52988 : ae_int_t dir;
52989 : double sft;
52990 : ae_int_t ii;
52991 : ae_int_t j;
52992 : ae_int_t bndt;
52993 :
52994 :
52995 :
52996 : /*
52997 : * No shifts
52998 : */
52999 0 : if( settings->shifting==0 )
53000 : {
53001 0 : return;
53002 : }
53003 0 : if( q<0 )
53004 : {
53005 0 : return;
53006 : }
53007 :
53008 : /*
53009 : * EXPAND with ThetaD=0
53010 : */
53011 0 : if( settings->shifting==1 )
53012 : {
53013 0 : dir = ae_sign(delta, _state);
53014 0 : if( ae_fp_greater_eq(*thetad*dir,(double)(0)) )
53015 : {
53016 0 : return;
53017 : }
53018 0 : s->effc.ptr.p_double[q] = s->effc.ptr.p_double[q]-s->d.ptr.p_double[q];
53019 0 : s->d.ptr.p_double[q] = (double)(0);
53020 0 : *thetad = (double)(0);
53021 0 : return;
53022 : }
53023 :
53024 : /*
53025 : * EXPAND with ThetaD=ShiftLen
53026 : */
53027 0 : if( settings->shifting==2 )
53028 : {
53029 0 : dir = ae_sign(delta, _state);
53030 0 : if( ae_fp_greater(*thetad*dir,(double)(0)) )
53031 : {
53032 0 : return;
53033 : }
53034 :
53035 : /*
53036 : * Ensure that non-zero step is performed
53037 : */
53038 0 : *thetad = dir*reviseddualsimplex_shiftlen;
53039 :
53040 : /*
53041 : * Shift Q-th coefficient
53042 : */
53043 0 : sft = *thetad*(dir*alpharpiv)-s->d.ptr.p_double[q];
53044 0 : s->effc.ptr.p_double[q] = s->effc.ptr.p_double[q]+sft;
53045 0 : s->d.ptr.p_double[q] = s->d.ptr.p_double[q]+sft;
53046 :
53047 : /*
53048 : * Shift other coefficients
53049 : */
53050 0 : for(ii=0; ii<=alphar->k-1; ii++)
53051 : {
53052 0 : j = alphar->idx.ptr.p_int[ii];
53053 0 : bndt = s->bndt.ptr.p_int[j];
53054 0 : if( (j==q||bndt==reviseddualsimplex_ccfixed)||bndt==reviseddualsimplex_ccfree )
53055 : {
53056 0 : continue;
53057 : }
53058 0 : sft = *thetad*(dir*alphar->vals.ptr.p_double[ii])-s->d.ptr.p_double[j];
53059 :
53060 : /*
53061 : * Handle variables at lower bound
53062 : */
53063 0 : if( bndt==reviseddualsimplex_cclower||(bndt==reviseddualsimplex_ccrange&&s->xa.ptr.p_double[j]==s->bndl.ptr.p_double[j]) )
53064 : {
53065 0 : sft = sft-settings->dtolabs;
53066 0 : if( sft>0 )
53067 : {
53068 0 : s->effc.ptr.p_double[j] = s->effc.ptr.p_double[j]+sft;
53069 0 : s->d.ptr.p_double[j] = s->d.ptr.p_double[j]+sft;
53070 : }
53071 0 : continue;
53072 : }
53073 0 : if( bndt==reviseddualsimplex_ccupper||(bndt==reviseddualsimplex_ccrange&&s->xa.ptr.p_double[j]==s->bndu.ptr.p_double[j]) )
53074 : {
53075 0 : sft = sft+settings->dtolabs;
53076 0 : if( sft<0 )
53077 : {
53078 0 : s->effc.ptr.p_double[j] = s->effc.ptr.p_double[j]+sft;
53079 0 : s->d.ptr.p_double[j] = s->d.ptr.p_double[j]+sft;
53080 : }
53081 0 : continue;
53082 : }
53083 : }
53084 :
53085 : /*
53086 : * Done
53087 : */
53088 0 : return;
53089 : }
53090 0 : ae_assert(ae_false, "Shifting: unexpected shifting type", _state);
53091 : }
53092 :
53093 :
53094 : /*************************************************************************
53095 : This function performs pricing step
53096 :
53097 : Additional parameters:
53098 : * Phase1Pricing - if True, then special Phase #1 restriction is applied to
53099 : leaving variables: only those are eligible which will move to zero bound
53100 : after basis change.
53101 :
53102 : This trick allows to accelerate and stabilize phase #1. See Robert Fourer,
53103 : 'Notes on the dual simplex method', draft report, 1994, for more info.
53104 :
53105 : Returns:
53106 : * leaving variable index P
53107 : * its index R in the basis, in [0,M) range
53108 : * Delta - difference between variable value and corresponding bound
53109 :
53110 : NOTE: this function expects that basic components are stored in XB[];
53111 : corresponding entries of XA[] are ignored.
53112 :
53113 : -- ALGLIB --
53114 : Copyright 19.07.2018 by Bochkanov Sergey
53115 : *************************************************************************/
53116 0 : static void reviseddualsimplex_pricingstep(dualsimplexstate* state,
53117 : dualsimplexsubproblem* s,
53118 : ae_bool phase1pricing,
53119 : ae_int_t* p,
53120 : ae_int_t* r,
53121 : double* delta,
53122 : dualsimplexsettings* settings,
53123 : ae_state *_state)
53124 : {
53125 : ae_int_t m;
53126 : ae_int_t i;
53127 : ae_int_t bi;
53128 : double v;
53129 : double vtarget;
53130 : double xbi;
53131 : double bndl;
53132 : double bndu;
53133 : double vdiff;
53134 : double vtest;
53135 : double invw;
53136 : ae_int_t bndt;
53137 : ae_bool hasboth;
53138 : ae_bool hasl;
53139 : ae_bool hasu;
53140 : ae_int_t t0;
53141 :
53142 0 : *p = 0;
53143 0 : *r = 0;
53144 0 : *delta = 0;
53145 :
53146 0 : m = s->m;
53147 :
53148 : /*
53149 : * Integrity checks
53150 : */
53151 0 : ae_assert(s->state==reviseddualsimplex_ssvalid, "PricingStep: invalid X", _state);
53152 0 : ae_assert(m>0, "PricingStep: M<=0", _state);
53153 :
53154 : /*
53155 : * Timers
53156 : */
53157 0 : t0 = 0;
53158 0 : if( state->dotimers )
53159 : {
53160 0 : t0 = ae_tickcount();
53161 : }
53162 :
53163 : /*
53164 : * Pricing
53165 : */
53166 0 : if( settings->pricing==0 )
53167 : {
53168 :
53169 : /*
53170 : * "Most infeasible" pricing
53171 : */
53172 0 : *p = -1;
53173 0 : *r = -1;
53174 0 : *delta = (double)(0);
53175 0 : vtarget = (double)(0);
53176 0 : for(i=0; i<=m-1; i++)
53177 : {
53178 0 : bndt = s->bndtb.ptr.p_int[i];
53179 0 : hasboth = bndt==3||bndt==0;
53180 0 : hasl = hasboth||bndt==1;
53181 0 : hasu = hasboth||bndt==2;
53182 0 : xbi = s->xb.ptr.p_double[i];
53183 0 : if( hasl )
53184 : {
53185 0 : bndl = s->bndlb.ptr.p_double[i];
53186 0 : vdiff = xbi-bndl;
53187 0 : v = -vdiff;
53188 0 : if( v>s->bndtollb.ptr.p_double[i]&&v>vtarget )
53189 : {
53190 :
53191 : /*
53192 : * Special phase 1 pricing: do not choose variables which move to non-zero bound
53193 : */
53194 0 : if( phase1pricing&&!(bndl==0.0) )
53195 : {
53196 0 : continue;
53197 : }
53198 :
53199 : /*
53200 : * Proceed as usual
53201 : */
53202 0 : *p = state->basis.idx.ptr.p_int[i];
53203 0 : *r = i;
53204 0 : *delta = vdiff;
53205 0 : vtarget = v;
53206 0 : continue;
53207 : }
53208 : }
53209 0 : if( hasu )
53210 : {
53211 0 : bndu = s->bndub.ptr.p_double[i];
53212 0 : vdiff = xbi-bndu;
53213 0 : v = vdiff;
53214 0 : if( v>s->bndtolub.ptr.p_double[i]&&v>vtarget )
53215 : {
53216 :
53217 : /*
53218 : * Special phase 1 pricing: do not choose variables which move to non-zero bound
53219 : */
53220 0 : if( phase1pricing&&!(bndu==0.0) )
53221 : {
53222 0 : continue;
53223 : }
53224 :
53225 : /*
53226 : * Proceed as usual
53227 : */
53228 0 : *p = state->basis.idx.ptr.p_int[i];
53229 0 : *r = i;
53230 0 : *delta = vdiff;
53231 0 : vtarget = v;
53232 0 : continue;
53233 : }
53234 : }
53235 : }
53236 :
53237 : /*
53238 : * Trace/profile
53239 : */
53240 0 : if( state->dotrace )
53241 : {
53242 0 : ae_trace("> pricing: most infeasible variable removed\n");
53243 0 : ae_trace("P = %12d (R=%0d)\n",
53244 0 : (int)(*p),
53245 0 : (int)(*r));
53246 0 : ae_trace("Delta = %12.3e\n",
53247 : (double)(*delta));
53248 : }
53249 0 : if( state->dotimers )
53250 : {
53251 0 : state->repdualpricingtime = state->repdualpricingtime+(ae_tickcount()-t0);
53252 : }
53253 :
53254 : /*
53255 : * Done
53256 : */
53257 0 : return;
53258 : }
53259 0 : if( settings->pricing==-1||settings->pricing==1 )
53260 : {
53261 :
53262 : /*
53263 : * Dual steepest edge pricing
53264 : */
53265 0 : reviseddualsimplex_basisrequestweights(&state->basis, settings, _state);
53266 0 : *p = -1;
53267 0 : *r = -1;
53268 0 : *delta = (double)(0);
53269 0 : vtarget = (double)(0);
53270 0 : for(i=0; i<=m-1; i++)
53271 : {
53272 0 : bi = state->basis.idx.ptr.p_int[i];
53273 0 : bndt = s->bndtb.ptr.p_int[i];
53274 0 : hasboth = bndt==3||bndt==0;
53275 0 : hasl = hasboth||bndt==1;
53276 0 : hasu = hasboth||bndt==2;
53277 0 : xbi = s->xb.ptr.p_double[i];
53278 0 : invw = 1/state->basis.dseweights.ptr.p_double[i];
53279 0 : if( hasl )
53280 : {
53281 0 : bndl = s->bndlb.ptr.p_double[i];
53282 0 : vdiff = xbi-bndl;
53283 0 : vtest = vdiff*vdiff*invw;
53284 0 : if( vdiff<-s->bndtollb.ptr.p_double[i]&&(*p<0||vtest>vtarget) )
53285 : {
53286 :
53287 : /*
53288 : * Special phase 1 pricing: do not choose variables which move to non-zero bound
53289 : */
53290 0 : if( phase1pricing&&!(bndl==0.0) )
53291 : {
53292 0 : continue;
53293 : }
53294 :
53295 : /*
53296 : * Proceed as usual
53297 : */
53298 0 : *p = bi;
53299 0 : *r = i;
53300 0 : *delta = vdiff;
53301 0 : vtarget = vtest;
53302 0 : continue;
53303 : }
53304 : }
53305 0 : if( hasu )
53306 : {
53307 0 : bndu = s->bndub.ptr.p_double[i];
53308 0 : vdiff = xbi-bndu;
53309 0 : vtest = vdiff*vdiff*invw;
53310 0 : if( vdiff>s->bndtolub.ptr.p_double[i]&&(*p<0||vtest>vtarget) )
53311 : {
53312 :
53313 : /*
53314 : * Special phase 1 pricing: do not choose variables which move to non-zero bound
53315 : */
53316 0 : if( phase1pricing&&!(bndu==0.0) )
53317 : {
53318 0 : continue;
53319 : }
53320 :
53321 : /*
53322 : * Proceed as usual
53323 : */
53324 0 : *p = bi;
53325 0 : *r = i;
53326 0 : *delta = vdiff;
53327 0 : vtarget = vtest;
53328 0 : continue;
53329 : }
53330 : }
53331 : }
53332 :
53333 : /*
53334 : * Trace/profile
53335 : */
53336 0 : if( state->dotrace )
53337 : {
53338 0 : ae_trace("> dual steepest edge pricing: leaving variable found\n");
53339 0 : ae_trace("P = %12d (variable index)\n",
53340 0 : (int)(*p));
53341 0 : ae_trace("R = %12d (variable index in basis)\n",
53342 0 : (int)(*r));
53343 0 : ae_trace("Delta = %12.3e (primal infeasibility removed)\n",
53344 : (double)(*delta));
53345 : }
53346 0 : if( state->dotimers )
53347 : {
53348 0 : state->repdualpricingtime = state->repdualpricingtime+(ae_tickcount()-t0);
53349 : }
53350 :
53351 : /*
53352 : * Done
53353 : */
53354 0 : return;
53355 : }
53356 0 : ae_assert(ae_false, "PricingStep: unknown pricing type", _state);
53357 : }
53358 :
53359 :
53360 : /*************************************************************************
53361 : This function performs BTran step
53362 :
53363 : Accepts:
53364 : * R, index of the leaving variable in the basis, in [0,M) range
53365 :
53366 : Returns:
53367 : * RhoR, array[M], BTran result
53368 :
53369 : -- ALGLIB --
53370 : Copyright 19.07.2020 by Bochkanov Sergey
53371 : *************************************************************************/
53372 0 : static void reviseddualsimplex_btranstep(dualsimplexstate* state,
53373 : dualsimplexsubproblem* s,
53374 : ae_int_t r,
53375 : dssvector* rhor,
53376 : dualsimplexsettings* settings,
53377 : ae_state *_state)
53378 : {
53379 : ae_int_t m;
53380 : ae_int_t i;
53381 : ae_int_t t0;
53382 :
53383 :
53384 0 : m = s->m;
53385 :
53386 : /*
53387 : * Integrity checks
53388 : */
53389 0 : ae_assert(m>0, "BTranStep: M<=0", _state);
53390 :
53391 : /*
53392 : * Timers
53393 : */
53394 0 : t0 = 0;
53395 0 : if( state->dotimers )
53396 : {
53397 0 : t0 = ae_tickcount();
53398 : }
53399 :
53400 : /*
53401 : * BTran
53402 : */
53403 0 : rvectorsetlengthatleast(&state->btrantmp0, m, _state);
53404 0 : rvectorsetlengthatleast(&state->btrantmp1, m, _state);
53405 0 : rvectorsetlengthatleast(&state->btrantmp2, m, _state);
53406 0 : for(i=0; i<=m-1; i++)
53407 : {
53408 0 : state->btrantmp0.ptr.p_double[i] = (double)(0);
53409 : }
53410 0 : state->btrantmp0.ptr.p_double[r] = (double)(1);
53411 0 : reviseddualsimplex_dvalloc(rhor, m, _state);
53412 0 : reviseddualsimplex_basissolvet(&state->basis, &state->btrantmp0, &rhor->dense, &state->btrantmp1, _state);
53413 0 : reviseddualsimplex_dvdensetosparse(rhor, _state);
53414 :
53415 : /*
53416 : * Timers
53417 : */
53418 0 : if( state->dotimers )
53419 : {
53420 0 : state->repdualbtrantime = state->repdualbtrantime+(ae_tickcount()-t0);
53421 : }
53422 0 : }
53423 :
53424 :
53425 : /*************************************************************************
53426 : This function performs PivotRow step
53427 :
53428 : Accepts:
53429 : * RhoR, BTRan result
53430 :
53431 : Returns:
53432 : * AlphaR, array[N+M], pivot row
53433 :
53434 : -- ALGLIB --
53435 : Copyright 19.07.2020 by Bochkanov Sergey
53436 : *************************************************************************/
53437 0 : static void reviseddualsimplex_pivotrowstep(dualsimplexstate* state,
53438 : dualsimplexsubproblem* s,
53439 : dssvector* rhor,
53440 : dssvector* alphar,
53441 : dualsimplexsettings* settings,
53442 : ae_state *_state)
53443 : {
53444 : ae_int_t m;
53445 : ae_int_t ns;
53446 : ae_int_t nx;
53447 : ae_int_t i;
53448 : ae_int_t j;
53449 : ae_int_t k;
53450 : ae_int_t jj;
53451 : ae_int_t j0;
53452 : ae_int_t j1;
53453 : ae_int_t alphark;
53454 : double v;
53455 : ae_int_t t0;
53456 : double avgcolwise;
53457 : double avgrowwise;
53458 :
53459 :
53460 0 : m = s->m;
53461 0 : ns = s->ns;
53462 0 : nx = s->ns+s->m;
53463 :
53464 : /*
53465 : * Integrity checks
53466 : */
53467 0 : ae_assert(m>0, "BTranStep: M<=0", _state);
53468 :
53469 : /*
53470 : * Timers
53471 : */
53472 0 : t0 = 0;
53473 0 : if( state->dotimers )
53474 : {
53475 0 : t0 = ae_tickcount();
53476 : }
53477 :
53478 : /*
53479 : * Determine operation counts for columnwise and rowwise approaches
53480 : */
53481 0 : avgrowwise = rhor->k*((double)state->at.ridx.ptr.p_int[nx]/(double)m);
53482 0 : avgcolwise = ns*((double)state->at.ridx.ptr.p_int[nx]/(double)nx);
53483 :
53484 : /*
53485 : * Pivot row
53486 : */
53487 0 : if( ae_fp_less(avgrowwise,avgcolwise) )
53488 : {
53489 :
53490 : /*
53491 : * Use rowwise algorithm
53492 : */
53493 0 : reviseddualsimplex_dvinit(alphar, nx, _state);
53494 0 : for(i=0; i<=rhor->k-1; i++)
53495 : {
53496 0 : k = rhor->idx.ptr.p_int[i];
53497 0 : v = rhor->vals.ptr.p_double[i];
53498 0 : j0 = state->a.ridx.ptr.p_int[k];
53499 0 : j1 = state->a.ridx.ptr.p_int[k+1]-1;
53500 0 : for(j=j0; j<=j1; j++)
53501 : {
53502 0 : jj = state->a.idx.ptr.p_int[j];
53503 0 : alphar->dense.ptr.p_double[jj] = alphar->dense.ptr.p_double[jj]+v*state->a.vals.ptr.p_double[j];
53504 : }
53505 : }
53506 0 : alphark = 0;
53507 0 : for(i=0; i<=nx-1; i++)
53508 : {
53509 0 : if( !state->basis.isbasic.ptr.p_bool[i] )
53510 : {
53511 :
53512 : /*
53513 : * Fetch nonbasic nonzeros to sparse part
53514 : */
53515 0 : v = alphar->dense.ptr.p_double[i];
53516 0 : if( v!=0.0 )
53517 : {
53518 0 : alphar->idx.ptr.p_int[alphark] = i;
53519 0 : alphar->vals.ptr.p_double[alphark] = v;
53520 0 : alphark = alphark+1;
53521 : }
53522 : }
53523 : else
53524 : {
53525 :
53526 : /*
53527 : * Enforce condition that basic elements of AlphaR are exactly zero
53528 : */
53529 0 : alphar->dense.ptr.p_double[i] = (double)(0);
53530 : }
53531 : }
53532 0 : alphar->k = alphark;
53533 : }
53534 : else
53535 : {
53536 :
53537 : /*
53538 : * Use colwise algorithm
53539 : */
53540 0 : reviseddualsimplex_dvalloc(alphar, nx, _state);
53541 0 : alphark = 0;
53542 0 : for(i=0; i<=ns-1; i++)
53543 : {
53544 0 : k = state->basis.nidx.ptr.p_int[i];
53545 0 : j0 = state->at.ridx.ptr.p_int[k];
53546 0 : j1 = state->at.ridx.ptr.p_int[k+1]-1;
53547 0 : v = (double)(0);
53548 0 : for(j=j0; j<=j1; j++)
53549 : {
53550 0 : v = v+state->at.vals.ptr.p_double[j]*rhor->dense.ptr.p_double[state->at.idx.ptr.p_int[j]];
53551 : }
53552 0 : if( v!=0.0 )
53553 : {
53554 0 : alphar->idx.ptr.p_int[alphark] = k;
53555 0 : alphar->vals.ptr.p_double[alphark] = v;
53556 0 : alphark = alphark+1;
53557 : }
53558 : }
53559 0 : alphar->k = alphark;
53560 0 : reviseddualsimplex_dvsparsetodense(alphar, _state);
53561 : }
53562 :
53563 : /*
53564 : * Timers and tracing
53565 : */
53566 0 : if( state->dodetailedtrace )
53567 : {
53568 0 : reviseddualsimplex_updateavgcounter(rhor->k/coalesce((double)(rhor->n), (double)(1), _state), &state->repfillrhor, &state->repfillrhorcnt, _state);
53569 0 : reviseddualsimplex_updateavgcounter(alphar->k/coalesce((double)(alphar->n), (double)(1), _state), &state->repfillpivotrow, &state->repfillpivotrowcnt, _state);
53570 : }
53571 0 : if( state->dotimers )
53572 : {
53573 0 : state->repdualpivotrowtime = state->repdualpivotrowtime+(ae_tickcount()-t0);
53574 : }
53575 0 : }
53576 :
53577 :
53578 : /*************************************************************************
53579 : This function performs FTran step
53580 :
53581 : Accepts:
53582 : * RhoR, array[M]
53583 : * Q, index of the entering variable, in [0,NX) range
53584 :
53585 : Returns:
53586 : * AlphaQ, array[M], FTran result
53587 : * AlphaQim, array[M], intermediate FTran result used by Forest-Tomlin update
53588 : * Tau, array[M], used to compute DSE temporaries
53589 :
53590 : -- ALGLIB --
53591 : Copyright 19.07.2020 by Bochkanov Sergey
53592 : *************************************************************************/
53593 0 : static void reviseddualsimplex_ftranstep(dualsimplexstate* state,
53594 : dualsimplexsubproblem* s,
53595 : dssvector* rhor,
53596 : ae_int_t q,
53597 : /* Real */ ae_vector* alphaq,
53598 : /* Real */ ae_vector* alphaqim,
53599 : /* Real */ ae_vector* tau,
53600 : dualsimplexsettings* settings,
53601 : ae_state *_state)
53602 : {
53603 : ae_int_t m;
53604 : ae_int_t i;
53605 : ae_int_t j;
53606 : ae_int_t j0;
53607 : ae_int_t j1;
53608 : ae_int_t t0;
53609 :
53610 :
53611 0 : m = s->m;
53612 :
53613 : /*
53614 : * Integrity checks
53615 : */
53616 0 : ae_assert(m>0, "BTranStep: M<=0", _state);
53617 :
53618 : /*
53619 : * Timers
53620 : */
53621 0 : t0 = 0;
53622 0 : if( state->dotimers )
53623 : {
53624 0 : t0 = ae_tickcount();
53625 : }
53626 :
53627 : /*
53628 : * FTran
53629 : */
53630 0 : rvectorsetlengthatleast(&state->ftrantmp0, m, _state);
53631 0 : for(i=0; i<=m-1; i++)
53632 : {
53633 0 : state->ftrantmp0.ptr.p_double[i] = (double)(0);
53634 : }
53635 0 : j0 = state->at.ridx.ptr.p_int[q];
53636 0 : j1 = state->at.ridx.ptr.p_int[q+1]-1;
53637 0 : for(j=j0; j<=j1; j++)
53638 : {
53639 0 : state->ftrantmp0.ptr.p_double[state->at.idx.ptr.p_int[j]] = state->at.vals.ptr.p_double[j];
53640 : }
53641 0 : reviseddualsimplex_basissolvex(&state->basis, &state->ftrantmp0, alphaq, alphaqim, ae_true, &state->ftrantmp1, _state);
53642 0 : ae_assert((settings->pricing==-1||settings->pricing==0)||settings->pricing==1, "FTran: unexpected Settings.Pricing", _state);
53643 0 : if( settings->pricing==1 )
53644 : {
53645 0 : reviseddualsimplex_basissolve(&state->basis, &rhor->dense, tau, &state->ftrantmp1, _state);
53646 : }
53647 :
53648 : /*
53649 : * Timers
53650 : */
53651 0 : if( state->dotimers )
53652 : {
53653 0 : state->repdualftrantime = state->repdualftrantime+(ae_tickcount()-t0);
53654 : }
53655 0 : }
53656 :
53657 :
53658 : /*************************************************************************
53659 : This function performs ratio test, either simple one or BFRT.
53660 :
53661 : It accepts following parameters:
53662 : * AlphaR - pivot row
53663 : * Delta - delta from pricing step
53664 : * P - index of leaving variable from pricing step
53665 :
53666 : It returns following results:
53667 : * Q - non-negative value for success, negative for primal infeasible problem
53668 : * AlphaRPiv - AlphaR[Q] (due to AlphaR being stored in sparse format this
53669 : value is difficult to extract by index Q).
53670 : * ThetaD - dual step length
53671 : * PossibleFlips[PossibleFlipsCnt] - for possible flip indexes (for BFRT
53672 : this set coincides with actual flips, but stabilizing BFRT is a bit more
53673 : complex - some variables in PossibleFlips[] may need flipping and some not)
53674 :
53675 : Internally it uses following fields of State for temporaries:
53676 : * EligibleAlphaR
53677 :
53678 : -- ALGLIB --
53679 : Copyright 19.07.2018 by Bochkanov Sergey
53680 : *************************************************************************/
53681 0 : static void reviseddualsimplex_ratiotest(dualsimplexstate* state,
53682 : dualsimplexsubproblem* s,
53683 : dssvector* alphar,
53684 : double delta,
53685 : ae_int_t p,
53686 : ae_int_t* q,
53687 : double* alpharpiv,
53688 : double* thetad,
53689 : /* Integer */ ae_vector* possibleflips,
53690 : ae_int_t* possibleflipscnt,
53691 : dualsimplexsettings* settings,
53692 : ae_state *_state)
53693 : {
53694 : ae_int_t nx;
53695 : ae_int_t j;
53696 : ae_int_t nj;
53697 : ae_int_t dir;
53698 : double vx;
53699 : double vp;
53700 : ae_int_t ej;
53701 : double alpharej;
53702 : double vtarget;
53703 : double vtest;
53704 : ae_int_t eligiblecnt;
53705 : ae_int_t originaleligiblecnt;
53706 : ae_int_t bndt;
53707 : double alphawaver;
53708 : double adelta;
53709 : ae_int_t idx;
53710 : double vtheta;
53711 : ae_int_t t0;
53712 :
53713 0 : *q = 0;
53714 0 : *alpharpiv = 0;
53715 0 : *thetad = 0;
53716 :
53717 0 : nx = s->ns+s->m;
53718 0 : ae_assert(ae_fp_neq(delta,(double)(0)), "RatioTest: zero delta", _state);
53719 0 : ae_assert(s->state==reviseddualsimplex_ssvalid, "RatioTest: invalid X", _state);
53720 :
53721 : /*
53722 : * Timers
53723 : */
53724 0 : t0 = 0;
53725 0 : if( state->dotimers )
53726 : {
53727 0 : t0 = ae_tickcount();
53728 : }
53729 :
53730 : /*
53731 : * Clear output
53732 : */
53733 0 : *q = -1;
53734 0 : *alpharpiv = (double)(0);
53735 0 : *thetad = (double)(0);
53736 0 : *possibleflipscnt = 0;
53737 :
53738 : /*
53739 : * Prepare temporaries
53740 : *
53741 : * Scaled tolerances are used to test AlphaWaveR for positivity/negativity,
53742 : * scale of I-th tolerance is calculated as ratio of ColScale[I] and ColScale[P].
53743 : */
53744 0 : dir = ae_sign(delta, _state);
53745 0 : ivectorsetlengthatleast(possibleflips, nx, _state);
53746 :
53747 : /*
53748 : * Prepare set of eligible variables
53749 : *
53750 : * NOTE: free variables are immediately chosen at this stage
53751 : */
53752 0 : ivectorsetlengthatleast(&state->eligiblealphar, alphar->k, _state);
53753 0 : eligiblecnt = 0;
53754 0 : for(j=0; j<=alphar->k-1; j++)
53755 : {
53756 0 : nj = alphar->idx.ptr.p_int[j];
53757 0 : bndt = s->bndt.ptr.p_int[nj];
53758 :
53759 : /*
53760 : * Handle fixed and free variables: fixed ones are not eligible,
53761 : * free non-basic variables are always and immediately eligible
53762 : */
53763 0 : if( bndt==reviseddualsimplex_ccfixed )
53764 : {
53765 0 : continue;
53766 : }
53767 0 : if( bndt==reviseddualsimplex_ccfree )
53768 : {
53769 0 : *q = nj;
53770 0 : *thetad = (double)(0);
53771 0 : *alpharpiv = alphar->vals.ptr.p_double[j];
53772 0 : if( state->dotrace )
53773 : {
53774 0 : ae_trace("> ratio test: quick exit, found free nonbasic variable\n");
53775 0 : ae_trace("Q = %12d (variable selected)\n",
53776 0 : (int)(*q));
53777 0 : ae_trace("ThetaD = %12.3e (dual step length)\n",
53778 : (double)(*thetad));
53779 : }
53780 0 : if( state->dotimers )
53781 : {
53782 0 : state->repdualratiotesttime = state->repdualratiotesttime+(ae_tickcount()-t0);
53783 : }
53784 0 : return;
53785 : }
53786 :
53787 : /*
53788 : * Handle lower/upper/range constraints
53789 : */
53790 0 : vx = s->xa.ptr.p_double[nj];
53791 0 : vp = settings->pivottol;
53792 0 : alphawaver = dir*alphar->vals.ptr.p_double[j];
53793 0 : if( bndt==reviseddualsimplex_cclower||(bndt==reviseddualsimplex_ccrange&&vx==s->bndl.ptr.p_double[nj]) )
53794 : {
53795 0 : if( alphawaver>vp )
53796 : {
53797 0 : state->eligiblealphar.ptr.p_int[eligiblecnt] = j;
53798 0 : eligiblecnt = eligiblecnt+1;
53799 0 : continue;
53800 : }
53801 : }
53802 0 : if( bndt==reviseddualsimplex_ccupper||(bndt==reviseddualsimplex_ccrange&&vx==s->bndu.ptr.p_double[nj]) )
53803 : {
53804 0 : if( alphawaver<-vp )
53805 : {
53806 0 : state->eligiblealphar.ptr.p_int[eligiblecnt] = j;
53807 0 : eligiblecnt = eligiblecnt+1;
53808 0 : continue;
53809 : }
53810 : }
53811 : }
53812 0 : originaleligiblecnt = eligiblecnt;
53813 :
53814 : /*
53815 : * Simple ratio test.
53816 : */
53817 0 : if( settings->ratiotest==0 )
53818 : {
53819 :
53820 : /*
53821 : * Ratio test
53822 : */
53823 0 : vtarget = (double)(0);
53824 0 : for(j=0; j<=eligiblecnt-1; j++)
53825 : {
53826 0 : ej = state->eligiblealphar.ptr.p_int[j];
53827 0 : nj = alphar->idx.ptr.p_int[ej];
53828 0 : alpharej = alphar->vals.ptr.p_double[ej];
53829 :
53830 : /*
53831 : * More general case
53832 : */
53833 0 : alphawaver = dir*alpharej;
53834 0 : vtest = s->d.ptr.p_double[nj]/alphawaver;
53835 0 : if( *q<0||vtest<vtarget )
53836 : {
53837 0 : *q = nj;
53838 0 : *alpharpiv = alpharej;
53839 0 : vtarget = vtest;
53840 0 : *thetad = s->d.ptr.p_double[nj]/alpharej;
53841 : }
53842 : }
53843 0 : reviseddualsimplex_shifting(state, s, alphar, delta, *q, *alpharpiv, thetad, settings, _state);
53844 :
53845 : /*
53846 : * Trace
53847 : */
53848 0 : if( state->dotrace )
53849 : {
53850 0 : ae_trace("> dual ratio test:\n");
53851 0 : ae_trace("|E| = %12d (eligible set size)\n",
53852 : (int)(originaleligiblecnt));
53853 0 : ae_trace("Q = %12d (variable selected)\n",
53854 0 : (int)(*q));
53855 0 : ae_trace("ThetaD = %12.3e (dual step length)\n",
53856 : (double)(*thetad));
53857 : }
53858 0 : if( state->dotimers )
53859 : {
53860 0 : state->repdualratiotesttime = state->repdualratiotesttime+(ae_tickcount()-t0);
53861 : }
53862 :
53863 : /*
53864 : * Done
53865 : */
53866 0 : return;
53867 : }
53868 :
53869 : /*
53870 : * Bounds flipping ratio test
53871 : */
53872 0 : if( settings->ratiotest==1 )
53873 : {
53874 0 : adelta = ae_fabs(delta, _state);
53875 :
53876 : /*
53877 : * Quick exit
53878 : */
53879 0 : if( eligiblecnt==0 )
53880 : {
53881 0 : if( state->dotrace )
53882 : {
53883 0 : ae_trace("> ratio test: quick exit, no eligible variables\n");
53884 : }
53885 0 : return;
53886 : }
53887 :
53888 : /*
53889 : * BFRT
53890 : */
53891 0 : while(eligiblecnt>0)
53892 : {
53893 :
53894 : /*
53895 : * Find Q satisfying BFRT criteria
53896 : */
53897 0 : idx = -1;
53898 0 : *q = -1;
53899 0 : *alpharpiv = (double)(0);
53900 0 : vtarget = (double)(0);
53901 0 : for(j=0; j<=eligiblecnt-1; j++)
53902 : {
53903 0 : ej = state->eligiblealphar.ptr.p_int[j];
53904 0 : nj = alphar->idx.ptr.p_int[ej];
53905 0 : alpharej = alphar->vals.ptr.p_double[ej];
53906 0 : vtheta = s->d.ptr.p_double[nj]/alpharej;
53907 0 : vtest = dir*vtheta;
53908 0 : if( *q<0||vtest<vtarget )
53909 : {
53910 0 : *q = nj;
53911 0 : *alpharpiv = alpharej;
53912 0 : vtarget = vtest;
53913 0 : *thetad = vtheta;
53914 0 : idx = j;
53915 : }
53916 : }
53917 0 : ae_assert(*q>=0, "RatioTest: integrity check failed (BFRT)", _state);
53918 :
53919 : /*
53920 : * BFRT mini-iterations will be terminated upon discovery
53921 : * of non-boxed variable or upon exhausting of eligible set.
53922 : */
53923 0 : if( s->bndt.ptr.p_int[*q]!=reviseddualsimplex_ccrange )
53924 : {
53925 0 : break;
53926 : }
53927 0 : if( eligiblecnt==1 )
53928 : {
53929 0 : break;
53930 : }
53931 :
53932 : /*
53933 : * Update and test ADelta. Break BFRT mini-iterations once
53934 : * we get negative slope.
53935 : */
53936 0 : adelta = adelta-(s->bndu.ptr.p_double[*q]-s->bndl.ptr.p_double[*q])*ae_fabs(*alpharpiv, _state);
53937 0 : if( ae_fp_less_eq(adelta,(double)(0)) )
53938 : {
53939 0 : break;
53940 : }
53941 :
53942 : /*
53943 : * Update eligible set, record flip
53944 : */
53945 0 : possibleflips->ptr.p_int[*possibleflipscnt] = state->eligiblealphar.ptr.p_int[idx];
53946 0 : *possibleflipscnt = *possibleflipscnt+1;
53947 0 : state->eligiblealphar.ptr.p_int[idx] = state->eligiblealphar.ptr.p_int[eligiblecnt-1];
53948 0 : eligiblecnt = eligiblecnt-1;
53949 : }
53950 0 : ae_assert(*q>=0, "RatioTest: unexpected failure", _state);
53951 0 : *thetad = s->d.ptr.p_double[*q]/(*alpharpiv);
53952 0 : reviseddualsimplex_shifting(state, s, alphar, delta, *q, *alpharpiv, thetad, settings, _state);
53953 :
53954 : /*
53955 : * Trace
53956 : */
53957 0 : if( state->dotrace )
53958 : {
53959 0 : ae_trace("> dual bounds flipping ratio test:\n");
53960 0 : ae_trace("|E| = %12d (eligible set size)\n",
53961 : (int)(originaleligiblecnt));
53962 0 : ae_trace("Q = %12d (variable selected)\n",
53963 0 : (int)(*q));
53964 0 : ae_trace("ThetaD = %12.3e (dual step length)\n",
53965 : (double)(*thetad));
53966 0 : ae_trace("Flips = %12d (possible bound flips)\n",
53967 0 : (int)(state->possibleflipscnt));
53968 : }
53969 0 : if( state->dotimers )
53970 : {
53971 0 : state->repdualratiotesttime = state->repdualratiotesttime+(ae_tickcount()-t0);
53972 : }
53973 :
53974 : /*
53975 : * Done
53976 : */
53977 0 : return;
53978 : }
53979 :
53980 : /*
53981 : * Unknown test type
53982 : */
53983 0 : ae_assert(ae_false, "RatioTest: integrity check failed, unknown test type", _state);
53984 : }
53985 :
53986 :
53987 : /*************************************************************************
53988 : This function performs update of XB, XN, D and Z during final step of revised
53989 : dual simplex method.
53990 :
53991 : It also updates basis cache of the subproblem (s.bcache field).
53992 :
53993 : Depending on Settings.RatioTest, following operations are performed:
53994 : * Settings.RatioTest=0 -> simple update is performed
53995 : * Settings.RatioTest=1 -> bounds flipping ratio test update is performed
53996 : * Settings.RatioTest=2 -> stabilizing bounds flipping ratio test update is performed
53997 :
53998 : It accepts following parameters:
53999 : * P - index of leaving variable from pricing step
54000 : * Q - index of entering variable.
54001 : * R - index of leaving variable in AlphaQ
54002 : * Delta - delta from pricing step
54003 : * AlphaPiv - pivot element (in absence of numerical rounding it is AlphaR[Q]=AlphaQ[R])
54004 : * ThetaP - primal step length
54005 : * ThetaD - dual step length
54006 : * AlphaQ - pivot column
54007 : * AlphaQim - intermediate result from Ftran for AlphaQ, used for
54008 : Forest-Tomlin update, not referenced when other update scheme is set
54009 : * AlphaR - pivot row
54010 : * Tau - tau-vector for DSE pricing (ignored if simple pricing is used)
54011 : * PossibleAlphaRFlips, PossibleAlphaRFlipsCnt - outputs of the RatioTest()
54012 : information about possible variable flips - indexes of AlphaR positions
54013 : which are considered for flipping due to BFRT (however, we have to check
54014 : residual costs before actually flipping variables - it is possible that some variables
54015 : in this set actually do not need flipping)
54016 :
54017 : It performs following operations:
54018 : * basis update
54019 : * update of XB/BndTB/BndLB/BndUB[] and XA[] (basic and nonbasic components), D
54020 : * update of pricing weights
54021 :
54022 : -- ALGLIB --
54023 : Copyright 19.07.2018 by Bochkanov Sergey
54024 : *************************************************************************/
54025 0 : static void reviseddualsimplex_updatestep(dualsimplexstate* state,
54026 : dualsimplexsubproblem* s,
54027 : ae_int_t p,
54028 : ae_int_t q,
54029 : ae_int_t r,
54030 : double delta,
54031 : double alphapiv,
54032 : double thetap,
54033 : double thetad,
54034 : /* Real */ ae_vector* alphaq,
54035 : /* Real */ ae_vector* alphaqim,
54036 : dssvector* alphar,
54037 : /* Real */ ae_vector* tau,
54038 : /* Integer */ ae_vector* possiblealpharflips,
54039 : ae_int_t possiblealpharflipscnt,
54040 : dualsimplexsettings* settings,
54041 : ae_state *_state)
54042 : {
54043 : ae_int_t nx;
54044 : ae_int_t m;
54045 : ae_int_t ii;
54046 : ae_int_t j;
54047 : ae_int_t k;
54048 : ae_int_t aj;
54049 : ae_int_t k0;
54050 : ae_int_t k1;
54051 : double bndl;
54052 : double bndu;
54053 : ae_bool flipped;
54054 : double flip;
54055 : double dj;
54056 : ae_int_t dir;
54057 : ae_int_t idx;
54058 : ae_int_t actualflipscnt;
54059 : ae_int_t t0;
54060 : ae_int_t alpharlen;
54061 :
54062 :
54063 0 : nx = s->ns+s->m;
54064 0 : m = s->m;
54065 :
54066 : /*
54067 : * Integrity checks
54068 : */
54069 0 : ae_assert((settings->ratiotest==0||settings->ratiotest==1)||settings->ratiotest==2, "UpdateStep: invalid X", _state);
54070 0 : ae_assert(s->state==reviseddualsimplex_ssvalid, "UpdateStep: invalid X", _state);
54071 0 : ae_assert(p>=0&&q>=0, "UpdateStep: invalid P/Q", _state);
54072 0 : ae_assert(ae_fp_neq(delta,(double)(0)), "UpdateStep: Delta=0", _state);
54073 0 : ae_assert(ae_fp_neq(alphapiv,(double)(0)), "UpdateStep: AlphaPiv=0", _state);
54074 :
54075 : /*
54076 : * Timers
54077 : */
54078 0 : t0 = 0;
54079 0 : if( state->dotimers )
54080 : {
54081 0 : t0 = ae_tickcount();
54082 : }
54083 :
54084 : /*
54085 : * Prepare
54086 : */
54087 0 : dir = ae_sign(delta, _state);
54088 0 : alpharlen = alphar->k;
54089 0 : flip = (double)(0);
54090 0 : rvectorsetlengthatleast(&state->tmp0, m, _state);
54091 0 : for(k=0; k<=m-1; k++)
54092 : {
54093 0 : state->tmp0.ptr.p_double[k] = (double)(0);
54094 : }
54095 0 : ivectorsetlengthatleast(&state->ustmpi, nx, _state);
54096 0 : actualflipscnt = 0;
54097 :
54098 : /*
54099 : * Evaluate and update non-basic elements of D
54100 : */
54101 0 : for(ii=0; ii<=alpharlen-1; ii++)
54102 : {
54103 0 : j = alphar->idx.ptr.p_int[ii];
54104 0 : s->d.ptr.p_double[j] = s->d.ptr.p_double[j]-thetad*alphar->vals.ptr.p_double[ii];
54105 : }
54106 0 : for(ii=0; ii<=possiblealpharflipscnt-1; ii++)
54107 : {
54108 0 : aj = possiblealpharflips->ptr.p_int[ii];
54109 0 : j = alphar->idx.ptr.p_int[aj];
54110 0 : dj = s->d.ptr.p_double[j];
54111 0 : bndl = s->bndl.ptr.p_double[j];
54112 0 : bndu = s->bndu.ptr.p_double[j];
54113 0 : flipped = ae_false;
54114 0 : if( s->xa.ptr.p_double[j]==bndl&&dj<0 )
54115 : {
54116 0 : flip = bndu-bndl;
54117 0 : flipped = ae_true;
54118 : }
54119 : else
54120 : {
54121 0 : if( s->xa.ptr.p_double[j]==bndu&&dj>0 )
54122 : {
54123 0 : flip = bndl-bndu;
54124 0 : flipped = ae_true;
54125 : }
54126 : }
54127 0 : if( flipped )
54128 : {
54129 0 : delta = delta-dir*(bndu-bndl)*ae_fabs(alphar->vals.ptr.p_double[aj], _state);
54130 0 : state->ustmpi.ptr.p_int[actualflipscnt] = j;
54131 0 : actualflipscnt = actualflipscnt+1;
54132 0 : k0 = state->at.ridx.ptr.p_int[j];
54133 0 : k1 = state->at.ridx.ptr.p_int[j+1]-1;
54134 0 : for(k=k0; k<=k1; k++)
54135 : {
54136 0 : idx = state->at.idx.ptr.p_int[k];
54137 0 : state->tmp0.ptr.p_double[idx] = state->tmp0.ptr.p_double[idx]+flip*state->at.vals.ptr.p_double[k];
54138 : }
54139 : }
54140 : }
54141 0 : s->d.ptr.p_double[p] = -thetad;
54142 0 : s->d.ptr.p_double[q] = 0.0;
54143 :
54144 : /*
54145 : * Apply BFRT update (aka long dual step) or simple ratio update
54146 : */
54147 0 : if( actualflipscnt>0 )
54148 : {
54149 0 : thetap = delta/alphapiv;
54150 0 : k0 = state->at.ridx.ptr.p_int[q];
54151 0 : k1 = state->at.ridx.ptr.p_int[q+1]-1;
54152 0 : for(k=k0; k<=k1; k++)
54153 : {
54154 0 : idx = state->at.idx.ptr.p_int[k];
54155 0 : state->tmp0.ptr.p_double[idx] = state->tmp0.ptr.p_double[idx]+thetap*state->at.vals.ptr.p_double[k];
54156 : }
54157 0 : reviseddualsimplex_basissolve(&state->basis, &state->tmp0, &state->tmp1, &state->tmp2, _state);
54158 0 : for(j=0; j<=m-1; j++)
54159 : {
54160 0 : s->xb.ptr.p_double[j] = s->xb.ptr.p_double[j]-state->tmp1.ptr.p_double[j];
54161 : }
54162 0 : for(ii=0; ii<=actualflipscnt-1; ii++)
54163 : {
54164 0 : j = state->ustmpi.ptr.p_int[ii];
54165 0 : if( s->xa.ptr.p_double[j]==s->bndl.ptr.p_double[j] )
54166 : {
54167 0 : s->xa.ptr.p_double[j] = s->bndu.ptr.p_double[j];
54168 : }
54169 : else
54170 : {
54171 0 : s->xa.ptr.p_double[j] = s->bndl.ptr.p_double[j];
54172 : }
54173 : }
54174 0 : s->xb.ptr.p_double[r] = s->xa.ptr.p_double[q]+thetap;
54175 0 : if( dir<0 )
54176 : {
54177 0 : s->xa.ptr.p_double[p] = s->bndl.ptr.p_double[p];
54178 : }
54179 : else
54180 : {
54181 0 : s->xa.ptr.p_double[p] = s->bndu.ptr.p_double[p];
54182 : }
54183 : }
54184 : else
54185 : {
54186 0 : for(j=0; j<=m-1; j++)
54187 : {
54188 0 : s->xb.ptr.p_double[j] = s->xb.ptr.p_double[j]-thetap*alphaq->ptr.p_double[j];
54189 : }
54190 0 : s->xb.ptr.p_double[r] = s->xa.ptr.p_double[q]+thetap;
54191 0 : if( dir<0 )
54192 : {
54193 0 : s->xa.ptr.p_double[p] = s->bndl.ptr.p_double[p];
54194 : }
54195 : else
54196 : {
54197 0 : s->xa.ptr.p_double[p] = s->bndu.ptr.p_double[p];
54198 : }
54199 : }
54200 :
54201 : /*
54202 : * Update basis
54203 : */
54204 0 : reviseddualsimplex_basisupdatetrf(&state->basis, &state->at, p, q, alphaq, alphaqim, r, tau, settings, _state);
54205 :
54206 : /*
54207 : * Update cached variables
54208 : */
54209 0 : reviseddualsimplex_cacheboundinfo(s, r, q, settings, _state);
54210 :
54211 : /*
54212 : * Tracing and timers
54213 : */
54214 0 : if( state->dodetailedtrace )
54215 : {
54216 0 : if( state->basis.trftype==3 )
54217 : {
54218 0 : reviseddualsimplex_updateavgcounter(reviseddualsimplex_sparsityof(&state->basis.densemu, state->basis.trfage*m, _state), &state->repfilldensemu, &state->repfilldensemucnt, _state);
54219 : }
54220 : }
54221 0 : if( state->dotimers )
54222 : {
54223 0 : state->repdualupdatesteptime = state->repdualupdatesteptime+(ae_tickcount()-t0);
54224 : }
54225 0 : }
54226 :
54227 :
54228 : /*************************************************************************
54229 : This function performs several checks for accumulation of errors during
54230 : factorization update. It returns True if refactorization is advised.
54231 :
54232 : -- ALGLIB --
54233 : Copyright 24.01.2019 by Bochkanov Sergey
54234 : *************************************************************************/
54235 0 : static ae_bool reviseddualsimplex_refactorizationrequired(dualsimplexstate* state,
54236 : dualsimplexsubproblem* s,
54237 : ae_int_t q,
54238 : double alpharpiv,
54239 : ae_int_t r,
54240 : double alphaqpiv,
54241 : ae_state *_state)
54242 : {
54243 : ae_int_t m;
54244 : ae_int_t i;
54245 : double mx;
54246 : double v;
54247 : ae_bool result;
54248 :
54249 :
54250 0 : m = s->m;
54251 0 : result = ae_false;
54252 :
54253 : /*
54254 : * Quick exit
54255 : */
54256 0 : if( state->basis.trfage<=reviseddualsimplex_safetrfage )
54257 : {
54258 0 : return result;
54259 : }
54260 :
54261 : /*
54262 : * Compare Q-th entry of the pivot row AlphaR with R-th entry of the AlphaQ;
54263 : * ideally, both should match exactly. The difference is a rough estimate
54264 : * of the magnitude of the numerical errors.
54265 : */
54266 0 : mx = 0.0;
54267 0 : for(i=0; i<=m-1; i++)
54268 : {
54269 0 : v = state->alphaq.ptr.p_double[i];
54270 0 : v = v*v;
54271 0 : if( v>mx )
54272 : {
54273 0 : mx = v;
54274 : }
54275 : }
54276 0 : mx = ae_sqrt(mx, _state);
54277 0 : result = result||ae_fp_greater(ae_fabs(alphaqpiv-alpharpiv, _state),reviseddualsimplex_alphatrigger*(1.0+mx));
54278 0 : result = result||ae_fp_greater(ae_fabs(alphaqpiv-alpharpiv, _state),reviseddualsimplex_alphatrigger2*ae_fabs(alpharpiv, _state));
54279 0 : return result;
54280 : }
54281 :
54282 :
54283 : /*************************************************************************
54284 : This function caches information for I-th column of the basis, which is
54285 : assumed to store variable K:
54286 : * lower bound in S.BndLB[I]=S.BndL[K]
54287 : * upper bound in S.BndUB[I]=S.BndU[K]
54288 : * bound type in S.BndTB[I]=S.BndT[K]
54289 : * lower bound primal error tolerance in S.BndTolLB[I] (nonnegative)
54290 : * upper bound primal error tolerance in S.BndTolLB[I] (nonnegative).
54291 :
54292 : -- ALGLIB --
54293 : Copyright 18.07.2020 by Bochkanov Sergey
54294 : *************************************************************************/
54295 0 : static void reviseddualsimplex_cacheboundinfo(dualsimplexsubproblem* s,
54296 : ae_int_t i,
54297 : ae_int_t k,
54298 : dualsimplexsettings* settings,
54299 : ae_state *_state)
54300 : {
54301 :
54302 :
54303 0 : s->bndlb.ptr.p_double[i] = s->bndl.ptr.p_double[k];
54304 0 : s->bndub.ptr.p_double[i] = s->bndu.ptr.p_double[k];
54305 0 : s->bndtb.ptr.p_int[i] = s->bndt.ptr.p_int[k];
54306 0 : s->bndtollb.ptr.p_double[i] = settings->xtolabs+settings->xtolrelabs*settings->xtolabs*ae_fabs(s->bndlb.ptr.p_double[i], _state);
54307 0 : s->bndtolub.ptr.p_double[i] = settings->xtolabs+settings->xtolrelabs*settings->xtolabs*ae_fabs(s->bndub.ptr.p_double[i], _state);
54308 0 : }
54309 :
54310 :
54311 : /*************************************************************************
54312 : This function performs actual solution of dual simplex subproblem (either
54313 : primary one or phase 1 one).
54314 :
54315 : A problem with following properties is expected:
54316 : * M>0
54317 : * feasible box constraints
54318 : * dual feasible initial basis
54319 : * actual initial point XC and target value Z
54320 : * actual reduced cost vector D
54321 : * pricing weights being set to 1.0 or copied from previous problem
54322 :
54323 : Returns:
54324 : * Info = +1 for success, -3 for infeasible
54325 : * IterationsCount is increased by amount of iterations performed
54326 :
54327 : NOTE: this function internally uses separate storage of basic and nonbasic
54328 : components; however, all inputs and outputs use single array S.XA[]
54329 : to store both basic and nonbasic variables. It transparently splits
54330 : variables on input and recombines them on output.
54331 :
54332 : -- ALGLIB --
54333 : Copyright 19.07.2018 by Bochkanov Sergey
54334 : *************************************************************************/
54335 0 : static void reviseddualsimplex_solvesubproblemdual(dualsimplexstate* state,
54336 : dualsimplexsubproblem* s,
54337 : ae_bool isphase1,
54338 : dualsimplexsettings* settings,
54339 : ae_int_t* info,
54340 : ae_state *_state)
54341 : {
54342 : ae_int_t nx;
54343 : ae_int_t m;
54344 : ae_int_t i;
54345 : ae_int_t p;
54346 : ae_int_t r;
54347 : ae_int_t q;
54348 : double alpharpiv;
54349 : double alphaqpiv;
54350 : double thetad;
54351 : double thetap;
54352 : double delta;
54353 : ae_int_t forcedrestarts;
54354 :
54355 0 : *info = 0;
54356 :
54357 0 : nx = s->ns+s->m;
54358 0 : m = s->m;
54359 0 : forcedrestarts = 0;
54360 :
54361 : /*
54362 : * Integrity checks
54363 : */
54364 0 : ae_assert(s->state==reviseddualsimplex_ssvalid, "SolveSubproblemDual: X is not valid", _state);
54365 0 : ae_assert(m>0, "SolveSubproblemDual: M<=0", _state);
54366 0 : for(i=0; i<=nx-1; i++)
54367 : {
54368 0 : ae_assert(s->bndt.ptr.p_int[i]!=reviseddualsimplex_ccinfeasible, "SolveSubproblemDual: infeasible box constraints", _state);
54369 : }
54370 0 : ae_assert(reviseddualsimplex_isdualfeasible(state, s, settings, _state), "SolveSubproblemDual: dual infeasible initial basis", _state);
54371 :
54372 : /*
54373 : * Actual processing
54374 : */
54375 0 : reviseddualsimplex_offloadbasiccomponents(s, &state->basis, settings, _state);
54376 0 : *info = 0;
54377 0 : rvectorsetlengthatleast(&state->tmp0, m, _state);
54378 : for(;;)
54379 : {
54380 :
54381 : /*
54382 : * Iteration report
54383 : */
54384 0 : if( state->dotrace )
54385 : {
54386 0 : i = state->repiterationscount2;
54387 0 : if( isphase1 )
54388 : {
54389 0 : i = state->repiterationscount1;
54390 : }
54391 0 : ae_trace("=== ITERATION %5d STARTED ========================================================================\n",
54392 : (int)(i));
54393 0 : if( state->dodetailedtrace )
54394 : {
54395 : }
54396 : }
54397 :
54398 : /*
54399 : * Pricing
54400 : */
54401 0 : reviseddualsimplex_pricingstep(state, s, isphase1, &p, &r, &delta, settings, _state);
54402 0 : if( ae_fp_eq(delta,(double)(0)) )
54403 : {
54404 :
54405 : /*
54406 : * Solved! Feasible and bounded!
54407 : */
54408 0 : if( state->dotrace )
54409 : {
54410 0 : ae_trace("> pricing: feasible point found\n");
54411 : }
54412 0 : reviseddualsimplex_recombinebasicnonbasicx(s, &state->basis, _state);
54413 0 : *info = 1;
54414 0 : return;
54415 : }
54416 :
54417 : /*
54418 : * BTran
54419 : */
54420 0 : reviseddualsimplex_btranstep(state, s, r, &state->rhor, settings, _state);
54421 :
54422 : /*
54423 : * Pivot row
54424 : */
54425 0 : reviseddualsimplex_pivotrowstep(state, s, &state->rhor, &state->alphar, settings, _state);
54426 :
54427 : /*
54428 : * Ratio test
54429 : */
54430 0 : reviseddualsimplex_ratiotest(state, s, &state->alphar, delta, p, &q, &alpharpiv, &thetad, &state->possibleflips, &state->possibleflipscnt, settings, _state);
54431 0 : if( q<0 )
54432 : {
54433 :
54434 : /*
54435 : * Do we have fresh factorization and state? If not,
54436 : * refresh them prior to declaring that we have no solution.
54437 : */
54438 0 : if( state->basis.trfage>0&&forcedrestarts<reviseddualsimplex_maxforcedrestarts )
54439 : {
54440 0 : if( state->dotrace )
54441 : {
54442 0 : ae_trace("> ratio test: failed, basis is old (age=%0d), forcing restart (%0d of %0d)\n",
54443 0 : (int)(state->basis.trfage),
54444 : (int)(forcedrestarts),
54445 0 : (int)(reviseddualsimplex_maxforcedrestarts-1));
54446 : }
54447 0 : reviseddualsimplex_basisfreshtrf(&state->basis, &state->at, settings, _state);
54448 0 : reviseddualsimplex_subproblemhandlexnupdate(state, s, _state);
54449 0 : reviseddualsimplex_offloadbasiccomponents(s, &state->basis, settings, _state);
54450 0 : inc(&forcedrestarts, _state);
54451 0 : continue;
54452 : }
54453 :
54454 : /*
54455 : * Dual unbounded, primal infeasible
54456 : */
54457 0 : if( state->dotrace )
54458 : {
54459 0 : ae_trace("> ratio test: failed, results are accepted\n");
54460 : }
54461 0 : reviseddualsimplex_recombinebasicnonbasicx(s, &state->basis, _state);
54462 0 : *info = -3;
54463 0 : return;
54464 : }
54465 0 : thetap = delta/alpharpiv;
54466 :
54467 : /*
54468 : * FTran, including additional FTran for DSE weights (if needed)
54469 : *
54470 : * NOTE: AlphaQim is filled by intermediate FTran result which is useful
54471 : * for Forest-Tomlin update scheme. If not Forest-Tomlin update is
54472 : * used, then it is not set.
54473 : */
54474 0 : reviseddualsimplex_ftranstep(state, s, &state->rhor, q, &state->alphaq, &state->alphaqim, &state->tau, settings, _state);
54475 0 : alphaqpiv = state->alphaq.ptr.p_double[r];
54476 :
54477 : /*
54478 : * Check numerical accuracy, trigger refactorization if needed
54479 : */
54480 0 : if( reviseddualsimplex_refactorizationrequired(state, s, q, alpharpiv, r, alphaqpiv, _state) )
54481 : {
54482 0 : if( state->dotrace )
54483 : {
54484 0 : ae_trace("> refactorization test: numerical errors are too large, forcing refactorization and restart\n");
54485 : }
54486 0 : reviseddualsimplex_basisfreshtrf(&state->basis, &state->at, settings, _state);
54487 0 : reviseddualsimplex_subproblemhandlexnupdate(state, s, _state);
54488 0 : reviseddualsimplex_offloadbasiccomponents(s, &state->basis, settings, _state);
54489 0 : continue;
54490 : }
54491 :
54492 : /*
54493 : * Basis change and update
54494 : */
54495 0 : reviseddualsimplex_updatestep(state, s, p, q, r, delta, alpharpiv, thetap, thetad, &state->alphaq, &state->alphaqim, &state->alphar, &state->tau, &state->possibleflips, state->possibleflipscnt, settings, _state);
54496 0 : inc(&state->repiterationscount, _state);
54497 0 : if( isphase1 )
54498 : {
54499 0 : inc(&state->repiterationscount1, _state);
54500 : }
54501 : else
54502 : {
54503 0 : inc(&state->repiterationscount2, _state);
54504 : }
54505 : }
54506 : }
54507 :
54508 :
54509 : /*************************************************************************
54510 : This function solves simplex subproblem using primal simplex method.
54511 :
54512 : A problem with following properties is expected:
54513 : * M>0
54514 : * feasible box constraints
54515 : * primal feasible initial basis
54516 : * actual initial point XC and target value Z
54517 : * actual reduced cost vector D
54518 : * pricing weights being set to 1.0 or copied from previous problem
54519 :
54520 : Returns:
54521 : * Info = +1 for success, -3 for infeasible
54522 : * IterationsCount is increased by amount of iterations performed
54523 :
54524 : -- ALGLIB --
54525 : Copyright 19.07.2018 by Bochkanov Sergey
54526 : *************************************************************************/
54527 0 : static void reviseddualsimplex_solvesubproblemprimal(dualsimplexstate* state,
54528 : dualsimplexsubproblem* s,
54529 : dualsimplexsettings* settings,
54530 : ae_int_t* info,
54531 : ae_state *_state)
54532 : {
54533 : ae_int_t nn;
54534 : ae_int_t nx;
54535 : ae_int_t m;
54536 : ae_int_t i;
54537 : ae_int_t j;
54538 : double v;
54539 : double vmax;
54540 : ae_int_t bi;
54541 : double dj;
54542 : ae_int_t bndt;
54543 : ae_int_t q;
54544 : ae_int_t p;
54545 : ae_int_t r;
54546 : ae_int_t dir;
54547 : double lim;
54548 : ae_bool haslim;
54549 : double thetap;
54550 : double xbnd;
54551 : double flip;
54552 : ae_int_t canddir;
54553 : double candlim;
54554 : double candflip;
54555 : ae_int_t j0;
54556 : ae_int_t j1;
54557 : double alphawave;
54558 : double vp;
54559 : double vb;
54560 : double vx;
54561 : double vtest;
54562 : double vv;
54563 :
54564 0 : *info = 0;
54565 :
54566 0 : nn = s->ns;
54567 0 : nx = s->ns+s->m;
54568 0 : m = s->m;
54569 :
54570 : /*
54571 : * Integrity checks
54572 : */
54573 0 : ae_assert(s->state==reviseddualsimplex_ssvalid, "SolveSubproblemPrimal: X is not valid", _state);
54574 0 : ae_assert(m>0, "SolveSubproblemPrimal: M<=0", _state);
54575 0 : for(i=0; i<=nx-1; i++)
54576 : {
54577 0 : ae_assert(s->bndt.ptr.p_int[i]!=reviseddualsimplex_ccinfeasible, "SolveSubproblemPrimal: infeasible box constraints", _state);
54578 : }
54579 :
54580 : /*
54581 : * Actual processing
54582 : */
54583 0 : *info = 1;
54584 0 : rvectorsetlengthatleast(&state->tmp0, m, _state);
54585 : for(;;)
54586 : {
54587 :
54588 : /*
54589 : * Iteration report
54590 : */
54591 0 : if( state->dotrace )
54592 : {
54593 0 : i = state->repiterationscount3;
54594 0 : ae_trace("=== ITERATION %5d STARTED ========================================================================\n",
54595 : (int)(i));
54596 0 : if( state->dodetailedtrace )
54597 : {
54598 : }
54599 : }
54600 :
54601 : /*
54602 : * Primal simplex pricing step: we implement the very basic version
54603 : * of the pricing step because it is expected that primal simplex method
54604 : * is used just to apply quick correction after removal of the perturbation.
54605 : */
54606 0 : q = -1;
54607 0 : vmax = (double)(0);
54608 0 : dir = 0;
54609 0 : lim = ae_maxrealnumber;
54610 0 : haslim = ae_false;
54611 0 : flip = (double)(0);
54612 0 : canddir = 0;
54613 0 : for(i=0; i<=nn-1; i++)
54614 : {
54615 0 : j = state->basis.nidx.ptr.p_int[i];
54616 0 : dj = s->d.ptr.p_double[j];
54617 0 : bndt = s->bndt.ptr.p_int[j];
54618 0 : if( bndt==reviseddualsimplex_ccfixed )
54619 : {
54620 0 : continue;
54621 : }
54622 0 : if( bndt==reviseddualsimplex_ccrange )
54623 : {
54624 0 : v = (double)(0);
54625 0 : candlim = s->bndu.ptr.p_double[j]-s->bndl.ptr.p_double[j];
54626 0 : candflip = (double)(0);
54627 0 : if( s->xa.ptr.p_double[j]==s->bndl.ptr.p_double[j] )
54628 : {
54629 0 : v = -dj;
54630 0 : canddir = 1;
54631 0 : candflip = s->bndu.ptr.p_double[j];
54632 : }
54633 0 : if( s->xa.ptr.p_double[j]==s->bndu.ptr.p_double[j] )
54634 : {
54635 0 : v = dj;
54636 0 : canddir = -1;
54637 0 : candflip = s->bndl.ptr.p_double[j];
54638 : }
54639 0 : if( v>vmax )
54640 : {
54641 0 : vmax = v;
54642 0 : dir = canddir;
54643 0 : lim = candlim;
54644 0 : haslim = ae_true;
54645 0 : flip = candflip;
54646 0 : q = j;
54647 : }
54648 0 : continue;
54649 : }
54650 0 : v = (double)(0);
54651 0 : canddir = 0;
54652 0 : if( bndt==reviseddualsimplex_cclower )
54653 : {
54654 0 : v = -dj;
54655 0 : canddir = 1;
54656 : }
54657 0 : if( bndt==reviseddualsimplex_ccupper )
54658 : {
54659 0 : v = dj;
54660 0 : canddir = -1;
54661 : }
54662 0 : if( bndt==reviseddualsimplex_ccfree )
54663 : {
54664 0 : v = ae_fabs(dj, _state);
54665 0 : canddir = -ae_sign(dj, _state);
54666 : }
54667 0 : if( v>vmax )
54668 : {
54669 0 : vmax = v;
54670 0 : dir = canddir;
54671 0 : lim = ae_maxrealnumber;
54672 0 : haslim = ae_false;
54673 0 : q = j;
54674 : }
54675 0 : continue;
54676 : }
54677 0 : if( vmax<=settings->dtolabs )
54678 : {
54679 :
54680 : /*
54681 : * Solved: primal and dual feasible!
54682 : */
54683 0 : if( state->dotrace )
54684 : {
54685 0 : ae_trace("> primal pricing: feasible point found\n");
54686 : }
54687 0 : return;
54688 : }
54689 0 : ae_assert(q>=0, "SolveSubproblemPrimal: integrity check failed", _state);
54690 0 : if( state->dotrace )
54691 : {
54692 0 : ae_trace("> primal pricing: found entering variable\n");
54693 0 : ae_trace("Q = %12d (variable selected)\n",
54694 : (int)(q));
54695 0 : ae_trace("|D| = %12.3e (dual infeasibility)\n",
54696 : (double)(vmax));
54697 : }
54698 :
54699 : /*
54700 : * FTran and textbook ratio test (again, we expect primal phase to terminate quickly)
54701 : *
54702 : * NOTE: AlphaQim is filled by intermediate FTran result which is useful
54703 : * for Forest-Tomlin update scheme. If not Forest-Tomlin update is
54704 : * used, then it is not set.
54705 : */
54706 0 : for(i=0; i<=m-1; i++)
54707 : {
54708 0 : state->tmp0.ptr.p_double[i] = (double)(0);
54709 : }
54710 0 : j0 = state->at.ridx.ptr.p_int[q];
54711 0 : j1 = state->at.ridx.ptr.p_int[q+1]-1;
54712 0 : for(j=j0; j<=j1; j++)
54713 : {
54714 0 : state->tmp0.ptr.p_double[state->at.idx.ptr.p_int[j]] = state->at.vals.ptr.p_double[j];
54715 : }
54716 0 : reviseddualsimplex_basissolvex(&state->basis, &state->tmp0, &state->alphaq, &state->alphaqim, ae_true, &state->tmp2, _state);
54717 0 : vp = settings->pivottol;
54718 0 : p = -1;
54719 0 : r = -1;
54720 0 : thetap = (double)(0);
54721 0 : xbnd = (double)(0);
54722 0 : for(i=0; i<=m-1; i++)
54723 : {
54724 0 : bi = state->basis.idx.ptr.p_int[i];
54725 0 : alphawave = -dir*state->alphaq.ptr.p_double[i];
54726 0 : vx = s->xa.ptr.p_double[bi];
54727 0 : if( alphawave<-vp&&reviseddualsimplex_hasbndl(s, bi, _state) )
54728 : {
54729 0 : vb = s->bndl.ptr.p_double[bi];
54730 0 : if( vx<=vb )
54731 : {
54732 :
54733 : /*
54734 : * X[Bi] is already out of bounds due to rounding errors, perform shifting
54735 : */
54736 0 : vb = vx-reviseddualsimplex_shiftlen;
54737 0 : s->bndl.ptr.p_double[bi] = vx;
54738 : }
54739 0 : vtest = (vb-vx)/alphawave;
54740 0 : if( p<0||vtest<thetap )
54741 : {
54742 0 : p = bi;
54743 0 : r = i;
54744 0 : thetap = vtest;
54745 0 : xbnd = vb;
54746 : }
54747 : }
54748 0 : if( alphawave>vp&&reviseddualsimplex_hasbndu(s, bi, _state) )
54749 : {
54750 0 : vb = s->bndu.ptr.p_double[bi];
54751 0 : if( vx>=vb )
54752 : {
54753 :
54754 : /*
54755 : * X[Bi] is already out of bounds due to rounding errors, perform shifting
54756 : */
54757 0 : vb = vx+reviseddualsimplex_shiftlen;
54758 0 : s->bndu.ptr.p_double[bi] = vb;
54759 : }
54760 0 : vtest = (vb-vx)/alphawave;
54761 0 : if( p<0||vtest<thetap )
54762 : {
54763 0 : p = bi;
54764 0 : r = i;
54765 0 : thetap = vtest;
54766 0 : xbnd = vb;
54767 : }
54768 : }
54769 : }
54770 0 : if( p<0&&!haslim )
54771 : {
54772 :
54773 : /*
54774 : * Primal unbounded
54775 : */
54776 0 : *info = -4;
54777 0 : if( state->dotrace )
54778 : {
54779 0 : ae_trace("> primal ratio test: dual infeasible, primal unbounded\n");
54780 : }
54781 0 : return;
54782 : }
54783 0 : if( state->dotrace )
54784 : {
54785 0 : ae_trace("> primal ratio test: found leaving variable\n");
54786 0 : ae_trace("P = %12d (variable index)\n",
54787 : (int)(p));
54788 0 : ae_trace("R = %12d (variable index in basis)\n",
54789 : (int)(r));
54790 0 : ae_trace("ThetaP = %12.3e (primal step length)\n",
54791 : (double)(thetap));
54792 : }
54793 :
54794 : /*
54795 : * Update step
54796 : */
54797 0 : if( p>=0&&(!haslim||thetap<lim) )
54798 : {
54799 :
54800 : /*
54801 : * One of the basic variables hit the boundary and become non-basic.
54802 : *
54803 : * Perform update:
54804 : * * update basic elements of X[] (X[p] is explicitly set to the
54805 : * boundary value) and X[q]
54806 : * * update target value Z
54807 : * * update factorization
54808 : * * update D[]
54809 : */
54810 0 : rvectorsetlengthatleast(&state->tmp0, m, _state);
54811 0 : for(i=0; i<=m-1; i++)
54812 : {
54813 0 : bi = state->basis.idx.ptr.p_int[i];
54814 0 : vv = thetap*(dir*state->alphaq.ptr.p_double[i]);
54815 0 : s->xa.ptr.p_double[bi] = s->xa.ptr.p_double[bi]-vv;
54816 : }
54817 0 : s->xa.ptr.p_double[p] = xbnd;
54818 0 : s->xa.ptr.p_double[q] = s->xa.ptr.p_double[q]+dir*thetap;
54819 0 : for(i=0; i<=m-1; i++)
54820 : {
54821 0 : state->tmp0.ptr.p_double[i] = (double)(0);
54822 : }
54823 0 : reviseddualsimplex_basisupdatetrf(&state->basis, &state->at, p, q, &state->alphaq, &state->alphaqim, r, &state->tmp0, settings, _state);
54824 0 : for(i=0; i<=m-1; i++)
54825 : {
54826 0 : state->tmp0.ptr.p_double[i] = s->effc.ptr.p_double[state->basis.idx.ptr.p_int[i]];
54827 : }
54828 0 : reviseddualsimplex_basissolvet(&state->basis, &state->tmp0, &state->tmp1, &state->tmp2, _state);
54829 0 : reviseddualsimplex_computeantv(state, &state->tmp1, &s->d, _state);
54830 0 : for(i=0; i<=nn-1; i++)
54831 : {
54832 0 : j = state->basis.nidx.ptr.p_int[i];
54833 0 : s->d.ptr.p_double[j] = s->effc.ptr.p_double[j]-s->d.ptr.p_double[j];
54834 : }
54835 : }
54836 : else
54837 : {
54838 :
54839 : /*
54840 : * Basis does not change because Qth variable flips from one bound
54841 : * to another one long before we encounter the boundary
54842 : */
54843 0 : s->xa.ptr.p_double[q] = flip;
54844 0 : for(i=0; i<=m-1; i++)
54845 : {
54846 0 : bi = state->basis.idx.ptr.p_int[i];
54847 0 : vv = lim*(dir*state->alphaq.ptr.p_double[i]);
54848 0 : s->xa.ptr.p_double[bi] = s->xa.ptr.p_double[bi]-vv;
54849 : }
54850 : }
54851 0 : inc(&state->repiterationscount, _state);
54852 0 : inc(&state->repiterationscount3, _state);
54853 : }
54854 : }
54855 :
54856 :
54857 : /*************************************************************************
54858 : This function estimates feasibility properties of the current basis and
54859 : invokes phase 1 if necessary.
54860 :
54861 : A problem with following properties is expected:
54862 : * M>0
54863 : * feasible box constraints
54864 : * some initial basis (can be dual infeasible) with actual factorization
54865 : * actual initial point XC and target value Z
54866 : * actual reduced cost vector D
54867 :
54868 : It returns:
54869 : * +1 if dual feasible basis was found
54870 : * -4 if problem is dual infeasible
54871 :
54872 : -- ALGLIB --
54873 : Copyright 19.07.2018 by Bochkanov Sergey
54874 : *************************************************************************/
54875 0 : static void reviseddualsimplex_invokephase1(dualsimplexstate* state,
54876 : dualsimplexsettings* settings,
54877 : ae_state *_state)
54878 : {
54879 : ae_int_t m;
54880 : double dualerr;
54881 :
54882 :
54883 0 : m = state->primary.m;
54884 0 : state->repterminationtype = 0;
54885 :
54886 : /*
54887 : * Integrity checks
54888 : */
54889 0 : ae_assert(state->primary.state==reviseddualsimplex_ssvalid, "InvokePhase1: invalid primary X", _state);
54890 0 : ae_assert(m>0, "InvokePhase1: M<=0", _state);
54891 :
54892 : /*
54893 : * Is it dual feasible from the very beginning (or maybe after initial DFC)?
54894 : */
54895 0 : if( state->dotrace )
54896 : {
54897 0 : ae_trace("> performing initial dual feasibility correction...\n");
54898 : }
54899 0 : dualerr = reviseddualsimplex_initialdualfeasibilitycorrection(state, &state->primary, settings, _state);
54900 0 : if( state->dotrace )
54901 : {
54902 0 : ae_trace("> initial dual feasibility correction done\ndualErr = %0.3e\n",
54903 : (double)(dualerr));
54904 : }
54905 0 : if( ae_fp_less_eq(dualerr,settings->dtolabs) )
54906 : {
54907 0 : if( state->dotrace )
54908 : {
54909 0 : ae_trace("> solution is dual feasible, phase 1 is done\n");
54910 : }
54911 0 : state->repterminationtype = 1;
54912 0 : return;
54913 : }
54914 0 : if( state->dotrace )
54915 : {
54916 0 : ae_trace("> solution is not dual feasible, proceeding to full-scale phase 1\n");
54917 0 : ae_trace("\n");
54918 0 : ae_trace("****************************************************************************************************\n");
54919 0 : ae_trace("* PHASE 1 OF DUAL SIMPLEX SOLVER *\n");
54920 0 : ae_trace("****************************************************************************************************\n");
54921 : }
54922 :
54923 : /*
54924 : * Solve phase #1 subproblem
54925 : */
54926 0 : reviseddualsimplex_subprobleminitphase1(&state->primary, &state->basis, &state->phase1, _state);
54927 0 : if( state->dotrace )
54928 : {
54929 0 : ae_trace("> performing phase 1 dual feasibility correction...\n");
54930 : }
54931 0 : dualerr = reviseddualsimplex_initialdualfeasibilitycorrection(state, &state->phase1, settings, _state);
54932 0 : if( state->dotrace )
54933 : {
54934 0 : ae_trace("> phase 1 dual feasibility correction done\ndualErr = %0.3e\n",
54935 : (double)(dualerr));
54936 : }
54937 0 : reviseddualsimplex_solvesubproblemdual(state, &state->phase1, ae_true, settings, &state->repterminationtype, _state);
54938 0 : ae_assert(state->repterminationtype>0, "DualSimplexSolver: unexpected failure of phase #1", _state);
54939 0 : state->repterminationtype = 1;
54940 :
54941 : /*
54942 : * Setup initial basis for phase #2 using solution of phase #1
54943 : */
54944 0 : if( state->dotrace )
54945 : {
54946 0 : ae_trace("> setting up phase 2 initial solution\n");
54947 : }
54948 0 : reviseddualsimplex_subprobleminferinitialxn(state, &state->primary, _state);
54949 0 : dualerr = reviseddualsimplex_initialdualfeasibilitycorrection(state, &state->primary, settings, _state);
54950 0 : if( ae_fp_greater(dualerr,settings->dtolabs) )
54951 : {
54952 0 : if( state->dotrace )
54953 : {
54954 0 : ae_trace("> initial dual feasibility correction failed! terminating...\n");
54955 : }
54956 0 : state->repterminationtype = -4;
54957 0 : return;
54958 : }
54959 0 : state->repterminationtype = 1;
54960 : }
54961 :
54962 :
54963 : /*************************************************************************
54964 : This function performs actual solution.
54965 :
54966 : INPUT PARAMETERS:
54967 : State - state
54968 :
54969 : Solution results can be found in fields of State which are explicitly
54970 : declared as accessible by external code.
54971 :
54972 : -- ALGLIB --
54973 : Copyright 19.07.2018 by Bochkanov Sergey
54974 : *************************************************************************/
54975 0 : static void reviseddualsimplex_dssoptimizewrk(dualsimplexstate* state,
54976 : dualsimplexsettings* settings,
54977 : ae_state *_state)
54978 : {
54979 : ae_frame _frame_block;
54980 : ae_int_t nx;
54981 : ae_int_t m;
54982 : ae_int_t i;
54983 : ae_int_t j;
54984 : double v;
54985 : hqrndstate rs;
54986 : ae_int_t t0;
54987 :
54988 0 : ae_frame_make(_state, &_frame_block);
54989 0 : memset(&rs, 0, sizeof(rs));
54990 0 : _hqrndstate_init(&rs, _state, ae_true);
54991 :
54992 0 : nx = state->primary.ns+state->primary.m;
54993 0 : m = state->primary.m;
54994 0 : t0 = 0;
54995 :
54996 : /*
54997 : * Handle case when M=0; after this block we assume that M>0.
54998 : */
54999 0 : if( m==0 )
55000 : {
55001 :
55002 : /*
55003 : * Trace
55004 : */
55005 0 : if( state->dotrace )
55006 : {
55007 0 : ae_trace("> box-only LP problem, quick solution\n");
55008 : }
55009 :
55010 : /*
55011 : * Solve
55012 : */
55013 0 : reviseddualsimplex_solveboxonly(state, _state);
55014 0 : ae_frame_leave(_state);
55015 0 : return;
55016 : }
55017 :
55018 : /*
55019 : * Most basic check for correctness of box and/or linear constraints
55020 : */
55021 0 : for(j=0; j<=nx-1; j++)
55022 : {
55023 0 : if( state->primary.bndt.ptr.p_int[j]==reviseddualsimplex_ccinfeasible )
55024 : {
55025 :
55026 : /*
55027 : * Set error flag and generate some point to return
55028 : */
55029 0 : if( state->dotrace )
55030 : {
55031 0 : ae_trace("[WARNING] infeasible box constraint (or range constraint with AL>AU) found, terminating\n");
55032 : }
55033 0 : state->repterminationtype = -3;
55034 0 : reviseddualsimplex_setzeroxystats(state, _state);
55035 0 : ae_frame_leave(_state);
55036 0 : return;
55037 : }
55038 : }
55039 :
55040 : /*
55041 : * Initialization:
55042 : * * initial perturbed C[]
55043 : */
55044 0 : hqrndseed(7456, 2355, &rs, _state);
55045 0 : for(i=0; i<=nx-1; i++)
55046 : {
55047 0 : if( !reviseddualsimplex_isfree(&state->primary, i, _state) )
55048 : {
55049 :
55050 : /*
55051 : * apply perturbation
55052 : */
55053 0 : v = settings->perturbmag*(1+ae_fabs(state->primary.rawc.ptr.p_double[i], _state))*(1+hqrnduniformr(&rs, _state));
55054 0 : if( !reviseddualsimplex_hasbndl(&state->primary, i, _state) )
55055 : {
55056 0 : v = -v;
55057 : }
55058 0 : state->primary.effc.ptr.p_double[i] = state->primary.rawc.ptr.p_double[i]+v;
55059 : }
55060 : }
55061 :
55062 : /*
55063 : * Solve phase 1 subproblem, then perturbed subproblem
55064 : */
55065 0 : reviseddualsimplex_basisfreshtrf(&state->basis, &state->at, settings, _state);
55066 0 : if( state->primary.state==reviseddualsimplex_ssinvalid )
55067 : {
55068 0 : reviseddualsimplex_subprobleminferinitialxn(state, &state->primary, _state);
55069 : }
55070 0 : if( state->primary.state==reviseddualsimplex_ssvalidxn )
55071 : {
55072 0 : reviseddualsimplex_subproblemhandlexnupdate(state, &state->primary, _state);
55073 : }
55074 0 : ae_assert(state->primary.state==reviseddualsimplex_ssvalid, "DSS: integrity check failed (init)", _state);
55075 0 : if( state->dotimers )
55076 : {
55077 0 : t0 = ae_tickcount();
55078 : }
55079 0 : reviseddualsimplex_invokephase1(state, settings, _state);
55080 0 : if( state->dotimers )
55081 : {
55082 0 : state->repphase1time = ae_tickcount()-t0;
55083 : }
55084 0 : if( state->repterminationtype<=0 )
55085 : {
55086 :
55087 : /*
55088 : * Primal unbounded, dual infeasible
55089 : */
55090 0 : ae_assert(state->repterminationtype==-4, "DSS: integrity check for InvokePhase1() result failed", _state);
55091 0 : if( state->dotrace )
55092 : {
55093 0 : ae_trace("> the problem is dual infeasible, primal unbounded\n> done\n");
55094 : }
55095 0 : reviseddualsimplex_setxydstats(state, &state->primary, &state->basis, &state->xydsbuf, &state->repx, &state->replagbc, &state->replaglc, &state->repstats, _state);
55096 0 : ae_frame_leave(_state);
55097 0 : return;
55098 : }
55099 0 : if( state->dotrace )
55100 : {
55101 0 : ae_trace("\n");
55102 0 : ae_trace("****************************************************************************************************\n");
55103 0 : ae_trace("* PHASE 2 OF DUAL SIMPLEX SOLVER *\n");
55104 0 : ae_trace("****************************************************************************************************\n");
55105 : }
55106 0 : if( state->dotimers )
55107 : {
55108 0 : t0 = ae_tickcount();
55109 : }
55110 0 : reviseddualsimplex_solvesubproblemdual(state, &state->primary, ae_false, settings, &state->repterminationtype, _state);
55111 0 : if( state->dotimers )
55112 : {
55113 0 : state->repphase2time = ae_tickcount()-t0;
55114 : }
55115 0 : if( state->repterminationtype<=0 )
55116 : {
55117 :
55118 : /*
55119 : * Primal infeasible
55120 : */
55121 0 : ae_assert(state->repterminationtype==-3, "DSS: integrity check for SolveSubproblemDual() result failed", _state);
55122 0 : if( state->dotrace )
55123 : {
55124 0 : ae_trace("> the problem is primal infeasible\n> done\n");
55125 : }
55126 0 : reviseddualsimplex_setxydstats(state, &state->primary, &state->basis, &state->xydsbuf, &state->repx, &state->replagbc, &state->replaglc, &state->repstats, _state);
55127 0 : ae_frame_leave(_state);
55128 0 : return;
55129 : }
55130 :
55131 : /*
55132 : * Remove perturbation from the cost vector,
55133 : * then use primal simplex to enforce dual feasibility
55134 : * after removal of the perturbation (if necessary).
55135 : */
55136 0 : if( state->dotrace )
55137 : {
55138 0 : ae_trace("\n");
55139 0 : ae_trace("****************************************************************************************************\n");
55140 0 : ae_trace("* PHASE 3 OF DUAL SIMPLEX SOLVER (perturbation removed from cost vector) *\n");
55141 0 : ae_trace("****************************************************************************************************\n");
55142 : }
55143 0 : if( state->dotimers )
55144 : {
55145 0 : t0 = ae_tickcount();
55146 : }
55147 0 : reviseddualsimplex_subprobleminitphase3(&state->primary, &state->phase3, _state);
55148 0 : for(i=0; i<=nx-1; i++)
55149 : {
55150 0 : state->phase3.effc.ptr.p_double[i] = state->primary.rawc.ptr.p_double[i];
55151 : }
55152 0 : ae_assert(state->phase3.state>=reviseddualsimplex_ssvalidxn, "DSS: integrity check failed (remove perturbation)", _state);
55153 0 : reviseddualsimplex_subproblemhandlexnupdate(state, &state->phase3, _state);
55154 0 : reviseddualsimplex_solvesubproblemprimal(state, &state->phase3, settings, &state->repterminationtype, _state);
55155 0 : if( state->dotimers )
55156 : {
55157 0 : state->repphase3time = ae_tickcount()-t0;
55158 : }
55159 0 : if( state->repterminationtype<=0 )
55160 : {
55161 :
55162 : /*
55163 : * Dual infeasible, primal unbounded
55164 : */
55165 0 : ae_assert(state->repterminationtype==-4, "DSS: integrity check for SolveSubproblemPrimal() result failed", _state);
55166 0 : if( state->dotrace )
55167 : {
55168 0 : ae_trace("> the problem is primal unbounded\n> done\n");
55169 : }
55170 0 : reviseddualsimplex_setxydstats(state, &state->phase3, &state->basis, &state->xydsbuf, &state->repx, &state->replagbc, &state->replaglc, &state->repstats, _state);
55171 0 : ae_frame_leave(_state);
55172 0 : return;
55173 : }
55174 0 : for(i=0; i<=nx-1; i++)
55175 : {
55176 0 : state->primary.xa.ptr.p_double[i] = state->phase3.xa.ptr.p_double[i];
55177 0 : if( reviseddualsimplex_hasbndl(&state->primary, i, _state) )
55178 : {
55179 0 : state->primary.xa.ptr.p_double[i] = ae_maxreal(state->primary.xa.ptr.p_double[i], state->primary.bndl.ptr.p_double[i], _state);
55180 : }
55181 0 : if( reviseddualsimplex_hasbndu(&state->primary, i, _state) )
55182 : {
55183 0 : state->primary.xa.ptr.p_double[i] = ae_minreal(state->primary.xa.ptr.p_double[i], state->primary.bndu.ptr.p_double[i], _state);
55184 : }
55185 : }
55186 :
55187 : /*
55188 : * Primal and dual feasible, problem solved
55189 : */
55190 0 : state->repterminationtype = 1;
55191 0 : reviseddualsimplex_setxydstats(state, &state->primary, &state->basis, &state->xydsbuf, &state->repx, &state->replagbc, &state->replaglc, &state->repstats, _state);
55192 0 : ae_frame_leave(_state);
55193 : }
55194 :
55195 :
55196 : /*************************************************************************
55197 : Box-constrained solver; sets State.RepX, State.RepStats and State.RepTerminationType,
55198 : does not change other fields.
55199 :
55200 : -- ALGLIB --
55201 : Copyright 19.07.2018 by Bochkanov Sergey
55202 : *************************************************************************/
55203 0 : static void reviseddualsimplex_solveboxonly(dualsimplexstate* state,
55204 : ae_state *_state)
55205 : {
55206 : ae_int_t i;
55207 : ae_int_t ns;
55208 :
55209 :
55210 0 : ns = state->primary.ns;
55211 0 : ae_assert(state->primary.m==0, "SolveBoxOnly: integrity check failed", _state);
55212 0 : rsetv(ns, 0.0, &state->replagbc, _state);
55213 0 : for(i=0; i<=ns-1; i++)
55214 : {
55215 :
55216 : /*
55217 : * Handle infeasible variable
55218 : */
55219 0 : if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccinfeasible )
55220 : {
55221 0 : state->repterminationtype = -3;
55222 0 : state->repx.ptr.p_double[i] = 0.5*(state->primary.bndl.ptr.p_double[i]+state->primary.bndu.ptr.p_double[i]);
55223 0 : state->repstats.ptr.p_int[i] = 0;
55224 0 : continue;
55225 : }
55226 :
55227 : /*
55228 : * Handle fixed variable
55229 : */
55230 0 : if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccfixed )
55231 : {
55232 0 : state->repx.ptr.p_double[i] = state->primary.bndl.ptr.p_double[i];
55233 0 : state->repstats.ptr.p_int[i] = -1;
55234 0 : state->replagbc.ptr.p_double[i] = -state->primary.rawc.ptr.p_double[i];
55235 0 : continue;
55236 : }
55237 :
55238 : /*
55239 : * Handle non-zero cost component
55240 : */
55241 0 : if( ae_fp_greater(state->primary.rawc.ptr.p_double[i],(double)(0)) )
55242 : {
55243 0 : if( state->primary.bndt.ptr.p_int[i]!=reviseddualsimplex_ccrange&&state->primary.bndt.ptr.p_int[i]!=reviseddualsimplex_cclower )
55244 : {
55245 0 : if( state->repterminationtype>0 )
55246 : {
55247 0 : state->repterminationtype = -4;
55248 : }
55249 0 : if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccupper )
55250 : {
55251 0 : state->repx.ptr.p_double[i] = state->primary.bndu.ptr.p_double[i];
55252 0 : state->repstats.ptr.p_int[i] = 1;
55253 : }
55254 : else
55255 : {
55256 0 : state->repx.ptr.p_double[i] = (double)(0);
55257 0 : state->repstats.ptr.p_int[i] = 0;
55258 : }
55259 0 : state->replagbc.ptr.p_double[i] = (double)(0);
55260 : }
55261 : else
55262 : {
55263 0 : state->repx.ptr.p_double[i] = state->primary.bndl.ptr.p_double[i];
55264 0 : state->repstats.ptr.p_int[i] = -1;
55265 0 : state->replagbc.ptr.p_double[i] = -state->primary.rawc.ptr.p_double[i];
55266 : }
55267 0 : continue;
55268 : }
55269 0 : if( ae_fp_less(state->primary.rawc.ptr.p_double[i],(double)(0)) )
55270 : {
55271 0 : if( state->primary.bndt.ptr.p_int[i]!=reviseddualsimplex_ccrange&&state->primary.bndt.ptr.p_int[i]!=reviseddualsimplex_ccupper )
55272 : {
55273 0 : if( state->repterminationtype>0 )
55274 : {
55275 0 : state->repterminationtype = -4;
55276 : }
55277 0 : if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_cclower )
55278 : {
55279 0 : state->repx.ptr.p_double[i] = state->primary.bndl.ptr.p_double[i];
55280 0 : state->repstats.ptr.p_int[i] = -1;
55281 : }
55282 : else
55283 : {
55284 0 : state->repx.ptr.p_double[i] = (double)(0);
55285 0 : state->repstats.ptr.p_int[i] = 0;
55286 : }
55287 0 : state->replagbc.ptr.p_double[i] = (double)(0);
55288 : }
55289 : else
55290 : {
55291 0 : state->repx.ptr.p_double[i] = state->primary.bndu.ptr.p_double[i];
55292 0 : state->repstats.ptr.p_int[i] = 1;
55293 0 : state->replagbc.ptr.p_double[i] = -state->primary.rawc.ptr.p_double[i];
55294 : }
55295 0 : continue;
55296 : }
55297 :
55298 : /*
55299 : * Handle non-free variable with zero cost component
55300 : */
55301 0 : if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccupper||state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccrange )
55302 : {
55303 0 : state->repx.ptr.p_double[i] = state->primary.bndu.ptr.p_double[i];
55304 0 : state->repstats.ptr.p_int[i] = 1;
55305 0 : state->replagbc.ptr.p_double[i] = (double)(0);
55306 0 : continue;
55307 : }
55308 0 : if( state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_cclower )
55309 : {
55310 0 : state->repx.ptr.p_double[i] = state->primary.bndl.ptr.p_double[i];
55311 0 : state->repstats.ptr.p_int[i] = -1;
55312 0 : state->replagbc.ptr.p_double[i] = (double)(0);
55313 0 : continue;
55314 : }
55315 :
55316 : /*
55317 : * Free variable, zero cost component
55318 : */
55319 0 : ae_assert(state->primary.bndt.ptr.p_int[i]==reviseddualsimplex_ccfree, "DSSOptimize: integrity check failed", _state);
55320 0 : state->repx.ptr.p_double[i] = (double)(0);
55321 0 : state->repstats.ptr.p_int[i] = 0;
55322 0 : state->replagbc.ptr.p_double[i] = (double)(0);
55323 : }
55324 0 : }
55325 :
55326 :
55327 : /*************************************************************************
55328 : Zero-fill RepX, RepLagBC, RepLagLC, RepStats.
55329 :
55330 : -- ALGLIB --
55331 : Copyright 19.07.2018 by Bochkanov Sergey
55332 : *************************************************************************/
55333 0 : static void reviseddualsimplex_setzeroxystats(dualsimplexstate* state,
55334 : ae_state *_state)
55335 : {
55336 : ae_int_t i;
55337 :
55338 :
55339 0 : for(i=0; i<=state->primary.ns-1; i++)
55340 : {
55341 0 : state->repx.ptr.p_double[i] = (double)(0);
55342 0 : state->replagbc.ptr.p_double[i] = (double)(0);
55343 : }
55344 0 : for(i=0; i<=state->primary.m-1; i++)
55345 : {
55346 0 : state->replaglc.ptr.p_double[i] = (double)(0);
55347 : }
55348 0 : for(i=0; i<=state->primary.ns+state->primary.m-1; i++)
55349 : {
55350 0 : state->repstats.ptr.p_int[i] = 0;
55351 : }
55352 0 : }
55353 :
55354 :
55355 : /*************************************************************************
55356 : This function initializes basis structure; no triangular factorization is
55357 : prepared yet. Previously allocated memory is reused.
55358 :
55359 : -- ALGLIB --
55360 : Copyright 19.07.2018 by Bochkanov Sergey
55361 : *************************************************************************/
55362 0 : static void reviseddualsimplex_basisinit(ae_int_t ns,
55363 : ae_int_t m,
55364 : dualsimplexbasis* s,
55365 : ae_state *_state)
55366 : {
55367 : ae_int_t i;
55368 :
55369 :
55370 0 : s->ns = ns;
55371 0 : s->m = m;
55372 0 : ivectorgrowto(&s->idx, m, _state);
55373 0 : ivectorgrowto(&s->nidx, ns, _state);
55374 0 : bvectorgrowto(&s->isbasic, ns+m, _state);
55375 0 : for(i=0; i<=ns-1; i++)
55376 : {
55377 0 : s->nidx.ptr.p_int[i] = i;
55378 0 : s->isbasic.ptr.p_bool[i] = ae_false;
55379 : }
55380 0 : for(i=0; i<=m-1; i++)
55381 : {
55382 0 : s->idx.ptr.p_int[i] = ns+i;
55383 0 : s->isbasic.ptr.p_bool[ns+i] = ae_true;
55384 : }
55385 0 : s->trftype = 3;
55386 0 : s->trfage = 0;
55387 0 : s->isvalidtrf = ae_false;
55388 0 : rvectorsetlengthatleast(&s->dseweights, m, _state);
55389 0 : for(i=0; i<=m-1; i++)
55390 : {
55391 0 : s->dseweights.ptr.p_double[i] = 1.0;
55392 : }
55393 0 : s->dsevalid = ae_false;
55394 0 : reviseddualsimplex_basisclearstats(s, _state);
55395 0 : }
55396 :
55397 :
55398 : /*************************************************************************
55399 : This function clears internal performance counters of the basis
55400 :
55401 : -- ALGLIB --
55402 : Copyright 19.07.2018 by Bochkanov Sergey
55403 : *************************************************************************/
55404 0 : static void reviseddualsimplex_basisclearstats(dualsimplexbasis* s,
55405 : ae_state *_state)
55406 : {
55407 :
55408 :
55409 0 : s->statfact = 0;
55410 0 : s->statupdt = 0;
55411 0 : s->statoffdiag = (double)(0);
55412 0 : }
55413 :
55414 :
55415 : /*************************************************************************
55416 : This function resizes basis. It is assumed that constraint matrix is
55417 : completely overwritten by new one, but both matrices are similar enough
55418 : so we can reuse previous basis.
55419 :
55420 : Dual steepest edge weights are invalidated by this function.
55421 :
55422 : This function:
55423 : * tries to resize basis
55424 : * if possible, returns True and valid basis with valid factorization
55425 : * if resize is impossible (or abandoned due to stability reasons), it
55426 : returns False and basis object is left in the invalid state (you have
55427 : to reinitialize it by all-logicals basis)
55428 :
55429 : Following types of resize are supported:
55430 : * new basis size is larger than previous one => logical elements are
55431 : added to the new basis
55432 : * basis sizes match => no operation is performed
55433 : * new basis size is zero => basis is set to zero
55434 :
55435 : This function:
55436 : * requires valid triangular factorization at S on entry
55437 : * replaces it by another, valid factorization
55438 : * checks that new factorization deviates from the previous one not too much
55439 : by comparing magnitudes of min[abs(u_ii)] in both factorization (sharp
55440 : decrease results in attempt to resize being abandoned
55441 :
55442 : IMPORTANT: if smooth resize is not possible, this function throws an
55443 : exception! It is responsibility of the caller to check that
55444 : smooth resize is possible
55445 :
55446 : -- ALGLIB --
55447 : Copyright 19.07.2018 by Bochkanov Sergey
55448 : *************************************************************************/
55449 0 : static ae_bool reviseddualsimplex_basistryresize(dualsimplexbasis* s,
55450 : ae_int_t newm,
55451 : sparsematrix* at,
55452 : dualsimplexsettings* settings,
55453 : ae_state *_state)
55454 : {
55455 : ae_int_t ns;
55456 : ae_int_t oldm;
55457 : ae_int_t i;
55458 : double oldminu;
55459 : double newminu;
55460 : ae_bool result;
55461 :
55462 :
55463 0 : ns = s->ns;
55464 0 : oldm = s->m;
55465 0 : result = ae_false;
55466 :
55467 : /*
55468 : * Quick exit strategies
55469 : */
55470 0 : if( newm==0 )
55471 : {
55472 0 : reviseddualsimplex_basisinit(ns, 0, s, _state);
55473 0 : result = ae_true;
55474 0 : return result;
55475 : }
55476 :
55477 : /*
55478 : * Same size or larger
55479 : */
55480 0 : if( newm>=oldm )
55481 : {
55482 0 : ae_assert(s->isvalidtrf||oldm==0, "BasisTryResize: needs valid TRF in S", _state);
55483 :
55484 : /*
55485 : * Save information about matrix conditioning
55486 : */
55487 0 : oldminu = reviseddualsimplex_basisminimumdiagonalelement(s, _state);
55488 :
55489 : /*
55490 : * Growth if needed
55491 : */
55492 0 : s->m = newm;
55493 0 : ivectorgrowto(&s->idx, newm, _state);
55494 0 : bvectorgrowto(&s->isbasic, ns+newm, _state);
55495 0 : for(i=oldm; i<=newm-1; i++)
55496 : {
55497 0 : s->idx.ptr.p_int[i] = ns+i;
55498 0 : s->isbasic.ptr.p_bool[ns+i] = ae_true;
55499 : }
55500 :
55501 : /*
55502 : * DSE weights are invalid and filled by 1.0
55503 : */
55504 0 : rvectorgrowto(&s->dseweights, newm, _state);
55505 0 : for(i=0; i<=newm-1; i++)
55506 : {
55507 0 : s->dseweights.ptr.p_double[i] = 1.0;
55508 : }
55509 0 : s->dsevalid = ae_false;
55510 :
55511 : /*
55512 : * Invalidate TRF.
55513 : * Try to refactorize.
55514 : */
55515 0 : s->isvalidtrf = ae_false;
55516 0 : newminu = reviseddualsimplex_basisfreshtrfunsafe(s, at, settings, _state);
55517 0 : result = ae_fp_greater_eq(newminu,reviseddualsimplex_maxudecay*oldminu);
55518 0 : return result;
55519 : }
55520 0 : ae_assert(ae_false, "BasisTryResize: unexpected branch", _state);
55521 0 : return result;
55522 : }
55523 :
55524 :
55525 : /*************************************************************************
55526 : This function returns minimum diagonal element of S. Result=1 is returned
55527 : for M=0.
55528 :
55529 : -- ALGLIB --
55530 : Copyright 19.07.2018 by Bochkanov Sergey
55531 : *************************************************************************/
55532 0 : static double reviseddualsimplex_basisminimumdiagonalelement(dualsimplexbasis* s,
55533 : ae_state *_state)
55534 : {
55535 : double v;
55536 : double vv;
55537 : ae_int_t i;
55538 : ae_int_t m;
55539 : double result;
55540 :
55541 :
55542 0 : m = s->m;
55543 0 : if( m==0 )
55544 : {
55545 0 : result = (double)(1);
55546 0 : return result;
55547 : }
55548 0 : ae_assert(((s->trftype==0||s->trftype==1)||s->trftype==2)||s->trftype==3, "BasisMinimumDiagonalElement: unexpected TRF type", _state);
55549 0 : ae_assert(s->isvalidtrf, "BasisMinimumDiagonalElement: TRF is invalid", _state);
55550 0 : v = ae_maxrealnumber;
55551 0 : for(i=0; i<=m-1; i++)
55552 : {
55553 0 : vv = (double)(0);
55554 0 : if( s->trftype==0||s->trftype==1 )
55555 : {
55556 0 : vv = s->denselu.ptr.pp_double[i][i];
55557 : }
55558 0 : if( s->trftype==2||s->trftype==3 )
55559 : {
55560 0 : vv = sparsegetdiagonal(&s->sparseu, i, _state);
55561 : }
55562 0 : if( vv<0 )
55563 : {
55564 0 : vv = -vv;
55565 : }
55566 0 : if( vv<v )
55567 : {
55568 0 : v = vv;
55569 : }
55570 : }
55571 0 : result = v;
55572 0 : return result;
55573 : }
55574 :
55575 :
55576 : /*************************************************************************
55577 : This function exports division of variables into basic/nonbasic ones; only
55578 : basic/nonbasic sets are exported - triangular factorization is NOT exported;
55579 : however, valid triangular factorization IS required in order to perform
55580 : exporting.
55581 :
55582 : -- ALGLIB --
55583 : Copyright 19.07.2018 by Bochkanov Sergey
55584 : *************************************************************************/
55585 0 : static void reviseddualsimplex_basisexportto(dualsimplexbasis* s0,
55586 : dualsimplexbasis* s1,
55587 : ae_state *_state)
55588 : {
55589 :
55590 :
55591 0 : s1->ns = s0->ns;
55592 0 : s1->m = s0->m;
55593 0 : copyintegerarray(&s0->idx, &s1->idx, _state);
55594 0 : copyintegerarray(&s0->nidx, &s1->nidx, _state);
55595 0 : copybooleanarray(&s0->isbasic, &s1->isbasic, _state);
55596 0 : s1->isvalidtrf = ae_false;
55597 0 : s1->trftype = -1;
55598 0 : s1->dsevalid = ae_false;
55599 0 : if( s0->m>0 )
55600 : {
55601 0 : ae_assert(s0->isvalidtrf, "BasisExport: valid factorization is required for source basis", _state);
55602 0 : s1->eminu = reviseddualsimplex_basisminimumdiagonalelement(s0, _state);
55603 : }
55604 : else
55605 : {
55606 0 : s1->eminu = (double)(1);
55607 : }
55608 0 : }
55609 :
55610 :
55611 : /*************************************************************************
55612 : This function imports from S1 to S0 a division of variables into
55613 : basic/nonbasic ones; only basic/nonbasic sets are imported.
55614 :
55615 : Triangular factorization is not imported; however, this function checks
55616 : that new factorization deviates from the previous one not too much by
55617 : comparing magnitudes of min[abs(u_ii)] in both factorization (basis being
55618 : imported stores statistics about U). Sharp decrease of diagonal elements
55619 : means that we have too unstable situation which results in import being
55620 : abandoned. In this case False is returned, and the basis S0 is left in the
55621 : indeterminate invalid state (you have to reinitialize it by all-logicals).
55622 :
55623 : IMPORTANT: if metrics of S0 and S1 do not match, an exception will be generated.
55624 :
55625 : -- ALGLIB --
55626 : Copyright 19.07.2018 by Bochkanov Sergey
55627 : *************************************************************************/
55628 0 : static ae_bool reviseddualsimplex_basistryimportfrom(dualsimplexbasis* s0,
55629 : dualsimplexbasis* s1,
55630 : sparsematrix* at,
55631 : dualsimplexsettings* settings,
55632 : ae_state *_state)
55633 : {
55634 : ae_int_t i;
55635 : double newminu;
55636 : ae_bool result;
55637 :
55638 :
55639 0 : ae_assert(s0->ns==s1->ns, "BasisImportFrom: structural variable counts do not match", _state);
55640 0 : reviseddualsimplex_basisclearstats(s0, _state);
55641 0 : s0->m = s1->m;
55642 0 : for(i=0; i<=s0->m-1; i++)
55643 : {
55644 0 : s0->idx.ptr.p_int[i] = s1->idx.ptr.p_int[i];
55645 : }
55646 0 : for(i=0; i<=s0->ns-1; i++)
55647 : {
55648 0 : s0->nidx.ptr.p_int[i] = s1->nidx.ptr.p_int[i];
55649 : }
55650 0 : for(i=0; i<=s0->m+s0->ns-1; i++)
55651 : {
55652 0 : s0->isbasic.ptr.p_bool[i] = s1->isbasic.ptr.p_bool[i];
55653 : }
55654 0 : s0->isvalidtrf = ae_false;
55655 0 : rvectorsetlengthatleast(&s0->dseweights, s1->m, _state);
55656 0 : for(i=0; i<=s1->m-1; i++)
55657 : {
55658 0 : s0->dseweights.ptr.p_double[i] = 1.0;
55659 : }
55660 0 : s0->dsevalid = ae_false;
55661 0 : newminu = reviseddualsimplex_basisfreshtrfunsafe(s0, at, settings, _state);
55662 0 : result = ae_fp_greater_eq(newminu,reviseddualsimplex_maxudecay*s1->eminu);
55663 0 : if( !result )
55664 : {
55665 0 : s0->isvalidtrf = ae_false;
55666 0 : s0->trftype = -1;
55667 : }
55668 0 : return result;
55669 : }
55670 :
55671 :
55672 : /*************************************************************************
55673 : This function computes fresh triangular factorization.
55674 :
55675 : If TRF of age 0 (fresh) is already present, no new factorization is calculated.
55676 : If factorization has exactly zero element along diagonal, this function
55677 : generates exception.
55678 :
55679 :
55680 : -- ALGLIB --
55681 : Copyright 19.07.2018 by Bochkanov Sergey
55682 : *************************************************************************/
55683 0 : static void reviseddualsimplex_basisfreshtrf(dualsimplexbasis* s,
55684 : sparsematrix* at,
55685 : dualsimplexsettings* settings,
55686 : ae_state *_state)
55687 : {
55688 : double v;
55689 :
55690 :
55691 0 : v = reviseddualsimplex_basisfreshtrfunsafe(s, at, settings, _state);
55692 0 : ae_assert(ae_fp_greater(v,(double)(0)), "BasisFreshTrf: degeneracy of B is detected", _state);
55693 0 : }
55694 :
55695 :
55696 : /*************************************************************************
55697 : This function computes fresh triangular factorization.
55698 :
55699 : If TRF of age 0 (fresh) is already present, no new factorization is calculated.
55700 :
55701 : It returns min[abs(u[i,i])] which can be used to determine whether factorization
55702 : is degenerate or not (it will factorize anything, the question is whether
55703 : it is possible to use factorization)
55704 :
55705 : -- ALGLIB --
55706 : Copyright 19.07.2018 by Bochkanov Sergey
55707 : *************************************************************************/
55708 0 : static double reviseddualsimplex_basisfreshtrfunsafe(dualsimplexbasis* s,
55709 : sparsematrix* at,
55710 : dualsimplexsettings* settings,
55711 : ae_state *_state)
55712 : {
55713 : ae_int_t m;
55714 : ae_int_t ns;
55715 : ae_int_t i;
55716 : ae_int_t j;
55717 : ae_int_t k;
55718 : ae_int_t j0;
55719 : ae_int_t j1;
55720 : ae_int_t k1;
55721 : ae_int_t nzl;
55722 : ae_int_t nzu;
55723 : ae_int_t nlogical;
55724 : ae_int_t nstructural;
55725 : ae_int_t offs;
55726 : ae_int_t offs1;
55727 : ae_int_t offs2;
55728 : double result;
55729 :
55730 :
55731 0 : m = s->m;
55732 0 : ns = s->ns;
55733 0 : result = (double)(0);
55734 :
55735 : /*
55736 : * Compare TRF type with one required by settings, invalidation and refresh otherwise
55737 : */
55738 0 : if( s->trftype!=settings->trftype )
55739 : {
55740 0 : s->trftype = settings->trftype;
55741 0 : s->isvalidtrf = ae_false;
55742 0 : result = reviseddualsimplex_basisfreshtrfunsafe(s, at, settings, _state);
55743 0 : return result;
55744 : }
55745 :
55746 : /*
55747 : * Is it valid and fresh?
55748 : */
55749 0 : if( s->isvalidtrf&&s->trfage==0 )
55750 : {
55751 0 : result = reviseddualsimplex_basisminimumdiagonalelement(s, _state);
55752 0 : return result;
55753 : }
55754 :
55755 : /*
55756 : * Dense TRF
55757 : */
55758 0 : if( s->trftype==0||s->trftype==1 )
55759 : {
55760 0 : ivectorsetlengthatleast(&s->colpermbwd, m, _state);
55761 0 : for(i=0; i<=m-1; i++)
55762 : {
55763 0 : s->colpermbwd.ptr.p_int[i] = i;
55764 : }
55765 0 : rmatrixsetlengthatleast(&s->denselu, m, m, _state);
55766 0 : for(i=0; i<=m-1; i++)
55767 : {
55768 0 : for(j=0; j<=m-1; j++)
55769 : {
55770 0 : s->denselu.ptr.pp_double[i][j] = (double)(0);
55771 : }
55772 : }
55773 0 : for(i=0; i<=m-1; i++)
55774 : {
55775 0 : j0 = at->ridx.ptr.p_int[s->idx.ptr.p_int[i]];
55776 0 : j1 = at->ridx.ptr.p_int[s->idx.ptr.p_int[i]+1]-1;
55777 0 : for(j=j0; j<=j1; j++)
55778 : {
55779 0 : s->denselu.ptr.pp_double[i][at->idx.ptr.p_int[j]] = at->vals.ptr.p_double[j];
55780 : }
55781 : }
55782 0 : rmatrixlu(&s->denselu, m, m, &s->tmpi, _state);
55783 0 : reviseddualsimplex_pivottobwd(&s->tmpi, m, &s->rowpermbwd, _state);
55784 0 : s->isvalidtrf = ae_true;
55785 0 : s->trfage = 0;
55786 0 : s->statfact = s->statfact+1;
55787 0 : s->statoffdiag = s->statoffdiag+ae_sqr((double)(m-1), _state);
55788 0 : result = reviseddualsimplex_basisminimumdiagonalelement(s, _state);
55789 0 : return result;
55790 : }
55791 :
55792 : /*
55793 : * Sparse TRF (with either PFI or Forest-Tomlin)
55794 : */
55795 0 : if( s->trftype==2||s->trftype==3 )
55796 : {
55797 :
55798 : /*
55799 : * Determine permutation which moves logical variables
55800 : * to the beginning.
55801 : *
55802 : * NOTE: this reordering results in stable factorization
55803 : * because we prenormalized constraints with 2-norm,
55804 : * all elements in the logical columns are less than
55805 : * 1.0 in magnitude.
55806 : *
55807 : * After this block is done we have following arrays:
55808 : * * tCInvIdx[j], which is an inverse of ColPermBwf[]
55809 : */
55810 0 : ivectorsetlengthatleast(&s->tcinvidx, m, _state);
55811 0 : ivectorsetlengthatleast(&s->rowpermbwd, m, _state);
55812 0 : ivectorsetlengthatleast(&s->colpermbwd, m, _state);
55813 0 : for(i=0; i<=m-1; i++)
55814 : {
55815 0 : s->tcinvidx.ptr.p_int[i] = i;
55816 0 : s->rowpermbwd.ptr.p_int[i] = i;
55817 0 : s->colpermbwd.ptr.p_int[i] = i;
55818 : }
55819 0 : nlogical = 0;
55820 0 : for(i=0; i<=m-1; i++)
55821 : {
55822 0 : if( s->idx.ptr.p_int[i]>=ns )
55823 : {
55824 0 : j = s->rowpermbwd.ptr.p_int[nlogical];
55825 0 : s->rowpermbwd.ptr.p_int[nlogical] = s->rowpermbwd.ptr.p_int[i];
55826 0 : s->rowpermbwd.ptr.p_int[i] = j;
55827 0 : j1 = s->tcinvidx.ptr.p_int[s->idx.ptr.p_int[i]-ns];
55828 0 : j = s->colpermbwd.ptr.p_int[j1];
55829 0 : s->colpermbwd.ptr.p_int[j1] = s->colpermbwd.ptr.p_int[nlogical];
55830 0 : s->colpermbwd.ptr.p_int[nlogical] = j;
55831 0 : s->tcinvidx.ptr.p_int[s->colpermbwd.ptr.p_int[nlogical]] = nlogical;
55832 0 : s->tcinvidx.ptr.p_int[s->colpermbwd.ptr.p_int[j1]] = j1;
55833 0 : nlogical = nlogical+1;
55834 : }
55835 : }
55836 0 : sortmiddlei(&s->colpermbwd, nlogical, m-nlogical, _state);
55837 0 : for(i=0; i<=m-1; i++)
55838 : {
55839 0 : s->tcinvidx.ptr.p_int[s->colpermbwd.ptr.p_int[i]] = i;
55840 : }
55841 0 : nstructural = m-nlogical;
55842 :
55843 : /*
55844 : * Prepare SparseLU1 to receive factored out logical part of the matrix
55845 : * and SparseLU2 to receive structural part of the matrix.
55846 : */
55847 0 : ivectorsetlengthatleast(&s->sparselu1.ridx, nstructural+1, _state);
55848 0 : ivectorsetlengthatleast(&s->sparselu1.didx, nstructural, _state);
55849 0 : ivectorsetlengthatleast(&s->sparselu1.uidx, nstructural, _state);
55850 0 : s->sparselu1.matrixtype = 1;
55851 0 : s->sparselu1.m = nstructural;
55852 0 : s->sparselu1.n = nlogical;
55853 0 : s->sparselu1.ridx.ptr.p_int[0] = 0;
55854 0 : ivectorsetlengthatleast(&s->sparselu2.ridx, nstructural+1, _state);
55855 0 : ivectorsetlengthatleast(&s->sparselu2.didx, nstructural, _state);
55856 0 : ivectorsetlengthatleast(&s->sparselu2.uidx, nstructural, _state);
55857 0 : s->sparselu2.matrixtype = 1;
55858 0 : s->sparselu2.m = nstructural;
55859 0 : s->sparselu2.n = nstructural;
55860 0 : s->sparselu2.ridx.ptr.p_int[0] = 0;
55861 :
55862 : /*
55863 : * Reorder array, perform LU factorization
55864 : */
55865 0 : for(k=0; k<=nstructural-1; k++)
55866 : {
55867 :
55868 : /*
55869 : * Make sure SparseLU1 and SparseLU2 have enough place.
55870 : */
55871 0 : offs1 = s->sparselu1.ridx.ptr.p_int[k];
55872 0 : offs2 = s->sparselu2.ridx.ptr.p_int[k];
55873 0 : ivectorgrowto(&s->sparselu1.idx, offs1+m, _state);
55874 0 : rvectorgrowto(&s->sparselu1.vals, offs1+m, _state);
55875 0 : ivectorgrowto(&s->sparselu2.idx, offs2+m, _state);
55876 0 : rvectorgrowto(&s->sparselu2.vals, offs2+m, _state);
55877 :
55878 : /*
55879 : * Extract K-th row of the SparseLU1/2 (I-th row of the original matrix)
55880 : */
55881 0 : i = s->rowpermbwd.ptr.p_int[k+nlogical];
55882 0 : j0 = at->ridx.ptr.p_int[s->idx.ptr.p_int[i]];
55883 0 : j1 = at->ridx.ptr.p_int[s->idx.ptr.p_int[i]+1]-1;
55884 0 : for(j=j0; j<=j1; j++)
55885 : {
55886 0 : k1 = s->tcinvidx.ptr.p_int[at->idx.ptr.p_int[j]];
55887 0 : if( k1<nlogical )
55888 : {
55889 :
55890 : /*
55891 : * Append element to SparseLU1
55892 : */
55893 0 : s->sparselu1.idx.ptr.p_int[offs1] = k1;
55894 0 : s->sparselu1.vals.ptr.p_double[offs1] = at->vals.ptr.p_double[j];
55895 0 : offs1 = offs1+1;
55896 : }
55897 : else
55898 : {
55899 :
55900 : /*
55901 : * Append element to SparseLU2
55902 : */
55903 0 : s->sparselu2.idx.ptr.p_int[offs2] = k1-nlogical;
55904 0 : s->sparselu2.vals.ptr.p_double[offs2] = at->vals.ptr.p_double[j];
55905 0 : offs2 = offs2+1;
55906 : }
55907 : }
55908 :
55909 : /*
55910 : * Elements added to the last row of LU1 can be unordered,
55911 : * so it needs resorting.
55912 : *
55913 : * LU2 does NOT need resorting because trailing NStructural
55914 : * elements of permutation were post-sorted to produce
55915 : * already sorted results.
55916 : */
55917 0 : tagsortmiddleir(&s->sparselu1.idx, &s->sparselu1.vals, s->sparselu1.ridx.ptr.p_int[k], offs1-s->sparselu1.ridx.ptr.p_int[k], _state);
55918 0 : s->sparselu1.ridx.ptr.p_int[k+1] = offs1;
55919 0 : s->sparselu2.ridx.ptr.p_int[k+1] = offs2;
55920 : }
55921 0 : s->sparselu1.ninitialized = s->sparselu1.ridx.ptr.p_int[nstructural];
55922 0 : s->sparselu2.ninitialized = s->sparselu2.ridx.ptr.p_int[nstructural];
55923 0 : sparseinitduidx(&s->sparselu1, _state);
55924 0 : sparseinitduidx(&s->sparselu2, _state);
55925 0 : if( nstructural>0 )
55926 : {
55927 0 : sptrflu(&s->sparselu2, 2, &s->densep2, &s->densep2c, &s->lubuf2, _state);
55928 0 : for(i=0; i<=nstructural-1; i++)
55929 : {
55930 0 : j = s->rowpermbwd.ptr.p_int[i+nlogical];
55931 0 : s->rowpermbwd.ptr.p_int[i+nlogical] = s->rowpermbwd.ptr.p_int[s->densep2.ptr.p_int[i]+nlogical];
55932 0 : s->rowpermbwd.ptr.p_int[s->densep2.ptr.p_int[i]+nlogical] = j;
55933 0 : j = s->colpermbwd.ptr.p_int[i+nlogical];
55934 0 : s->colpermbwd.ptr.p_int[i+nlogical] = s->colpermbwd.ptr.p_int[s->densep2c.ptr.p_int[i]+nlogical];
55935 0 : s->colpermbwd.ptr.p_int[s->densep2c.ptr.p_int[i]+nlogical] = j;
55936 : }
55937 :
55938 : /*
55939 : * Process L factor:
55940 : *
55941 : * 1. count number of non-zeros in the L factor,
55942 : * 2. fill NLogical*NLogical leading block
55943 : * 3. NStructural*M bottom block
55944 : */
55945 0 : nzl = nlogical;
55946 0 : for(i=0; i<=nstructural-1; i++)
55947 : {
55948 0 : k = s->lubuf2.rowpermrawidx.ptr.p_int[i];
55949 0 : nzl = nzl+(s->sparselu1.ridx.ptr.p_int[k+1]-s->sparselu1.ridx.ptr.p_int[k]);
55950 0 : nzl = nzl+1+(s->sparselu2.didx.ptr.p_int[i]-s->sparselu2.ridx.ptr.p_int[i]);
55951 : }
55952 0 : rvectorsetlengthatleast(&s->sparsel.vals, nzl, _state);
55953 0 : ivectorsetlengthatleast(&s->sparsel.idx, nzl, _state);
55954 0 : ivectorsetlengthatleast(&s->sparsel.ridx, m+1, _state);
55955 0 : ivectorsetlengthatleast(&s->sparsel.didx, m, _state);
55956 0 : ivectorsetlengthatleast(&s->sparsel.uidx, m, _state);
55957 0 : s->sparsel.matrixtype = 1;
55958 0 : s->sparsel.m = m;
55959 0 : s->sparsel.n = m;
55960 0 : s->sparsel.ninitialized = nzl;
55961 0 : s->sparsel.ridx.ptr.p_int[0] = 0;
55962 0 : for(i=0; i<=nlogical-1; i++)
55963 : {
55964 0 : s->sparsel.idx.ptr.p_int[i] = i;
55965 0 : s->sparsel.vals.ptr.p_double[i] = 1.0;
55966 0 : s->sparsel.ridx.ptr.p_int[i+1] = i+1;
55967 : }
55968 0 : for(i=0; i<=nstructural-1; i++)
55969 : {
55970 0 : offs = s->sparsel.ridx.ptr.p_int[nlogical+i];
55971 0 : k = s->lubuf2.rowpermrawidx.ptr.p_int[i];
55972 0 : j0 = s->sparselu1.ridx.ptr.p_int[k];
55973 0 : j1 = s->sparselu1.ridx.ptr.p_int[k+1]-1;
55974 0 : for(j=j0; j<=j1; j++)
55975 : {
55976 0 : s->sparsel.idx.ptr.p_int[offs] = s->sparselu1.idx.ptr.p_int[j];
55977 0 : s->sparsel.vals.ptr.p_double[offs] = -s->sparselu1.vals.ptr.p_double[j];
55978 0 : offs = offs+1;
55979 : }
55980 0 : j0 = s->sparselu2.ridx.ptr.p_int[i];
55981 0 : j1 = s->sparselu2.didx.ptr.p_int[i]-1;
55982 0 : for(j=j0; j<=j1; j++)
55983 : {
55984 0 : s->sparsel.idx.ptr.p_int[offs] = nlogical+s->sparselu2.idx.ptr.p_int[j];
55985 0 : s->sparsel.vals.ptr.p_double[offs] = s->sparselu2.vals.ptr.p_double[j];
55986 0 : offs = offs+1;
55987 : }
55988 0 : s->sparsel.idx.ptr.p_int[offs] = nlogical+i;
55989 0 : s->sparsel.vals.ptr.p_double[offs] = 1.0;
55990 0 : offs = offs+1;
55991 0 : s->sparsel.ridx.ptr.p_int[nlogical+i+1] = offs;
55992 : }
55993 0 : ae_assert(s->sparsel.ninitialized==s->sparsel.ridx.ptr.p_int[m], "BasisFreshTrf: integrity check failed", _state);
55994 0 : sparseinitduidx(&s->sparsel, _state);
55995 :
55996 : /*
55997 : * Process U factor:
55998 : *
55999 : * 1. count number of non-zeros in the U factor,
56000 : * 2. fill NLogical*NLogical leading block
56001 : * 3. NStructural*NStructural bottom block
56002 : */
56003 0 : nzu = nlogical;
56004 0 : for(i=0; i<=nstructural-1; i++)
56005 : {
56006 0 : nzu = nzu+1+(s->sparselu2.ridx.ptr.p_int[i+1]-s->sparselu2.uidx.ptr.p_int[i]);
56007 : }
56008 0 : rvectorsetlengthatleast(&s->sparseu.vals, nzu, _state);
56009 0 : ivectorsetlengthatleast(&s->sparseu.idx, nzu, _state);
56010 0 : ivectorsetlengthatleast(&s->sparseu.ridx, m+1, _state);
56011 0 : ivectorsetlengthatleast(&s->sparseu.didx, m, _state);
56012 0 : ivectorsetlengthatleast(&s->sparseu.uidx, m, _state);
56013 0 : s->sparseu.matrixtype = 1;
56014 0 : s->sparseu.m = m;
56015 0 : s->sparseu.n = m;
56016 0 : s->sparseu.ninitialized = nzu;
56017 0 : s->sparseu.ridx.ptr.p_int[0] = 0;
56018 0 : for(i=0; i<=nlogical-1; i++)
56019 : {
56020 0 : s->sparseu.idx.ptr.p_int[i] = i;
56021 0 : s->sparseu.vals.ptr.p_double[i] = -1.0;
56022 0 : s->sparseu.ridx.ptr.p_int[i+1] = i+1;
56023 : }
56024 0 : for(i=0; i<=nstructural-1; i++)
56025 : {
56026 0 : offs = s->sparseu.ridx.ptr.p_int[nlogical+i];
56027 0 : s->sparseu.idx.ptr.p_int[offs] = nlogical+i;
56028 0 : j = s->sparselu2.didx.ptr.p_int[i];
56029 0 : if( j<s->sparselu2.uidx.ptr.p_int[i] )
56030 : {
56031 0 : ae_assert(s->sparselu2.idx.ptr.p_int[j]==i, "BasisFreshTrf: integrity check failed", _state);
56032 0 : s->sparseu.vals.ptr.p_double[offs] = s->sparselu2.vals.ptr.p_double[j];
56033 : }
56034 : else
56035 : {
56036 0 : s->sparseu.vals.ptr.p_double[offs] = (double)(0);
56037 : }
56038 0 : offs = offs+1;
56039 0 : j0 = s->sparselu2.uidx.ptr.p_int[i];
56040 0 : j1 = s->sparselu2.ridx.ptr.p_int[i+1]-1;
56041 0 : for(j=j0; j<=j1; j++)
56042 : {
56043 0 : s->sparseu.idx.ptr.p_int[offs] = nlogical+s->sparselu2.idx.ptr.p_int[j];
56044 0 : s->sparseu.vals.ptr.p_double[offs] = s->sparselu2.vals.ptr.p_double[j];
56045 0 : offs = offs+1;
56046 : }
56047 0 : s->sparseu.ridx.ptr.p_int[nlogical+i+1] = offs;
56048 : }
56049 0 : ae_assert(s->sparseu.ninitialized==s->sparseu.ridx.ptr.p_int[m], "BasisFreshTrf: integrity check failed", _state);
56050 0 : sparseinitduidx(&s->sparseu, _state);
56051 : }
56052 : else
56053 : {
56054 0 : ivectorsetlengthatleast(&s->nrs, m, _state);
56055 0 : for(i=0; i<=m-1; i++)
56056 : {
56057 0 : s->nrs.ptr.p_int[i] = 1;
56058 : }
56059 0 : sparsecreatecrsbuf(m, m, &s->nrs, &s->sparsel, _state);
56060 0 : for(i=0; i<=nlogical-1; i++)
56061 : {
56062 0 : sparseset(&s->sparsel, i, i, 1.0, _state);
56063 : }
56064 0 : sparsecreatecrsbuf(m, m, &s->nrs, &s->sparseu, _state);
56065 0 : for(i=0; i<=nlogical-1; i++)
56066 : {
56067 0 : sparseset(&s->sparseu, i, i, -1.0, _state);
56068 : }
56069 : }
56070 0 : sparsecopytransposecrsbuf(&s->sparseu, &s->sparseut, _state);
56071 0 : s->isvalidtrf = ae_true;
56072 0 : s->trfage = 0;
56073 0 : s->statfact = s->statfact+1;
56074 0 : s->statoffdiag = s->statoffdiag+(s->sparsel.ridx.ptr.p_int[m]-m)+(s->sparseu.ridx.ptr.p_int[m]-m);
56075 0 : result = reviseddualsimplex_basisminimumdiagonalelement(s, _state);
56076 0 : return result;
56077 : }
56078 :
56079 : /*
56080 : *
56081 : */
56082 0 : ae_assert(ae_false, "BasisFreshTrf: unexpected TRF type", _state);
56083 0 : return result;
56084 : }
56085 :
56086 :
56087 : /*************************************************************************
56088 : This function fills S.DSEWeights by actual weights according to current
56089 : settings and sets validity flag.
56090 :
56091 : Basis object MUST store valid triangular factorization, otherwise this
56092 : function throws an exception.
56093 :
56094 : -- ALGLIB --
56095 : Copyright 19.07.2018 by Bochkanov Sergey
56096 : *************************************************************************/
56097 0 : static void reviseddualsimplex_basisrequestweights(dualsimplexbasis* s,
56098 : dualsimplexsettings* settings,
56099 : ae_state *_state)
56100 : {
56101 : ae_int_t m;
56102 : ae_int_t ns;
56103 : ae_int_t i;
56104 : ae_int_t j;
56105 : double v;
56106 : double vv;
56107 :
56108 :
56109 0 : m = s->m;
56110 0 : ns = s->ns;
56111 0 : ae_assert((settings->pricing==-1||settings->pricing==0)||settings->pricing==1, "BasisRequestWeights: unknown pricing type", _state);
56112 0 : ae_assert(s->isvalidtrf, "BasisRequestWeights: factorization is not computed prior to calling this function", _state);
56113 :
56114 : /*
56115 : * If weights are valid, return immediately
56116 : */
56117 0 : if( s->dsevalid )
56118 : {
56119 0 : return;
56120 : }
56121 :
56122 : /*
56123 : * Compute weights from scratch
56124 : */
56125 0 : if( settings->pricing==-1||settings->pricing==1 )
56126 : {
56127 0 : for(i=0; i<=m-1; i++)
56128 : {
56129 0 : if( s->idx.ptr.p_int[i]<ns )
56130 : {
56131 :
56132 : /*
56133 : * Structural variable, DSE weight is computed by definition
56134 : */
56135 0 : rvectorsetlengthatleast(&s->wtmp0, m, _state);
56136 0 : rvectorsetlengthatleast(&s->wtmp1, m, _state);
56137 0 : for(j=0; j<=m-1; j++)
56138 : {
56139 0 : s->wtmp0.ptr.p_double[j] = (double)(0);
56140 : }
56141 0 : s->wtmp0.ptr.p_double[i] = (double)(1);
56142 0 : reviseddualsimplex_basissolvet(s, &s->wtmp0, &s->wtmp1, &s->wtmp2, _state);
56143 0 : v = (double)(0);
56144 0 : for(j=0; j<=m-1; j++)
56145 : {
56146 0 : vv = s->wtmp1.ptr.p_double[j];
56147 0 : v = v+vv*vv;
56148 : }
56149 0 : s->dseweights.ptr.p_double[i] = v;
56150 : }
56151 : else
56152 : {
56153 :
56154 : /*
56155 : * Logical variable, weight can be set to 1.0
56156 : */
56157 0 : s->dseweights.ptr.p_double[i] = 1.0;
56158 : }
56159 : }
56160 0 : s->dsevalid = ae_true;
56161 0 : return;
56162 : }
56163 :
56164 : /*
56165 : * Compute weights from scratch
56166 : */
56167 0 : if( settings->pricing==0 )
56168 : {
56169 0 : for(i=0; i<=m-1; i++)
56170 : {
56171 0 : s->dseweights.ptr.p_double[i] = 1.0;
56172 : }
56173 0 : s->dsevalid = ae_true;
56174 0 : return;
56175 : }
56176 0 : ae_assert(ae_false, "BasisRequestWeights: unexpected pricing type", _state);
56177 : }
56178 :
56179 :
56180 : /*************************************************************************
56181 : This function updates triangular factorization by adding Q to basis and
56182 : removing P from basis. It also updates index tables IsBasic[], BasicIdx[],
56183 : Basis.NIdx[].
56184 :
56185 : AlphaQim contains intermediate result from Ftran for AlphaQ, it is used
56186 : by Forest-Tomlin update scheme. If other update is used, it is not referenced
56187 : at all.
56188 :
56189 : X[], D[], Z are NOT recomputed.
56190 :
56191 : Tau is used if Settings.Pricing=1, ignored otherwise.
56192 :
56193 : -- ALGLIB --
56194 : Copyright 19.07.2018 by Bochkanov Sergey
56195 : *************************************************************************/
56196 0 : static void reviseddualsimplex_basisupdatetrf(dualsimplexbasis* s,
56197 : sparsematrix* at,
56198 : ae_int_t p,
56199 : ae_int_t q,
56200 : /* Real */ ae_vector* alphaq,
56201 : /* Real */ ae_vector* alphaqim,
56202 : ae_int_t r,
56203 : /* Real */ ae_vector* tau,
56204 : dualsimplexsettings* settings,
56205 : ae_state *_state)
56206 : {
56207 : ae_int_t m;
56208 : ae_int_t nn;
56209 : ae_int_t i;
56210 : ae_int_t j;
56211 : ae_bool processed;
56212 : double invaq;
56213 : ae_int_t dstoffs;
56214 : ae_int_t srcoffs;
56215 : ae_int_t srcidx;
56216 : double srcval;
56217 : double vcorner;
56218 : ae_int_t idxd;
56219 : double v;
56220 :
56221 :
56222 0 : m = s->m;
56223 0 : nn = s->ns;
56224 :
56225 : /*
56226 : * Update index tables
56227 : *
56228 : * TODO: better code!!!!!!!!!!!!!!!!!!!!!!!
56229 : */
56230 0 : s->isbasic.ptr.p_bool[p] = ae_false;
56231 0 : s->isbasic.ptr.p_bool[q] = ae_true;
56232 0 : for(i=0; i<=m-1; i++)
56233 : {
56234 0 : if( s->idx.ptr.p_int[i]==p )
56235 : {
56236 0 : s->idx.ptr.p_int[i] = q;
56237 0 : break;
56238 : }
56239 : }
56240 0 : for(i=0; i<=nn-1; i++)
56241 : {
56242 0 : if( s->nidx.ptr.p_int[i]==q )
56243 : {
56244 0 : s->nidx.ptr.p_int[i] = p;
56245 0 : break;
56246 : }
56247 : }
56248 :
56249 : /*
56250 : * Update dense factorization
56251 : */
56252 0 : if( ((s->trftype!=settings->trftype||s->trftype==0)||!s->isvalidtrf)||s->trfage>=settings->maxtrfage )
56253 : {
56254 :
56255 : /*
56256 : * Complete refresh is needed for factorization
56257 : */
56258 0 : s->isvalidtrf = ae_false;
56259 0 : reviseddualsimplex_basisfreshtrf(s, at, settings, _state);
56260 : }
56261 : else
56262 : {
56263 0 : processed = ae_false;
56264 0 : if( (s->trftype==0||s->trftype==1)||s->trftype==2 )
56265 : {
56266 :
56267 : /*
56268 : * Dense/sparse factorizations with dense PFI
56269 : */
56270 0 : ae_assert(ae_fp_neq(alphaq->ptr.p_double[r],(double)(0)), "BasisUpdateTrf: integrity check failed, AlphaQ[R]=0", _state);
56271 0 : rvectorgrowto(&s->densepfieta, (s->trfage+1)*m, _state);
56272 0 : ivectorgrowto(&s->rk, s->trfage+1, _state);
56273 0 : s->rk.ptr.p_int[s->trfage] = r;
56274 0 : invaq = 1.0/alphaq->ptr.p_double[r];
56275 0 : for(i=0; i<=m-1; i++)
56276 : {
56277 0 : if( i!=r )
56278 : {
56279 0 : s->densepfieta.ptr.p_double[s->trfage*m+i] = -alphaq->ptr.p_double[i]*invaq;
56280 : }
56281 : else
56282 : {
56283 0 : s->densepfieta.ptr.p_double[s->trfage*m+i] = invaq;
56284 : }
56285 : }
56286 0 : inc(&s->trfage, _state);
56287 0 : s->statupdt = s->statupdt+1;
56288 0 : s->statoffdiag = s->statoffdiag+ae_sqr((double)(m-1), _state);
56289 0 : processed = ae_true;
56290 : }
56291 0 : if( s->trftype==3 )
56292 : {
56293 :
56294 : /*
56295 : * Sparse factorization with Forest-Tomlin update
56296 : */
56297 0 : ae_assert(ae_fp_neq(alphaq->ptr.p_double[r],(double)(0)), "BasisUpdateTrf: integrity check failed, AlphaQ[R]=0", _state);
56298 0 : rvectorgrowto(&s->densemu, (s->trfage+1)*m, _state);
56299 0 : ivectorgrowto(&s->rk, s->trfage+1, _state);
56300 0 : ivectorgrowto(&s->dk, s->trfage+1, _state);
56301 0 : rvectorsetlengthatleast(&s->utmp0, m, _state);
56302 :
56303 : /*
56304 : * Determine D - index of row being overwritten by Forest-Tomlin update
56305 : */
56306 0 : idxd = -1;
56307 0 : for(i=0; i<=m-1; i++)
56308 : {
56309 0 : if( s->rowpermbwd.ptr.p_int[i]==r )
56310 : {
56311 0 : idxd = i;
56312 0 : break;
56313 : }
56314 : }
56315 0 : ae_assert(idxd>=0, "BasisUpdateTrf: unexpected integrity check failure", _state);
56316 0 : s->rk.ptr.p_int[s->trfage] = r;
56317 0 : s->dk.ptr.p_int[s->trfage] = idxd;
56318 :
56319 : /*
56320 : * Modify L with permutation which moves D-th row/column to the end:
56321 : * * rows 0...D-1 are left intact
56322 : * * rows D+1...M-1 are moved one position up, with columns 0..D-1
56323 : * retained as is, and columns D+1...M-1 being moved one position left.
56324 : * * last row is filled by permutation/modification of AlphaQim
56325 : * Determine FT update coefficients in the process.
56326 : */
56327 0 : ivectorgrowto(&s->sparsel.idx, s->sparsel.ridx.ptr.p_int[m]+m, _state);
56328 0 : rvectorgrowto(&s->sparsel.vals, s->sparsel.ridx.ptr.p_int[m]+m, _state);
56329 0 : for(i=0; i<=m-1; i++)
56330 : {
56331 0 : s->utmp0.ptr.p_double[i] = (double)(0);
56332 : }
56333 0 : for(i=idxd+1; i<=m-1; i++)
56334 : {
56335 0 : j = s->sparsel.ridx.ptr.p_int[i+1]-1;
56336 0 : if( s->sparsel.idx.ptr.p_int[j]!=i||s->sparsel.vals.ptr.p_double[j]!=1 )
56337 : {
56338 0 : ae_assert(ae_false, "UpdateTrf: integrity check failed for sparse L", _state);
56339 : }
56340 0 : dstoffs = s->sparsel.ridx.ptr.p_int[i-1];
56341 0 : srcoffs = s->sparsel.ridx.ptr.p_int[i];
56342 :
56343 : /*
56344 : * Read first element in the row (it has at least one - unit diagonal)
56345 : */
56346 0 : srcidx = s->sparsel.idx.ptr.p_int[srcoffs];
56347 0 : srcval = s->sparsel.vals.ptr.p_double[srcoffs];
56348 :
56349 : /*
56350 : * Read/write columns 0...D-1
56351 : */
56352 0 : while(srcidx<idxd)
56353 : {
56354 0 : s->sparsel.idx.ptr.p_int[dstoffs] = srcidx;
56355 0 : s->sparsel.vals.ptr.p_double[dstoffs] = srcval;
56356 0 : dstoffs = dstoffs+1;
56357 0 : srcoffs = srcoffs+1;
56358 0 : srcidx = s->sparsel.idx.ptr.p_int[srcoffs];
56359 0 : srcval = s->sparsel.vals.ptr.p_double[srcoffs];
56360 : }
56361 :
56362 : /*
56363 : * If we have non-zero element in column D, use it as
56364 : * right-hand side of intermediate linear system which
56365 : * is used to determine coefficients of update matrix.
56366 : */
56367 0 : if( srcidx==idxd )
56368 : {
56369 0 : s->utmp0.ptr.p_double[i-1] = srcval;
56370 0 : srcoffs = srcoffs+1;
56371 0 : srcidx = s->sparsel.idx.ptr.p_int[srcoffs];
56372 0 : srcval = s->sparsel.vals.ptr.p_double[srcoffs];
56373 : }
56374 :
56375 : /*
56376 : * Process columns D+1...I-1
56377 : */
56378 0 : v = s->utmp0.ptr.p_double[i-1];
56379 0 : while(srcidx<i)
56380 : {
56381 0 : s->sparsel.idx.ptr.p_int[dstoffs] = srcidx-1;
56382 0 : s->sparsel.vals.ptr.p_double[dstoffs] = srcval;
56383 0 : v = v-srcval*s->utmp0.ptr.p_double[srcidx-1];
56384 0 : dstoffs = dstoffs+1;
56385 0 : srcoffs = srcoffs+1;
56386 0 : srcidx = s->sparsel.idx.ptr.p_int[srcoffs];
56387 0 : srcval = s->sparsel.vals.ptr.p_double[srcoffs];
56388 : }
56389 0 : s->utmp0.ptr.p_double[i-1] = v;
56390 :
56391 : /*
56392 : * Write out unit diagonal, finalize row
56393 : */
56394 0 : s->sparsel.idx.ptr.p_int[dstoffs] = i-1;
56395 0 : s->sparsel.vals.ptr.p_double[dstoffs] = (double)(1);
56396 0 : dstoffs = dstoffs+1;
56397 0 : s->sparsel.ridx.ptr.p_int[i] = dstoffs;
56398 : }
56399 0 : s->utmp0.ptr.p_double[m-1] = (double)(1);
56400 0 : dstoffs = s->sparsel.ridx.ptr.p_int[m-1];
56401 0 : for(j=0; j<=idxd-1; j++)
56402 : {
56403 0 : v = alphaqim->ptr.p_double[j];
56404 0 : if( v!=0 )
56405 : {
56406 0 : s->sparsel.idx.ptr.p_int[dstoffs] = j;
56407 0 : s->sparsel.vals.ptr.p_double[dstoffs] = v;
56408 0 : dstoffs = dstoffs+1;
56409 : }
56410 : }
56411 0 : vcorner = alphaqim->ptr.p_double[idxd];
56412 0 : for(j=idxd+1; j<=m-1; j++)
56413 : {
56414 0 : v = alphaqim->ptr.p_double[j];
56415 0 : if( v!=0 )
56416 : {
56417 0 : s->sparsel.idx.ptr.p_int[dstoffs] = j-1;
56418 0 : s->sparsel.vals.ptr.p_double[dstoffs] = v;
56419 0 : dstoffs = dstoffs+1;
56420 0 : vcorner = vcorner-v*s->utmp0.ptr.p_double[j-1];
56421 : }
56422 : }
56423 0 : s->sparsel.idx.ptr.p_int[dstoffs] = m-1;
56424 0 : s->sparsel.vals.ptr.p_double[dstoffs] = (double)(1);
56425 0 : dstoffs = dstoffs+1;
56426 0 : s->sparsel.ridx.ptr.p_int[m] = dstoffs;
56427 0 : s->sparsel.ninitialized = s->sparsel.ridx.ptr.p_int[m];
56428 0 : for(i=0; i<=m-1; i++)
56429 : {
56430 0 : j = s->sparsel.ridx.ptr.p_int[i+1];
56431 0 : s->sparsel.didx.ptr.p_int[i] = j-1;
56432 0 : s->sparsel.uidx.ptr.p_int[i] = j;
56433 : }
56434 0 : ae_assert(vcorner!=0, "UpdateTrf: corner element is zero, degeneracy detected", _state);
56435 0 : v = 1/vcorner;
56436 0 : for(i=0; i<=m-2; i++)
56437 : {
56438 0 : s->densemu.ptr.p_double[s->trfage*m+i] = -s->utmp0.ptr.p_double[i]*v;
56439 : }
56440 0 : s->densemu.ptr.p_double[s->trfage*m+m-1] = v;
56441 :
56442 : /*
56443 : * Multiply row permutation matrix by cyclic permutation applied to L
56444 : */
56445 0 : reviseddualsimplex_inversecyclicpermutation(&s->rowpermbwd, m, idxd, &s->utmpi, _state);
56446 :
56447 : /*
56448 : * Done
56449 : */
56450 0 : inc(&s->trfage, _state);
56451 0 : s->statupdt = s->statupdt+1;
56452 0 : s->statoffdiag = s->statoffdiag+(s->sparsel.ridx.ptr.p_int[m]-m)+(s->sparseu.ridx.ptr.p_int[m]-m);
56453 0 : processed = ae_true;
56454 : }
56455 0 : ae_assert(processed, "BasisUpdateTrf: unexpected TRF type", _state);
56456 : }
56457 :
56458 : /*
56459 : * Update pricing weights
56460 : */
56461 0 : ae_assert((settings->pricing==-1||settings->pricing==0)||settings->pricing==1, "BasisUpdateTrf: unexpected Settings.Pricing", _state);
56462 0 : processed = ae_false;
56463 0 : if( settings->pricing==-1 )
56464 : {
56465 :
56466 : /*
56467 : * Weights are recomputed from scratch at every step.
56468 : * VERY, VERY time consuming, used only for debug purposes.
56469 : */
56470 0 : s->dsevalid = ae_false;
56471 0 : reviseddualsimplex_basisrequestweights(s, settings, _state);
56472 0 : processed = ae_true;
56473 : }
56474 0 : if( settings->pricing==0 )
56475 : {
56476 :
56477 : /*
56478 : * Weights are filled by 1.0
56479 : */
56480 0 : if( !s->dsevalid )
56481 : {
56482 0 : for(i=0; i<=m-1; i++)
56483 : {
56484 0 : s->dseweights.ptr.p_double[i] = 1.0;
56485 : }
56486 0 : s->dsevalid = ae_true;
56487 : }
56488 0 : processed = ae_true;
56489 : }
56490 0 : if( settings->pricing==1 )
56491 : {
56492 :
56493 : /*
56494 : * Weights are computed using DSE update formula.
56495 : */
56496 0 : if( s->dsevalid )
56497 : {
56498 :
56499 : /*
56500 : * Compute using update formula
56501 : */
56502 0 : for(i=0; i<=m-1; i++)
56503 : {
56504 0 : if( i!=r )
56505 : {
56506 0 : s->dseweights.ptr.p_double[i] = s->dseweights.ptr.p_double[i]-2*(alphaq->ptr.p_double[i]/alphaq->ptr.p_double[r])*tau->ptr.p_double[i]+s->dseweights.ptr.p_double[r]*ae_sqr(alphaq->ptr.p_double[i]/alphaq->ptr.p_double[r], _state);
56507 0 : s->dseweights.ptr.p_double[i] = ae_maxreal(s->dseweights.ptr.p_double[i], reviseddualsimplex_minbeta, _state);
56508 : }
56509 : }
56510 0 : s->dseweights.ptr.p_double[r] = s->dseweights.ptr.p_double[r]/(alphaq->ptr.p_double[r]*alphaq->ptr.p_double[r]);
56511 : }
56512 : else
56513 : {
56514 :
56515 : /*
56516 : * No prior values, compute from scratch (usually it is done only once)
56517 : */
56518 0 : reviseddualsimplex_basisrequestweights(s, settings, _state);
56519 : }
56520 0 : processed = ae_true;
56521 : }
56522 0 : ae_assert(processed, "BasisUpdateTrf: unexpected pricing type", _state);
56523 0 : }
56524 :
56525 :
56526 : /*************************************************************************
56527 : This function computes solution to B*x=r.
56528 :
56529 : Output array is reallocated if needed. Temporary array TmpX[] is used and
56530 : reallocated if necessary.
56531 :
56532 : -- ALGLIB --
56533 : Copyright 19.07.2018 by Bochkanov Sergey
56534 : *************************************************************************/
56535 0 : static void reviseddualsimplex_basissolve(dualsimplexbasis* s,
56536 : /* Real */ ae_vector* r,
56537 : /* Real */ ae_vector* x,
56538 : /* Real */ ae_vector* tmpx,
56539 : ae_state *_state)
56540 : {
56541 :
56542 :
56543 0 : reviseddualsimplex_basissolvex(s, r, x, x, ae_false, tmpx, _state);
56544 0 : }
56545 :
56546 :
56547 : /*************************************************************************
56548 : This function computes solution to B*x=r. It also additionally outputs
56549 : intermediate result of multiplication by inv(DS)*inv(U)*inv(colPerm), a
56550 : value essential for Forest-Tomlin update.
56551 :
56552 : Output arrays are reallocated if needed. Temporary array TX[] can be
56553 : used/reallocated.
56554 :
56555 : If NeedIntermediate is False or Forest-Tomlin updates are not used,
56556 : then Xim[] is not referenced at all.
56557 :
56558 : -- ALGLIB --
56559 : Copyright 19.07.2018 by Bochkanov Sergey
56560 : *************************************************************************/
56561 0 : static void reviseddualsimplex_basissolvex(dualsimplexbasis* s,
56562 : /* Real */ ae_vector* r,
56563 : /* Real */ ae_vector* x,
56564 : /* Real */ ae_vector* xim,
56565 : ae_bool needintermediate,
56566 : /* Real */ ae_vector* tx,
56567 : ae_state *_state)
56568 : {
56569 : ae_int_t m;
56570 : ae_int_t i;
56571 : ae_int_t d;
56572 : ae_int_t k;
56573 : double v;
56574 : double vd;
56575 : double vv;
56576 : ae_bool processed;
56577 :
56578 :
56579 0 : ae_assert(s->isvalidtrf, "BasisSolve: integrity check failed", _state);
56580 0 : m = s->m;
56581 0 : processed = ae_false;
56582 0 : rvectorsetlengthatleast(tx, m, _state);
56583 :
56584 : /*
56585 : * Dense/sparse factorizations with dense PFI
56586 : *
56587 : * NOTE: although we solve B*x=r, internally we store factorization of B^T
56588 : */
56589 0 : if( (s->trftype==0||s->trftype==1)||s->trftype==2 )
56590 : {
56591 0 : ae_assert(s->trfage==0||s->trftype!=0, "BasisSolve: integrity check failed TrfAge vs TrfType", _state);
56592 0 : rvectorsetlengthatleast(x, m, _state);
56593 0 : for(i=0; i<=m-1; i++)
56594 : {
56595 0 : x->ptr.p_double[i] = r->ptr.p_double[s->colpermbwd.ptr.p_int[i]];
56596 : }
56597 0 : if( s->trftype==0||s->trftype==1 )
56598 : {
56599 :
56600 : /*
56601 : * Dense TRF
56602 : */
56603 0 : rmatrixtrsv(m, &s->denselu, 0, 0, ae_true, ae_false, 1, x, 0, _state);
56604 0 : rmatrixtrsv(m, &s->denselu, 0, 0, ae_false, ae_true, 1, x, 0, _state);
56605 : }
56606 : else
56607 : {
56608 :
56609 : /*
56610 : * Sparse TRF
56611 : */
56612 0 : sparsetrsv(&s->sparseu, ae_true, ae_false, 1, x, _state);
56613 0 : sparsetrsv(&s->sparsel, ae_false, ae_false, 1, x, _state);
56614 : }
56615 0 : for(i=0; i<=m-1; i++)
56616 : {
56617 0 : tx->ptr.p_double[s->rowpermbwd.ptr.p_int[i]] = x->ptr.p_double[i];
56618 : }
56619 0 : for(i=0; i<=m-1; i++)
56620 : {
56621 0 : x->ptr.p_double[i] = tx->ptr.p_double[i];
56622 : }
56623 0 : for(k=0; k<=s->trfage-1; k++)
56624 : {
56625 0 : v = x->ptr.p_double[s->rk.ptr.p_int[k]];
56626 0 : for(i=0; i<=m-1; i++)
56627 : {
56628 0 : x->ptr.p_double[i] = x->ptr.p_double[i]+s->densepfieta.ptr.p_double[k*m+i]*v;
56629 : }
56630 0 : x->ptr.p_double[s->rk.ptr.p_int[k]] = x->ptr.p_double[s->rk.ptr.p_int[k]]-v;
56631 : }
56632 0 : processed = ae_true;
56633 : }
56634 :
56635 : /*
56636 : * Sparse factorization with Forest-Tomlin update
56637 : *
56638 : * NOTE: although we solve B*x=r, internally we store factorization of B^T
56639 : */
56640 0 : if( s->trftype==3 )
56641 : {
56642 0 : rvectorsetlengthatleast(x, m, _state);
56643 0 : for(i=0; i<=m-1; i++)
56644 : {
56645 0 : x->ptr.p_double[i] = r->ptr.p_double[s->colpermbwd.ptr.p_int[i]];
56646 : }
56647 0 : sparsetrsv(&s->sparseu, ae_true, ae_false, 1, x, _state);
56648 0 : for(k=0; k<=s->trfage-1; k++)
56649 : {
56650 :
56651 : /*
56652 : * The code below is an amalgamation of two parts:
56653 : *
56654 : * cyclic permutation
56655 : * V:=X[D];
56656 : * for I:=D to M-2 do
56657 : * X[I]:=X[I+1];
56658 : * X[M-1]:=V;
56659 : *
56660 : * and triangular factor
56661 : * V:=0;
56662 : * for I:=D to M-1 do
56663 : * V:=V+X[I]*S.DenseMu[K*M+I];
56664 : * X[M-1]:=V;
56665 : */
56666 0 : d = s->dk.ptr.p_int[k];
56667 0 : vv = (double)(0);
56668 0 : vd = x->ptr.p_double[d];
56669 0 : for(i=d; i<=m-2; i++)
56670 : {
56671 0 : v = x->ptr.p_double[i+1];
56672 0 : x->ptr.p_double[i] = v;
56673 0 : vv = vv+v*s->densemu.ptr.p_double[k*m+i];
56674 : }
56675 0 : x->ptr.p_double[m-1] = vv+vd*s->densemu.ptr.p_double[k*m+m-1];
56676 : }
56677 0 : if( needintermediate )
56678 : {
56679 0 : rvectorsetlengthatleast(xim, m, _state);
56680 0 : for(i=0; i<=m-1; i++)
56681 : {
56682 0 : xim->ptr.p_double[i] = x->ptr.p_double[i];
56683 : }
56684 : }
56685 0 : sparsetrsv(&s->sparsel, ae_false, ae_false, 1, x, _state);
56686 0 : for(i=0; i<=m-1; i++)
56687 : {
56688 0 : tx->ptr.p_double[s->rowpermbwd.ptr.p_int[i]] = x->ptr.p_double[i];
56689 : }
56690 0 : for(i=0; i<=m-1; i++)
56691 : {
56692 0 : x->ptr.p_double[i] = tx->ptr.p_double[i];
56693 : }
56694 0 : processed = ae_true;
56695 : }
56696 :
56697 : /*
56698 : * Integrity check
56699 : */
56700 0 : ae_assert(processed, "BasisSolve: unsupported TRF type", _state);
56701 0 : v = (double)(0);
56702 0 : for(i=0; i<=m-1; i++)
56703 : {
56704 0 : v = v+x->ptr.p_double[i];
56705 : }
56706 0 : ae_assert(ae_isfinite(v, _state), "BasisSolve: integrity check failed (degeneracy in B?)", _state);
56707 0 : }
56708 :
56709 :
56710 : /*************************************************************************
56711 : This function computes solution to (B^T)*x=r.
56712 :
56713 : Output array is reallocated if needed. TX[] temporary is reallocated if
56714 : needed
56715 :
56716 : -- ALGLIB --
56717 : Copyright 19.07.2018 by Bochkanov Sergey
56718 : *************************************************************************/
56719 0 : static void reviseddualsimplex_basissolvet(dualsimplexbasis* s,
56720 : /* Real */ ae_vector* r,
56721 : /* Real */ ae_vector* x,
56722 : /* Real */ ae_vector* tx,
56723 : ae_state *_state)
56724 : {
56725 : ae_int_t m;
56726 : ae_int_t i;
56727 : ae_int_t d;
56728 : ae_int_t k;
56729 : double v;
56730 : double vm;
56731 : ae_bool processed;
56732 :
56733 :
56734 0 : ae_assert(s->isvalidtrf, "BasisSolveT: integrity check failed", _state);
56735 0 : m = s->m;
56736 0 : processed = ae_false;
56737 0 : rvectorsetlengthatleast(tx, m, _state);
56738 :
56739 : /*
56740 : * Dense factorizations
56741 : */
56742 0 : if( (s->trftype==0||s->trftype==1)||s->trftype==2 )
56743 : {
56744 0 : ae_assert(s->trfage==0||s->trftype!=0, "BasisSolveT: integrity check failed TrfAge vs TrfType", _state);
56745 0 : rvectorsetlengthatleast(x, m, _state);
56746 0 : for(i=0; i<=m-1; i++)
56747 : {
56748 0 : x->ptr.p_double[i] = r->ptr.p_double[i];
56749 : }
56750 0 : for(k=s->trfage-1; k>=0; k--)
56751 : {
56752 0 : v = (double)(0);
56753 0 : for(i=0; i<=m-1; i++)
56754 : {
56755 0 : v = v+s->densepfieta.ptr.p_double[k*m+i]*x->ptr.p_double[i];
56756 : }
56757 0 : x->ptr.p_double[s->rk.ptr.p_int[k]] = v;
56758 : }
56759 0 : for(i=0; i<=m-1; i++)
56760 : {
56761 0 : tx->ptr.p_double[i] = x->ptr.p_double[s->rowpermbwd.ptr.p_int[i]];
56762 : }
56763 0 : for(i=0; i<=m-1; i++)
56764 : {
56765 0 : x->ptr.p_double[i] = tx->ptr.p_double[i];
56766 : }
56767 0 : if( s->trftype==0||s->trftype==1 )
56768 : {
56769 :
56770 : /*
56771 : * Dense TRF
56772 : */
56773 0 : rmatrixtrsv(m, &s->denselu, 0, 0, ae_false, ae_true, 0, x, 0, _state);
56774 0 : rmatrixtrsv(m, &s->denselu, 0, 0, ae_true, ae_false, 0, x, 0, _state);
56775 : }
56776 : else
56777 : {
56778 :
56779 : /*
56780 : * Sparse TRF
56781 : */
56782 0 : sparsetrsv(&s->sparsel, ae_false, ae_false, 0, x, _state);
56783 0 : sparsetrsv(&s->sparseu, ae_true, ae_false, 0, x, _state);
56784 : }
56785 0 : for(i=0; i<=m-1; i++)
56786 : {
56787 0 : tx->ptr.p_double[s->colpermbwd.ptr.p_int[i]] = x->ptr.p_double[i];
56788 : }
56789 0 : for(i=0; i<=m-1; i++)
56790 : {
56791 0 : x->ptr.p_double[i] = tx->ptr.p_double[i];
56792 : }
56793 0 : processed = ae_true;
56794 : }
56795 :
56796 : /*
56797 : * Sparse factorization with Forest-Tomlin update
56798 : */
56799 0 : if( s->trftype==3 )
56800 : {
56801 0 : rvectorsetlengthatleast(x, m, _state);
56802 0 : for(i=0; i<=m-1; i++)
56803 : {
56804 0 : x->ptr.p_double[i] = r->ptr.p_double[i];
56805 : }
56806 0 : for(i=0; i<=m-1; i++)
56807 : {
56808 0 : tx->ptr.p_double[i] = x->ptr.p_double[s->rowpermbwd.ptr.p_int[i]];
56809 : }
56810 0 : for(i=0; i<=m-1; i++)
56811 : {
56812 0 : x->ptr.p_double[i] = tx->ptr.p_double[i];
56813 : }
56814 0 : sparsetrsv(&s->sparsel, ae_false, ae_false, 0, x, _state);
56815 0 : for(k=s->trfage-1; k>=0; k--)
56816 : {
56817 :
56818 : /*
56819 : * The code below is an amalgamation of two parts:
56820 : *
56821 : * triangular factor
56822 : * V:=X[M-1];
56823 : * for I:=D to M-2 do
56824 : * X[I]:=X[I]+S.DenseMu[K*M+I]*V;
56825 : * X[M-1]:=S.DenseMu[K*M+(M-1)]*V;
56826 : *
56827 : * inverse of cyclic permutation
56828 : * V:=X[M-1];
56829 : * for I:=M-1 downto D+1 do
56830 : * X[I]:=X[I-1];
56831 : * X[D]:=V;
56832 : */
56833 0 : d = s->dk.ptr.p_int[k];
56834 0 : vm = x->ptr.p_double[m-1];
56835 0 : v = s->densemu.ptr.p_double[k*m+(m-1)]*vm;
56836 0 : if( vm!=0 )
56837 : {
56838 :
56839 : /*
56840 : * X[M-1] is non-zero, apply update
56841 : */
56842 0 : for(i=m-2; i>=d; i--)
56843 : {
56844 0 : x->ptr.p_double[i+1] = x->ptr.p_double[i]+s->densemu.ptr.p_double[k*m+i]*vm;
56845 : }
56846 : }
56847 : else
56848 : {
56849 :
56850 : /*
56851 : * X[M-1] is zero, just cyclic permutation
56852 : */
56853 0 : for(i=m-2; i>=d; i--)
56854 : {
56855 0 : x->ptr.p_double[i+1] = x->ptr.p_double[i];
56856 : }
56857 : }
56858 0 : x->ptr.p_double[d] = v;
56859 : }
56860 0 : sparsetrsv(&s->sparseut, ae_false, ae_false, 1, x, _state);
56861 0 : for(i=0; i<=m-1; i++)
56862 : {
56863 0 : tx->ptr.p_double[s->colpermbwd.ptr.p_int[i]] = x->ptr.p_double[i];
56864 : }
56865 0 : for(i=0; i<=m-1; i++)
56866 : {
56867 0 : x->ptr.p_double[i] = tx->ptr.p_double[i];
56868 : }
56869 0 : processed = ae_true;
56870 : }
56871 :
56872 : /*
56873 : * Integrity check
56874 : */
56875 0 : ae_assert(processed, "BasisSolveT: unsupported TRF type", _state);
56876 0 : v = (double)(0);
56877 0 : for(i=0; i<=m-1; i++)
56878 : {
56879 0 : v = v+x->ptr.p_double[i];
56880 : }
56881 0 : ae_assert(ae_isfinite(v, _state), "BasisSolveT: integrity check failed (degeneracy in B?)", _state);
56882 0 : }
56883 :
56884 :
56885 : /*************************************************************************
56886 : This function computes product AN*XN, where AN is a non-basic subset of
56887 : columns of A, and XN is a non-basic subset of columns of X.
56888 :
56889 : Output array is reallocated if its size is too small.
56890 :
56891 : -- ALGLIB --
56892 : Copyright 19.07.2018 by Bochkanov Sergey
56893 : *************************************************************************/
56894 0 : static void reviseddualsimplex_computeanxn(dualsimplexstate* state,
56895 : dualsimplexsubproblem* subproblem,
56896 : /* Real */ ae_vector* x,
56897 : /* Real */ ae_vector* y,
56898 : ae_state *_state)
56899 : {
56900 : ae_int_t nn;
56901 : ae_int_t nx;
56902 : ae_int_t m;
56903 : ae_int_t i;
56904 : ae_int_t j;
56905 : ae_int_t k;
56906 : ae_int_t j0;
56907 : ae_int_t j1;
56908 : double v;
56909 :
56910 :
56911 0 : nx = subproblem->ns+subproblem->m;
56912 0 : m = subproblem->m;
56913 0 : nn = nx-m;
56914 :
56915 : /*
56916 : * Integrity check
56917 : */
56918 0 : ae_assert(subproblem->state>=reviseddualsimplex_ssvalidxn, "ComputeANXN: XN is invalid", _state);
56919 :
56920 : /*
56921 : * Compute
56922 : */
56923 0 : rvectorsetlengthatleast(y, m, _state);
56924 0 : for(i=0; i<=m-1; i++)
56925 : {
56926 0 : y->ptr.p_double[i] = (double)(0);
56927 : }
56928 0 : for(i=0; i<=nn-1; i++)
56929 : {
56930 0 : j0 = state->at.ridx.ptr.p_int[state->basis.nidx.ptr.p_int[i]];
56931 0 : j1 = state->at.ridx.ptr.p_int[state->basis.nidx.ptr.p_int[i]+1]-1;
56932 0 : v = x->ptr.p_double[state->basis.nidx.ptr.p_int[i]];
56933 0 : for(j=j0; j<=j1; j++)
56934 : {
56935 0 : k = state->at.idx.ptr.p_int[j];
56936 0 : y->ptr.p_double[k] = y->ptr.p_double[k]+v*state->at.vals.ptr.p_double[j];
56937 : }
56938 : }
56939 0 : }
56940 :
56941 :
56942 : /*************************************************************************
56943 : This function computes product (AN^T)*y, where AN is a non-basic subset of
56944 : columns of A, and y is some vector.
56945 :
56946 : Output array is set to full NX-sized length, with basic components of the
56947 : output being set to zeros.
56948 :
56949 : -- ALGLIB --
56950 : Copyright 19.07.2018 by Bochkanov Sergey
56951 : *************************************************************************/
56952 0 : static void reviseddualsimplex_computeantv(dualsimplexstate* state,
56953 : /* Real */ ae_vector* y,
56954 : /* Real */ ae_vector* r,
56955 : ae_state *_state)
56956 : {
56957 : ae_int_t nn;
56958 : ae_int_t nx;
56959 : ae_int_t m;
56960 : ae_int_t i;
56961 : ae_int_t j;
56962 : ae_int_t j0;
56963 : ae_int_t j1;
56964 : double v;
56965 :
56966 :
56967 0 : nx = state->ns+state->m;
56968 0 : m = state->m;
56969 0 : nn = nx-m;
56970 :
56971 : /*
56972 : * Allocate output, set to zero
56973 : */
56974 0 : rvectorsetlengthatleast(r, nx, _state);
56975 0 : for(i=0; i<=nx-1; i++)
56976 : {
56977 0 : r->ptr.p_double[i] = (double)(0);
56978 : }
56979 0 : for(i=0; i<=nn-1; i++)
56980 : {
56981 0 : j0 = state->at.ridx.ptr.p_int[state->basis.nidx.ptr.p_int[i]];
56982 0 : j1 = state->at.ridx.ptr.p_int[state->basis.nidx.ptr.p_int[i]+1]-1;
56983 0 : v = (double)(0);
56984 0 : for(j=j0; j<=j1; j++)
56985 : {
56986 0 : v = v+state->at.vals.ptr.p_double[j]*y->ptr.p_double[state->at.idx.ptr.p_int[j]];
56987 : }
56988 0 : r->ptr.p_double[state->basis.nidx.ptr.p_int[i]] = v;
56989 : }
56990 0 : }
56991 :
56992 :
56993 : /*************************************************************************
56994 : Returns True if I-th lower bound is present
56995 :
56996 : -- ALGLIB --
56997 : Copyright 19.07.2018 by Bochkanov Sergey
56998 : *************************************************************************/
56999 0 : static ae_bool reviseddualsimplex_hasbndl(dualsimplexsubproblem* subproblem,
57000 : ae_int_t i,
57001 : ae_state *_state)
57002 : {
57003 : ae_int_t k;
57004 : ae_bool result;
57005 :
57006 :
57007 0 : k = subproblem->bndt.ptr.p_int[i];
57008 0 : result = ae_false;
57009 0 : if( (k==0||k==1)||k==3 )
57010 : {
57011 0 : result = ae_true;
57012 0 : return result;
57013 : }
57014 0 : if( k==2||k==4 )
57015 : {
57016 0 : result = ae_false;
57017 0 : return result;
57018 : }
57019 0 : ae_assert(ae_false, "HasBndL: integrity check failed", _state);
57020 0 : return result;
57021 : }
57022 :
57023 :
57024 : /*************************************************************************
57025 : Returns True if I-th upper bound is present
57026 :
57027 : -- ALGLIB --
57028 : Copyright 19.07.2018 by Bochkanov Sergey
57029 : *************************************************************************/
57030 0 : static ae_bool reviseddualsimplex_hasbndu(dualsimplexsubproblem* subproblem,
57031 : ae_int_t i,
57032 : ae_state *_state)
57033 : {
57034 : ae_int_t k;
57035 : ae_bool result;
57036 :
57037 :
57038 0 : k = subproblem->bndt.ptr.p_int[i];
57039 0 : result = ae_false;
57040 0 : if( (k==0||k==2)||k==3 )
57041 : {
57042 0 : result = ae_true;
57043 0 : return result;
57044 : }
57045 0 : if( k==1||k==4 )
57046 : {
57047 0 : result = ae_false;
57048 0 : return result;
57049 : }
57050 0 : ae_assert(ae_false, "HasBndL: integrity check failed", _state);
57051 0 : return result;
57052 : }
57053 :
57054 :
57055 : /*************************************************************************
57056 : Returns True if I-th variable if free
57057 :
57058 : -- ALGLIB --
57059 : Copyright 19.07.2018 by Bochkanov Sergey
57060 : *************************************************************************/
57061 0 : static ae_bool reviseddualsimplex_isfree(dualsimplexsubproblem* subproblem,
57062 : ae_int_t i,
57063 : ae_state *_state)
57064 : {
57065 : ae_int_t k;
57066 : ae_bool result;
57067 :
57068 :
57069 0 : k = subproblem->bndt.ptr.p_int[i];
57070 0 : result = ae_false;
57071 0 : if( ((k==0||k==1)||k==2)||k==3 )
57072 : {
57073 0 : result = ae_false;
57074 0 : return result;
57075 : }
57076 0 : if( k==4 )
57077 : {
57078 0 : result = ae_true;
57079 0 : return result;
57080 : }
57081 0 : ae_assert(ae_false, "IsFree: integrity check failed", _state);
57082 0 : return result;
57083 : }
57084 :
57085 :
57086 : /*************************************************************************
57087 : Downgrades problem state to the specified one (if status is lower than one
57088 : specified by user, nothing is changed)
57089 :
57090 : -- ALGLIB --
57091 : Copyright 19.07.2018 by Bochkanov Sergey
57092 : *************************************************************************/
57093 0 : static void reviseddualsimplex_downgradestate(dualsimplexsubproblem* subproblem,
57094 : ae_int_t s,
57095 : ae_state *_state)
57096 : {
57097 :
57098 :
57099 0 : subproblem->state = ae_minint(subproblem->state, s, _state);
57100 0 : }
57101 :
57102 :
57103 : /*************************************************************************
57104 : Returns maximum dual infeasibility (only non-basic variables are checked,
57105 : we assume that basic variables are good enough).
57106 :
57107 : -- ALGLIB --
57108 : Copyright 19.07.2018 by Bochkanov Sergey
57109 : *************************************************************************/
57110 0 : static double reviseddualsimplex_dualfeasibilityerror(dualsimplexstate* state,
57111 : dualsimplexsubproblem* s,
57112 : ae_state *_state)
57113 : {
57114 : ae_int_t i;
57115 : ae_int_t j;
57116 : ae_int_t nn;
57117 : ae_int_t bndt;
57118 : double result;
57119 :
57120 :
57121 0 : nn = s->ns;
57122 0 : ae_assert(s->state==reviseddualsimplex_ssvalid, "DualFeasibilityError: invalid X", _state);
57123 0 : result = (double)(0);
57124 0 : for(i=0; i<=nn-1; i++)
57125 : {
57126 0 : j = state->basis.nidx.ptr.p_int[i];
57127 0 : bndt = s->bndt.ptr.p_int[j];
57128 0 : if( bndt==reviseddualsimplex_ccfixed )
57129 : {
57130 0 : continue;
57131 : }
57132 0 : if( bndt==reviseddualsimplex_ccrange )
57133 : {
57134 0 : if( s->xa.ptr.p_double[j]==s->bndl.ptr.p_double[j] )
57135 : {
57136 0 : result = ae_maxreal(result, -s->d.ptr.p_double[j], _state);
57137 0 : continue;
57138 : }
57139 0 : if( s->xa.ptr.p_double[j]==s->bndu.ptr.p_double[j] )
57140 : {
57141 0 : result = ae_maxreal(result, s->d.ptr.p_double[j], _state);
57142 0 : continue;
57143 : }
57144 0 : ae_assert(ae_false, "DualFeasibilityError: integrity check failed", _state);
57145 : }
57146 0 : if( bndt==reviseddualsimplex_cclower )
57147 : {
57148 0 : ae_assert(s->xa.ptr.p_double[j]==s->bndl.ptr.p_double[j], "DualFeasibilityError: integrity check failed", _state);
57149 0 : result = ae_maxreal(result, -s->d.ptr.p_double[j], _state);
57150 0 : continue;
57151 : }
57152 0 : if( bndt==reviseddualsimplex_ccupper )
57153 : {
57154 0 : ae_assert(s->xa.ptr.p_double[j]==s->bndu.ptr.p_double[j], "DualFeasibilityError: integrity check failed", _state);
57155 0 : result = ae_maxreal(result, s->d.ptr.p_double[j], _state);
57156 0 : continue;
57157 : }
57158 0 : if( bndt==reviseddualsimplex_ccfree )
57159 : {
57160 0 : result = ae_maxreal(result, ae_fabs(s->d.ptr.p_double[j], _state), _state);
57161 0 : continue;
57162 : }
57163 0 : ae_assert(ae_false, "DSSOptimize: integrity check failed (infeasible constraint)", _state);
57164 : }
57165 0 : return result;
57166 : }
57167 :
57168 :
57169 : /*************************************************************************
57170 : Returns True for dual feasible basis (some minor dual feasibility error is
57171 : allowed), False otherwise
57172 :
57173 : -- ALGLIB --
57174 : Copyright 19.07.2018 by Bochkanov Sergey
57175 : *************************************************************************/
57176 0 : static ae_bool reviseddualsimplex_isdualfeasible(dualsimplexstate* state,
57177 : dualsimplexsubproblem* s,
57178 : dualsimplexsettings* settings,
57179 : ae_state *_state)
57180 : {
57181 : ae_bool result;
57182 :
57183 :
57184 0 : result = ae_fp_less_eq(reviseddualsimplex_dualfeasibilityerror(state, s, _state),settings->dtolabs);
57185 0 : return result;
57186 : }
57187 :
57188 :
57189 : /*************************************************************************
57190 : Transforms sequence of pivot permutations P0*P1*...*Pm to forward/backward
57191 : permutation representation.
57192 :
57193 : -- ALGLIB --
57194 : Copyright 12.09.2018 by Bochkanov Sergey
57195 : *************************************************************************/
57196 0 : static void reviseddualsimplex_pivottobwd(/* Integer */ ae_vector* p,
57197 : ae_int_t m,
57198 : /* Integer */ ae_vector* bwd,
57199 : ae_state *_state)
57200 : {
57201 : ae_int_t i;
57202 : ae_int_t k;
57203 : ae_int_t t;
57204 :
57205 :
57206 0 : ivectorsetlengthatleast(bwd, m, _state);
57207 0 : for(i=0; i<=m-1; i++)
57208 : {
57209 0 : bwd->ptr.p_int[i] = i;
57210 : }
57211 0 : for(i=0; i<=m-1; i++)
57212 : {
57213 0 : k = p->ptr.p_int[i];
57214 0 : if( k!=i )
57215 : {
57216 0 : t = bwd->ptr.p_int[i];
57217 0 : bwd->ptr.p_int[i] = bwd->ptr.p_int[k];
57218 0 : bwd->ptr.p_int[k] = t;
57219 : }
57220 : }
57221 0 : }
57222 :
57223 :
57224 : /*************************************************************************
57225 : Applies inverse cyclic permutation of [D,M-1) (element D is moved to the end, the
57226 : rest of elements is shifted one position backward) to the already existing
57227 : permutation.
57228 :
57229 : -- ALGLIB --
57230 : Copyright 12.09.2018 by Bochkanov Sergey
57231 : *************************************************************************/
57232 0 : static void reviseddualsimplex_inversecyclicpermutation(/* Integer */ ae_vector* bwd,
57233 : ae_int_t m,
57234 : ae_int_t d,
57235 : /* Integer */ ae_vector* tmpi,
57236 : ae_state *_state)
57237 : {
57238 : ae_int_t i;
57239 : ae_int_t k;
57240 :
57241 :
57242 :
57243 : /*
57244 : * update Bwd[]
57245 : */
57246 0 : k = bwd->ptr.p_int[d];
57247 0 : for(i=d; i<=m-2; i++)
57248 : {
57249 0 : bwd->ptr.p_int[i] = bwd->ptr.p_int[i+1];
57250 : }
57251 0 : bwd->ptr.p_int[m-1] = k;
57252 0 : }
57253 :
57254 :
57255 : /*************************************************************************
57256 : Offloads basic components of X[], BndT[], BndL[], BndU[] to XB/BndTB/BndLB/BndUB.
57257 :
57258 : -- ALGLIB --
57259 : Copyright 24.01.2019 by Bochkanov Sergey
57260 : *************************************************************************/
57261 0 : static void reviseddualsimplex_offloadbasiccomponents(dualsimplexsubproblem* s,
57262 : dualsimplexbasis* basis,
57263 : dualsimplexsettings* settings,
57264 : ae_state *_state)
57265 : {
57266 : ae_int_t i;
57267 : ae_int_t m;
57268 :
57269 :
57270 0 : m = basis->m;
57271 0 : for(i=0; i<=m-1; i++)
57272 : {
57273 0 : s->xb.ptr.p_double[i] = s->xa.ptr.p_double[basis->idx.ptr.p_int[i]];
57274 0 : reviseddualsimplex_cacheboundinfo(s, i, basis->idx.ptr.p_int[i], settings, _state);
57275 : }
57276 0 : }
57277 :
57278 :
57279 : /*************************************************************************
57280 : Recombines basic and non-basic components in X[]
57281 :
57282 : -- ALGLIB --
57283 : Copyright 24.01.2019 by Bochkanov Sergey
57284 : *************************************************************************/
57285 0 : static void reviseddualsimplex_recombinebasicnonbasicx(dualsimplexsubproblem* s,
57286 : dualsimplexbasis* basis,
57287 : ae_state *_state)
57288 : {
57289 : ae_int_t m;
57290 : ae_int_t i;
57291 :
57292 :
57293 0 : m = basis->m;
57294 0 : for(i=0; i<=m-1; i++)
57295 : {
57296 0 : s->xa.ptr.p_double[basis->idx.ptr.p_int[i]] = s->xb.ptr.p_double[i];
57297 : }
57298 0 : }
57299 :
57300 :
57301 : /*************************************************************************
57302 : Computes Stats array
57303 :
57304 : INPUT PARAMETERS:
57305 : S - problem, contains current solution at S.XA
57306 : Basis - basis
57307 : X - possibly preallocated output buffer
57308 : LagBC - possibly preallocated output buffer
57309 : LagLC - possibly preallocated output buffer
57310 : Stats - possibly preallocated output buffer
57311 : Buffers - temporary buffers
57312 :
57313 : OUTPUT PARAMETERS:
57314 : X - array[NS], solution
57315 : LagBC - array[NS], Lagrange multipliers for box constraints
57316 : LagLC - array[M], Lagrange multipliers for linear constraints
57317 : Stats - array[NS+M], primary/slack variable stats:
57318 : * -1 = variable at lower bound
57319 : * +1 = variable at upper bound
57320 : * 0 = basic or free (possibly nonbasic) variable
57321 : fixed variables may be set to +1 or -1
57322 :
57323 : -- ALGLIB --
57324 : Copyright 24.01.2019 by Bochkanov Sergey
57325 : *************************************************************************/
57326 0 : static void reviseddualsimplex_setxydstats(dualsimplexstate* state,
57327 : dualsimplexsubproblem* s,
57328 : dualsimplexbasis* basis,
57329 : apbuffers* buffers,
57330 : /* Real */ ae_vector* x,
57331 : /* Real */ ae_vector* lagbc,
57332 : /* Real */ ae_vector* laglc,
57333 : /* Integer */ ae_vector* stats,
57334 : ae_state *_state)
57335 : {
57336 : ae_int_t i;
57337 : ae_int_t j;
57338 : ae_int_t m;
57339 : ae_int_t ns;
57340 : ae_int_t nx;
57341 :
57342 :
57343 :
57344 : /*
57345 : * Prepare
57346 : */
57347 0 : m = s->m;
57348 0 : ns = s->ns;
57349 0 : nx = s->ns+s->m;
57350 0 : rvectorsetlengthatleast(x, ns, _state);
57351 0 : rvectorsetlengthatleast(laglc, m, _state);
57352 0 : ivectorsetlengthatleast(stats, nx, _state);
57353 0 : rsetallocv(ns, 0.0, lagbc, _state);
57354 :
57355 : /*
57356 : * Compute Y (in Buffers.RA1) and D (in Buffers.RA3)
57357 : */
57358 0 : rvectorsetlengthatleast(&buffers->ra0, m, _state);
57359 0 : rvectorsetlengthatleast(&buffers->ra1, m, _state);
57360 0 : rvectorsetlengthatleast(&buffers->ra3, nx, _state);
57361 0 : for(i=0; i<=m-1; i++)
57362 : {
57363 0 : buffers->ra0.ptr.p_double[i] = s->rawc.ptr.p_double[basis->idx.ptr.p_int[i]];
57364 : }
57365 0 : reviseddualsimplex_basissolvet(basis, &buffers->ra0, &buffers->ra1, &buffers->ra2, _state);
57366 0 : reviseddualsimplex_computeantv(state, &buffers->ra1, &buffers->ra3, _state);
57367 0 : for(i=0; i<=ns-1; i++)
57368 : {
57369 0 : j = state->basis.nidx.ptr.p_int[i];
57370 0 : buffers->ra3.ptr.p_double[j] = state->primary.rawc.ptr.p_double[j]-buffers->ra3.ptr.p_double[j];
57371 0 : if( j<ns )
57372 : {
57373 0 : lagbc->ptr.p_double[j] = -buffers->ra3.ptr.p_double[j];
57374 : }
57375 : }
57376 0 : for(i=0; i<=m-1; i++)
57377 : {
57378 0 : buffers->ra3.ptr.p_double[state->basis.idx.ptr.p_int[i]] = (double)(0);
57379 : }
57380 :
57381 : /*
57382 : * Compute X, Y, Stats
57383 : */
57384 0 : for(i=0; i<=ns-1; i++)
57385 : {
57386 0 : x->ptr.p_double[i] = s->xa.ptr.p_double[i];
57387 0 : if( ae_isfinite(state->rawbndl.ptr.p_double[i], _state) )
57388 : {
57389 0 : x->ptr.p_double[i] = ae_maxreal(x->ptr.p_double[i], state->rawbndl.ptr.p_double[i], _state);
57390 : }
57391 0 : if( ae_isfinite(state->rawbndu.ptr.p_double[i], _state) )
57392 : {
57393 0 : x->ptr.p_double[i] = ae_minreal(x->ptr.p_double[i], state->rawbndu.ptr.p_double[i], _state);
57394 : }
57395 : }
57396 0 : for(i=0; i<=ns-1; i++)
57397 : {
57398 0 : if( basis->isbasic.ptr.p_bool[i] )
57399 : {
57400 0 : lagbc->ptr.p_double[i] = (double)(0);
57401 0 : continue;
57402 : }
57403 0 : if( s->bndt.ptr.p_int[i]==reviseddualsimplex_ccfixed )
57404 : {
57405 0 : continue;
57406 : }
57407 0 : if( reviseddualsimplex_hasbndl(s, i, _state)&&ae_fp_eq(s->xa.ptr.p_double[i],s->bndl.ptr.p_double[i]) )
57408 : {
57409 0 : lagbc->ptr.p_double[i] = ae_minreal(lagbc->ptr.p_double[i], 0.0, _state);
57410 0 : continue;
57411 : }
57412 0 : if( reviseddualsimplex_hasbndu(s, i, _state)&&ae_fp_eq(s->xa.ptr.p_double[i],s->bndu.ptr.p_double[i]) )
57413 : {
57414 0 : lagbc->ptr.p_double[i] = ae_maxreal(lagbc->ptr.p_double[i], 0.0, _state);
57415 0 : continue;
57416 : }
57417 0 : ae_assert(!reviseddualsimplex_hasbndl(s, i, _state)&&!reviseddualsimplex_hasbndu(s, i, _state), "SetStats: integrity check failed (zetta5)", _state);
57418 0 : lagbc->ptr.p_double[i] = (double)(0);
57419 : }
57420 0 : for(i=0; i<=m-1; i++)
57421 : {
57422 0 : laglc->ptr.p_double[i] = -buffers->ra1.ptr.p_double[i]/state->rowscales.ptr.p_double[i];
57423 : }
57424 0 : for(i=0; i<=nx-1; i++)
57425 : {
57426 0 : if( basis->isbasic.ptr.p_bool[i] )
57427 : {
57428 0 : stats->ptr.p_int[i] = 0;
57429 0 : continue;
57430 : }
57431 0 : if( reviseddualsimplex_hasbndl(s, i, _state)&&ae_fp_eq(s->xa.ptr.p_double[i],s->bndl.ptr.p_double[i]) )
57432 : {
57433 0 : stats->ptr.p_int[i] = -1;
57434 0 : continue;
57435 : }
57436 0 : if( reviseddualsimplex_hasbndu(s, i, _state)&&ae_fp_eq(s->xa.ptr.p_double[i],s->bndu.ptr.p_double[i]) )
57437 : {
57438 0 : stats->ptr.p_int[i] = 1;
57439 0 : continue;
57440 : }
57441 0 : ae_assert(!reviseddualsimplex_hasbndl(s, i, _state)&&!reviseddualsimplex_hasbndu(s, i, _state), "SetStats: integrity check failed (zetta5)", _state);
57442 0 : stats->ptr.p_int[i] = 0;
57443 : }
57444 0 : }
57445 :
57446 :
57447 : /*************************************************************************
57448 : Initializes vector, sets all internal arrays to length N (so that we may
57449 : store any vector without reallocation). Previously allocated memory is
57450 : reused as much as possible.
57451 :
57452 : No zero-filling is performed, X.K is undefined. Only X.N is set.
57453 :
57454 : INPUT PARAMETERS:
57455 : X - temporary buffers
57456 :
57457 : OUTPUT PARAMETERS:
57458 : X - preallocated vector, X.N=N, contents undefined
57459 :
57460 : -- ALGLIB --
57461 : Copyright 24.07.2020 by Bochkanov Sergey
57462 : *************************************************************************/
57463 0 : static void reviseddualsimplex_dvalloc(dssvector* x,
57464 : ae_int_t n,
57465 : ae_state *_state)
57466 : {
57467 :
57468 :
57469 0 : ivectorsetlengthatleast(&x->idx, n, _state);
57470 0 : rvectorsetlengthatleast(&x->vals, n, _state);
57471 0 : rvectorsetlengthatleast(&x->dense, n, _state);
57472 0 : x->n = n;
57473 0 : }
57474 :
57475 :
57476 : /*************************************************************************
57477 : Initializes vector, sets all internal arrays to length N and zero-fills
57478 : them. Previously allocated memory is reused as much as possible.
57479 :
57480 : INPUT PARAMETERS:
57481 : X - temporary buffers
57482 :
57483 : OUTPUT PARAMETERS:
57484 : X - preallocated vector:
57485 : * X.N=N
57486 : * X.K=0
57487 : * X.Dense is zero-filled.
57488 :
57489 : -- ALGLIB --
57490 : Copyright 24.07.2020 by Bochkanov Sergey
57491 : *************************************************************************/
57492 0 : static void reviseddualsimplex_dvinit(dssvector* x,
57493 : ae_int_t n,
57494 : ae_state *_state)
57495 : {
57496 :
57497 :
57498 0 : ivectorsetlengthatleast(&x->idx, n, _state);
57499 0 : rvectorsetlengthatleast(&x->vals, n, _state);
57500 0 : rvectorsetlengthatleast(&x->dense, n, _state);
57501 0 : rsetv(n, 0.0, &x->dense, _state);
57502 0 : x->n = n;
57503 0 : x->k = 0;
57504 0 : }
57505 :
57506 :
57507 : /*************************************************************************
57508 : Copies dense part to sparse one.
57509 :
57510 : INPUT PARAMETERS:
57511 : X - allocated vector; dense part must be valid
57512 :
57513 : OUTPUT PARAMETERS:
57514 : X - both dense and sparse parts are valid.
57515 :
57516 : -- ALGLIB --
57517 : Copyright 24.07.2020 by Bochkanov Sergey
57518 : *************************************************************************/
57519 0 : static void reviseddualsimplex_dvdensetosparse(dssvector* x,
57520 : ae_state *_state)
57521 : {
57522 : ae_int_t i;
57523 : ae_int_t n;
57524 : ae_int_t k;
57525 : double v;
57526 :
57527 :
57528 0 : n = x->n;
57529 0 : ivectorsetlengthatleast(&x->idx, n, _state);
57530 0 : rvectorsetlengthatleast(&x->vals, n, _state);
57531 0 : k = 0;
57532 0 : for(i=0; i<=n-1; i++)
57533 : {
57534 0 : v = x->dense.ptr.p_double[i];
57535 0 : if( v!=0.0 )
57536 : {
57537 0 : x->idx.ptr.p_int[k] = i;
57538 0 : x->vals.ptr.p_double[k] = v;
57539 0 : k = k+1;
57540 : }
57541 : }
57542 0 : x->k = k;
57543 0 : }
57544 :
57545 :
57546 : /*************************************************************************
57547 : Copies sparse part to dense one.
57548 :
57549 : INPUT PARAMETERS:
57550 : X - allocated vector; sparse part must be valid
57551 :
57552 : OUTPUT PARAMETERS:
57553 : X - both dense and sparse parts are valid.
57554 :
57555 : -- ALGLIB --
57556 : Copyright 24.07.2020 by Bochkanov Sergey
57557 : *************************************************************************/
57558 0 : static void reviseddualsimplex_dvsparsetodense(dssvector* x,
57559 : ae_state *_state)
57560 : {
57561 : ae_int_t i;
57562 : ae_int_t n;
57563 : ae_int_t k;
57564 :
57565 :
57566 0 : n = x->n;
57567 0 : k = x->k;
57568 0 : rsetv(n, 0.0, &x->dense, _state);
57569 0 : for(i=0; i<=k-1; i++)
57570 : {
57571 0 : x->dense.ptr.p_double[x->idx.ptr.p_int[i]] = x->vals.ptr.p_double[i];
57572 : }
57573 0 : }
57574 :
57575 :
57576 0 : static double reviseddualsimplex_sparsityof(/* Real */ ae_vector* x,
57577 : ae_int_t n,
57578 : ae_state *_state)
57579 : {
57580 : ae_int_t i;
57581 : ae_int_t k;
57582 : double mx;
57583 : double result;
57584 :
57585 :
57586 0 : if( n<=1 )
57587 : {
57588 0 : result = (double)(0);
57589 0 : return result;
57590 : }
57591 0 : mx = 1.0;
57592 0 : for(i=0; i<=n-1; i++)
57593 : {
57594 0 : mx = ae_maxreal(mx, ae_fabs(x->ptr.p_double[i], _state), _state);
57595 : }
57596 0 : mx = 1.0E5*ae_machineepsilon*mx;
57597 0 : k = 0;
57598 0 : for(i=0; i<=n-1; i++)
57599 : {
57600 0 : if( ae_fp_greater(ae_fabs(x->ptr.p_double[i], _state),mx) )
57601 : {
57602 0 : k = k+1;
57603 : }
57604 : }
57605 0 : result = (double)k/(double)n;
57606 0 : return result;
57607 : }
57608 :
57609 :
57610 0 : static void reviseddualsimplex_updateavgcounter(double v,
57611 : double* acc,
57612 : ae_int_t* cnt,
57613 : ae_state *_state)
57614 : {
57615 :
57616 :
57617 0 : *acc = *acc+v;
57618 0 : *cnt = *cnt+1;
57619 0 : }
57620 :
57621 :
57622 0 : void _dualsimplexsettings_init(void* _p, ae_state *_state, ae_bool make_automatic)
57623 : {
57624 0 : dualsimplexsettings *p = (dualsimplexsettings*)_p;
57625 0 : ae_touch_ptr((void*)p);
57626 0 : }
57627 :
57628 :
57629 0 : void _dualsimplexsettings_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
57630 : {
57631 0 : dualsimplexsettings *dst = (dualsimplexsettings*)_dst;
57632 0 : dualsimplexsettings *src = (dualsimplexsettings*)_src;
57633 0 : dst->pivottol = src->pivottol;
57634 0 : dst->perturbmag = src->perturbmag;
57635 0 : dst->maxtrfage = src->maxtrfage;
57636 0 : dst->trftype = src->trftype;
57637 0 : dst->ratiotest = src->ratiotest;
57638 0 : dst->pricing = src->pricing;
57639 0 : dst->shifting = src->shifting;
57640 0 : dst->xtolabs = src->xtolabs;
57641 0 : dst->xtolrelabs = src->xtolrelabs;
57642 0 : dst->dtolabs = src->dtolabs;
57643 0 : }
57644 :
57645 :
57646 0 : void _dualsimplexsettings_clear(void* _p)
57647 : {
57648 0 : dualsimplexsettings *p = (dualsimplexsettings*)_p;
57649 0 : ae_touch_ptr((void*)p);
57650 0 : }
57651 :
57652 :
57653 0 : void _dualsimplexsettings_destroy(void* _p)
57654 : {
57655 0 : dualsimplexsettings *p = (dualsimplexsettings*)_p;
57656 0 : ae_touch_ptr((void*)p);
57657 0 : }
57658 :
57659 :
57660 0 : void _dssvector_init(void* _p, ae_state *_state, ae_bool make_automatic)
57661 : {
57662 0 : dssvector *p = (dssvector*)_p;
57663 0 : ae_touch_ptr((void*)p);
57664 0 : ae_vector_init(&p->idx, 0, DT_INT, _state, make_automatic);
57665 0 : ae_vector_init(&p->vals, 0, DT_REAL, _state, make_automatic);
57666 0 : ae_vector_init(&p->dense, 0, DT_REAL, _state, make_automatic);
57667 0 : }
57668 :
57669 :
57670 0 : void _dssvector_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
57671 : {
57672 0 : dssvector *dst = (dssvector*)_dst;
57673 0 : dssvector *src = (dssvector*)_src;
57674 0 : dst->n = src->n;
57675 0 : dst->k = src->k;
57676 0 : ae_vector_init_copy(&dst->idx, &src->idx, _state, make_automatic);
57677 0 : ae_vector_init_copy(&dst->vals, &src->vals, _state, make_automatic);
57678 0 : ae_vector_init_copy(&dst->dense, &src->dense, _state, make_automatic);
57679 0 : }
57680 :
57681 :
57682 0 : void _dssvector_clear(void* _p)
57683 : {
57684 0 : dssvector *p = (dssvector*)_p;
57685 0 : ae_touch_ptr((void*)p);
57686 0 : ae_vector_clear(&p->idx);
57687 0 : ae_vector_clear(&p->vals);
57688 0 : ae_vector_clear(&p->dense);
57689 0 : }
57690 :
57691 :
57692 0 : void _dssvector_destroy(void* _p)
57693 : {
57694 0 : dssvector *p = (dssvector*)_p;
57695 0 : ae_touch_ptr((void*)p);
57696 0 : ae_vector_destroy(&p->idx);
57697 0 : ae_vector_destroy(&p->vals);
57698 0 : ae_vector_destroy(&p->dense);
57699 0 : }
57700 :
57701 :
57702 0 : void _dualsimplexbasis_init(void* _p, ae_state *_state, ae_bool make_automatic)
57703 : {
57704 0 : dualsimplexbasis *p = (dualsimplexbasis*)_p;
57705 0 : ae_touch_ptr((void*)p);
57706 0 : ae_vector_init(&p->idx, 0, DT_INT, _state, make_automatic);
57707 0 : ae_vector_init(&p->nidx, 0, DT_INT, _state, make_automatic);
57708 0 : ae_vector_init(&p->isbasic, 0, DT_BOOL, _state, make_automatic);
57709 0 : ae_matrix_init(&p->denselu, 0, 0, DT_REAL, _state, make_automatic);
57710 0 : _sparsematrix_init(&p->sparsel, _state, make_automatic);
57711 0 : _sparsematrix_init(&p->sparseu, _state, make_automatic);
57712 0 : _sparsematrix_init(&p->sparseut, _state, make_automatic);
57713 0 : ae_vector_init(&p->rowpermbwd, 0, DT_INT, _state, make_automatic);
57714 0 : ae_vector_init(&p->colpermbwd, 0, DT_INT, _state, make_automatic);
57715 0 : ae_vector_init(&p->densepfieta, 0, DT_REAL, _state, make_automatic);
57716 0 : ae_vector_init(&p->densemu, 0, DT_REAL, _state, make_automatic);
57717 0 : ae_vector_init(&p->rk, 0, DT_INT, _state, make_automatic);
57718 0 : ae_vector_init(&p->dk, 0, DT_INT, _state, make_automatic);
57719 0 : ae_vector_init(&p->dseweights, 0, DT_REAL, _state, make_automatic);
57720 0 : ae_vector_init(&p->wtmp0, 0, DT_REAL, _state, make_automatic);
57721 0 : ae_vector_init(&p->wtmp1, 0, DT_REAL, _state, make_automatic);
57722 0 : ae_vector_init(&p->wtmp2, 0, DT_REAL, _state, make_automatic);
57723 0 : ae_vector_init(&p->nrs, 0, DT_INT, _state, make_automatic);
57724 0 : ae_vector_init(&p->tcinvidx, 0, DT_INT, _state, make_automatic);
57725 0 : ae_matrix_init(&p->denselu2, 0, 0, DT_REAL, _state, make_automatic);
57726 0 : ae_vector_init(&p->densep2, 0, DT_INT, _state, make_automatic);
57727 0 : ae_vector_init(&p->densep2c, 0, DT_INT, _state, make_automatic);
57728 0 : _sparsematrix_init(&p->sparselu1, _state, make_automatic);
57729 0 : _sparsematrix_init(&p->sparselu2, _state, make_automatic);
57730 0 : _sluv2buffer_init(&p->lubuf2, _state, make_automatic);
57731 0 : ae_vector_init(&p->tmpi, 0, DT_INT, _state, make_automatic);
57732 0 : ae_vector_init(&p->utmp0, 0, DT_REAL, _state, make_automatic);
57733 0 : ae_vector_init(&p->utmpi, 0, DT_INT, _state, make_automatic);
57734 0 : _sparsematrix_init(&p->sparseludbg, _state, make_automatic);
57735 0 : }
57736 :
57737 :
57738 0 : void _dualsimplexbasis_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
57739 : {
57740 0 : dualsimplexbasis *dst = (dualsimplexbasis*)_dst;
57741 0 : dualsimplexbasis *src = (dualsimplexbasis*)_src;
57742 0 : dst->ns = src->ns;
57743 0 : dst->m = src->m;
57744 0 : ae_vector_init_copy(&dst->idx, &src->idx, _state, make_automatic);
57745 0 : ae_vector_init_copy(&dst->nidx, &src->nidx, _state, make_automatic);
57746 0 : ae_vector_init_copy(&dst->isbasic, &src->isbasic, _state, make_automatic);
57747 0 : dst->trftype = src->trftype;
57748 0 : dst->isvalidtrf = src->isvalidtrf;
57749 0 : dst->trfage = src->trfage;
57750 0 : ae_matrix_init_copy(&dst->denselu, &src->denselu, _state, make_automatic);
57751 0 : _sparsematrix_init_copy(&dst->sparsel, &src->sparsel, _state, make_automatic);
57752 0 : _sparsematrix_init_copy(&dst->sparseu, &src->sparseu, _state, make_automatic);
57753 0 : _sparsematrix_init_copy(&dst->sparseut, &src->sparseut, _state, make_automatic);
57754 0 : ae_vector_init_copy(&dst->rowpermbwd, &src->rowpermbwd, _state, make_automatic);
57755 0 : ae_vector_init_copy(&dst->colpermbwd, &src->colpermbwd, _state, make_automatic);
57756 0 : ae_vector_init_copy(&dst->densepfieta, &src->densepfieta, _state, make_automatic);
57757 0 : ae_vector_init_copy(&dst->densemu, &src->densemu, _state, make_automatic);
57758 0 : ae_vector_init_copy(&dst->rk, &src->rk, _state, make_automatic);
57759 0 : ae_vector_init_copy(&dst->dk, &src->dk, _state, make_automatic);
57760 0 : ae_vector_init_copy(&dst->dseweights, &src->dseweights, _state, make_automatic);
57761 0 : dst->dsevalid = src->dsevalid;
57762 0 : dst->eminu = src->eminu;
57763 0 : dst->statfact = src->statfact;
57764 0 : dst->statupdt = src->statupdt;
57765 0 : dst->statoffdiag = src->statoffdiag;
57766 0 : ae_vector_init_copy(&dst->wtmp0, &src->wtmp0, _state, make_automatic);
57767 0 : ae_vector_init_copy(&dst->wtmp1, &src->wtmp1, _state, make_automatic);
57768 0 : ae_vector_init_copy(&dst->wtmp2, &src->wtmp2, _state, make_automatic);
57769 0 : ae_vector_init_copy(&dst->nrs, &src->nrs, _state, make_automatic);
57770 0 : ae_vector_init_copy(&dst->tcinvidx, &src->tcinvidx, _state, make_automatic);
57771 0 : ae_matrix_init_copy(&dst->denselu2, &src->denselu2, _state, make_automatic);
57772 0 : ae_vector_init_copy(&dst->densep2, &src->densep2, _state, make_automatic);
57773 0 : ae_vector_init_copy(&dst->densep2c, &src->densep2c, _state, make_automatic);
57774 0 : _sparsematrix_init_copy(&dst->sparselu1, &src->sparselu1, _state, make_automatic);
57775 0 : _sparsematrix_init_copy(&dst->sparselu2, &src->sparselu2, _state, make_automatic);
57776 0 : _sluv2buffer_init_copy(&dst->lubuf2, &src->lubuf2, _state, make_automatic);
57777 0 : ae_vector_init_copy(&dst->tmpi, &src->tmpi, _state, make_automatic);
57778 0 : ae_vector_init_copy(&dst->utmp0, &src->utmp0, _state, make_automatic);
57779 0 : ae_vector_init_copy(&dst->utmpi, &src->utmpi, _state, make_automatic);
57780 0 : _sparsematrix_init_copy(&dst->sparseludbg, &src->sparseludbg, _state, make_automatic);
57781 0 : }
57782 :
57783 :
57784 0 : void _dualsimplexbasis_clear(void* _p)
57785 : {
57786 0 : dualsimplexbasis *p = (dualsimplexbasis*)_p;
57787 0 : ae_touch_ptr((void*)p);
57788 0 : ae_vector_clear(&p->idx);
57789 0 : ae_vector_clear(&p->nidx);
57790 0 : ae_vector_clear(&p->isbasic);
57791 0 : ae_matrix_clear(&p->denselu);
57792 0 : _sparsematrix_clear(&p->sparsel);
57793 0 : _sparsematrix_clear(&p->sparseu);
57794 0 : _sparsematrix_clear(&p->sparseut);
57795 0 : ae_vector_clear(&p->rowpermbwd);
57796 0 : ae_vector_clear(&p->colpermbwd);
57797 0 : ae_vector_clear(&p->densepfieta);
57798 0 : ae_vector_clear(&p->densemu);
57799 0 : ae_vector_clear(&p->rk);
57800 0 : ae_vector_clear(&p->dk);
57801 0 : ae_vector_clear(&p->dseweights);
57802 0 : ae_vector_clear(&p->wtmp0);
57803 0 : ae_vector_clear(&p->wtmp1);
57804 0 : ae_vector_clear(&p->wtmp2);
57805 0 : ae_vector_clear(&p->nrs);
57806 0 : ae_vector_clear(&p->tcinvidx);
57807 0 : ae_matrix_clear(&p->denselu2);
57808 0 : ae_vector_clear(&p->densep2);
57809 0 : ae_vector_clear(&p->densep2c);
57810 0 : _sparsematrix_clear(&p->sparselu1);
57811 0 : _sparsematrix_clear(&p->sparselu2);
57812 0 : _sluv2buffer_clear(&p->lubuf2);
57813 0 : ae_vector_clear(&p->tmpi);
57814 0 : ae_vector_clear(&p->utmp0);
57815 0 : ae_vector_clear(&p->utmpi);
57816 0 : _sparsematrix_clear(&p->sparseludbg);
57817 0 : }
57818 :
57819 :
57820 0 : void _dualsimplexbasis_destroy(void* _p)
57821 : {
57822 0 : dualsimplexbasis *p = (dualsimplexbasis*)_p;
57823 0 : ae_touch_ptr((void*)p);
57824 0 : ae_vector_destroy(&p->idx);
57825 0 : ae_vector_destroy(&p->nidx);
57826 0 : ae_vector_destroy(&p->isbasic);
57827 0 : ae_matrix_destroy(&p->denselu);
57828 0 : _sparsematrix_destroy(&p->sparsel);
57829 0 : _sparsematrix_destroy(&p->sparseu);
57830 0 : _sparsematrix_destroy(&p->sparseut);
57831 0 : ae_vector_destroy(&p->rowpermbwd);
57832 0 : ae_vector_destroy(&p->colpermbwd);
57833 0 : ae_vector_destroy(&p->densepfieta);
57834 0 : ae_vector_destroy(&p->densemu);
57835 0 : ae_vector_destroy(&p->rk);
57836 0 : ae_vector_destroy(&p->dk);
57837 0 : ae_vector_destroy(&p->dseweights);
57838 0 : ae_vector_destroy(&p->wtmp0);
57839 0 : ae_vector_destroy(&p->wtmp1);
57840 0 : ae_vector_destroy(&p->wtmp2);
57841 0 : ae_vector_destroy(&p->nrs);
57842 0 : ae_vector_destroy(&p->tcinvidx);
57843 0 : ae_matrix_destroy(&p->denselu2);
57844 0 : ae_vector_destroy(&p->densep2);
57845 0 : ae_vector_destroy(&p->densep2c);
57846 0 : _sparsematrix_destroy(&p->sparselu1);
57847 0 : _sparsematrix_destroy(&p->sparselu2);
57848 0 : _sluv2buffer_destroy(&p->lubuf2);
57849 0 : ae_vector_destroy(&p->tmpi);
57850 0 : ae_vector_destroy(&p->utmp0);
57851 0 : ae_vector_destroy(&p->utmpi);
57852 0 : _sparsematrix_destroy(&p->sparseludbg);
57853 0 : }
57854 :
57855 :
57856 0 : void _dualsimplexsubproblem_init(void* _p, ae_state *_state, ae_bool make_automatic)
57857 : {
57858 0 : dualsimplexsubproblem *p = (dualsimplexsubproblem*)_p;
57859 0 : ae_touch_ptr((void*)p);
57860 0 : ae_vector_init(&p->rawc, 0, DT_REAL, _state, make_automatic);
57861 0 : ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic);
57862 0 : ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic);
57863 0 : ae_vector_init(&p->bndt, 0, DT_INT, _state, make_automatic);
57864 0 : ae_vector_init(&p->xa, 0, DT_REAL, _state, make_automatic);
57865 0 : ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic);
57866 0 : ae_vector_init(&p->xb, 0, DT_REAL, _state, make_automatic);
57867 0 : ae_vector_init(&p->bndlb, 0, DT_REAL, _state, make_automatic);
57868 0 : ae_vector_init(&p->bndub, 0, DT_REAL, _state, make_automatic);
57869 0 : ae_vector_init(&p->bndtb, 0, DT_INT, _state, make_automatic);
57870 0 : ae_vector_init(&p->bndtollb, 0, DT_REAL, _state, make_automatic);
57871 0 : ae_vector_init(&p->bndtolub, 0, DT_REAL, _state, make_automatic);
57872 0 : ae_vector_init(&p->effc, 0, DT_REAL, _state, make_automatic);
57873 0 : }
57874 :
57875 :
57876 0 : void _dualsimplexsubproblem_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
57877 : {
57878 0 : dualsimplexsubproblem *dst = (dualsimplexsubproblem*)_dst;
57879 0 : dualsimplexsubproblem *src = (dualsimplexsubproblem*)_src;
57880 0 : dst->ns = src->ns;
57881 0 : dst->m = src->m;
57882 0 : ae_vector_init_copy(&dst->rawc, &src->rawc, _state, make_automatic);
57883 0 : ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic);
57884 0 : ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic);
57885 0 : ae_vector_init_copy(&dst->bndt, &src->bndt, _state, make_automatic);
57886 0 : ae_vector_init_copy(&dst->xa, &src->xa, _state, make_automatic);
57887 0 : ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic);
57888 0 : dst->state = src->state;
57889 0 : ae_vector_init_copy(&dst->xb, &src->xb, _state, make_automatic);
57890 0 : ae_vector_init_copy(&dst->bndlb, &src->bndlb, _state, make_automatic);
57891 0 : ae_vector_init_copy(&dst->bndub, &src->bndub, _state, make_automatic);
57892 0 : ae_vector_init_copy(&dst->bndtb, &src->bndtb, _state, make_automatic);
57893 0 : ae_vector_init_copy(&dst->bndtollb, &src->bndtollb, _state, make_automatic);
57894 0 : ae_vector_init_copy(&dst->bndtolub, &src->bndtolub, _state, make_automatic);
57895 0 : ae_vector_init_copy(&dst->effc, &src->effc, _state, make_automatic);
57896 0 : }
57897 :
57898 :
57899 0 : void _dualsimplexsubproblem_clear(void* _p)
57900 : {
57901 0 : dualsimplexsubproblem *p = (dualsimplexsubproblem*)_p;
57902 0 : ae_touch_ptr((void*)p);
57903 0 : ae_vector_clear(&p->rawc);
57904 0 : ae_vector_clear(&p->bndl);
57905 0 : ae_vector_clear(&p->bndu);
57906 0 : ae_vector_clear(&p->bndt);
57907 0 : ae_vector_clear(&p->xa);
57908 0 : ae_vector_clear(&p->d);
57909 0 : ae_vector_clear(&p->xb);
57910 0 : ae_vector_clear(&p->bndlb);
57911 0 : ae_vector_clear(&p->bndub);
57912 0 : ae_vector_clear(&p->bndtb);
57913 0 : ae_vector_clear(&p->bndtollb);
57914 0 : ae_vector_clear(&p->bndtolub);
57915 0 : ae_vector_clear(&p->effc);
57916 0 : }
57917 :
57918 :
57919 0 : void _dualsimplexsubproblem_destroy(void* _p)
57920 : {
57921 0 : dualsimplexsubproblem *p = (dualsimplexsubproblem*)_p;
57922 0 : ae_touch_ptr((void*)p);
57923 0 : ae_vector_destroy(&p->rawc);
57924 0 : ae_vector_destroy(&p->bndl);
57925 0 : ae_vector_destroy(&p->bndu);
57926 0 : ae_vector_destroy(&p->bndt);
57927 0 : ae_vector_destroy(&p->xa);
57928 0 : ae_vector_destroy(&p->d);
57929 0 : ae_vector_destroy(&p->xb);
57930 0 : ae_vector_destroy(&p->bndlb);
57931 0 : ae_vector_destroy(&p->bndub);
57932 0 : ae_vector_destroy(&p->bndtb);
57933 0 : ae_vector_destroy(&p->bndtollb);
57934 0 : ae_vector_destroy(&p->bndtolub);
57935 0 : ae_vector_destroy(&p->effc);
57936 0 : }
57937 :
57938 :
57939 0 : void _dualsimplexstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
57940 : {
57941 0 : dualsimplexstate *p = (dualsimplexstate*)_p;
57942 0 : ae_touch_ptr((void*)p);
57943 0 : ae_vector_init(&p->rowscales, 0, DT_REAL, _state, make_automatic);
57944 0 : ae_vector_init(&p->rawbndl, 0, DT_REAL, _state, make_automatic);
57945 0 : ae_vector_init(&p->rawbndu, 0, DT_REAL, _state, make_automatic);
57946 0 : _sparsematrix_init(&p->a, _state, make_automatic);
57947 0 : _sparsematrix_init(&p->at, _state, make_automatic);
57948 0 : _dualsimplexbasis_init(&p->basis, _state, make_automatic);
57949 0 : _dualsimplexsubproblem_init(&p->primary, _state, make_automatic);
57950 0 : _dualsimplexsubproblem_init(&p->phase1, _state, make_automatic);
57951 0 : _dualsimplexsubproblem_init(&p->phase3, _state, make_automatic);
57952 0 : ae_vector_init(&p->repx, 0, DT_REAL, _state, make_automatic);
57953 0 : ae_vector_init(&p->replagbc, 0, DT_REAL, _state, make_automatic);
57954 0 : ae_vector_init(&p->replaglc, 0, DT_REAL, _state, make_automatic);
57955 0 : ae_vector_init(&p->repstats, 0, DT_INT, _state, make_automatic);
57956 0 : ae_vector_init(&p->btrantmp0, 0, DT_REAL, _state, make_automatic);
57957 0 : ae_vector_init(&p->btrantmp1, 0, DT_REAL, _state, make_automatic);
57958 0 : ae_vector_init(&p->btrantmp2, 0, DT_REAL, _state, make_automatic);
57959 0 : ae_vector_init(&p->ftrantmp0, 0, DT_REAL, _state, make_automatic);
57960 0 : ae_vector_init(&p->ftrantmp1, 0, DT_REAL, _state, make_automatic);
57961 0 : ae_vector_init(&p->possibleflips, 0, DT_INT, _state, make_automatic);
57962 0 : ae_vector_init(&p->dfctmp0, 0, DT_REAL, _state, make_automatic);
57963 0 : ae_vector_init(&p->dfctmp1, 0, DT_REAL, _state, make_automatic);
57964 0 : ae_vector_init(&p->dfctmp2, 0, DT_REAL, _state, make_automatic);
57965 0 : ae_vector_init(&p->ustmpi, 0, DT_INT, _state, make_automatic);
57966 0 : _apbuffers_init(&p->xydsbuf, _state, make_automatic);
57967 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
57968 0 : ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic);
57969 0 : ae_vector_init(&p->tmp2, 0, DT_REAL, _state, make_automatic);
57970 0 : _dssvector_init(&p->alphar, _state, make_automatic);
57971 0 : _dssvector_init(&p->rhor, _state, make_automatic);
57972 0 : ae_vector_init(&p->tau, 0, DT_REAL, _state, make_automatic);
57973 0 : ae_vector_init(&p->alphaq, 0, DT_REAL, _state, make_automatic);
57974 0 : ae_vector_init(&p->alphaqim, 0, DT_REAL, _state, make_automatic);
57975 0 : ae_vector_init(&p->eligiblealphar, 0, DT_INT, _state, make_automatic);
57976 0 : ae_vector_init(&p->harrisset, 0, DT_INT, _state, make_automatic);
57977 0 : }
57978 :
57979 :
57980 0 : void _dualsimplexstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
57981 : {
57982 0 : dualsimplexstate *dst = (dualsimplexstate*)_dst;
57983 0 : dualsimplexstate *src = (dualsimplexstate*)_src;
57984 0 : ae_vector_init_copy(&dst->rowscales, &src->rowscales, _state, make_automatic);
57985 0 : ae_vector_init_copy(&dst->rawbndl, &src->rawbndl, _state, make_automatic);
57986 0 : ae_vector_init_copy(&dst->rawbndu, &src->rawbndu, _state, make_automatic);
57987 0 : dst->ns = src->ns;
57988 0 : dst->m = src->m;
57989 0 : _sparsematrix_init_copy(&dst->a, &src->a, _state, make_automatic);
57990 0 : _sparsematrix_init_copy(&dst->at, &src->at, _state, make_automatic);
57991 0 : _dualsimplexbasis_init_copy(&dst->basis, &src->basis, _state, make_automatic);
57992 0 : _dualsimplexsubproblem_init_copy(&dst->primary, &src->primary, _state, make_automatic);
57993 0 : _dualsimplexsubproblem_init_copy(&dst->phase1, &src->phase1, _state, make_automatic);
57994 0 : _dualsimplexsubproblem_init_copy(&dst->phase3, &src->phase3, _state, make_automatic);
57995 0 : ae_vector_init_copy(&dst->repx, &src->repx, _state, make_automatic);
57996 0 : ae_vector_init_copy(&dst->replagbc, &src->replagbc, _state, make_automatic);
57997 0 : ae_vector_init_copy(&dst->replaglc, &src->replaglc, _state, make_automatic);
57998 0 : ae_vector_init_copy(&dst->repstats, &src->repstats, _state, make_automatic);
57999 0 : dst->repterminationtype = src->repterminationtype;
58000 0 : dst->repiterationscount = src->repiterationscount;
58001 0 : dst->repiterationscount1 = src->repiterationscount1;
58002 0 : dst->repiterationscount2 = src->repiterationscount2;
58003 0 : dst->repiterationscount3 = src->repiterationscount3;
58004 0 : dst->repphase1time = src->repphase1time;
58005 0 : dst->repphase2time = src->repphase2time;
58006 0 : dst->repphase3time = src->repphase3time;
58007 0 : dst->repdualpricingtime = src->repdualpricingtime;
58008 0 : dst->repdualbtrantime = src->repdualbtrantime;
58009 0 : dst->repdualpivotrowtime = src->repdualpivotrowtime;
58010 0 : dst->repdualratiotesttime = src->repdualratiotesttime;
58011 0 : dst->repdualftrantime = src->repdualftrantime;
58012 0 : dst->repdualupdatesteptime = src->repdualupdatesteptime;
58013 0 : dst->repfillpivotrow = src->repfillpivotrow;
58014 0 : dst->repfillpivotrowcnt = src->repfillpivotrowcnt;
58015 0 : dst->repfillrhor = src->repfillrhor;
58016 0 : dst->repfillrhorcnt = src->repfillrhorcnt;
58017 0 : dst->repfilldensemu = src->repfilldensemu;
58018 0 : dst->repfilldensemucnt = src->repfilldensemucnt;
58019 0 : dst->dotrace = src->dotrace;
58020 0 : dst->dodetailedtrace = src->dodetailedtrace;
58021 0 : dst->dotimers = src->dotimers;
58022 0 : ae_vector_init_copy(&dst->btrantmp0, &src->btrantmp0, _state, make_automatic);
58023 0 : ae_vector_init_copy(&dst->btrantmp1, &src->btrantmp1, _state, make_automatic);
58024 0 : ae_vector_init_copy(&dst->btrantmp2, &src->btrantmp2, _state, make_automatic);
58025 0 : ae_vector_init_copy(&dst->ftrantmp0, &src->ftrantmp0, _state, make_automatic);
58026 0 : ae_vector_init_copy(&dst->ftrantmp1, &src->ftrantmp1, _state, make_automatic);
58027 0 : ae_vector_init_copy(&dst->possibleflips, &src->possibleflips, _state, make_automatic);
58028 0 : dst->possibleflipscnt = src->possibleflipscnt;
58029 0 : ae_vector_init_copy(&dst->dfctmp0, &src->dfctmp0, _state, make_automatic);
58030 0 : ae_vector_init_copy(&dst->dfctmp1, &src->dfctmp1, _state, make_automatic);
58031 0 : ae_vector_init_copy(&dst->dfctmp2, &src->dfctmp2, _state, make_automatic);
58032 0 : ae_vector_init_copy(&dst->ustmpi, &src->ustmpi, _state, make_automatic);
58033 0 : _apbuffers_init_copy(&dst->xydsbuf, &src->xydsbuf, _state, make_automatic);
58034 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
58035 0 : ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic);
58036 0 : ae_vector_init_copy(&dst->tmp2, &src->tmp2, _state, make_automatic);
58037 0 : _dssvector_init_copy(&dst->alphar, &src->alphar, _state, make_automatic);
58038 0 : _dssvector_init_copy(&dst->rhor, &src->rhor, _state, make_automatic);
58039 0 : ae_vector_init_copy(&dst->tau, &src->tau, _state, make_automatic);
58040 0 : ae_vector_init_copy(&dst->alphaq, &src->alphaq, _state, make_automatic);
58041 0 : ae_vector_init_copy(&dst->alphaqim, &src->alphaqim, _state, make_automatic);
58042 0 : ae_vector_init_copy(&dst->eligiblealphar, &src->eligiblealphar, _state, make_automatic);
58043 0 : ae_vector_init_copy(&dst->harrisset, &src->harrisset, _state, make_automatic);
58044 0 : }
58045 :
58046 :
58047 0 : void _dualsimplexstate_clear(void* _p)
58048 : {
58049 0 : dualsimplexstate *p = (dualsimplexstate*)_p;
58050 0 : ae_touch_ptr((void*)p);
58051 0 : ae_vector_clear(&p->rowscales);
58052 0 : ae_vector_clear(&p->rawbndl);
58053 0 : ae_vector_clear(&p->rawbndu);
58054 0 : _sparsematrix_clear(&p->a);
58055 0 : _sparsematrix_clear(&p->at);
58056 0 : _dualsimplexbasis_clear(&p->basis);
58057 0 : _dualsimplexsubproblem_clear(&p->primary);
58058 0 : _dualsimplexsubproblem_clear(&p->phase1);
58059 0 : _dualsimplexsubproblem_clear(&p->phase3);
58060 0 : ae_vector_clear(&p->repx);
58061 0 : ae_vector_clear(&p->replagbc);
58062 0 : ae_vector_clear(&p->replaglc);
58063 0 : ae_vector_clear(&p->repstats);
58064 0 : ae_vector_clear(&p->btrantmp0);
58065 0 : ae_vector_clear(&p->btrantmp1);
58066 0 : ae_vector_clear(&p->btrantmp2);
58067 0 : ae_vector_clear(&p->ftrantmp0);
58068 0 : ae_vector_clear(&p->ftrantmp1);
58069 0 : ae_vector_clear(&p->possibleflips);
58070 0 : ae_vector_clear(&p->dfctmp0);
58071 0 : ae_vector_clear(&p->dfctmp1);
58072 0 : ae_vector_clear(&p->dfctmp2);
58073 0 : ae_vector_clear(&p->ustmpi);
58074 0 : _apbuffers_clear(&p->xydsbuf);
58075 0 : ae_vector_clear(&p->tmp0);
58076 0 : ae_vector_clear(&p->tmp1);
58077 0 : ae_vector_clear(&p->tmp2);
58078 0 : _dssvector_clear(&p->alphar);
58079 0 : _dssvector_clear(&p->rhor);
58080 0 : ae_vector_clear(&p->tau);
58081 0 : ae_vector_clear(&p->alphaq);
58082 0 : ae_vector_clear(&p->alphaqim);
58083 0 : ae_vector_clear(&p->eligiblealphar);
58084 0 : ae_vector_clear(&p->harrisset);
58085 0 : }
58086 :
58087 :
58088 0 : void _dualsimplexstate_destroy(void* _p)
58089 : {
58090 0 : dualsimplexstate *p = (dualsimplexstate*)_p;
58091 0 : ae_touch_ptr((void*)p);
58092 0 : ae_vector_destroy(&p->rowscales);
58093 0 : ae_vector_destroy(&p->rawbndl);
58094 0 : ae_vector_destroy(&p->rawbndu);
58095 0 : _sparsematrix_destroy(&p->a);
58096 0 : _sparsematrix_destroy(&p->at);
58097 0 : _dualsimplexbasis_destroy(&p->basis);
58098 0 : _dualsimplexsubproblem_destroy(&p->primary);
58099 0 : _dualsimplexsubproblem_destroy(&p->phase1);
58100 0 : _dualsimplexsubproblem_destroy(&p->phase3);
58101 0 : ae_vector_destroy(&p->repx);
58102 0 : ae_vector_destroy(&p->replagbc);
58103 0 : ae_vector_destroy(&p->replaglc);
58104 0 : ae_vector_destroy(&p->repstats);
58105 0 : ae_vector_destroy(&p->btrantmp0);
58106 0 : ae_vector_destroy(&p->btrantmp1);
58107 0 : ae_vector_destroy(&p->btrantmp2);
58108 0 : ae_vector_destroy(&p->ftrantmp0);
58109 0 : ae_vector_destroy(&p->ftrantmp1);
58110 0 : ae_vector_destroy(&p->possibleflips);
58111 0 : ae_vector_destroy(&p->dfctmp0);
58112 0 : ae_vector_destroy(&p->dfctmp1);
58113 0 : ae_vector_destroy(&p->dfctmp2);
58114 0 : ae_vector_destroy(&p->ustmpi);
58115 0 : _apbuffers_destroy(&p->xydsbuf);
58116 0 : ae_vector_destroy(&p->tmp0);
58117 0 : ae_vector_destroy(&p->tmp1);
58118 0 : ae_vector_destroy(&p->tmp2);
58119 0 : _dssvector_destroy(&p->alphar);
58120 0 : _dssvector_destroy(&p->rhor);
58121 0 : ae_vector_destroy(&p->tau);
58122 0 : ae_vector_destroy(&p->alphaq);
58123 0 : ae_vector_destroy(&p->alphaqim);
58124 0 : ae_vector_destroy(&p->eligiblealphar);
58125 0 : ae_vector_destroy(&p->harrisset);
58126 0 : }
58127 :
58128 :
58129 : #endif
58130 : #if defined(AE_COMPILE_MINLP) || !defined(AE_PARTIAL_BUILD)
58131 :
58132 :
58133 : /*************************************************************************
58134 : LINEAR PROGRAMMING
58135 :
58136 : The subroutine creates LP solver. After initial creation it contains
58137 : default optimization problem with zero cost vector and all variables being
58138 : fixed to zero values and no constraints.
58139 :
58140 : In order to actually solve something you should:
58141 : * set cost vector with minlpsetcost()
58142 : * set variable bounds with minlpsetbc() or minlpsetbcall()
58143 : * specify constraint matrix with one of the following functions:
58144 : [*] minlpsetlc() for dense one-sided constraints
58145 : [*] minlpsetlc2dense() for dense two-sided constraints
58146 : [*] minlpsetlc2() for sparse two-sided constraints
58147 : [*] minlpaddlc2dense() to add one dense row to constraint matrix
58148 : [*] minlpaddlc2() to add one row to constraint matrix (compressed format)
58149 : * call minlpoptimize() to run the solver and minlpresults() to get the
58150 : solution vector and additional information.
58151 :
58152 : By default, LP solver uses best algorithm available. As of ALGLIB 3.17,
58153 : sparse interior point (barrier) solver is used. Future releases of ALGLIB
58154 : may introduce other solvers.
58155 :
58156 : User may choose specific LP algorithm by calling:
58157 : * minlpsetalgodss() for revised dual simplex method with DSE pricing and
58158 : bounds flipping ratio test (aka long dual step). Large-scale sparse LU
58159 : solverwith Forest-Tomlin update is used internally as linear algebra
58160 : driver.
58161 : * minlpsetalgoipm() for sparse interior point method
58162 :
58163 : INPUT PARAMETERS:
58164 : N - problem size
58165 :
58166 : OUTPUT PARAMETERS:
58167 : State - optimizer in the default state
58168 :
58169 : -- ALGLIB --
58170 : Copyright 19.07.2018 by Bochkanov Sergey
58171 : *************************************************************************/
58172 0 : void minlpcreate(ae_int_t n, minlpstate* state, ae_state *_state)
58173 : {
58174 : ae_int_t i;
58175 :
58176 0 : _minlpstate_clear(state);
58177 :
58178 0 : ae_assert(n>=1, "MinLPCreate: N<1", _state);
58179 :
58180 : /*
58181 : * Initialize
58182 : */
58183 0 : state->n = n;
58184 0 : state->m = 0;
58185 0 : minlpsetalgoipm(state, 0.0, _state);
58186 0 : state->ipmlambda = (double)(0);
58187 0 : ae_vector_set_length(&state->c, n, _state);
58188 0 : ae_vector_set_length(&state->s, n, _state);
58189 0 : ae_vector_set_length(&state->bndl, n, _state);
58190 0 : ae_vector_set_length(&state->bndu, n, _state);
58191 0 : ae_vector_set_length(&state->xs, n, _state);
58192 0 : for(i=0; i<=n-1; i++)
58193 : {
58194 0 : state->bndl.ptr.p_double[i] = (double)(0);
58195 0 : state->bndu.ptr.p_double[i] = (double)(0);
58196 0 : state->c.ptr.p_double[i] = 0.0;
58197 0 : state->s.ptr.p_double[i] = 1.0;
58198 0 : state->xs.ptr.p_double[i] = 1.0;
58199 : }
58200 0 : minlp_clearreportfields(state, _state);
58201 0 : }
58202 :
58203 :
58204 : /*************************************************************************
58205 : This function sets LP algorithm to revised dual simplex method.
58206 :
58207 : ALGLIB implementation of dual simplex method supports advanced performance
58208 : and stability improvements like DSE pricing , bounds flipping ratio test
58209 : (aka long dual step), Forest-Tomlin update, shifting.
58210 :
58211 : INPUT PARAMETERS:
58212 : State - optimizer
58213 : Eps - stopping condition, Eps>=0:
58214 : * should be small number about 1E-6 or 1E-7.
58215 : * zero value means that solver automatically selects good
58216 : value (can be different in different ALGLIB versions)
58217 : * default value is zero
58218 : Algorithm stops when relative error is less than Eps.
58219 :
58220 : ===== TRACING DSS SOLVER =================================================
58221 :
58222 : DSS solver supports advanced tracing capabilities. You can trace algorithm
58223 : output by specifying following trace symbols (case-insensitive) by means
58224 : of trace_file() call:
58225 : * 'DSS' - for basic trace of algorithm steps and decisions. Only
58226 : short scalars (function values and deltas) are printed.
58227 : N-dimensional quantities like search directions are NOT
58228 : printed.
58229 : * 'DSS.DETAILED'- for output of points being visited and search directions
58230 : This symbol also implicitly defines 'DSS'. You can
58231 : control output format by additionally specifying:
58232 : * nothing to output in 6-digit exponential format
58233 : * 'PREC.E15' to output in 15-digit exponential format
58234 : * 'PREC.F6' to output in 6-digit fixed-point format
58235 :
58236 : By default trace is disabled and adds no overhead to the optimization
58237 : process. However, specifying any of the symbols adds some formatting and
58238 : output-related overhead.
58239 :
58240 : You may specify multiple symbols by separating them with commas:
58241 : >
58242 : > alglib::trace_file("DSS,PREC.F6", "path/to/trace.log")
58243 : >
58244 :
58245 : -- ALGLIB --
58246 : Copyright 08.11.2020 by Bochkanov Sergey
58247 : *************************************************************************/
58248 0 : void minlpsetalgodss(minlpstate* state, double eps, ae_state *_state)
58249 : {
58250 :
58251 :
58252 0 : ae_assert(ae_isfinite(eps, _state), "MinLPSetAlgoDSS: Eps is not finite number", _state);
58253 0 : ae_assert(ae_fp_greater_eq(eps,(double)(0)), "MinLPSetAlgoDSS: Eps<0", _state);
58254 0 : state->algokind = 1;
58255 0 : if( ae_fp_eq(eps,(double)(0)) )
58256 : {
58257 0 : eps = 1.0E-6;
58258 : }
58259 0 : state->dsseps = eps;
58260 0 : }
58261 :
58262 :
58263 : /*************************************************************************
58264 : This function sets LP algorithm to sparse interior point method.
58265 :
58266 : ALGORITHM INFORMATION:
58267 :
58268 : * this algorithm is our implementation of interior point method as
58269 : formulated by R.J.Vanderbei, with minor modifications to the algorithm
58270 : (damped Newton directions are extensively used)
58271 : * like all interior point methods, this algorithm tends to converge in
58272 : roughly same number of iterations (between 15 and 50) independently from
58273 : the problem dimensionality
58274 :
58275 : INPUT PARAMETERS:
58276 : State - optimizer
58277 : Eps - stopping condition, Eps>=0:
58278 : * should be small number about 1E-7 or 1E-8.
58279 : * zero value means that solver automatically selects good
58280 : value (can be different in different ALGLIB versions)
58281 : * default value is zero
58282 : Algorithm stops when primal error AND dual error AND
58283 : duality gap are less than Eps.
58284 :
58285 : ===== TRACING IPM SOLVER =================================================
58286 :
58287 : IPM solver supports advanced tracing capabilities. You can trace algorithm
58288 : output by specifying following trace symbols (case-insensitive) by means
58289 : of trace_file() call:
58290 : * 'IPM' - for basic trace of algorithm steps and decisions. Only
58291 : short scalars (function values and deltas) are printed.
58292 : N-dimensional quantities like search directions are NOT
58293 : printed.
58294 : * 'IPM.DETAILED'- for output of points being visited and search directions
58295 : This symbol also implicitly defines 'IPM'. You can
58296 : control output format by additionally specifying:
58297 : * nothing to output in 6-digit exponential format
58298 : * 'PREC.E15' to output in 15-digit exponential format
58299 : * 'PREC.F6' to output in 6-digit fixed-point format
58300 :
58301 : By default trace is disabled and adds no overhead to the optimization
58302 : process. However, specifying any of the symbols adds some formatting and
58303 : output-related overhead.
58304 :
58305 : You may specify multiple symbols by separating them with commas:
58306 : >
58307 : > alglib::trace_file("IPM,PREC.F6", "path/to/trace.log")
58308 : >
58309 :
58310 : -- ALGLIB --
58311 : Copyright 08.11.2020 by Bochkanov Sergey
58312 : *************************************************************************/
58313 0 : void minlpsetalgoipm(minlpstate* state, double eps, ae_state *_state)
58314 : {
58315 :
58316 :
58317 0 : ae_assert(ae_isfinite(eps, _state), "MinLPSetAlgoIPM: Eps is not finite number", _state);
58318 0 : ae_assert(ae_fp_greater_eq(eps,(double)(0)), "MinLPSetAlgoIPM: Eps<0", _state);
58319 0 : state->algokind = 2;
58320 0 : state->ipmeps = eps;
58321 0 : state->ipmlambda = 0.0;
58322 0 : }
58323 :
58324 :
58325 : /*************************************************************************
58326 : This function sets cost term for LP solver.
58327 :
58328 : By default, cost term is zero.
58329 :
58330 : INPUT PARAMETERS:
58331 : State - structure which stores algorithm state
58332 : C - cost term, array[N].
58333 :
58334 : -- ALGLIB --
58335 : Copyright 19.07.2018 by Bochkanov Sergey
58336 : *************************************************************************/
58337 0 : void minlpsetcost(minlpstate* state,
58338 : /* Real */ ae_vector* c,
58339 : ae_state *_state)
58340 : {
58341 : ae_int_t n;
58342 : ae_int_t i;
58343 :
58344 :
58345 0 : n = state->n;
58346 0 : ae_assert(c->cnt>=n, "MinLPSetCost: Length(C)<N", _state);
58347 0 : ae_assert(isfinitevector(c, n, _state), "MinLPSetCost: C contains infinite or NaN elements", _state);
58348 0 : for(i=0; i<=n-1; i++)
58349 : {
58350 0 : state->c.ptr.p_double[i] = c->ptr.p_double[i];
58351 : }
58352 0 : }
58353 :
58354 :
58355 : /*************************************************************************
58356 : This function sets scaling coefficients.
58357 :
58358 : ALGLIB optimizers use scaling matrices to test stopping conditions and as
58359 : preconditioner.
58360 :
58361 : Scale of the I-th variable is a translation invariant measure of:
58362 : a) "how large" the variable is
58363 : b) how large the step should be to make significant changes in the
58364 : function
58365 :
58366 : INPUT PARAMETERS:
58367 : State - structure stores algorithm state
58368 : S - array[N], non-zero scaling coefficients
58369 : S[i] may be negative, sign doesn't matter.
58370 :
58371 : -- ALGLIB --
58372 : Copyright 19.07.2018 by Bochkanov Sergey
58373 : *************************************************************************/
58374 0 : void minlpsetscale(minlpstate* state,
58375 : /* Real */ ae_vector* s,
58376 : ae_state *_state)
58377 : {
58378 : ae_int_t i;
58379 :
58380 :
58381 0 : ae_assert(s->cnt>=state->n, "MinLPSetScale: Length(S)<N", _state);
58382 0 : for(i=0; i<=state->n-1; i++)
58383 : {
58384 0 : ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "MinLPSetScale: S contains infinite or NAN elements", _state);
58385 0 : ae_assert(ae_fp_neq(s->ptr.p_double[i],(double)(0)), "MinLPSetScale: S contains zero elements", _state);
58386 : }
58387 0 : for(i=0; i<=state->n-1; i++)
58388 : {
58389 0 : state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state);
58390 : }
58391 0 : }
58392 :
58393 :
58394 : /*************************************************************************
58395 : This function sets box constraints for LP solver (all variables at once,
58396 : different constraints for different variables).
58397 :
58398 : The default state of constraints is to have all variables fixed at zero.
58399 : You have to overwrite it by your own constraint vector. Constraint status
58400 : is preserved until constraints are explicitly overwritten with another
58401 : minlpsetbc() call, overwritten with minlpsetbcall(), or partially
58402 : overwritten with minlmsetbci() call.
58403 :
58404 : Following types of constraints are supported:
58405 :
58406 : DESCRIPTION CONSTRAINT HOW TO SPECIFY
58407 : fixed variable x[i]=Bnd[i] BndL[i]=BndU[i]
58408 : lower bound BndL[i]<=x[i] BndU[i]=+INF
58409 : upper bound x[i]<=BndU[i] BndL[i]=-INF
58410 : range BndL[i]<=x[i]<=BndU[i] ...
58411 : free variable - BndL[I]=-INF, BndU[I]+INF
58412 :
58413 : INPUT PARAMETERS:
58414 : State - structure stores algorithm state
58415 : BndL - lower bounds, array[N].
58416 : BndU - upper bounds, array[N].
58417 :
58418 : NOTE: infinite values can be specified by means of Double.PositiveInfinity
58419 : and Double.NegativeInfinity (in C#) and alglib::fp_posinf and
58420 : alglib::fp_neginf (in C++).
58421 :
58422 : NOTE: you may replace infinities by very small/very large values, but it
58423 : is not recommended because large numbers may introduce large numerical
58424 : errors in the algorithm.
58425 :
58426 : NOTE: if constraints for all variables are same you may use minlpsetbcall()
58427 : which allows to specify constraints without using arrays.
58428 :
58429 : NOTE: BndL>BndU will result in LP problem being recognized as infeasible.
58430 :
58431 : -- ALGLIB --
58432 : Copyright 19.07.2018 by Bochkanov Sergey
58433 : *************************************************************************/
58434 0 : void minlpsetbc(minlpstate* state,
58435 : /* Real */ ae_vector* bndl,
58436 : /* Real */ ae_vector* bndu,
58437 : ae_state *_state)
58438 : {
58439 : ae_int_t i;
58440 : ae_int_t n;
58441 :
58442 :
58443 0 : n = state->n;
58444 0 : ae_assert(bndl->cnt>=n, "MinLPSetBC: Length(BndL)<N", _state);
58445 0 : ae_assert(bndu->cnt>=n, "MinLPSetBC: Length(BndU)<N", _state);
58446 0 : for(i=0; i<=n-1; i++)
58447 : {
58448 0 : ae_assert(ae_isfinite(bndl->ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "MinLPSetBC: BndL contains NAN or +INF", _state);
58449 0 : ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "MinLPSetBC: BndU contains NAN or -INF", _state);
58450 0 : state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i];
58451 0 : state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i];
58452 : }
58453 0 : }
58454 :
58455 :
58456 : /*************************************************************************
58457 : This function sets box constraints for LP solver (all variables at once,
58458 : same constraints for all variables)
58459 :
58460 : The default state of constraints is to have all variables fixed at zero.
58461 : You have to overwrite it by your own constraint vector. Constraint status
58462 : is preserved until constraints are explicitly overwritten with another
58463 : minlpsetbc() call or partially overwritten with minlpsetbcall().
58464 :
58465 : Following types of constraints are supported:
58466 :
58467 : DESCRIPTION CONSTRAINT HOW TO SPECIFY
58468 : fixed variable x[i]=Bnd[i] BndL[i]=BndU[i]
58469 : lower bound BndL[i]<=x[i] BndU[i]=+INF
58470 : upper bound x[i]<=BndU[i] BndL[i]=-INF
58471 : range BndL[i]<=x[i]<=BndU[i] ...
58472 : free variable - BndL[I]=-INF, BndU[I]+INF
58473 :
58474 : INPUT PARAMETERS:
58475 : State - structure stores algorithm state
58476 : BndL - lower bound, same for all variables
58477 : BndU - upper bound, same for all variables
58478 :
58479 : NOTE: infinite values can be specified by means of Double.PositiveInfinity
58480 : and Double.NegativeInfinity (in C#) and alglib::fp_posinf and
58481 : alglib::fp_neginf (in C++).
58482 :
58483 : NOTE: you may replace infinities by very small/very large values, but it
58484 : is not recommended because large numbers may introduce large numerical
58485 : errors in the algorithm.
58486 :
58487 : NOTE: minlpsetbc() can be used to specify different constraints for
58488 : different variables.
58489 :
58490 : NOTE: BndL>BndU will result in LP problem being recognized as infeasible.
58491 :
58492 : -- ALGLIB --
58493 : Copyright 19.07.2018 by Bochkanov Sergey
58494 : *************************************************************************/
58495 0 : void minlpsetbcall(minlpstate* state,
58496 : double bndl,
58497 : double bndu,
58498 : ae_state *_state)
58499 : {
58500 : ae_int_t i;
58501 : ae_int_t n;
58502 :
58503 :
58504 0 : n = state->n;
58505 0 : ae_assert(ae_isfinite(bndl, _state)||ae_isneginf(bndl, _state), "MinLPSetBCAll: BndL is NAN or +INF", _state);
58506 0 : ae_assert(ae_isfinite(bndu, _state)||ae_isposinf(bndu, _state), "MinLPSetBCAll: BndU is NAN or -INF", _state);
58507 0 : for(i=0; i<=n-1; i++)
58508 : {
58509 0 : state->bndl.ptr.p_double[i] = bndl;
58510 0 : state->bndu.ptr.p_double[i] = bndu;
58511 : }
58512 0 : }
58513 :
58514 :
58515 : /*************************************************************************
58516 : This function sets box constraints for I-th variable (other variables are
58517 : not modified).
58518 :
58519 : The default state of constraints is to have all variables fixed at zero.
58520 : You have to overwrite it by your own constraint vector.
58521 :
58522 : Following types of constraints are supported:
58523 :
58524 : DESCRIPTION CONSTRAINT HOW TO SPECIFY
58525 : fixed variable x[i]=Bnd[i] BndL[i]=BndU[i]
58526 : lower bound BndL[i]<=x[i] BndU[i]=+INF
58527 : upper bound x[i]<=BndU[i] BndL[i]=-INF
58528 : range BndL[i]<=x[i]<=BndU[i] ...
58529 : free variable - BndL[I]=-INF, BndU[I]+INF
58530 :
58531 : INPUT PARAMETERS:
58532 : State - structure stores algorithm state
58533 : I - variable index, in [0,N)
58534 : BndL - lower bound for I-th variable
58535 : BndU - upper bound for I-th variable
58536 :
58537 : NOTE: infinite values can be specified by means of Double.PositiveInfinity
58538 : and Double.NegativeInfinity (in C#) and alglib::fp_posinf and
58539 : alglib::fp_neginf (in C++).
58540 :
58541 : NOTE: you may replace infinities by very small/very large values, but it
58542 : is not recommended because large numbers may introduce large numerical
58543 : errors in the algorithm.
58544 :
58545 : NOTE: minlpsetbc() can be used to specify different constraints for
58546 : different variables.
58547 :
58548 : NOTE: BndL>BndU will result in LP problem being recognized as infeasible.
58549 :
58550 : -- ALGLIB --
58551 : Copyright 19.07.2018 by Bochkanov Sergey
58552 : *************************************************************************/
58553 0 : void minlpsetbci(minlpstate* state,
58554 : ae_int_t i,
58555 : double bndl,
58556 : double bndu,
58557 : ae_state *_state)
58558 : {
58559 : ae_int_t n;
58560 :
58561 :
58562 0 : n = state->n;
58563 0 : ae_assert(i>=0&&i<n, "MinLPSetBCi: I is outside of [0,N)", _state);
58564 0 : ae_assert(ae_isfinite(bndl, _state)||ae_isneginf(bndl, _state), "MinLPSetBCi: BndL is NAN or +INF", _state);
58565 0 : ae_assert(ae_isfinite(bndu, _state)||ae_isposinf(bndu, _state), "MinLPSetBCi: BndU is NAN or -INF", _state);
58566 0 : state->bndl.ptr.p_double[i] = bndl;
58567 0 : state->bndu.ptr.p_double[i] = bndu;
58568 0 : }
58569 :
58570 :
58571 : /*************************************************************************
58572 : This function sets one-sided linear constraints A*x ~ AU, where "~" can be
58573 : a mix of "<=", "=" and ">=".
58574 :
58575 : IMPORTANT: this function is provided here for compatibility with the rest
58576 : of ALGLIB optimizers which accept constraints in format like
58577 : this one. Many real-life problems feature two-sided constraints
58578 : like a0 <= a*x <= a1. It is really inefficient to add them as a
58579 : pair of one-sided constraints.
58580 :
58581 : Use minlpsetlc2dense(), minlpsetlc2(), minlpaddlc2() (or its
58582 : sparse version) wherever possible.
58583 :
58584 : INPUT PARAMETERS:
58585 : State - structure previously allocated with minlpcreate() call.
58586 : A - linear constraints, array[K,N+1]. Each row of A represents
58587 : one constraint, with first N elements being linear coefficients,
58588 : and last element being right side.
58589 : CT - constraint types, array[K]:
58590 : * if CT[i]>0, then I-th constraint is A[i,*]*x >= A[i,n]
58591 : * if CT[i]=0, then I-th constraint is A[i,*]*x = A[i,n]
58592 : * if CT[i]<0, then I-th constraint is A[i,*]*x <= A[i,n]
58593 : K - number of equality/inequality constraints, K>=0; if not
58594 : given, inferred from sizes of A and CT.
58595 :
58596 : -- ALGLIB --
58597 : Copyright 19.07.2018 by Bochkanov Sergey
58598 : *************************************************************************/
58599 0 : void minlpsetlc(minlpstate* state,
58600 : /* Real */ ae_matrix* a,
58601 : /* Integer */ ae_vector* ct,
58602 : ae_int_t k,
58603 : ae_state *_state)
58604 : {
58605 : ae_frame _frame_block;
58606 : ae_vector al;
58607 : ae_vector au;
58608 : ae_int_t n;
58609 : ae_int_t i;
58610 :
58611 0 : ae_frame_make(_state, &_frame_block);
58612 0 : memset(&al, 0, sizeof(al));
58613 0 : memset(&au, 0, sizeof(au));
58614 0 : ae_vector_init(&al, 0, DT_REAL, _state, ae_true);
58615 0 : ae_vector_init(&au, 0, DT_REAL, _state, ae_true);
58616 :
58617 0 : n = state->n;
58618 0 : ae_assert(k>=0, "MinLPSetLC: K<0", _state);
58619 0 : ae_assert(k==0||a->cols>=n+1, "MinLPSetLC: Cols(A)<N+1", _state);
58620 0 : ae_assert(a->rows>=k, "MinLPSetLC: Rows(A)<K", _state);
58621 0 : ae_assert(ct->cnt>=k, "MinLPSetLC: Length(CT)<K", _state);
58622 0 : ae_assert(apservisfinitematrix(a, k, n+1, _state), "MinLPSetLC: A contains infinite or NaN values!", _state);
58623 :
58624 : /*
58625 : * Handle zero K
58626 : */
58627 0 : if( k==0 )
58628 : {
58629 0 : state->m = 0;
58630 0 : ae_frame_leave(_state);
58631 0 : return;
58632 : }
58633 :
58634 : /*
58635 : * Convert constraints to two-sided storage format, call another function
58636 : */
58637 0 : ae_vector_set_length(&al, k, _state);
58638 0 : ae_vector_set_length(&au, k, _state);
58639 0 : for(i=0; i<=k-1; i++)
58640 : {
58641 0 : if( ct->ptr.p_int[i]>0 )
58642 : {
58643 0 : al.ptr.p_double[i] = a->ptr.pp_double[i][n];
58644 0 : au.ptr.p_double[i] = _state->v_posinf;
58645 0 : continue;
58646 : }
58647 0 : if( ct->ptr.p_int[i]<0 )
58648 : {
58649 0 : al.ptr.p_double[i] = _state->v_neginf;
58650 0 : au.ptr.p_double[i] = a->ptr.pp_double[i][n];
58651 0 : continue;
58652 : }
58653 0 : al.ptr.p_double[i] = a->ptr.pp_double[i][n];
58654 0 : au.ptr.p_double[i] = a->ptr.pp_double[i][n];
58655 : }
58656 0 : minlpsetlc2dense(state, a, &al, &au, k, _state);
58657 0 : ae_frame_leave(_state);
58658 : }
58659 :
58660 :
58661 : /*************************************************************************
58662 : This function sets two-sided linear constraints AL <= A*x <= AU.
58663 :
58664 : This version accepts dense matrix as input; internally LP solver uses
58665 : sparse storage anyway (most LP problems are sparse), but for your
58666 : convenience it may accept dense inputs. This function overwrites linear
58667 : constraints set by previous calls (if such calls were made).
58668 :
58669 : We recommend you to use sparse version of this function unless you solve
58670 : small-scale LP problem (less than few hundreds of variables).
58671 :
58672 : NOTE: there also exist several versions of this function:
58673 : * one-sided dense version which accepts constraints in the same
58674 : format as one used by QP and NLP solvers
58675 : * two-sided sparse version which accepts sparse matrix
58676 : * two-sided dense version which allows you to add constraints row by row
58677 : * two-sided sparse version which allows you to add constraints row by row
58678 :
58679 : INPUT PARAMETERS:
58680 : State - structure previously allocated with minlpcreate() call.
58681 : A - linear constraints, array[K,N]. Each row of A represents
58682 : one constraint. One-sided inequality constraints, two-
58683 : sided inequality constraints, equality constraints are
58684 : supported (see below)
58685 : AL, AU - lower and upper bounds, array[K];
58686 : * AL[i]=AU[i] => equality constraint Ai*x
58687 : * AL[i]<AU[i] => two-sided constraint AL[i]<=Ai*x<=AU[i]
58688 : * AL[i]=-INF => one-sided constraint Ai*x<=AU[i]
58689 : * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x
58690 : * AL[i]=-INF, AU[i]=+INF => constraint is ignored
58691 : K - number of equality/inequality constraints, K>=0; if not
58692 : given, inferred from sizes of A, AL, AU.
58693 :
58694 : -- ALGLIB --
58695 : Copyright 19.07.2018 by Bochkanov Sergey
58696 : *************************************************************************/
58697 0 : void minlpsetlc2dense(minlpstate* state,
58698 : /* Real */ ae_matrix* a,
58699 : /* Real */ ae_vector* al,
58700 : /* Real */ ae_vector* au,
58701 : ae_int_t k,
58702 : ae_state *_state)
58703 : {
58704 : ae_frame _frame_block;
58705 : ae_int_t i;
58706 : ae_int_t j;
58707 : ae_int_t n;
58708 : ae_int_t nz;
58709 : ae_vector nrs;
58710 :
58711 0 : ae_frame_make(_state, &_frame_block);
58712 0 : memset(&nrs, 0, sizeof(nrs));
58713 0 : ae_vector_init(&nrs, 0, DT_INT, _state, ae_true);
58714 :
58715 0 : n = state->n;
58716 0 : ae_assert(k>=0, "MinLPSetLC2Dense: K<0", _state);
58717 0 : ae_assert(k==0||a->cols>=n, "MinLPSetLC2Dense: Cols(A)<N", _state);
58718 0 : ae_assert(a->rows>=k, "MinLPSetLC2Dense: Rows(A)<K", _state);
58719 0 : ae_assert(al->cnt>=k, "MinLPSetLC2Dense: Length(AL)<K", _state);
58720 0 : ae_assert(au->cnt>=k, "MinLPSetLC2Dense: Length(AU)<K", _state);
58721 0 : ae_assert(apservisfinitematrix(a, k, n, _state), "MinLPSetLC2Dense: A contains infinite or NaN values!", _state);
58722 :
58723 : /*
58724 : * Count actual (different from -INF<=A*x<=+INF) constraints;
58725 : * count non-zero elements in each row.
58726 : */
58727 0 : ae_vector_set_length(&nrs, k, _state);
58728 0 : state->m = k;
58729 0 : if( state->m==0 )
58730 : {
58731 0 : ae_frame_leave(_state);
58732 0 : return;
58733 : }
58734 0 : for(i=0; i<=k-1; i++)
58735 : {
58736 0 : ae_assert(ae_isfinite(al->ptr.p_double[i], _state)||ae_isneginf(al->ptr.p_double[i], _state), "MinLPSetLC2Dense: AL contains NAN or +INF", _state);
58737 0 : ae_assert(ae_isfinite(au->ptr.p_double[i], _state)||ae_isposinf(au->ptr.p_double[i], _state), "MinLPSetLC2Dense: AU contains NAN or -INF", _state);
58738 0 : nz = 0;
58739 0 : for(j=0; j<=n-1; j++)
58740 : {
58741 0 : if( ae_fp_neq(a->ptr.pp_double[i][j],(double)(0)) )
58742 : {
58743 0 : inc(&nz, _state);
58744 : }
58745 : }
58746 0 : nrs.ptr.p_int[i] = nz;
58747 : }
58748 :
58749 : /*
58750 : * Allocate storage, copy
58751 : */
58752 0 : rvectorsetlengthatleast(&state->al, state->m, _state);
58753 0 : rvectorsetlengthatleast(&state->au, state->m, _state);
58754 0 : sparsecreatecrsbuf(state->m, n, &nrs, &state->a, _state);
58755 0 : for(i=0; i<=k-1; i++)
58756 : {
58757 0 : for(j=0; j<=n-1; j++)
58758 : {
58759 0 : if( ae_fp_neq(a->ptr.pp_double[i][j],(double)(0)) )
58760 : {
58761 0 : sparseset(&state->a, i, j, a->ptr.pp_double[i][j], _state);
58762 : }
58763 : }
58764 0 : state->al.ptr.p_double[i] = al->ptr.p_double[i];
58765 0 : state->au.ptr.p_double[i] = au->ptr.p_double[i];
58766 : }
58767 0 : ae_frame_leave(_state);
58768 : }
58769 :
58770 :
58771 : /*************************************************************************
58772 : This function sets two-sided linear constraints AL <= A*x <= AU with
58773 : sparse constraining matrix A. Recommended for large-scale problems.
58774 :
58775 : This function overwrites linear (non-box) constraints set by previous
58776 : calls (if such calls were made).
58777 :
58778 : INPUT PARAMETERS:
58779 : State - structure previously allocated with minlpcreate() call.
58780 : A - sparse matrix with size [K,N] (exactly!).
58781 : Each row of A represents one general linear constraint.
58782 : A can be stored in any sparse storage format.
58783 : AL, AU - lower and upper bounds, array[K];
58784 : * AL[i]=AU[i] => equality constraint Ai*x
58785 : * AL[i]<AU[i] => two-sided constraint AL[i]<=Ai*x<=AU[i]
58786 : * AL[i]=-INF => one-sided constraint Ai*x<=AU[i]
58787 : * AU[i]=+INF => one-sided constraint AL[i]<=Ai*x
58788 : * AL[i]=-INF, AU[i]=+INF => constraint is ignored
58789 : K - number of equality/inequality constraints, K>=0. If K=0
58790 : is specified, A, AL, AU are ignored.
58791 :
58792 : -- ALGLIB --
58793 : Copyright 19.07.2018 by Bochkanov Sergey
58794 : *************************************************************************/
58795 0 : void minlpsetlc2(minlpstate* state,
58796 : sparsematrix* a,
58797 : /* Real */ ae_vector* al,
58798 : /* Real */ ae_vector* au,
58799 : ae_int_t k,
58800 : ae_state *_state)
58801 : {
58802 : ae_int_t n;
58803 : ae_int_t i;
58804 :
58805 :
58806 0 : n = state->n;
58807 :
58808 : /*
58809 : * Quick exit
58810 : */
58811 0 : if( k==0 )
58812 : {
58813 0 : state->m = 0;
58814 0 : return;
58815 : }
58816 :
58817 : /*
58818 : * Integrity checks
58819 : */
58820 0 : ae_assert(k>0, "MinLPSetLC2: K<0", _state);
58821 0 : ae_assert(sparsegetncols(a, _state)==n, "MinLPSetLC2: Cols(A)<>N", _state);
58822 0 : ae_assert(sparsegetnrows(a, _state)==k, "MinLPSetLC2: Rows(A)<>K", _state);
58823 0 : ae_assert(al->cnt>=k, "MinLPSetLC2: Length(AL)<K", _state);
58824 0 : ae_assert(au->cnt>=k, "MinLPSetLC2: Length(AU)<K", _state);
58825 0 : for(i=0; i<=k-1; i++)
58826 : {
58827 0 : ae_assert(ae_isfinite(al->ptr.p_double[i], _state)||ae_isneginf(al->ptr.p_double[i], _state), "MinLPSetLC2: AL contains NAN or +INF", _state);
58828 0 : ae_assert(ae_isfinite(au->ptr.p_double[i], _state)||ae_isposinf(au->ptr.p_double[i], _state), "MinLPSetLC2: AU contains NAN or -INF", _state);
58829 : }
58830 :
58831 : /*
58832 : * Copy
58833 : */
58834 0 : state->m = k;
58835 0 : sparsecopytocrsbuf(a, &state->a, _state);
58836 0 : rvectorsetlengthatleast(&state->al, k, _state);
58837 0 : rvectorsetlengthatleast(&state->au, k, _state);
58838 0 : for(i=0; i<=k-1; i++)
58839 : {
58840 0 : state->al.ptr.p_double[i] = al->ptr.p_double[i];
58841 0 : state->au.ptr.p_double[i] = au->ptr.p_double[i];
58842 : }
58843 : }
58844 :
58845 :
58846 : /*************************************************************************
58847 : This function appends two-sided linear constraint AL <= A*x <= AU to the
58848 : list of currently present constraints.
58849 :
58850 : This version accepts dense constraint vector as input, but sparsifies it
58851 : for internal storage and processing. Thus, time to add one constraint in
58852 : is O(N) - we have to scan entire array of length N. Sparse version of this
58853 : function is order of magnitude faster for constraints with just a few
58854 : nonzeros per row.
58855 :
58856 : INPUT PARAMETERS:
58857 : State - structure previously allocated with minlpcreate() call.
58858 : A - linear constraint coefficient, array[N], right side is NOT
58859 : included.
58860 : AL, AU - lower and upper bounds;
58861 : * AL=AU => equality constraint Ai*x
58862 : * AL<AU => two-sided constraint AL<=A*x<=AU
58863 : * AL=-INF => one-sided constraint Ai*x<=AU
58864 : * AU=+INF => one-sided constraint AL<=Ai*x
58865 : * AL=-INF, AU=+INF => constraint is ignored
58866 :
58867 : -- ALGLIB --
58868 : Copyright 19.07.2018 by Bochkanov Sergey
58869 : *************************************************************************/
58870 0 : void minlpaddlc2dense(minlpstate* state,
58871 : /* Real */ ae_vector* a,
58872 : double al,
58873 : double au,
58874 : ae_state *_state)
58875 : {
58876 : ae_int_t i;
58877 : ae_int_t n;
58878 : ae_int_t nnz;
58879 :
58880 :
58881 0 : n = state->n;
58882 0 : ae_assert(a->cnt>=n, "MinLPAddLC2Dense: Length(A)<N", _state);
58883 0 : ae_assert(isfinitevector(a, n, _state), "MinLPAddLC2Dense: A contains infinite or NaN values!", _state);
58884 0 : ae_assert(ae_isfinite(al, _state)||ae_isneginf(al, _state), "MinLPAddLC2Dense: AL is NAN or +INF", _state);
58885 0 : ae_assert(ae_isfinite(au, _state)||ae_isposinf(au, _state), "MinLPAddLC2Dense: AU is NAN or -INF", _state);
58886 0 : ivectorsetlengthatleast(&state->adddtmpi, n, _state);
58887 0 : rvectorsetlengthatleast(&state->adddtmpr, n, _state);
58888 0 : nnz = 0;
58889 0 : for(i=0; i<=n-1; i++)
58890 : {
58891 0 : if( a->ptr.p_double[i]!=0.0 )
58892 : {
58893 0 : state->adddtmpi.ptr.p_int[nnz] = i;
58894 0 : state->adddtmpr.ptr.p_double[nnz] = a->ptr.p_double[i];
58895 0 : nnz = nnz+1;
58896 : }
58897 : }
58898 0 : minlpaddlc2(state, &state->adddtmpi, &state->adddtmpr, nnz, al, au, _state);
58899 0 : }
58900 :
58901 :
58902 : /*************************************************************************
58903 : This function appends two-sided linear constraint AL <= A*x <= AU to the
58904 : list of currently present constraints.
58905 :
58906 : Constraint is passed in compressed format: as list of non-zero entries of
58907 : coefficient vector A. Such approach is more efficient than dense storage
58908 : for highly sparse constraint vectors.
58909 :
58910 : INPUT PARAMETERS:
58911 : State - structure previously allocated with minlpcreate() call.
58912 : IdxA - array[NNZ], indexes of non-zero elements of A:
58913 : * can be unsorted
58914 : * can include duplicate indexes (corresponding entries of
58915 : ValA[] will be summed)
58916 : ValA - array[NNZ], values of non-zero elements of A
58917 : NNZ - number of non-zero coefficients in A
58918 : AL, AU - lower and upper bounds;
58919 : * AL=AU => equality constraint A*x
58920 : * AL<AU => two-sided constraint AL<=A*x<=AU
58921 : * AL=-INF => one-sided constraint A*x<=AU
58922 : * AU=+INF => one-sided constraint AL<=A*x
58923 : * AL=-INF, AU=+INF => constraint is ignored
58924 :
58925 : -- ALGLIB --
58926 : Copyright 19.07.2018 by Bochkanov Sergey
58927 : *************************************************************************/
58928 0 : void minlpaddlc2(minlpstate* state,
58929 : /* Integer */ ae_vector* idxa,
58930 : /* Real */ ae_vector* vala,
58931 : ae_int_t nnz,
58932 : double al,
58933 : double au,
58934 : ae_state *_state)
58935 : {
58936 : ae_int_t i;
58937 : ae_int_t j;
58938 : ae_int_t k;
58939 : ae_int_t offs;
58940 : ae_int_t offsdst;
58941 : ae_int_t m;
58942 : ae_int_t n;
58943 : ae_int_t didx;
58944 : ae_int_t uidx;
58945 :
58946 :
58947 0 : m = state->m;
58948 0 : n = state->n;
58949 :
58950 : /*
58951 : * Check inputs
58952 : */
58953 0 : ae_assert(nnz>=0, "MinLPAddLC2: NNZ<0", _state);
58954 0 : ae_assert(idxa->cnt>=nnz, "MinLPAddLC2: Length(IdxA)<NNZ", _state);
58955 0 : ae_assert(vala->cnt>=nnz, "MinLPAddLC2: Length(ValA)<NNZ", _state);
58956 0 : for(i=0; i<=nnz-1; i++)
58957 : {
58958 0 : ae_assert(idxa->ptr.p_int[i]>=0&&idxa->ptr.p_int[i]<n, "MinLPAddLC2: IdxA contains indexes outside of [0,N) range", _state);
58959 : }
58960 0 : ae_assert(isfinitevector(vala, nnz, _state), "MinLPAddLC2: ValA contains infinite or NaN values!", _state);
58961 0 : ae_assert(ae_isfinite(al, _state)||ae_isneginf(al, _state), "MinLPAddLC2Dense: AL is NAN or +INF", _state);
58962 0 : ae_assert(ae_isfinite(au, _state)||ae_isposinf(au, _state), "MinLPAddLC2Dense: AU is NAN or -INF", _state);
58963 :
58964 : /*
58965 : * If M=0, it means that A is uninitialized.
58966 : * Prepare sparse matrix structure
58967 : */
58968 0 : if( m==0 )
58969 : {
58970 0 : state->a.matrixtype = 1;
58971 0 : state->a.m = 0;
58972 0 : state->a.n = n;
58973 0 : state->a.ninitialized = 0;
58974 0 : ivectorsetlengthatleast(&state->a.ridx, 1, _state);
58975 0 : state->a.ridx.ptr.p_int[0] = 0;
58976 : }
58977 :
58978 : /*
58979 : * Reallocate storage
58980 : */
58981 0 : offs = state->a.ridx.ptr.p_int[m];
58982 0 : ivectorgrowto(&state->a.idx, offs+nnz, _state);
58983 0 : rvectorgrowto(&state->a.vals, offs+nnz, _state);
58984 0 : ivectorgrowto(&state->a.didx, m+1, _state);
58985 0 : ivectorgrowto(&state->a.uidx, m+1, _state);
58986 0 : ivectorgrowto(&state->a.ridx, m+2, _state);
58987 0 : rvectorgrowto(&state->al, m+1, _state);
58988 0 : rvectorgrowto(&state->au, m+1, _state);
58989 :
58990 : /*
58991 : * If NNZ=0, perform quick and simple row append.
58992 : */
58993 0 : if( nnz==0 )
58994 : {
58995 0 : state->a.didx.ptr.p_int[m] = state->a.ridx.ptr.p_int[m];
58996 0 : state->a.uidx.ptr.p_int[m] = state->a.ridx.ptr.p_int[m];
58997 0 : state->a.ridx.ptr.p_int[m+1] = state->a.ridx.ptr.p_int[m];
58998 0 : state->al.ptr.p_double[m] = al;
58999 0 : state->au.ptr.p_double[m] = au;
59000 0 : state->a.m = m+1;
59001 0 : state->m = m+1;
59002 0 : return;
59003 : }
59004 :
59005 : /*
59006 : * Now we are sure that A contains properly initialized sparse
59007 : * matrix (or some appropriate dummy for M=0) and we have NNZ>0
59008 : * (no need to care about degenerate cases).
59009 : *
59010 : * Append rows to A:
59011 : * * append data
59012 : * * sort in place
59013 : * * merge duplicate indexes
59014 : * * compute DIdx and UIdx
59015 : *
59016 : */
59017 0 : for(i=0; i<=nnz-1; i++)
59018 : {
59019 0 : state->a.idx.ptr.p_int[offs+i] = idxa->ptr.p_int[i];
59020 0 : state->a.vals.ptr.p_double[offs+i] = vala->ptr.p_double[i];
59021 : }
59022 0 : tagsortmiddleir(&state->a.idx, &state->a.vals, offs, nnz, _state);
59023 0 : offsdst = offs;
59024 0 : for(i=1; i<=nnz-1; i++)
59025 : {
59026 0 : if( state->a.idx.ptr.p_int[offsdst]!=state->a.idx.ptr.p_int[offs+i] )
59027 : {
59028 0 : offsdst = offsdst+1;
59029 0 : state->a.idx.ptr.p_int[offsdst] = state->a.idx.ptr.p_int[offs+i];
59030 0 : state->a.vals.ptr.p_double[offsdst] = state->a.vals.ptr.p_double[offs+i];
59031 : }
59032 : else
59033 : {
59034 0 : state->a.vals.ptr.p_double[offsdst] = state->a.vals.ptr.p_double[offsdst]+state->a.vals.ptr.p_double[offs+i];
59035 : }
59036 : }
59037 0 : nnz = offsdst-offs+1;
59038 0 : uidx = -1;
59039 0 : didx = -1;
59040 0 : for(j=offs; j<=offsdst; j++)
59041 : {
59042 0 : k = state->a.idx.ptr.p_int[j];
59043 0 : if( k==m )
59044 : {
59045 0 : didx = j;
59046 : }
59047 : else
59048 : {
59049 0 : if( k>m&&uidx==-1 )
59050 : {
59051 0 : uidx = j;
59052 0 : break;
59053 : }
59054 : }
59055 : }
59056 0 : if( uidx==-1 )
59057 : {
59058 0 : uidx = offsdst+1;
59059 : }
59060 0 : if( didx==-1 )
59061 : {
59062 0 : didx = uidx;
59063 : }
59064 0 : state->a.didx.ptr.p_int[m] = didx;
59065 0 : state->a.uidx.ptr.p_int[m] = uidx;
59066 0 : state->a.ridx.ptr.p_int[m+1] = offsdst+1;
59067 0 : state->a.m = m+1;
59068 0 : state->a.ninitialized = state->a.ninitialized+nnz;
59069 0 : state->al.ptr.p_double[m] = al;
59070 0 : state->au.ptr.p_double[m] = au;
59071 0 : state->m = m+1;
59072 : }
59073 :
59074 :
59075 : /*************************************************************************
59076 : This function solves LP problem.
59077 :
59078 : INPUT PARAMETERS:
59079 : State - algorithm state
59080 :
59081 : You should use minlpresults() function to access results after calls to
59082 : this function.
59083 :
59084 : -- ALGLIB --
59085 : Copyright 19.07.2018 by Bochkanov Sergey.
59086 : *************************************************************************/
59087 0 : void minlpoptimize(minlpstate* state, ae_state *_state)
59088 : {
59089 : ae_frame _frame_block;
59090 : ae_int_t n;
59091 : ae_int_t m;
59092 : ae_int_t i;
59093 : double v;
59094 : dualsimplexsettings settings;
59095 : ae_matrix dummy;
59096 : dualsimplexbasis dummybasis;
59097 : ae_bool badconstr;
59098 :
59099 0 : ae_frame_make(_state, &_frame_block);
59100 0 : memset(&settings, 0, sizeof(settings));
59101 0 : memset(&dummy, 0, sizeof(dummy));
59102 0 : memset(&dummybasis, 0, sizeof(dummybasis));
59103 0 : _dualsimplexsettings_init(&settings, _state, ae_true);
59104 0 : ae_matrix_init(&dummy, 0, 0, DT_REAL, _state, ae_true);
59105 0 : _dualsimplexbasis_init(&dummybasis, _state, ae_true);
59106 :
59107 0 : n = state->n;
59108 0 : m = state->m;
59109 0 : minlp_clearreportfields(state, _state);
59110 :
59111 : /*
59112 : * Most basic check for correctness of constraints
59113 : */
59114 0 : badconstr = ae_false;
59115 0 : for(i=0; i<=n-1; i++)
59116 : {
59117 0 : if( (ae_isfinite(state->bndl.ptr.p_double[i], _state)&&ae_isfinite(state->bndu.ptr.p_double[i], _state))&&ae_fp_greater(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
59118 : {
59119 0 : badconstr = ae_true;
59120 : }
59121 : }
59122 0 : for(i=0; i<=m-1; i++)
59123 : {
59124 0 : if( (ae_isfinite(state->al.ptr.p_double[i], _state)&&ae_isfinite(state->au.ptr.p_double[i], _state))&&ae_fp_greater(state->al.ptr.p_double[i],state->au.ptr.p_double[i]) )
59125 : {
59126 0 : badconstr = ae_true;
59127 : }
59128 : }
59129 0 : if( badconstr )
59130 : {
59131 0 : state->repterminationtype = -3;
59132 0 : state->repn = n;
59133 0 : state->repm = m;
59134 0 : rsetallocv(n, 0.0, &state->xs, _state);
59135 0 : rsetallocv(n, 0.0, &state->lagbc, _state);
59136 0 : rsetallocv(m, 0.0, &state->laglc, _state);
59137 0 : isetallocv(n+m, 0, &state->cs, _state);
59138 0 : state->repf = (double)(0);
59139 0 : state->repprimalerror = (double)(0);
59140 0 : for(i=0; i<=n-1; i++)
59141 : {
59142 0 : if( ae_isfinite(state->bndl.ptr.p_double[i], _state) )
59143 : {
59144 0 : state->repprimalerror = ae_maxreal(state->repprimalerror, state->bndl.ptr.p_double[i]-0, _state);
59145 : }
59146 0 : if( ae_isfinite(state->bndu.ptr.p_double[i], _state) )
59147 : {
59148 0 : state->repprimalerror = ae_maxreal(state->repprimalerror, 0-state->bndu.ptr.p_double[i], _state);
59149 : }
59150 : }
59151 0 : for(i=0; i<=m-1; i++)
59152 : {
59153 0 : if( ae_isfinite(state->al.ptr.p_double[i], _state) )
59154 : {
59155 0 : state->repprimalerror = ae_maxreal(state->repprimalerror, state->al.ptr.p_double[i]-0, _state);
59156 : }
59157 0 : if( ae_isfinite(state->au.ptr.p_double[i], _state) )
59158 : {
59159 0 : state->repprimalerror = ae_maxreal(state->repprimalerror, 0-state->au.ptr.p_double[i], _state);
59160 : }
59161 : }
59162 0 : state->repdualerror = (double)(0);
59163 0 : for(i=0; i<=n-1; i++)
59164 : {
59165 0 : state->repdualerror = ae_maxreal(state->repdualerror, ae_fabs(state->c.ptr.p_double[i], _state), _state);
59166 : }
59167 0 : state->repslackerror = (double)(0);
59168 0 : ae_frame_leave(_state);
59169 0 : return;
59170 : }
59171 :
59172 : /*
59173 : * Call current solver
59174 : */
59175 0 : if( state->algokind==1||state->algokind==2 )
59176 : {
59177 :
59178 : /*
59179 : * Call the solver
59180 : */
59181 0 : if( state->algokind==1 )
59182 : {
59183 :
59184 : /*
59185 : * Dual simplex method with presolve
59186 : */
59187 0 : presolvenonescaleuser(&state->s, &state->c, &state->bndl, &state->bndu, n, &state->a, &state->al, &state->au, m, &state->presolver, _state);
59188 0 : dsssettingsinit(&settings, _state);
59189 0 : settings.xtolabs = state->dsseps;
59190 0 : settings.dtolabs = state->dsseps;
59191 0 : dssinit(state->presolver.newn, &state->dss, _state);
59192 0 : dsssetproblem(&state->dss, &state->presolver.c, &state->presolver.bndl, &state->presolver.bndu, &dummy, &state->presolver.sparsea, 1, &state->presolver.al, &state->presolver.au, state->presolver.newm, &dummybasis, minlp_alllogicalsbasis, &settings, _state);
59193 0 : dssoptimize(&state->dss, &settings, _state);
59194 :
59195 : /*
59196 : * Export results, convert from presolve
59197 : */
59198 0 : rvectorsetlengthatleast(&state->xs, state->presolver.newn, _state);
59199 0 : rvectorsetlengthatleast(&state->lagbc, state->presolver.newn, _state);
59200 0 : rvectorsetlengthatleast(&state->laglc, state->presolver.newm, _state);
59201 0 : ivectorsetlengthatleast(&state->cs, state->presolver.newn+state->presolver.newm, _state);
59202 0 : for(i=0; i<=state->presolver.newn-1; i++)
59203 : {
59204 0 : state->xs.ptr.p_double[i] = state->dss.repx.ptr.p_double[i];
59205 0 : state->lagbc.ptr.p_double[i] = state->dss.replagbc.ptr.p_double[i];
59206 : }
59207 0 : for(i=0; i<=state->presolver.newm-1; i++)
59208 : {
59209 0 : state->laglc.ptr.p_double[i] = state->dss.replaglc.ptr.p_double[i];
59210 : }
59211 0 : for(i=0; i<=state->presolver.newn+state->presolver.newm-1; i++)
59212 : {
59213 0 : state->cs.ptr.p_int[i] = state->dss.repstats.ptr.p_int[i];
59214 : }
59215 0 : state->repiterationscount = state->dss.repiterationscount;
59216 0 : state->repterminationtype = state->dss.repterminationtype;
59217 0 : presolvebwd(&state->presolver, &state->xs, &state->cs, &state->lagbc, &state->laglc, _state);
59218 0 : state->repn = n;
59219 0 : state->repm = m;
59220 : }
59221 0 : if( state->algokind==2 )
59222 : {
59223 :
59224 : /*
59225 : * Interior point method with presolve
59226 : */
59227 0 : presolvenonescaleuser(&state->s, &state->c, &state->bndl, &state->bndu, n, &state->a, &state->al, &state->au, m, &state->presolver, _state);
59228 0 : rsetallocv(state->presolver.newn, 1.0, &state->units, _state);
59229 0 : rsetallocv(state->presolver.newn, 0.0, &state->zeroorigin, _state);
59230 0 : sparsecreatesksbandbuf(state->presolver.newn, state->presolver.newn, 0, &state->ipmquadratic, _state);
59231 0 : for(i=0; i<=state->presolver.newn-1; i++)
59232 : {
59233 0 : sparseset(&state->ipmquadratic, i, i, state->ipmlambda, _state);
59234 : }
59235 0 : sparseconverttocrs(&state->ipmquadratic, _state);
59236 0 : vipminitsparse(&state->ipm, &state->units, &state->zeroorigin, state->presolver.newn, _state);
59237 0 : vipmsetquadraticlinear(&state->ipm, &dummy, &state->ipmquadratic, 1, ae_false, &state->presolver.c, _state);
59238 0 : vipmsetconstraints(&state->ipm, &state->presolver.bndl, &state->presolver.bndu, &state->presolver.sparsea, state->presolver.newm, &dummy, 0, &state->presolver.al, &state->presolver.au, _state);
59239 0 : vipmsetcond(&state->ipm, state->ipmeps, state->ipmeps, state->ipmeps, _state);
59240 0 : vipmoptimize(&state->ipm, ae_true, &state->xs, &state->lagbc, &state->laglc, &state->repterminationtype, _state);
59241 :
59242 : /*
59243 : * Export results, convert from presolve
59244 : */
59245 0 : isetallocv(state->presolver.newn+state->presolver.newm, 0, &state->cs, _state);
59246 0 : presolvebwd(&state->presolver, &state->xs, &state->cs, &state->lagbc, &state->laglc, _state);
59247 0 : state->repn = n;
59248 0 : state->repm = m;
59249 : }
59250 :
59251 : /*
59252 : * Compute F, primal and dual errors
59253 : */
59254 0 : state->repf = rdotv(n, &state->xs, &state->c, _state);
59255 0 : state->repprimalerror = (double)(0);
59256 0 : state->repdualerror = (double)(0);
59257 0 : state->repslackerror = (double)(0);
59258 0 : rcopyallocv(n, &state->c, &state->tmpg, _state);
59259 0 : if( m>0 )
59260 : {
59261 0 : sparsemv(&state->a, &state->xs, &state->tmpax, _state);
59262 0 : sparsegemv(&state->a, 1.0, 1, &state->laglc, 0, 1.0, &state->tmpg, 0, _state);
59263 : }
59264 0 : raddv(n, 1.0, &state->lagbc, &state->tmpg, _state);
59265 0 : for(i=0; i<=n-1; i++)
59266 : {
59267 0 : if( ae_isfinite(state->bndl.ptr.p_double[i], _state) )
59268 : {
59269 0 : state->repprimalerror = ae_maxreal(state->repprimalerror, state->bndl.ptr.p_double[i]-state->xs.ptr.p_double[i], _state);
59270 0 : state->repslackerror = ae_maxreal(state->repslackerror, ae_maxreal(state->xs.ptr.p_double[i]-state->bndl.ptr.p_double[i], 0.0, _state)*ae_maxreal(-state->lagbc.ptr.p_double[i], 0.0, _state), _state);
59271 : }
59272 0 : if( ae_isfinite(state->bndu.ptr.p_double[i], _state) )
59273 : {
59274 0 : state->repprimalerror = ae_maxreal(state->repprimalerror, state->xs.ptr.p_double[i]-state->bndu.ptr.p_double[i], _state);
59275 0 : state->repslackerror = ae_maxreal(state->repslackerror, ae_maxreal(state->bndu.ptr.p_double[i]-state->xs.ptr.p_double[i], 0.0, _state)*ae_maxreal(state->lagbc.ptr.p_double[i], 0.0, _state), _state);
59276 : }
59277 0 : state->repdualerror = ae_maxreal(state->repdualerror, ae_fabs(state->tmpg.ptr.p_double[i], _state), _state);
59278 : }
59279 0 : for(i=0; i<=m-1; i++)
59280 : {
59281 0 : v = state->tmpax.ptr.p_double[i];
59282 0 : if( ae_isfinite(state->al.ptr.p_double[i], _state) )
59283 : {
59284 0 : state->repprimalerror = ae_maxreal(state->repprimalerror, state->al.ptr.p_double[i]-v, _state);
59285 0 : state->repslackerror = ae_maxreal(state->repslackerror, ae_maxreal(v-state->al.ptr.p_double[i], 0.0, _state)*ae_maxreal(-state->laglc.ptr.p_double[i], 0.0, _state), _state);
59286 : }
59287 0 : if( ae_isfinite(state->au.ptr.p_double[i], _state) )
59288 : {
59289 0 : state->repprimalerror = ae_maxreal(state->repprimalerror, v-state->au.ptr.p_double[i], _state);
59290 0 : state->repslackerror = ae_maxreal(state->repslackerror, ae_maxreal(state->au.ptr.p_double[i]-v, 0.0, _state)*ae_maxreal(state->laglc.ptr.p_double[i], 0.0, _state), _state);
59291 : }
59292 : }
59293 0 : ae_frame_leave(_state);
59294 0 : return;
59295 : }
59296 :
59297 : /*
59298 : * Integrity check failed - unknown solver
59299 : */
59300 0 : ae_assert(ae_false, "MinQPOptimize: integrity check failed - unknown solver", _state);
59301 0 : ae_frame_leave(_state);
59302 : }
59303 :
59304 :
59305 : /*************************************************************************
59306 : LP solver results
59307 :
59308 : INPUT PARAMETERS:
59309 : State - algorithm state
59310 :
59311 : OUTPUT PARAMETERS:
59312 : X - array[N], solution (on failure: last trial point)
59313 : Rep - optimization report. You should check Rep.TerminationType,
59314 : which contains completion code, and you may check another
59315 : fields which contain another information about algorithm
59316 : functioning.
59317 :
59318 : Failure codes returned by algorithm are:
59319 : * -4 LP problem is primal unbounded (dual infeasible)
59320 : * -3 LP problem is primal infeasible (dual unbounded)
59321 : * -2 IPM solver detected that problem is either
59322 : infeasible or unbounded
59323 :
59324 : Success codes:
59325 : * 1..4 successful completion
59326 : * 5 MaxIts steps was taken
59327 :
59328 : -- ALGLIB --
59329 : Copyright 11.01.2011 by Bochkanov Sergey
59330 : *************************************************************************/
59331 0 : void minlpresults(minlpstate* state,
59332 : /* Real */ ae_vector* x,
59333 : minlpreport* rep,
59334 : ae_state *_state)
59335 : {
59336 :
59337 0 : ae_vector_clear(x);
59338 0 : _minlpreport_clear(rep);
59339 :
59340 0 : minlpresultsbuf(state, x, rep, _state);
59341 0 : }
59342 :
59343 :
59344 : /*************************************************************************
59345 : LP results
59346 :
59347 : Buffered implementation of MinLPResults() which uses pre-allocated buffer
59348 : to store X[]. If buffer size is too small, it resizes buffer. It is
59349 : intended to be used in the inner cycles of performance critical algorithms
59350 : where array reallocation penalty is too large to be ignored.
59351 :
59352 : -- ALGLIB --
59353 : Copyright 11.01.2011 by Bochkanov Sergey
59354 : *************************************************************************/
59355 0 : void minlpresultsbuf(minlpstate* state,
59356 : /* Real */ ae_vector* x,
59357 : minlpreport* rep,
59358 : ae_state *_state)
59359 : {
59360 : ae_int_t i;
59361 : ae_int_t repn;
59362 : ae_int_t repm;
59363 :
59364 :
59365 0 : repn = state->repn;
59366 0 : repm = state->repm;
59367 0 : if( x->cnt<repn )
59368 : {
59369 0 : ae_vector_set_length(x, repn, _state);
59370 : }
59371 0 : ae_vector_set_length(&rep->y, repm, _state);
59372 0 : ae_vector_set_length(&rep->stats, repn+repm, _state);
59373 0 : rep->f = state->repf;
59374 0 : rep->primalerror = state->repprimalerror;
59375 0 : rep->dualerror = state->repdualerror;
59376 0 : rep->slackerror = state->repslackerror;
59377 0 : rep->iterationscount = state->repiterationscount;
59378 0 : rep->terminationtype = state->repterminationtype;
59379 0 : rcopyallocv(repm, &state->laglc, &rep->laglc, _state);
59380 0 : rcopyallocv(repn, &state->lagbc, &rep->lagbc, _state);
59381 0 : for(i=0; i<=repn-1; i++)
59382 : {
59383 0 : x->ptr.p_double[i] = state->xs.ptr.p_double[i];
59384 : }
59385 0 : for(i=0; i<=repm-1; i++)
59386 : {
59387 0 : rep->y.ptr.p_double[i] = -rep->laglc.ptr.p_double[i];
59388 : }
59389 0 : for(i=0; i<=repn+repm-1; i++)
59390 : {
59391 0 : rep->stats.ptr.p_int[i] = state->cs.ptr.p_int[i];
59392 : }
59393 0 : }
59394 :
59395 :
59396 : /*************************************************************************
59397 : Clear report fields prior to the optimization.
59398 :
59399 : -- ALGLIB --
59400 : Copyright 19.07.2018 by Bochkanov Sergey.
59401 : *************************************************************************/
59402 0 : static void minlp_clearreportfields(minlpstate* state, ae_state *_state)
59403 : {
59404 :
59405 :
59406 0 : state->repf = 0.0;
59407 0 : state->repprimalerror = 0.0;
59408 0 : state->repdualerror = 0.0;
59409 0 : state->repiterationscount = 0;
59410 0 : state->repterminationtype = 0;
59411 0 : state->repn = 0;
59412 0 : state->repm = 0;
59413 0 : }
59414 :
59415 :
59416 0 : void _minlpstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
59417 : {
59418 0 : minlpstate *p = (minlpstate*)_p;
59419 0 : ae_touch_ptr((void*)p);
59420 0 : ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic);
59421 0 : ae_vector_init(&p->c, 0, DT_REAL, _state, make_automatic);
59422 0 : ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic);
59423 0 : ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic);
59424 0 : _sparsematrix_init(&p->a, _state, make_automatic);
59425 0 : ae_vector_init(&p->al, 0, DT_REAL, _state, make_automatic);
59426 0 : ae_vector_init(&p->au, 0, DT_REAL, _state, make_automatic);
59427 0 : ae_vector_init(&p->xs, 0, DT_REAL, _state, make_automatic);
59428 0 : ae_vector_init(&p->lagbc, 0, DT_REAL, _state, make_automatic);
59429 0 : ae_vector_init(&p->laglc, 0, DT_REAL, _state, make_automatic);
59430 0 : ae_vector_init(&p->cs, 0, DT_INT, _state, make_automatic);
59431 0 : _dualsimplexstate_init(&p->dss, _state, make_automatic);
59432 0 : _vipmstate_init(&p->ipm, _state, make_automatic);
59433 0 : ae_vector_init(&p->adddtmpi, 0, DT_INT, _state, make_automatic);
59434 0 : ae_vector_init(&p->adddtmpr, 0, DT_REAL, _state, make_automatic);
59435 0 : ae_vector_init(&p->tmpax, 0, DT_REAL, _state, make_automatic);
59436 0 : ae_vector_init(&p->tmpg, 0, DT_REAL, _state, make_automatic);
59437 0 : _presolveinfo_init(&p->presolver, _state, make_automatic);
59438 0 : ae_vector_init(&p->zeroorigin, 0, DT_REAL, _state, make_automatic);
59439 0 : ae_vector_init(&p->units, 0, DT_REAL, _state, make_automatic);
59440 0 : _sparsematrix_init(&p->ipmquadratic, _state, make_automatic);
59441 0 : }
59442 :
59443 :
59444 0 : void _minlpstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
59445 : {
59446 0 : minlpstate *dst = (minlpstate*)_dst;
59447 0 : minlpstate *src = (minlpstate*)_src;
59448 0 : dst->n = src->n;
59449 0 : dst->algokind = src->algokind;
59450 0 : dst->ipmlambda = src->ipmlambda;
59451 0 : ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic);
59452 0 : ae_vector_init_copy(&dst->c, &src->c, _state, make_automatic);
59453 0 : ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic);
59454 0 : ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic);
59455 0 : dst->m = src->m;
59456 0 : _sparsematrix_init_copy(&dst->a, &src->a, _state, make_automatic);
59457 0 : ae_vector_init_copy(&dst->al, &src->al, _state, make_automatic);
59458 0 : ae_vector_init_copy(&dst->au, &src->au, _state, make_automatic);
59459 0 : ae_vector_init_copy(&dst->xs, &src->xs, _state, make_automatic);
59460 0 : ae_vector_init_copy(&dst->lagbc, &src->lagbc, _state, make_automatic);
59461 0 : ae_vector_init_copy(&dst->laglc, &src->laglc, _state, make_automatic);
59462 0 : ae_vector_init_copy(&dst->cs, &src->cs, _state, make_automatic);
59463 0 : dst->repf = src->repf;
59464 0 : dst->repprimalerror = src->repprimalerror;
59465 0 : dst->repdualerror = src->repdualerror;
59466 0 : dst->repslackerror = src->repslackerror;
59467 0 : dst->repiterationscount = src->repiterationscount;
59468 0 : dst->repterminationtype = src->repterminationtype;
59469 0 : dst->repn = src->repn;
59470 0 : dst->repm = src->repm;
59471 0 : dst->dsseps = src->dsseps;
59472 0 : dst->ipmeps = src->ipmeps;
59473 0 : _dualsimplexstate_init_copy(&dst->dss, &src->dss, _state, make_automatic);
59474 0 : _vipmstate_init_copy(&dst->ipm, &src->ipm, _state, make_automatic);
59475 0 : ae_vector_init_copy(&dst->adddtmpi, &src->adddtmpi, _state, make_automatic);
59476 0 : ae_vector_init_copy(&dst->adddtmpr, &src->adddtmpr, _state, make_automatic);
59477 0 : ae_vector_init_copy(&dst->tmpax, &src->tmpax, _state, make_automatic);
59478 0 : ae_vector_init_copy(&dst->tmpg, &src->tmpg, _state, make_automatic);
59479 0 : _presolveinfo_init_copy(&dst->presolver, &src->presolver, _state, make_automatic);
59480 0 : ae_vector_init_copy(&dst->zeroorigin, &src->zeroorigin, _state, make_automatic);
59481 0 : ae_vector_init_copy(&dst->units, &src->units, _state, make_automatic);
59482 0 : _sparsematrix_init_copy(&dst->ipmquadratic, &src->ipmquadratic, _state, make_automatic);
59483 0 : }
59484 :
59485 :
59486 0 : void _minlpstate_clear(void* _p)
59487 : {
59488 0 : minlpstate *p = (minlpstate*)_p;
59489 0 : ae_touch_ptr((void*)p);
59490 0 : ae_vector_clear(&p->s);
59491 0 : ae_vector_clear(&p->c);
59492 0 : ae_vector_clear(&p->bndl);
59493 0 : ae_vector_clear(&p->bndu);
59494 0 : _sparsematrix_clear(&p->a);
59495 0 : ae_vector_clear(&p->al);
59496 0 : ae_vector_clear(&p->au);
59497 0 : ae_vector_clear(&p->xs);
59498 0 : ae_vector_clear(&p->lagbc);
59499 0 : ae_vector_clear(&p->laglc);
59500 0 : ae_vector_clear(&p->cs);
59501 0 : _dualsimplexstate_clear(&p->dss);
59502 0 : _vipmstate_clear(&p->ipm);
59503 0 : ae_vector_clear(&p->adddtmpi);
59504 0 : ae_vector_clear(&p->adddtmpr);
59505 0 : ae_vector_clear(&p->tmpax);
59506 0 : ae_vector_clear(&p->tmpg);
59507 0 : _presolveinfo_clear(&p->presolver);
59508 0 : ae_vector_clear(&p->zeroorigin);
59509 0 : ae_vector_clear(&p->units);
59510 0 : _sparsematrix_clear(&p->ipmquadratic);
59511 0 : }
59512 :
59513 :
59514 0 : void _minlpstate_destroy(void* _p)
59515 : {
59516 0 : minlpstate *p = (minlpstate*)_p;
59517 0 : ae_touch_ptr((void*)p);
59518 0 : ae_vector_destroy(&p->s);
59519 0 : ae_vector_destroy(&p->c);
59520 0 : ae_vector_destroy(&p->bndl);
59521 0 : ae_vector_destroy(&p->bndu);
59522 0 : _sparsematrix_destroy(&p->a);
59523 0 : ae_vector_destroy(&p->al);
59524 0 : ae_vector_destroy(&p->au);
59525 0 : ae_vector_destroy(&p->xs);
59526 0 : ae_vector_destroy(&p->lagbc);
59527 0 : ae_vector_destroy(&p->laglc);
59528 0 : ae_vector_destroy(&p->cs);
59529 0 : _dualsimplexstate_destroy(&p->dss);
59530 0 : _vipmstate_destroy(&p->ipm);
59531 0 : ae_vector_destroy(&p->adddtmpi);
59532 0 : ae_vector_destroy(&p->adddtmpr);
59533 0 : ae_vector_destroy(&p->tmpax);
59534 0 : ae_vector_destroy(&p->tmpg);
59535 0 : _presolveinfo_destroy(&p->presolver);
59536 0 : ae_vector_destroy(&p->zeroorigin);
59537 0 : ae_vector_destroy(&p->units);
59538 0 : _sparsematrix_destroy(&p->ipmquadratic);
59539 0 : }
59540 :
59541 :
59542 0 : void _minlpreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
59543 : {
59544 0 : minlpreport *p = (minlpreport*)_p;
59545 0 : ae_touch_ptr((void*)p);
59546 0 : ae_vector_init(&p->lagbc, 0, DT_REAL, _state, make_automatic);
59547 0 : ae_vector_init(&p->laglc, 0, DT_REAL, _state, make_automatic);
59548 0 : ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic);
59549 0 : ae_vector_init(&p->stats, 0, DT_INT, _state, make_automatic);
59550 0 : }
59551 :
59552 :
59553 0 : void _minlpreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
59554 : {
59555 0 : minlpreport *dst = (minlpreport*)_dst;
59556 0 : minlpreport *src = (minlpreport*)_src;
59557 0 : dst->f = src->f;
59558 0 : ae_vector_init_copy(&dst->lagbc, &src->lagbc, _state, make_automatic);
59559 0 : ae_vector_init_copy(&dst->laglc, &src->laglc, _state, make_automatic);
59560 0 : ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic);
59561 0 : ae_vector_init_copy(&dst->stats, &src->stats, _state, make_automatic);
59562 0 : dst->primalerror = src->primalerror;
59563 0 : dst->dualerror = src->dualerror;
59564 0 : dst->slackerror = src->slackerror;
59565 0 : dst->iterationscount = src->iterationscount;
59566 0 : dst->terminationtype = src->terminationtype;
59567 0 : }
59568 :
59569 :
59570 0 : void _minlpreport_clear(void* _p)
59571 : {
59572 0 : minlpreport *p = (minlpreport*)_p;
59573 0 : ae_touch_ptr((void*)p);
59574 0 : ae_vector_clear(&p->lagbc);
59575 0 : ae_vector_clear(&p->laglc);
59576 0 : ae_vector_clear(&p->y);
59577 0 : ae_vector_clear(&p->stats);
59578 0 : }
59579 :
59580 :
59581 0 : void _minlpreport_destroy(void* _p)
59582 : {
59583 0 : minlpreport *p = (minlpreport*)_p;
59584 0 : ae_touch_ptr((void*)p);
59585 0 : ae_vector_destroy(&p->lagbc);
59586 0 : ae_vector_destroy(&p->laglc);
59587 0 : ae_vector_destroy(&p->y);
59588 0 : ae_vector_destroy(&p->stats);
59589 0 : }
59590 :
59591 :
59592 : #endif
59593 : #if defined(AE_COMPILE_NLCSLP) || !defined(AE_PARTIAL_BUILD)
59594 :
59595 :
59596 0 : void minslpinitbuf(/* Real */ ae_vector* bndl,
59597 : /* Real */ ae_vector* bndu,
59598 : /* Real */ ae_vector* s,
59599 : /* Real */ ae_vector* x0,
59600 : ae_int_t n,
59601 : /* Real */ ae_matrix* cleic,
59602 : /* Integer */ ae_vector* lcsrcidx,
59603 : ae_int_t nec,
59604 : ae_int_t nic,
59605 : ae_int_t nlec,
59606 : ae_int_t nlic,
59607 : double epsx,
59608 : ae_int_t maxits,
59609 : minslpstate* state,
59610 : ae_state *_state)
59611 : {
59612 : ae_int_t i;
59613 : ae_int_t j;
59614 : double v;
59615 : double vv;
59616 :
59617 :
59618 0 : state->n = n;
59619 0 : state->nec = nec;
59620 0 : state->nic = nic;
59621 0 : state->nlec = nlec;
59622 0 : state->nlic = nlic;
59623 :
59624 : /*
59625 : * Settings
59626 : */
59627 0 : state->hessiantype = 2;
59628 :
59629 : /*
59630 : * Prepare RCOMM state
59631 : */
59632 0 : ae_vector_set_length(&state->rstate.ia, 9+1, _state);
59633 0 : ae_vector_set_length(&state->rstate.ba, 2+1, _state);
59634 0 : ae_vector_set_length(&state->rstate.ra, 10+1, _state);
59635 0 : state->rstate.stage = -1;
59636 0 : state->needfij = ae_false;
59637 0 : state->xupdated = ae_false;
59638 0 : ae_vector_set_length(&state->x, n, _state);
59639 0 : ae_vector_set_length(&state->fi, 1+nlec+nlic, _state);
59640 0 : ae_matrix_set_length(&state->j, 1+nlec+nlic, n, _state);
59641 :
59642 : /*
59643 : * Allocate memory.
59644 : */
59645 0 : rvectorsetlengthatleast(&state->s, n, _state);
59646 0 : rvectorsetlengthatleast(&state->step0x, n, _state);
59647 0 : rvectorsetlengthatleast(&state->stepkx, n, _state);
59648 0 : rvectorsetlengthatleast(&state->backupx, n, _state);
59649 0 : rvectorsetlengthatleast(&state->step0fi, 1+nlec+nlic, _state);
59650 0 : rvectorsetlengthatleast(&state->stepkfi, 1+nlec+nlic, _state);
59651 0 : rvectorsetlengthatleast(&state->backupfi, 1+nlec+nlic, _state);
59652 0 : rmatrixsetlengthatleast(&state->step0j, 1+nlec+nlic, n, _state);
59653 0 : rmatrixsetlengthatleast(&state->stepkj, 1+nlec+nlic, n, _state);
59654 0 : rmatrixsetlengthatleast(&state->backupj, 1+nlec+nlic, n, _state);
59655 0 : rvectorsetlengthatleast(&state->fscales, 1+nlec+nlic, _state);
59656 0 : rvectorsetlengthatleast(&state->meritlagmult, nec+nic+nlec+nlic, _state);
59657 0 : rvectorsetlengthatleast(&state->dummylagmult, nec+nic+nlec+nlic, _state);
59658 0 : bvectorsetlengthatleast(&state->hasbndl, n, _state);
59659 0 : bvectorsetlengthatleast(&state->hasbndu, n, _state);
59660 0 : rvectorsetlengthatleast(&state->scaledbndl, n, _state);
59661 0 : rvectorsetlengthatleast(&state->scaledbndu, n, _state);
59662 0 : rmatrixsetlengthatleast(&state->scaledcleic, nec+nic, n+1, _state);
59663 0 : ivectorsetlengthatleast(&state->lcsrcidx, nec+nic, _state);
59664 0 : rvectorsetlengthatleast(&state->meritfunctionhistory, nlcslp_nonmonotonicphase2limit+1, _state);
59665 :
59666 : /*
59667 : * Prepare scaled problem
59668 : */
59669 0 : for(i=0; i<=n-1; i++)
59670 : {
59671 0 : state->hasbndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state);
59672 0 : state->hasbndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state);
59673 0 : if( state->hasbndl.ptr.p_bool[i] )
59674 : {
59675 0 : state->scaledbndl.ptr.p_double[i] = bndl->ptr.p_double[i]/s->ptr.p_double[i];
59676 : }
59677 0 : if( state->hasbndu.ptr.p_bool[i] )
59678 : {
59679 0 : state->scaledbndu.ptr.p_double[i] = bndu->ptr.p_double[i]/s->ptr.p_double[i];
59680 : }
59681 0 : if( state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i] )
59682 : {
59683 0 : ae_assert(ae_fp_less_eq(bndl->ptr.p_double[i],bndu->ptr.p_double[i]), "SLP: integrity check failed, box constraints are inconsistent", _state);
59684 : }
59685 0 : state->step0x.ptr.p_double[i] = x0->ptr.p_double[i]/s->ptr.p_double[i];
59686 0 : state->s.ptr.p_double[i] = s->ptr.p_double[i];
59687 : }
59688 0 : for(i=0; i<=nec+nic-1; i++)
59689 : {
59690 :
59691 : /*
59692 : * Permutation
59693 : */
59694 0 : state->lcsrcidx.ptr.p_int[i] = lcsrcidx->ptr.p_int[i];
59695 :
59696 : /*
59697 : * Scale and normalize linear constraints
59698 : */
59699 0 : vv = 0.0;
59700 0 : for(j=0; j<=n-1; j++)
59701 : {
59702 0 : v = cleic->ptr.pp_double[i][j]*s->ptr.p_double[j];
59703 0 : state->scaledcleic.ptr.pp_double[i][j] = v;
59704 0 : vv = vv+v*v;
59705 : }
59706 0 : vv = ae_sqrt(vv, _state);
59707 0 : state->scaledcleic.ptr.pp_double[i][n] = cleic->ptr.pp_double[i][n];
59708 0 : if( ae_fp_greater(vv,(double)(0)) )
59709 : {
59710 0 : for(j=0; j<=n; j++)
59711 : {
59712 0 : state->scaledcleic.ptr.pp_double[i][j] = state->scaledcleic.ptr.pp_double[i][j]/vv;
59713 : }
59714 : }
59715 : }
59716 :
59717 : /*
59718 : * Initial enforcement of box constraints
59719 : */
59720 0 : for(i=0; i<=n-1; i++)
59721 : {
59722 0 : if( state->hasbndl.ptr.p_bool[i] )
59723 : {
59724 0 : state->step0x.ptr.p_double[i] = ae_maxreal(state->step0x.ptr.p_double[i], state->scaledbndl.ptr.p_double[i], _state);
59725 : }
59726 0 : if( state->hasbndu.ptr.p_bool[i] )
59727 : {
59728 0 : state->step0x.ptr.p_double[i] = ae_minreal(state->step0x.ptr.p_double[i], state->scaledbndu.ptr.p_double[i], _state);
59729 : }
59730 : }
59731 :
59732 : /*
59733 : * Stopping criteria
59734 : */
59735 0 : state->epsx = epsx;
59736 0 : state->maxits = maxits;
59737 :
59738 : /*
59739 : * Report fields
59740 : */
59741 0 : state->repsimplexiterations = 0;
59742 0 : state->repsimplexiterations1 = 0;
59743 0 : state->repsimplexiterations2 = 0;
59744 0 : state->repsimplexiterations3 = 0;
59745 0 : state->repterminationtype = 0;
59746 0 : state->repbcerr = (double)(0);
59747 0 : state->repbcidx = -1;
59748 0 : state->replcerr = (double)(0);
59749 0 : state->replcidx = -1;
59750 0 : state->repnlcerr = (double)(0);
59751 0 : state->repnlcidx = -1;
59752 0 : state->repinneriterationscount = 0;
59753 0 : state->repouteriterationscount = 0;
59754 :
59755 : /*
59756 : * Integrity checks:
59757 : * * it is important that significant step length is large enough that
59758 : * we do not decrease trust regiod radius; it should also be small,
59759 : * so we won't treat large steps as insignificant
59760 : */
59761 0 : ae_assert(ae_fp_less(nlcslp_slpstpclosetozero,nlcslp_slpdeltadecrease), "MinSLP: integrity check failed", _state);
59762 0 : ae_assert(ae_fp_less(nlcslp_slpdeltadecrease,nlcslp_slpdeltaincrease), "MinSLP: integrity check failed", _state);
59763 0 : ae_assert(ae_fp_less(nlcslp_slpdeltaincrease,nlcslp_slpstpclosetoone), "MinSLP: integrity check failed", _state);
59764 0 : }
59765 :
59766 :
59767 : /*************************************************************************
59768 : This function performs actual processing for SLP algorithm. It expects
59769 : that caller redirects its reverse communication requests NeedFiJ/XUpdated
59770 : to external user who will provide analytic derivative (or handle reports
59771 : about progress).
59772 :
59773 : In case external user does not have analytic derivative, it is responsibility
59774 : of caller to intercept NeedFiJ request and replace it with appropriate
59775 : numerical differentiation scheme.
59776 :
59777 : Results are stored:
59778 : * point - in State.StepKX
59779 :
59780 : IMPORTANT: this function works with scaled problem formulation; it is
59781 : responsibility of the caller to unscale request and scale
59782 : Jacobian.
59783 :
59784 : NOTE: SMonitor is expected to be correctly initialized smoothness monitor.
59785 :
59786 : -- ALGLIB --
59787 : Copyright 05.03.2018 by Bochkanov Sergey
59788 : *************************************************************************/
59789 0 : ae_bool minslpiteration(minslpstate* state,
59790 : smoothnessmonitor* smonitor,
59791 : ae_bool userterminationneeded,
59792 : ae_state *_state)
59793 : {
59794 : ae_int_t n;
59795 : ae_int_t nslack;
59796 : ae_int_t nec;
59797 : ae_int_t nic;
59798 : ae_int_t nlec;
59799 : ae_int_t nlic;
59800 : ae_int_t i;
59801 : ae_int_t j;
59802 : ae_int_t innerk;
59803 : double v;
59804 : double vv;
59805 : double mx;
59806 : ae_bool lpstagesuccess;
59807 : double gammamax;
59808 : double f1;
59809 : double f2;
59810 : ae_int_t status;
59811 : double stp;
59812 : double deltamax;
59813 : double multiplyby;
59814 : double setscaleto;
59815 : double prevtrustrad;
59816 : ae_bool dotrace;
59817 : ae_bool dodetailedtrace;
59818 : ae_bool result;
59819 :
59820 :
59821 :
59822 : /*
59823 : * Reverse communication preparations
59824 : * I know it looks ugly, but it works the same way
59825 : * anywhere from C++ to Python.
59826 : *
59827 : * This code initializes locals by:
59828 : * * random values determined during code
59829 : * generation - on first subroutine call
59830 : * * values from previous call - on subsequent calls
59831 : */
59832 0 : if( state->rstate.stage>=0 )
59833 : {
59834 0 : n = state->rstate.ia.ptr.p_int[0];
59835 0 : nslack = state->rstate.ia.ptr.p_int[1];
59836 0 : nec = state->rstate.ia.ptr.p_int[2];
59837 0 : nic = state->rstate.ia.ptr.p_int[3];
59838 0 : nlec = state->rstate.ia.ptr.p_int[4];
59839 0 : nlic = state->rstate.ia.ptr.p_int[5];
59840 0 : i = state->rstate.ia.ptr.p_int[6];
59841 0 : j = state->rstate.ia.ptr.p_int[7];
59842 0 : innerk = state->rstate.ia.ptr.p_int[8];
59843 0 : status = state->rstate.ia.ptr.p_int[9];
59844 0 : lpstagesuccess = state->rstate.ba.ptr.p_bool[0];
59845 0 : dotrace = state->rstate.ba.ptr.p_bool[1];
59846 0 : dodetailedtrace = state->rstate.ba.ptr.p_bool[2];
59847 0 : v = state->rstate.ra.ptr.p_double[0];
59848 0 : vv = state->rstate.ra.ptr.p_double[1];
59849 0 : mx = state->rstate.ra.ptr.p_double[2];
59850 0 : gammamax = state->rstate.ra.ptr.p_double[3];
59851 0 : f1 = state->rstate.ra.ptr.p_double[4];
59852 0 : f2 = state->rstate.ra.ptr.p_double[5];
59853 0 : stp = state->rstate.ra.ptr.p_double[6];
59854 0 : deltamax = state->rstate.ra.ptr.p_double[7];
59855 0 : multiplyby = state->rstate.ra.ptr.p_double[8];
59856 0 : setscaleto = state->rstate.ra.ptr.p_double[9];
59857 0 : prevtrustrad = state->rstate.ra.ptr.p_double[10];
59858 : }
59859 : else
59860 : {
59861 0 : n = 359;
59862 0 : nslack = -58;
59863 0 : nec = -919;
59864 0 : nic = -909;
59865 0 : nlec = 81;
59866 0 : nlic = 255;
59867 0 : i = 74;
59868 0 : j = -788;
59869 0 : innerk = 809;
59870 0 : status = 205;
59871 0 : lpstagesuccess = ae_false;
59872 0 : dotrace = ae_true;
59873 0 : dodetailedtrace = ae_false;
59874 0 : v = 763;
59875 0 : vv = -541;
59876 0 : mx = -698;
59877 0 : gammamax = -900;
59878 0 : f1 = -318;
59879 0 : f2 = -940;
59880 0 : stp = 1016;
59881 0 : deltamax = -229;
59882 0 : multiplyby = -536;
59883 0 : setscaleto = 487;
59884 0 : prevtrustrad = -115;
59885 : }
59886 0 : if( state->rstate.stage==0 )
59887 : {
59888 0 : goto lbl_0;
59889 : }
59890 0 : if( state->rstate.stage==1 )
59891 : {
59892 0 : goto lbl_1;
59893 : }
59894 0 : if( state->rstate.stage==2 )
59895 : {
59896 0 : goto lbl_2;
59897 : }
59898 0 : if( state->rstate.stage==3 )
59899 : {
59900 0 : goto lbl_3;
59901 : }
59902 0 : if( state->rstate.stage==4 )
59903 : {
59904 0 : goto lbl_4;
59905 : }
59906 :
59907 : /*
59908 : * Routine body
59909 : */
59910 0 : n = state->n;
59911 0 : nec = state->nec;
59912 0 : nic = state->nic;
59913 0 : nlec = state->nlec;
59914 0 : nlic = state->nlic;
59915 0 : nslack = n+2*(nec+nlec)+(nic+nlic);
59916 0 : dotrace = ae_is_trace_enabled("SLP");
59917 0 : dodetailedtrace = dotrace&&ae_is_trace_enabled("SLP.DETAILED");
59918 :
59919 : /*
59920 : * Prepare rcomm interface
59921 : */
59922 0 : state->needfij = ae_false;
59923 0 : state->xupdated = ae_false;
59924 :
59925 : /*
59926 : * Initialize algorithm data:
59927 : * * Lagrangian and "Big C" estimates
59928 : * * trust region
59929 : * * initial function scales (vector of 1's)
59930 : * * current approximation of the Hessian matrix H (unit matrix)
59931 : * * initial linearized constraints
59932 : * * initial violation of linear/nonlinear constraints
59933 : */
59934 0 : state->lpfailurecnt = 0;
59935 0 : state->fstagnationcnt = 0;
59936 0 : state->trustrad = nlcslp_inittrustrad;
59937 0 : for(i=0; i<=nlec+nlic; i++)
59938 : {
59939 0 : state->fscales.ptr.p_double[i] = 1.0;
59940 : }
59941 0 : for(i=0; i<=nlcslp_nonmonotonicphase2limit; i++)
59942 : {
59943 0 : state->meritfunctionhistory.ptr.p_double[i] = ae_maxrealnumber;
59944 : }
59945 0 : state->historylen = 0;
59946 0 : gammamax = 0.0;
59947 :
59948 : /*
59949 : * Avoid spurious warnings about possibly uninitialized vars
59950 : */
59951 0 : status = 0;
59952 0 : stp = (double)(0);
59953 :
59954 : /*
59955 : * Evaluate function vector and Jacobian at Step0X, send first location report.
59956 : * Compute initial violation of constraints.
59957 : */
59958 0 : nlcslp_slpsendx(state, &state->step0x, _state);
59959 0 : state->needfij = ae_true;
59960 0 : state->rstate.stage = 0;
59961 0 : goto lbl_rcomm;
59962 0 : lbl_0:
59963 0 : state->needfij = ae_false;
59964 0 : if( !nlcslp_slpretrievefij(state, &state->step0fi, &state->step0j, _state) )
59965 : {
59966 :
59967 : /*
59968 : * Failed to retrieve function/Jaconian, infinities detected!
59969 : */
59970 0 : for(i=0; i<=n-1; i++)
59971 : {
59972 0 : state->stepkx.ptr.p_double[i] = state->step0x.ptr.p_double[i];
59973 : }
59974 0 : state->repterminationtype = -8;
59975 0 : result = ae_false;
59976 0 : return result;
59977 : }
59978 0 : nlcslp_slpcopystate(state, &state->step0x, &state->step0fi, &state->step0j, &state->stepkx, &state->stepkfi, &state->stepkj, _state);
59979 0 : nlcslp_slpsendx(state, &state->stepkx, _state);
59980 0 : state->f = state->stepkfi.ptr.p_double[0]*state->fscales.ptr.p_double[0];
59981 0 : state->xupdated = ae_true;
59982 0 : state->rstate.stage = 1;
59983 0 : goto lbl_rcomm;
59984 0 : lbl_1:
59985 0 : state->xupdated = ae_false;
59986 0 : checklcviolation(&state->scaledcleic, &state->lcsrcidx, nec, nic, &state->stepkx, n, &state->replcerr, &state->replcidx, _state);
59987 0 : unscaleandchecknlcviolation(&state->stepkfi, &state->fscales, nlec, nlic, &state->repnlcerr, &state->repnlcidx, _state);
59988 :
59989 : /*
59990 : * Trace output (if needed)
59991 : */
59992 0 : if( dotrace )
59993 : {
59994 0 : ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n");
59995 0 : ae_trace("// SLP SOLVER STARTED //\n");
59996 0 : ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n");
59997 : }
59998 :
59999 : /*
60000 : * Perform outer (NLC) iterations
60001 : */
60002 0 : nlcslp_initlpsubsolver(state, &state->subsolver, state->hessiantype, _state);
60003 0 : lbl_5:
60004 : if( ae_false )
60005 : {
60006 : goto lbl_6;
60007 : }
60008 :
60009 : /*
60010 : * Before beginning new outer iteration:
60011 : * * renormalize target function and/or constraints, if some of them have too large magnitudes
60012 : * * save initial point for the outer iteration
60013 : */
60014 0 : for(i=0; i<=nlec+nlic; i++)
60015 : {
60016 :
60017 : /*
60018 : * Determine (a) multiplicative coefficient applied to function value
60019 : * and Jacobian row, and (b) new value of the function scale.
60020 : */
60021 0 : mx = (double)(0);
60022 0 : for(j=0; j<=n-1; j++)
60023 : {
60024 0 : mx = ae_maxreal(mx, ae_fabs(state->stepkj.ptr.pp_double[i][j], _state), _state);
60025 : }
60026 0 : multiplyby = 1.0;
60027 0 : setscaleto = state->fscales.ptr.p_double[i];
60028 0 : if( ae_fp_greater_eq(mx,nlcslp_slpbigscale) )
60029 : {
60030 0 : multiplyby = 1/mx;
60031 0 : setscaleto = state->fscales.ptr.p_double[i]*mx;
60032 : }
60033 0 : if( ae_fp_less_eq(mx,nlcslp_slpsmallscale)&&ae_fp_greater(state->fscales.ptr.p_double[i],1.0) )
60034 : {
60035 0 : if( ae_fp_greater(state->fscales.ptr.p_double[i]*mx,(double)(1)) )
60036 : {
60037 0 : multiplyby = 1/mx;
60038 0 : setscaleto = state->fscales.ptr.p_double[i]*mx;
60039 : }
60040 : else
60041 : {
60042 0 : multiplyby = state->fscales.ptr.p_double[i];
60043 0 : setscaleto = 1.0;
60044 : }
60045 : }
60046 0 : if( ae_fp_neq(multiplyby,1.0) )
60047 : {
60048 :
60049 : /*
60050 : * Function #I needs renormalization:
60051 : * * update function vector element and Jacobian matrix row
60052 : * * update FScales[] array
60053 : */
60054 0 : state->stepkfi.ptr.p_double[i] = state->stepkfi.ptr.p_double[i]*multiplyby;
60055 0 : for(j=0; j<=n-1; j++)
60056 : {
60057 0 : state->stepkj.ptr.pp_double[i][j] = state->stepkj.ptr.pp_double[i][j]*multiplyby;
60058 : }
60059 0 : state->fscales.ptr.p_double[i] = setscaleto;
60060 : }
60061 : }
60062 :
60063 : /*
60064 : * Save initial point for the outer iteration
60065 : */
60066 0 : nlcslp_slpcopystate(state, &state->stepkx, &state->stepkfi, &state->stepkj, &state->step0x, &state->step0fi, &state->step0j, _state);
60067 :
60068 : /*
60069 : * Trace output (if needed)
60070 : */
60071 0 : if( dotrace )
60072 : {
60073 0 : ae_trace("\n=== OUTER ITERATION %5d STARTED ==================================================================\n",
60074 0 : (int)(state->repouteriterationscount));
60075 0 : if( dodetailedtrace )
60076 : {
60077 0 : ae_trace("> printing raw data (prior to applying variable and function scales)\n");
60078 0 : ae_trace("X (raw) = ");
60079 0 : tracevectorunscaledunshiftedautoprec(&state->step0x, n, &state->s, ae_true, &state->s, ae_false, _state);
60080 0 : ae_trace("\n");
60081 0 : ae_trace("> printing scaled data (after applying variable and function scales)\n");
60082 0 : ae_trace("X (scaled) = ");
60083 0 : tracevectorautoprec(&state->step0x, 0, n, _state);
60084 0 : ae_trace("\n");
60085 0 : ae_trace("FScales = ");
60086 0 : tracevectorautoprec(&state->fscales, 0, 1+nlec+nlic, _state);
60087 0 : ae_trace("\n");
60088 0 : ae_trace("Fi (scaled) = ");
60089 0 : tracevectorautoprec(&state->stepkfi, 0, 1+nlec+nlic, _state);
60090 0 : ae_trace("\n");
60091 0 : ae_trace("|Ji| (scaled) = ");
60092 0 : tracerownrm1autoprec(&state->stepkj, 0, 1+nlec+nlic, 0, n, _state);
60093 0 : ae_trace("\n");
60094 : }
60095 0 : mx = (double)(0);
60096 0 : for(i=1; i<=nlec; i++)
60097 : {
60098 0 : mx = ae_maxreal(mx, ae_fabs(state->stepkfi.ptr.p_double[i], _state), _state);
60099 : }
60100 0 : for(i=nlec+1; i<=nlec+nlic; i++)
60101 : {
60102 0 : mx = ae_maxreal(mx, state->stepkfi.ptr.p_double[i], _state);
60103 : }
60104 0 : ae_trace("trustRad = %0.3e\n",
60105 0 : (double)(state->trustrad));
60106 0 : ae_trace("lin.violation = %0.3e (scaled violation of linear constraints)\n",
60107 0 : (double)(state->replcerr));
60108 0 : ae_trace("nlc.violation = %0.3e (scaled violation of nonlinear constraints)\n",
60109 : (double)(mx));
60110 0 : ae_trace("gammaMax = %0.3e\n",
60111 : (double)(gammamax));
60112 : }
60113 :
60114 : /*
60115 : * PHASE 1:
60116 : *
60117 : * * perform step using linear model with second order correction
60118 : * * compute "reference" Lagrange multipliers
60119 : * * compute merit function at the end of the phase 1 and push it to the history queue
60120 : *
60121 : * NOTE: a second order correction helps to overcome Maratos effect - a tendency
60122 : * of L1 penalized merit function to reject nonzero steps along steepest
60123 : * descent direction.
60124 : *
60125 : * The idea (explained in more details in the Phase13Iteration() body)
60126 : * is to perform one look-ahead step and use updated constraint values
60127 : * back at the initial point.
60128 : */
60129 0 : nlcslp_phase13init(&state->state13, n, nec, nic, nlec, nlic, ae_false, _state);
60130 0 : lbl_7:
60131 0 : if( !nlcslp_phase13iteration(state, &state->state13, smonitor, userterminationneeded, &state->stepkx, &state->stepkfi, &state->stepkj, &state->meritlagmult, &status, &stp, _state) )
60132 : {
60133 0 : goto lbl_8;
60134 : }
60135 0 : state->rstate.stage = 2;
60136 0 : goto lbl_rcomm;
60137 0 : lbl_2:
60138 0 : goto lbl_7;
60139 0 : lbl_8:
60140 0 : if( status<0 )
60141 : {
60142 0 : goto lbl_5;
60143 : }
60144 0 : if( status==0 )
60145 : {
60146 0 : goto lbl_6;
60147 : }
60148 0 : for(i=state->historylen; i>=1; i--)
60149 : {
60150 0 : state->meritfunctionhistory.ptr.p_double[i] = state->meritfunctionhistory.ptr.p_double[i-1];
60151 : }
60152 0 : state->meritfunctionhistory.ptr.p_double[0] = nlcslp_meritfunction(state, &state->stepkx, &state->stepkfi, &state->meritlagmult, &state->tmpmerit, _state);
60153 0 : state->historylen = ae_minint(state->historylen+1, nlcslp_nonmonotonicphase2limit, _state);
60154 :
60155 : /*
60156 : * PHASE 2: conjugate subiterations
60157 : *
60158 : * If step with second order correction is shorter than 1.0, it means
60159 : * that target is sufficiently nonlinear to use advanced iterations.
60160 : * * perform inner LP subiterations with additional conjugacy constraints
60161 : * * check changes in merit function, discard iteration results if merit function increased
60162 : */
60163 0 : if( ae_fp_greater_eq(stp,nlcslp_slpstpclosetoone) )
60164 : {
60165 0 : goto lbl_9;
60166 : }
60167 0 : if( dotrace )
60168 : {
60169 0 : ae_trace("> linear model produced short step, starting conjugate-gradient-like phase\n");
60170 : }
60171 0 : nlcslp_slpcopystate(state, &state->stepkx, &state->stepkfi, &state->stepkj, &state->backupx, &state->backupfi, &state->backupj, _state);
60172 :
60173 : /*
60174 : * LP subiterations
60175 : */
60176 0 : nlcslp_phase2init(&state->state2, n, nec, nic, nlec, nlic, &state->meritlagmult, _state);
60177 0 : lbl_11:
60178 0 : if( !nlcslp_phase2iteration(state, &state->state2, smonitor, userterminationneeded, &state->stepkx, &state->stepkfi, &state->stepkj, &state->dummylagmult, &gammamax, &status, _state) )
60179 : {
60180 0 : goto lbl_12;
60181 : }
60182 0 : state->rstate.stage = 3;
60183 0 : goto lbl_rcomm;
60184 0 : lbl_3:
60185 0 : goto lbl_11;
60186 0 : lbl_12:
60187 0 : if( status==0 )
60188 : {
60189 :
60190 : /*
60191 : * Save progress so far and stop
60192 : */
60193 0 : goto lbl_6;
60194 : }
60195 :
60196 : /*
60197 : * Evaluating step
60198 : *
60199 : * This step is essential because previous step (which minimizes Lagrangian) may fail
60200 : * to produce descent direction for L1-penalized merit function and will increase it
60201 : * instead of decreasing.
60202 : *
60203 : * During evaluation we compare merit function at new location with maximum computed
60204 : * over last NonmonotonicPhase2Limit+1 previous ones (as suggested in 'A Sequential
60205 : * Quadratic Programming Algorithm with Non-Monotone Line Search' by Yu-Hong Dai).
60206 : *
60207 : * Settings NonmonotonicPhase2Limit to 0 will result in strictly monotonic line search,
60208 : * whilst having nonzero limits means that we perform more robust nonmonotonic search.
60209 : */
60210 0 : f1 = state->meritfunctionhistory.ptr.p_double[0];
60211 0 : for(i=1; i<=state->historylen; i++)
60212 : {
60213 0 : f1 = ae_maxreal(f1, state->meritfunctionhistory.ptr.p_double[i], _state);
60214 : }
60215 0 : f2 = nlcslp_meritfunction(state, &state->stepkx, &state->stepkfi, &state->meritlagmult, &state->tmpmerit, _state);
60216 0 : if( dotrace )
60217 : {
60218 0 : ae_trace("> evaluating changes in merit function (max over last %0d values is used for reference):\n",
60219 0 : (int)(nlcslp_nonmonotonicphase2limit+1));
60220 0 : ae_trace("meritF: %14.6e -> %14.6e (delta=%11.3e)\n",
60221 : (double)(f1),
60222 : (double)(f2),
60223 : (double)(f2-f1));
60224 : }
60225 0 : if( ae_fp_less(f2,f1) )
60226 : {
60227 0 : goto lbl_13;
60228 : }
60229 :
60230 : /*
60231 : * Merit function does not decrease, discard phase results and report is as one
60232 : * more "fake" inner iteration.
60233 : *
60234 : * NOTE: it is important that F2=F1 is considered as "does not decrease"
60235 : */
60236 0 : if( dotrace )
60237 : {
60238 0 : ae_trace("> CG-like phase increased merit function, completely discarding phase (happens sometimes, but not too often)\n");
60239 : }
60240 0 : nlcslp_slpcopystate(state, &state->backupx, &state->backupfi, &state->backupj, &state->stepkx, &state->stepkfi, &state->stepkj, _state);
60241 0 : inc(&state->repinneriterationscount, _state);
60242 0 : nlcslp_slpsendx(state, &state->stepkx, _state);
60243 0 : state->f = state->stepkfi.ptr.p_double[0]*state->fscales.ptr.p_double[0];
60244 0 : state->xupdated = ae_true;
60245 0 : state->rstate.stage = 4;
60246 0 : goto lbl_rcomm;
60247 0 : lbl_4:
60248 0 : state->xupdated = ae_false;
60249 0 : checklcviolation(&state->scaledcleic, &state->lcsrcidx, nec, nic, &state->stepkx, n, &state->replcerr, &state->replcidx, _state);
60250 0 : unscaleandchecknlcviolation(&state->stepkfi, &state->fscales, nlec, nlic, &state->repnlcerr, &state->repnlcidx, _state);
60251 0 : goto lbl_14;
60252 0 : lbl_13:
60253 :
60254 : /*
60255 : * Merit function decreased, accept phase
60256 : */
60257 0 : state->meritfunctionhistory.ptr.p_double[0] = f2;
60258 0 : if( dotrace )
60259 : {
60260 0 : ae_trace("> CG-like phase decreased merit function, CG-like step accepted\n");
60261 : }
60262 0 : lbl_14:
60263 0 : goto lbl_10;
60264 0 : lbl_9:
60265 :
60266 : /*
60267 : * No phase #2
60268 : */
60269 0 : if( dotrace )
60270 : {
60271 0 : if( ae_fp_greater(stp,(double)(0)) )
60272 : {
60273 0 : ae_trace("> linear model produced long step, no need to start CG-like iterations\n");
60274 : }
60275 : else
60276 : {
60277 0 : ae_trace("> linear model produced zero step, maybe trust radius is too large\n");
60278 : }
60279 : }
60280 0 : lbl_10:
60281 :
60282 : /*
60283 : * Update trust region
60284 : */
60285 0 : prevtrustrad = state->trustrad;
60286 0 : deltamax = (double)(0);
60287 0 : for(i=0; i<=n-1; i++)
60288 : {
60289 0 : deltamax = ae_maxreal(deltamax, ae_fabs(state->step0x.ptr.p_double[i]-state->stepkx.ptr.p_double[i], _state)/state->trustrad, _state);
60290 : }
60291 0 : if( ae_fp_less_eq(deltamax,nlcslp_slpdeltadecrease) )
60292 : {
60293 0 : state->trustrad = state->trustrad*ae_maxreal(deltamax/nlcslp_slpdeltadecrease, nlcslp_maxtrustraddecay, _state);
60294 : }
60295 0 : if( ae_fp_greater_eq(deltamax,nlcslp_slpdeltaincrease) )
60296 : {
60297 0 : state->trustrad = state->trustrad*ae_minreal(deltamax/nlcslp_slpdeltaincrease, nlcslp_maxtrustradgrowth, _state);
60298 : }
60299 :
60300 : /*
60301 : * Trace
60302 : */
60303 0 : if( dotrace )
60304 : {
60305 0 : ae_trace("\n--- outer iteration ends ---------------------------------------------------------------------------\n");
60306 0 : ae_trace("deltaMax = %0.3f (ratio of step length to trust radius)\n",
60307 : (double)(deltamax));
60308 0 : ae_trace("newTrustRad = %0.3e",
60309 0 : (double)(state->trustrad));
60310 0 : if( ae_fp_greater(state->trustrad,prevtrustrad) )
60311 : {
60312 0 : ae_trace(", trust radius increased");
60313 : }
60314 0 : if( ae_fp_less(state->trustrad,prevtrustrad) )
60315 : {
60316 0 : ae_trace(", trust radius decreased");
60317 : }
60318 0 : ae_trace("\n");
60319 : }
60320 :
60321 : /*
60322 : * Advance outer iteration counter, test stopping criteria
60323 : */
60324 0 : inc(&state->repouteriterationscount, _state);
60325 0 : if( ae_fp_less_eq(ae_fabs(state->stepkfi.ptr.p_double[0]-state->step0fi.ptr.p_double[0], _state),nlcslp_stagnationepsf*ae_fabs(state->step0fi.ptr.p_double[0], _state)) )
60326 : {
60327 0 : inc(&state->fstagnationcnt, _state);
60328 : }
60329 : else
60330 : {
60331 0 : state->fstagnationcnt = 0;
60332 : }
60333 0 : if( ae_fp_less_eq(state->trustrad,state->epsx) )
60334 : {
60335 0 : state->repterminationtype = 2;
60336 0 : if( dotrace )
60337 : {
60338 0 : ae_trace("> stopping condition met: trust radius is smaller than %0.3e\n",
60339 0 : (double)(state->epsx));
60340 : }
60341 0 : goto lbl_6;
60342 : }
60343 0 : if( state->maxits>0&&state->repinneriterationscount>=state->maxits )
60344 : {
60345 0 : state->repterminationtype = 5;
60346 0 : if( dotrace )
60347 : {
60348 0 : ae_trace("> stopping condition met: %0d iterations performed\n",
60349 0 : (int)(state->repinneriterationscount));
60350 : }
60351 0 : goto lbl_6;
60352 : }
60353 0 : if( state->fstagnationcnt>=nlcslp_fstagnationlimit )
60354 : {
60355 0 : state->repterminationtype = 7;
60356 0 : if( dotrace )
60357 : {
60358 0 : ae_trace("> stopping criteria are too stringent: F stagnated for %0d its, stopping\n",
60359 0 : (int)(state->fstagnationcnt));
60360 : }
60361 0 : goto lbl_6;
60362 : }
60363 0 : goto lbl_5;
60364 0 : lbl_6:
60365 0 : smoothnessmonitortracestatus(smonitor, dotrace, _state);
60366 0 : result = ae_false;
60367 0 : return result;
60368 :
60369 : /*
60370 : * Saving state
60371 : */
60372 0 : lbl_rcomm:
60373 0 : result = ae_true;
60374 0 : state->rstate.ia.ptr.p_int[0] = n;
60375 0 : state->rstate.ia.ptr.p_int[1] = nslack;
60376 0 : state->rstate.ia.ptr.p_int[2] = nec;
60377 0 : state->rstate.ia.ptr.p_int[3] = nic;
60378 0 : state->rstate.ia.ptr.p_int[4] = nlec;
60379 0 : state->rstate.ia.ptr.p_int[5] = nlic;
60380 0 : state->rstate.ia.ptr.p_int[6] = i;
60381 0 : state->rstate.ia.ptr.p_int[7] = j;
60382 0 : state->rstate.ia.ptr.p_int[8] = innerk;
60383 0 : state->rstate.ia.ptr.p_int[9] = status;
60384 0 : state->rstate.ba.ptr.p_bool[0] = lpstagesuccess;
60385 0 : state->rstate.ba.ptr.p_bool[1] = dotrace;
60386 0 : state->rstate.ba.ptr.p_bool[2] = dodetailedtrace;
60387 0 : state->rstate.ra.ptr.p_double[0] = v;
60388 0 : state->rstate.ra.ptr.p_double[1] = vv;
60389 0 : state->rstate.ra.ptr.p_double[2] = mx;
60390 0 : state->rstate.ra.ptr.p_double[3] = gammamax;
60391 0 : state->rstate.ra.ptr.p_double[4] = f1;
60392 0 : state->rstate.ra.ptr.p_double[5] = f2;
60393 0 : state->rstate.ra.ptr.p_double[6] = stp;
60394 0 : state->rstate.ra.ptr.p_double[7] = deltamax;
60395 0 : state->rstate.ra.ptr.p_double[8] = multiplyby;
60396 0 : state->rstate.ra.ptr.p_double[9] = setscaleto;
60397 0 : state->rstate.ra.ptr.p_double[10] = prevtrustrad;
60398 0 : return result;
60399 : }
60400 :
60401 :
60402 : /*************************************************************************
60403 : This function initializes SLP subproblem.
60404 : Should be called once in the beginning of the optimization.
60405 :
60406 : INPUT PARAMETERS:
60407 : SState - solver state
60408 : Subsolver - SLP subproblem to initialize
60409 : HessianType - 0 for identity Hessian, 1 for BFGS update
60410 :
60411 :
60412 : RETURN VALUE:
60413 : True on success
60414 : False on failure of the LP solver (unexpected... but possible due to numerical errors)
60415 :
60416 :
60417 : -- ALGLIB --
60418 : Copyright 05.03.2018 by Bochkanov Sergey
60419 : *************************************************************************/
60420 0 : static void nlcslp_initlpsubsolver(minslpstate* sstate,
60421 : minslpsubsolver* subsolver,
60422 : ae_int_t hessiantype,
60423 : ae_state *_state)
60424 : {
60425 : ae_int_t n;
60426 : ae_int_t nslack;
60427 : ae_int_t nec;
60428 : ae_int_t nic;
60429 : ae_int_t nlec;
60430 : ae_int_t nlic;
60431 : ae_int_t lccnt;
60432 : ae_int_t nnz;
60433 : ae_int_t offs;
60434 : ae_int_t i;
60435 : ae_int_t j;
60436 :
60437 :
60438 0 : n = sstate->n;
60439 0 : nec = sstate->nec;
60440 0 : nic = sstate->nic;
60441 0 : nlec = sstate->nlec;
60442 0 : nlic = sstate->nlic;
60443 0 : nslack = n+2*(nec+nlec)+(nic+nlic);
60444 0 : lccnt = nec+nic+nlec+nlic;
60445 :
60446 : /*
60447 : * Create simplex solver.
60448 : *
60449 : * NOTE: we disable DSE pricing because it interferes with our
60450 : * warm-start strategy.
60451 : */
60452 0 : dsssettingsinit(&subsolver->dsssettings, _state);
60453 0 : subsolver->dsssettings.pricing = 0;
60454 :
60455 : /*
60456 : * Allocate temporaries
60457 : */
60458 0 : rvectorsetlengthatleast(&subsolver->cural, lccnt+n, _state);
60459 0 : rvectorsetlengthatleast(&subsolver->curau, lccnt+n, _state);
60460 0 : rmatrixsetlengthatleast(&subsolver->curd, n, n, _state);
60461 0 : rmatrixsetlengthatleast(&subsolver->curhd, n, n, _state);
60462 0 : rvectorsetlengthatleast(&subsolver->curbndl, nslack, _state);
60463 0 : rvectorsetlengthatleast(&subsolver->curbndu, nslack, _state);
60464 0 : rvectorsetlengthatleast(&subsolver->curb, nslack, _state);
60465 0 : rvectorsetlengthatleast(&subsolver->sk, n, _state);
60466 0 : rvectorsetlengthatleast(&subsolver->yk, n, _state);
60467 :
60468 : /*
60469 : * Initial state
60470 : */
60471 0 : subsolver->basispresent = ae_false;
60472 0 : subsolver->curdcnt = 0;
60473 0 : subsolver->hessiantype = hessiantype;
60474 0 : if( hessiantype==1||hessiantype==2 )
60475 : {
60476 :
60477 : /*
60478 : * Prepare Hessian matrix
60479 : */
60480 0 : rmatrixsetlengthatleast(&subsolver->h, n, n, _state);
60481 0 : for(i=0; i<=n-1; i++)
60482 : {
60483 0 : for(j=0; j<=n-1; j++)
60484 : {
60485 0 : subsolver->h.ptr.pp_double[i][j] = (double)(0);
60486 : }
60487 0 : subsolver->h.ptr.pp_double[i][i] = (double)(1);
60488 : }
60489 : }
60490 :
60491 : /*
60492 : * Linear constraints do not change across subiterations, that's
60493 : * why we allocate storage for them at the start of the program.
60494 : *
60495 : * A full set of "raw" constraints is stored; later we will filter
60496 : * out inequality ones which are inactive anywhere in the current
60497 : * trust region.
60498 : *
60499 : * NOTE: because sparserawlc object stores only linear constraint
60500 : * (linearizations of nonlinear ones are not stored) we
60501 : * allocate only minimum necessary space.
60502 : */
60503 0 : nnz = 0;
60504 0 : for(i=0; i<=nec+nic-1; i++)
60505 : {
60506 0 : for(j=0; j<=n-1; j++)
60507 : {
60508 0 : if( sstate->scaledcleic.ptr.pp_double[i][j]!=0.0 )
60509 : {
60510 0 : nnz = nnz+1;
60511 : }
60512 : }
60513 : }
60514 0 : ivectorsetlengthatleast(&subsolver->sparserawlc.ridx, nec+nic+1, _state);
60515 0 : rvectorsetlengthatleast(&subsolver->sparserawlc.vals, nnz, _state);
60516 0 : ivectorsetlengthatleast(&subsolver->sparserawlc.idx, nnz, _state);
60517 0 : ivectorsetlengthatleast(&subsolver->sparserawlc.didx, nec+nic, _state);
60518 0 : ivectorsetlengthatleast(&subsolver->sparserawlc.uidx, nec+nic, _state);
60519 0 : offs = 0;
60520 0 : subsolver->sparserawlc.ridx.ptr.p_int[0] = 0;
60521 0 : for(i=0; i<=nec+nic-1; i++)
60522 : {
60523 0 : for(j=0; j<=n-1; j++)
60524 : {
60525 0 : if( sstate->scaledcleic.ptr.pp_double[i][j]!=0.0 )
60526 : {
60527 :
60528 : /*
60529 : * Primary part of the matrix
60530 : */
60531 0 : subsolver->sparserawlc.vals.ptr.p_double[offs] = sstate->scaledcleic.ptr.pp_double[i][j];
60532 0 : subsolver->sparserawlc.idx.ptr.p_int[offs] = j;
60533 0 : offs = offs+1;
60534 : }
60535 : }
60536 0 : subsolver->sparserawlc.ridx.ptr.p_int[i+1] = offs;
60537 : }
60538 0 : subsolver->sparserawlc.matrixtype = 1;
60539 0 : subsolver->sparserawlc.ninitialized = subsolver->sparserawlc.ridx.ptr.p_int[nec+nic];
60540 0 : subsolver->sparserawlc.m = nec+nic;
60541 0 : subsolver->sparserawlc.n = n;
60542 0 : sparseinitduidx(&subsolver->sparserawlc, _state);
60543 0 : }
60544 :
60545 :
60546 : /*************************************************************************
60547 : Restarts LP subproblem (cleans the matrix of internally stored directions)
60548 :
60549 : INPUT PARAMETERS:
60550 : SState - solver state
60551 : Subsolver - SLP subproblem to initialize
60552 :
60553 : -- ALGLIB --
60554 : Copyright 05.03.2018 by Bochkanov Sergey
60555 : *************************************************************************/
60556 0 : static void nlcslp_lpsubproblemrestart(minslpstate* sstate,
60557 : minslpsubsolver* subsolver,
60558 : ae_state *_state)
60559 : {
60560 :
60561 :
60562 0 : subsolver->curdcnt = 0;
60563 0 : }
60564 :
60565 :
60566 : /*************************************************************************
60567 : Updates Hessian estimate
60568 :
60569 : INPUT PARAMETERS:
60570 : SState - solver state
60571 : Subsolver - SLP subproblem to initialize
60572 :
60573 :
60574 : -- ALGLIB --
60575 : Copyright 05.03.2018 by Bochkanov Sergey
60576 : *************************************************************************/
60577 0 : static void nlcslp_lpsubproblemupdatehessian(minslpstate* sstate,
60578 : minslpsubsolver* subsolver,
60579 : /* Real */ ae_vector* x0,
60580 : /* Real */ ae_vector* g0,
60581 : /* Real */ ae_vector* x1,
60582 : /* Real */ ae_vector* g1,
60583 : ae_state *_state)
60584 : {
60585 : ae_int_t i;
60586 : ae_int_t n;
60587 : double vv;
60588 : double v;
60589 : double v0;
60590 : double v1;
60591 : double v2;
60592 : double gk;
60593 : double sk;
60594 : double yk;
60595 :
60596 :
60597 0 : n = sstate->n;
60598 0 : if( subsolver->hessiantype==1||subsolver->hessiantype==2 )
60599 : {
60600 0 : rvectorsetlengthatleast(&subsolver->tmp0, n, _state);
60601 0 : v = (double)(0);
60602 0 : v0 = (double)(0);
60603 0 : v1 = (double)(0);
60604 0 : v2 = (double)(0);
60605 0 : for(i=0; i<=n-1; i++)
60606 : {
60607 0 : sk = x1->ptr.p_double[i]-x0->ptr.p_double[i];
60608 0 : yk = g1->ptr.p_double[i]-g0->ptr.p_double[i];
60609 0 : gk = g0->ptr.p_double[i];
60610 0 : v = v+sk*yk;
60611 0 : v0 = v0+sk*sk;
60612 0 : v1 = v1+yk*yk;
60613 0 : v2 = v2+gk*gk;
60614 0 : subsolver->sk.ptr.p_double[i] = sk;
60615 0 : subsolver->yk.ptr.p_double[i] = yk;
60616 : }
60617 0 : if( (ae_fp_greater(ae_sqrt(v0, _state),ae_maxreal(sstate->epsx, nlcslp_bfgstol, _state))&&ae_fp_greater(ae_sqrt(v1, _state),nlcslp_bfgstol*ae_sqrt(v2, _state)))&&ae_fp_greater(v,nlcslp_bfgstol*ae_sqrt(v0, _state)*ae_sqrt(v1, _state)) )
60618 : {
60619 :
60620 : /*
60621 : * Update Hessian if following criteria hold:
60622 : * * MCINFO=1 (good step)
60623 : * * step length is large enough
60624 : * * |Yk| is large enough when compared with |G|
60625 : * * (Sk,Yk) is large enough when compared with |S| and |G|
60626 : */
60627 0 : vv = rmatrixsyvmv(n, &subsolver->h, 0, 0, ae_true, &subsolver->sk, 0, &subsolver->tmp0, _state);
60628 0 : rmatrixgemv(n, n, 1.0, &subsolver->h, 0, 0, 0, &subsolver->sk, 0, 0.0, &subsolver->tmp0, 0, _state);
60629 0 : rmatrixger(n, n, &subsolver->h, 0, 0, 1/v, &subsolver->yk, 0, &subsolver->yk, 0, _state);
60630 0 : rmatrixger(n, n, &subsolver->h, 0, 0, -1/vv, &subsolver->tmp0, 0, &subsolver->tmp0, 0, _state);
60631 : }
60632 : }
60633 0 : }
60634 :
60635 :
60636 : /*************************************************************************
60637 : This function solves LP subproblem given by initial point X, function vector Fi
60638 : and Jacobian Jac, and returns estimates of Lagrangian multipliers and search direction D[].
60639 :
60640 : This function does NOT append search direction D to conjugacy constraints,
60641 : you have to use LPSubproblemAppendConjugacyConstraint().
60642 :
60643 : -- ALGLIB --
60644 : Copyright 05.03.2018 by Bochkanov Sergey
60645 : *************************************************************************/
60646 0 : static ae_bool nlcslp_lpsubproblemsolve(minslpstate* state,
60647 : minslpsubsolver* subsolver,
60648 : /* Real */ ae_vector* x,
60649 : /* Real */ ae_vector* fi,
60650 : /* Real */ ae_matrix* jac,
60651 : ae_int_t innerk,
60652 : /* Real */ ae_vector* d,
60653 : /* Real */ ae_vector* lagmult,
60654 : ae_state *_state)
60655 : {
60656 : ae_int_t n;
60657 : ae_int_t nslack;
60658 : ae_int_t nec;
60659 : ae_int_t nic;
60660 : ae_int_t nlec;
60661 : ae_int_t nlic;
60662 : ae_int_t i;
60663 : ae_int_t j;
60664 : ae_int_t k;
60665 : double v;
60666 : double vv;
60667 : double vright;
60668 : double vmax;
60669 : ae_int_t basisinittype;
60670 : ae_int_t lccnt;
60671 : ae_int_t offsslackec;
60672 : ae_int_t offsslacknlec;
60673 : ae_int_t offsslackic;
60674 : ae_int_t offsslacknlic;
60675 : ae_int_t offs;
60676 : ae_int_t nnz;
60677 : ae_int_t j0;
60678 : ae_int_t j1;
60679 : ae_bool result;
60680 :
60681 :
60682 0 : n = state->n;
60683 0 : nec = state->nec;
60684 0 : nic = state->nic;
60685 0 : nlec = state->nlec;
60686 0 : nlic = state->nlic;
60687 0 : nslack = n+2*(nec+nlec)+(nic+nlic);
60688 0 : lccnt = nec+nic+nlec+nlic;
60689 :
60690 : /*
60691 : * Locations of slack variables
60692 : */
60693 0 : offsslackec = n;
60694 0 : offsslacknlec = n+2*nec;
60695 0 : offsslackic = n+2*nec+2*nlec;
60696 0 : offsslacknlic = n+2*(nec+nlec)+nic;
60697 :
60698 : /*
60699 : * Prepare temporary structures
60700 : */
60701 0 : rvectorgrowto(&subsolver->cural, lccnt+subsolver->curdcnt, _state);
60702 0 : rvectorgrowto(&subsolver->curau, lccnt+subsolver->curdcnt, _state);
60703 :
60704 : /*
60705 : * Prepare default solution: all zeros
60706 : */
60707 0 : result = ae_true;
60708 0 : for(i=0; i<=nslack-1; i++)
60709 : {
60710 0 : d->ptr.p_double[i] = 0.0;
60711 : }
60712 0 : for(i=0; i<=lccnt-1; i++)
60713 : {
60714 0 : lagmult->ptr.p_double[i] = (double)(0);
60715 : }
60716 :
60717 : /*
60718 : * Linear term B
60719 : *
60720 : * NOTE: elements [N,NSlack) are equal to bigC + perturbation to improve numeric properties of LP problem
60721 : */
60722 0 : for(i=0; i<=n-1; i++)
60723 : {
60724 0 : subsolver->curb.ptr.p_double[i] = jac->ptr.pp_double[0][i];
60725 : }
60726 0 : v = (double)(0);
60727 0 : for(i=0; i<=n-1; i++)
60728 : {
60729 0 : v = v+ae_sqr(jac->ptr.pp_double[0][i], _state);
60730 : }
60731 0 : v = coalesce(ae_sqrt(v, _state), 1.0, _state);
60732 0 : for(i=n; i<=nslack-1; i++)
60733 : {
60734 0 : subsolver->curb.ptr.p_double[i] = (nlcslp_bigc+1.0/(1+i))*v;
60735 : }
60736 :
60737 : /*
60738 : * Trust radius constraints for primary variables
60739 : */
60740 0 : for(i=0; i<=n-1; i++)
60741 : {
60742 0 : subsolver->curbndl.ptr.p_double[i] = -state->trustrad;
60743 0 : subsolver->curbndu.ptr.p_double[i] = state->trustrad;
60744 0 : if( state->hasbndl.ptr.p_bool[i] )
60745 : {
60746 0 : subsolver->curbndl.ptr.p_double[i] = ae_maxreal(subsolver->curbndl.ptr.p_double[i], state->scaledbndl.ptr.p_double[i]-x->ptr.p_double[i], _state);
60747 : }
60748 0 : if( state->hasbndu.ptr.p_bool[i] )
60749 : {
60750 0 : subsolver->curbndu.ptr.p_double[i] = ae_minreal(subsolver->curbndu.ptr.p_double[i], state->scaledbndu.ptr.p_double[i]-x->ptr.p_double[i], _state);
60751 : }
60752 : }
60753 :
60754 : /*
60755 : * Prepare storage for "effective" constraining matrix
60756 : */
60757 0 : nnz = subsolver->sparserawlc.ridx.ptr.p_int[nec+nic];
60758 0 : for(i=0; i<=nlec+nlic-1; i++)
60759 : {
60760 0 : for(j=0; j<=n-1; j++)
60761 : {
60762 0 : if( jac->ptr.pp_double[1+i][j]!=0.0 )
60763 : {
60764 0 : nnz = nnz+1;
60765 : }
60766 : }
60767 : }
60768 0 : nnz = nnz+2*nec+nic;
60769 0 : nnz = nnz+2*nlec+nlic;
60770 0 : nnz = nnz+subsolver->curdcnt*n;
60771 0 : ivectorgrowto(&subsolver->sparseefflc.ridx, lccnt+n+1, _state);
60772 0 : rvectorgrowto(&subsolver->sparseefflc.vals, nnz, _state);
60773 0 : ivectorgrowto(&subsolver->sparseefflc.idx, nnz, _state);
60774 0 : ivectorsetlengthatleast(&subsolver->sparseefflc.didx, lccnt+n, _state);
60775 0 : ivectorsetlengthatleast(&subsolver->sparseefflc.uidx, lccnt+n, _state);
60776 0 : subsolver->sparseefflc.m = 0;
60777 0 : subsolver->sparseefflc.n = nslack;
60778 0 : subsolver->sparseefflc.matrixtype = 1;
60779 :
60780 : /*
60781 : * Append linear equality/inequality constraints
60782 : *
60783 : * Scan sparsified linear constraints stored in sparserawlc[], skip ones
60784 : * which are inactive anywhere in the trust region.
60785 : */
60786 0 : rvectorsetlengthatleast(&subsolver->tmp0, nslack, _state);
60787 0 : for(i=0; i<=n-1; i++)
60788 : {
60789 0 : subsolver->tmp0.ptr.p_double[i] = x->ptr.p_double[i];
60790 : }
60791 0 : for(i=n; i<=nslack-1; i++)
60792 : {
60793 0 : subsolver->tmp0.ptr.p_double[i] = (double)(0);
60794 : }
60795 0 : for(i=0; i<=nec+nic-1; i++)
60796 : {
60797 :
60798 : /*
60799 : * Calculate:
60800 : * * VRight - product of X[] (extended with zeros up to NSlack elements)
60801 : * and AR[i] - Ith row of sparserawlc matrix.
60802 : * * VMax - maximum value of X*ARi computed over trust region
60803 : */
60804 0 : vright = (double)(0);
60805 0 : vmax = (double)(0);
60806 0 : j0 = subsolver->sparserawlc.ridx.ptr.p_int[i];
60807 0 : j1 = subsolver->sparserawlc.ridx.ptr.p_int[i+1]-1;
60808 0 : for(k=j0; k<=j1; k++)
60809 : {
60810 0 : j = subsolver->sparserawlc.idx.ptr.p_int[k];
60811 0 : v = subsolver->tmp0.ptr.p_double[j];
60812 0 : vv = subsolver->sparserawlc.vals.ptr.p_double[k];
60813 0 : vright = vright+vv*v;
60814 0 : if( vv>=0 )
60815 : {
60816 0 : vmax = vmax+vv*(v+subsolver->curbndu.ptr.p_double[j]);
60817 : }
60818 : else
60819 : {
60820 0 : vmax = vmax+vv*(v+subsolver->curbndl.ptr.p_double[j]);
60821 : }
60822 : }
60823 :
60824 : /*
60825 : * If constraint is an inequality one and guaranteed to be inactive
60826 : * within trust region, it is skipped (row itself is retained but
60827 : * filled by zeros).
60828 : */
60829 0 : if( i>=nec&&vmax<=state->scaledcleic.ptr.pp_double[i][n] )
60830 : {
60831 0 : offs = subsolver->sparseefflc.ridx.ptr.p_int[i];
60832 0 : subsolver->sparseefflc.vals.ptr.p_double[offs] = (double)(-1);
60833 0 : subsolver->sparseefflc.idx.ptr.p_int[offs] = offsslackic+(i-nec);
60834 0 : subsolver->sparseefflc.ridx.ptr.p_int[i+1] = offs+1;
60835 0 : subsolver->cural.ptr.p_double[i] = 0.0;
60836 0 : subsolver->curau.ptr.p_double[i] = 0.0;
60837 0 : subsolver->curbndl.ptr.p_double[offsslackic+(i-nec)] = (double)(0);
60838 0 : subsolver->curbndu.ptr.p_double[offsslackic+(i-nec)] = (double)(0);
60839 0 : continue;
60840 : }
60841 :
60842 : /*
60843 : * Start working on row I
60844 : */
60845 0 : offs = subsolver->sparseefflc.ridx.ptr.p_int[i];
60846 :
60847 : /*
60848 : * Copy constraint from sparserawlc[] to sparseefflc[]
60849 : */
60850 0 : j0 = subsolver->sparserawlc.ridx.ptr.p_int[i];
60851 0 : j1 = subsolver->sparserawlc.ridx.ptr.p_int[i+1]-1;
60852 0 : for(k=j0; k<=j1; k++)
60853 : {
60854 0 : subsolver->sparseefflc.idx.ptr.p_int[offs] = subsolver->sparserawlc.idx.ptr.p_int[k];
60855 0 : subsolver->sparseefflc.vals.ptr.p_double[offs] = subsolver->sparserawlc.vals.ptr.p_double[k];
60856 0 : offs = offs+1;
60857 : }
60858 :
60859 : /*
60860 : * Set up slack variables
60861 : */
60862 0 : if( i<nec )
60863 : {
60864 0 : subsolver->sparseefflc.vals.ptr.p_double[offs+0] = (double)(-1);
60865 0 : subsolver->sparseefflc.vals.ptr.p_double[offs+1] = (double)(1);
60866 0 : subsolver->sparseefflc.idx.ptr.p_int[offs+0] = offsslackec+2*i+0;
60867 0 : subsolver->sparseefflc.idx.ptr.p_int[offs+1] = offsslackec+2*i+1;
60868 0 : offs = offs+2;
60869 : }
60870 : else
60871 : {
60872 :
60873 : /*
60874 : * Slack variables for inequality constraints
60875 : */
60876 0 : subsolver->sparseefflc.vals.ptr.p_double[offs] = (double)(-1);
60877 0 : subsolver->sparseefflc.idx.ptr.p_int[offs] = offsslackic+(i-nec);
60878 0 : offs = offs+1;
60879 : }
60880 :
60881 : /*
60882 : * Finalize row
60883 : */
60884 0 : subsolver->sparseefflc.ridx.ptr.p_int[i+1] = offs;
60885 :
60886 : /*
60887 : * Set up bounds.
60888 : *
60889 : * NOTE: bounds for equality and inequality constraints are
60890 : * handled differently
60891 : */
60892 0 : v = vright-state->scaledcleic.ptr.pp_double[i][n];
60893 0 : if( i<nec )
60894 : {
60895 0 : subsolver->cural.ptr.p_double[i] = -v;
60896 0 : subsolver->curau.ptr.p_double[i] = -v;
60897 0 : subsolver->curbndl.ptr.p_double[offsslackec+2*i+0] = (double)(0);
60898 0 : subsolver->curbndl.ptr.p_double[offsslackec+2*i+1] = (double)(0);
60899 0 : subsolver->curbndu.ptr.p_double[offsslackec+2*i+0] = ae_fabs(v, _state);
60900 0 : subsolver->curbndu.ptr.p_double[offsslackec+2*i+1] = ae_fabs(v, _state);
60901 : }
60902 : else
60903 : {
60904 0 : subsolver->cural.ptr.p_double[i] = _state->v_neginf;
60905 0 : subsolver->curau.ptr.p_double[i] = -v;
60906 0 : subsolver->curbndl.ptr.p_double[offsslackic+(i-nec)] = (double)(0);
60907 0 : subsolver->curbndu.ptr.p_double[offsslackic+(i-nec)] = ae_maxreal(v, (double)(0), _state);
60908 : }
60909 : }
60910 0 : subsolver->sparseefflc.m = subsolver->sparseefflc.m+(nec+nic);
60911 :
60912 : /*
60913 : * Append nonlinear equality/inequality constraints
60914 : */
60915 0 : for(i=0; i<=nlec+nlic-1; i++)
60916 : {
60917 :
60918 : /*
60919 : * Calculate scale coefficient
60920 : */
60921 0 : vv = (double)(0);
60922 0 : for(j=0; j<=n-1; j++)
60923 : {
60924 0 : v = jac->ptr.pp_double[1+i][j];
60925 0 : vv = vv+v*v;
60926 : }
60927 0 : vv = 1/coalesce(ae_sqrt(vv, _state), (double)(1), _state);
60928 :
60929 : /*
60930 : * Copy scaled row
60931 : */
60932 0 : offs = subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m+i];
60933 0 : for(j=0; j<=n-1; j++)
60934 : {
60935 0 : if( jac->ptr.pp_double[1+i][j]!=0.0 )
60936 : {
60937 0 : subsolver->sparseefflc.vals.ptr.p_double[offs] = vv*jac->ptr.pp_double[1+i][j];
60938 0 : subsolver->sparseefflc.idx.ptr.p_int[offs] = j;
60939 0 : offs = offs+1;
60940 : }
60941 : }
60942 0 : if( i<nlec )
60943 : {
60944 :
60945 : /*
60946 : * Add slack terms for equality constraints
60947 : */
60948 0 : subsolver->sparseefflc.vals.ptr.p_double[offs+0] = (double)(-1);
60949 0 : subsolver->sparseefflc.vals.ptr.p_double[offs+1] = (double)(1);
60950 0 : subsolver->sparseefflc.idx.ptr.p_int[offs+0] = offsslacknlec+2*i+0;
60951 0 : subsolver->sparseefflc.idx.ptr.p_int[offs+1] = offsslacknlec+2*i+1;
60952 0 : offs = offs+2;
60953 : }
60954 : else
60955 : {
60956 :
60957 : /*
60958 : * Add slack terms for inequality constraints
60959 : */
60960 0 : subsolver->sparseefflc.vals.ptr.p_double[offs] = (double)(-1);
60961 0 : subsolver->sparseefflc.idx.ptr.p_int[offs] = offsslacknlic+(i-nlec);
60962 0 : offs = offs+1;
60963 : }
60964 0 : subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m+i+1] = offs;
60965 :
60966 : /*
60967 : * Set box constraints on slack variables and bounds on linear equality/inequality constraints
60968 : */
60969 0 : v = vv*fi->ptr.p_double[1+i];
60970 0 : if( i<nlec )
60971 : {
60972 :
60973 : /*
60974 : * Equality constraint
60975 : */
60976 0 : subsolver->cural.ptr.p_double[subsolver->sparseefflc.m+i] = -v;
60977 0 : subsolver->curau.ptr.p_double[subsolver->sparseefflc.m+i] = -v;
60978 0 : subsolver->curbndl.ptr.p_double[offsslacknlec+2*i+0] = (double)(0);
60979 0 : subsolver->curbndl.ptr.p_double[offsslacknlec+2*i+1] = (double)(0);
60980 0 : subsolver->curbndu.ptr.p_double[offsslacknlec+2*i+0] = ae_fabs(v, _state);
60981 0 : subsolver->curbndu.ptr.p_double[offsslacknlec+2*i+1] = ae_fabs(v, _state);
60982 : }
60983 : else
60984 : {
60985 :
60986 : /*
60987 : * Inequality constraint
60988 : */
60989 0 : subsolver->cural.ptr.p_double[subsolver->sparseefflc.m+i] = _state->v_neginf;
60990 0 : subsolver->curau.ptr.p_double[subsolver->sparseefflc.m+i] = -v;
60991 0 : subsolver->curbndl.ptr.p_double[offsslacknlic+(i-nlec)] = (double)(0);
60992 0 : subsolver->curbndu.ptr.p_double[offsslacknlic+(i-nlec)] = ae_maxreal(v, (double)(0), _state);
60993 : }
60994 : }
60995 0 : subsolver->sparseefflc.m = subsolver->sparseefflc.m+(nlec+nlic);
60996 :
60997 : /*
60998 : * Append conjugacy constraints
60999 : */
61000 0 : for(i=0; i<=subsolver->curdcnt-1; i++)
61001 : {
61002 :
61003 : /*
61004 : * Copy N elements of CurHD
61005 : *
61006 : * NOTE: we expect product of D and H to be dense, so we copy all N elements
61007 : */
61008 0 : v = (double)(0);
61009 0 : for(j=0; j<=n-1; j++)
61010 : {
61011 0 : vv = subsolver->curhd.ptr.pp_double[i][j];
61012 0 : v = v+vv*vv;
61013 : }
61014 0 : v = 1.0/coalesce(ae_sqrt(v, _state), 1.0, _state);
61015 0 : offs = subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m];
61016 0 : for(j=0; j<=n-1; j++)
61017 : {
61018 0 : vv = subsolver->curhd.ptr.pp_double[i][j];
61019 0 : subsolver->sparseefflc.vals.ptr.p_double[offs] = v*vv;
61020 0 : subsolver->sparseefflc.idx.ptr.p_int[offs] = j;
61021 0 : offs = offs+1;
61022 : }
61023 0 : subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m+1] = offs;
61024 :
61025 : /*
61026 : * Set bounds on linear constraints
61027 : */
61028 0 : subsolver->cural.ptr.p_double[subsolver->sparseefflc.m] = (double)(0);
61029 0 : subsolver->curau.ptr.p_double[subsolver->sparseefflc.m] = (double)(0);
61030 :
61031 : /*
61032 : * Increase row count
61033 : */
61034 0 : subsolver->sparseefflc.m = subsolver->sparseefflc.m+1;
61035 : }
61036 :
61037 : /*
61038 : * Finalize sparse matrix structure
61039 : */
61040 0 : ae_assert(subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m]<=subsolver->sparseefflc.idx.cnt, "LPSubproblemSolve: critical integrity check failed", _state);
61041 0 : ae_assert(subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m]<=subsolver->sparseefflc.vals.cnt, "LPSubproblemSolve: critical integrity check failed", _state);
61042 0 : subsolver->sparseefflc.ninitialized = subsolver->sparseefflc.ridx.ptr.p_int[subsolver->sparseefflc.m];
61043 0 : sparseinitduidx(&subsolver->sparseefflc, _state);
61044 :
61045 : /*
61046 : * Choose dual simplex method basis initialization type
61047 : */
61048 0 : if( innerk==1&&subsolver->basispresent )
61049 : {
61050 0 : basisinittype = 2;
61051 : }
61052 : else
61053 : {
61054 0 : basisinittype = 1;
61055 : }
61056 :
61057 : /*
61058 : * Solve linear program
61059 : */
61060 0 : rvectorsetlengthatleast(&subsolver->tmp0, nslack, _state);
61061 0 : for(i=0; i<=nslack-1; i++)
61062 : {
61063 0 : subsolver->tmp0.ptr.p_double[i] = state->trustrad;
61064 : }
61065 0 : presolvenonescaleuser(&subsolver->tmp0, &subsolver->curb, &subsolver->curbndl, &subsolver->curbndu, nslack, &subsolver->sparseefflc, &subsolver->cural, &subsolver->curau, subsolver->sparseefflc.m, &subsolver->presolver, _state);
61066 0 : dssinit(subsolver->presolver.newn, &subsolver->dss, _state);
61067 0 : dsssetproblem(&subsolver->dss, &subsolver->presolver.c, &subsolver->presolver.bndl, &subsolver->presolver.bndu, &subsolver->densedummy, &subsolver->presolver.sparsea, 1, &subsolver->presolver.al, &subsolver->presolver.au, subsolver->presolver.newm, &subsolver->lastbasis, basisinittype, &subsolver->dsssettings, _state);
61068 0 : dssoptimize(&subsolver->dss, &subsolver->dsssettings, _state);
61069 0 : rcopyallocv(subsolver->presolver.newn, &subsolver->dss.repx, &subsolver->xs, _state);
61070 0 : rcopyallocv(subsolver->presolver.newn, &subsolver->dss.replagbc, &subsolver->lagbc, _state);
61071 0 : rcopyallocv(subsolver->presolver.newm, &subsolver->dss.replaglc, &subsolver->laglc, _state);
61072 0 : icopyallocv(subsolver->presolver.newn+subsolver->presolver.newm, &subsolver->dss.repstats, &subsolver->cs, _state);
61073 0 : presolvebwd(&subsolver->presolver, &subsolver->xs, &subsolver->cs, &subsolver->lagbc, &subsolver->laglc, _state);
61074 0 : state->repsimplexiterations = state->repsimplexiterations+subsolver->dss.repiterationscount;
61075 0 : state->repsimplexiterations1 = state->repsimplexiterations1+subsolver->dss.repiterationscount1;
61076 0 : state->repsimplexiterations2 = state->repsimplexiterations2+subsolver->dss.repiterationscount2;
61077 0 : state->repsimplexiterations3 = state->repsimplexiterations3+subsolver->dss.repiterationscount3;
61078 0 : if( subsolver->dss.repterminationtype<=0 )
61079 : {
61080 :
61081 : /*
61082 : * LP solver failed due to numerical errors; exit
61083 : */
61084 0 : result = ae_false;
61085 0 : return result;
61086 : }
61087 0 : if( innerk==1 )
61088 : {
61089 :
61090 : /*
61091 : * Store basis
61092 : */
61093 0 : dssexportbasis(&subsolver->dss, &subsolver->lastbasis, _state);
61094 0 : subsolver->basispresent = ae_true;
61095 : }
61096 :
61097 : /*
61098 : * Extract direction D[] and Lagrange multipliers
61099 : */
61100 0 : for(i=0; i<=nslack-1; i++)
61101 : {
61102 0 : d->ptr.p_double[i] = subsolver->xs.ptr.p_double[i];
61103 : }
61104 0 : for(i=0; i<=lccnt-1; i++)
61105 : {
61106 0 : lagmult->ptr.p_double[i] = subsolver->laglc.ptr.p_double[i];
61107 : }
61108 0 : return result;
61109 : }
61110 :
61111 :
61112 : /*************************************************************************
61113 : This function appends last search direction D to conjugacy constraints of
61114 : the LP subproblem.
61115 :
61116 : -- ALGLIB --
61117 : Copyright 05.03.2018 by Bochkanov Sergey
61118 : *************************************************************************/
61119 0 : static void nlcslp_lpsubproblemappendconjugacyconstraint(minslpstate* state,
61120 : minslpsubsolver* subsolver,
61121 : /* Real */ ae_vector* d,
61122 : ae_state *_state)
61123 : {
61124 : ae_int_t n;
61125 : ae_int_t i;
61126 : ae_int_t j;
61127 :
61128 :
61129 0 : n = state->n;
61130 :
61131 : /*
61132 : * Update matrix of products H*Dprev
61133 : */
61134 0 : ae_assert(subsolver->curdcnt<subsolver->curd.rows, "SLP: CurD is too small", _state);
61135 0 : for(i=0; i<=n-1; i++)
61136 : {
61137 :
61138 : /*
61139 : * Store direction and default conjugacy constraint d'*I*Dprev=0
61140 : */
61141 0 : subsolver->curd.ptr.pp_double[subsolver->curdcnt][i] = d->ptr.p_double[i];
61142 0 : subsolver->curhd.ptr.pp_double[subsolver->curdcnt][i] = d->ptr.p_double[i];
61143 : }
61144 0 : inc(&subsolver->curdcnt, _state);
61145 0 : if( state->hessiantype==1 )
61146 : {
61147 :
61148 : /*
61149 : * Conjugacy constraint d*H*Dprev=0, full recomputation of (H*Dprev)
61150 : */
61151 0 : rmatrixgemm(subsolver->curdcnt, n, n, 1.0, &subsolver->curd, 0, 0, 0, &subsolver->h, 0, 0, 0, 0.0, &subsolver->curhd, 0, 0, _state);
61152 : }
61153 0 : if( state->hessiantype==2 )
61154 : {
61155 :
61156 : /*
61157 : * Conjugacy constraint d*H*Dprev=0, only last row of (H*Dprev) is recomputed
61158 : */
61159 0 : rvectorsetlengthatleast(&subsolver->tmp0, n, _state);
61160 0 : rmatrixgemv(n, n, 1.0, &subsolver->h, 0, 0, 0, d, 0, 0.0, &subsolver->tmp0, 0, _state);
61161 0 : for(j=0; j<=n-1; j++)
61162 : {
61163 0 : subsolver->curhd.ptr.pp_double[subsolver->curdcnt-1][j] = subsolver->tmp0.ptr.p_double[j];
61164 : }
61165 : }
61166 0 : }
61167 :
61168 :
61169 : /*************************************************************************
61170 : This function initializes Phase13 temporaries. It should be called before
61171 : beginning of each new iteration. You may call it multiple times for the
61172 : same instance of Phase13 temporaries.
61173 :
61174 : INPUT PARAMETERS:
61175 : State13 - instance to be initialized.
61176 : N - problem dimensionality
61177 : NEC, NIC - linear equality/inequality constraint count
61178 : NLEC, NLIC - nonlinear equality/inequality constraint count
61179 : UseCorrection - True if we want to perform second order correction
61180 :
61181 : OUTPUT PARAMETERS:
61182 : State13 - instance being initialized
61183 :
61184 : -- ALGLIB --
61185 : Copyright 05.02.2019 by Bochkanov Sergey
61186 : *************************************************************************/
61187 0 : static void nlcslp_phase13init(minslpphase13state* state13,
61188 : ae_int_t n,
61189 : ae_int_t nec,
61190 : ae_int_t nic,
61191 : ae_int_t nlec,
61192 : ae_int_t nlic,
61193 : ae_bool usecorrection,
61194 : ae_state *_state)
61195 : {
61196 : ae_int_t nslack;
61197 :
61198 :
61199 0 : nslack = n+2*(nec+nlec)+(nic+nlic);
61200 0 : state13->usecorrection = usecorrection;
61201 0 : rvectorsetlengthatleast(&state13->d, nslack, _state);
61202 0 : rvectorsetlengthatleast(&state13->dx, nslack, _state);
61203 0 : rvectorsetlengthatleast(&state13->stepkxc, n, _state);
61204 0 : rvectorsetlengthatleast(&state13->stepkxn, n, _state);
61205 0 : rvectorsetlengthatleast(&state13->stepkfic, 1+nlec+nlic, _state);
61206 0 : rvectorsetlengthatleast(&state13->stepkfin, 1+nlec+nlic, _state);
61207 0 : rmatrixsetlengthatleast(&state13->stepkjc, 1+nlec+nlic, n, _state);
61208 0 : rmatrixsetlengthatleast(&state13->stepkjn, 1+nlec+nlic, n, _state);
61209 0 : rvectorsetlengthatleast(&state13->dummylagmult, nec+nic+nlec+nlic, _state);
61210 0 : ae_vector_set_length(&state13->rphase13state.ia, 8+1, _state);
61211 0 : ae_vector_set_length(&state13->rphase13state.ba, 2+1, _state);
61212 0 : ae_vector_set_length(&state13->rphase13state.ra, 5+1, _state);
61213 0 : state13->rphase13state.stage = -1;
61214 0 : }
61215 :
61216 :
61217 : /*************************************************************************
61218 : This function tries to perform either phase #1 or phase #3 step.
61219 :
61220 : Former corresponds to linear model step (without conjugacy constraints) with
61221 : correction for nonlinearity ("second order correction"). Such correction
61222 : helps to overcome Maratos effect (a tendency of L1 penalized merit
61223 : functions to reject nonzero steps).
61224 :
61225 : Latter is a step using linear model with no second order correction.
61226 :
61227 : INPUT PARAMETERS:
61228 : State - SLP solver state
61229 : SMonitor - smoothness monitor
61230 : UserTerminationNeeded-True if user requested termination
61231 : CurX - current point, array[N]
61232 : CurFi - function vector at CurX, array[1+NLEC+NLIC]
61233 : CurJ - Jacobian at CurX, array[1+NLEC+NLIC,N]
61234 : LagMult - array[NEC+NIC+NLEC+NLIC], contents ignored on input.
61235 :
61236 : OUTPUT PARAMETERS:
61237 : State - RepTerminationType is set to current termination code (if Status=0).
61238 : CurX - advanced to new point
61239 : CurFi - updated with function vector at CurX[]
61240 : CurJ - updated with Jacobian at CurX[]
61241 : LagMult - filled with current Lagrange multipliers
61242 : Status - when reverse communication is done, Status is set to:
61243 : * negative value, if we have to restart outer
61244 : iteration
61245 : * positive value, if we can proceed to the next stage
61246 : of the outer iteration
61247 : * zero, if algorithm is terminated (RepTerminationType
61248 : is set to appropriate value)
61249 : Stp - step length, in [0,1]
61250 :
61251 : -- ALGLIB --
61252 : Copyright 05.02.2019 by Bochkanov Sergey
61253 : *************************************************************************/
61254 0 : static ae_bool nlcslp_phase13iteration(minslpstate* state,
61255 : minslpphase13state* state13,
61256 : smoothnessmonitor* smonitor,
61257 : ae_bool userterminationneeded,
61258 : /* Real */ ae_vector* curx,
61259 : /* Real */ ae_vector* curfi,
61260 : /* Real */ ae_matrix* curj,
61261 : /* Real */ ae_vector* lagmult,
61262 : ae_int_t* status,
61263 : double* stp,
61264 : ae_state *_state)
61265 : {
61266 : ae_int_t n;
61267 : ae_int_t nslack;
61268 : ae_int_t nec;
61269 : ae_int_t nic;
61270 : ae_int_t nlec;
61271 : ae_int_t nlic;
61272 : ae_int_t innerk;
61273 : ae_int_t i;
61274 : ae_int_t j;
61275 : double v;
61276 : double mx;
61277 : double f0;
61278 : double f1;
61279 : double nu;
61280 : double localstp;
61281 : ae_bool dotrace;
61282 : ae_bool doprobing;
61283 : ae_bool dotracexd;
61284 : ae_bool result;
61285 :
61286 :
61287 :
61288 : /*
61289 : * Reverse communication preparations
61290 : * I know it looks ugly, but it works the same way
61291 : * anywhere from C++ to Python.
61292 : *
61293 : * This code initializes locals by:
61294 : * * random values determined during code
61295 : * generation - on first subroutine call
61296 : * * values from previous call - on subsequent calls
61297 : */
61298 0 : if( state13->rphase13state.stage>=0 )
61299 : {
61300 0 : n = state13->rphase13state.ia.ptr.p_int[0];
61301 0 : nslack = state13->rphase13state.ia.ptr.p_int[1];
61302 0 : nec = state13->rphase13state.ia.ptr.p_int[2];
61303 0 : nic = state13->rphase13state.ia.ptr.p_int[3];
61304 0 : nlec = state13->rphase13state.ia.ptr.p_int[4];
61305 0 : nlic = state13->rphase13state.ia.ptr.p_int[5];
61306 0 : innerk = state13->rphase13state.ia.ptr.p_int[6];
61307 0 : i = state13->rphase13state.ia.ptr.p_int[7];
61308 0 : j = state13->rphase13state.ia.ptr.p_int[8];
61309 0 : dotrace = state13->rphase13state.ba.ptr.p_bool[0];
61310 0 : doprobing = state13->rphase13state.ba.ptr.p_bool[1];
61311 0 : dotracexd = state13->rphase13state.ba.ptr.p_bool[2];
61312 0 : v = state13->rphase13state.ra.ptr.p_double[0];
61313 0 : mx = state13->rphase13state.ra.ptr.p_double[1];
61314 0 : f0 = state13->rphase13state.ra.ptr.p_double[2];
61315 0 : f1 = state13->rphase13state.ra.ptr.p_double[3];
61316 0 : nu = state13->rphase13state.ra.ptr.p_double[4];
61317 0 : localstp = state13->rphase13state.ra.ptr.p_double[5];
61318 : }
61319 : else
61320 : {
61321 0 : n = 886;
61322 0 : nslack = 346;
61323 0 : nec = -722;
61324 0 : nic = -413;
61325 0 : nlec = -461;
61326 0 : nlic = 927;
61327 0 : innerk = 201;
61328 0 : i = 922;
61329 0 : j = -154;
61330 0 : dotrace = ae_false;
61331 0 : doprobing = ae_true;
61332 0 : dotracexd = ae_true;
61333 0 : v = -463;
61334 0 : mx = 88;
61335 0 : f0 = -861;
61336 0 : f1 = -678;
61337 0 : nu = -731;
61338 0 : localstp = -675;
61339 : }
61340 0 : if( state13->rphase13state.stage==0 )
61341 : {
61342 0 : goto lbl_0;
61343 : }
61344 0 : if( state13->rphase13state.stage==1 )
61345 : {
61346 0 : goto lbl_1;
61347 : }
61348 0 : if( state13->rphase13state.stage==2 )
61349 : {
61350 0 : goto lbl_2;
61351 : }
61352 0 : if( state13->rphase13state.stage==3 )
61353 : {
61354 0 : goto lbl_3;
61355 : }
61356 :
61357 : /*
61358 : * Routine body
61359 : */
61360 0 : n = state->n;
61361 0 : nec = state->nec;
61362 0 : nic = state->nic;
61363 0 : nlec = state->nlec;
61364 0 : nlic = state->nlic;
61365 0 : nslack = n+2*(nec+nlec)+(nic+nlic);
61366 0 : innerk = 1;
61367 0 : dotrace = ae_is_trace_enabled("SLP");
61368 0 : dotracexd = dotrace&&ae_is_trace_enabled("SLP.DETAILED");
61369 0 : doprobing = ae_is_trace_enabled("SLP.PROBING");
61370 0 : ae_assert(lagmult->cnt>=nec+nic+nlec+nlic, "Phase13Iteration: integrity check failed", _state);
61371 :
61372 : /*
61373 : * Report iteration beginning
61374 : */
61375 0 : if( dotrace )
61376 : {
61377 0 : if( state13->usecorrection )
61378 : {
61379 0 : ae_trace("\n--- linear step with second-order correction -------------------------------------------------------\n");
61380 : }
61381 : else
61382 : {
61383 0 : ae_trace("\n--- linear step without second-order correction ----------------------------------------------------\n");
61384 : }
61385 : }
61386 :
61387 : /*
61388 : * Default decision is to continue algorithm
61389 : */
61390 0 : *status = 1;
61391 0 : *stp = (double)(0);
61392 :
61393 : /*
61394 : * Determine step direction using linearized model with no conjugacy terms
61395 : */
61396 0 : nlcslp_lpsubproblemrestart(state, &state->subsolver, _state);
61397 0 : if( !nlcslp_lpsubproblemsolve(state, &state->subsolver, curx, curfi, curj, innerk, &state13->d, lagmult, _state) )
61398 : {
61399 0 : if( dotrace )
61400 : {
61401 0 : ae_trace("> [WARNING] initial phase #1 LP subproblem failed\n");
61402 : }
61403 :
61404 : /*
61405 : * Increase failures counter.
61406 : * Stop after too many subsequent failures
61407 : */
61408 0 : inc(&state->lpfailurecnt, _state);
61409 0 : if( state->lpfailurecnt>=nlcslp_lpfailureslimit )
61410 : {
61411 0 : state->repterminationtype = 7;
61412 0 : *status = 0;
61413 0 : if( dotrace )
61414 : {
61415 0 : ae_trace("> stopping condition met: too many phase #1 LP failures\n");
61416 : }
61417 0 : result = ae_false;
61418 0 : return result;
61419 : }
61420 :
61421 : /*
61422 : * Can not solve LP subproblem, decrease trust radius
61423 : */
61424 0 : state->trustrad = 0.5*state->trustrad;
61425 0 : if( dotrace )
61426 : {
61427 0 : ae_trace("> trust radius was decreased to %0.4e\n",
61428 0 : (double)(state->trustrad));
61429 : }
61430 0 : if( ae_fp_less(state->trustrad,state->epsx) )
61431 : {
61432 0 : state->repterminationtype = 2;
61433 0 : *status = 0;
61434 0 : if( dotrace )
61435 : {
61436 0 : ae_trace("> stopping condition met: trust radius is smaller than %0.3e\n",
61437 0 : (double)(state->epsx));
61438 : }
61439 : }
61440 : else
61441 : {
61442 0 : *status = -1;
61443 : }
61444 0 : result = ae_false;
61445 0 : return result;
61446 : }
61447 0 : nlcslp_lpsubproblemappendconjugacyconstraint(state, &state->subsolver, &state13->d, _state);
61448 :
61449 : /*
61450 : * Compute second order correction if required. The issue we address here
61451 : * is a tendency of L1 penalized function to reject steps built using simple
61452 : * linearized model when nonlinear constraints change faster than the target.
61453 : *
61454 : * The idea is that we perform trial step (stp=1) using simple linearized model,
61455 : * compute constraint vector at the new trial point - and use these updated
61456 : * constraint linearizations back at the initial point.
61457 : */
61458 0 : if( !state13->usecorrection )
61459 : {
61460 0 : goto lbl_4;
61461 : }
61462 :
61463 : /*
61464 : * Perform trial step using vector D to StepKXC
61465 : */
61466 0 : for(i=0; i<=n-1; i++)
61467 : {
61468 0 : state13->stepkxc.ptr.p_double[i] = curx->ptr.p_double[i]+state13->d.ptr.p_double[i];
61469 : }
61470 0 : nlcslp_slpsendx(state, &state13->stepkxc, _state);
61471 0 : state->needfij = ae_true;
61472 0 : state13->rphase13state.stage = 0;
61473 0 : goto lbl_rcomm;
61474 0 : lbl_0:
61475 0 : state->needfij = ae_false;
61476 0 : if( !nlcslp_slpretrievefij(state, &state13->stepkfic, &state13->stepkjc, _state) )
61477 : {
61478 :
61479 : /*
61480 : * Failed to retrieve func/Jac, infinities detected
61481 : */
61482 0 : state->repterminationtype = -8;
61483 0 : *status = 0;
61484 0 : if( dotrace )
61485 : {
61486 0 : ae_trace("[ERROR] infinities in target/constraints are detected\n");
61487 : }
61488 0 : result = ae_false;
61489 0 : return result;
61490 : }
61491 :
61492 : /*
61493 : * Move back to point CurX[], restore original linearization of the target
61494 : */
61495 0 : state13->stepkfic.ptr.p_double[0] = curfi->ptr.p_double[0];
61496 0 : for(j=0; j<=n-1; j++)
61497 : {
61498 0 : state13->stepkxc.ptr.p_double[j] = curx->ptr.p_double[j];
61499 0 : state13->stepkjc.ptr.pp_double[0][j] = curj->ptr.pp_double[0][j];
61500 : }
61501 :
61502 : /*
61503 : * Extrapolate linearization of nonlinear constraints back to origin
61504 : */
61505 0 : for(i=1; i<=nlec+nlic; i++)
61506 : {
61507 0 : v = (double)(0);
61508 0 : for(j=0; j<=n-1; j++)
61509 : {
61510 0 : v = v+state13->d.ptr.p_double[j]*state13->stepkjc.ptr.pp_double[i][j];
61511 : }
61512 0 : state13->stepkfic.ptr.p_double[i] = state13->stepkfic.ptr.p_double[i]-v;
61513 : }
61514 :
61515 : /*
61516 : * Solve linearized problem one more time, now with new linearization of constraints
61517 : * (but still old linearization of the target), obtain DX
61518 : *
61519 : * NOTE: because lpsubproblemrestart() call resets set of conjugate constraints, we
61520 : * have to re-add it after solve.
61521 : */
61522 0 : nlcslp_lpsubproblemrestart(state, &state->subsolver, _state);
61523 0 : if( !nlcslp_lpsubproblemsolve(state, &state->subsolver, &state13->stepkxc, &state13->stepkfic, &state13->stepkjc, innerk, &state13->dx, &state13->dummylagmult, _state) )
61524 : {
61525 :
61526 : /*
61527 : * Second LP subproblem failed.
61528 : * Noncritical failure, can be ignored,
61529 : */
61530 0 : if( dotrace )
61531 : {
61532 0 : ae_trace("> [WARNING] second phase #1 LP subproblem failed\n");
61533 : }
61534 0 : if( dotrace )
61535 : {
61536 0 : ae_trace("> using step without second order correction\n");
61537 : }
61538 : }
61539 : else
61540 : {
61541 :
61542 : /*
61543 : * Set D to new direction
61544 : */
61545 0 : for(i=0; i<=n-1; i++)
61546 : {
61547 0 : state13->d.ptr.p_double[i] = state13->dx.ptr.p_double[i];
61548 : }
61549 : }
61550 0 : nlcslp_lpsubproblemappendconjugacyconstraint(state, &state->subsolver, &state13->d, _state);
61551 0 : lbl_4:
61552 :
61553 : /*
61554 : * Perform merit function backtracking line search, with trial point being
61555 : * computed as XN = XK + Stp*D, with Stp in [0,1]
61556 : *
61557 : * NOTE: we use MeritLagMult - Lagrange multipliers computed for initial,
61558 : * uncorrected task - for the merit function model.
61559 : * Using DummyLagMult can destabilize algorithm.
61560 : */
61561 0 : localstp = 1.0;
61562 0 : nu = 0.5;
61563 0 : f0 = nlcslp_meritfunction(state, curx, curfi, lagmult, &state13->tmpmerit, _state);
61564 0 : f1 = f0;
61565 0 : smoothnessmonitorstartlinesearch(smonitor, curx, curfi, curj, _state);
61566 0 : lbl_6:
61567 : if( ae_false )
61568 : {
61569 : goto lbl_7;
61570 : }
61571 0 : for(i=0; i<=n-1; i++)
61572 : {
61573 0 : state13->stepkxn.ptr.p_double[i] = curx->ptr.p_double[i]+localstp*state13->d.ptr.p_double[i];
61574 : }
61575 0 : nlcslp_slpsendx(state, &state13->stepkxn, _state);
61576 0 : state->needfij = ae_true;
61577 0 : state13->rphase13state.stage = 1;
61578 0 : goto lbl_rcomm;
61579 0 : lbl_1:
61580 0 : state->needfij = ae_false;
61581 0 : if( !nlcslp_slpretrievefij(state, &state13->stepkfin, &state13->stepkjn, _state) )
61582 : {
61583 :
61584 : /*
61585 : * Failed to retrieve func/Jac, infinities detected
61586 : */
61587 0 : state->repterminationtype = -8;
61588 0 : *status = 0;
61589 0 : if( dotrace )
61590 : {
61591 0 : ae_trace("[ERROR] infinities in target/constraints are detected\n");
61592 : }
61593 0 : result = ae_false;
61594 0 : return result;
61595 : }
61596 0 : smoothnessmonitorenqueuepoint(smonitor, &state13->d, localstp, &state13->stepkxn, &state13->stepkfin, &state13->stepkjn, _state);
61597 0 : f1 = nlcslp_meritfunction(state, &state13->stepkxn, &state13->stepkfin, lagmult, &state13->tmpmerit, _state);
61598 0 : if( ae_fp_less(f1,f0) )
61599 : {
61600 :
61601 : /*
61602 : * Step is found!
61603 : */
61604 0 : goto lbl_7;
61605 : }
61606 0 : if( ae_fp_less(localstp,0.001) )
61607 : {
61608 :
61609 : /*
61610 : * Step is shorter than 0.001 times current search direction,
61611 : * it means that no good step can be found.
61612 : */
61613 0 : localstp = (double)(0);
61614 0 : nlcslp_slpcopystate(state, curx, curfi, curj, &state13->stepkxn, &state13->stepkfin, &state13->stepkjn, _state);
61615 0 : goto lbl_7;
61616 : }
61617 0 : localstp = nu*localstp;
61618 0 : nu = ae_maxreal(0.1, 0.5*nu, _state);
61619 0 : goto lbl_6;
61620 0 : lbl_7:
61621 0 : smoothnessmonitorfinalizelinesearch(smonitor, _state);
61622 0 : for(i=0; i<=n-1; i++)
61623 : {
61624 0 : if( state->hasbndl.ptr.p_bool[i] )
61625 : {
61626 0 : state13->stepkxn.ptr.p_double[i] = ae_maxreal(state13->stepkxn.ptr.p_double[i], state->scaledbndl.ptr.p_double[i], _state);
61627 : }
61628 0 : if( state->hasbndu.ptr.p_bool[i] )
61629 : {
61630 0 : state13->stepkxn.ptr.p_double[i] = ae_minreal(state13->stepkxn.ptr.p_double[i], state->scaledbndu.ptr.p_double[i], _state);
61631 : }
61632 : }
61633 0 : if( userterminationneeded )
61634 : {
61635 :
61636 : /*
61637 : * User requested termination, break before we move to new point
61638 : */
61639 0 : state->repterminationtype = 8;
61640 0 : *status = 0;
61641 0 : if( dotrace )
61642 : {
61643 0 : ae_trace("> user requested termination\n");
61644 : }
61645 0 : result = ae_false;
61646 0 : return result;
61647 : }
61648 :
61649 : /*
61650 : * Trace
61651 : */
61652 0 : if( !dotrace )
61653 : {
61654 0 : goto lbl_8;
61655 : }
61656 0 : if( !doprobing )
61657 : {
61658 0 : goto lbl_10;
61659 : }
61660 0 : smoothnessmonitorstartprobing(smonitor, 1.0, 2, state->trustrad, _state);
61661 0 : lbl_12:
61662 0 : if( !smoothnessmonitorprobe(smonitor, _state) )
61663 : {
61664 0 : goto lbl_13;
61665 : }
61666 0 : for(j=0; j<=n-1; j++)
61667 : {
61668 0 : state13->stepkxc.ptr.p_double[j] = curx->ptr.p_double[j]+smonitor->probingstp*state13->d.ptr.p_double[j];
61669 0 : if( state->hasbndl.ptr.p_bool[j] )
61670 : {
61671 0 : state13->stepkxc.ptr.p_double[j] = ae_maxreal(state13->stepkxc.ptr.p_double[j], state->scaledbndl.ptr.p_double[j], _state);
61672 : }
61673 0 : if( state->hasbndu.ptr.p_bool[j] )
61674 : {
61675 0 : state13->stepkxc.ptr.p_double[j] = ae_minreal(state13->stepkxc.ptr.p_double[j], state->scaledbndu.ptr.p_double[j], _state);
61676 : }
61677 : }
61678 0 : nlcslp_slpsendx(state, &state13->stepkxc, _state);
61679 0 : state->needfij = ae_true;
61680 0 : state13->rphase13state.stage = 2;
61681 0 : goto lbl_rcomm;
61682 0 : lbl_2:
61683 0 : state->needfij = ae_false;
61684 0 : if( !nlcslp_slpretrievefij(state, &state13->stepkfic, &state13->stepkjc, _state) )
61685 : {
61686 0 : goto lbl_13;
61687 : }
61688 0 : smonitor->probingf.ptr.p_double[0] = nlcslp_rawlagrangian(state, &state13->stepkxc, &state13->stepkfic, lagmult, &state13->tmpmerit, _state);
61689 0 : smonitor->probingf.ptr.p_double[1] = state13->stepkfic.ptr.p_double[0];
61690 0 : goto lbl_12;
61691 0 : lbl_13:
61692 0 : ae_trace("*** ------------------------------------------------------------\n");
61693 0 : ae_trace("*** | probing search direction suggested by LP subproblem |\n");
61694 0 : ae_trace("*** ------------------------------------------------------------\n");
61695 0 : ae_trace("*** | Step | Lagrangian (unaugmentd)| Target function |\n");
61696 0 : ae_trace("*** |along D| must be smooth | must be smooth |\n");
61697 0 : ae_trace("*** | | function | slope | function | slope |\n");
61698 0 : smoothnessmonitortraceprobingresults(smonitor, _state);
61699 0 : lbl_10:
61700 0 : mx = (double)(0);
61701 0 : for(i=0; i<=n-1; i++)
61702 : {
61703 0 : mx = ae_maxreal(mx, ae_fabs(state13->d.ptr.p_double[i], _state)/state->trustrad, _state);
61704 : }
61705 0 : if( ae_fp_greater(localstp,(double)(0)) )
61706 : {
61707 0 : ae_trace("> nonzero linear step was performed\n");
61708 : }
61709 : else
61710 : {
61711 0 : ae_trace("> zero linear step was performed\n");
61712 : }
61713 0 : ae_trace("max(|Di|)/TrustRad = %0.6f\n",
61714 : (double)(mx));
61715 0 : ae_trace("stp = %0.6f\n",
61716 : (double)(localstp));
61717 0 : if( dotracexd )
61718 : {
61719 0 : ae_trace("X0 (scaled) = ");
61720 0 : tracevectorautoprec(curx, 0, n, _state);
61721 0 : ae_trace("\n");
61722 0 : ae_trace("D (scaled) = ");
61723 0 : tracevectorautoprec(&state13->d, 0, n, _state);
61724 0 : ae_trace("\n");
61725 0 : ae_trace("X1 (scaled) = ");
61726 0 : tracevectorautoprec(&state13->stepkxn, 0, n, _state);
61727 0 : ae_trace("\n");
61728 : }
61729 0 : ae_trace("meritF: %14.6e -> %14.6e (delta=%11.3e)\n",
61730 : (double)(f0),
61731 : (double)(f1),
61732 : (double)(f1-f0));
61733 0 : ae_trace("scaled-targetF: %14.6e -> %14.6e (delta=%11.3e)\n",
61734 0 : (double)(curfi->ptr.p_double[0]),
61735 0 : (double)(state13->stepkfin.ptr.p_double[0]),
61736 0 : (double)(state13->stepkfin.ptr.p_double[0]-curfi->ptr.p_double[0]));
61737 0 : lbl_8:
61738 :
61739 : /*
61740 : * Move to new point
61741 : */
61742 0 : *stp = localstp;
61743 0 : nlcslp_slpcopystate(state, &state13->stepkxn, &state13->stepkfin, &state13->stepkjn, curx, curfi, curj, _state);
61744 0 : if( ae_fp_less_eq(localstp,(double)(0)) )
61745 : {
61746 0 : goto lbl_14;
61747 : }
61748 :
61749 : /*
61750 : * Report one more inner iteration
61751 : */
61752 0 : inc(&state->repinneriterationscount, _state);
61753 0 : nlcslp_slpsendx(state, curx, _state);
61754 0 : state->f = curfi->ptr.p_double[0]*state->fscales.ptr.p_double[0];
61755 0 : state->xupdated = ae_true;
61756 0 : state13->rphase13state.stage = 3;
61757 0 : goto lbl_rcomm;
61758 0 : lbl_3:
61759 0 : state->xupdated = ae_false;
61760 :
61761 : /*
61762 : * Update constraint violations
61763 : */
61764 0 : checklcviolation(&state->scaledcleic, &state->lcsrcidx, nec, nic, curx, n, &state->replcerr, &state->replcidx, _state);
61765 0 : unscaleandchecknlcviolation(curfi, &state->fscales, nlec, nlic, &state->repnlcerr, &state->repnlcidx, _state);
61766 0 : lbl_14:
61767 0 : result = ae_false;
61768 0 : return result;
61769 :
61770 : /*
61771 : * Saving state
61772 : */
61773 0 : lbl_rcomm:
61774 0 : result = ae_true;
61775 0 : state13->rphase13state.ia.ptr.p_int[0] = n;
61776 0 : state13->rphase13state.ia.ptr.p_int[1] = nslack;
61777 0 : state13->rphase13state.ia.ptr.p_int[2] = nec;
61778 0 : state13->rphase13state.ia.ptr.p_int[3] = nic;
61779 0 : state13->rphase13state.ia.ptr.p_int[4] = nlec;
61780 0 : state13->rphase13state.ia.ptr.p_int[5] = nlic;
61781 0 : state13->rphase13state.ia.ptr.p_int[6] = innerk;
61782 0 : state13->rphase13state.ia.ptr.p_int[7] = i;
61783 0 : state13->rphase13state.ia.ptr.p_int[8] = j;
61784 0 : state13->rphase13state.ba.ptr.p_bool[0] = dotrace;
61785 0 : state13->rphase13state.ba.ptr.p_bool[1] = doprobing;
61786 0 : state13->rphase13state.ba.ptr.p_bool[2] = dotracexd;
61787 0 : state13->rphase13state.ra.ptr.p_double[0] = v;
61788 0 : state13->rphase13state.ra.ptr.p_double[1] = mx;
61789 0 : state13->rphase13state.ra.ptr.p_double[2] = f0;
61790 0 : state13->rphase13state.ra.ptr.p_double[3] = f1;
61791 0 : state13->rphase13state.ra.ptr.p_double[4] = nu;
61792 0 : state13->rphase13state.ra.ptr.p_double[5] = localstp;
61793 0 : return result;
61794 : }
61795 :
61796 :
61797 : /*************************************************************************
61798 : This function initializes Phase2 temporaries. It should be called before
61799 : beginning of each new iteration. You may call it multiple times for the
61800 : same instance of Phase2 temporaries.
61801 :
61802 : INPUT PARAMETERS:
61803 : State2 - instance to be initialized.
61804 : N - problem dimensionality
61805 : NEC, NIC - linear equality/inequality constraint count
61806 : NLEC, NLIC - nonlinear equality/inequality constraint count
61807 : MeritLagMult - Lagrange multiplier estimates used by merit function
61808 : (we could use ones computed during phase #2,
61809 : but these may differ from ones computed
61810 : initially at the beginning of the outer
61811 : iteration, so it may confuse algorithm)
61812 :
61813 : OUTPUT PARAMETERS:
61814 : State2 - instance being initialized
61815 :
61816 : -- ALGLIB --
61817 : Copyright 05.02.2019 by Bochkanov Sergey
61818 : *************************************************************************/
61819 0 : static void nlcslp_phase2init(minslpphase2state* state2,
61820 : ae_int_t n,
61821 : ae_int_t nec,
61822 : ae_int_t nic,
61823 : ae_int_t nlec,
61824 : ae_int_t nlic,
61825 : /* Real */ ae_vector* meritlagmult,
61826 : ae_state *_state)
61827 : {
61828 : ae_int_t i;
61829 : ae_int_t nslack;
61830 :
61831 :
61832 0 : nslack = n+2*(nec+nlec)+(nic+nlic);
61833 0 : rvectorsetlengthatleast(&state2->d, nslack, _state);
61834 0 : rvectorsetlengthatleast(&state2->tmp0, nslack, _state);
61835 0 : rvectorsetlengthatleast(&state2->stepkxn, n, _state);
61836 0 : rvectorsetlengthatleast(&state2->stepkxc, n, _state);
61837 0 : rvectorsetlengthatleast(&state2->stepkfin, 1+nlec+nlic, _state);
61838 0 : rvectorsetlengthatleast(&state2->stepkfic, 1+nlec+nlic, _state);
61839 0 : rmatrixsetlengthatleast(&state2->stepkjn, 1+nlec+nlic, n, _state);
61840 0 : rmatrixsetlengthatleast(&state2->stepkjc, 1+nlec+nlic, n, _state);
61841 0 : rvectorsetlengthatleast(&state2->stepklaggrad, n, _state);
61842 0 : rvectorsetlengthatleast(&state2->stepknlaggrad, n, _state);
61843 0 : rvectorsetlengthatleast(&state2->stepknlagmult, nec+nic+nlec+nlic, _state);
61844 0 : rvectorsetlengthatleast(&state2->meritlagmult, nec+nic+nlec+nlic, _state);
61845 0 : for(i=0; i<=nec+nic+nlec+nlic-1; i++)
61846 : {
61847 0 : state2->meritlagmult.ptr.p_double[i] = meritlagmult->ptr.p_double[i];
61848 : }
61849 0 : ae_vector_set_length(&state2->rphase2state.ia, 12+1, _state);
61850 0 : ae_vector_set_length(&state2->rphase2state.ba, 2+1, _state);
61851 0 : ae_vector_set_length(&state2->rphase2state.ra, 8+1, _state);
61852 0 : state2->rphase2state.stage = -1;
61853 0 : }
61854 :
61855 :
61856 : /*************************************************************************
61857 : This function tries to perform phase #2 iterations.
61858 :
61859 : Phase #2 is a sequence of linearized steps minimizing L2-penalized
61860 : Lagrangian performed with successively increasing set of conjugacy
61861 : constraints (which make algorithm behavior similar to that of CG).
61862 :
61863 : INPUT PARAMETERS:
61864 : State - SLP solver state
61865 : SMonitor - smoothness monitor
61866 : UserTerminationNeeded-True if user requested termination
61867 : CurX - current point, array[N]
61868 : CurFi - function vector at CurX, array[1+NLEC+NLIC]
61869 : CurJ - Jacobian at CurX, array[1+NLEC+NLIC,N]
61870 : LagMult - array[NEC+NIC+NLEC+NLIC], contents ignored on input.
61871 : GammaMax - current estimate of the Hessian norm
61872 :
61873 : OUTPUT PARAMETERS:
61874 : State - RepTerminationType is set to current termination code (if Status=0).
61875 : CurX - advanced to new point
61876 : CurFi - updated with function vector at CurX[]
61877 : CurJ - updated with Jacobian at CurX[]
61878 : LagMult - filled with current Lagrange multipliers
61879 : GammaMax - updated estimate of the Hessian norm
61880 : Status - when reverse communication is done, Status is set to:
61881 : * negative value, if we have to restart outer
61882 : iteration
61883 : * positive value, if we can proceed to the next stage
61884 : of the outer iteration
61885 : * zero, if algorithm is terminated (RepTerminationType
61886 : is set to appropriate value)
61887 :
61888 : -- ALGLIB --
61889 : Copyright 05.02.2019 by Bochkanov Sergey
61890 : *************************************************************************/
61891 0 : static ae_bool nlcslp_phase2iteration(minslpstate* state,
61892 : minslpphase2state* state2,
61893 : smoothnessmonitor* smonitor,
61894 : ae_bool userterminationneeded,
61895 : /* Real */ ae_vector* curx,
61896 : /* Real */ ae_vector* curfi,
61897 : /* Real */ ae_matrix* curj,
61898 : /* Real */ ae_vector* lagmult,
61899 : double* gammamax,
61900 : ae_int_t* status,
61901 : ae_state *_state)
61902 : {
61903 : ae_int_t n;
61904 : ae_int_t nslack;
61905 : ae_int_t nec;
61906 : ae_int_t nic;
61907 : ae_int_t nlec;
61908 : ae_int_t nlic;
61909 : double stp;
61910 : ae_int_t mcinfo;
61911 : ae_int_t mcnfev;
61912 : ae_int_t mcstage;
61913 : ae_int_t i;
61914 : ae_int_t j;
61915 : ae_int_t innerk;
61916 : double v;
61917 : double vv;
61918 : double mx;
61919 : ae_int_t nondescentcnt;
61920 : double stepklagval;
61921 : double stepknlagval;
61922 : double gammaprev;
61923 : double f0;
61924 : double f1;
61925 : ae_bool dotrace;
61926 : ae_bool doprobing;
61927 : ae_bool dotracexd;
61928 : ae_bool result;
61929 :
61930 :
61931 :
61932 : /*
61933 : * Reverse communication preparations
61934 : * I know it looks ugly, but it works the same way
61935 : * anywhere from C++ to Python.
61936 : *
61937 : * This code initializes locals by:
61938 : * * random values determined during code
61939 : * generation - on first subroutine call
61940 : * * values from previous call - on subsequent calls
61941 : */
61942 0 : if( state2->rphase2state.stage>=0 )
61943 : {
61944 0 : n = state2->rphase2state.ia.ptr.p_int[0];
61945 0 : nslack = state2->rphase2state.ia.ptr.p_int[1];
61946 0 : nec = state2->rphase2state.ia.ptr.p_int[2];
61947 0 : nic = state2->rphase2state.ia.ptr.p_int[3];
61948 0 : nlec = state2->rphase2state.ia.ptr.p_int[4];
61949 0 : nlic = state2->rphase2state.ia.ptr.p_int[5];
61950 0 : mcinfo = state2->rphase2state.ia.ptr.p_int[6];
61951 0 : mcnfev = state2->rphase2state.ia.ptr.p_int[7];
61952 0 : mcstage = state2->rphase2state.ia.ptr.p_int[8];
61953 0 : i = state2->rphase2state.ia.ptr.p_int[9];
61954 0 : j = state2->rphase2state.ia.ptr.p_int[10];
61955 0 : innerk = state2->rphase2state.ia.ptr.p_int[11];
61956 0 : nondescentcnt = state2->rphase2state.ia.ptr.p_int[12];
61957 0 : dotrace = state2->rphase2state.ba.ptr.p_bool[0];
61958 0 : doprobing = state2->rphase2state.ba.ptr.p_bool[1];
61959 0 : dotracexd = state2->rphase2state.ba.ptr.p_bool[2];
61960 0 : stp = state2->rphase2state.ra.ptr.p_double[0];
61961 0 : v = state2->rphase2state.ra.ptr.p_double[1];
61962 0 : vv = state2->rphase2state.ra.ptr.p_double[2];
61963 0 : mx = state2->rphase2state.ra.ptr.p_double[3];
61964 0 : stepklagval = state2->rphase2state.ra.ptr.p_double[4];
61965 0 : stepknlagval = state2->rphase2state.ra.ptr.p_double[5];
61966 0 : gammaprev = state2->rphase2state.ra.ptr.p_double[6];
61967 0 : f0 = state2->rphase2state.ra.ptr.p_double[7];
61968 0 : f1 = state2->rphase2state.ra.ptr.p_double[8];
61969 : }
61970 : else
61971 : {
61972 0 : n = -763;
61973 0 : nslack = -233;
61974 0 : nec = -936;
61975 0 : nic = -279;
61976 0 : nlec = 94;
61977 0 : nlic = -812;
61978 0 : mcinfo = 427;
61979 0 : mcnfev = 178;
61980 0 : mcstage = -819;
61981 0 : i = -826;
61982 0 : j = 667;
61983 0 : innerk = 692;
61984 0 : nondescentcnt = 84;
61985 0 : dotrace = ae_true;
61986 0 : doprobing = ae_false;
61987 0 : dotracexd = ae_false;
61988 0 : stp = -908;
61989 0 : v = 577;
61990 0 : vv = 289;
61991 0 : mx = 317;
61992 0 : stepklagval = 476;
61993 0 : stepknlagval = -889;
61994 0 : gammaprev = -400;
61995 0 : f0 = 489;
61996 0 : f1 = -962;
61997 : }
61998 0 : if( state2->rphase2state.stage==0 )
61999 : {
62000 0 : goto lbl_0;
62001 : }
62002 0 : if( state2->rphase2state.stage==1 )
62003 : {
62004 0 : goto lbl_1;
62005 : }
62006 0 : if( state2->rphase2state.stage==2 )
62007 : {
62008 0 : goto lbl_2;
62009 : }
62010 :
62011 : /*
62012 : * Routine body
62013 : */
62014 0 : n = state->n;
62015 0 : nec = state->nec;
62016 0 : nic = state->nic;
62017 0 : nlec = state->nlec;
62018 0 : nlic = state->nlic;
62019 0 : nslack = n+2*(nec+nlec)+(nic+nlic);
62020 0 : dotrace = ae_is_trace_enabled("SLP");
62021 0 : dotracexd = dotrace&&ae_is_trace_enabled("SLP.DETAILED");
62022 0 : doprobing = ae_is_trace_enabled("SLP.PROBING");
62023 0 : ae_assert(lagmult->cnt>=nec+nic+nlec+nlic, "Phase13Iteration: integrity check failed", _state);
62024 :
62025 : /*
62026 : * Report iteration beginning
62027 : */
62028 0 : if( dotrace )
62029 : {
62030 0 : ae_trace("\n--- linear step with conjugate constraints (CG-like convergence) -----------------------------------\n");
62031 : }
62032 :
62033 : /*
62034 : * The default decision is to continue iterations
62035 : */
62036 0 : *status = 1;
62037 :
62038 : /*
62039 : * Perform inner LP subiterations.
62040 : *
62041 : * During this process we maintain information about several points:
62042 : * * point #0, initial one, with "step0" prefix
62043 : * * point #K, last one of current LP session, with "stepk" prefix
62044 : * * additionally we have point #KN, current candidate during line search at step K.
62045 : *
62046 : * For each point we store:
62047 : * * location X (scaled coordinates)
62048 : * * function vector Fi (target function + nonlinear constraints)
62049 : * * scaled Jacobian J
62050 : */
62051 0 : nondescentcnt = 0;
62052 0 : nlcslp_lpsubproblemrestart(state, &state->subsolver, _state);
62053 0 : innerk = 1;
62054 0 : lbl_3:
62055 0 : if( innerk>n )
62056 : {
62057 0 : goto lbl_5;
62058 : }
62059 :
62060 : /*
62061 : * Formulate LP subproblem and solve it
62062 : */
62063 0 : if( !nlcslp_lpsubproblemsolve(state, &state->subsolver, curx, curfi, curj, innerk, &state2->d, lagmult, _state) )
62064 : {
62065 :
62066 : /*
62067 : * LP solver failed due to numerical errors; exit.
62068 : * It may happen when we solve problem with LOTS of conjugacy constraints.
62069 : */
62070 0 : if( innerk==1 )
62071 : {
62072 :
62073 : /*
62074 : * The very first iteration failed, really strange.
62075 : */
62076 0 : if( dotrace )
62077 : {
62078 0 : ae_trace("[WARNING] the very first LP subproblem failed to produce descent direction\n");
62079 : }
62080 : }
62081 : else
62082 : {
62083 :
62084 : /*
62085 : * Quite a normal, the problem is overconstrained by conjugacy constraints now
62086 : */
62087 0 : if( dotrace )
62088 : {
62089 0 : ae_trace("> LP subproblem is overconstrained (happens after too many iterations), time to stop\n");
62090 : }
62091 : }
62092 0 : result = ae_false;
62093 0 : return result;
62094 : }
62095 0 : mx = (double)(0);
62096 0 : for(i=0; i<=n-1; i++)
62097 : {
62098 0 : mx = ae_maxreal(mx, ae_fabs(state2->d.ptr.p_double[i], _state)/state->trustrad, _state);
62099 : }
62100 0 : if( ae_fp_eq(mx,(double)(0)) )
62101 : {
62102 :
62103 : /*
62104 : * Nearly-zero direction is suggested (maybe we arrived exactly to the solution), stop iterations
62105 : */
62106 0 : *status = 1;
62107 0 : nlcslp_slpcopystate(state, curx, curfi, curj, &state2->stepkxn, &state2->stepkfin, &state2->stepkjn, _state);
62108 0 : if( dotrace )
62109 : {
62110 0 : ae_trace("> LP subproblem suggested nearly zero step\n");
62111 : }
62112 0 : if( dotrace )
62113 : {
62114 0 : ae_trace("max(|Di|)/TrustRad = %0.6f\n",
62115 : (double)(mx));
62116 : }
62117 0 : if( dotrace )
62118 : {
62119 0 : ae_trace("> stopping CG-like iterations\n");
62120 : }
62121 0 : result = ae_false;
62122 0 : return result;
62123 : }
62124 0 : nlcslp_lpsubproblemappendconjugacyconstraint(state, &state->subsolver, &state2->d, _state);
62125 :
62126 : /*
62127 : * Perform line search to minimize Lagrangian along D.
62128 : * Post-normalize StepKXN with respect to box constraints.
62129 : *
62130 : * MCSRCH can fail in the following cases:
62131 : * * rounding errors prevent optimization
62132 : * * non-descent direction is specified (MCINFO=0 is returned)
62133 : * In the latter case we proceed to minimization of merit function.
62134 : *
62135 : * NOTE: constraint violation reports are updated during Lagrangian computation
62136 : */
62137 0 : state2->lastlcerr = (double)(0);
62138 0 : state2->lastlcidx = -1;
62139 0 : state2->lastnlcerr = (double)(0);
62140 0 : state2->lastnlcidx = -1;
62141 0 : rvectorsetlengthatleast(&state2->tmp0, n, _state);
62142 0 : nlcslp_lagrangianfg(state, curx, state->trustrad, curfi, curj, lagmult, &state2->tmplagrangianfg, &stepklagval, &state2->stepklaggrad, &state2->lastlcerr, &state2->lastlcidx, &state2->lastnlcerr, &state2->lastnlcidx, _state);
62143 0 : nlcslp_slpcopystate(state, curx, curfi, curj, &state2->stepkxn, &state2->stepkfin, &state2->stepkjn, _state);
62144 0 : v = (double)(0);
62145 0 : for(i=0; i<=n-1; i++)
62146 : {
62147 0 : state2->stepknlaggrad.ptr.p_double[i] = state2->stepklaggrad.ptr.p_double[i];
62148 0 : v = v+state2->d.ptr.p_double[i]*state2->stepklaggrad.ptr.p_double[i];
62149 : }
62150 0 : if( ae_fp_greater_eq(v,(double)(0)) )
62151 : {
62152 :
62153 : /*
62154 : * Non-descent direction D was specified; it may happen because LP subproblem favors
62155 : * directions which decrease L1 penalty and default augmentation of Lagrangian involves
62156 : * only L2 term.
62157 : *
62158 : * Append direction to the conjugacy constraints and retry direction generation.
62159 : *
62160 : * We make several retries with conjugate directions before giving up.
62161 : */
62162 0 : if( dotrace )
62163 : {
62164 0 : ae_trace("> LP subproblem suggested nondescent step, skipping it (dLag=%0.3e)\n",
62165 : (double)(v));
62166 : }
62167 0 : inc(&nondescentcnt, _state);
62168 0 : if( nlcslp_nondescentlimit>0&&nondescentcnt>nlcslp_nondescentlimit )
62169 : {
62170 0 : if( dotrace )
62171 : {
62172 0 : ae_trace("> too many nondescent steps, stopping CG-like iterations\n");
62173 : }
62174 0 : *status = 1;
62175 0 : result = ae_false;
62176 0 : return result;
62177 : }
62178 0 : goto lbl_4;
62179 : }
62180 0 : smoothnessmonitorstartlinesearch(smonitor, curx, curfi, curj, _state);
62181 0 : stepknlagval = stepklagval;
62182 0 : mcnfev = 0;
62183 0 : mcstage = 0;
62184 0 : stp = 1.0;
62185 0 : mcsrch(n, &state2->stepkxn, &stepknlagval, &state2->stepknlaggrad, &state2->d, &stp, 1.0, nlcslp_slpgtol, &mcinfo, &mcnfev, &state2->tmp0, &state2->mcstate, &mcstage, _state);
62186 0 : lbl_6:
62187 0 : if( mcstage==0 )
62188 : {
62189 0 : goto lbl_7;
62190 : }
62191 0 : nlcslp_slpsendx(state, &state2->stepkxn, _state);
62192 0 : state->needfij = ae_true;
62193 0 : state2->rphase2state.stage = 0;
62194 0 : goto lbl_rcomm;
62195 0 : lbl_0:
62196 0 : state->needfij = ae_false;
62197 0 : if( !nlcslp_slpretrievefij(state, &state2->stepkfin, &state2->stepkjn, _state) )
62198 : {
62199 :
62200 : /*
62201 : * Failed to retrieve func/Jac, infinities detected
62202 : */
62203 0 : *status = 0;
62204 0 : state->repterminationtype = -8;
62205 0 : if( dotrace )
62206 : {
62207 0 : ae_trace("[ERROR] infinities in target/constraints are detected\n");
62208 : }
62209 0 : result = ae_false;
62210 0 : return result;
62211 : }
62212 0 : smoothnessmonitorenqueuepoint(smonitor, &state2->d, stp, &state2->stepkxn, &state2->stepkfin, &state2->stepkjn, _state);
62213 0 : nlcslp_lagrangianfg(state, &state2->stepkxn, state->trustrad, &state2->stepkfin, &state2->stepkjn, lagmult, &state2->tmplagrangianfg, &stepknlagval, &state2->stepknlaggrad, &state2->lastlcerr, &state2->lastlcidx, &state2->lastnlcerr, &state2->lastnlcidx, _state);
62214 0 : mcsrch(n, &state2->stepkxn, &stepknlagval, &state2->stepknlaggrad, &state2->d, &stp, 1.0, nlcslp_slpgtol, &mcinfo, &mcnfev, &state2->tmp0, &state2->mcstate, &mcstage, _state);
62215 0 : goto lbl_6;
62216 0 : lbl_7:
62217 0 : smoothnessmonitorfinalizelinesearch(smonitor, _state);
62218 0 : for(i=0; i<=n-1; i++)
62219 : {
62220 0 : if( state->hasbndl.ptr.p_bool[i] )
62221 : {
62222 0 : state2->stepkxn.ptr.p_double[i] = ae_maxreal(state2->stepkxn.ptr.p_double[i], state->scaledbndl.ptr.p_double[i], _state);
62223 : }
62224 0 : if( state->hasbndu.ptr.p_bool[i] )
62225 : {
62226 0 : state2->stepkxn.ptr.p_double[i] = ae_minreal(state2->stepkxn.ptr.p_double[i], state->scaledbndu.ptr.p_double[i], _state);
62227 : }
62228 : }
62229 0 : if( mcinfo<=0 )
62230 : {
62231 :
62232 : /*
62233 : * Line search failed miserably, terminate
62234 : */
62235 0 : *status = 1;
62236 0 : if( innerk==1 )
62237 : {
62238 :
62239 : /*
62240 : * The very first iteration failed, really strange.
62241 : * Let's decrease trust radius and try one more time.
62242 : */
62243 0 : state->trustrad = 0.5*state->trustrad;
62244 0 : if( dotrace )
62245 : {
62246 0 : ae_trace("> line search failed miserably for unknown reason, decreasing trust radius\n");
62247 : }
62248 0 : if( ae_fp_less(state->trustrad,state->epsx) )
62249 : {
62250 0 : state->repterminationtype = 2;
62251 0 : *status = 0;
62252 0 : if( dotrace )
62253 : {
62254 0 : ae_trace("> stopping condition met: trust radius is smaller than %0.3e\n",
62255 0 : (double)(state->epsx));
62256 : }
62257 : }
62258 : }
62259 : else
62260 : {
62261 :
62262 : /*
62263 : * Well, it can be normal
62264 : */
62265 0 : if( dotrace )
62266 : {
62267 0 : ae_trace("> line search failed miserably for unknown reason, proceeding further\n");
62268 : }
62269 : }
62270 0 : result = ae_false;
62271 0 : return result;
62272 : }
62273 0 : if( mcinfo==1 )
62274 : {
62275 0 : nlcslp_lpsubproblemupdatehessian(state, &state->subsolver, curx, &state2->stepklaggrad, &state2->stepkxn, &state2->stepknlaggrad, _state);
62276 : }
62277 :
62278 : /*
62279 : * Update GammaMax - estimate of the function Hessian norm
62280 : */
62281 0 : v = (double)(0);
62282 0 : vv = (double)(0);
62283 0 : mx = (double)(0);
62284 0 : for(i=0; i<=n-1; i++)
62285 : {
62286 0 : mx = ae_maxreal(mx, ae_fabs(state2->stepkxn.ptr.p_double[i]-curx->ptr.p_double[i], _state), _state);
62287 0 : v = v+ae_sqr(state2->stepkxn.ptr.p_double[i]-curx->ptr.p_double[i], _state);
62288 0 : vv = vv+(state2->stepkjn.ptr.pp_double[0][i]-curj->ptr.pp_double[0][i])*(state2->stepkxn.ptr.p_double[i]-curx->ptr.p_double[i]);
62289 : }
62290 0 : gammaprev = *gammamax;
62291 0 : if( ae_fp_greater(mx,nlcslp_bfgstol) )
62292 : {
62293 0 : *gammamax = ae_maxreal(*gammamax, ae_fabs(vv/v, _state), _state);
62294 : }
62295 :
62296 : /*
62297 : * Trace
62298 : */
62299 0 : if( !dotrace )
62300 : {
62301 0 : goto lbl_8;
62302 : }
62303 0 : if( !doprobing )
62304 : {
62305 0 : goto lbl_10;
62306 : }
62307 0 : smoothnessmonitorstartprobing(smonitor, 1.0, 2, state->trustrad, _state);
62308 0 : lbl_12:
62309 0 : if( !smoothnessmonitorprobe(smonitor, _state) )
62310 : {
62311 0 : goto lbl_13;
62312 : }
62313 0 : for(j=0; j<=n-1; j++)
62314 : {
62315 0 : state2->stepkxc.ptr.p_double[j] = curx->ptr.p_double[j]+smonitor->probingstp*state2->d.ptr.p_double[j];
62316 0 : if( state->hasbndl.ptr.p_bool[j] )
62317 : {
62318 0 : state2->stepkxc.ptr.p_double[j] = ae_maxreal(state2->stepkxc.ptr.p_double[j], state->scaledbndl.ptr.p_double[j], _state);
62319 : }
62320 0 : if( state->hasbndu.ptr.p_bool[j] )
62321 : {
62322 0 : state2->stepkxc.ptr.p_double[j] = ae_minreal(state2->stepkxc.ptr.p_double[j], state->scaledbndu.ptr.p_double[j], _state);
62323 : }
62324 : }
62325 0 : nlcslp_slpsendx(state, &state2->stepkxc, _state);
62326 0 : state->needfij = ae_true;
62327 0 : state2->rphase2state.stage = 1;
62328 0 : goto lbl_rcomm;
62329 0 : lbl_1:
62330 0 : state->needfij = ae_false;
62331 0 : if( !nlcslp_slpretrievefij(state, &state2->stepkfic, &state2->stepkjc, _state) )
62332 : {
62333 0 : goto lbl_13;
62334 : }
62335 0 : smonitor->probingf.ptr.p_double[0] = nlcslp_rawlagrangian(state, &state2->stepkxc, &state2->stepkfic, lagmult, &state2->tmpmerit, _state);
62336 0 : smonitor->probingf.ptr.p_double[1] = state2->stepkfic.ptr.p_double[0];
62337 0 : goto lbl_12;
62338 0 : lbl_13:
62339 0 : ae_trace("*** ------------------------------------------------------------\n");
62340 0 : ae_trace("*** | probing search direction suggested by LP subproblem |\n");
62341 0 : ae_trace("*** ------------------------------------------------------------\n");
62342 0 : ae_trace("*** | Step | Lagrangian (unaugmentd)| Target function |\n");
62343 0 : ae_trace("*** |along D| must be smooth | must be smooth |\n");
62344 0 : ae_trace("*** | | function | slope | function | slope |\n");
62345 0 : smoothnessmonitortraceprobingresults(smonitor, _state);
62346 0 : lbl_10:
62347 0 : mx = (double)(0);
62348 0 : for(i=0; i<=n-1; i++)
62349 : {
62350 0 : mx = ae_maxreal(mx, ae_fabs(state2->d.ptr.p_double[i], _state)/state->trustrad, _state);
62351 : }
62352 0 : f0 = nlcslp_meritfunction(state, curx, curfi, &state2->meritlagmult, &state2->tmpmerit, _state);
62353 0 : f1 = nlcslp_meritfunction(state, &state2->stepkxn, &state2->stepkfin, &state2->meritlagmult, &state2->tmpmerit, _state);
62354 0 : ae_trace("> LP subproblem produced good direction, minimization was performed\n");
62355 0 : ae_trace("max(|Di|)/TrustRad = %0.6f\n",
62356 : (double)(mx));
62357 0 : ae_trace("stp = %0.6f\n",
62358 : (double)(stp));
62359 0 : if( dotracexd )
62360 : {
62361 0 : ae_trace("X0 = ");
62362 0 : tracevectorautoprec(curx, 0, n, _state);
62363 0 : ae_trace("\n");
62364 0 : ae_trace("D = ");
62365 0 : tracevectorautoprec(&state2->d, 0, n, _state);
62366 0 : ae_trace("\n");
62367 0 : ae_trace("X1 = X0 + stp*D\n");
62368 0 : ae_trace(" = ");
62369 0 : tracevectorautoprec(&state2->stepkxn, 0, n, _state);
62370 0 : ae_trace("\n");
62371 : }
62372 0 : ae_trace("meritF: %14.6e -> %14.6e (delta=%11.3e)\n",
62373 : (double)(f0),
62374 : (double)(f1),
62375 : (double)(f1-f0));
62376 0 : ae_trace("scaled-targetF: %14.6e -> %14.6e (delta=%11.3e)\n",
62377 0 : (double)(curfi->ptr.p_double[0]),
62378 0 : (double)(state2->stepkfin.ptr.p_double[0]),
62379 0 : (double)(state2->stepkfin.ptr.p_double[0]-curfi->ptr.p_double[0]));
62380 0 : ae_trace("aug.Lagrangian: %14.6e -> %14.6e (delta=%11.3e)\n",
62381 : (double)(stepklagval),
62382 : (double)(stepknlagval),
62383 : (double)(stepknlagval-stepklagval));
62384 0 : if( ae_fp_greater(*gammamax,gammaprev) )
62385 : {
62386 0 : ae_trace("|H| = %0.3e (Hessian norm increased)\n",
62387 : (double)(*gammamax));
62388 : }
62389 0 : lbl_8:
62390 :
62391 : /*
62392 : * Check status of the termination request
62393 : * Update current point
62394 : * Update constraint status.
62395 : * Report iteration.
62396 : */
62397 0 : if( userterminationneeded )
62398 : {
62399 :
62400 : /*
62401 : * User requested termination, break before we move to new point
62402 : */
62403 0 : *status = 0;
62404 0 : state->repterminationtype = 8;
62405 0 : if( dotrace )
62406 : {
62407 0 : ae_trace("# user requested termination\n");
62408 : }
62409 0 : result = ae_false;
62410 0 : return result;
62411 : }
62412 0 : nlcslp_slpcopystate(state, &state2->stepkxn, &state2->stepkfin, &state2->stepkjn, curx, curfi, curj, _state);
62413 0 : state->replcerr = state2->lastlcerr;
62414 0 : state->replcidx = state2->lastlcidx;
62415 0 : state->repnlcerr = state2->lastnlcerr;
62416 0 : state->repnlcidx = state2->lastnlcidx;
62417 0 : inc(&state->repinneriterationscount, _state);
62418 0 : nlcslp_slpsendx(state, curx, _state);
62419 0 : state->f = curfi->ptr.p_double[0]*state->fscales.ptr.p_double[0];
62420 0 : state->xupdated = ae_true;
62421 0 : state2->rphase2state.stage = 2;
62422 0 : goto lbl_rcomm;
62423 0 : lbl_2:
62424 0 : state->xupdated = ae_false;
62425 :
62426 : /*
62427 : * Terminate inner LP subiterations
62428 : */
62429 0 : if( state->maxits>0&&state->repinneriterationscount>=state->maxits )
62430 : {
62431 :
62432 : /*
62433 : * Iteration limit exhausted
62434 : */
62435 0 : *status = 1;
62436 0 : if( dotrace )
62437 : {
62438 0 : ae_trace("# stopping criteria met (MaxIts iterations performed)\n");
62439 : }
62440 0 : result = ae_false;
62441 0 : return result;
62442 : }
62443 0 : if( ae_fp_greater_eq(stp,nlcslp_slpstpclosetoone) )
62444 : {
62445 :
62446 : /*
62447 : * Step is close to 1.0, either of two is likely:
62448 : * * we move through nearly linear region of F()
62449 : * * we try to enforce some strongly violated constraint
62450 : *
62451 : * In any case, authors of the original algorithm recommend to break inner LP
62452 : * iteration and proceed to test of sufficient decrease of merit function.
62453 : */
62454 0 : *status = 1;
62455 0 : if( dotrace )
62456 : {
62457 0 : ae_trace("> step is close to 1, stopping iterations\n");
62458 : }
62459 0 : result = ae_false;
62460 0 : return result;
62461 : }
62462 0 : if( (mcinfo!=1&&mcinfo!=3)&&mcinfo!=5 )
62463 : {
62464 :
62465 : /*
62466 : * Line search ended with "bad" MCINFO
62467 : * (neither sufficient decrease, neither maximum step);
62468 : * terminate.
62469 : */
62470 0 : *status = 1;
62471 0 : if( dotrace )
62472 : {
62473 0 : ae_trace("> line search ended with bad MCINFO, no more CG-like iterations\n");
62474 : }
62475 0 : result = ae_false;
62476 0 : return result;
62477 : }
62478 0 : lbl_4:
62479 0 : innerk = innerk+1;
62480 0 : goto lbl_3;
62481 0 : lbl_5:
62482 0 : result = ae_false;
62483 0 : return result;
62484 :
62485 : /*
62486 : * Saving state
62487 : */
62488 0 : lbl_rcomm:
62489 0 : result = ae_true;
62490 0 : state2->rphase2state.ia.ptr.p_int[0] = n;
62491 0 : state2->rphase2state.ia.ptr.p_int[1] = nslack;
62492 0 : state2->rphase2state.ia.ptr.p_int[2] = nec;
62493 0 : state2->rphase2state.ia.ptr.p_int[3] = nic;
62494 0 : state2->rphase2state.ia.ptr.p_int[4] = nlec;
62495 0 : state2->rphase2state.ia.ptr.p_int[5] = nlic;
62496 0 : state2->rphase2state.ia.ptr.p_int[6] = mcinfo;
62497 0 : state2->rphase2state.ia.ptr.p_int[7] = mcnfev;
62498 0 : state2->rphase2state.ia.ptr.p_int[8] = mcstage;
62499 0 : state2->rphase2state.ia.ptr.p_int[9] = i;
62500 0 : state2->rphase2state.ia.ptr.p_int[10] = j;
62501 0 : state2->rphase2state.ia.ptr.p_int[11] = innerk;
62502 0 : state2->rphase2state.ia.ptr.p_int[12] = nondescentcnt;
62503 0 : state2->rphase2state.ba.ptr.p_bool[0] = dotrace;
62504 0 : state2->rphase2state.ba.ptr.p_bool[1] = doprobing;
62505 0 : state2->rphase2state.ba.ptr.p_bool[2] = dotracexd;
62506 0 : state2->rphase2state.ra.ptr.p_double[0] = stp;
62507 0 : state2->rphase2state.ra.ptr.p_double[1] = v;
62508 0 : state2->rphase2state.ra.ptr.p_double[2] = vv;
62509 0 : state2->rphase2state.ra.ptr.p_double[3] = mx;
62510 0 : state2->rphase2state.ra.ptr.p_double[4] = stepklagval;
62511 0 : state2->rphase2state.ra.ptr.p_double[5] = stepknlagval;
62512 0 : state2->rphase2state.ra.ptr.p_double[6] = gammaprev;
62513 0 : state2->rphase2state.ra.ptr.p_double[7] = f0;
62514 0 : state2->rphase2state.ra.ptr.p_double[8] = f1;
62515 0 : return result;
62516 : }
62517 :
62518 :
62519 : /*************************************************************************
62520 : Copies X to State.X
62521 : *************************************************************************/
62522 0 : static void nlcslp_slpsendx(minslpstate* state,
62523 : /* Real */ ae_vector* xs,
62524 : ae_state *_state)
62525 : {
62526 : ae_int_t i;
62527 : ae_int_t n;
62528 :
62529 :
62530 0 : n = state->n;
62531 0 : for(i=0; i<=n-1; i++)
62532 : {
62533 0 : if( state->hasbndl.ptr.p_bool[i]&&xs->ptr.p_double[i]<=state->scaledbndl.ptr.p_double[i] )
62534 : {
62535 0 : state->x.ptr.p_double[i] = state->scaledbndl.ptr.p_double[i];
62536 0 : continue;
62537 : }
62538 0 : if( state->hasbndu.ptr.p_bool[i]&&xs->ptr.p_double[i]>=state->scaledbndu.ptr.p_double[i] )
62539 : {
62540 0 : state->x.ptr.p_double[i] = state->scaledbndu.ptr.p_double[i];
62541 0 : continue;
62542 : }
62543 0 : state->x.ptr.p_double[i] = xs->ptr.p_double[i];
62544 : }
62545 0 : }
62546 :
62547 :
62548 : /*************************************************************************
62549 : Retrieves F-vector and scaled Jacobian, copies them to FiS and JS.
62550 :
62551 : Returns True on success, False on failure (when F or J are not finite numbers).
62552 : *************************************************************************/
62553 0 : static ae_bool nlcslp_slpretrievefij(minslpstate* state,
62554 : /* Real */ ae_vector* fis,
62555 : /* Real */ ae_matrix* js,
62556 : ae_state *_state)
62557 : {
62558 : ae_int_t nlec;
62559 : ae_int_t nlic;
62560 : ae_int_t n;
62561 : ae_int_t i;
62562 : ae_int_t j;
62563 : double v;
62564 : double vv;
62565 : ae_bool result;
62566 :
62567 :
62568 0 : n = state->n;
62569 0 : nlec = state->nlec;
62570 0 : nlic = state->nlic;
62571 0 : v = (double)(0);
62572 0 : for(i=0; i<=nlec+nlic; i++)
62573 : {
62574 0 : vv = 1/state->fscales.ptr.p_double[i];
62575 0 : fis->ptr.p_double[i] = vv*state->fi.ptr.p_double[i];
62576 0 : v = 0.1*v+fis->ptr.p_double[i];
62577 0 : for(j=0; j<=n-1; j++)
62578 : {
62579 0 : js->ptr.pp_double[i][j] = vv*state->j.ptr.pp_double[i][j];
62580 0 : v = 0.1*v+js->ptr.pp_double[i][j];
62581 : }
62582 : }
62583 0 : result = ae_isfinite(v, _state);
62584 0 : return result;
62585 : }
62586 :
62587 :
62588 : /*************************************************************************
62589 : Copies state (X point, Fi vector, J jacobian) to preallocated storage.
62590 : *************************************************************************/
62591 0 : static void nlcslp_slpcopystate(minslpstate* state,
62592 : /* Real */ ae_vector* x0,
62593 : /* Real */ ae_vector* fi0,
62594 : /* Real */ ae_matrix* j0,
62595 : /* Real */ ae_vector* x1,
62596 : /* Real */ ae_vector* fi1,
62597 : /* Real */ ae_matrix* j1,
62598 : ae_state *_state)
62599 : {
62600 : ae_int_t nlec;
62601 : ae_int_t nlic;
62602 : ae_int_t n;
62603 : ae_int_t i;
62604 : ae_int_t j;
62605 :
62606 :
62607 0 : n = state->n;
62608 0 : nlec = state->nlec;
62609 0 : nlic = state->nlic;
62610 0 : for(i=0; i<=n-1; i++)
62611 : {
62612 0 : x1->ptr.p_double[i] = x0->ptr.p_double[i];
62613 : }
62614 0 : for(i=0; i<=nlec+nlic; i++)
62615 : {
62616 0 : fi1->ptr.p_double[i] = fi0->ptr.p_double[i];
62617 0 : for(j=0; j<=n-1; j++)
62618 : {
62619 0 : j1->ptr.pp_double[i][j] = j0->ptr.pp_double[i][j];
62620 : }
62621 : }
62622 0 : }
62623 :
62624 :
62625 : /*************************************************************************
62626 : This function calculates Lagrangian of the problem (in scaled variables):
62627 : its value and gradient.
62628 :
62629 : Additionally it also estimates violation of linear constraints at the point
62630 : as well as index of the most violated constraint
62631 : *************************************************************************/
62632 0 : static void nlcslp_lagrangianfg(minslpstate* state,
62633 : /* Real */ ae_vector* x,
62634 : double trustrad,
62635 : /* Real */ ae_vector* fi,
62636 : /* Real */ ae_matrix* j,
62637 : /* Real */ ae_vector* lagmult,
62638 : minslptmplagrangian* tmp,
62639 : double* f,
62640 : /* Real */ ae_vector* g,
62641 : double* lcerr,
62642 : ae_int_t* lcidx,
62643 : double* nlcerr,
62644 : ae_int_t* nlcidx,
62645 : ae_state *_state)
62646 : {
62647 : ae_int_t i;
62648 : ae_int_t n;
62649 : ae_int_t nec;
62650 : ae_int_t nic;
62651 : ae_int_t nlec;
62652 : ae_int_t nlic;
62653 : double v;
62654 : double vlag;
62655 : double vact;
62656 : double vd;
62657 : double vviolate;
62658 : ae_bool usesparsegemv;
62659 : double dampingfactor;
62660 :
62661 0 : *f = 0;
62662 0 : *lcerr = 0;
62663 0 : *lcidx = 0;
62664 0 : *nlcerr = 0;
62665 0 : *nlcidx = 0;
62666 :
62667 0 : n = state->n;
62668 0 : nec = state->nec;
62669 0 : nic = state->nic;
62670 0 : nlec = state->nlec;
62671 0 : nlic = state->nlic;
62672 0 : dampingfactor = nlcslp_inequalitydampingfactor/trustrad;
62673 :
62674 : /*
62675 : * Prepare constraint violation report
62676 : */
62677 0 : *lcerr = (double)(0);
62678 0 : *lcidx = -1;
62679 0 : *nlcerr = (double)(0);
62680 0 : *nlcidx = -1;
62681 :
62682 : /*
62683 : * Target function
62684 : */
62685 0 : *f = fi->ptr.p_double[0];
62686 0 : for(i=0; i<=n-1; i++)
62687 : {
62688 0 : g->ptr.p_double[i] = j->ptr.pp_double[0][i];
62689 : }
62690 :
62691 : /*
62692 : * Lagrangian terms for linear constraints, constraint violations
62693 : */
62694 0 : if( nec+nic>0 )
62695 : {
62696 0 : usesparsegemv = state->subsolver.sparserawlc.ridx.ptr.p_int[nec+nic]<sparselevel2density(_state)*n*(nec+nic);
62697 0 : rvectorsetlengthatleast(&tmp->sclagtmp0, ae_maxint(nec+nic, n, _state), _state);
62698 0 : rvectorsetlengthatleast(&tmp->sclagtmp1, ae_maxint(nec+nic, n, _state), _state);
62699 0 : if( usesparsegemv )
62700 : {
62701 0 : sparsemv(&state->subsolver.sparserawlc, x, &tmp->sclagtmp0, _state);
62702 : }
62703 : else
62704 : {
62705 0 : rmatrixgemv(nec+nic, n, 1.0, &state->scaledcleic, 0, 0, 0, x, 0, 0.0, &tmp->sclagtmp0, 0, _state);
62706 : }
62707 0 : for(i=0; i<=nec+nic-1; i++)
62708 : {
62709 :
62710 : /*
62711 : * Estimate constraint value at the point, update violation info
62712 : *
62713 : * NOTE: here we expect that scaledCLEIC[] has normalized rows
62714 : */
62715 0 : v = tmp->sclagtmp0.ptr.p_double[i]-state->scaledcleic.ptr.pp_double[i][n];
62716 0 : if( i<nec||v>0 )
62717 : {
62718 :
62719 : /*
62720 : * Either equality constraint or violated inequality one.
62721 : * Update violation report.
62722 : */
62723 0 : vviolate = ae_fabs(v, _state);
62724 0 : if( vviolate>*lcerr )
62725 : {
62726 0 : *lcerr = vviolate;
62727 0 : *lcidx = state->lcsrcidx.ptr.p_int[i];
62728 : }
62729 : }
62730 :
62731 : /*
62732 : * Prepare
62733 : */
62734 0 : vlag = lagmult->ptr.p_double[i];
62735 0 : tmp->sclagtmp1.ptr.p_double[i] = (double)(0);
62736 :
62737 : /*
62738 : * Primary Lagrangian term
62739 : */
62740 0 : if( i<nec||v>0 )
62741 : {
62742 0 : vact = v;
62743 0 : vd = (double)(1);
62744 : }
62745 : else
62746 : {
62747 0 : vd = 1/(1-dampingfactor*v);
62748 0 : vact = v*vd;
62749 0 : vd = vd*vd;
62750 : }
62751 0 : *f = *f+vlag*vact;
62752 0 : tmp->sclagtmp1.ptr.p_double[i] = tmp->sclagtmp1.ptr.p_double[i]+vlag*vd;
62753 :
62754 : /*
62755 : * Quadratic augmentation term
62756 : */
62757 0 : if( i<nec||v>0 )
62758 : {
62759 0 : vact = v;
62760 : }
62761 : else
62762 : {
62763 0 : vact = (double)(0);
62764 : }
62765 0 : *f = *f+0.5*nlcslp_augmentationfactor*vact*vact;
62766 0 : tmp->sclagtmp1.ptr.p_double[i] = tmp->sclagtmp1.ptr.p_double[i]+nlcslp_augmentationfactor*vact;
62767 : }
62768 0 : if( usesparsegemv )
62769 : {
62770 0 : sparsemtv(&state->subsolver.sparserawlc, &tmp->sclagtmp1, &tmp->sclagtmp0, _state);
62771 0 : for(i=0; i<=n-1; i++)
62772 : {
62773 0 : g->ptr.p_double[i] = g->ptr.p_double[i]+tmp->sclagtmp0.ptr.p_double[i];
62774 : }
62775 : }
62776 : else
62777 : {
62778 0 : rmatrixgemv(n, nec+nic, 1.0, &state->scaledcleic, 0, 0, 1, &tmp->sclagtmp1, 0, 1.0, g, 0, _state);
62779 : }
62780 : }
62781 :
62782 : /*
62783 : * Lagrangian terms for nonlinear constraints
62784 : */
62785 0 : rvectorsetlengthatleast(&tmp->sclagtmp1, nlec+nlic, _state);
62786 0 : for(i=0; i<=nlec+nlic-1; i++)
62787 : {
62788 0 : v = fi->ptr.p_double[1+i];
62789 0 : if( i<nlec||v>0 )
62790 : {
62791 :
62792 : /*
62793 : * Either equality constraint or violated inequality one.
62794 : * Update violation report.
62795 : */
62796 0 : vviolate = ae_fabs(v, _state)*state->fscales.ptr.p_double[1+i];
62797 0 : if( vviolate>*nlcerr )
62798 : {
62799 0 : *nlcerr = vviolate;
62800 0 : *nlcidx = i;
62801 : }
62802 : }
62803 0 : vlag = lagmult->ptr.p_double[nec+nic+i];
62804 0 : tmp->sclagtmp1.ptr.p_double[i] = (double)(0);
62805 :
62806 : /*
62807 : * Lagrangian term
62808 : */
62809 0 : if( i<nlec||v>0 )
62810 : {
62811 0 : vact = v;
62812 0 : vd = (double)(1);
62813 : }
62814 : else
62815 : {
62816 0 : vd = 1/(1-dampingfactor*v);
62817 0 : vact = v*vd;
62818 0 : vd = vd*vd;
62819 : }
62820 0 : *f = *f+vlag*vact;
62821 0 : tmp->sclagtmp1.ptr.p_double[i] = tmp->sclagtmp1.ptr.p_double[i]+vlag*vd;
62822 :
62823 : /*
62824 : * Augmentation term
62825 : */
62826 0 : if( i<nlec||v>0 )
62827 : {
62828 0 : vact = v;
62829 : }
62830 : else
62831 : {
62832 0 : vact = (double)(0);
62833 : }
62834 0 : *f = *f+0.5*nlcslp_augmentationfactor*vact*vact;
62835 0 : tmp->sclagtmp1.ptr.p_double[i] = tmp->sclagtmp1.ptr.p_double[i]+nlcslp_augmentationfactor*vact;
62836 : }
62837 0 : rmatrixgemv(n, nlec+nlic, 1.0, j, 1, 0, 1, &tmp->sclagtmp1, 0, 1.0, g, 0, _state);
62838 0 : }
62839 :
62840 :
62841 : /*************************************************************************
62842 : This function calculates L1-penalized merit function
62843 : *************************************************************************/
62844 0 : static double nlcslp_meritfunction(minslpstate* state,
62845 : /* Real */ ae_vector* x,
62846 : /* Real */ ae_vector* fi,
62847 : /* Real */ ae_vector* lagmult,
62848 : minslptmpmerit* tmp,
62849 : ae_state *_state)
62850 : {
62851 : double tmp0;
62852 : double tmp1;
62853 : double result;
62854 :
62855 :
62856 0 : nlcslp_meritfunctionandrawlagrangian(state, x, fi, lagmult, tmp, &tmp0, &tmp1, _state);
62857 0 : result = tmp0;
62858 0 : return result;
62859 : }
62860 :
62861 :
62862 : /*************************************************************************
62863 : This function calculates raw (unaugmented and smooth) Lagrangian
62864 : *************************************************************************/
62865 0 : static double nlcslp_rawlagrangian(minslpstate* state,
62866 : /* Real */ ae_vector* x,
62867 : /* Real */ ae_vector* fi,
62868 : /* Real */ ae_vector* lagmult,
62869 : minslptmpmerit* tmp,
62870 : ae_state *_state)
62871 : {
62872 : double tmp0;
62873 : double tmp1;
62874 : double result;
62875 :
62876 :
62877 0 : nlcslp_meritfunctionandrawlagrangian(state, x, fi, lagmult, tmp, &tmp0, &tmp1, _state);
62878 0 : result = tmp1;
62879 0 : return result;
62880 : }
62881 :
62882 :
62883 : /*************************************************************************
62884 : This function calculates L1-penalized merit function and raw (smooth and
62885 : un-augmented) Lagrangian
62886 : *************************************************************************/
62887 0 : static void nlcslp_meritfunctionandrawlagrangian(minslpstate* state,
62888 : /* Real */ ae_vector* x,
62889 : /* Real */ ae_vector* fi,
62890 : /* Real */ ae_vector* lagmult,
62891 : minslptmpmerit* tmp,
62892 : double* meritf,
62893 : double* rawlag,
62894 : ae_state *_state)
62895 : {
62896 : ae_int_t i;
62897 : ae_int_t n;
62898 : ae_int_t nec;
62899 : ae_int_t nic;
62900 : ae_int_t nlec;
62901 : ae_int_t nlic;
62902 : double v;
62903 :
62904 0 : *meritf = 0;
62905 0 : *rawlag = 0;
62906 :
62907 0 : n = state->n;
62908 0 : nec = state->nec;
62909 0 : nic = state->nic;
62910 0 : nlec = state->nlec;
62911 0 : nlic = state->nlic;
62912 :
62913 : /*
62914 : * Merit function and Lagrangian: primary term
62915 : */
62916 0 : *meritf = fi->ptr.p_double[0];
62917 0 : *rawlag = fi->ptr.p_double[0];
62918 :
62919 : /*
62920 : * Merit function: augmentation and penalty for linear constraints
62921 : */
62922 0 : rvectorsetlengthatleast(&tmp->mftmp0, nec+nic, _state);
62923 0 : rmatrixgemv(nec+nic, n, 1.0, &state->scaledcleic, 0, 0, 0, x, 0, 0.0, &tmp->mftmp0, 0, _state);
62924 0 : for(i=0; i<=nec+nic-1; i++)
62925 : {
62926 0 : v = tmp->mftmp0.ptr.p_double[i]-state->scaledcleic.ptr.pp_double[i][n];
62927 0 : if( i<nec )
62928 : {
62929 :
62930 : /*
62931 : * Merit function: augmentation term + L1 penalty term
62932 : */
62933 0 : *meritf = *meritf+0.5*nlcslp_augmentationfactor*v*v;
62934 0 : *meritf = *meritf+nlcslp_meritfunctionbase*ae_fabs(v, _state)+nlcslp_meritfunctiongain*ae_fabs(lagmult->ptr.p_double[i], _state)*ae_fabs(v, _state);
62935 :
62936 : /*
62937 : * Raw Lagrangian
62938 : */
62939 0 : *rawlag = *rawlag+lagmult->ptr.p_double[i]*v;
62940 : }
62941 : else
62942 : {
62943 :
62944 : /*
62945 : * Merit function: augmentation term + L1 penalty term
62946 : */
62947 0 : *meritf = *meritf+0.5*nlcslp_augmentationfactor*ae_sqr(ae_maxreal(v, (double)(0), _state), _state);
62948 0 : *meritf = *meritf+nlcslp_meritfunctionbase*ae_maxreal(v, (double)(0), _state)+nlcslp_meritfunctiongain*ae_maxreal(lagmult->ptr.p_double[i]*v, (double)(0), _state);
62949 :
62950 : /*
62951 : * Raw Lagrangian
62952 : */
62953 0 : *rawlag = *rawlag+lagmult->ptr.p_double[i]*v;
62954 : }
62955 : }
62956 :
62957 : /*
62958 : * Merit function: augmentation and penalty for nonlinear constraints
62959 : */
62960 0 : for(i=0; i<=nlec+nlic-1; i++)
62961 : {
62962 0 : v = fi->ptr.p_double[1+i];
62963 0 : if( i<nlec )
62964 : {
62965 :
62966 : /*
62967 : * Merit function: augmentation term + L1 penalty term
62968 : */
62969 0 : *meritf = *meritf+0.5*nlcslp_augmentationfactor*v*v;
62970 0 : *meritf = *meritf+nlcslp_meritfunctionbase*ae_fabs(v, _state)+nlcslp_meritfunctiongain*ae_fabs(lagmult->ptr.p_double[nec+nic+i]*v, _state);
62971 :
62972 : /*
62973 : * Raw Lagrangian
62974 : */
62975 0 : *rawlag = *rawlag+lagmult->ptr.p_double[nec+nic+i]*v;
62976 : }
62977 : else
62978 : {
62979 :
62980 : /*
62981 : * Merit function: augmentation term + L1 penalty term
62982 : */
62983 0 : *meritf = *meritf+0.5*nlcslp_augmentationfactor*ae_sqr(ae_maxreal(v, (double)(0), _state), _state);
62984 0 : *meritf = *meritf+nlcslp_meritfunctionbase*ae_maxreal(v, (double)(0), _state)+nlcslp_meritfunctiongain*ae_maxreal(lagmult->ptr.p_double[nec+nic+i]*v, (double)(0), _state);
62985 :
62986 : /*
62987 : * Raw Lagrangian
62988 : */
62989 0 : *rawlag = *rawlag+lagmult->ptr.p_double[nec+nic+i]*v;
62990 : }
62991 : }
62992 0 : }
62993 :
62994 :
62995 0 : void _minslpsubsolver_init(void* _p, ae_state *_state, ae_bool make_automatic)
62996 : {
62997 0 : minslpsubsolver *p = (minslpsubsolver*)_p;
62998 0 : ae_touch_ptr((void*)p);
62999 0 : _presolveinfo_init(&p->presolver, _state, make_automatic);
63000 0 : _dualsimplexstate_init(&p->dss, _state, make_automatic);
63001 0 : _dualsimplexsettings_init(&p->dsssettings, _state, make_automatic);
63002 0 : _dualsimplexbasis_init(&p->lastbasis, _state, make_automatic);
63003 0 : ae_matrix_init(&p->curd, 0, 0, DT_REAL, _state, make_automatic);
63004 0 : ae_vector_init(&p->curb, 0, DT_REAL, _state, make_automatic);
63005 0 : ae_vector_init(&p->curbndl, 0, DT_REAL, _state, make_automatic);
63006 0 : ae_vector_init(&p->curbndu, 0, DT_REAL, _state, make_automatic);
63007 0 : ae_vector_init(&p->cural, 0, DT_REAL, _state, make_automatic);
63008 0 : ae_vector_init(&p->curau, 0, DT_REAL, _state, make_automatic);
63009 0 : _sparsematrix_init(&p->sparserawlc, _state, make_automatic);
63010 0 : _sparsematrix_init(&p->sparseefflc, _state, make_automatic);
63011 0 : ae_matrix_init(&p->h, 0, 0, DT_REAL, _state, make_automatic);
63012 0 : ae_matrix_init(&p->curhd, 0, 0, DT_REAL, _state, make_automatic);
63013 0 : ae_matrix_init(&p->densedummy, 0, 0, DT_REAL, _state, make_automatic);
63014 0 : _sparsematrix_init(&p->sparsedummy, _state, make_automatic);
63015 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
63016 0 : ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic);
63017 0 : ae_vector_init(&p->sk, 0, DT_REAL, _state, make_automatic);
63018 0 : ae_vector_init(&p->yk, 0, DT_REAL, _state, make_automatic);
63019 0 : ae_vector_init(&p->xs, 0, DT_REAL, _state, make_automatic);
63020 0 : ae_vector_init(&p->laglc, 0, DT_REAL, _state, make_automatic);
63021 0 : ae_vector_init(&p->lagbc, 0, DT_REAL, _state, make_automatic);
63022 0 : ae_vector_init(&p->cs, 0, DT_INT, _state, make_automatic);
63023 0 : }
63024 :
63025 :
63026 0 : void _minslpsubsolver_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
63027 : {
63028 0 : minslpsubsolver *dst = (minslpsubsolver*)_dst;
63029 0 : minslpsubsolver *src = (minslpsubsolver*)_src;
63030 0 : _presolveinfo_init_copy(&dst->presolver, &src->presolver, _state, make_automatic);
63031 0 : _dualsimplexstate_init_copy(&dst->dss, &src->dss, _state, make_automatic);
63032 0 : _dualsimplexsettings_init_copy(&dst->dsssettings, &src->dsssettings, _state, make_automatic);
63033 0 : _dualsimplexbasis_init_copy(&dst->lastbasis, &src->lastbasis, _state, make_automatic);
63034 0 : dst->basispresent = src->basispresent;
63035 0 : ae_matrix_init_copy(&dst->curd, &src->curd, _state, make_automatic);
63036 0 : dst->curdcnt = src->curdcnt;
63037 0 : ae_vector_init_copy(&dst->curb, &src->curb, _state, make_automatic);
63038 0 : ae_vector_init_copy(&dst->curbndl, &src->curbndl, _state, make_automatic);
63039 0 : ae_vector_init_copy(&dst->curbndu, &src->curbndu, _state, make_automatic);
63040 0 : ae_vector_init_copy(&dst->cural, &src->cural, _state, make_automatic);
63041 0 : ae_vector_init_copy(&dst->curau, &src->curau, _state, make_automatic);
63042 0 : _sparsematrix_init_copy(&dst->sparserawlc, &src->sparserawlc, _state, make_automatic);
63043 0 : _sparsematrix_init_copy(&dst->sparseefflc, &src->sparseefflc, _state, make_automatic);
63044 0 : dst->hessiantype = src->hessiantype;
63045 0 : ae_matrix_init_copy(&dst->h, &src->h, _state, make_automatic);
63046 0 : ae_matrix_init_copy(&dst->curhd, &src->curhd, _state, make_automatic);
63047 0 : ae_matrix_init_copy(&dst->densedummy, &src->densedummy, _state, make_automatic);
63048 0 : _sparsematrix_init_copy(&dst->sparsedummy, &src->sparsedummy, _state, make_automatic);
63049 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
63050 0 : ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic);
63051 0 : ae_vector_init_copy(&dst->sk, &src->sk, _state, make_automatic);
63052 0 : ae_vector_init_copy(&dst->yk, &src->yk, _state, make_automatic);
63053 0 : ae_vector_init_copy(&dst->xs, &src->xs, _state, make_automatic);
63054 0 : ae_vector_init_copy(&dst->laglc, &src->laglc, _state, make_automatic);
63055 0 : ae_vector_init_copy(&dst->lagbc, &src->lagbc, _state, make_automatic);
63056 0 : ae_vector_init_copy(&dst->cs, &src->cs, _state, make_automatic);
63057 0 : }
63058 :
63059 :
63060 0 : void _minslpsubsolver_clear(void* _p)
63061 : {
63062 0 : minslpsubsolver *p = (minslpsubsolver*)_p;
63063 0 : ae_touch_ptr((void*)p);
63064 0 : _presolveinfo_clear(&p->presolver);
63065 0 : _dualsimplexstate_clear(&p->dss);
63066 0 : _dualsimplexsettings_clear(&p->dsssettings);
63067 0 : _dualsimplexbasis_clear(&p->lastbasis);
63068 0 : ae_matrix_clear(&p->curd);
63069 0 : ae_vector_clear(&p->curb);
63070 0 : ae_vector_clear(&p->curbndl);
63071 0 : ae_vector_clear(&p->curbndu);
63072 0 : ae_vector_clear(&p->cural);
63073 0 : ae_vector_clear(&p->curau);
63074 0 : _sparsematrix_clear(&p->sparserawlc);
63075 0 : _sparsematrix_clear(&p->sparseefflc);
63076 0 : ae_matrix_clear(&p->h);
63077 0 : ae_matrix_clear(&p->curhd);
63078 0 : ae_matrix_clear(&p->densedummy);
63079 0 : _sparsematrix_clear(&p->sparsedummy);
63080 0 : ae_vector_clear(&p->tmp0);
63081 0 : ae_vector_clear(&p->tmp1);
63082 0 : ae_vector_clear(&p->sk);
63083 0 : ae_vector_clear(&p->yk);
63084 0 : ae_vector_clear(&p->xs);
63085 0 : ae_vector_clear(&p->laglc);
63086 0 : ae_vector_clear(&p->lagbc);
63087 0 : ae_vector_clear(&p->cs);
63088 0 : }
63089 :
63090 :
63091 0 : void _minslpsubsolver_destroy(void* _p)
63092 : {
63093 0 : minslpsubsolver *p = (minslpsubsolver*)_p;
63094 0 : ae_touch_ptr((void*)p);
63095 0 : _presolveinfo_destroy(&p->presolver);
63096 0 : _dualsimplexstate_destroy(&p->dss);
63097 0 : _dualsimplexsettings_destroy(&p->dsssettings);
63098 0 : _dualsimplexbasis_destroy(&p->lastbasis);
63099 0 : ae_matrix_destroy(&p->curd);
63100 0 : ae_vector_destroy(&p->curb);
63101 0 : ae_vector_destroy(&p->curbndl);
63102 0 : ae_vector_destroy(&p->curbndu);
63103 0 : ae_vector_destroy(&p->cural);
63104 0 : ae_vector_destroy(&p->curau);
63105 0 : _sparsematrix_destroy(&p->sparserawlc);
63106 0 : _sparsematrix_destroy(&p->sparseefflc);
63107 0 : ae_matrix_destroy(&p->h);
63108 0 : ae_matrix_destroy(&p->curhd);
63109 0 : ae_matrix_destroy(&p->densedummy);
63110 0 : _sparsematrix_destroy(&p->sparsedummy);
63111 0 : ae_vector_destroy(&p->tmp0);
63112 0 : ae_vector_destroy(&p->tmp1);
63113 0 : ae_vector_destroy(&p->sk);
63114 0 : ae_vector_destroy(&p->yk);
63115 0 : ae_vector_destroy(&p->xs);
63116 0 : ae_vector_destroy(&p->laglc);
63117 0 : ae_vector_destroy(&p->lagbc);
63118 0 : ae_vector_destroy(&p->cs);
63119 0 : }
63120 :
63121 :
63122 0 : void _minslptmplagrangian_init(void* _p, ae_state *_state, ae_bool make_automatic)
63123 : {
63124 0 : minslptmplagrangian *p = (minslptmplagrangian*)_p;
63125 0 : ae_touch_ptr((void*)p);
63126 0 : ae_vector_init(&p->sclagtmp0, 0, DT_REAL, _state, make_automatic);
63127 0 : ae_vector_init(&p->sclagtmp1, 0, DT_REAL, _state, make_automatic);
63128 0 : }
63129 :
63130 :
63131 0 : void _minslptmplagrangian_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
63132 : {
63133 0 : minslptmplagrangian *dst = (minslptmplagrangian*)_dst;
63134 0 : minslptmplagrangian *src = (minslptmplagrangian*)_src;
63135 0 : ae_vector_init_copy(&dst->sclagtmp0, &src->sclagtmp0, _state, make_automatic);
63136 0 : ae_vector_init_copy(&dst->sclagtmp1, &src->sclagtmp1, _state, make_automatic);
63137 0 : }
63138 :
63139 :
63140 0 : void _minslptmplagrangian_clear(void* _p)
63141 : {
63142 0 : minslptmplagrangian *p = (minslptmplagrangian*)_p;
63143 0 : ae_touch_ptr((void*)p);
63144 0 : ae_vector_clear(&p->sclagtmp0);
63145 0 : ae_vector_clear(&p->sclagtmp1);
63146 0 : }
63147 :
63148 :
63149 0 : void _minslptmplagrangian_destroy(void* _p)
63150 : {
63151 0 : minslptmplagrangian *p = (minslptmplagrangian*)_p;
63152 0 : ae_touch_ptr((void*)p);
63153 0 : ae_vector_destroy(&p->sclagtmp0);
63154 0 : ae_vector_destroy(&p->sclagtmp1);
63155 0 : }
63156 :
63157 :
63158 0 : void _minslptmpmerit_init(void* _p, ae_state *_state, ae_bool make_automatic)
63159 : {
63160 0 : minslptmpmerit *p = (minslptmpmerit*)_p;
63161 0 : ae_touch_ptr((void*)p);
63162 0 : ae_vector_init(&p->mftmp0, 0, DT_REAL, _state, make_automatic);
63163 0 : }
63164 :
63165 :
63166 0 : void _minslptmpmerit_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
63167 : {
63168 0 : minslptmpmerit *dst = (minslptmpmerit*)_dst;
63169 0 : minslptmpmerit *src = (minslptmpmerit*)_src;
63170 0 : ae_vector_init_copy(&dst->mftmp0, &src->mftmp0, _state, make_automatic);
63171 0 : }
63172 :
63173 :
63174 0 : void _minslptmpmerit_clear(void* _p)
63175 : {
63176 0 : minslptmpmerit *p = (minslptmpmerit*)_p;
63177 0 : ae_touch_ptr((void*)p);
63178 0 : ae_vector_clear(&p->mftmp0);
63179 0 : }
63180 :
63181 :
63182 0 : void _minslptmpmerit_destroy(void* _p)
63183 : {
63184 0 : minslptmpmerit *p = (minslptmpmerit*)_p;
63185 0 : ae_touch_ptr((void*)p);
63186 0 : ae_vector_destroy(&p->mftmp0);
63187 0 : }
63188 :
63189 :
63190 0 : void _minslpphase13state_init(void* _p, ae_state *_state, ae_bool make_automatic)
63191 : {
63192 0 : minslpphase13state *p = (minslpphase13state*)_p;
63193 0 : ae_touch_ptr((void*)p);
63194 0 : ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic);
63195 0 : ae_vector_init(&p->dx, 0, DT_REAL, _state, make_automatic);
63196 0 : ae_vector_init(&p->stepkxc, 0, DT_REAL, _state, make_automatic);
63197 0 : ae_vector_init(&p->stepkxn, 0, DT_REAL, _state, make_automatic);
63198 0 : ae_vector_init(&p->stepkfic, 0, DT_REAL, _state, make_automatic);
63199 0 : ae_vector_init(&p->stepkfin, 0, DT_REAL, _state, make_automatic);
63200 0 : ae_matrix_init(&p->stepkjc, 0, 0, DT_REAL, _state, make_automatic);
63201 0 : ae_matrix_init(&p->stepkjn, 0, 0, DT_REAL, _state, make_automatic);
63202 0 : ae_vector_init(&p->dummylagmult, 0, DT_REAL, _state, make_automatic);
63203 0 : _minslptmpmerit_init(&p->tmpmerit, _state, make_automatic);
63204 0 : _rcommstate_init(&p->rphase13state, _state, make_automatic);
63205 0 : }
63206 :
63207 :
63208 0 : void _minslpphase13state_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
63209 : {
63210 0 : minslpphase13state *dst = (minslpphase13state*)_dst;
63211 0 : minslpphase13state *src = (minslpphase13state*)_src;
63212 0 : dst->usecorrection = src->usecorrection;
63213 0 : ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic);
63214 0 : ae_vector_init_copy(&dst->dx, &src->dx, _state, make_automatic);
63215 0 : ae_vector_init_copy(&dst->stepkxc, &src->stepkxc, _state, make_automatic);
63216 0 : ae_vector_init_copy(&dst->stepkxn, &src->stepkxn, _state, make_automatic);
63217 0 : ae_vector_init_copy(&dst->stepkfic, &src->stepkfic, _state, make_automatic);
63218 0 : ae_vector_init_copy(&dst->stepkfin, &src->stepkfin, _state, make_automatic);
63219 0 : ae_matrix_init_copy(&dst->stepkjc, &src->stepkjc, _state, make_automatic);
63220 0 : ae_matrix_init_copy(&dst->stepkjn, &src->stepkjn, _state, make_automatic);
63221 0 : ae_vector_init_copy(&dst->dummylagmult, &src->dummylagmult, _state, make_automatic);
63222 0 : _minslptmpmerit_init_copy(&dst->tmpmerit, &src->tmpmerit, _state, make_automatic);
63223 0 : _rcommstate_init_copy(&dst->rphase13state, &src->rphase13state, _state, make_automatic);
63224 0 : }
63225 :
63226 :
63227 0 : void _minslpphase13state_clear(void* _p)
63228 : {
63229 0 : minslpphase13state *p = (minslpphase13state*)_p;
63230 0 : ae_touch_ptr((void*)p);
63231 0 : ae_vector_clear(&p->d);
63232 0 : ae_vector_clear(&p->dx);
63233 0 : ae_vector_clear(&p->stepkxc);
63234 0 : ae_vector_clear(&p->stepkxn);
63235 0 : ae_vector_clear(&p->stepkfic);
63236 0 : ae_vector_clear(&p->stepkfin);
63237 0 : ae_matrix_clear(&p->stepkjc);
63238 0 : ae_matrix_clear(&p->stepkjn);
63239 0 : ae_vector_clear(&p->dummylagmult);
63240 0 : _minslptmpmerit_clear(&p->tmpmerit);
63241 0 : _rcommstate_clear(&p->rphase13state);
63242 0 : }
63243 :
63244 :
63245 0 : void _minslpphase13state_destroy(void* _p)
63246 : {
63247 0 : minslpphase13state *p = (minslpphase13state*)_p;
63248 0 : ae_touch_ptr((void*)p);
63249 0 : ae_vector_destroy(&p->d);
63250 0 : ae_vector_destroy(&p->dx);
63251 0 : ae_vector_destroy(&p->stepkxc);
63252 0 : ae_vector_destroy(&p->stepkxn);
63253 0 : ae_vector_destroy(&p->stepkfic);
63254 0 : ae_vector_destroy(&p->stepkfin);
63255 0 : ae_matrix_destroy(&p->stepkjc);
63256 0 : ae_matrix_destroy(&p->stepkjn);
63257 0 : ae_vector_destroy(&p->dummylagmult);
63258 0 : _minslptmpmerit_destroy(&p->tmpmerit);
63259 0 : _rcommstate_destroy(&p->rphase13state);
63260 0 : }
63261 :
63262 :
63263 0 : void _minslpphase2state_init(void* _p, ae_state *_state, ae_bool make_automatic)
63264 : {
63265 0 : minslpphase2state *p = (minslpphase2state*)_p;
63266 0 : ae_touch_ptr((void*)p);
63267 0 : ae_vector_init(&p->stepkxn, 0, DT_REAL, _state, make_automatic);
63268 0 : ae_vector_init(&p->stepkxc, 0, DT_REAL, _state, make_automatic);
63269 0 : ae_vector_init(&p->stepkfin, 0, DT_REAL, _state, make_automatic);
63270 0 : ae_vector_init(&p->stepkfic, 0, DT_REAL, _state, make_automatic);
63271 0 : ae_matrix_init(&p->stepkjn, 0, 0, DT_REAL, _state, make_automatic);
63272 0 : ae_matrix_init(&p->stepkjc, 0, 0, DT_REAL, _state, make_automatic);
63273 0 : ae_vector_init(&p->stepklaggrad, 0, DT_REAL, _state, make_automatic);
63274 0 : ae_vector_init(&p->stepknlaggrad, 0, DT_REAL, _state, make_automatic);
63275 0 : ae_vector_init(&p->stepknlagmult, 0, DT_REAL, _state, make_automatic);
63276 0 : ae_vector_init(&p->meritlagmult, 0, DT_REAL, _state, make_automatic);
63277 0 : _minslptmplagrangian_init(&p->tmplagrangianfg, _state, make_automatic);
63278 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
63279 0 : ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic);
63280 0 : _linminstate_init(&p->mcstate, _state, make_automatic);
63281 0 : _minslptmpmerit_init(&p->tmpmerit, _state, make_automatic);
63282 0 : _rcommstate_init(&p->rphase2state, _state, make_automatic);
63283 0 : }
63284 :
63285 :
63286 0 : void _minslpphase2state_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
63287 : {
63288 0 : minslpphase2state *dst = (minslpphase2state*)_dst;
63289 0 : minslpphase2state *src = (minslpphase2state*)_src;
63290 0 : ae_vector_init_copy(&dst->stepkxn, &src->stepkxn, _state, make_automatic);
63291 0 : ae_vector_init_copy(&dst->stepkxc, &src->stepkxc, _state, make_automatic);
63292 0 : ae_vector_init_copy(&dst->stepkfin, &src->stepkfin, _state, make_automatic);
63293 0 : ae_vector_init_copy(&dst->stepkfic, &src->stepkfic, _state, make_automatic);
63294 0 : ae_matrix_init_copy(&dst->stepkjn, &src->stepkjn, _state, make_automatic);
63295 0 : ae_matrix_init_copy(&dst->stepkjc, &src->stepkjc, _state, make_automatic);
63296 0 : ae_vector_init_copy(&dst->stepklaggrad, &src->stepklaggrad, _state, make_automatic);
63297 0 : ae_vector_init_copy(&dst->stepknlaggrad, &src->stepknlaggrad, _state, make_automatic);
63298 0 : ae_vector_init_copy(&dst->stepknlagmult, &src->stepknlagmult, _state, make_automatic);
63299 0 : ae_vector_init_copy(&dst->meritlagmult, &src->meritlagmult, _state, make_automatic);
63300 0 : _minslptmplagrangian_init_copy(&dst->tmplagrangianfg, &src->tmplagrangianfg, _state, make_automatic);
63301 0 : dst->lastlcerr = src->lastlcerr;
63302 0 : dst->lastlcidx = src->lastlcidx;
63303 0 : dst->lastnlcerr = src->lastnlcerr;
63304 0 : dst->lastnlcidx = src->lastnlcidx;
63305 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
63306 0 : ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic);
63307 0 : _linminstate_init_copy(&dst->mcstate, &src->mcstate, _state, make_automatic);
63308 0 : _minslptmpmerit_init_copy(&dst->tmpmerit, &src->tmpmerit, _state, make_automatic);
63309 0 : _rcommstate_init_copy(&dst->rphase2state, &src->rphase2state, _state, make_automatic);
63310 0 : }
63311 :
63312 :
63313 0 : void _minslpphase2state_clear(void* _p)
63314 : {
63315 0 : minslpphase2state *p = (minslpphase2state*)_p;
63316 0 : ae_touch_ptr((void*)p);
63317 0 : ae_vector_clear(&p->stepkxn);
63318 0 : ae_vector_clear(&p->stepkxc);
63319 0 : ae_vector_clear(&p->stepkfin);
63320 0 : ae_vector_clear(&p->stepkfic);
63321 0 : ae_matrix_clear(&p->stepkjn);
63322 0 : ae_matrix_clear(&p->stepkjc);
63323 0 : ae_vector_clear(&p->stepklaggrad);
63324 0 : ae_vector_clear(&p->stepknlaggrad);
63325 0 : ae_vector_clear(&p->stepknlagmult);
63326 0 : ae_vector_clear(&p->meritlagmult);
63327 0 : _minslptmplagrangian_clear(&p->tmplagrangianfg);
63328 0 : ae_vector_clear(&p->tmp0);
63329 0 : ae_vector_clear(&p->d);
63330 0 : _linminstate_clear(&p->mcstate);
63331 0 : _minslptmpmerit_clear(&p->tmpmerit);
63332 0 : _rcommstate_clear(&p->rphase2state);
63333 0 : }
63334 :
63335 :
63336 0 : void _minslpphase2state_destroy(void* _p)
63337 : {
63338 0 : minslpphase2state *p = (minslpphase2state*)_p;
63339 0 : ae_touch_ptr((void*)p);
63340 0 : ae_vector_destroy(&p->stepkxn);
63341 0 : ae_vector_destroy(&p->stepkxc);
63342 0 : ae_vector_destroy(&p->stepkfin);
63343 0 : ae_vector_destroy(&p->stepkfic);
63344 0 : ae_matrix_destroy(&p->stepkjn);
63345 0 : ae_matrix_destroy(&p->stepkjc);
63346 0 : ae_vector_destroy(&p->stepklaggrad);
63347 0 : ae_vector_destroy(&p->stepknlaggrad);
63348 0 : ae_vector_destroy(&p->stepknlagmult);
63349 0 : ae_vector_destroy(&p->meritlagmult);
63350 0 : _minslptmplagrangian_destroy(&p->tmplagrangianfg);
63351 0 : ae_vector_destroy(&p->tmp0);
63352 0 : ae_vector_destroy(&p->d);
63353 0 : _linminstate_destroy(&p->mcstate);
63354 0 : _minslptmpmerit_destroy(&p->tmpmerit);
63355 0 : _rcommstate_destroy(&p->rphase2state);
63356 0 : }
63357 :
63358 :
63359 0 : void _minslpstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
63360 : {
63361 0 : minslpstate *p = (minslpstate*)_p;
63362 0 : ae_touch_ptr((void*)p);
63363 0 : ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic);
63364 0 : ae_matrix_init(&p->scaledcleic, 0, 0, DT_REAL, _state, make_automatic);
63365 0 : ae_vector_init(&p->lcsrcidx, 0, DT_INT, _state, make_automatic);
63366 0 : ae_vector_init(&p->hasbndl, 0, DT_BOOL, _state, make_automatic);
63367 0 : ae_vector_init(&p->hasbndu, 0, DT_BOOL, _state, make_automatic);
63368 0 : ae_vector_init(&p->scaledbndl, 0, DT_REAL, _state, make_automatic);
63369 0 : ae_vector_init(&p->scaledbndu, 0, DT_REAL, _state, make_automatic);
63370 0 : ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
63371 0 : ae_vector_init(&p->fi, 0, DT_REAL, _state, make_automatic);
63372 0 : ae_matrix_init(&p->j, 0, 0, DT_REAL, _state, make_automatic);
63373 0 : _minslpphase13state_init(&p->state13, _state, make_automatic);
63374 0 : _minslpphase2state_init(&p->state2, _state, make_automatic);
63375 0 : ae_vector_init(&p->step0x, 0, DT_REAL, _state, make_automatic);
63376 0 : ae_vector_init(&p->stepkx, 0, DT_REAL, _state, make_automatic);
63377 0 : ae_vector_init(&p->backupx, 0, DT_REAL, _state, make_automatic);
63378 0 : ae_vector_init(&p->step0fi, 0, DT_REAL, _state, make_automatic);
63379 0 : ae_vector_init(&p->stepkfi, 0, DT_REAL, _state, make_automatic);
63380 0 : ae_vector_init(&p->backupfi, 0, DT_REAL, _state, make_automatic);
63381 0 : ae_matrix_init(&p->step0j, 0, 0, DT_REAL, _state, make_automatic);
63382 0 : ae_matrix_init(&p->stepkj, 0, 0, DT_REAL, _state, make_automatic);
63383 0 : ae_matrix_init(&p->backupj, 0, 0, DT_REAL, _state, make_automatic);
63384 0 : ae_vector_init(&p->meritlagmult, 0, DT_REAL, _state, make_automatic);
63385 0 : ae_vector_init(&p->dummylagmult, 0, DT_REAL, _state, make_automatic);
63386 0 : ae_vector_init(&p->fscales, 0, DT_REAL, _state, make_automatic);
63387 0 : ae_vector_init(&p->meritfunctionhistory, 0, DT_REAL, _state, make_automatic);
63388 0 : _minslpsubsolver_init(&p->subsolver, _state, make_automatic);
63389 0 : _minslptmpmerit_init(&p->tmpmerit, _state, make_automatic);
63390 0 : _rcommstate_init(&p->rstate, _state, make_automatic);
63391 0 : }
63392 :
63393 :
63394 0 : void _minslpstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
63395 : {
63396 0 : minslpstate *dst = (minslpstate*)_dst;
63397 0 : minslpstate *src = (minslpstate*)_src;
63398 0 : dst->n = src->n;
63399 0 : dst->nec = src->nec;
63400 0 : dst->nic = src->nic;
63401 0 : dst->nlec = src->nlec;
63402 0 : dst->nlic = src->nlic;
63403 0 : ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic);
63404 0 : ae_matrix_init_copy(&dst->scaledcleic, &src->scaledcleic, _state, make_automatic);
63405 0 : ae_vector_init_copy(&dst->lcsrcidx, &src->lcsrcidx, _state, make_automatic);
63406 0 : ae_vector_init_copy(&dst->hasbndl, &src->hasbndl, _state, make_automatic);
63407 0 : ae_vector_init_copy(&dst->hasbndu, &src->hasbndu, _state, make_automatic);
63408 0 : ae_vector_init_copy(&dst->scaledbndl, &src->scaledbndl, _state, make_automatic);
63409 0 : ae_vector_init_copy(&dst->scaledbndu, &src->scaledbndu, _state, make_automatic);
63410 0 : dst->epsx = src->epsx;
63411 0 : dst->maxits = src->maxits;
63412 0 : dst->hessiantype = src->hessiantype;
63413 0 : ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
63414 0 : ae_vector_init_copy(&dst->fi, &src->fi, _state, make_automatic);
63415 0 : ae_matrix_init_copy(&dst->j, &src->j, _state, make_automatic);
63416 0 : dst->f = src->f;
63417 0 : dst->needfij = src->needfij;
63418 0 : dst->xupdated = src->xupdated;
63419 0 : _minslpphase13state_init_copy(&dst->state13, &src->state13, _state, make_automatic);
63420 0 : _minslpphase2state_init_copy(&dst->state2, &src->state2, _state, make_automatic);
63421 0 : dst->trustrad = src->trustrad;
63422 0 : dst->lpfailurecnt = src->lpfailurecnt;
63423 0 : dst->fstagnationcnt = src->fstagnationcnt;
63424 0 : ae_vector_init_copy(&dst->step0x, &src->step0x, _state, make_automatic);
63425 0 : ae_vector_init_copy(&dst->stepkx, &src->stepkx, _state, make_automatic);
63426 0 : ae_vector_init_copy(&dst->backupx, &src->backupx, _state, make_automatic);
63427 0 : ae_vector_init_copy(&dst->step0fi, &src->step0fi, _state, make_automatic);
63428 0 : ae_vector_init_copy(&dst->stepkfi, &src->stepkfi, _state, make_automatic);
63429 0 : ae_vector_init_copy(&dst->backupfi, &src->backupfi, _state, make_automatic);
63430 0 : ae_matrix_init_copy(&dst->step0j, &src->step0j, _state, make_automatic);
63431 0 : ae_matrix_init_copy(&dst->stepkj, &src->stepkj, _state, make_automatic);
63432 0 : ae_matrix_init_copy(&dst->backupj, &src->backupj, _state, make_automatic);
63433 0 : ae_vector_init_copy(&dst->meritlagmult, &src->meritlagmult, _state, make_automatic);
63434 0 : ae_vector_init_copy(&dst->dummylagmult, &src->dummylagmult, _state, make_automatic);
63435 0 : ae_vector_init_copy(&dst->fscales, &src->fscales, _state, make_automatic);
63436 0 : ae_vector_init_copy(&dst->meritfunctionhistory, &src->meritfunctionhistory, _state, make_automatic);
63437 0 : dst->historylen = src->historylen;
63438 0 : _minslpsubsolver_init_copy(&dst->subsolver, &src->subsolver, _state, make_automatic);
63439 0 : _minslptmpmerit_init_copy(&dst->tmpmerit, &src->tmpmerit, _state, make_automatic);
63440 0 : dst->repsimplexiterations = src->repsimplexiterations;
63441 0 : dst->repsimplexiterations1 = src->repsimplexiterations1;
63442 0 : dst->repsimplexiterations2 = src->repsimplexiterations2;
63443 0 : dst->repsimplexiterations3 = src->repsimplexiterations3;
63444 0 : dst->repinneriterationscount = src->repinneriterationscount;
63445 0 : dst->repouteriterationscount = src->repouteriterationscount;
63446 0 : dst->repterminationtype = src->repterminationtype;
63447 0 : dst->repbcerr = src->repbcerr;
63448 0 : dst->repbcidx = src->repbcidx;
63449 0 : dst->replcerr = src->replcerr;
63450 0 : dst->replcidx = src->replcidx;
63451 0 : dst->repnlcerr = src->repnlcerr;
63452 0 : dst->repnlcidx = src->repnlcidx;
63453 0 : _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic);
63454 0 : }
63455 :
63456 :
63457 0 : void _minslpstate_clear(void* _p)
63458 : {
63459 0 : minslpstate *p = (minslpstate*)_p;
63460 0 : ae_touch_ptr((void*)p);
63461 0 : ae_vector_clear(&p->s);
63462 0 : ae_matrix_clear(&p->scaledcleic);
63463 0 : ae_vector_clear(&p->lcsrcidx);
63464 0 : ae_vector_clear(&p->hasbndl);
63465 0 : ae_vector_clear(&p->hasbndu);
63466 0 : ae_vector_clear(&p->scaledbndl);
63467 0 : ae_vector_clear(&p->scaledbndu);
63468 0 : ae_vector_clear(&p->x);
63469 0 : ae_vector_clear(&p->fi);
63470 0 : ae_matrix_clear(&p->j);
63471 0 : _minslpphase13state_clear(&p->state13);
63472 0 : _minslpphase2state_clear(&p->state2);
63473 0 : ae_vector_clear(&p->step0x);
63474 0 : ae_vector_clear(&p->stepkx);
63475 0 : ae_vector_clear(&p->backupx);
63476 0 : ae_vector_clear(&p->step0fi);
63477 0 : ae_vector_clear(&p->stepkfi);
63478 0 : ae_vector_clear(&p->backupfi);
63479 0 : ae_matrix_clear(&p->step0j);
63480 0 : ae_matrix_clear(&p->stepkj);
63481 0 : ae_matrix_clear(&p->backupj);
63482 0 : ae_vector_clear(&p->meritlagmult);
63483 0 : ae_vector_clear(&p->dummylagmult);
63484 0 : ae_vector_clear(&p->fscales);
63485 0 : ae_vector_clear(&p->meritfunctionhistory);
63486 0 : _minslpsubsolver_clear(&p->subsolver);
63487 0 : _minslptmpmerit_clear(&p->tmpmerit);
63488 0 : _rcommstate_clear(&p->rstate);
63489 0 : }
63490 :
63491 :
63492 0 : void _minslpstate_destroy(void* _p)
63493 : {
63494 0 : minslpstate *p = (minslpstate*)_p;
63495 0 : ae_touch_ptr((void*)p);
63496 0 : ae_vector_destroy(&p->s);
63497 0 : ae_matrix_destroy(&p->scaledcleic);
63498 0 : ae_vector_destroy(&p->lcsrcidx);
63499 0 : ae_vector_destroy(&p->hasbndl);
63500 0 : ae_vector_destroy(&p->hasbndu);
63501 0 : ae_vector_destroy(&p->scaledbndl);
63502 0 : ae_vector_destroy(&p->scaledbndu);
63503 0 : ae_vector_destroy(&p->x);
63504 0 : ae_vector_destroy(&p->fi);
63505 0 : ae_matrix_destroy(&p->j);
63506 0 : _minslpphase13state_destroy(&p->state13);
63507 0 : _minslpphase2state_destroy(&p->state2);
63508 0 : ae_vector_destroy(&p->step0x);
63509 0 : ae_vector_destroy(&p->stepkx);
63510 0 : ae_vector_destroy(&p->backupx);
63511 0 : ae_vector_destroy(&p->step0fi);
63512 0 : ae_vector_destroy(&p->stepkfi);
63513 0 : ae_vector_destroy(&p->backupfi);
63514 0 : ae_matrix_destroy(&p->step0j);
63515 0 : ae_matrix_destroy(&p->stepkj);
63516 0 : ae_matrix_destroy(&p->backupj);
63517 0 : ae_vector_destroy(&p->meritlagmult);
63518 0 : ae_vector_destroy(&p->dummylagmult);
63519 0 : ae_vector_destroy(&p->fscales);
63520 0 : ae_vector_destroy(&p->meritfunctionhistory);
63521 0 : _minslpsubsolver_destroy(&p->subsolver);
63522 0 : _minslptmpmerit_destroy(&p->tmpmerit);
63523 0 : _rcommstate_destroy(&p->rstate);
63524 0 : }
63525 :
63526 :
63527 : #endif
63528 : #if defined(AE_COMPILE_MINNLC) || !defined(AE_PARTIAL_BUILD)
63529 :
63530 :
63531 : /*************************************************************************
63532 : NONLINEARLY CONSTRAINED OPTIMIZATION
63533 : WITH PRECONDITIONED AUGMENTED LAGRANGIAN ALGORITHM
63534 :
63535 : DESCRIPTION:
63536 : The subroutine minimizes function F(x) of N arguments subject to any
63537 : combination of:
63538 : * bound constraints
63539 : * linear inequality constraints
63540 : * linear equality constraints
63541 : * nonlinear equality constraints Gi(x)=0
63542 : * nonlinear inequality constraints Hi(x)<=0
63543 :
63544 : REQUIREMENTS:
63545 : * user must provide function value and gradient for F(), H(), G()
63546 : * starting point X0 must be feasible or not too far away from the feasible
63547 : set
63548 : * F(), G(), H() are continuously differentiable on the feasible set and
63549 : its neighborhood
63550 : * nonlinear constraints G() and H() must have non-zero gradient at G(x)=0
63551 : and at H(x)=0. Say, constraint like x^2>=1 is supported, but x^2>=0 is
63552 : NOT supported.
63553 :
63554 : USAGE:
63555 :
63556 : Constrained optimization if far more complex than the unconstrained one.
63557 : Nonlinearly constrained optimization is one of the most esoteric numerical
63558 : procedures.
63559 :
63560 : Here we give very brief outline of the MinNLC optimizer. We strongly
63561 : recommend you to study examples in the ALGLIB Reference Manual and to read
63562 : ALGLIB User Guide on optimization, which is available at
63563 : http://www.alglib.net/optimization/
63564 :
63565 : 1. User initializes algorithm state with MinNLCCreate() call and chooses
63566 : what NLC solver to use. There is some solver which is used by default,
63567 : with default settings, but you should NOT rely on default choice. It
63568 : may change in future releases of ALGLIB without notice, and no one can
63569 : guarantee that new solver will be able to solve your problem with
63570 : default settings.
63571 :
63572 : From the other side, if you choose solver explicitly, you can be pretty
63573 : sure that it will work with new ALGLIB releases.
63574 :
63575 : In the current release following solvers can be used:
63576 : * SQP solver, recommended for medium-scale problems (less than thousand
63577 : of variables) with hard-to-evaluate target functions. Requires less
63578 : function evaluations than other solvers but each step involves
63579 : solution of QP subproblem, so running time may be higher than that of
63580 : AUL (another recommended option). Activated with minnlcsetalgosqp()
63581 : function.
63582 : * AUL solver with dense preconditioner, recommended for large-scale
63583 : problems or for problems with cheap target function. Needs more
63584 : function evaluations that SQP (about 5x-10x times more), but its
63585 : iterations are much cheaper that that of SQP. Activated with
63586 : minnlcsetalgoaul() function.
63587 : * SLP solver, successive linear programming. The slowest one, requires
63588 : more target function evaluations that SQP and AUL. However, it is
63589 : somewhat more robust in tricky cases, so it can be used as a backup
63590 : plan. Activated with minnlcsetalgoslp() function.
63591 :
63592 : 2. [optional] user activates OptGuard integrity checker which tries to
63593 : detect possible errors in the user-supplied callbacks:
63594 : * discontinuity/nonsmoothness of the target/nonlinear constraints
63595 : * errors in the analytic gradient provided by user
63596 : This feature is essential for early prototyping stages because it helps
63597 : to catch common coding and problem statement errors.
63598 : OptGuard can be activated with following functions (one per each check
63599 : performed):
63600 : * minnlcoptguardsmoothness()
63601 : * minnlcoptguardgradient()
63602 :
63603 : 3. User adds boundary and/or linear and/or nonlinear constraints by means
63604 : of calling one of the following functions:
63605 : a) minnlcsetbc() for boundary constraints
63606 : b) minnlcsetlc() for linear constraints
63607 : c) minnlcsetnlc() for nonlinear constraints
63608 : You may combine (a), (b) and (c) in one optimization problem.
63609 :
63610 : 4. User sets scale of the variables with minnlcsetscale() function. It is
63611 : VERY important to set scale of the variables, because nonlinearly
63612 : constrained problems are hard to solve when variables are badly scaled.
63613 :
63614 : 5. User sets stopping conditions with minnlcsetcond(). If NLC solver
63615 : uses inner/outer iteration layout, this function sets stopping
63616 : conditions for INNER iterations.
63617 :
63618 : 6. Finally, user calls minnlcoptimize() function which takes algorithm
63619 : state and pointer (delegate, etc.) to callback function which calculates
63620 : F/G/H.
63621 :
63622 : 7. User calls minnlcresults() to get solution; additionally you can
63623 : retrieve OptGuard report with minnlcoptguardresults(), and get detailed
63624 : report about purported errors in the target function with:
63625 : * minnlcoptguardnonc1test0results()
63626 : * minnlcoptguardnonc1test1results()
63627 :
63628 : 8. Optionally user may call minnlcrestartfrom() to solve another problem
63629 : with same N but another starting point. minnlcrestartfrom() allows to
63630 : reuse already initialized structure.
63631 :
63632 :
63633 : INPUT PARAMETERS:
63634 : N - problem dimension, N>0:
63635 : * if given, only leading N elements of X are used
63636 : * if not given, automatically determined from size ofX
63637 : X - starting point, array[N]:
63638 : * it is better to set X to a feasible point
63639 : * but X can be infeasible, in which case algorithm will try
63640 : to find feasible point first, using X as initial
63641 : approximation.
63642 :
63643 : OUTPUT PARAMETERS:
63644 : State - structure stores algorithm state
63645 :
63646 : -- ALGLIB --
63647 : Copyright 06.06.2014 by Bochkanov Sergey
63648 : *************************************************************************/
63649 0 : void minnlccreate(ae_int_t n,
63650 : /* Real */ ae_vector* x,
63651 : minnlcstate* state,
63652 : ae_state *_state)
63653 : {
63654 :
63655 0 : _minnlcstate_clear(state);
63656 :
63657 0 : ae_assert(n>=1, "MinNLCCreate: N<1", _state);
63658 0 : ae_assert(x->cnt>=n, "MinNLCCreate: Length(X)<N", _state);
63659 0 : ae_assert(isfinitevector(x, n, _state), "MinNLCCreate: X contains infinite or NaN values", _state);
63660 0 : minnlc_minnlcinitinternal(n, x, 0.0, state, _state);
63661 0 : }
63662 :
63663 :
63664 : /*************************************************************************
63665 : This subroutine is a finite difference variant of MinNLCCreate(). It uses
63666 : finite differences in order to differentiate target function.
63667 :
63668 : Description below contains information which is specific to this function
63669 : only. We recommend to read comments on MinNLCCreate() in order to get more
63670 : information about creation of NLC optimizer.
63671 :
63672 : INPUT PARAMETERS:
63673 : N - problem dimension, N>0:
63674 : * if given, only leading N elements of X are used
63675 : * if not given, automatically determined from size ofX
63676 : X - starting point, array[N]:
63677 : * it is better to set X to a feasible point
63678 : * but X can be infeasible, in which case algorithm will try
63679 : to find feasible point first, using X as initial
63680 : approximation.
63681 : DiffStep- differentiation step, >0
63682 :
63683 : OUTPUT PARAMETERS:
63684 : State - structure stores algorithm state
63685 :
63686 : NOTES:
63687 : 1. algorithm uses 4-point central formula for differentiation.
63688 : 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
63689 : S[] is scaling vector which can be set by MinNLCSetScale() call.
63690 : 3. we recommend you to use moderate values of differentiation step. Too
63691 : large step will result in too large TRUNCATION errors, while too small
63692 : step will result in too large NUMERICAL errors. 1.0E-4 can be good
63693 : value to start from.
63694 : 4. Numerical differentiation is very inefficient - one gradient
63695 : calculation needs 4*N function evaluations. This function will work for
63696 : any N - either small (1...10), moderate (10...100) or large (100...).
63697 : However, performance penalty will be too severe for any N's except for
63698 : small ones.
63699 : We should also say that code which relies on numerical differentiation
63700 : is less robust and precise. Imprecise gradient may slow down
63701 : convergence, especially on highly nonlinear problems.
63702 : Thus we recommend to use this function for fast prototyping on small-
63703 : dimensional problems only, and to implement analytical gradient as soon
63704 : as possible.
63705 :
63706 : -- ALGLIB --
63707 : Copyright 06.06.2014 by Bochkanov Sergey
63708 : *************************************************************************/
63709 0 : void minnlccreatef(ae_int_t n,
63710 : /* Real */ ae_vector* x,
63711 : double diffstep,
63712 : minnlcstate* state,
63713 : ae_state *_state)
63714 : {
63715 :
63716 0 : _minnlcstate_clear(state);
63717 :
63718 0 : ae_assert(n>=1, "MinNLCCreateF: N<1", _state);
63719 0 : ae_assert(x->cnt>=n, "MinNLCCreateF: Length(X)<N", _state);
63720 0 : ae_assert(isfinitevector(x, n, _state), "MinNLCCreateF: X contains infinite or NaN values", _state);
63721 0 : ae_assert(ae_isfinite(diffstep, _state), "MinNLCCreateF: DiffStep is infinite or NaN!", _state);
63722 0 : ae_assert(ae_fp_greater(diffstep,(double)(0)), "MinNLCCreateF: DiffStep is non-positive!", _state);
63723 0 : minnlc_minnlcinitinternal(n, x, diffstep, state, _state);
63724 0 : }
63725 :
63726 :
63727 : /*************************************************************************
63728 : This function sets boundary constraints for NLC optimizer.
63729 :
63730 : Boundary constraints are inactive by default (after initial creation).
63731 : They are preserved after algorithm restart with MinNLCRestartFrom().
63732 :
63733 : You may combine boundary constraints with general linear ones - and with
63734 : nonlinear ones! Boundary constraints are handled more efficiently than
63735 : other types. Thus, if your problem has mixed constraints, you may
63736 : explicitly specify some of them as boundary and save some time/space.
63737 :
63738 : INPUT PARAMETERS:
63739 : State - structure stores algorithm state
63740 : BndL - lower bounds, array[N].
63741 : If some (all) variables are unbounded, you may specify
63742 : very small number or -INF.
63743 : BndU - upper bounds, array[N].
63744 : If some (all) variables are unbounded, you may specify
63745 : very large number or +INF.
63746 :
63747 : NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th
63748 : variable will be "frozen" at X[i]=BndL[i]=BndU[i].
63749 :
63750 : NOTE 2: when you solve your problem with augmented Lagrangian solver,
63751 : boundary constraints are satisfied only approximately! It is
63752 : possible that algorithm will evaluate function outside of
63753 : feasible area!
63754 :
63755 : -- ALGLIB --
63756 : Copyright 06.06.2014 by Bochkanov Sergey
63757 : *************************************************************************/
63758 0 : void minnlcsetbc(minnlcstate* state,
63759 : /* Real */ ae_vector* bndl,
63760 : /* Real */ ae_vector* bndu,
63761 : ae_state *_state)
63762 : {
63763 : ae_int_t i;
63764 : ae_int_t n;
63765 :
63766 :
63767 0 : n = state->n;
63768 0 : ae_assert(bndl->cnt>=n, "MinNLCSetBC: Length(BndL)<N", _state);
63769 0 : ae_assert(bndu->cnt>=n, "MinNLCSetBC: Length(BndU)<N", _state);
63770 0 : for(i=0; i<=n-1; i++)
63771 : {
63772 0 : ae_assert(ae_isfinite(bndl->ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "MinNLCSetBC: BndL contains NAN or +INF", _state);
63773 0 : ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "MinNLCSetBC: BndL contains NAN or -INF", _state);
63774 0 : state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i];
63775 0 : state->hasbndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state);
63776 0 : state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i];
63777 0 : state->hasbndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state);
63778 : }
63779 0 : }
63780 :
63781 :
63782 : /*************************************************************************
63783 : This function sets linear constraints for MinNLC optimizer.
63784 :
63785 : Linear constraints are inactive by default (after initial creation). They
63786 : are preserved after algorithm restart with MinNLCRestartFrom().
63787 :
63788 : You may combine linear constraints with boundary ones - and with nonlinear
63789 : ones! If your problem has mixed constraints, you may explicitly specify
63790 : some of them as linear. It may help optimizer to handle them more
63791 : efficiently.
63792 :
63793 : INPUT PARAMETERS:
63794 : State - structure previously allocated with MinNLCCreate call.
63795 : C - linear constraints, array[K,N+1].
63796 : Each row of C represents one constraint, either equality
63797 : or inequality (see below):
63798 : * first N elements correspond to coefficients,
63799 : * last element corresponds to the right part.
63800 : All elements of C (including right part) must be finite.
63801 : CT - type of constraints, array[K]:
63802 : * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
63803 : * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
63804 : * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
63805 : K - number of equality/inequality constraints, K>=0:
63806 : * if given, only leading K elements of C/CT are used
63807 : * if not given, automatically determined from sizes of C/CT
63808 :
63809 : NOTE 1: when you solve your problem with augmented Lagrangian solver,
63810 : linear constraints are satisfied only approximately! It is
63811 : possible that algorithm will evaluate function outside of
63812 : feasible area!
63813 :
63814 : -- ALGLIB --
63815 : Copyright 06.06.2014 by Bochkanov Sergey
63816 : *************************************************************************/
63817 0 : void minnlcsetlc(minnlcstate* state,
63818 : /* Real */ ae_matrix* c,
63819 : /* Integer */ ae_vector* ct,
63820 : ae_int_t k,
63821 : ae_state *_state)
63822 : {
63823 : ae_int_t n;
63824 : ae_int_t i;
63825 :
63826 :
63827 0 : n = state->n;
63828 :
63829 : /*
63830 : * First, check for errors in the inputs
63831 : */
63832 0 : ae_assert(k>=0, "MinNLCSetLC: K<0", _state);
63833 0 : ae_assert(c->cols>=n+1||k==0, "MinNLCSetLC: Cols(C)<N+1", _state);
63834 0 : ae_assert(c->rows>=k, "MinNLCSetLC: Rows(C)<K", _state);
63835 0 : ae_assert(ct->cnt>=k, "MinNLCSetLC: Length(CT)<K", _state);
63836 0 : ae_assert(apservisfinitematrix(c, k, n+1, _state), "MinNLCSetLC: C contains infinite or NaN values!", _state);
63837 :
63838 : /*
63839 : * Handle zero K
63840 : */
63841 0 : if( k==0 )
63842 : {
63843 0 : state->nec = 0;
63844 0 : state->nic = 0;
63845 0 : return;
63846 : }
63847 :
63848 : /*
63849 : * Equality constraints are stored first, in the upper
63850 : * NEC rows of State.CLEIC matrix. Inequality constraints
63851 : * are stored in the next NIC rows.
63852 : *
63853 : * NOTE: we convert inequality constraints to the form
63854 : * A*x<=b before copying them.
63855 : */
63856 0 : rmatrixsetlengthatleast(&state->cleic, k, n+1, _state);
63857 0 : ivectorsetlengthatleast(&state->lcsrcidx, k, _state);
63858 0 : state->nec = 0;
63859 0 : state->nic = 0;
63860 0 : for(i=0; i<=k-1; i++)
63861 : {
63862 0 : if( ct->ptr.p_int[i]==0 )
63863 : {
63864 0 : ae_v_move(&state->cleic.ptr.pp_double[state->nec][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n));
63865 0 : state->lcsrcidx.ptr.p_int[state->nec] = i;
63866 0 : state->nec = state->nec+1;
63867 : }
63868 : }
63869 0 : for(i=0; i<=k-1; i++)
63870 : {
63871 0 : if( ct->ptr.p_int[i]!=0 )
63872 : {
63873 0 : if( ct->ptr.p_int[i]>0 )
63874 : {
63875 0 : 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));
63876 : }
63877 : else
63878 : {
63879 0 : 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));
63880 : }
63881 0 : state->lcsrcidx.ptr.p_int[state->nec+state->nic] = i;
63882 0 : state->nic = state->nic+1;
63883 : }
63884 : }
63885 : }
63886 :
63887 :
63888 : /*************************************************************************
63889 : This function sets nonlinear constraints for MinNLC optimizer.
63890 :
63891 : In fact, this function sets NUMBER of nonlinear constraints. Constraints
63892 : itself (constraint functions) are passed to MinNLCOptimize() method. This
63893 : method requires user-defined vector function F[] and its Jacobian J[],
63894 : where:
63895 : * first component of F[] and first row of Jacobian J[] corresponds to
63896 : function being minimized
63897 : * next NLEC components of F[] (and rows of J) correspond to nonlinear
63898 : equality constraints G_i(x)=0
63899 : * next NLIC components of F[] (and rows of J) correspond to nonlinear
63900 : inequality constraints H_i(x)<=0
63901 :
63902 : NOTE: you may combine nonlinear constraints with linear/boundary ones. If
63903 : your problem has mixed constraints, you may explicitly specify some
63904 : of them as linear ones. It may help optimizer to handle them more
63905 : efficiently.
63906 :
63907 : INPUT PARAMETERS:
63908 : State - structure previously allocated with MinNLCCreate call.
63909 : NLEC - number of Non-Linear Equality Constraints (NLEC), >=0
63910 : NLIC - number of Non-Linear Inquality Constraints (NLIC), >=0
63911 :
63912 : NOTE 1: when you solve your problem with augmented Lagrangian solver,
63913 : nonlinear constraints are satisfied only approximately! It is
63914 : possible that algorithm will evaluate function outside of
63915 : feasible area!
63916 :
63917 : NOTE 2: algorithm scales variables according to scale specified by
63918 : MinNLCSetScale() function, so it can handle problems with badly
63919 : scaled variables (as long as we KNOW their scales).
63920 :
63921 : However, there is no way to automatically scale nonlinear
63922 : constraints Gi(x) and Hi(x). Inappropriate scaling of Gi/Hi may
63923 : ruin convergence. Solving problem with constraint "1000*G0(x)=0"
63924 : is NOT same as solving it with constraint "0.001*G0(x)=0".
63925 :
63926 : It means that YOU are the one who is responsible for correct
63927 : scaling of nonlinear constraints Gi(x) and Hi(x). We recommend you
63928 : to scale nonlinear constraints in such way that I-th component of
63929 : dG/dX (or dH/dx) has approximately unit magnitude (for problems
63930 : with unit scale) or has magnitude approximately equal to 1/S[i]
63931 : (where S is a scale set by MinNLCSetScale() function).
63932 :
63933 :
63934 : -- ALGLIB --
63935 : Copyright 06.06.2014 by Bochkanov Sergey
63936 : *************************************************************************/
63937 0 : void minnlcsetnlc(minnlcstate* state,
63938 : ae_int_t nlec,
63939 : ae_int_t nlic,
63940 : ae_state *_state)
63941 : {
63942 :
63943 :
63944 0 : ae_assert(nlec>=0, "MinNLCSetNLC: NLEC<0", _state);
63945 0 : ae_assert(nlic>=0, "MinNLCSetNLC: NLIC<0", _state);
63946 0 : state->ng = nlec;
63947 0 : state->nh = nlic;
63948 0 : ae_vector_set_length(&state->fi, 1+state->ng+state->nh, _state);
63949 0 : ae_matrix_set_length(&state->j, 1+state->ng+state->nh, state->n, _state);
63950 0 : }
63951 :
63952 :
63953 : /*************************************************************************
63954 : This function sets stopping conditions for inner iterations of optimizer.
63955 :
63956 : INPUT PARAMETERS:
63957 : State - structure which stores algorithm state
63958 : EpsX - >=0
63959 : The subroutine finishes its work if on k+1-th iteration
63960 : the condition |v|<=EpsX is fulfilled, where:
63961 : * |.| means Euclidian norm
63962 : * v - scaled step vector, v[i]=dx[i]/s[i]
63963 : * dx - step vector, dx=X(k+1)-X(k)
63964 : * s - scaling coefficients set by MinNLCSetScale()
63965 : MaxIts - maximum number of iterations. If MaxIts=0, the number of
63966 : iterations is unlimited.
63967 :
63968 : Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic
63969 : selection of the stopping condition.
63970 :
63971 : -- ALGLIB --
63972 : Copyright 06.06.2014 by Bochkanov Sergey
63973 : *************************************************************************/
63974 0 : void minnlcsetcond(minnlcstate* state,
63975 : double epsx,
63976 : ae_int_t maxits,
63977 : ae_state *_state)
63978 : {
63979 :
63980 :
63981 0 : ae_assert(ae_isfinite(epsx, _state), "MinNLCSetCond: EpsX is not finite number", _state);
63982 0 : ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "MinNLCSetCond: negative EpsX", _state);
63983 0 : ae_assert(maxits>=0, "MinNLCSetCond: negative MaxIts!", _state);
63984 0 : if( ae_fp_eq(epsx,(double)(0))&&maxits==0 )
63985 : {
63986 0 : epsx = 1.0E-8;
63987 : }
63988 0 : state->epsx = epsx;
63989 0 : state->maxits = maxits;
63990 0 : }
63991 :
63992 :
63993 : /*************************************************************************
63994 : This function sets scaling coefficients for NLC optimizer.
63995 :
63996 : ALGLIB optimizers use scaling matrices to test stopping conditions (step
63997 : size and gradient are scaled before comparison with tolerances). Scale of
63998 : the I-th variable is a translation invariant measure of:
63999 : a) "how large" the variable is
64000 : b) how large the step should be to make significant changes in the function
64001 :
64002 : Scaling is also used by finite difference variant of the optimizer - step
64003 : along I-th axis is equal to DiffStep*S[I].
64004 :
64005 : INPUT PARAMETERS:
64006 : State - structure stores algorithm state
64007 : S - array[N], non-zero scaling coefficients
64008 : S[i] may be negative, sign doesn't matter.
64009 :
64010 : -- ALGLIB --
64011 : Copyright 06.06.2014 by Bochkanov Sergey
64012 : *************************************************************************/
64013 0 : void minnlcsetscale(minnlcstate* state,
64014 : /* Real */ ae_vector* s,
64015 : ae_state *_state)
64016 : {
64017 : ae_int_t i;
64018 :
64019 :
64020 0 : ae_assert(s->cnt>=state->n, "MinNLCSetScale: Length(S)<N", _state);
64021 0 : for(i=0; i<=state->n-1; i++)
64022 : {
64023 0 : ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "MinNLCSetScale: S contains infinite or NAN elements", _state);
64024 0 : ae_assert(ae_fp_neq(s->ptr.p_double[i],(double)(0)), "MinNLCSetScale: S contains zero elements", _state);
64025 0 : state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state);
64026 : }
64027 0 : }
64028 :
64029 :
64030 : /*************************************************************************
64031 : This function sets preconditioner to "inexact LBFGS-based" mode.
64032 :
64033 : Preconditioning is very important for convergence of Augmented Lagrangian
64034 : algorithm because presence of penalty term makes problem ill-conditioned.
64035 : Difference between performance of preconditioned and unpreconditioned
64036 : methods can be as large as 100x!
64037 :
64038 : MinNLC optimizer may use following preconditioners, each with its own
64039 : benefits and drawbacks:
64040 : a) inexact LBFGS-based, with O(N*K) evaluation time
64041 : b) exact low rank one, with O(N*K^2) evaluation time
64042 : c) exact robust one, with O(N^3+K*N^2) evaluation time
64043 : where K is a total number of general linear and nonlinear constraints (box
64044 : ones are not counted).
64045 :
64046 : Inexact LBFGS-based preconditioner uses L-BFGS formula combined with
64047 : orthogonality assumption to perform very fast updates. For a N-dimensional
64048 : problem with K general linear or nonlinear constraints (boundary ones are
64049 : not counted) it has O(N*K) cost per iteration. This preconditioner has
64050 : best quality (less iterations) when general linear and nonlinear
64051 : constraints are orthogonal to each other (orthogonality with respect to
64052 : boundary constraints is not required). Number of iterations increases when
64053 : constraints are non-orthogonal, because algorithm assumes orthogonality,
64054 : but still it is better than no preconditioner at all.
64055 :
64056 : INPUT PARAMETERS:
64057 : State - structure stores algorithm state
64058 :
64059 : -- ALGLIB --
64060 : Copyright 26.09.2014 by Bochkanov Sergey
64061 : *************************************************************************/
64062 0 : void minnlcsetprecinexact(minnlcstate* state, ae_state *_state)
64063 : {
64064 :
64065 :
64066 0 : state->updatefreq = 0;
64067 0 : state->prectype = 1;
64068 0 : }
64069 :
64070 :
64071 : /*************************************************************************
64072 : This function sets preconditioner to "exact low rank" mode.
64073 :
64074 : Preconditioning is very important for convergence of Augmented Lagrangian
64075 : algorithm because presence of penalty term makes problem ill-conditioned.
64076 : Difference between performance of preconditioned and unpreconditioned
64077 : methods can be as large as 100x!
64078 :
64079 : MinNLC optimizer may use following preconditioners, each with its own
64080 : benefits and drawbacks:
64081 : a) inexact LBFGS-based, with O(N*K) evaluation time
64082 : b) exact low rank one, with O(N*K^2) evaluation time
64083 : c) exact robust one, with O(N^3+K*N^2) evaluation time
64084 : where K is a total number of general linear and nonlinear constraints (box
64085 : ones are not counted).
64086 :
64087 : It also provides special unpreconditioned mode of operation which can be
64088 : used for test purposes. Comments below discuss low rank preconditioner.
64089 :
64090 : Exact low-rank preconditioner uses Woodbury matrix identity to build
64091 : quadratic model of the penalized function. It has following features:
64092 : * no special assumptions about orthogonality of constraints
64093 : * preconditioner evaluation is optimized for K<<N. Its cost is O(N*K^2),
64094 : so it may become prohibitively slow for K>=N.
64095 : * finally, stability of the process is guaranteed only for K<<N. Woodbury
64096 : update often fail for K>=N due to degeneracy of intermediate matrices.
64097 : That's why we recommend to use "exact robust" preconditioner for such
64098 : cases.
64099 :
64100 : RECOMMENDATIONS
64101 :
64102 : We recommend to choose between "exact low rank" and "exact robust"
64103 : preconditioners, with "low rank" version being chosen when you know in
64104 : advance that total count of non-box constraints won't exceed N, and "robust"
64105 : version being chosen when you need bulletproof solution.
64106 :
64107 : INPUT PARAMETERS:
64108 : State - structure stores algorithm state
64109 : UpdateFreq- update frequency. Preconditioner is rebuilt after every
64110 : UpdateFreq iterations. Recommended value: 10 or higher.
64111 : Zero value means that good default value will be used.
64112 :
64113 : -- ALGLIB --
64114 : Copyright 26.09.2014 by Bochkanov Sergey
64115 : *************************************************************************/
64116 0 : void minnlcsetprecexactlowrank(minnlcstate* state,
64117 : ae_int_t updatefreq,
64118 : ae_state *_state)
64119 : {
64120 :
64121 :
64122 0 : ae_assert(updatefreq>=0, "MinNLCSetPrecExactLowRank: UpdateFreq<0", _state);
64123 0 : if( updatefreq==0 )
64124 : {
64125 0 : updatefreq = 10;
64126 : }
64127 0 : state->prectype = 2;
64128 0 : state->updatefreq = updatefreq;
64129 0 : }
64130 :
64131 :
64132 : /*************************************************************************
64133 : This function sets preconditioner to "exact robust" mode.
64134 :
64135 : Preconditioning is very important for convergence of Augmented Lagrangian
64136 : algorithm because presence of penalty term makes problem ill-conditioned.
64137 : Difference between performance of preconditioned and unpreconditioned
64138 : methods can be as large as 100x!
64139 :
64140 : MinNLC optimizer may use following preconditioners, each with its own
64141 : benefits and drawbacks:
64142 : a) inexact LBFGS-based, with O(N*K) evaluation time
64143 : b) exact low rank one, with O(N*K^2) evaluation time
64144 : c) exact robust one, with O(N^3+K*N^2) evaluation time
64145 : where K is a total number of general linear and nonlinear constraints (box
64146 : ones are not counted).
64147 :
64148 : It also provides special unpreconditioned mode of operation which can be
64149 : used for test purposes. Comments below discuss robust preconditioner.
64150 :
64151 : Exact robust preconditioner uses Cholesky decomposition to invert
64152 : approximate Hessian matrix H=D+W'*C*W (where D stands for diagonal terms
64153 : of Hessian, combined result of initial scaling matrix and penalty from box
64154 : constraints; W stands for general linear constraints and linearization of
64155 : nonlinear ones; C stands for diagonal matrix of penalty coefficients).
64156 :
64157 : This preconditioner has following features:
64158 : * no special assumptions about constraint structure
64159 : * preconditioner is optimized for stability; unlike "exact low rank"
64160 : version which fails for K>=N, this one works well for any value of K.
64161 : * the only drawback is that is takes O(N^3+K*N^2) time to build it. No
64162 : economical Woodbury update is applied even when it makes sense, thus
64163 : there are exist situations (K<<N) when "exact low rank" preconditioner
64164 : outperforms this one.
64165 :
64166 : RECOMMENDATIONS
64167 :
64168 : We recommend to choose between "exact low rank" and "exact robust"
64169 : preconditioners, with "low rank" version being chosen when you know in
64170 : advance that total count of non-box constraints won't exceed N, and "robust"
64171 : version being chosen when you need bulletproof solution.
64172 :
64173 : INPUT PARAMETERS:
64174 : State - structure stores algorithm state
64175 : UpdateFreq- update frequency. Preconditioner is rebuilt after every
64176 : UpdateFreq iterations. Recommended value: 10 or higher.
64177 : Zero value means that good default value will be used.
64178 :
64179 : -- ALGLIB --
64180 : Copyright 26.09.2014 by Bochkanov Sergey
64181 : *************************************************************************/
64182 0 : void minnlcsetprecexactrobust(minnlcstate* state,
64183 : ae_int_t updatefreq,
64184 : ae_state *_state)
64185 : {
64186 :
64187 :
64188 0 : ae_assert(updatefreq>=0, "MinNLCSetPrecExactLowRank: UpdateFreq<0", _state);
64189 0 : if( updatefreq==0 )
64190 : {
64191 0 : updatefreq = 10;
64192 : }
64193 0 : state->prectype = 3;
64194 0 : state->updatefreq = updatefreq;
64195 0 : }
64196 :
64197 :
64198 : /*************************************************************************
64199 : This function sets preconditioner to "turned off" mode.
64200 :
64201 : Preconditioning is very important for convergence of Augmented Lagrangian
64202 : algorithm because presence of penalty term makes problem ill-conditioned.
64203 : Difference between performance of preconditioned and unpreconditioned
64204 : methods can be as large as 100x!
64205 :
64206 : MinNLC optimizer may utilize two preconditioners, each with its own
64207 : benefits and drawbacks: a) inexact LBFGS-based, and b) exact low rank one.
64208 : It also provides special unpreconditioned mode of operation which can be
64209 : used for test purposes.
64210 :
64211 : This function activates this test mode. Do not use it in production code
64212 : to solve real-life problems.
64213 :
64214 : INPUT PARAMETERS:
64215 : State - structure stores algorithm state
64216 :
64217 : -- ALGLIB --
64218 : Copyright 26.09.2014 by Bochkanov Sergey
64219 : *************************************************************************/
64220 0 : void minnlcsetprecnone(minnlcstate* state, ae_state *_state)
64221 : {
64222 :
64223 :
64224 0 : state->updatefreq = 0;
64225 0 : state->prectype = 0;
64226 0 : }
64227 :
64228 :
64229 : /*************************************************************************
64230 : This function sets maximum step length (after scaling of step vector with
64231 : respect to variable scales specified by minnlcsetscale() call).
64232 :
64233 : INPUT PARAMETERS:
64234 : State - structure which stores algorithm state
64235 : StpMax - maximum step length, >=0. Set StpMax to 0.0 (default), if
64236 : you don't want to limit step length.
64237 :
64238 : Use this subroutine when you optimize target function which contains exp()
64239 : or other fast growing functions, and optimization algorithm makes too
64240 : large steps which leads to overflow. This function allows us to reject
64241 : steps that are too large (and therefore expose us to the possible
64242 : overflow) without actually calculating function value at the x+stp*d.
64243 :
64244 : NOTE: different solvers employed by MinNLC optimizer use different norms
64245 : for step; AUL solver uses 2-norm, whilst SLP solver uses INF-norm.
64246 :
64247 : -- ALGLIB --
64248 : Copyright 02.04.2010 by Bochkanov Sergey
64249 : *************************************************************************/
64250 0 : void minnlcsetstpmax(minnlcstate* state, double stpmax, ae_state *_state)
64251 : {
64252 :
64253 :
64254 0 : ae_assert(ae_isfinite(stpmax, _state), "MinNLCSetStpMax: StpMax is not finite!", _state);
64255 0 : ae_assert(ae_fp_greater_eq(stpmax,(double)(0)), "MinNLCSetStpMax: StpMax<0!", _state);
64256 0 : state->stpmax = stpmax;
64257 0 : }
64258 :
64259 :
64260 : /*************************************************************************
64261 : This function tells MinNLC unit to use Augmented Lagrangian algorithm
64262 : for nonlinearly constrained optimization. This algorithm is a slight
64263 : modification of one described in "A Modified Barrier-Augmented Lagrangian
64264 : Method for Constrained Minimization (1999)" by D.GOLDFARB, R.POLYAK,
64265 : K. SCHEINBERG, I.YUZEFOVICH.
64266 :
64267 : AUL solver can be significantly faster than SQP on easy problems due to
64268 : cheaper iterations, although it needs more function evaluations.
64269 :
64270 : Augmented Lagrangian algorithm works by converting problem of minimizing
64271 : F(x) subject to equality/inequality constraints to unconstrained problem
64272 : of the form
64273 :
64274 : min[ f(x) +
64275 : + Rho*PENALTY_EQ(x) + SHIFT_EQ(x,Nu1) +
64276 : + Rho*PENALTY_INEQ(x) + SHIFT_INEQ(x,Nu2) ]
64277 :
64278 : where:
64279 : * Rho is a fixed penalization coefficient
64280 : * PENALTY_EQ(x) is a penalty term, which is used to APPROXIMATELY enforce
64281 : equality constraints
64282 : * SHIFT_EQ(x) is a special "shift" term which is used to "fine-tune"
64283 : equality constraints, greatly increasing precision
64284 : * PENALTY_INEQ(x) is a penalty term which is used to approximately enforce
64285 : inequality constraints
64286 : * SHIFT_INEQ(x) is a special "shift" term which is used to "fine-tune"
64287 : inequality constraints, greatly increasing precision
64288 : * Nu1/Nu2 are vectors of Lagrange coefficients which are fine-tuned during
64289 : outer iterations of algorithm
64290 :
64291 : This version of AUL algorithm uses preconditioner, which greatly
64292 : accelerates convergence. Because this algorithm is similar to penalty
64293 : methods, it may perform steps into infeasible area. All kinds of
64294 : constraints (boundary, linear and nonlinear ones) may be violated in
64295 : intermediate points - and in the solution. However, properly configured
64296 : AUL method is significantly better at handling constraints than barrier
64297 : and/or penalty methods.
64298 :
64299 : The very basic outline of algorithm is given below:
64300 : 1) first outer iteration is performed with "default" values of Lagrange
64301 : multipliers Nu1/Nu2. Solution quality is low (candidate point can be
64302 : too far away from true solution; large violation of constraints is
64303 : possible) and is comparable with that of penalty methods.
64304 : 2) subsequent outer iterations refine Lagrange multipliers and improve
64305 : quality of the solution.
64306 :
64307 : INPUT PARAMETERS:
64308 : State - structure which stores algorithm state
64309 : Rho - penalty coefficient, Rho>0:
64310 : * large enough that algorithm converges with desired
64311 : precision. Minimum value is 10*max(S'*diag(H)*S), where
64312 : S is a scale matrix (set by MinNLCSetScale) and H is a
64313 : Hessian of the function being minimized. If you can not
64314 : easily estimate Hessian norm, see our recommendations
64315 : below.
64316 : * not TOO large to prevent ill-conditioning
64317 : * for unit-scale problems (variables and Hessian have unit
64318 : magnitude), Rho=100 or Rho=1000 can be used.
64319 : * it is important to note that Rho is internally multiplied
64320 : by scaling matrix, i.e. optimum value of Rho depends on
64321 : scale of variables specified by MinNLCSetScale().
64322 : ItsCnt - number of outer iterations:
64323 : * ItsCnt=0 means that small number of outer iterations is
64324 : automatically chosen (10 iterations in current version).
64325 : * ItsCnt=1 means that AUL algorithm performs just as usual
64326 : barrier method.
64327 : * ItsCnt>1 means that AUL algorithm performs specified
64328 : number of outer iterations
64329 :
64330 : HOW TO CHOOSE PARAMETERS
64331 :
64332 : Nonlinear optimization is a tricky area and Augmented Lagrangian algorithm
64333 : is sometimes hard to tune. Good values of Rho and ItsCnt are problem-
64334 : specific. In order to help you we prepared following set of
64335 : recommendations:
64336 :
64337 : * for unit-scale problems (variables and Hessian have unit magnitude),
64338 : Rho=100 or Rho=1000 can be used.
64339 :
64340 : * start from some small value of Rho and solve problem with just one
64341 : outer iteration (ItcCnt=1). In this case algorithm behaves like penalty
64342 : method. Increase Rho in 2x or 10x steps until you see that one outer
64343 : iteration returns point which is "rough approximation to solution".
64344 :
64345 : It is very important to have Rho so large that penalty term becomes
64346 : constraining i.e. modified function becomes highly convex in constrained
64347 : directions.
64348 :
64349 : From the other side, too large Rho may prevent you from converging to
64350 : the solution. You can diagnose it by studying number of inner iterations
64351 : performed by algorithm: too few (5-10 on 1000-dimensional problem) or
64352 : too many (orders of magnitude more than dimensionality) usually means
64353 : that Rho is too large.
64354 :
64355 : * with just one outer iteration you usually have low-quality solution.
64356 : Some constraints can be violated with very large margin, while other
64357 : ones (which are NOT violated in the true solution) can push final point
64358 : too far in the inner area of the feasible set.
64359 :
64360 : For example, if you have constraint x0>=0 and true solution x0=1, then
64361 : merely a presence of "x0>=0" will introduce a bias towards larger values
64362 : of x0. Say, algorithm may stop at x0=1.5 instead of 1.0.
64363 :
64364 : * after you found good Rho, you may increase number of outer iterations.
64365 : ItsCnt=10 is a good value. Subsequent outer iteration will refine values
64366 : of Lagrange multipliers. Constraints which were violated will be
64367 : enforced, inactive constraints will be dropped (corresponding multipliers
64368 : will be decreased). Ideally, you should see 10-1000x improvement in
64369 : constraint handling (constraint violation is reduced).
64370 :
64371 : * if you see that algorithm converges to vicinity of solution, but
64372 : additional outer iterations do not refine solution, it may mean that
64373 : algorithm is unstable - it wanders around true solution, but can not
64374 : approach it. Sometimes algorithm may be stabilized by increasing Rho one
64375 : more time, making it 5x or 10x larger.
64376 :
64377 : SCALING OF CONSTRAINTS [IMPORTANT]
64378 :
64379 : AUL optimizer scales variables according to scale specified by
64380 : MinNLCSetScale() function, so it can handle problems with badly scaled
64381 : variables (as long as we KNOW their scales). However, because function
64382 : being optimized is a mix of original function and constraint-dependent
64383 : penalty functions, it is important to rescale both variables AND
64384 : constraints.
64385 :
64386 : Say, if you minimize f(x)=x^2 subject to 1000000*x>=0, then you have
64387 : constraint whose scale is different from that of target function (another
64388 : example is 0.000001*x>=0). It is also possible to have constraints whose
64389 : scales are misaligned: 1000000*x0>=0, 0.000001*x1<=0. Inappropriate
64390 : scaling may ruin convergence because minimizing x^2 subject to x>=0 is NOT
64391 : same as minimizing it subject to 1000000*x>=0.
64392 :
64393 : Because we know coefficients of boundary/linear constraints, we can
64394 : automatically rescale and normalize them. However, there is no way to
64395 : automatically rescale nonlinear constraints Gi(x) and Hi(x) - they are
64396 : black boxes.
64397 :
64398 : It means that YOU are the one who is responsible for correct scaling of
64399 : nonlinear constraints Gi(x) and Hi(x). We recommend you to rescale
64400 : nonlinear constraints in such way that I-th component of dG/dX (or dH/dx)
64401 : has magnitude approximately equal to 1/S[i] (where S is a scale set by
64402 : MinNLCSetScale() function).
64403 :
64404 : WHAT IF IT DOES NOT CONVERGE?
64405 :
64406 : It is possible that AUL algorithm fails to converge to precise values of
64407 : Lagrange multipliers. It stops somewhere around true solution, but candidate
64408 : point is still too far from solution, and some constraints are violated.
64409 : Such kind of failure is specific for Lagrangian algorithms - technically,
64410 : they stop at some point, but this point is not constrained solution.
64411 :
64412 : There are exist several reasons why algorithm may fail to converge:
64413 : a) too loose stopping criteria for inner iteration
64414 : b) degenerate, redundant constraints
64415 : c) target function has unconstrained extremum exactly at the boundary of
64416 : some constraint
64417 : d) numerical noise in the target function
64418 :
64419 : In all these cases algorithm is unstable - each outer iteration results in
64420 : large and almost random step which improves handling of some constraints,
64421 : but violates other ones (ideally outer iterations should form a sequence
64422 : of progressively decreasing steps towards solution).
64423 :
64424 : First reason possible is that too loose stopping criteria for inner
64425 : iteration were specified. Augmented Lagrangian algorithm solves a sequence
64426 : of intermediate problems, and requries each of them to be solved with high
64427 : precision. Insufficient precision results in incorrect update of Lagrange
64428 : multipliers.
64429 :
64430 : Another reason is that you may have specified degenerate constraints: say,
64431 : some constraint was repeated twice. In most cases AUL algorithm gracefully
64432 : handles such situations, but sometimes it may spend too much time figuring
64433 : out subtle degeneracies in constraint matrix.
64434 :
64435 : Third reason is tricky and hard to diagnose. Consider situation when you
64436 : minimize f=x^2 subject to constraint x>=0. Unconstrained extremum is
64437 : located exactly at the boundary of constrained area. In this case
64438 : algorithm will tend to oscillate between negative and positive x. Each
64439 : time it stops at x<0 it "reinforces" constraint x>=0, and each time it is
64440 : bounced to x>0 it "relaxes" constraint (and is attracted to x<0).
64441 :
64442 : Such situation sometimes happens in problems with hidden symetries.
64443 : Algorithm is got caught in a loop with Lagrange multipliers being
64444 : continuously increased/decreased. Luckily, such loop forms after at least
64445 : three iterations, so this problem can be solved by DECREASING number of
64446 : outer iterations down to 1-2 and increasing penalty coefficient Rho as
64447 : much as possible.
64448 :
64449 : Final reason is numerical noise. AUL algorithm is robust against moderate
64450 : noise (more robust than, say, active set methods), but large noise may
64451 : destabilize algorithm.
64452 :
64453 : -- ALGLIB --
64454 : Copyright 06.06.2014 by Bochkanov Sergey
64455 : *************************************************************************/
64456 0 : void minnlcsetalgoaul(minnlcstate* state,
64457 : double rho,
64458 : ae_int_t itscnt,
64459 : ae_state *_state)
64460 : {
64461 :
64462 :
64463 0 : ae_assert(itscnt>=0, "MinNLCSetAlgoAUL: negative ItsCnt", _state);
64464 0 : ae_assert(ae_isfinite(rho, _state), "MinNLCSetAlgoAUL: Rho is not finite", _state);
64465 0 : ae_assert(ae_fp_greater(rho,(double)(0)), "MinNLCSetAlgoAUL: Rho<=0", _state);
64466 0 : if( itscnt==0 )
64467 : {
64468 0 : itscnt = 10;
64469 : }
64470 0 : state->aulitscnt = itscnt;
64471 0 : state->rho = rho;
64472 0 : state->solvertype = 0;
64473 0 : }
64474 :
64475 :
64476 : /*************************************************************************
64477 : This function tells MinNLC optimizer to use SLP (Successive Linear
64478 : Programming) algorithm for nonlinearly constrained optimization. This
64479 : algorithm is a slight modification of one described in "A Linear
64480 : programming-based optimization algorithm for solving nonlinear programming
64481 : problems" (2010) by Claus Still and Tapio Westerlund.
64482 :
64483 : This solver is the slowest one in ALGLIB, it requires more target function
64484 : evaluations that SQP and AUL. However it is somewhat more robust in tricky
64485 : cases, so it can be used as a backup plan. We recommend to use this algo
64486 : when SQP/AUL do not work (does not return the solution you expect). If
64487 : trying different approach gives same results, then MAYBE something is
64488 : wrong with your optimization problem.
64489 :
64490 : Despite its name ("linear" = "first order method") this algorithm performs
64491 : steps similar to that of conjugate gradients method; internally it uses
64492 : orthogonality/conjugacy requirement for subsequent steps which makes it
64493 : closer to second order methods in terms of convergence speed.
64494 :
64495 : Convergence is proved for the following case:
64496 : * function and constraints are continuously differentiable (C1 class)
64497 : * extended Mangasarian–Fromovitz constraint qualification (EMFCQ) holds;
64498 : in the context of this algorithm EMFCQ means that one can, for any
64499 : infeasible point, find a search direction such that the constraint
64500 : infeasibilities are reduced.
64501 :
64502 : This algorithm has following nice properties:
64503 : * no parameters to tune
64504 : * no convexity requirements for target function or constraints
64505 : * initial point can be infeasible
64506 : * algorithm respects box constraints in all intermediate points (it does
64507 : not even evaluate function outside of box constrained area)
64508 : * once linear constraints are enforced, algorithm will not violate them
64509 : * no such guarantees can be provided for nonlinear constraints, but once
64510 : nonlinear constraints are enforced, algorithm will try to respect them
64511 : as much as possible
64512 : * numerical differentiation does not violate box constraints (although
64513 : general linear and nonlinear ones can be violated during differentiation)
64514 : * from our experience, this algorithm is somewhat more robust in really
64515 : difficult cases
64516 :
64517 : INPUT PARAMETERS:
64518 : State - structure which stores algorithm state
64519 :
64520 : ===== TRACING SLP SOLVER =================================================
64521 :
64522 : SLP solver supports advanced tracing capabilities. You can trace algorithm
64523 : output by specifying following trace symbols (case-insensitive) by means
64524 : of trace_file() call:
64525 : * 'SLP' - for basic trace of algorithm steps and decisions. Only
64526 : short scalars (function values and deltas) are printed.
64527 : N-dimensional quantities like search directions are NOT
64528 : printed.
64529 : It also prints OptGuard integrity checker report when
64530 : nonsmoothness of target/constraints is suspected.
64531 : * 'SLP.DETAILED'- for output of points being visited and search directions
64532 : This symbol also implicitly defines 'SLP'. You can
64533 : control output format by additionally specifying:
64534 : * nothing to output in 6-digit exponential format
64535 : * 'PREC.E15' to output in 15-digit exponential format
64536 : * 'PREC.F6' to output in 6-digit fixed-point format
64537 : * 'SLP.PROBING' - to let algorithm insert additional function evaluations
64538 : before line search in order to build human-readable
64539 : chart of the raw Lagrangian (~40 additional function
64540 : evaluations is performed for each line search). This
64541 : symbol also implicitly defines 'SLP'.
64542 : * 'OPTGUARD' - for report of smoothness/continuity violations in target
64543 : and/or constraints. This kind of reporting is included
64544 : in 'SLP', but it comes with lots of additional info. If
64545 : you need just smoothness monitoring, specify this
64546 : setting.
64547 :
64548 : NOTE: this tag merely directs OptGuard output to log
64549 : file. Even if you specify it, you still have to
64550 : configure OptGuard by calling minnlcoptguard...()
64551 : family of functions.
64552 :
64553 : By default trace is disabled and adds no overhead to the optimization
64554 : process. However, specifying any of the symbols adds some formatting and
64555 : output-related overhead. Specifying 'SLP.PROBING' adds even larger
64556 : overhead due to additional function evaluations being performed.
64557 :
64558 : You may specify multiple symbols by separating them with commas:
64559 : >
64560 : > alglib::trace_file("SLP,SLP.PROBING,PREC.F6", "path/to/trace.log")
64561 : >
64562 :
64563 : -- ALGLIB --
64564 : Copyright 02.04.2018 by Bochkanov Sergey
64565 : *************************************************************************/
64566 0 : void minnlcsetalgoslp(minnlcstate* state, ae_state *_state)
64567 : {
64568 :
64569 :
64570 0 : state->solvertype = 1;
64571 0 : }
64572 :
64573 :
64574 : /*************************************************************************
64575 : This function tells MinNLC optimizer to use SQP (Successive Quadratic
64576 : Programming) algorithm for nonlinearly constrained optimization.
64577 :
64578 : This algorithm needs order of magnitude (5x-10x) less function evaluations
64579 : than AUL solver, but has higher overhead because each iteration involves
64580 : solution of quadratic programming problem.
64581 :
64582 : Convergence is proved for the following case:
64583 : * function and constraints are continuously differentiable (C1 class)
64584 :
64585 : This algorithm has following nice properties:
64586 : * no parameters to tune
64587 : * no convexity requirements for target function or constraints
64588 : * initial point can be infeasible
64589 : * algorithm respects box constraints in all intermediate points (it does
64590 : not even evaluate function outside of box constrained area)
64591 : * once linear constraints are enforced, algorithm will not violate them
64592 : * no such guarantees can be provided for nonlinear constraints, but once
64593 : nonlinear constraints are enforced, algorithm will try to respect them
64594 : as much as possible
64595 : * numerical differentiation does not violate box constraints (although
64596 : general linear and nonlinear ones can be violated during differentiation)
64597 :
64598 : We recommend this algorithm as a default option for medium-scale problems
64599 : (less than thousand of variables) or problems with target function being
64600 : hard to evaluate.
64601 :
64602 : For large-scale problems or ones with very cheap target function
64603 : AUL solver can be better option.
64604 :
64605 : INPUT PARAMETERS:
64606 : State - structure which stores algorithm state
64607 :
64608 : ===== INTERACTION WITH OPTGUARD ==========================================
64609 :
64610 : OptGuard integrity checker allows us to catch problems like errors in
64611 : gradients and discontinuity/nonsmoothness of the target/constraints.
64612 : Latter kind of problems can be detected by looking upon line searches
64613 : performed during optimization and searching for signs of nonsmoothness.
64614 :
64615 : The problem with SQP is that it is too good for OptGuard to work - it does
64616 : not perform line searches. It typically needs 1-2 function evaluations
64617 : per step, and it is not enough for OptGuard to detect nonsmoothness.
64618 :
64619 : So, if you suspect that your problem is nonsmooth, we recommend you to use
64620 : AUL or SLP solvers.
64621 :
64622 : ===== TRACING SQP SOLVER =================================================
64623 :
64624 : SQP solver supports advanced tracing capabilities. You can trace algorithm
64625 : output by specifying following trace symbols (case-insensitive) by means
64626 : of trace_file() call:
64627 : * 'SQP' - for basic trace of algorithm steps and decisions. Only
64628 : short scalars (function values and deltas) are printed.
64629 : N-dimensional quantities like search directions are NOT
64630 : printed.
64631 : It also prints OptGuard integrity checker report when
64632 : nonsmoothness of target/constraints is suspected.
64633 : * 'SQP.DETAILED'- for output of points being visited and search directions
64634 : This symbol also implicitly defines 'SQP'. You can
64635 : control output format by additionally specifying:
64636 : * nothing to output in 6-digit exponential format
64637 : * 'PREC.E15' to output in 15-digit exponential format
64638 : * 'PREC.F6' to output in 6-digit fixed-point format
64639 : * 'SQP.PROBING' - to let algorithm insert additional function evaluations
64640 : before line search in order to build human-readable
64641 : chart of the raw Lagrangian (~40 additional function
64642 : evaluations is performed for each line search). This
64643 : symbol also implicitly defines 'SQP' and activates
64644 : OptGuard integrity checker which detects continuity and
64645 : smoothness violations. An OptGuard log is printed at the
64646 : end of the file.
64647 :
64648 : By default trace is disabled and adds no overhead to the optimization
64649 : process. However, specifying any of the symbols adds some formatting and
64650 : output-related overhead. Specifying 'SQP.PROBING' adds even larger
64651 : overhead due to additional function evaluations being performed.
64652 :
64653 : You may specify multiple symbols by separating them with commas:
64654 : >
64655 : > alglib::trace_file("SQP,SQP.PROBING,PREC.F6", "path/to/trace.log")
64656 : >
64657 :
64658 : -- ALGLIB --
64659 : Copyright 02.12.2019 by Bochkanov Sergey
64660 : *************************************************************************/
64661 0 : void minnlcsetalgosqp(minnlcstate* state, ae_state *_state)
64662 : {
64663 :
64664 :
64665 0 : state->solvertype = 2;
64666 0 : }
64667 :
64668 :
64669 : /*************************************************************************
64670 : This function turns on/off reporting.
64671 :
64672 : INPUT PARAMETERS:
64673 : State - structure which stores algorithm state
64674 : NeedXRep- whether iteration reports are needed or not
64675 :
64676 : If NeedXRep is True, algorithm will call rep() callback function if it is
64677 : provided to MinNLCOptimize().
64678 :
64679 : NOTE: algorithm passes two parameters to rep() callback - current point
64680 : and penalized function value at current point. Important - function
64681 : value which is returned is NOT function being minimized. It is sum
64682 : of the value of the function being minimized - and penalty term.
64683 :
64684 : -- ALGLIB --
64685 : Copyright 28.11.2010 by Bochkanov Sergey
64686 : *************************************************************************/
64687 0 : void minnlcsetxrep(minnlcstate* state, ae_bool needxrep, ae_state *_state)
64688 : {
64689 :
64690 :
64691 0 : state->xrep = needxrep;
64692 0 : }
64693 :
64694 :
64695 : /*************************************************************************
64696 :
64697 : NOTES:
64698 :
64699 : 1. This function has two different implementations: one which uses exact
64700 : (analytical) user-supplied Jacobian, and one which uses only function
64701 : vector and numerically differentiates function in order to obtain
64702 : gradient.
64703 :
64704 : Depending on the specific function used to create optimizer object
64705 : you should choose appropriate variant of MinNLCOptimize() - one which
64706 : accepts function AND Jacobian or one which accepts ONLY function.
64707 :
64708 : Be careful to choose variant of MinNLCOptimize() which corresponds to
64709 : your optimization scheme! Table below lists different combinations of
64710 : callback (function/gradient) passed to MinNLCOptimize() and specific
64711 : function used to create optimizer.
64712 :
64713 :
64714 : | USER PASSED TO MinNLCOptimize()
64715 : CREATED WITH | function only | function and gradient
64716 : ------------------------------------------------------------
64717 : MinNLCCreateF() | works FAILS
64718 : MinNLCCreate() | FAILS works
64719 :
64720 : Here "FAILS" denotes inappropriate combinations of optimizer creation
64721 : function and MinNLCOptimize() version. Attemps to use such
64722 : combination will lead to exception. Either you did not pass gradient
64723 : when it WAS needed or you passed gradient when it was NOT needed.
64724 :
64725 : -- ALGLIB --
64726 : Copyright 06.06.2014 by Bochkanov Sergey
64727 : *************************************************************************/
64728 0 : ae_bool minnlciteration(minnlcstate* state, ae_state *_state)
64729 : {
64730 : ae_int_t i;
64731 : ae_int_t k;
64732 : ae_int_t n;
64733 : ae_int_t ng;
64734 : ae_int_t nh;
64735 : double vleft;
64736 : double vright;
64737 : ae_bool b;
64738 : ae_bool result;
64739 :
64740 :
64741 :
64742 : /*
64743 : * Reverse communication preparations
64744 : * I know it looks ugly, but it works the same way
64745 : * anywhere from C++ to Python.
64746 : *
64747 : * This code initializes locals by:
64748 : * * random values determined during code
64749 : * generation - on first subroutine call
64750 : * * values from previous call - on subsequent calls
64751 : */
64752 0 : if( state->rstate.stage>=0 )
64753 : {
64754 0 : i = state->rstate.ia.ptr.p_int[0];
64755 0 : k = state->rstate.ia.ptr.p_int[1];
64756 0 : n = state->rstate.ia.ptr.p_int[2];
64757 0 : ng = state->rstate.ia.ptr.p_int[3];
64758 0 : nh = state->rstate.ia.ptr.p_int[4];
64759 0 : b = state->rstate.ba.ptr.p_bool[0];
64760 0 : vleft = state->rstate.ra.ptr.p_double[0];
64761 0 : vright = state->rstate.ra.ptr.p_double[1];
64762 : }
64763 : else
64764 : {
64765 0 : i = 359;
64766 0 : k = -58;
64767 0 : n = -919;
64768 0 : ng = -909;
64769 0 : nh = 81;
64770 0 : b = ae_true;
64771 0 : vleft = 74;
64772 0 : vright = -788;
64773 : }
64774 0 : if( state->rstate.stage==0 )
64775 : {
64776 0 : goto lbl_0;
64777 : }
64778 0 : if( state->rstate.stage==1 )
64779 : {
64780 0 : goto lbl_1;
64781 : }
64782 0 : if( state->rstate.stage==2 )
64783 : {
64784 0 : goto lbl_2;
64785 : }
64786 0 : if( state->rstate.stage==3 )
64787 : {
64788 0 : goto lbl_3;
64789 : }
64790 0 : if( state->rstate.stage==4 )
64791 : {
64792 0 : goto lbl_4;
64793 : }
64794 0 : if( state->rstate.stage==5 )
64795 : {
64796 0 : goto lbl_5;
64797 : }
64798 0 : if( state->rstate.stage==6 )
64799 : {
64800 0 : goto lbl_6;
64801 : }
64802 0 : if( state->rstate.stage==7 )
64803 : {
64804 0 : goto lbl_7;
64805 : }
64806 0 : if( state->rstate.stage==8 )
64807 : {
64808 0 : goto lbl_8;
64809 : }
64810 0 : if( state->rstate.stage==9 )
64811 : {
64812 0 : goto lbl_9;
64813 : }
64814 0 : if( state->rstate.stage==10 )
64815 : {
64816 0 : goto lbl_10;
64817 : }
64818 0 : if( state->rstate.stage==11 )
64819 : {
64820 0 : goto lbl_11;
64821 : }
64822 0 : if( state->rstate.stage==12 )
64823 : {
64824 0 : goto lbl_12;
64825 : }
64826 0 : if( state->rstate.stage==13 )
64827 : {
64828 0 : goto lbl_13;
64829 : }
64830 0 : if( state->rstate.stage==14 )
64831 : {
64832 0 : goto lbl_14;
64833 : }
64834 0 : if( state->rstate.stage==15 )
64835 : {
64836 0 : goto lbl_15;
64837 : }
64838 0 : if( state->rstate.stage==16 )
64839 : {
64840 0 : goto lbl_16;
64841 : }
64842 0 : if( state->rstate.stage==17 )
64843 : {
64844 0 : goto lbl_17;
64845 : }
64846 0 : if( state->rstate.stage==18 )
64847 : {
64848 0 : goto lbl_18;
64849 : }
64850 0 : if( state->rstate.stage==19 )
64851 : {
64852 0 : goto lbl_19;
64853 : }
64854 0 : if( state->rstate.stage==20 )
64855 : {
64856 0 : goto lbl_20;
64857 : }
64858 0 : if( state->rstate.stage==21 )
64859 : {
64860 0 : goto lbl_21;
64861 : }
64862 0 : if( state->rstate.stage==22 )
64863 : {
64864 0 : goto lbl_22;
64865 : }
64866 0 : if( state->rstate.stage==23 )
64867 : {
64868 0 : goto lbl_23;
64869 : }
64870 0 : if( state->rstate.stage==24 )
64871 : {
64872 0 : goto lbl_24;
64873 : }
64874 :
64875 : /*
64876 : * Routine body
64877 : */
64878 :
64879 : /*
64880 : * Init
64881 : */
64882 0 : state->userterminationneeded = ae_false;
64883 0 : state->repterminationtype = 0;
64884 0 : state->repinneriterationscount = 0;
64885 0 : state->repouteriterationscount = 0;
64886 0 : state->repnfev = 0;
64887 0 : state->repdbgphase0its = 0;
64888 0 : state->repbcerr = (double)(0);
64889 0 : state->repbcidx = -1;
64890 0 : state->replcerr = (double)(0);
64891 0 : state->replcidx = -1;
64892 0 : state->repnlcerr = (double)(0);
64893 0 : state->repnlcidx = -1;
64894 0 : n = state->n;
64895 0 : ng = state->ng;
64896 0 : nh = state->nh;
64897 0 : minnlc_clearrequestfields(state, _state);
64898 0 : ae_assert(state->smoothnessguardlevel==0||state->smoothnessguardlevel==1, "MinNLCIteration: integrity check failed", _state);
64899 0 : b = state->smoothnessguardlevel>0;
64900 0 : b = b||(state->solvertype==1&&ae_is_trace_enabled("SLP.PROBING"));
64901 0 : b = b||(state->solvertype==2&&ae_is_trace_enabled("SQP.PROBING"));
64902 0 : smoothnessmonitorinit(&state->smonitor, &state->s, n, 1+ng+nh, b, _state);
64903 0 : for(i=0; i<=n-1; i++)
64904 : {
64905 0 : state->lastscaleused.ptr.p_double[i] = state->s.ptr.p_double[i];
64906 : }
64907 :
64908 : /*
64909 : * Check correctness of box constraints
64910 : */
64911 0 : for(i=0; i<=n-1; i++)
64912 : {
64913 0 : if( state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i] )
64914 : {
64915 0 : if( ae_fp_greater(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
64916 : {
64917 0 : state->repterminationtype = -3;
64918 0 : state->repbcerr = state->bndl.ptr.p_double[i]-state->bndu.ptr.p_double[i];
64919 0 : state->repbcidx = i;
64920 0 : result = ae_false;
64921 0 : return result;
64922 : }
64923 : }
64924 : }
64925 :
64926 : /*
64927 : * Test gradient
64928 : */
64929 0 : if( !(ae_fp_eq(state->diffstep,(double)(0))&&ae_fp_greater(state->teststep,(double)(0))) )
64930 : {
64931 0 : goto lbl_25;
64932 : }
64933 0 : lbl_27:
64934 0 : if( !smoothnessmonitorcheckgradientatx0(&state->smonitor, &state->xstart, &state->s, &state->bndl, &state->bndu, ae_true, state->teststep, _state) )
64935 : {
64936 0 : goto lbl_28;
64937 : }
64938 0 : for(i=0; i<=n-1; i++)
64939 : {
64940 0 : state->x.ptr.p_double[i] = state->smonitor.x.ptr.p_double[i];
64941 : }
64942 0 : state->needfij = ae_true;
64943 0 : state->rstate.stage = 0;
64944 0 : goto lbl_rcomm;
64945 0 : lbl_0:
64946 0 : state->needfij = ae_false;
64947 0 : for(i=0; i<=ng+nh; i++)
64948 : {
64949 0 : state->smonitor.fi.ptr.p_double[i] = state->fi.ptr.p_double[i];
64950 0 : for(k=0; k<=n-1; k++)
64951 : {
64952 0 : state->smonitor.j.ptr.pp_double[i][k] = state->j.ptr.pp_double[i][k];
64953 : }
64954 : }
64955 0 : goto lbl_27;
64956 0 : lbl_28:
64957 0 : lbl_25:
64958 :
64959 : /*
64960 : * AUL solver
64961 : */
64962 0 : if( state->solvertype!=0 )
64963 : {
64964 0 : goto lbl_29;
64965 : }
64966 0 : if( ae_fp_neq(state->diffstep,(double)(0)) )
64967 : {
64968 0 : rvectorsetlengthatleast(&state->xbase, n, _state);
64969 0 : rvectorsetlengthatleast(&state->fbase, 1+ng+nh, _state);
64970 0 : rvectorsetlengthatleast(&state->fm2, 1+ng+nh, _state);
64971 0 : rvectorsetlengthatleast(&state->fm1, 1+ng+nh, _state);
64972 0 : rvectorsetlengthatleast(&state->fp1, 1+ng+nh, _state);
64973 0 : rvectorsetlengthatleast(&state->fp2, 1+ng+nh, _state);
64974 : }
64975 0 : ae_vector_set_length(&state->rstateaul.ia, 8+1, _state);
64976 0 : ae_vector_set_length(&state->rstateaul.ra, 7+1, _state);
64977 0 : state->rstateaul.stage = -1;
64978 0 : lbl_31:
64979 0 : if( !minnlc_auliteration(state, &state->smonitor, _state) )
64980 : {
64981 0 : goto lbl_32;
64982 : }
64983 :
64984 : /*
64985 : * Numerical differentiation (if needed) - intercept NeedFiJ
64986 : * request and replace it by sequence of NeedFi requests
64987 : */
64988 0 : if( !(ae_fp_neq(state->diffstep,(double)(0))&&state->needfij) )
64989 : {
64990 0 : goto lbl_33;
64991 : }
64992 0 : state->needfij = ae_false;
64993 0 : state->needfi = ae_true;
64994 0 : ae_v_move(&state->xbase.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1));
64995 0 : k = 0;
64996 0 : lbl_35:
64997 0 : if( k>n-1 )
64998 : {
64999 0 : goto lbl_37;
65000 : }
65001 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
65002 0 : state->x.ptr.p_double[k] = state->x.ptr.p_double[k]-state->s.ptr.p_double[k]*state->diffstep;
65003 0 : state->rstate.stage = 1;
65004 0 : goto lbl_rcomm;
65005 0 : lbl_1:
65006 0 : ae_v_move(&state->fm2.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh));
65007 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
65008 0 : state->x.ptr.p_double[k] = state->x.ptr.p_double[k]-0.5*state->s.ptr.p_double[k]*state->diffstep;
65009 0 : state->rstate.stage = 2;
65010 0 : goto lbl_rcomm;
65011 0 : lbl_2:
65012 0 : ae_v_move(&state->fm1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh));
65013 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
65014 0 : state->x.ptr.p_double[k] = state->x.ptr.p_double[k]+0.5*state->s.ptr.p_double[k]*state->diffstep;
65015 0 : state->rstate.stage = 3;
65016 0 : goto lbl_rcomm;
65017 0 : lbl_3:
65018 0 : ae_v_move(&state->fp1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh));
65019 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
65020 0 : state->x.ptr.p_double[k] = state->x.ptr.p_double[k]+state->s.ptr.p_double[k]*state->diffstep;
65021 0 : state->rstate.stage = 4;
65022 0 : goto lbl_rcomm;
65023 0 : lbl_4:
65024 0 : ae_v_move(&state->fp2.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh));
65025 0 : for(i=0; i<=ng+nh; i++)
65026 : {
65027 0 : state->j.ptr.pp_double[i][k] = (8*(state->fp1.ptr.p_double[i]-state->fm1.ptr.p_double[i])-(state->fp2.ptr.p_double[i]-state->fm2.ptr.p_double[i]))/(6*state->diffstep*state->s.ptr.p_double[i]);
65028 : }
65029 0 : k = k+1;
65030 0 : goto lbl_35;
65031 0 : lbl_37:
65032 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
65033 0 : state->rstate.stage = 5;
65034 0 : goto lbl_rcomm;
65035 0 : lbl_5:
65036 :
65037 : /*
65038 : * Restore previous values of fields and continue
65039 : */
65040 0 : state->needfi = ae_false;
65041 0 : state->needfij = ae_true;
65042 0 : goto lbl_31;
65043 0 : lbl_33:
65044 :
65045 : /*
65046 : * Forward request to caller
65047 : */
65048 0 : state->rstate.stage = 6;
65049 0 : goto lbl_rcomm;
65050 0 : lbl_6:
65051 0 : goto lbl_31;
65052 0 : lbl_32:
65053 0 : result = ae_false;
65054 0 : return result;
65055 0 : lbl_29:
65056 :
65057 : /*
65058 : * SLP solver
65059 : */
65060 0 : if( state->solvertype!=1 )
65061 : {
65062 0 : goto lbl_38;
65063 : }
65064 0 : if( ae_fp_neq(state->diffstep,(double)(0)) )
65065 : {
65066 0 : rvectorsetlengthatleast(&state->xbase, n, _state);
65067 0 : rvectorsetlengthatleast(&state->fbase, 1+ng+nh, _state);
65068 0 : rvectorsetlengthatleast(&state->fm2, 1+ng+nh, _state);
65069 0 : rvectorsetlengthatleast(&state->fm1, 1+ng+nh, _state);
65070 0 : rvectorsetlengthatleast(&state->fp1, 1+ng+nh, _state);
65071 0 : rvectorsetlengthatleast(&state->fp2, 1+ng+nh, _state);
65072 : }
65073 0 : minslpinitbuf(&state->bndl, &state->bndu, &state->s, &state->xstart, n, &state->cleic, &state->lcsrcidx, state->nec, state->nic, state->ng, state->nh, state->epsx, state->maxits, &state->slpsolverstate, _state);
65074 0 : lbl_40:
65075 0 : if( !minslpiteration(&state->slpsolverstate, &state->smonitor, state->userterminationneeded, _state) )
65076 : {
65077 0 : goto lbl_41;
65078 : }
65079 :
65080 : /*
65081 : * Forward request to caller
65082 : */
65083 0 : if( !state->slpsolverstate.needfij )
65084 : {
65085 0 : goto lbl_42;
65086 : }
65087 :
65088 : /*
65089 : * Evaluate target function/Jacobian
65090 : */
65091 0 : if( ae_fp_neq(state->diffstep,(double)(0)) )
65092 : {
65093 0 : goto lbl_44;
65094 : }
65095 :
65096 : /*
65097 : * Analytic Jacobian is provided
65098 : */
65099 0 : minnlc_unscale(state, &state->slpsolverstate.x, &state->slpsolverstate.scaledbndl, &state->slpsolverstate.scaledbndu, &state->x, _state);
65100 0 : state->needfij = ae_true;
65101 0 : state->rstate.stage = 7;
65102 0 : goto lbl_rcomm;
65103 0 : lbl_7:
65104 0 : state->needfij = ae_false;
65105 0 : for(i=0; i<=ng+nh; i++)
65106 : {
65107 0 : state->slpsolverstate.fi.ptr.p_double[i] = state->fi.ptr.p_double[i];
65108 0 : for(k=0; k<=n-1; k++)
65109 : {
65110 0 : state->slpsolverstate.j.ptr.pp_double[i][k] = state->j.ptr.pp_double[i][k]*state->s.ptr.p_double[k];
65111 : }
65112 : }
65113 0 : goto lbl_45;
65114 0 : lbl_44:
65115 :
65116 : /*
65117 : * Numerical differentiation
65118 : */
65119 0 : state->needfij = ae_false;
65120 0 : state->needfi = ae_true;
65121 0 : minnlc_unscale(state, &state->slpsolverstate.x, &state->slpsolverstate.scaledbndl, &state->slpsolverstate.scaledbndu, &state->xbase, _state);
65122 0 : k = 0;
65123 0 : lbl_46:
65124 0 : if( k>n-1 )
65125 : {
65126 0 : goto lbl_48;
65127 : }
65128 0 : vleft = state->xbase.ptr.p_double[k]-state->s.ptr.p_double[k]*state->diffstep;
65129 0 : vright = state->xbase.ptr.p_double[k]+state->s.ptr.p_double[k]*state->diffstep;
65130 0 : if( !((state->hasbndl.ptr.p_bool[k]&&ae_fp_less(vleft,state->bndl.ptr.p_double[k]))||(state->hasbndu.ptr.p_bool[k]&&ae_fp_greater(vright,state->bndu.ptr.p_double[k]))) )
65131 : {
65132 0 : goto lbl_49;
65133 : }
65134 :
65135 : /*
65136 : * Box constraint is violated by 4-point centered formula, use 2-point uncentered one
65137 : */
65138 0 : if( state->hasbndl.ptr.p_bool[k]&&ae_fp_less(vleft,state->bndl.ptr.p_double[k]) )
65139 : {
65140 0 : vleft = state->bndl.ptr.p_double[k];
65141 : }
65142 0 : if( state->hasbndu.ptr.p_bool[k]&&ae_fp_greater(vright,state->bndu.ptr.p_double[k]) )
65143 : {
65144 0 : vright = state->bndu.ptr.p_double[k];
65145 : }
65146 0 : ae_assert(ae_fp_less_eq(vleft,vright), "MinNLC: integrity check failed", _state);
65147 0 : if( ae_fp_eq(vleft,vright) )
65148 : {
65149 :
65150 : /*
65151 : * Fixed variable
65152 : */
65153 0 : for(i=0; i<=ng+nh; i++)
65154 : {
65155 0 : state->j.ptr.pp_double[i][k] = (double)(0);
65156 : }
65157 0 : goto lbl_47;
65158 : }
65159 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
65160 0 : state->x.ptr.p_double[k] = vleft;
65161 0 : state->rstate.stage = 8;
65162 0 : goto lbl_rcomm;
65163 0 : lbl_8:
65164 0 : ae_v_move(&state->fm1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh));
65165 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
65166 0 : state->x.ptr.p_double[k] = vright;
65167 0 : state->rstate.stage = 9;
65168 0 : goto lbl_rcomm;
65169 0 : lbl_9:
65170 0 : ae_v_move(&state->fp1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh));
65171 0 : for(i=0; i<=ng+nh; i++)
65172 : {
65173 0 : state->j.ptr.pp_double[i][k] = (state->fp1.ptr.p_double[i]-state->fm1.ptr.p_double[i])/(vright-vleft);
65174 : }
65175 0 : goto lbl_50;
65176 0 : lbl_49:
65177 :
65178 : /*
65179 : * 4-point centered formula does not violate box constraints
65180 : */
65181 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
65182 0 : state->x.ptr.p_double[k] = state->x.ptr.p_double[k]-state->s.ptr.p_double[k]*state->diffstep;
65183 0 : state->rstate.stage = 10;
65184 0 : goto lbl_rcomm;
65185 0 : lbl_10:
65186 0 : ae_v_move(&state->fm2.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh));
65187 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
65188 0 : state->x.ptr.p_double[k] = state->x.ptr.p_double[k]-0.5*state->s.ptr.p_double[k]*state->diffstep;
65189 0 : state->rstate.stage = 11;
65190 0 : goto lbl_rcomm;
65191 0 : lbl_11:
65192 0 : ae_v_move(&state->fm1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh));
65193 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
65194 0 : state->x.ptr.p_double[k] = state->x.ptr.p_double[k]+0.5*state->s.ptr.p_double[k]*state->diffstep;
65195 0 : state->rstate.stage = 12;
65196 0 : goto lbl_rcomm;
65197 0 : lbl_12:
65198 0 : ae_v_move(&state->fp1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh));
65199 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
65200 0 : state->x.ptr.p_double[k] = state->x.ptr.p_double[k]+state->s.ptr.p_double[k]*state->diffstep;
65201 0 : state->rstate.stage = 13;
65202 0 : goto lbl_rcomm;
65203 0 : lbl_13:
65204 0 : ae_v_move(&state->fp2.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh));
65205 0 : for(i=0; i<=ng+nh; i++)
65206 : {
65207 0 : state->j.ptr.pp_double[i][k] = (8*(state->fp1.ptr.p_double[i]-state->fm1.ptr.p_double[i])-(state->fp2.ptr.p_double[i]-state->fm2.ptr.p_double[i]))/(6*state->diffstep*state->s.ptr.p_double[k]);
65208 : }
65209 0 : lbl_50:
65210 0 : lbl_47:
65211 0 : k = k+1;
65212 0 : goto lbl_46;
65213 0 : lbl_48:
65214 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
65215 0 : state->rstate.stage = 14;
65216 0 : goto lbl_rcomm;
65217 0 : lbl_14:
65218 0 : state->needfi = ae_false;
65219 0 : state->needfij = ae_true;
65220 0 : for(i=0; i<=ng+nh; i++)
65221 : {
65222 0 : state->slpsolverstate.fi.ptr.p_double[i] = state->fi.ptr.p_double[i];
65223 0 : for(k=0; k<=n-1; k++)
65224 : {
65225 0 : state->slpsolverstate.j.ptr.pp_double[i][k] = state->j.ptr.pp_double[i][k]*state->s.ptr.p_double[k];
65226 : }
65227 : }
65228 0 : lbl_45:
65229 0 : inc(&state->repnfev, _state);
65230 0 : goto lbl_40;
65231 0 : lbl_42:
65232 0 : if( !state->slpsolverstate.xupdated )
65233 : {
65234 0 : goto lbl_51;
65235 : }
65236 :
65237 : /*
65238 : * Report current point
65239 : */
65240 0 : if( !state->xrep )
65241 : {
65242 0 : goto lbl_53;
65243 : }
65244 0 : minnlc_unscale(state, &state->slpsolverstate.x, &state->slpsolverstate.scaledbndl, &state->slpsolverstate.scaledbndu, &state->x, _state);
65245 0 : state->f = state->slpsolverstate.f;
65246 0 : state->xupdated = ae_true;
65247 0 : state->rstate.stage = 15;
65248 0 : goto lbl_rcomm;
65249 0 : lbl_15:
65250 0 : state->xupdated = ae_false;
65251 0 : lbl_53:
65252 0 : goto lbl_40;
65253 0 : lbl_51:
65254 0 : ae_assert(state->slpsolverstate.needfij, "NLC:SLP:request", _state);
65255 0 : goto lbl_40;
65256 0 : lbl_41:
65257 0 : state->repterminationtype = state->slpsolverstate.repterminationtype;
65258 0 : state->repouteriterationscount = state->slpsolverstate.repouteriterationscount;
65259 0 : state->repinneriterationscount = state->slpsolverstate.repinneriterationscount;
65260 0 : state->repbcerr = state->slpsolverstate.repbcerr;
65261 0 : state->repbcidx = state->slpsolverstate.repbcidx;
65262 0 : state->replcerr = state->slpsolverstate.replcerr;
65263 0 : state->replcidx = state->slpsolverstate.replcidx;
65264 0 : state->repnlcerr = state->slpsolverstate.repnlcerr;
65265 0 : state->repnlcidx = state->slpsolverstate.repnlcidx;
65266 0 : minnlc_unscale(state, &state->slpsolverstate.stepkx, &state->slpsolverstate.scaledbndl, &state->slpsolverstate.scaledbndu, &state->xc, _state);
65267 0 : result = ae_false;
65268 0 : return result;
65269 0 : lbl_38:
65270 :
65271 : /*
65272 : * SQP solver
65273 : */
65274 0 : if( state->solvertype!=2 )
65275 : {
65276 0 : goto lbl_55;
65277 : }
65278 0 : if( ae_fp_neq(state->diffstep,(double)(0)) )
65279 : {
65280 0 : rvectorsetlengthatleast(&state->xbase, n, _state);
65281 0 : rvectorsetlengthatleast(&state->fbase, 1+ng+nh, _state);
65282 0 : rvectorsetlengthatleast(&state->fm2, 1+ng+nh, _state);
65283 0 : rvectorsetlengthatleast(&state->fm1, 1+ng+nh, _state);
65284 0 : rvectorsetlengthatleast(&state->fp1, 1+ng+nh, _state);
65285 0 : rvectorsetlengthatleast(&state->fp2, 1+ng+nh, _state);
65286 : }
65287 0 : minsqpinitbuf(&state->bndl, &state->bndu, &state->s, &state->xstart, n, &state->cleic, &state->lcsrcidx, state->nec, state->nic, state->ng, state->nh, state->epsx, state->maxits, &state->sqpsolverstate, _state);
65288 0 : lbl_57:
65289 0 : if( !minsqpiteration(&state->sqpsolverstate, &state->smonitor, state->userterminationneeded, _state) )
65290 : {
65291 0 : goto lbl_58;
65292 : }
65293 :
65294 : /*
65295 : * Forward request to caller
65296 : */
65297 0 : if( !state->sqpsolverstate.needfij )
65298 : {
65299 0 : goto lbl_59;
65300 : }
65301 :
65302 : /*
65303 : * Evaluate target function/Jacobian
65304 : */
65305 0 : if( ae_fp_neq(state->diffstep,(double)(0)) )
65306 : {
65307 0 : goto lbl_61;
65308 : }
65309 :
65310 : /*
65311 : * Analytic Jacobian is provided
65312 : */
65313 0 : minnlc_unscale(state, &state->sqpsolverstate.x, &state->sqpsolverstate.scaledbndl, &state->sqpsolverstate.scaledbndu, &state->x, _state);
65314 0 : state->needfij = ae_true;
65315 0 : state->rstate.stage = 16;
65316 0 : goto lbl_rcomm;
65317 0 : lbl_16:
65318 0 : state->needfij = ae_false;
65319 0 : for(i=0; i<=ng+nh; i++)
65320 : {
65321 0 : state->sqpsolverstate.fi.ptr.p_double[i] = state->fi.ptr.p_double[i];
65322 0 : for(k=0; k<=n-1; k++)
65323 : {
65324 0 : state->sqpsolverstate.j.ptr.pp_double[i][k] = state->j.ptr.pp_double[i][k]*state->s.ptr.p_double[k];
65325 : }
65326 : }
65327 0 : goto lbl_62;
65328 0 : lbl_61:
65329 :
65330 : /*
65331 : * Numerical differentiation
65332 : */
65333 0 : state->needfij = ae_false;
65334 0 : state->needfi = ae_true;
65335 0 : minnlc_unscale(state, &state->sqpsolverstate.x, &state->sqpsolverstate.scaledbndl, &state->sqpsolverstate.scaledbndu, &state->xbase, _state);
65336 0 : k = 0;
65337 0 : lbl_63:
65338 0 : if( k>n-1 )
65339 : {
65340 0 : goto lbl_65;
65341 : }
65342 0 : vleft = state->xbase.ptr.p_double[k]-state->s.ptr.p_double[k]*state->diffstep;
65343 0 : vright = state->xbase.ptr.p_double[k]+state->s.ptr.p_double[k]*state->diffstep;
65344 0 : if( !((state->hasbndl.ptr.p_bool[k]&&ae_fp_less(vleft,state->bndl.ptr.p_double[k]))||(state->hasbndu.ptr.p_bool[k]&&ae_fp_greater(vright,state->bndu.ptr.p_double[k]))) )
65345 : {
65346 0 : goto lbl_66;
65347 : }
65348 :
65349 : /*
65350 : * Box constraint is violated by 4-point centered formula, use 2-point uncentered one
65351 : */
65352 0 : if( state->hasbndl.ptr.p_bool[k]&&ae_fp_less(vleft,state->bndl.ptr.p_double[k]) )
65353 : {
65354 0 : vleft = state->bndl.ptr.p_double[k];
65355 : }
65356 0 : if( state->hasbndu.ptr.p_bool[k]&&ae_fp_greater(vright,state->bndu.ptr.p_double[k]) )
65357 : {
65358 0 : vright = state->bndu.ptr.p_double[k];
65359 : }
65360 0 : ae_assert(ae_fp_less_eq(vleft,vright), "MinNLC: integrity check failed", _state);
65361 0 : if( ae_fp_eq(vleft,vright) )
65362 : {
65363 :
65364 : /*
65365 : * Fixed variable
65366 : */
65367 0 : for(i=0; i<=ng+nh; i++)
65368 : {
65369 0 : state->j.ptr.pp_double[i][k] = (double)(0);
65370 : }
65371 0 : goto lbl_64;
65372 : }
65373 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
65374 0 : state->x.ptr.p_double[k] = vleft;
65375 0 : state->rstate.stage = 17;
65376 0 : goto lbl_rcomm;
65377 0 : lbl_17:
65378 0 : ae_v_move(&state->fm1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh));
65379 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
65380 0 : state->x.ptr.p_double[k] = vright;
65381 0 : state->rstate.stage = 18;
65382 0 : goto lbl_rcomm;
65383 0 : lbl_18:
65384 0 : ae_v_move(&state->fp1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh));
65385 0 : for(i=0; i<=ng+nh; i++)
65386 : {
65387 0 : state->j.ptr.pp_double[i][k] = (state->fp1.ptr.p_double[i]-state->fm1.ptr.p_double[i])/(vright-vleft);
65388 : }
65389 0 : goto lbl_67;
65390 0 : lbl_66:
65391 :
65392 : /*
65393 : * 4-point centered formula does not violate box constraints
65394 : */
65395 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
65396 0 : state->x.ptr.p_double[k] = state->x.ptr.p_double[k]-state->s.ptr.p_double[k]*state->diffstep;
65397 0 : state->rstate.stage = 19;
65398 0 : goto lbl_rcomm;
65399 0 : lbl_19:
65400 0 : ae_v_move(&state->fm2.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh));
65401 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
65402 0 : state->x.ptr.p_double[k] = state->x.ptr.p_double[k]-0.5*state->s.ptr.p_double[k]*state->diffstep;
65403 0 : state->rstate.stage = 20;
65404 0 : goto lbl_rcomm;
65405 0 : lbl_20:
65406 0 : ae_v_move(&state->fm1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh));
65407 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
65408 0 : state->x.ptr.p_double[k] = state->x.ptr.p_double[k]+0.5*state->s.ptr.p_double[k]*state->diffstep;
65409 0 : state->rstate.stage = 21;
65410 0 : goto lbl_rcomm;
65411 0 : lbl_21:
65412 0 : ae_v_move(&state->fp1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh));
65413 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
65414 0 : state->x.ptr.p_double[k] = state->x.ptr.p_double[k]+state->s.ptr.p_double[k]*state->diffstep;
65415 0 : state->rstate.stage = 22;
65416 0 : goto lbl_rcomm;
65417 0 : lbl_22:
65418 0 : ae_v_move(&state->fp2.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh));
65419 0 : for(i=0; i<=ng+nh; i++)
65420 : {
65421 0 : state->j.ptr.pp_double[i][k] = (8*(state->fp1.ptr.p_double[i]-state->fm1.ptr.p_double[i])-(state->fp2.ptr.p_double[i]-state->fm2.ptr.p_double[i]))/(6*state->diffstep*state->s.ptr.p_double[k]);
65422 : }
65423 0 : lbl_67:
65424 0 : lbl_64:
65425 0 : k = k+1;
65426 0 : goto lbl_63;
65427 0 : lbl_65:
65428 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
65429 0 : state->rstate.stage = 23;
65430 0 : goto lbl_rcomm;
65431 0 : lbl_23:
65432 0 : state->needfi = ae_false;
65433 0 : state->needfij = ae_true;
65434 0 : for(i=0; i<=ng+nh; i++)
65435 : {
65436 0 : state->sqpsolverstate.fi.ptr.p_double[i] = state->fi.ptr.p_double[i];
65437 0 : for(k=0; k<=n-1; k++)
65438 : {
65439 0 : state->sqpsolverstate.j.ptr.pp_double[i][k] = state->j.ptr.pp_double[i][k]*state->s.ptr.p_double[k];
65440 : }
65441 : }
65442 0 : lbl_62:
65443 0 : inc(&state->repnfev, _state);
65444 0 : goto lbl_57;
65445 0 : lbl_59:
65446 0 : if( !state->sqpsolverstate.xupdated )
65447 : {
65448 0 : goto lbl_68;
65449 : }
65450 :
65451 : /*
65452 : * Report current point
65453 : */
65454 0 : if( !state->xrep )
65455 : {
65456 0 : goto lbl_70;
65457 : }
65458 0 : minnlc_unscale(state, &state->sqpsolverstate.x, &state->sqpsolverstate.scaledbndl, &state->sqpsolverstate.scaledbndu, &state->x, _state);
65459 0 : state->f = state->sqpsolverstate.f;
65460 0 : state->xupdated = ae_true;
65461 0 : state->rstate.stage = 24;
65462 0 : goto lbl_rcomm;
65463 0 : lbl_24:
65464 0 : state->xupdated = ae_false;
65465 0 : lbl_70:
65466 0 : goto lbl_57;
65467 0 : lbl_68:
65468 0 : ae_assert(state->sqpsolverstate.needfij, "NLC:SQP:request", _state);
65469 0 : goto lbl_57;
65470 0 : lbl_58:
65471 0 : state->repterminationtype = state->sqpsolverstate.repterminationtype;
65472 0 : state->repouteriterationscount = state->sqpsolverstate.repiterationscount;
65473 0 : state->repinneriterationscount = state->sqpsolverstate.repiterationscount;
65474 0 : state->repbcerr = state->sqpsolverstate.repbcerr;
65475 0 : state->repbcidx = state->sqpsolverstate.repbcidx;
65476 0 : state->replcerr = state->sqpsolverstate.replcerr;
65477 0 : state->replcidx = state->sqpsolverstate.replcidx;
65478 0 : state->repnlcerr = state->sqpsolverstate.repnlcerr;
65479 0 : state->repnlcidx = state->sqpsolverstate.repnlcidx;
65480 0 : minnlc_unscale(state, &state->sqpsolverstate.stepkx, &state->sqpsolverstate.scaledbndl, &state->sqpsolverstate.scaledbndu, &state->xc, _state);
65481 0 : result = ae_false;
65482 0 : return result;
65483 0 : lbl_55:
65484 0 : result = ae_false;
65485 0 : return result;
65486 :
65487 : /*
65488 : * Saving state
65489 : */
65490 0 : lbl_rcomm:
65491 0 : result = ae_true;
65492 0 : state->rstate.ia.ptr.p_int[0] = i;
65493 0 : state->rstate.ia.ptr.p_int[1] = k;
65494 0 : state->rstate.ia.ptr.p_int[2] = n;
65495 0 : state->rstate.ia.ptr.p_int[3] = ng;
65496 0 : state->rstate.ia.ptr.p_int[4] = nh;
65497 0 : state->rstate.ba.ptr.p_bool[0] = b;
65498 0 : state->rstate.ra.ptr.p_double[0] = vleft;
65499 0 : state->rstate.ra.ptr.p_double[1] = vright;
65500 0 : return result;
65501 : }
65502 :
65503 :
65504 : /*************************************************************************
65505 : This function activates/deactivates verification of the user-supplied
65506 : analytic gradient/Jacobian.
65507 :
65508 : Upon activation of this option OptGuard integrity checker performs
65509 : numerical differentiation of your target function (constraints) at the
65510 : initial point (note: future versions may also perform check at the final
65511 : point) and compares numerical gradient/Jacobian with analytic one provided
65512 : by you.
65513 :
65514 : If difference is too large, an error flag is set and optimization session
65515 : continues. After optimization session is over, you can retrieve the report
65516 : which stores both gradients/Jacobians, and specific components highlighted
65517 : as suspicious by the OptGuard.
65518 :
65519 : The primary OptGuard report can be retrieved with minnlcoptguardresults().
65520 :
65521 : IMPORTANT: gradient check is a high-overhead option which will cost you
65522 : about 3*N additional function evaluations. In many cases it may
65523 : cost as much as the rest of the optimization session.
65524 :
65525 : YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO
65526 : CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY.
65527 :
65528 : NOTE: unlike previous incarnation of the gradient checking code, OptGuard
65529 : does NOT interrupt optimization even if it discovers bad gradient.
65530 :
65531 : INPUT PARAMETERS:
65532 : State - structure used to store algorithm state
65533 : TestStep - verification step used for numerical differentiation:
65534 : * TestStep=0 turns verification off
65535 : * TestStep>0 activates verification
65536 : You should carefully choose TestStep. Value which is
65537 : too large (so large that function behavior is non-
65538 : cubic at this scale) will lead to false alarms. Too
65539 : short step will result in rounding errors dominating
65540 : numerical derivative.
65541 :
65542 : You may use different step for different parameters by
65543 : means of setting scale with minnlcsetscale().
65544 :
65545 : === EXPLANATION ==========================================================
65546 :
65547 : In order to verify gradient algorithm performs following steps:
65548 : * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i],
65549 : where X[i] is i-th component of the initial point and S[i] is a scale
65550 : of i-th parameter
65551 : * F(X) is evaluated at these trial points
65552 : * we perform one more evaluation in the middle point of the interval
65553 : * we build cubic model using function values and derivatives at trial
65554 : points and we compare its prediction with actual value in the middle
65555 : point
65556 :
65557 : -- ALGLIB --
65558 : Copyright 15.06.2014 by Bochkanov Sergey
65559 : *************************************************************************/
65560 0 : void minnlcoptguardgradient(minnlcstate* state,
65561 : double teststep,
65562 : ae_state *_state)
65563 : {
65564 :
65565 :
65566 0 : ae_assert(ae_isfinite(teststep, _state), "MinNLCOptGuardGradient: TestStep contains NaN or INF", _state);
65567 0 : ae_assert(ae_fp_greater_eq(teststep,(double)(0)), "MinNLCOptGuardGradient: invalid argument TestStep(TestStep<0)", _state);
65568 0 : state->teststep = teststep;
65569 0 : }
65570 :
65571 :
65572 : /*************************************************************************
65573 : This function activates/deactivates nonsmoothness monitoring option of
65574 : the OptGuard integrity checker. Smoothness monitor silently observes
65575 : solution process and tries to detect ill-posed problems, i.e. ones with:
65576 : a) discontinuous target function (non-C0) and/or constraints
65577 : b) nonsmooth target function (non-C1) and/or constraints
65578 :
65579 : Smoothness monitoring does NOT interrupt optimization even if it suspects
65580 : that your problem is nonsmooth. It just sets corresponding flags in the
65581 : OptGuard report which can be retrieved after optimization is over.
65582 :
65583 : Smoothness monitoring is a moderate overhead option which often adds less
65584 : than 1% to the optimizer running time. Thus, you can use it even for large
65585 : scale problems.
65586 :
65587 : NOTE: OptGuard does NOT guarantee that it will always detect C0/C1
65588 : continuity violations.
65589 :
65590 : First, minor errors are hard to catch - say, a 0.0001 difference in
65591 : the model values at two sides of the gap may be due to discontinuity
65592 : of the model - or simply because the model has changed.
65593 :
65594 : Second, C1-violations are especially difficult to detect in a
65595 : noninvasive way. The optimizer usually performs very short steps
65596 : near the nonsmoothness, and differentiation usually introduces a
65597 : lot of numerical noise. It is hard to tell whether some tiny
65598 : discontinuity in the slope is due to real nonsmoothness or just due
65599 : to numerical noise alone.
65600 :
65601 : Our top priority was to avoid false positives, so in some rare cases
65602 : minor errors may went unnoticed (however, in most cases they can be
65603 : spotted with restart from different initial point).
65604 :
65605 : INPUT PARAMETERS:
65606 : state - algorithm state
65607 : level - monitoring level:
65608 : * 0 - monitoring is disabled
65609 : * 1 - noninvasive low-overhead monitoring; function values
65610 : and/or gradients are recorded, but OptGuard does not
65611 : try to perform additional evaluations in order to
65612 : get more information about suspicious locations.
65613 : This kind of monitoring does not work well with SQP
65614 : because SQP solver needs just 1-2 function evaluations
65615 : per step, which is not enough for OptGuard to make
65616 : any conclusions.
65617 :
65618 : === EXPLANATION ==========================================================
65619 :
65620 : One major source of headache during optimization is the possibility of
65621 : the coding errors in the target function/constraints (or their gradients).
65622 : Such errors most often manifest themselves as discontinuity or
65623 : nonsmoothness of the target/constraints.
65624 :
65625 : Another frequent situation is when you try to optimize something involving
65626 : lots of min() and max() operations, i.e. nonsmooth target. Although not a
65627 : coding error, it is nonsmoothness anyway - and smooth optimizers usually
65628 : stop right after encountering nonsmoothness, well before reaching solution.
65629 :
65630 : OptGuard integrity checker helps you to catch such situations: it monitors
65631 : function values/gradients being passed to the optimizer and tries to
65632 : errors. Upon discovering suspicious pair of points it raises appropriate
65633 : flag (and allows you to continue optimization). When optimization is done,
65634 : you can study OptGuard result.
65635 :
65636 : -- ALGLIB --
65637 : Copyright 21.11.2018 by Bochkanov Sergey
65638 : *************************************************************************/
65639 0 : void minnlcoptguardsmoothness(minnlcstate* state,
65640 : ae_int_t level,
65641 : ae_state *_state)
65642 : {
65643 :
65644 :
65645 0 : ae_assert(level==0||level==1, "MinNLCOptGuardSmoothness: unexpected value of level parameter", _state);
65646 0 : state->smoothnessguardlevel = level;
65647 0 : }
65648 :
65649 :
65650 : /*************************************************************************
65651 : Results of OptGuard integrity check, should be called after optimization
65652 : session is over.
65653 :
65654 : === PRIMARY REPORT =======================================================
65655 :
65656 : OptGuard performs several checks which are intended to catch common errors
65657 : in the implementation of nonlinear function/gradient:
65658 : * incorrect analytic gradient
65659 : * discontinuous (non-C0) target functions (constraints)
65660 : * nonsmooth (non-C1) target functions (constraints)
65661 :
65662 : Each of these checks is activated with appropriate function:
65663 : * minnlcoptguardgradient() for gradient verification
65664 : * minnlcoptguardsmoothness() for C0/C1 checks
65665 :
65666 : Following flags are set when these errors are suspected:
65667 : * rep.badgradsuspected, and additionally:
65668 : * rep.badgradfidx for specific function (Jacobian row) suspected
65669 : * rep.badgradvidx for specific variable (Jacobian column) suspected
65670 : * rep.badgradxbase, a point where gradient/Jacobian is tested
65671 : * rep.badgraduser, user-provided gradient/Jacobian
65672 : * rep.badgradnum, reference gradient/Jacobian obtained via numerical
65673 : differentiation
65674 : * rep.nonc0suspected, and additionally:
65675 : * rep.nonc0fidx - an index of specific function violating C0 continuity
65676 : * rep.nonc1suspected, and additionally
65677 : * rep.nonc1fidx - an index of specific function violating C1 continuity
65678 : Here function index 0 means target function, index 1 or higher denotes
65679 : nonlinear constraints.
65680 :
65681 : === ADDITIONAL REPORTS/LOGS ==============================================
65682 :
65683 : Several different tests are performed to catch C0/C1 errors, you can find
65684 : out specific test signaled error by looking to:
65685 : * rep.nonc0test0positive, for non-C0 test #0
65686 : * rep.nonc1test0positive, for non-C1 test #0
65687 : * rep.nonc1test1positive, for non-C1 test #1
65688 :
65689 : Additional information (including line search logs) can be obtained by
65690 : means of:
65691 : * minnlcoptguardnonc1test0results()
65692 : * minnlcoptguardnonc1test1results()
65693 : which return detailed error reports, specific points where discontinuities
65694 : were found, and so on.
65695 :
65696 : ==========================================================================
65697 :
65698 : INPUT PARAMETERS:
65699 : state - algorithm state
65700 :
65701 : OUTPUT PARAMETERS:
65702 : rep - generic OptGuard report; more detailed reports can be
65703 : retrieved with other functions.
65704 :
65705 : NOTE: false negatives (nonsmooth problems are not identified as nonsmooth
65706 : ones) are possible although unlikely.
65707 :
65708 : The reason is that you need to make several evaluations around
65709 : nonsmoothness in order to accumulate enough information about
65710 : function curvature. Say, if you start right from the nonsmooth point,
65711 : optimizer simply won't get enough data to understand what is going
65712 : wrong before it terminates due to abrupt changes in the derivative.
65713 : It is also possible that "unlucky" step will move us to the
65714 : termination too quickly.
65715 :
65716 : Our current approach is to have less than 0.1% false negatives in
65717 : our test examples (measured with multiple restarts from random
65718 : points), and to have exactly 0% false positives.
65719 :
65720 : -- ALGLIB --
65721 : Copyright 21.11.2018 by Bochkanov Sergey
65722 : *************************************************************************/
65723 0 : void minnlcoptguardresults(minnlcstate* state,
65724 : optguardreport* rep,
65725 : ae_state *_state)
65726 : {
65727 :
65728 0 : _optguardreport_clear(rep);
65729 :
65730 0 : smoothnessmonitorexportreport(&state->smonitor, rep, _state);
65731 0 : }
65732 :
65733 :
65734 : /*************************************************************************
65735 : Detailed results of the OptGuard integrity check for nonsmoothness test #0
65736 :
65737 : Nonsmoothness (non-C1) test #0 studies function values (not gradient!)
65738 : obtained during line searches and monitors behavior of the directional
65739 : derivative estimate.
65740 :
65741 : This test is less powerful than test #1, but it does not depend on the
65742 : gradient values and thus it is more robust against artifacts introduced by
65743 : numerical differentiation.
65744 :
65745 : Two reports are returned:
65746 : * a "strongest" one, corresponding to line search which had highest
65747 : value of the nonsmoothness indicator
65748 : * a "longest" one, corresponding to line search which had more function
65749 : evaluations, and thus is more detailed
65750 :
65751 : In both cases following fields are returned:
65752 :
65753 : * positive - is TRUE when test flagged suspicious point; FALSE if test
65754 : did not notice anything (in the latter cases fields below are empty).
65755 : * fidx - is an index of the function (0 for target function, 1 or higher
65756 : for nonlinear constraints) which is suspected of being "non-C1"
65757 : * x0[], d[] - arrays of length N which store initial point and direction
65758 : for line search (d[] can be normalized, but does not have to)
65759 : * stp[], f[] - arrays of length CNT which store step lengths and function
65760 : values at these points; f[i] is evaluated in x0+stp[i]*d.
65761 : * stpidxa, stpidxb - we suspect that function violates C1 continuity
65762 : between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3,
65763 : with most likely position of the violation between stpidxa+1 and
65764 : stpidxa+2.
65765 :
65766 : ==========================================================================
65767 : = SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will
65768 : = see where C1 continuity is violated.
65769 : ==========================================================================
65770 :
65771 : INPUT PARAMETERS:
65772 : state - algorithm state
65773 :
65774 : OUTPUT PARAMETERS:
65775 : strrep - C1 test #0 "strong" report
65776 : lngrep - C1 test #0 "long" report
65777 :
65778 : -- ALGLIB --
65779 : Copyright 21.11.2018 by Bochkanov Sergey
65780 : *************************************************************************/
65781 0 : void minnlcoptguardnonc1test0results(minnlcstate* state,
65782 : optguardnonc1test0report* strrep,
65783 : optguardnonc1test0report* lngrep,
65784 : ae_state *_state)
65785 : {
65786 :
65787 0 : _optguardnonc1test0report_clear(strrep);
65788 0 : _optguardnonc1test0report_clear(lngrep);
65789 :
65790 0 : smoothnessmonitorexportc1test0report(&state->smonitor.nonc1test0strrep, &state->lastscaleused, strrep, _state);
65791 0 : smoothnessmonitorexportc1test0report(&state->smonitor.nonc1test0lngrep, &state->lastscaleused, lngrep, _state);
65792 0 : }
65793 :
65794 :
65795 : /*************************************************************************
65796 : Detailed results of the OptGuard integrity check for nonsmoothness test #1
65797 :
65798 : Nonsmoothness (non-C1) test #1 studies individual components of the
65799 : gradient computed during line search.
65800 :
65801 : When precise analytic gradient is provided this test is more powerful than
65802 : test #0 which works with function values and ignores user-provided
65803 : gradient. However, test #0 becomes more powerful when numerical
65804 : differentiation is employed (in such cases test #1 detects higher levels
65805 : of numerical noise and becomes too conservative).
65806 :
65807 : This test also tells specific components of the gradient which violate C1
65808 : continuity, which makes it more informative than #0, which just tells that
65809 : continuity is violated.
65810 :
65811 : Two reports are returned:
65812 : * a "strongest" one, corresponding to line search which had highest
65813 : value of the nonsmoothness indicator
65814 : * a "longest" one, corresponding to line search which had more function
65815 : evaluations, and thus is more detailed
65816 :
65817 : In both cases following fields are returned:
65818 :
65819 : * positive - is TRUE when test flagged suspicious point; FALSE if test
65820 : did not notice anything (in the latter cases fields below are empty).
65821 : * fidx - is an index of the function (0 for target function, 1 or higher
65822 : for nonlinear constraints) which is suspected of being "non-C1"
65823 : * vidx - is an index of the variable in [0,N) with nonsmooth derivative
65824 : * x0[], d[] - arrays of length N which store initial point and direction
65825 : for line search (d[] can be normalized, but does not have to)
65826 : * stp[], g[] - arrays of length CNT which store step lengths and gradient
65827 : values at these points; g[i] is evaluated in x0+stp[i]*d and contains
65828 : vidx-th component of the gradient.
65829 : * stpidxa, stpidxb - we suspect that function violates C1 continuity
65830 : between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3,
65831 : with most likely position of the violation between stpidxa+1 and
65832 : stpidxa+2.
65833 :
65834 : ==========================================================================
65835 : = SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will
65836 : = see where C1 continuity is violated.
65837 : ==========================================================================
65838 :
65839 : INPUT PARAMETERS:
65840 : state - algorithm state
65841 :
65842 : OUTPUT PARAMETERS:
65843 : strrep - C1 test #1 "strong" report
65844 : lngrep - C1 test #1 "long" report
65845 :
65846 : -- ALGLIB --
65847 : Copyright 21.11.2018 by Bochkanov Sergey
65848 : *************************************************************************/
65849 0 : void minnlcoptguardnonc1test1results(minnlcstate* state,
65850 : optguardnonc1test1report* strrep,
65851 : optguardnonc1test1report* lngrep,
65852 : ae_state *_state)
65853 : {
65854 :
65855 0 : _optguardnonc1test1report_clear(strrep);
65856 0 : _optguardnonc1test1report_clear(lngrep);
65857 :
65858 0 : smoothnessmonitorexportc1test1report(&state->smonitor.nonc1test1strrep, &state->lastscaleused, strrep, _state);
65859 0 : smoothnessmonitorexportc1test1report(&state->smonitor.nonc1test1lngrep, &state->lastscaleused, lngrep, _state);
65860 0 : }
65861 :
65862 :
65863 : /*************************************************************************
65864 : MinNLC results: the solution found, completion codes and additional
65865 : information.
65866 :
65867 : If you activated OptGuard integrity checking functionality and want to get
65868 : OptGuard report, it can be retrieved with:
65869 : * minnlcoptguardresults() - for a primary report about (a) suspected C0/C1
65870 : continuity violations and (b) errors in the analytic gradient.
65871 : * minnlcoptguardnonc1test0results() - for C1 continuity violation test #0,
65872 : detailed line search log
65873 : * minnlcoptguardnonc1test1results() - for C1 continuity violation test #1,
65874 : detailed line search log
65875 :
65876 : INPUT PARAMETERS:
65877 : State - algorithm state
65878 :
65879 : OUTPUT PARAMETERS:
65880 : X - array[0..N-1], solution
65881 : Rep - optimization report, contains information about completion
65882 : code, constraint violation at the solution and so on.
65883 :
65884 : You should check rep.terminationtype in order to
65885 : distinguish successful termination from unsuccessful one:
65886 :
65887 : === FAILURE CODES ===
65888 : * -8 internal integrity control detected infinite or
65889 : NAN values in function/gradient. Abnormal
65890 : termination signalled.
65891 : * -3 box constraints are infeasible.
65892 : Note: infeasibility of non-box constraints does
65893 : NOT trigger emergency completion; you have
65894 : to examine rep.bcerr/rep.lcerr/rep.nlcerr to
65895 : detect possibly inconsistent constraints.
65896 :
65897 : === SUCCESS CODES ===
65898 : * 2 scaled step is no more than EpsX.
65899 : * 5 MaxIts steps were taken.
65900 : * 8 user requested algorithm termination via
65901 : minnlcrequesttermination(), last accepted point is
65902 : returned.
65903 :
65904 : More information about fields of this structure can be
65905 : found in the comments on minnlcreport datatype.
65906 :
65907 : -- ALGLIB --
65908 : Copyright 06.06.2014 by Bochkanov Sergey
65909 : *************************************************************************/
65910 0 : void minnlcresults(minnlcstate* state,
65911 : /* Real */ ae_vector* x,
65912 : minnlcreport* rep,
65913 : ae_state *_state)
65914 : {
65915 :
65916 0 : ae_vector_clear(x);
65917 0 : _minnlcreport_clear(rep);
65918 :
65919 0 : minnlcresultsbuf(state, x, rep, _state);
65920 0 : }
65921 :
65922 :
65923 : /*************************************************************************
65924 : NLC results
65925 :
65926 : Buffered implementation of MinNLCResults() which uses pre-allocated buffer
65927 : to store X[]. If buffer size is too small, it resizes buffer. It is
65928 : intended to be used in the inner cycles of performance critical algorithms
65929 : where array reallocation penalty is too large to be ignored.
65930 :
65931 : -- ALGLIB --
65932 : Copyright 28.11.2010 by Bochkanov Sergey
65933 : *************************************************************************/
65934 0 : void minnlcresultsbuf(minnlcstate* state,
65935 : /* Real */ ae_vector* x,
65936 : minnlcreport* rep,
65937 : ae_state *_state)
65938 : {
65939 : ae_int_t i;
65940 :
65941 :
65942 0 : if( x->cnt<state->n )
65943 : {
65944 0 : ae_vector_set_length(x, state->n, _state);
65945 : }
65946 0 : rep->iterationscount = state->repinneriterationscount;
65947 0 : rep->nfev = state->repnfev;
65948 0 : rep->terminationtype = state->repterminationtype;
65949 0 : rep->bcerr = state->repbcerr;
65950 0 : rep->bcidx = state->repbcidx;
65951 0 : rep->lcerr = state->replcerr;
65952 0 : rep->lcidx = state->replcidx;
65953 0 : rep->nlcerr = state->repnlcerr;
65954 0 : rep->nlcidx = state->repnlcidx;
65955 0 : rep->dbgphase0its = state->repdbgphase0its;
65956 0 : if( state->repterminationtype>0 )
65957 : {
65958 0 : ae_v_move(&x->ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,state->n-1));
65959 : }
65960 : else
65961 : {
65962 0 : for(i=0; i<=state->n-1; i++)
65963 : {
65964 0 : x->ptr.p_double[i] = _state->v_nan;
65965 : }
65966 : }
65967 0 : }
65968 :
65969 :
65970 : /*************************************************************************
65971 : This subroutine submits request for termination of running optimizer. It
65972 : should be called from user-supplied callback when user decides that it is
65973 : time to "smoothly" terminate optimization process. As result, optimizer
65974 : stops at point which was "current accepted" when termination request was
65975 : submitted and returns error code 8 (successful termination).
65976 :
65977 : INPUT PARAMETERS:
65978 : State - optimizer structure
65979 :
65980 : NOTE: after request for termination optimizer may perform several
65981 : additional calls to user-supplied callbacks. It does NOT guarantee
65982 : to stop immediately - it just guarantees that these additional calls
65983 : will be discarded later.
65984 :
65985 : NOTE: calling this function on optimizer which is NOT running will have no
65986 : effect.
65987 :
65988 : NOTE: multiple calls to this function are possible. First call is counted,
65989 : subsequent calls are silently ignored.
65990 :
65991 : -- ALGLIB --
65992 : Copyright 08.10.2014 by Bochkanov Sergey
65993 : *************************************************************************/
65994 0 : void minnlcrequesttermination(minnlcstate* state, ae_state *_state)
65995 : {
65996 :
65997 :
65998 0 : state->userterminationneeded = ae_true;
65999 0 : }
66000 :
66001 :
66002 : /*************************************************************************
66003 : This subroutine restarts algorithm from new point.
66004 : All optimization parameters (including constraints) are left unchanged.
66005 :
66006 : This function allows to solve multiple optimization problems (which
66007 : must have same number of dimensions) without object reallocation penalty.
66008 :
66009 : INPUT PARAMETERS:
66010 : State - structure previously allocated with MinNLCCreate call.
66011 : X - new starting point.
66012 :
66013 : -- ALGLIB --
66014 : Copyright 28.11.2010 by Bochkanov Sergey
66015 : *************************************************************************/
66016 0 : void minnlcrestartfrom(minnlcstate* state,
66017 : /* Real */ ae_vector* x,
66018 : ae_state *_state)
66019 : {
66020 : ae_int_t n;
66021 :
66022 :
66023 0 : n = state->n;
66024 :
66025 : /*
66026 : * First, check for errors in the inputs
66027 : */
66028 0 : ae_assert(x->cnt>=n, "MinNLCRestartFrom: Length(X)<N", _state);
66029 0 : ae_assert(isfinitevector(x, n, _state), "MinNLCRestartFrom: X contains infinite or NaN values!", _state);
66030 :
66031 : /*
66032 : * Set XC
66033 : */
66034 0 : ae_v_move(&state->xstart.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
66035 :
66036 : /*
66037 : * prepare RComm facilities
66038 : */
66039 0 : ae_vector_set_length(&state->rstate.ia, 4+1, _state);
66040 0 : ae_vector_set_length(&state->rstate.ba, 0+1, _state);
66041 0 : ae_vector_set_length(&state->rstate.ra, 1+1, _state);
66042 0 : state->rstate.stage = -1;
66043 0 : minnlc_clearrequestfields(state, _state);
66044 0 : }
66045 :
66046 :
66047 : /*************************************************************************
66048 : Penalty function for equality constraints.
66049 : INPUT PARAMETERS:
66050 : Alpha - function argument. Penalty function becomes large when
66051 : Alpha approaches -1 or +1. It is defined for Alpha<=-1 or
66052 : Alpha>=+1 - in this case infinite value is returned.
66053 :
66054 : OUTPUT PARAMETERS:
66055 : F - depending on Alpha:
66056 : * for Alpha in (-1+eps,+1-eps), F=F(Alpha)
66057 : * for Alpha outside of interval, F is some very large number
66058 : DF - depending on Alpha:
66059 : * for Alpha in (-1+eps,+1-eps), DF=dF(Alpha)/dAlpha, exact
66060 : numerical derivative.
66061 : * otherwise, it is zero
66062 : D2F - second derivative
66063 :
66064 : -- ALGLIB --
66065 : Copyright 06.06.2014 by Bochkanov Sergey
66066 : *************************************************************************/
66067 0 : void minnlcequalitypenaltyfunction(double alpha,
66068 : double* f,
66069 : double* df,
66070 : double* d2f,
66071 : ae_state *_state)
66072 : {
66073 :
66074 0 : *f = 0;
66075 0 : *df = 0;
66076 0 : *d2f = 0;
66077 :
66078 0 : *f = 0.5*alpha*alpha;
66079 0 : *df = alpha;
66080 0 : *d2f = 1.0;
66081 0 : }
66082 :
66083 :
66084 : /*************************************************************************
66085 : "Penalty" function for inequality constraints, which is multiplied by
66086 : penalty coefficient Rho.
66087 :
66088 : "Penalty" function plays only supplementary role - it helps to stabilize
66089 : algorithm when solving non-convex problems. Because it is multiplied by
66090 : fixed and large Rho - not Lagrange multiplier Nu which may become
66091 : arbitrarily small! - it enforces convexity of the problem behind the
66092 : boundary of the feasible area.
66093 :
66094 : This function is zero at the feasible area and in the close neighborhood,
66095 : it becomes non-zero only at some distance (scaling is essential!) and grows
66096 : quadratically.
66097 :
66098 : Penalty function must enter augmented Lagrangian as
66099 : Rho*PENALTY(x-lowerbound)
66100 : with corresponding changes being made for upper bound or other kinds of
66101 : constraints.
66102 :
66103 : INPUT PARAMETERS:
66104 : Alpha - function argument. Typically, if we have active constraint
66105 : with precise Lagrange multiplier, we have Alpha around 1.
66106 : Large positive Alpha's correspond to inner area of the
66107 : feasible set. Alpha<1 corresponds to outer area of the
66108 : feasible set.
66109 : StabilizingPoint- point where F becomes non-zero. Must be negative
66110 : value, at least -1, large values (hundreds) are possible.
66111 :
66112 : OUTPUT PARAMETERS:
66113 : F - F(Alpha)
66114 : DF - DF=dF(Alpha)/dAlpha, exact derivative
66115 : D2F - second derivative
66116 :
66117 : NOTE: it is important to have significantly non-zero StabilizingPoint,
66118 : because when it is large, shift term does not interfere with
66119 : Lagrange multipliers converging to their final values. Thus,
66120 : convergence of such modified AUL algorithm is still guaranteed by
66121 : same set of theorems.
66122 :
66123 : -- ALGLIB --
66124 : Copyright 06.06.2014 by Bochkanov Sergey
66125 : *************************************************************************/
66126 0 : void minnlcinequalitypenaltyfunction(double alpha,
66127 : double stabilizingpoint,
66128 : double* f,
66129 : double* df,
66130 : double* d2f,
66131 : ae_state *_state)
66132 : {
66133 :
66134 0 : *f = 0;
66135 0 : *df = 0;
66136 0 : *d2f = 0;
66137 :
66138 0 : if( ae_fp_greater_eq(alpha,stabilizingpoint) )
66139 : {
66140 0 : *f = 0.0;
66141 0 : *df = 0.0;
66142 0 : *d2f = 0.0;
66143 : }
66144 : else
66145 : {
66146 0 : alpha = alpha-stabilizingpoint;
66147 0 : *f = 0.5*alpha*alpha;
66148 0 : *df = alpha;
66149 0 : *d2f = 1.0;
66150 : }
66151 0 : }
66152 :
66153 :
66154 : /*************************************************************************
66155 : "Shift" function for inequality constraints, which is multiplied by
66156 : corresponding Lagrange multiplier.
66157 :
66158 : "Shift" function is a main factor which enforces inequality constraints.
66159 : Inequality penalty function plays only supplementary role - it prevents
66160 : accidental step deep into infeasible area when working with non-convex
66161 : problems (read comments on corresponding function for more information).
66162 :
66163 : Shift function must enter augmented Lagrangian as
66164 : Nu/Rho*SHIFT((x-lowerbound)*Rho+1)
66165 : with corresponding changes being made for upper bound or other kinds of
66166 : constraints.
66167 :
66168 : INPUT PARAMETERS:
66169 : Alpha - function argument. Typically, if we have active constraint
66170 : with precise Lagrange multiplier, we have Alpha around 1.
66171 : Large positive Alpha's correspond to inner area of the
66172 : feasible set. Alpha<1 corresponds to outer area of the
66173 : feasible set.
66174 :
66175 : OUTPUT PARAMETERS:
66176 : F - F(Alpha)
66177 : DF - DF=dF(Alpha)/dAlpha, exact derivative
66178 : D2F - second derivative
66179 :
66180 : -- ALGLIB --
66181 : Copyright 06.06.2014 by Bochkanov Sergey
66182 : *************************************************************************/
66183 0 : void minnlcinequalityshiftfunction(double alpha,
66184 : double* f,
66185 : double* df,
66186 : double* d2f,
66187 : ae_state *_state)
66188 : {
66189 :
66190 0 : *f = 0;
66191 0 : *df = 0;
66192 0 : *d2f = 0;
66193 :
66194 0 : if( ae_fp_greater_eq(alpha,0.5) )
66195 : {
66196 0 : *f = -ae_log(alpha, _state);
66197 0 : *df = -1/alpha;
66198 0 : *d2f = 1/(alpha*alpha);
66199 : }
66200 : else
66201 : {
66202 0 : *f = 2*alpha*alpha-4*alpha+(ae_log((double)(2), _state)+1.5);
66203 0 : *df = 4*alpha-4;
66204 0 : *d2f = (double)(4);
66205 : }
66206 0 : }
66207 :
66208 :
66209 : /*************************************************************************
66210 : Clears request fileds (to be sure that we don't forget to clear something)
66211 : *************************************************************************/
66212 0 : static void minnlc_clearrequestfields(minnlcstate* state,
66213 : ae_state *_state)
66214 : {
66215 :
66216 :
66217 0 : state->needfi = ae_false;
66218 0 : state->needfij = ae_false;
66219 0 : state->xupdated = ae_false;
66220 0 : }
66221 :
66222 :
66223 : /*************************************************************************
66224 : Internal initialization subroutine.
66225 : Sets default NLC solver with default criteria.
66226 : *************************************************************************/
66227 0 : static void minnlc_minnlcinitinternal(ae_int_t n,
66228 : /* Real */ ae_vector* x,
66229 : double diffstep,
66230 : minnlcstate* state,
66231 : ae_state *_state)
66232 : {
66233 : ae_frame _frame_block;
66234 : ae_int_t i;
66235 : ae_matrix c;
66236 : ae_vector ct;
66237 :
66238 0 : ae_frame_make(_state, &_frame_block);
66239 0 : memset(&c, 0, sizeof(c));
66240 0 : memset(&ct, 0, sizeof(ct));
66241 0 : ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
66242 0 : ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
66243 :
66244 :
66245 : /*
66246 : * Default params
66247 : */
66248 0 : state->stabilizingpoint = -2.0;
66249 0 : state->initialinequalitymultiplier = 1.0;
66250 :
66251 : /*
66252 : * Smoothness monitor, default init
66253 : */
66254 0 : state->teststep = (double)(0);
66255 0 : state->smoothnessguardlevel = 0;
66256 0 : smoothnessmonitorinit(&state->smonitor, &state->s, 0, 0, ae_false, _state);
66257 :
66258 : /*
66259 : * Initialize other params
66260 : */
66261 0 : state->n = n;
66262 0 : state->diffstep = diffstep;
66263 0 : state->userterminationneeded = ae_false;
66264 0 : ae_vector_set_length(&state->bndl, n, _state);
66265 0 : ae_vector_set_length(&state->hasbndl, n, _state);
66266 0 : ae_vector_set_length(&state->bndu, n, _state);
66267 0 : ae_vector_set_length(&state->hasbndu, n, _state);
66268 0 : ae_vector_set_length(&state->s, n, _state);
66269 0 : ae_vector_set_length(&state->lastscaleused, n, _state);
66270 0 : ae_vector_set_length(&state->xstart, n, _state);
66271 0 : ae_vector_set_length(&state->xc, n, _state);
66272 0 : ae_vector_set_length(&state->x, n, _state);
66273 0 : for(i=0; i<=n-1; i++)
66274 : {
66275 0 : state->bndl.ptr.p_double[i] = _state->v_neginf;
66276 0 : state->hasbndl.ptr.p_bool[i] = ae_false;
66277 0 : state->bndu.ptr.p_double[i] = _state->v_posinf;
66278 0 : state->hasbndu.ptr.p_bool[i] = ae_false;
66279 0 : state->s.ptr.p_double[i] = 1.0;
66280 0 : state->lastscaleused.ptr.p_double[i] = 1.0;
66281 0 : state->xstart.ptr.p_double[i] = x->ptr.p_double[i];
66282 0 : state->xc.ptr.p_double[i] = x->ptr.p_double[i];
66283 : }
66284 0 : minnlcsetlc(state, &c, &ct, 0, _state);
66285 0 : minnlcsetnlc(state, 0, 0, _state);
66286 0 : minnlcsetcond(state, 0.0, 0, _state);
66287 0 : minnlcsetxrep(state, ae_false, _state);
66288 0 : minnlcsetalgosqp(state, _state);
66289 0 : minnlcsetprecexactrobust(state, 0, _state);
66290 0 : minnlcsetstpmax(state, 0.0, _state);
66291 0 : minlbfgscreate(n, ae_minint(minnlc_lbfgsfactor, n, _state), x, &state->auloptimizer, _state);
66292 0 : minnlcrestartfrom(state, x, _state);
66293 0 : ae_frame_leave(_state);
66294 0 : }
66295 :
66296 :
66297 : /*************************************************************************
66298 : This function clears preconditioner for L-BFGS optimizer (sets it do default
66299 : state);
66300 :
66301 : Parameters:
66302 : AULOptimizer - optimizer to tune
66303 :
66304 : -- ALGLIB --
66305 : Copyright 06.06.2014 by Bochkanov Sergey
66306 : *************************************************************************/
66307 0 : static void minnlc_clearpreconditioner(minlbfgsstate* auloptimizer,
66308 : ae_state *_state)
66309 : {
66310 :
66311 :
66312 0 : minlbfgssetprecdefault(auloptimizer, _state);
66313 0 : }
66314 :
66315 :
66316 : /*************************************************************************
66317 : This function updates preconditioner for L-BFGS optimizer.
66318 :
66319 : Parameters:
66320 : PrecType - preconditioner type:
66321 : * 0 for unpreconditioned iterations
66322 : * 1 for inexact LBFGS
66323 : * 2 for exact low rank preconditioner update after each UpdateFreq its
66324 : * 3 for exact robust preconditioner update after each UpdateFreq its
66325 : UpdateFreq - update frequency
66326 : PrecCounter - iterations counter, must be zero on the first call,
66327 : automatically increased by this function. This
66328 : counter is used to implement "update-once-in-X-iterations"
66329 : scheme.
66330 : AULOptimizer - optimizer to tune
66331 : X - current point
66332 : Rho - penalty term
66333 : GammaK - current estimate of Hessian norm (used for
66334 : initialization of preconditioner). Can be zero, in
66335 : which case Hessian is assumed to be unit.
66336 :
66337 : -- ALGLIB --
66338 : Copyright 06.06.2014 by Bochkanov Sergey
66339 : *************************************************************************/
66340 0 : static void minnlc_updatepreconditioner(ae_int_t prectype,
66341 : ae_int_t updatefreq,
66342 : ae_int_t* preccounter,
66343 : minlbfgsstate* auloptimizer,
66344 : /* Real */ ae_vector* x,
66345 : double rho,
66346 : double gammak,
66347 : /* Real */ ae_vector* bndl,
66348 : /* Boolean */ ae_vector* hasbndl,
66349 : /* Real */ ae_vector* bndu,
66350 : /* Boolean */ ae_vector* hasbndu,
66351 : /* Real */ ae_vector* nubc,
66352 : /* Real */ ae_matrix* cleic,
66353 : /* Real */ ae_vector* nulc,
66354 : /* Real */ ae_vector* fi,
66355 : /* Real */ ae_matrix* jac,
66356 : /* Real */ ae_vector* nunlc,
66357 : /* Real */ ae_vector* bufd,
66358 : /* Real */ ae_vector* bufc,
66359 : /* Real */ ae_matrix* bufw,
66360 : /* Real */ ae_matrix* bufz,
66361 : /* Real */ ae_vector* tmp0,
66362 : ae_int_t n,
66363 : ae_int_t nec,
66364 : ae_int_t nic,
66365 : ae_int_t ng,
66366 : ae_int_t nh,
66367 : ae_state *_state)
66368 : {
66369 : ae_int_t i;
66370 : ae_int_t j;
66371 : ae_int_t k;
66372 : double v;
66373 : double p;
66374 : double dp;
66375 : double d2p;
66376 : ae_bool bflag;
66377 :
66378 :
66379 0 : ae_assert(ae_fp_greater(rho,(double)(0)), "MinNLC: integrity check failed", _state);
66380 0 : rvectorsetlengthatleast(bufd, n, _state);
66381 0 : rvectorsetlengthatleast(bufc, nec+nic+ng+nh, _state);
66382 0 : rmatrixsetlengthatleast(bufw, nec+nic+ng+nh, n, _state);
66383 0 : rvectorsetlengthatleast(tmp0, n, _state);
66384 :
66385 : /*
66386 : * Preconditioner before update from barrier/penalty functions
66387 : */
66388 0 : if( ae_fp_eq(gammak,(double)(0)) )
66389 : {
66390 0 : gammak = (double)(1);
66391 : }
66392 0 : for(i=0; i<=n-1; i++)
66393 : {
66394 0 : bufd->ptr.p_double[i] = gammak;
66395 : }
66396 :
66397 : /*
66398 : * Update diagonal Hessian using nonlinearity from boundary constraints:
66399 : * * penalty term from equality constraints
66400 : * * shift term from inequality constraints
66401 : *
66402 : * NOTE: penalty term for inequality constraints is ignored because it
66403 : * is large only in exceptional cases.
66404 : */
66405 0 : for(i=0; i<=n-1; i++)
66406 : {
66407 0 : if( (hasbndl->ptr.p_bool[i]&&hasbndu->ptr.p_bool[i])&&ae_fp_eq(bndl->ptr.p_double[i],bndu->ptr.p_double[i]) )
66408 : {
66409 0 : minnlcequalitypenaltyfunction((x->ptr.p_double[i]-bndl->ptr.p_double[i])*rho, &p, &dp, &d2p, _state);
66410 0 : bufd->ptr.p_double[i] = bufd->ptr.p_double[i]+d2p*rho;
66411 0 : continue;
66412 : }
66413 0 : if( hasbndl->ptr.p_bool[i] )
66414 : {
66415 0 : minnlcinequalityshiftfunction((x->ptr.p_double[i]-bndl->ptr.p_double[i])*rho+1, &p, &dp, &d2p, _state);
66416 0 : bufd->ptr.p_double[i] = bufd->ptr.p_double[i]+nubc->ptr.p_double[2*i+0]*d2p*rho;
66417 : }
66418 0 : if( hasbndu->ptr.p_bool[i] )
66419 : {
66420 0 : minnlcinequalityshiftfunction((bndu->ptr.p_double[i]-x->ptr.p_double[i])*rho+1, &p, &dp, &d2p, _state);
66421 0 : bufd->ptr.p_double[i] = bufd->ptr.p_double[i]+nubc->ptr.p_double[2*i+1]*d2p*rho;
66422 : }
66423 : }
66424 :
66425 : /*
66426 : * Process linear constraints
66427 : */
66428 0 : for(i=0; i<=nec+nic-1; i++)
66429 : {
66430 0 : ae_v_move(&bufw->ptr.pp_double[i][0], 1, &cleic->ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
66431 0 : v = ae_v_dotproduct(&cleic->ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
66432 0 : v = v-cleic->ptr.pp_double[i][n];
66433 0 : if( i<nec )
66434 : {
66435 :
66436 : /*
66437 : * Equality constraint
66438 : */
66439 0 : minnlcequalitypenaltyfunction(v*rho, &p, &dp, &d2p, _state);
66440 0 : bufc->ptr.p_double[i] = d2p*rho;
66441 : }
66442 : else
66443 : {
66444 :
66445 : /*
66446 : * Inequality constraint
66447 : */
66448 0 : minnlcinequalityshiftfunction(-v*rho+1, &p, &dp, &d2p, _state);
66449 0 : bufc->ptr.p_double[i] = nulc->ptr.p_double[i]*d2p*rho;
66450 : }
66451 : }
66452 :
66453 : /*
66454 : * Process nonlinear constraints
66455 : */
66456 0 : for(i=0; i<=ng+nh-1; i++)
66457 : {
66458 0 : ae_v_move(&bufw->ptr.pp_double[nec+nic+i][0], 1, &jac->ptr.pp_double[1+i][0], 1, ae_v_len(0,n-1));
66459 0 : v = fi->ptr.p_double[1+i];
66460 0 : if( i<ng )
66461 : {
66462 :
66463 : /*
66464 : * Equality constraint
66465 : */
66466 0 : minnlcequalitypenaltyfunction(v*rho, &p, &dp, &d2p, _state);
66467 0 : bufc->ptr.p_double[nec+nic+i] = d2p*rho;
66468 : }
66469 : else
66470 : {
66471 :
66472 : /*
66473 : * Inequality constraint
66474 : */
66475 0 : minnlcinequalityshiftfunction(-v*rho+1, &p, &dp, &d2p, _state);
66476 0 : bufc->ptr.p_double[nec+nic+i] = nunlc->ptr.p_double[i]*d2p*rho;
66477 : }
66478 : }
66479 :
66480 : /*
66481 : * Add regularizer (large Rho often result in nearly-degenerate matrices;
66482 : * sometimes Cholesky decomposition fails without regularization).
66483 : *
66484 : * We use RegPrec*diag(W'*W) as preconditioner.
66485 : */
66486 0 : k = nec+nic+ng+nh;
66487 0 : for(j=0; j<=n-1; j++)
66488 : {
66489 0 : tmp0->ptr.p_double[j] = 0.0;
66490 : }
66491 0 : for(i=0; i<=k-1; i++)
66492 : {
66493 0 : v = bufc->ptr.p_double[i];
66494 0 : for(j=0; j<=n-1; j++)
66495 : {
66496 0 : tmp0->ptr.p_double[j] = tmp0->ptr.p_double[j]+v*bufw->ptr.pp_double[i][j]*bufw->ptr.pp_double[i][j];
66497 : }
66498 : }
66499 0 : for(j=0; j<=n-1; j++)
66500 : {
66501 0 : bufd->ptr.p_double[j] = bufd->ptr.p_double[j]+minnlc_regprec*tmp0->ptr.p_double[j];
66502 : }
66503 :
66504 : /*
66505 : * Apply preconditioner
66506 : */
66507 0 : if( prectype==1 )
66508 : {
66509 0 : minlbfgssetprecrankklbfgsfast(auloptimizer, bufd, bufc, bufw, nec+nic+ng+nh, _state);
66510 : }
66511 0 : if( prectype==2&&*preccounter%updatefreq==0 )
66512 : {
66513 0 : minlbfgssetpreclowrankexact(auloptimizer, bufd, bufc, bufw, nec+nic+ng+nh, _state);
66514 : }
66515 0 : if( prectype==3&&*preccounter%updatefreq==0 )
66516 : {
66517 :
66518 : /*
66519 : * Generate full NxN dense Hessian
66520 : */
66521 0 : rmatrixsetlengthatleast(bufz, n, n, _state);
66522 0 : for(i=0; i<=n-1; i++)
66523 : {
66524 0 : for(j=0; j<=n-1; j++)
66525 : {
66526 0 : bufz->ptr.pp_double[i][j] = (double)(0);
66527 : }
66528 0 : bufz->ptr.pp_double[i][i] = bufd->ptr.p_double[i];
66529 : }
66530 0 : if( nec+nic+ng+nh>0 )
66531 : {
66532 0 : for(i=0; i<=nec+nic+ng+nh-1; i++)
66533 : {
66534 0 : ae_assert(ae_fp_greater_eq(bufc->ptr.p_double[i],(double)(0)), "MinNLC: updatepreconditioner() integrity failure", _state);
66535 0 : v = ae_sqrt(bufc->ptr.p_double[i], _state);
66536 0 : for(j=0; j<=n-1; j++)
66537 : {
66538 0 : bufw->ptr.pp_double[i][j] = bufw->ptr.pp_double[i][j]*v;
66539 : }
66540 : }
66541 0 : rmatrixsyrk(n, nec+nic+ng+nh, 1.0, bufw, 0, 0, 2, 1.0, bufz, 0, 0, ae_true, _state);
66542 : }
66543 :
66544 : /*
66545 : * Evaluate Cholesky decomposition, set preconditioner
66546 : */
66547 0 : bflag = spdmatrixcholeskyrec(bufz, 0, n, ae_true, bufd, _state);
66548 0 : ae_assert(bflag, "MinNLC: updatepreconditioner() failure, Cholesky failed", _state);
66549 0 : minlbfgssetpreccholesky(auloptimizer, bufz, ae_true, _state);
66550 : }
66551 0 : inc(preccounter, _state);
66552 0 : }
66553 :
66554 :
66555 : /*************************************************************************
66556 : This subroutine adds penalty from boundary constraints to target function
66557 : and its gradient. Penalty function is one which is used for main AUL cycle
66558 : - with Lagrange multipliers and infinite at the barrier and beyond.
66559 :
66560 : Parameters:
66561 : X[] - current point
66562 : BndL[], BndU[] - boundary constraints
66563 : HasBndL[], HasBndU[] - I-th element is True if corresponding constraint is present
66564 : NuBC[] - Lagrange multipliers corresponding to constraints
66565 : Rho - penalty term
66566 : StabilizingPoint - branch point for inequality stabilizing term
66567 : F - function value to modify
66568 : G - gradient to modify
66569 :
66570 : -- ALGLIB --
66571 : Copyright 06.06.2014 by Bochkanov Sergey
66572 : *************************************************************************/
66573 0 : static void minnlc_penaltybc(/* Real */ ae_vector* x,
66574 : /* Real */ ae_vector* bndl,
66575 : /* Boolean */ ae_vector* hasbndl,
66576 : /* Real */ ae_vector* bndu,
66577 : /* Boolean */ ae_vector* hasbndu,
66578 : /* Real */ ae_vector* nubc,
66579 : ae_int_t n,
66580 : double rho,
66581 : double stabilizingpoint,
66582 : double* f,
66583 : /* Real */ ae_vector* g,
66584 : ae_state *_state)
66585 : {
66586 : ae_int_t i;
66587 : double p;
66588 : double dp;
66589 : double d2p;
66590 :
66591 :
66592 0 : for(i=0; i<=n-1; i++)
66593 : {
66594 0 : if( (hasbndl->ptr.p_bool[i]&&hasbndu->ptr.p_bool[i])&&ae_fp_eq(bndl->ptr.p_double[i],bndu->ptr.p_double[i]) )
66595 : {
66596 :
66597 : /*
66598 : * I-th boundary constraint is of equality-type
66599 : */
66600 0 : minnlcequalitypenaltyfunction((x->ptr.p_double[i]-bndl->ptr.p_double[i])*rho, &p, &dp, &d2p, _state);
66601 0 : *f = *f+p/rho-nubc->ptr.p_double[2*i+0]*(x->ptr.p_double[i]-bndl->ptr.p_double[i]);
66602 0 : g->ptr.p_double[i] = g->ptr.p_double[i]+dp-nubc->ptr.p_double[2*i+0];
66603 0 : continue;
66604 : }
66605 0 : if( hasbndl->ptr.p_bool[i] )
66606 : {
66607 :
66608 : /*
66609 : * Handle lower bound
66610 : */
66611 0 : minnlcinequalitypenaltyfunction(x->ptr.p_double[i]-bndl->ptr.p_double[i], stabilizingpoint, &p, &dp, &d2p, _state);
66612 0 : *f = *f+rho*p;
66613 0 : g->ptr.p_double[i] = g->ptr.p_double[i]+rho*dp;
66614 0 : minnlcinequalityshiftfunction((x->ptr.p_double[i]-bndl->ptr.p_double[i])*rho+1, &p, &dp, &d2p, _state);
66615 0 : *f = *f+p/rho*nubc->ptr.p_double[2*i+0];
66616 0 : g->ptr.p_double[i] = g->ptr.p_double[i]+dp*nubc->ptr.p_double[2*i+0];
66617 : }
66618 0 : if( hasbndu->ptr.p_bool[i] )
66619 : {
66620 :
66621 : /*
66622 : * Handle upper bound
66623 : */
66624 0 : minnlcinequalitypenaltyfunction(bndu->ptr.p_double[i]-x->ptr.p_double[i], stabilizingpoint, &p, &dp, &d2p, _state);
66625 0 : *f = *f+rho*p;
66626 0 : g->ptr.p_double[i] = g->ptr.p_double[i]-rho*dp;
66627 0 : minnlcinequalityshiftfunction((bndu->ptr.p_double[i]-x->ptr.p_double[i])*rho+1, &p, &dp, &d2p, _state);
66628 0 : *f = *f+p/rho*nubc->ptr.p_double[2*i+1];
66629 0 : g->ptr.p_double[i] = g->ptr.p_double[i]-dp*nubc->ptr.p_double[2*i+1];
66630 : }
66631 : }
66632 0 : }
66633 :
66634 :
66635 : /*************************************************************************
66636 : This subroutine adds penalty from linear constraints to target function
66637 : and its gradient. Penalty function is one which is used for main AUL cycle
66638 : - with Lagrange multipliers and infinite at the barrier and beyond.
66639 :
66640 : Parameters:
66641 : X[] - current point
66642 : CLEIC[] - constraints matrix, first NEC rows are equality ones, next
66643 : NIC rows are inequality ones. array[NEC+NIC,N+1]
66644 : NuLC[] - Lagrange multipliers corresponding to constraints,
66645 : array[NEC+NIC]
66646 : N - dimensionalty
66647 : NEC - number of equality constraints
66648 : NIC - number of inequality constraints.
66649 : Rho - penalty term
66650 : StabilizingPoint - branch point for inequality stabilizing term
66651 : F - function value to modify
66652 : G - gradient to modify
66653 :
66654 : -- ALGLIB --
66655 : Copyright 06.06.2014 by Bochkanov Sergey
66656 : *************************************************************************/
66657 0 : static void minnlc_penaltylc(/* Real */ ae_vector* x,
66658 : /* Real */ ae_matrix* cleic,
66659 : /* Real */ ae_vector* nulc,
66660 : ae_int_t n,
66661 : ae_int_t nec,
66662 : ae_int_t nic,
66663 : double rho,
66664 : double stabilizingpoint,
66665 : double* f,
66666 : /* Real */ ae_vector* g,
66667 : ae_state *_state)
66668 : {
66669 : ae_int_t i;
66670 : double v;
66671 : double p;
66672 : double dp;
66673 : double d2p;
66674 : double fupd;
66675 : double gupd;
66676 :
66677 :
66678 0 : for(i=0; i<=nec+nic-1; i++)
66679 : {
66680 0 : v = ae_v_dotproduct(&cleic->ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
66681 0 : v = v-cleic->ptr.pp_double[i][n];
66682 0 : fupd = (double)(0);
66683 0 : gupd = (double)(0);
66684 0 : if( i<nec )
66685 : {
66686 :
66687 : /*
66688 : * Equality constraint
66689 : */
66690 0 : minnlcequalitypenaltyfunction(v*rho, &p, &dp, &d2p, _state);
66691 0 : fupd = fupd+p/rho;
66692 0 : gupd = gupd+dp;
66693 0 : fupd = fupd-nulc->ptr.p_double[i]*v;
66694 0 : gupd = gupd-nulc->ptr.p_double[i];
66695 : }
66696 : else
66697 : {
66698 :
66699 : /*
66700 : * Inequality constraint
66701 : */
66702 0 : minnlcinequalitypenaltyfunction(-v, stabilizingpoint, &p, &dp, &d2p, _state);
66703 0 : fupd = fupd+p*rho;
66704 0 : gupd = gupd-dp*rho;
66705 0 : minnlcinequalityshiftfunction(-v*rho+1, &p, &dp, &d2p, _state);
66706 0 : fupd = fupd+p/rho*nulc->ptr.p_double[i];
66707 0 : gupd = gupd-dp*nulc->ptr.p_double[i];
66708 : }
66709 0 : *f = *f+fupd;
66710 0 : ae_v_addd(&g->ptr.p_double[0], 1, &cleic->ptr.pp_double[i][0], 1, ae_v_len(0,n-1), gupd);
66711 : }
66712 0 : }
66713 :
66714 :
66715 : /*************************************************************************
66716 : This subroutine adds penalty from nonlinear constraints to target function
66717 : and its gradient. Penalty function is one which is used for main AUL cycle
66718 : - with Lagrange multipliers and infinite at the barrier and beyond.
66719 :
66720 : Parameters:
66721 : Fi[] - function vector:
66722 : * 1 component for function being minimized
66723 : * NG components for equality constraints G_i(x)=0
66724 : * NH components for inequality constraints H_i(x)<=0
66725 : J[] - Jacobian matrix, array[1+NG+NH,N]
66726 : NuNLC[] - Lagrange multipliers corresponding to constraints,
66727 : array[NG+NH]
66728 : N - number of dimensions
66729 : NG - number of equality constraints
66730 : NH - number of inequality constraints
66731 : Rho - penalty term
66732 : StabilizingPoint - branch point for inequality stabilizing term
66733 : F - function value to modify
66734 : G - gradient to modify
66735 :
66736 : -- ALGLIB --
66737 : Copyright 06.06.2014 by Bochkanov Sergey
66738 : *************************************************************************/
66739 0 : static void minnlc_penaltynlc(/* Real */ ae_vector* fi,
66740 : /* Real */ ae_matrix* j,
66741 : /* Real */ ae_vector* nunlc,
66742 : ae_int_t n,
66743 : ae_int_t ng,
66744 : ae_int_t nh,
66745 : double rho,
66746 : double stabilizingpoint,
66747 : double* f,
66748 : /* Real */ ae_vector* g,
66749 : ae_state *_state)
66750 : {
66751 : ae_int_t i;
66752 : double v;
66753 : double p;
66754 : double dp;
66755 : double d2p;
66756 : double fupd;
66757 : double gupd;
66758 :
66759 :
66760 :
66761 : /*
66762 : * IMPORTANT: loop starts from 1, not zero!
66763 : */
66764 0 : for(i=1; i<=ng+nh; i++)
66765 : {
66766 0 : v = fi->ptr.p_double[i];
66767 0 : fupd = (double)(0);
66768 0 : gupd = (double)(0);
66769 0 : if( i<=ng )
66770 : {
66771 :
66772 : /*
66773 : * Equality constraint
66774 : */
66775 0 : minnlcequalitypenaltyfunction(v*rho, &p, &dp, &d2p, _state);
66776 0 : fupd = fupd+p/rho;
66777 0 : gupd = gupd+dp;
66778 0 : fupd = fupd-nunlc->ptr.p_double[i-1]*v;
66779 0 : gupd = gupd-nunlc->ptr.p_double[i-1];
66780 : }
66781 : else
66782 : {
66783 :
66784 : /*
66785 : * Inequality constraint
66786 : */
66787 0 : minnlcinequalitypenaltyfunction(-v, stabilizingpoint, &p, &dp, &d2p, _state);
66788 0 : fupd = fupd+p*rho;
66789 0 : gupd = gupd-dp*rho;
66790 0 : minnlcinequalityshiftfunction(-v*rho+1, &p, &dp, &d2p, _state);
66791 0 : fupd = fupd+p/rho*nunlc->ptr.p_double[i-1];
66792 0 : gupd = gupd-dp*nunlc->ptr.p_double[i-1];
66793 : }
66794 0 : *f = *f+fupd;
66795 0 : ae_v_addd(&g->ptr.p_double[0], 1, &j->ptr.pp_double[i][0], 1, ae_v_len(0,n-1), gupd);
66796 : }
66797 0 : }
66798 :
66799 :
66800 : /*************************************************************************
66801 : This function performs actual processing for AUL algorithm. It expects that
66802 : caller redirects its reverse communication requests NeedFiJ/XUpdated to
66803 : external user who will provide analytic derivative (or handle reports about
66804 : progress).
66805 :
66806 : In case external user does not have analytic derivative, it is responsibility
66807 : of caller to intercept NeedFiJ request and replace it with appropriate
66808 : numerical differentiation scheme.
66809 :
66810 : -- ALGLIB --
66811 : Copyright 06.06.2014 by Bochkanov Sergey
66812 : *************************************************************************/
66813 0 : static ae_bool minnlc_auliteration(minnlcstate* state,
66814 : smoothnessmonitor* smonitor,
66815 : ae_state *_state)
66816 : {
66817 : ae_int_t n;
66818 : ae_int_t nec;
66819 : ae_int_t nic;
66820 : ae_int_t ng;
66821 : ae_int_t nh;
66822 : ae_int_t i;
66823 : ae_int_t j;
66824 : ae_int_t outerit;
66825 : ae_int_t preccounter;
66826 : double v;
66827 : double vv;
66828 : double p;
66829 : double dp;
66830 : double d2p;
66831 : double v0;
66832 : double v1;
66833 : double v2;
66834 : ae_bool result;
66835 :
66836 :
66837 :
66838 : /*
66839 : * Reverse communication preparations
66840 : * I know it looks ugly, but it works the same way
66841 : * anywhere from C++ to Python.
66842 : *
66843 : * This code initializes locals by:
66844 : * * random values determined during code
66845 : * generation - on first subroutine call
66846 : * * values from previous call - on subsequent calls
66847 : */
66848 0 : if( state->rstateaul.stage>=0 )
66849 : {
66850 0 : n = state->rstateaul.ia.ptr.p_int[0];
66851 0 : nec = state->rstateaul.ia.ptr.p_int[1];
66852 0 : nic = state->rstateaul.ia.ptr.p_int[2];
66853 0 : ng = state->rstateaul.ia.ptr.p_int[3];
66854 0 : nh = state->rstateaul.ia.ptr.p_int[4];
66855 0 : i = state->rstateaul.ia.ptr.p_int[5];
66856 0 : j = state->rstateaul.ia.ptr.p_int[6];
66857 0 : outerit = state->rstateaul.ia.ptr.p_int[7];
66858 0 : preccounter = state->rstateaul.ia.ptr.p_int[8];
66859 0 : v = state->rstateaul.ra.ptr.p_double[0];
66860 0 : vv = state->rstateaul.ra.ptr.p_double[1];
66861 0 : p = state->rstateaul.ra.ptr.p_double[2];
66862 0 : dp = state->rstateaul.ra.ptr.p_double[3];
66863 0 : d2p = state->rstateaul.ra.ptr.p_double[4];
66864 0 : v0 = state->rstateaul.ra.ptr.p_double[5];
66865 0 : v1 = state->rstateaul.ra.ptr.p_double[6];
66866 0 : v2 = state->rstateaul.ra.ptr.p_double[7];
66867 : }
66868 : else
66869 : {
66870 0 : n = 809;
66871 0 : nec = 205;
66872 0 : nic = -838;
66873 0 : ng = 939;
66874 0 : nh = -526;
66875 0 : i = 763;
66876 0 : j = -541;
66877 0 : outerit = -698;
66878 0 : preccounter = -900;
66879 0 : v = -318;
66880 0 : vv = -940;
66881 0 : p = 1016;
66882 0 : dp = -229;
66883 0 : d2p = -536;
66884 0 : v0 = 487;
66885 0 : v1 = -115;
66886 0 : v2 = 886;
66887 : }
66888 0 : if( state->rstateaul.stage==0 )
66889 : {
66890 0 : goto lbl_0;
66891 : }
66892 0 : if( state->rstateaul.stage==1 )
66893 : {
66894 0 : goto lbl_1;
66895 : }
66896 0 : if( state->rstateaul.stage==2 )
66897 : {
66898 0 : goto lbl_2;
66899 : }
66900 :
66901 : /*
66902 : * Routine body
66903 : */
66904 0 : ae_assert(state->solvertype==0, "MinNLC: internal error", _state);
66905 0 : n = state->n;
66906 0 : nec = state->nec;
66907 0 : nic = state->nic;
66908 0 : ng = state->ng;
66909 0 : nh = state->nh;
66910 :
66911 : /*
66912 : * Prepare scaled problem
66913 : */
66914 0 : rvectorsetlengthatleast(&state->scaledbndl, n, _state);
66915 0 : rvectorsetlengthatleast(&state->scaledbndu, n, _state);
66916 0 : rmatrixsetlengthatleast(&state->scaledcleic, nec+nic, n+1, _state);
66917 0 : for(i=0; i<=n-1; i++)
66918 : {
66919 0 : if( state->hasbndl.ptr.p_bool[i] )
66920 : {
66921 0 : state->scaledbndl.ptr.p_double[i] = state->bndl.ptr.p_double[i]/state->s.ptr.p_double[i];
66922 : }
66923 0 : if( state->hasbndu.ptr.p_bool[i] )
66924 : {
66925 0 : state->scaledbndu.ptr.p_double[i] = state->bndu.ptr.p_double[i]/state->s.ptr.p_double[i];
66926 : }
66927 0 : state->xc.ptr.p_double[i] = state->xstart.ptr.p_double[i]/state->s.ptr.p_double[i];
66928 : }
66929 0 : for(i=0; i<=nec+nic-1; i++)
66930 : {
66931 :
66932 : /*
66933 : * Scale and normalize linear constraints
66934 : */
66935 0 : vv = 0.0;
66936 0 : for(j=0; j<=n-1; j++)
66937 : {
66938 0 : v = state->cleic.ptr.pp_double[i][j]*state->s.ptr.p_double[j];
66939 0 : state->scaledcleic.ptr.pp_double[i][j] = v;
66940 0 : vv = vv+v*v;
66941 : }
66942 0 : vv = ae_sqrt(vv, _state);
66943 0 : state->scaledcleic.ptr.pp_double[i][n] = state->cleic.ptr.pp_double[i][n];
66944 0 : if( ae_fp_greater(vv,(double)(0)) )
66945 : {
66946 0 : for(j=0; j<=n; j++)
66947 : {
66948 0 : state->scaledcleic.ptr.pp_double[i][j] = state->scaledcleic.ptr.pp_double[i][j]/vv;
66949 : }
66950 : }
66951 : }
66952 :
66953 : /*
66954 : * Prepare stopping criteria
66955 : */
66956 0 : minlbfgssetcond(&state->auloptimizer, (double)(0), (double)(0), state->epsx, state->maxits, _state);
66957 0 : minlbfgssetstpmax(&state->auloptimizer, state->stpmax, _state);
66958 :
66959 : /*
66960 : * Main AUL cycle:
66961 : * * prepare Lagrange multipliers NuNB/NuLC
66962 : * * set GammaK (current estimate of Hessian norm) to InitGamma and XKPresent to False
66963 : */
66964 0 : rvectorsetlengthatleast(&state->nubc, 2*n, _state);
66965 0 : rvectorsetlengthatleast(&state->nulc, nec+nic, _state);
66966 0 : rvectorsetlengthatleast(&state->nunlc, ng+nh, _state);
66967 0 : rvectorsetlengthatleast(&state->xk, n, _state);
66968 0 : rvectorsetlengthatleast(&state->gk, n, _state);
66969 0 : rvectorsetlengthatleast(&state->xk1, n, _state);
66970 0 : rvectorsetlengthatleast(&state->gk1, n, _state);
66971 0 : for(i=0; i<=n-1; i++)
66972 : {
66973 0 : state->nubc.ptr.p_double[2*i+0] = 0.0;
66974 0 : state->nubc.ptr.p_double[2*i+1] = 0.0;
66975 0 : 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]) )
66976 : {
66977 0 : continue;
66978 : }
66979 0 : if( state->hasbndl.ptr.p_bool[i] )
66980 : {
66981 0 : state->nubc.ptr.p_double[2*i+0] = state->initialinequalitymultiplier;
66982 : }
66983 0 : if( state->hasbndu.ptr.p_bool[i] )
66984 : {
66985 0 : state->nubc.ptr.p_double[2*i+1] = state->initialinequalitymultiplier;
66986 : }
66987 : }
66988 0 : for(i=0; i<=nec-1; i++)
66989 : {
66990 0 : state->nulc.ptr.p_double[i] = 0.0;
66991 : }
66992 0 : for(i=0; i<=nic-1; i++)
66993 : {
66994 0 : state->nulc.ptr.p_double[nec+i] = state->initialinequalitymultiplier;
66995 : }
66996 0 : for(i=0; i<=ng-1; i++)
66997 : {
66998 0 : state->nunlc.ptr.p_double[i] = 0.0;
66999 : }
67000 0 : for(i=0; i<=nh-1; i++)
67001 : {
67002 0 : state->nunlc.ptr.p_double[ng+i] = state->initialinequalitymultiplier;
67003 : }
67004 0 : state->gammak = minnlc_initgamma;
67005 0 : state->xkpresent = ae_false;
67006 0 : ae_assert(state->aulitscnt>0, "MinNLC: integrity check failed", _state);
67007 0 : minnlc_clearpreconditioner(&state->auloptimizer, _state);
67008 0 : outerit = 0;
67009 0 : lbl_3:
67010 0 : if( outerit>state->aulitscnt-1 )
67011 : {
67012 0 : goto lbl_5;
67013 : }
67014 :
67015 : /*
67016 : * Optimize with current Lagrange multipliers
67017 : *
67018 : * NOTE: this code expects and checks that line search ends in the
67019 : * point which is used as beginning for the next search. Such
67020 : * guarantee is given by MCSRCH function. L-BFGS optimizer
67021 : * does not formally guarantee it, but it follows same rule.
67022 : * Below we a) rely on such property of the optimizer, and b)
67023 : * assert that it is true, in order to fail loudly if it is
67024 : * not true.
67025 : *
67026 : * NOTE: security check for NAN/INF in F/G is responsibility of
67027 : * LBFGS optimizer. AUL optimizer checks for NAN/INF only
67028 : * when we update Lagrange multipliers.
67029 : */
67030 0 : preccounter = 0;
67031 0 : minlbfgssetxrep(&state->auloptimizer, ae_true, _state);
67032 0 : minlbfgsrestartfrom(&state->auloptimizer, &state->xc, _state);
67033 0 : lbl_6:
67034 0 : if( !minlbfgsiteration(&state->auloptimizer, _state) )
67035 : {
67036 0 : goto lbl_7;
67037 : }
67038 0 : if( !state->auloptimizer.needfg )
67039 : {
67040 0 : goto lbl_8;
67041 : }
67042 :
67043 : /*
67044 : * Un-scale X, evaluate F/G/H, re-scale Jacobian
67045 : */
67046 0 : for(i=0; i<=n-1; i++)
67047 : {
67048 0 : state->x.ptr.p_double[i] = state->auloptimizer.x.ptr.p_double[i]*state->s.ptr.p_double[i];
67049 : }
67050 0 : state->needfij = ae_true;
67051 0 : state->rstateaul.stage = 0;
67052 0 : goto lbl_rcomm;
67053 0 : lbl_0:
67054 0 : state->needfij = ae_false;
67055 0 : for(i=0; i<=ng+nh; i++)
67056 : {
67057 0 : for(j=0; j<=n-1; j++)
67058 : {
67059 0 : state->j.ptr.pp_double[i][j] = state->j.ptr.pp_double[i][j]*state->s.ptr.p_double[j];
67060 : }
67061 : }
67062 :
67063 : /*
67064 : * Store data for estimation of Hessian norm:
67065 : * * current point (re-scaled)
67066 : * * gradient of the target function (re-scaled, unmodified)
67067 : */
67068 0 : ae_v_move(&state->xk1.ptr.p_double[0], 1, &state->auloptimizer.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
67069 0 : ae_v_move(&state->gk1.ptr.p_double[0], 1, &state->j.ptr.pp_double[0][0], 1, ae_v_len(0,n-1));
67070 :
67071 : /*
67072 : * Function being optimized
67073 : */
67074 0 : state->auloptimizer.f = state->fi.ptr.p_double[0];
67075 0 : for(i=0; i<=n-1; i++)
67076 : {
67077 0 : state->auloptimizer.g.ptr.p_double[i] = state->j.ptr.pp_double[0][i];
67078 : }
67079 :
67080 : /*
67081 : * Send information to OptGuard monitor
67082 : */
67083 0 : smoothnessmonitorenqueuepoint(smonitor, &state->auloptimizer.d, state->auloptimizer.stp, &state->auloptimizer.x, &state->fi, &state->j, _state);
67084 :
67085 : /*
67086 : * Penalty for violation of boundary/linear/nonlinear constraints
67087 : */
67088 0 : minnlc_penaltybc(&state->auloptimizer.x, &state->scaledbndl, &state->hasbndl, &state->scaledbndu, &state->hasbndu, &state->nubc, n, state->rho, state->stabilizingpoint, &state->auloptimizer.f, &state->auloptimizer.g, _state);
67089 0 : minnlc_penaltylc(&state->auloptimizer.x, &state->scaledcleic, &state->nulc, n, nec, nic, state->rho, state->stabilizingpoint, &state->auloptimizer.f, &state->auloptimizer.g, _state);
67090 0 : minnlc_penaltynlc(&state->fi, &state->j, &state->nunlc, n, ng, nh, state->rho, state->stabilizingpoint, &state->auloptimizer.f, &state->auloptimizer.g, _state);
67091 :
67092 : /*
67093 : * Forward termination request if needed
67094 : */
67095 0 : if( state->userterminationneeded )
67096 : {
67097 0 : minlbfgsrequesttermination(&state->auloptimizer, _state);
67098 : }
67099 :
67100 : /*
67101 : * To optimizer
67102 : */
67103 0 : goto lbl_6;
67104 0 : lbl_8:
67105 0 : if( !state->auloptimizer.xupdated )
67106 : {
67107 0 : goto lbl_10;
67108 : }
67109 :
67110 : /*
67111 : * Report current point (if needed)
67112 : */
67113 0 : if( !state->xrep )
67114 : {
67115 0 : goto lbl_12;
67116 : }
67117 0 : for(i=0; i<=n-1; i++)
67118 : {
67119 0 : state->x.ptr.p_double[i] = state->auloptimizer.x.ptr.p_double[i]*state->s.ptr.p_double[i];
67120 : }
67121 0 : state->f = state->auloptimizer.f;
67122 0 : state->xupdated = ae_true;
67123 0 : state->rstateaul.stage = 1;
67124 0 : goto lbl_rcomm;
67125 0 : lbl_1:
67126 0 : state->xupdated = ae_false;
67127 0 : lbl_12:
67128 :
67129 : /*
67130 : * Send information to OptGuard monitor
67131 : */
67132 0 : smoothnessmonitorfinalizelinesearch(smonitor, _state);
67133 0 : smoothnessmonitorstartlinesearch(smonitor, &state->auloptimizer.x, &state->fi, &state->j, _state);
67134 :
67135 : /*
67136 : * Forward termination request if needed
67137 : */
67138 0 : if( state->userterminationneeded )
67139 : {
67140 0 : minlbfgsrequesttermination(&state->auloptimizer, _state);
67141 : }
67142 :
67143 : /*
67144 : * Update constraints violation
67145 : */
67146 0 : checkbcviolation(&state->hasbndl, &state->scaledbndl, &state->hasbndu, &state->scaledbndu, &state->auloptimizer.x, n, &state->s, ae_false, &state->repbcerr, &state->repbcidx, _state);
67147 0 : checklcviolation(&state->scaledcleic, &state->lcsrcidx, nec, nic, &state->auloptimizer.x, n, &state->replcerr, &state->replcidx, _state);
67148 0 : checknlcviolation(&state->fi, ng, nh, &state->repnlcerr, &state->repnlcidx, _state);
67149 :
67150 : /*
67151 : * Update GammaK
67152 : */
67153 0 : if( state->xkpresent )
67154 : {
67155 :
67156 : /*
67157 : * XK/GK store beginning of current line search, and XK1/GK1
67158 : * store data for the end of the line search:
67159 : * * first, we Assert() that XK1 (last point where function
67160 : * was evaluated) is same as AULOptimizer.X (what is
67161 : * reported by RComm interface
67162 : * * calculate step length V2.
67163 : *
67164 : * If V2>HessEstTol, then:
67165 : * * calculate V0 - directional derivative at XK,
67166 : * and V1 - directional derivative at XK1
67167 : * * set GammaK to Max(GammaK, |V1-V0|/V2)
67168 : */
67169 0 : for(i=0; i<=n-1; i++)
67170 : {
67171 0 : ae_assert(ae_fp_less_eq(ae_fabs(state->auloptimizer.x.ptr.p_double[i]-state->xk1.ptr.p_double[i], _state),100*ae_machineepsilon)||!(ae_isfinite(state->auloptimizer.x.ptr.p_double[i], _state)&&ae_isfinite(state->xk1.ptr.p_double[i], _state)), "MinNLC: integrity check failed, unexpected behavior of LBFGS optimizer", _state);
67172 : }
67173 0 : v2 = 0.0;
67174 0 : for(i=0; i<=n-1; i++)
67175 : {
67176 0 : v2 = v2+ae_sqr(state->xk.ptr.p_double[i]-state->xk1.ptr.p_double[i], _state);
67177 : }
67178 0 : v2 = ae_sqrt(v2, _state);
67179 0 : if( ae_fp_greater(v2,minnlc_hessesttol) )
67180 : {
67181 0 : v0 = 0.0;
67182 0 : v1 = 0.0;
67183 0 : for(i=0; i<=n-1; i++)
67184 : {
67185 0 : v = (state->xk.ptr.p_double[i]-state->xk1.ptr.p_double[i])/v2;
67186 0 : v0 = v0+state->gk.ptr.p_double[i]*v;
67187 0 : v1 = v1+state->gk1.ptr.p_double[i]*v;
67188 : }
67189 0 : state->gammak = ae_maxreal(state->gammak, ae_fabs(v1-v0, _state)/v2, _state);
67190 : }
67191 : }
67192 : else
67193 : {
67194 :
67195 : /*
67196 : * Beginning of the first line search, XK is not yet initialized.
67197 : */
67198 0 : ae_v_move(&state->xk.ptr.p_double[0], 1, &state->xk1.ptr.p_double[0], 1, ae_v_len(0,n-1));
67199 0 : ae_v_move(&state->gk.ptr.p_double[0], 1, &state->gk1.ptr.p_double[0], 1, ae_v_len(0,n-1));
67200 0 : state->xkpresent = ae_true;
67201 : }
67202 :
67203 : /*
67204 : * Update preconsitioner using current GammaK
67205 : */
67206 0 : minnlc_updatepreconditioner(state->prectype, state->updatefreq, &preccounter, &state->auloptimizer, &state->auloptimizer.x, state->rho, state->gammak, &state->scaledbndl, &state->hasbndl, &state->scaledbndu, &state->hasbndu, &state->nubc, &state->scaledcleic, &state->nulc, &state->fi, &state->j, &state->nunlc, &state->bufd, &state->bufc, &state->bufw, &state->bufz, &state->tmp0, n, nec, nic, ng, nh, _state);
67207 0 : goto lbl_6;
67208 0 : lbl_10:
67209 0 : ae_assert(ae_false, "MinNLC: integrity check failed", _state);
67210 0 : goto lbl_6;
67211 0 : lbl_7:
67212 0 : minlbfgsresultsbuf(&state->auloptimizer, &state->xc, &state->aulreport, _state);
67213 0 : state->repinneriterationscount = state->repinneriterationscount+state->aulreport.iterationscount;
67214 0 : state->repnfev = state->repnfev+state->aulreport.nfev;
67215 0 : state->repterminationtype = state->aulreport.terminationtype;
67216 0 : inc(&state->repouteriterationscount, _state);
67217 0 : if( state->repterminationtype<=0||state->repterminationtype==8 )
67218 : {
67219 0 : goto lbl_5;
67220 : }
67221 :
67222 : /*
67223 : * 1. Evaluate F/J
67224 : * 2. Check for NAN/INF in F/J: we just calculate sum of their
67225 : * components, it should be enough to reduce vector/matrix to
67226 : * just one value which either "normal" (all summands were "normal")
67227 : * or NAN/INF (at least one summand was NAN/INF).
67228 : * 3. Update Lagrange multipliers
67229 : */
67230 0 : for(i=0; i<=n-1; i++)
67231 : {
67232 0 : state->x.ptr.p_double[i] = state->xc.ptr.p_double[i]*state->s.ptr.p_double[i];
67233 : }
67234 0 : state->needfij = ae_true;
67235 0 : state->rstateaul.stage = 2;
67236 0 : goto lbl_rcomm;
67237 0 : lbl_2:
67238 0 : state->needfij = ae_false;
67239 0 : v = 0.0;
67240 0 : for(i=0; i<=ng+nh; i++)
67241 : {
67242 0 : v = 0.1*v+state->fi.ptr.p_double[i];
67243 0 : for(j=0; j<=n-1; j++)
67244 : {
67245 0 : v = 0.1*v+state->j.ptr.pp_double[i][j];
67246 : }
67247 : }
67248 0 : if( !ae_isfinite(v, _state) )
67249 : {
67250 :
67251 : /*
67252 : * Abnormal termination - infinities in function/gradient
67253 : */
67254 0 : state->repterminationtype = -8;
67255 0 : result = ae_false;
67256 0 : return result;
67257 : }
67258 0 : for(i=0; i<=ng+nh; i++)
67259 : {
67260 0 : for(j=0; j<=n-1; j++)
67261 : {
67262 0 : state->j.ptr.pp_double[i][j] = state->j.ptr.pp_double[i][j]*state->s.ptr.p_double[j];
67263 : }
67264 : }
67265 0 : for(i=0; i<=n-1; i++)
67266 : {
67267 :
67268 : /*
67269 : * Process coefficients corresponding to equality-type
67270 : * constraints.
67271 : */
67272 0 : 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]) )
67273 : {
67274 0 : minnlcequalitypenaltyfunction((state->xc.ptr.p_double[i]-state->scaledbndl.ptr.p_double[i])*state->rho, &p, &dp, &d2p, _state);
67275 0 : state->nubc.ptr.p_double[2*i+0] = boundval(state->nubc.ptr.p_double[2*i+0]-dp, -minnlc_maxlagmult, minnlc_maxlagmult, _state);
67276 0 : continue;
67277 : }
67278 :
67279 : /*
67280 : * Process coefficients corresponding to inequality-type
67281 : * constraints. These coefficients have limited growth/decay
67282 : * per iteration which helps to stabilize algorithm.
67283 : */
67284 0 : ae_assert(ae_fp_greater(minnlc_aulmaxgrowth,1.0), "MinNLC: integrity error", _state);
67285 0 : if( state->hasbndl.ptr.p_bool[i] )
67286 : {
67287 0 : minnlcinequalityshiftfunction((state->xc.ptr.p_double[i]-state->scaledbndl.ptr.p_double[i])*state->rho+1, &p, &dp, &d2p, _state);
67288 0 : v = ae_fabs(dp, _state);
67289 0 : v = ae_minreal(v, minnlc_aulmaxgrowth, _state);
67290 0 : v = ae_maxreal(v, 1/minnlc_aulmaxgrowth, _state);
67291 0 : state->nubc.ptr.p_double[2*i+0] = boundval(state->nubc.ptr.p_double[2*i+0]*v, -minnlc_maxlagmult, minnlc_maxlagmult, _state);
67292 : }
67293 0 : if( state->hasbndu.ptr.p_bool[i] )
67294 : {
67295 0 : minnlcinequalityshiftfunction((state->scaledbndu.ptr.p_double[i]-state->xc.ptr.p_double[i])*state->rho+1, &p, &dp, &d2p, _state);
67296 0 : v = ae_fabs(dp, _state);
67297 0 : v = ae_minreal(v, minnlc_aulmaxgrowth, _state);
67298 0 : v = ae_maxreal(v, 1/minnlc_aulmaxgrowth, _state);
67299 0 : state->nubc.ptr.p_double[2*i+1] = boundval(state->nubc.ptr.p_double[2*i+1]*v, -minnlc_maxlagmult, minnlc_maxlagmult, _state);
67300 : }
67301 : }
67302 0 : for(i=0; i<=nec+nic-1; i++)
67303 : {
67304 0 : v = ae_v_dotproduct(&state->scaledcleic.ptr.pp_double[i][0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
67305 0 : v = v-state->scaledcleic.ptr.pp_double[i][n];
67306 0 : if( i<nec )
67307 : {
67308 0 : minnlcequalitypenaltyfunction(v*state->rho, &p, &dp, &d2p, _state);
67309 0 : state->nulc.ptr.p_double[i] = boundval(state->nulc.ptr.p_double[i]-dp, -minnlc_maxlagmult, minnlc_maxlagmult, _state);
67310 : }
67311 : else
67312 : {
67313 0 : minnlcinequalityshiftfunction(-v*state->rho+1, &p, &dp, &d2p, _state);
67314 0 : v = ae_fabs(dp, _state);
67315 0 : v = ae_minreal(v, minnlc_aulmaxgrowth, _state);
67316 0 : v = ae_maxreal(v, 1/minnlc_aulmaxgrowth, _state);
67317 0 : state->nulc.ptr.p_double[i] = boundval(state->nulc.ptr.p_double[i]*v, -minnlc_maxlagmult, minnlc_maxlagmult, _state);
67318 : }
67319 : }
67320 0 : for(i=1; i<=ng+nh; i++)
67321 : {
67322 :
67323 : /*
67324 : * NOTE: loop index must start from 1, not zero!
67325 : */
67326 0 : v = state->fi.ptr.p_double[i];
67327 0 : if( i<=ng )
67328 : {
67329 0 : minnlcequalitypenaltyfunction(v*state->rho, &p, &dp, &d2p, _state);
67330 0 : state->nunlc.ptr.p_double[i-1] = boundval(state->nunlc.ptr.p_double[i-1]-dp, -minnlc_maxlagmult, minnlc_maxlagmult, _state);
67331 : }
67332 : else
67333 : {
67334 0 : minnlcinequalityshiftfunction(-v*state->rho+1, &p, &dp, &d2p, _state);
67335 0 : v = ae_fabs(dp, _state);
67336 0 : v = ae_minreal(v, minnlc_aulmaxgrowth, _state);
67337 0 : v = ae_maxreal(v, 1/minnlc_aulmaxgrowth, _state);
67338 0 : state->nunlc.ptr.p_double[i-1] = boundval(state->nunlc.ptr.p_double[i-1]*v, -minnlc_maxlagmult, minnlc_maxlagmult, _state);
67339 : }
67340 : }
67341 0 : outerit = outerit+1;
67342 0 : goto lbl_3;
67343 0 : lbl_5:
67344 0 : for(i=0; i<=n-1; i++)
67345 : {
67346 0 : state->xc.ptr.p_double[i] = state->xc.ptr.p_double[i]*state->s.ptr.p_double[i];
67347 : }
67348 0 : result = ae_false;
67349 0 : return result;
67350 :
67351 : /*
67352 : * Saving state
67353 : */
67354 0 : lbl_rcomm:
67355 0 : result = ae_true;
67356 0 : state->rstateaul.ia.ptr.p_int[0] = n;
67357 0 : state->rstateaul.ia.ptr.p_int[1] = nec;
67358 0 : state->rstateaul.ia.ptr.p_int[2] = nic;
67359 0 : state->rstateaul.ia.ptr.p_int[3] = ng;
67360 0 : state->rstateaul.ia.ptr.p_int[4] = nh;
67361 0 : state->rstateaul.ia.ptr.p_int[5] = i;
67362 0 : state->rstateaul.ia.ptr.p_int[6] = j;
67363 0 : state->rstateaul.ia.ptr.p_int[7] = outerit;
67364 0 : state->rstateaul.ia.ptr.p_int[8] = preccounter;
67365 0 : state->rstateaul.ra.ptr.p_double[0] = v;
67366 0 : state->rstateaul.ra.ptr.p_double[1] = vv;
67367 0 : state->rstateaul.ra.ptr.p_double[2] = p;
67368 0 : state->rstateaul.ra.ptr.p_double[3] = dp;
67369 0 : state->rstateaul.ra.ptr.p_double[4] = d2p;
67370 0 : state->rstateaul.ra.ptr.p_double[5] = v0;
67371 0 : state->rstateaul.ra.ptr.p_double[6] = v1;
67372 0 : state->rstateaul.ra.ptr.p_double[7] = v2;
67373 0 : return result;
67374 : }
67375 :
67376 :
67377 : /*************************************************************************
67378 : Unscales X (converts from scaled variables to original ones), paying special
67379 : attention to box constraints (output is always feasible; active constraints
67380 : are mapped to active ones).
67381 : *************************************************************************/
67382 0 : static void minnlc_unscale(minnlcstate* state,
67383 : /* Real */ ae_vector* xs,
67384 : /* Real */ ae_vector* scaledbndl,
67385 : /* Real */ ae_vector* scaledbndu,
67386 : /* Real */ ae_vector* xu,
67387 : ae_state *_state)
67388 : {
67389 : ae_int_t i;
67390 : ae_int_t n;
67391 :
67392 :
67393 0 : n = state->n;
67394 0 : for(i=0; i<=n-1; i++)
67395 : {
67396 0 : if( state->hasbndl.ptr.p_bool[i]&&xs->ptr.p_double[i]<=scaledbndl->ptr.p_double[i] )
67397 : {
67398 0 : xu->ptr.p_double[i] = state->bndl.ptr.p_double[i];
67399 0 : continue;
67400 : }
67401 0 : if( state->hasbndu.ptr.p_bool[i]&&xs->ptr.p_double[i]>=scaledbndu->ptr.p_double[i] )
67402 : {
67403 0 : xu->ptr.p_double[i] = state->bndu.ptr.p_double[i];
67404 0 : continue;
67405 : }
67406 0 : xu->ptr.p_double[i] = xs->ptr.p_double[i]*state->s.ptr.p_double[i];
67407 0 : if( state->hasbndl.ptr.p_bool[i]&&xu->ptr.p_double[i]<state->bndl.ptr.p_double[i] )
67408 : {
67409 0 : xu->ptr.p_double[i] = state->bndl.ptr.p_double[i];
67410 : }
67411 0 : if( state->hasbndu.ptr.p_bool[i]&&xu->ptr.p_double[i]>state->bndu.ptr.p_double[i] )
67412 : {
67413 0 : xu->ptr.p_double[i] = state->bndu.ptr.p_double[i];
67414 : }
67415 : }
67416 0 : }
67417 :
67418 :
67419 0 : void _minnlcstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
67420 : {
67421 0 : minnlcstate *p = (minnlcstate*)_p;
67422 0 : ae_touch_ptr((void*)p);
67423 0 : ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic);
67424 0 : ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic);
67425 0 : ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic);
67426 0 : ae_vector_init(&p->hasbndl, 0, DT_BOOL, _state, make_automatic);
67427 0 : ae_vector_init(&p->hasbndu, 0, DT_BOOL, _state, make_automatic);
67428 0 : ae_matrix_init(&p->cleic, 0, 0, DT_REAL, _state, make_automatic);
67429 0 : ae_vector_init(&p->lcsrcidx, 0, DT_INT, _state, make_automatic);
67430 0 : ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
67431 0 : ae_vector_init(&p->fi, 0, DT_REAL, _state, make_automatic);
67432 0 : ae_matrix_init(&p->j, 0, 0, DT_REAL, _state, make_automatic);
67433 0 : _rcommstate_init(&p->rstate, _state, make_automatic);
67434 0 : _rcommstate_init(&p->rstateaul, _state, make_automatic);
67435 0 : _rcommstate_init(&p->rstateslp, _state, make_automatic);
67436 0 : ae_vector_init(&p->scaledbndl, 0, DT_REAL, _state, make_automatic);
67437 0 : ae_vector_init(&p->scaledbndu, 0, DT_REAL, _state, make_automatic);
67438 0 : ae_matrix_init(&p->scaledcleic, 0, 0, DT_REAL, _state, make_automatic);
67439 0 : ae_vector_init(&p->xc, 0, DT_REAL, _state, make_automatic);
67440 0 : ae_vector_init(&p->xstart, 0, DT_REAL, _state, make_automatic);
67441 0 : ae_vector_init(&p->xbase, 0, DT_REAL, _state, make_automatic);
67442 0 : ae_vector_init(&p->fbase, 0, DT_REAL, _state, make_automatic);
67443 0 : ae_vector_init(&p->dfbase, 0, DT_REAL, _state, make_automatic);
67444 0 : ae_vector_init(&p->fm2, 0, DT_REAL, _state, make_automatic);
67445 0 : ae_vector_init(&p->fm1, 0, DT_REAL, _state, make_automatic);
67446 0 : ae_vector_init(&p->fp1, 0, DT_REAL, _state, make_automatic);
67447 0 : ae_vector_init(&p->fp2, 0, DT_REAL, _state, make_automatic);
67448 0 : ae_vector_init(&p->dfm1, 0, DT_REAL, _state, make_automatic);
67449 0 : ae_vector_init(&p->dfp1, 0, DT_REAL, _state, make_automatic);
67450 0 : ae_vector_init(&p->bufd, 0, DT_REAL, _state, make_automatic);
67451 0 : ae_vector_init(&p->bufc, 0, DT_REAL, _state, make_automatic);
67452 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
67453 0 : ae_matrix_init(&p->bufw, 0, 0, DT_REAL, _state, make_automatic);
67454 0 : ae_matrix_init(&p->bufz, 0, 0, DT_REAL, _state, make_automatic);
67455 0 : ae_vector_init(&p->xk, 0, DT_REAL, _state, make_automatic);
67456 0 : ae_vector_init(&p->xk1, 0, DT_REAL, _state, make_automatic);
67457 0 : ae_vector_init(&p->gk, 0, DT_REAL, _state, make_automatic);
67458 0 : ae_vector_init(&p->gk1, 0, DT_REAL, _state, make_automatic);
67459 0 : _minlbfgsstate_init(&p->auloptimizer, _state, make_automatic);
67460 0 : _minlbfgsreport_init(&p->aulreport, _state, make_automatic);
67461 0 : ae_vector_init(&p->nubc, 0, DT_REAL, _state, make_automatic);
67462 0 : ae_vector_init(&p->nulc, 0, DT_REAL, _state, make_automatic);
67463 0 : ae_vector_init(&p->nunlc, 0, DT_REAL, _state, make_automatic);
67464 0 : _minslpstate_init(&p->slpsolverstate, _state, make_automatic);
67465 0 : _minsqpstate_init(&p->sqpsolverstate, _state, make_automatic);
67466 0 : _smoothnessmonitor_init(&p->smonitor, _state, make_automatic);
67467 0 : ae_vector_init(&p->lastscaleused, 0, DT_REAL, _state, make_automatic);
67468 0 : }
67469 :
67470 :
67471 0 : void _minnlcstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
67472 : {
67473 0 : minnlcstate *dst = (minnlcstate*)_dst;
67474 0 : minnlcstate *src = (minnlcstate*)_src;
67475 0 : dst->stabilizingpoint = src->stabilizingpoint;
67476 0 : dst->initialinequalitymultiplier = src->initialinequalitymultiplier;
67477 0 : dst->solvertype = src->solvertype;
67478 0 : dst->prectype = src->prectype;
67479 0 : dst->updatefreq = src->updatefreq;
67480 0 : dst->rho = src->rho;
67481 0 : dst->n = src->n;
67482 0 : dst->epsx = src->epsx;
67483 0 : dst->maxits = src->maxits;
67484 0 : dst->aulitscnt = src->aulitscnt;
67485 0 : dst->xrep = src->xrep;
67486 0 : dst->stpmax = src->stpmax;
67487 0 : dst->diffstep = src->diffstep;
67488 0 : dst->teststep = src->teststep;
67489 0 : ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic);
67490 0 : ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic);
67491 0 : ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic);
67492 0 : ae_vector_init_copy(&dst->hasbndl, &src->hasbndl, _state, make_automatic);
67493 0 : ae_vector_init_copy(&dst->hasbndu, &src->hasbndu, _state, make_automatic);
67494 0 : dst->nec = src->nec;
67495 0 : dst->nic = src->nic;
67496 0 : ae_matrix_init_copy(&dst->cleic, &src->cleic, _state, make_automatic);
67497 0 : ae_vector_init_copy(&dst->lcsrcidx, &src->lcsrcidx, _state, make_automatic);
67498 0 : dst->ng = src->ng;
67499 0 : dst->nh = src->nh;
67500 0 : ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
67501 0 : dst->f = src->f;
67502 0 : ae_vector_init_copy(&dst->fi, &src->fi, _state, make_automatic);
67503 0 : ae_matrix_init_copy(&dst->j, &src->j, _state, make_automatic);
67504 0 : dst->needfij = src->needfij;
67505 0 : dst->needfi = src->needfi;
67506 0 : dst->xupdated = src->xupdated;
67507 0 : _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic);
67508 0 : _rcommstate_init_copy(&dst->rstateaul, &src->rstateaul, _state, make_automatic);
67509 0 : _rcommstate_init_copy(&dst->rstateslp, &src->rstateslp, _state, make_automatic);
67510 0 : ae_vector_init_copy(&dst->scaledbndl, &src->scaledbndl, _state, make_automatic);
67511 0 : ae_vector_init_copy(&dst->scaledbndu, &src->scaledbndu, _state, make_automatic);
67512 0 : ae_matrix_init_copy(&dst->scaledcleic, &src->scaledcleic, _state, make_automatic);
67513 0 : ae_vector_init_copy(&dst->xc, &src->xc, _state, make_automatic);
67514 0 : ae_vector_init_copy(&dst->xstart, &src->xstart, _state, make_automatic);
67515 0 : ae_vector_init_copy(&dst->xbase, &src->xbase, _state, make_automatic);
67516 0 : ae_vector_init_copy(&dst->fbase, &src->fbase, _state, make_automatic);
67517 0 : ae_vector_init_copy(&dst->dfbase, &src->dfbase, _state, make_automatic);
67518 0 : ae_vector_init_copy(&dst->fm2, &src->fm2, _state, make_automatic);
67519 0 : ae_vector_init_copy(&dst->fm1, &src->fm1, _state, make_automatic);
67520 0 : ae_vector_init_copy(&dst->fp1, &src->fp1, _state, make_automatic);
67521 0 : ae_vector_init_copy(&dst->fp2, &src->fp2, _state, make_automatic);
67522 0 : ae_vector_init_copy(&dst->dfm1, &src->dfm1, _state, make_automatic);
67523 0 : ae_vector_init_copy(&dst->dfp1, &src->dfp1, _state, make_automatic);
67524 0 : ae_vector_init_copy(&dst->bufd, &src->bufd, _state, make_automatic);
67525 0 : ae_vector_init_copy(&dst->bufc, &src->bufc, _state, make_automatic);
67526 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
67527 0 : ae_matrix_init_copy(&dst->bufw, &src->bufw, _state, make_automatic);
67528 0 : ae_matrix_init_copy(&dst->bufz, &src->bufz, _state, make_automatic);
67529 0 : ae_vector_init_copy(&dst->xk, &src->xk, _state, make_automatic);
67530 0 : ae_vector_init_copy(&dst->xk1, &src->xk1, _state, make_automatic);
67531 0 : ae_vector_init_copy(&dst->gk, &src->gk, _state, make_automatic);
67532 0 : ae_vector_init_copy(&dst->gk1, &src->gk1, _state, make_automatic);
67533 0 : dst->gammak = src->gammak;
67534 0 : dst->xkpresent = src->xkpresent;
67535 0 : _minlbfgsstate_init_copy(&dst->auloptimizer, &src->auloptimizer, _state, make_automatic);
67536 0 : _minlbfgsreport_init_copy(&dst->aulreport, &src->aulreport, _state, make_automatic);
67537 0 : ae_vector_init_copy(&dst->nubc, &src->nubc, _state, make_automatic);
67538 0 : ae_vector_init_copy(&dst->nulc, &src->nulc, _state, make_automatic);
67539 0 : ae_vector_init_copy(&dst->nunlc, &src->nunlc, _state, make_automatic);
67540 0 : dst->userterminationneeded = src->userterminationneeded;
67541 0 : _minslpstate_init_copy(&dst->slpsolverstate, &src->slpsolverstate, _state, make_automatic);
67542 0 : _minsqpstate_init_copy(&dst->sqpsolverstate, &src->sqpsolverstate, _state, make_automatic);
67543 0 : dst->smoothnessguardlevel = src->smoothnessguardlevel;
67544 0 : _smoothnessmonitor_init_copy(&dst->smonitor, &src->smonitor, _state, make_automatic);
67545 0 : ae_vector_init_copy(&dst->lastscaleused, &src->lastscaleused, _state, make_automatic);
67546 0 : dst->repinneriterationscount = src->repinneriterationscount;
67547 0 : dst->repouteriterationscount = src->repouteriterationscount;
67548 0 : dst->repnfev = src->repnfev;
67549 0 : dst->repterminationtype = src->repterminationtype;
67550 0 : dst->repbcerr = src->repbcerr;
67551 0 : dst->repbcidx = src->repbcidx;
67552 0 : dst->replcerr = src->replcerr;
67553 0 : dst->replcidx = src->replcidx;
67554 0 : dst->repnlcerr = src->repnlcerr;
67555 0 : dst->repnlcidx = src->repnlcidx;
67556 0 : dst->repdbgphase0its = src->repdbgphase0its;
67557 0 : }
67558 :
67559 :
67560 0 : void _minnlcstate_clear(void* _p)
67561 : {
67562 0 : minnlcstate *p = (minnlcstate*)_p;
67563 0 : ae_touch_ptr((void*)p);
67564 0 : ae_vector_clear(&p->s);
67565 0 : ae_vector_clear(&p->bndl);
67566 0 : ae_vector_clear(&p->bndu);
67567 0 : ae_vector_clear(&p->hasbndl);
67568 0 : ae_vector_clear(&p->hasbndu);
67569 0 : ae_matrix_clear(&p->cleic);
67570 0 : ae_vector_clear(&p->lcsrcidx);
67571 0 : ae_vector_clear(&p->x);
67572 0 : ae_vector_clear(&p->fi);
67573 0 : ae_matrix_clear(&p->j);
67574 0 : _rcommstate_clear(&p->rstate);
67575 0 : _rcommstate_clear(&p->rstateaul);
67576 0 : _rcommstate_clear(&p->rstateslp);
67577 0 : ae_vector_clear(&p->scaledbndl);
67578 0 : ae_vector_clear(&p->scaledbndu);
67579 0 : ae_matrix_clear(&p->scaledcleic);
67580 0 : ae_vector_clear(&p->xc);
67581 0 : ae_vector_clear(&p->xstart);
67582 0 : ae_vector_clear(&p->xbase);
67583 0 : ae_vector_clear(&p->fbase);
67584 0 : ae_vector_clear(&p->dfbase);
67585 0 : ae_vector_clear(&p->fm2);
67586 0 : ae_vector_clear(&p->fm1);
67587 0 : ae_vector_clear(&p->fp1);
67588 0 : ae_vector_clear(&p->fp2);
67589 0 : ae_vector_clear(&p->dfm1);
67590 0 : ae_vector_clear(&p->dfp1);
67591 0 : ae_vector_clear(&p->bufd);
67592 0 : ae_vector_clear(&p->bufc);
67593 0 : ae_vector_clear(&p->tmp0);
67594 0 : ae_matrix_clear(&p->bufw);
67595 0 : ae_matrix_clear(&p->bufz);
67596 0 : ae_vector_clear(&p->xk);
67597 0 : ae_vector_clear(&p->xk1);
67598 0 : ae_vector_clear(&p->gk);
67599 0 : ae_vector_clear(&p->gk1);
67600 0 : _minlbfgsstate_clear(&p->auloptimizer);
67601 0 : _minlbfgsreport_clear(&p->aulreport);
67602 0 : ae_vector_clear(&p->nubc);
67603 0 : ae_vector_clear(&p->nulc);
67604 0 : ae_vector_clear(&p->nunlc);
67605 0 : _minslpstate_clear(&p->slpsolverstate);
67606 0 : _minsqpstate_clear(&p->sqpsolverstate);
67607 0 : _smoothnessmonitor_clear(&p->smonitor);
67608 0 : ae_vector_clear(&p->lastscaleused);
67609 0 : }
67610 :
67611 :
67612 0 : void _minnlcstate_destroy(void* _p)
67613 : {
67614 0 : minnlcstate *p = (minnlcstate*)_p;
67615 0 : ae_touch_ptr((void*)p);
67616 0 : ae_vector_destroy(&p->s);
67617 0 : ae_vector_destroy(&p->bndl);
67618 0 : ae_vector_destroy(&p->bndu);
67619 0 : ae_vector_destroy(&p->hasbndl);
67620 0 : ae_vector_destroy(&p->hasbndu);
67621 0 : ae_matrix_destroy(&p->cleic);
67622 0 : ae_vector_destroy(&p->lcsrcidx);
67623 0 : ae_vector_destroy(&p->x);
67624 0 : ae_vector_destroy(&p->fi);
67625 0 : ae_matrix_destroy(&p->j);
67626 0 : _rcommstate_destroy(&p->rstate);
67627 0 : _rcommstate_destroy(&p->rstateaul);
67628 0 : _rcommstate_destroy(&p->rstateslp);
67629 0 : ae_vector_destroy(&p->scaledbndl);
67630 0 : ae_vector_destroy(&p->scaledbndu);
67631 0 : ae_matrix_destroy(&p->scaledcleic);
67632 0 : ae_vector_destroy(&p->xc);
67633 0 : ae_vector_destroy(&p->xstart);
67634 0 : ae_vector_destroy(&p->xbase);
67635 0 : ae_vector_destroy(&p->fbase);
67636 0 : ae_vector_destroy(&p->dfbase);
67637 0 : ae_vector_destroy(&p->fm2);
67638 0 : ae_vector_destroy(&p->fm1);
67639 0 : ae_vector_destroy(&p->fp1);
67640 0 : ae_vector_destroy(&p->fp2);
67641 0 : ae_vector_destroy(&p->dfm1);
67642 0 : ae_vector_destroy(&p->dfp1);
67643 0 : ae_vector_destroy(&p->bufd);
67644 0 : ae_vector_destroy(&p->bufc);
67645 0 : ae_vector_destroy(&p->tmp0);
67646 0 : ae_matrix_destroy(&p->bufw);
67647 0 : ae_matrix_destroy(&p->bufz);
67648 0 : ae_vector_destroy(&p->xk);
67649 0 : ae_vector_destroy(&p->xk1);
67650 0 : ae_vector_destroy(&p->gk);
67651 0 : ae_vector_destroy(&p->gk1);
67652 0 : _minlbfgsstate_destroy(&p->auloptimizer);
67653 0 : _minlbfgsreport_destroy(&p->aulreport);
67654 0 : ae_vector_destroy(&p->nubc);
67655 0 : ae_vector_destroy(&p->nulc);
67656 0 : ae_vector_destroy(&p->nunlc);
67657 0 : _minslpstate_destroy(&p->slpsolverstate);
67658 0 : _minsqpstate_destroy(&p->sqpsolverstate);
67659 0 : _smoothnessmonitor_destroy(&p->smonitor);
67660 0 : ae_vector_destroy(&p->lastscaleused);
67661 0 : }
67662 :
67663 :
67664 0 : void _minnlcreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
67665 : {
67666 0 : minnlcreport *p = (minnlcreport*)_p;
67667 0 : ae_touch_ptr((void*)p);
67668 0 : }
67669 :
67670 :
67671 0 : void _minnlcreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
67672 : {
67673 0 : minnlcreport *dst = (minnlcreport*)_dst;
67674 0 : minnlcreport *src = (minnlcreport*)_src;
67675 0 : dst->iterationscount = src->iterationscount;
67676 0 : dst->nfev = src->nfev;
67677 0 : dst->terminationtype = src->terminationtype;
67678 0 : dst->bcerr = src->bcerr;
67679 0 : dst->bcidx = src->bcidx;
67680 0 : dst->lcerr = src->lcerr;
67681 0 : dst->lcidx = src->lcidx;
67682 0 : dst->nlcerr = src->nlcerr;
67683 0 : dst->nlcidx = src->nlcidx;
67684 0 : dst->dbgphase0its = src->dbgphase0its;
67685 0 : }
67686 :
67687 :
67688 0 : void _minnlcreport_clear(void* _p)
67689 : {
67690 0 : minnlcreport *p = (minnlcreport*)_p;
67691 0 : ae_touch_ptr((void*)p);
67692 0 : }
67693 :
67694 :
67695 0 : void _minnlcreport_destroy(void* _p)
67696 : {
67697 0 : minnlcreport *p = (minnlcreport*)_p;
67698 0 : ae_touch_ptr((void*)p);
67699 0 : }
67700 :
67701 :
67702 : #endif
67703 : #if defined(AE_COMPILE_MINBC) || !defined(AE_PARTIAL_BUILD)
67704 :
67705 :
67706 : /*************************************************************************
67707 : BOX CONSTRAINED OPTIMIZATION
67708 : WITH FAST ACTIVATION OF MULTIPLE BOX CONSTRAINTS
67709 :
67710 : DESCRIPTION:
67711 : The subroutine minimizes function F(x) of N arguments subject to box
67712 : constraints (with some of box constraints actually being equality ones).
67713 :
67714 : This optimizer uses algorithm similar to that of MinBLEIC (optimizer with
67715 : general linear constraints), but presence of box-only constraints allows
67716 : us to use faster constraint activation strategies. On large-scale problems,
67717 : with multiple constraints active at the solution, this optimizer can be
67718 : several times faster than BLEIC.
67719 :
67720 : REQUIREMENTS:
67721 : * user must provide function value and gradient
67722 : * starting point X0 must be feasible or
67723 : not too far away from the feasible set
67724 : * grad(f) must be Lipschitz continuous on a level set:
67725 : L = { x : f(x)<=f(x0) }
67726 : * function must be defined everywhere on the feasible set F
67727 :
67728 : USAGE:
67729 :
67730 : Constrained optimization if far more complex than the unconstrained one.
67731 : Here we give very brief outline of the BC optimizer. We strongly recommend
67732 : you to read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide
67733 : on optimization, which is available at http://www.alglib.net/optimization/
67734 :
67735 : 1. User initializes algorithm state with MinBCCreate() call
67736 :
67737 : 2. USer adds box constraints by calling MinBCSetBC() function.
67738 :
67739 : 3. User sets stopping conditions with MinBCSetCond().
67740 :
67741 : 4. User calls MinBCOptimize() function which takes algorithm state and
67742 : pointer (delegate, etc.) to callback function which calculates F/G.
67743 :
67744 : 5. User calls MinBCResults() to get solution
67745 :
67746 : 6. Optionally user may call MinBCRestartFrom() to solve another problem
67747 : with same N but another starting point.
67748 : MinBCRestartFrom() allows to reuse already initialized structure.
67749 :
67750 :
67751 : INPUT PARAMETERS:
67752 : N - problem dimension, N>0:
67753 : * if given, only leading N elements of X are used
67754 : * if not given, automatically determined from size ofX
67755 : X - starting point, array[N]:
67756 : * it is better to set X to a feasible point
67757 : * but X can be infeasible, in which case algorithm will try
67758 : to find feasible point first, using X as initial
67759 : approximation.
67760 :
67761 : OUTPUT PARAMETERS:
67762 : State - structure stores algorithm state
67763 :
67764 : -- ALGLIB --
67765 : Copyright 28.11.2010 by Bochkanov Sergey
67766 : *************************************************************************/
67767 0 : void minbccreate(ae_int_t n,
67768 : /* Real */ ae_vector* x,
67769 : minbcstate* state,
67770 : ae_state *_state)
67771 : {
67772 : ae_frame _frame_block;
67773 : ae_matrix c;
67774 : ae_vector ct;
67775 :
67776 0 : ae_frame_make(_state, &_frame_block);
67777 0 : memset(&c, 0, sizeof(c));
67778 0 : memset(&ct, 0, sizeof(ct));
67779 0 : _minbcstate_clear(state);
67780 0 : ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
67781 0 : ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
67782 :
67783 0 : ae_assert(n>=1, "MinBCCreate: N<1", _state);
67784 0 : ae_assert(x->cnt>=n, "MinBCCreate: Length(X)<N", _state);
67785 0 : ae_assert(isfinitevector(x, n, _state), "MinBCCreate: X contains infinite or NaN values!", _state);
67786 0 : minbc_minbcinitinternal(n, x, 0.0, state, _state);
67787 0 : ae_frame_leave(_state);
67788 0 : }
67789 :
67790 :
67791 : /*************************************************************************
67792 : The subroutine is finite difference variant of MinBCCreate(). It uses
67793 : finite differences in order to differentiate target function.
67794 :
67795 : Description below contains information which is specific to this function
67796 : only. We recommend to read comments on MinBCCreate() in order to get
67797 : more information about creation of BC optimizer.
67798 :
67799 : INPUT PARAMETERS:
67800 : N - problem dimension, N>0:
67801 : * if given, only leading N elements of X are used
67802 : * if not given, automatically determined from size of X
67803 : X - starting point, array[0..N-1].
67804 : DiffStep- differentiation step, >0
67805 :
67806 : OUTPUT PARAMETERS:
67807 : State - structure which stores algorithm state
67808 :
67809 : NOTES:
67810 : 1. algorithm uses 4-point central formula for differentiation.
67811 : 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
67812 : S[] is scaling vector which can be set by MinBCSetScale() call.
67813 : 3. we recommend you to use moderate values of differentiation step. Too
67814 : large step will result in too large truncation errors, while too small
67815 : step will result in too large numerical errors. 1.0E-6 can be good
67816 : value to start with.
67817 : 4. Numerical differentiation is very inefficient - one gradient
67818 : calculation needs 4*N function evaluations. This function will work for
67819 : any N - either small (1...10), moderate (10...100) or large (100...).
67820 : However, performance penalty will be too severe for any N's except for
67821 : small ones.
67822 : We should also say that code which relies on numerical differentiation
67823 : is less robust and precise. CG needs exact gradient values. Imprecise
67824 : gradient may slow down convergence, especially on highly nonlinear
67825 : problems.
67826 : Thus we recommend to use this function for fast prototyping on small-
67827 : dimensional problems only, and to implement analytical gradient as soon
67828 : as possible.
67829 :
67830 : -- ALGLIB --
67831 : Copyright 16.05.2011 by Bochkanov Sergey
67832 : *************************************************************************/
67833 0 : void minbccreatef(ae_int_t n,
67834 : /* Real */ ae_vector* x,
67835 : double diffstep,
67836 : minbcstate* state,
67837 : ae_state *_state)
67838 : {
67839 : ae_frame _frame_block;
67840 : ae_matrix c;
67841 : ae_vector ct;
67842 :
67843 0 : ae_frame_make(_state, &_frame_block);
67844 0 : memset(&c, 0, sizeof(c));
67845 0 : memset(&ct, 0, sizeof(ct));
67846 0 : _minbcstate_clear(state);
67847 0 : ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
67848 0 : ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
67849 :
67850 0 : ae_assert(n>=1, "MinBCCreateF: N<1", _state);
67851 0 : ae_assert(x->cnt>=n, "MinBCCreateF: Length(X)<N", _state);
67852 0 : ae_assert(isfinitevector(x, n, _state), "MinBCCreateF: X contains infinite or NaN values!", _state);
67853 0 : ae_assert(ae_isfinite(diffstep, _state), "MinBCCreateF: DiffStep is infinite or NaN!", _state);
67854 0 : ae_assert(ae_fp_greater(diffstep,(double)(0)), "MinBCCreateF: DiffStep is non-positive!", _state);
67855 0 : minbc_minbcinitinternal(n, x, diffstep, state, _state);
67856 0 : ae_frame_leave(_state);
67857 0 : }
67858 :
67859 :
67860 : /*************************************************************************
67861 : This function sets boundary constraints for BC optimizer.
67862 :
67863 : Boundary constraints are inactive by default (after initial creation).
67864 : They are preserved after algorithm restart with MinBCRestartFrom().
67865 :
67866 : INPUT PARAMETERS:
67867 : State - structure stores algorithm state
67868 : BndL - lower bounds, array[N].
67869 : If some (all) variables are unbounded, you may specify
67870 : very small number or -INF.
67871 : BndU - upper bounds, array[N].
67872 : If some (all) variables are unbounded, you may specify
67873 : very large number or +INF.
67874 :
67875 : NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th
67876 : variable will be "frozen" at X[i]=BndL[i]=BndU[i].
67877 :
67878 : NOTE 2: this solver has following useful properties:
67879 : * bound constraints are always satisfied exactly
67880 : * function is evaluated only INSIDE area specified by bound constraints,
67881 : even when numerical differentiation is used (algorithm adjusts nodes
67882 : according to boundary constraints)
67883 :
67884 : -- ALGLIB --
67885 : Copyright 28.11.2010 by Bochkanov Sergey
67886 : *************************************************************************/
67887 0 : void minbcsetbc(minbcstate* state,
67888 : /* Real */ ae_vector* bndl,
67889 : /* Real */ ae_vector* bndu,
67890 : ae_state *_state)
67891 : {
67892 : ae_int_t i;
67893 : ae_int_t n;
67894 :
67895 :
67896 0 : n = state->nmain;
67897 0 : ae_assert(bndl->cnt>=n, "MinBCSetBC: Length(BndL)<N", _state);
67898 0 : ae_assert(bndu->cnt>=n, "MinBCSetBC: Length(BndU)<N", _state);
67899 0 : for(i=0; i<=n-1; i++)
67900 : {
67901 0 : ae_assert(ae_isfinite(bndl->ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "MinBCSetBC: BndL contains NAN or +INF", _state);
67902 0 : ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "MinBCSetBC: BndL contains NAN or -INF", _state);
67903 0 : state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i];
67904 0 : state->hasbndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state);
67905 0 : state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i];
67906 0 : state->hasbndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state);
67907 : }
67908 0 : }
67909 :
67910 :
67911 : /*************************************************************************
67912 : This function sets stopping conditions for the optimizer.
67913 :
67914 : INPUT PARAMETERS:
67915 : State - structure which stores algorithm state
67916 : EpsG - >=0
67917 : The subroutine finishes its work if the condition
67918 : |v|<EpsG is satisfied, where:
67919 : * |.| means Euclidian norm
67920 : * v - scaled gradient vector, v[i]=g[i]*s[i]
67921 : * g - gradient
67922 : * s - scaling coefficients set by MinBCSetScale()
67923 : EpsF - >=0
67924 : The subroutine finishes its work if on k+1-th iteration
67925 : the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
67926 : is satisfied.
67927 : EpsX - >=0
67928 : The subroutine finishes its work if on k+1-th iteration
67929 : the condition |v|<=EpsX is fulfilled, where:
67930 : * |.| means Euclidian norm
67931 : * v - scaled step vector, v[i]=dx[i]/s[i]
67932 : * dx - step vector, dx=X(k+1)-X(k)
67933 : * s - scaling coefficients set by MinBCSetScale()
67934 : MaxIts - maximum number of iterations. If MaxIts=0, the number of
67935 : iterations is unlimited.
67936 :
67937 : Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead
67938 : to automatic stopping criterion selection.
67939 :
67940 : NOTE: when SetCond() called with non-zero MaxIts, BC solver may perform
67941 : slightly more than MaxIts iterations. I.e., MaxIts sets non-strict
67942 : limit on iterations count.
67943 :
67944 : -- ALGLIB --
67945 : Copyright 28.11.2010 by Bochkanov Sergey
67946 : *************************************************************************/
67947 0 : void minbcsetcond(minbcstate* state,
67948 : double epsg,
67949 : double epsf,
67950 : double epsx,
67951 : ae_int_t maxits,
67952 : ae_state *_state)
67953 : {
67954 :
67955 :
67956 0 : ae_assert(ae_isfinite(epsg, _state), "MinBCSetCond: EpsG is not finite number", _state);
67957 0 : ae_assert(ae_fp_greater_eq(epsg,(double)(0)), "MinBCSetCond: negative EpsG", _state);
67958 0 : ae_assert(ae_isfinite(epsf, _state), "MinBCSetCond: EpsF is not finite number", _state);
67959 0 : ae_assert(ae_fp_greater_eq(epsf,(double)(0)), "MinBCSetCond: negative EpsF", _state);
67960 0 : ae_assert(ae_isfinite(epsx, _state), "MinBCSetCond: EpsX is not finite number", _state);
67961 0 : ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "MinBCSetCond: negative EpsX", _state);
67962 0 : ae_assert(maxits>=0, "MinBCSetCond: negative MaxIts!", _state);
67963 0 : if( ((ae_fp_eq(epsg,(double)(0))&&ae_fp_eq(epsf,(double)(0)))&&ae_fp_eq(epsx,(double)(0)))&&maxits==0 )
67964 : {
67965 0 : epsx = 1.0E-6;
67966 : }
67967 0 : state->epsg = epsg;
67968 0 : state->epsf = epsf;
67969 0 : state->epsx = epsx;
67970 0 : state->maxits = maxits;
67971 0 : }
67972 :
67973 :
67974 : /*************************************************************************
67975 : This function sets scaling coefficients for BC optimizer.
67976 :
67977 : ALGLIB optimizers use scaling matrices to test stopping conditions (step
67978 : size and gradient are scaled before comparison with tolerances). Scale of
67979 : the I-th variable is a translation invariant measure of:
67980 : a) "how large" the variable is
67981 : b) how large the step should be to make significant changes in the function
67982 :
67983 : Scaling is also used by finite difference variant of the optimizer - step
67984 : along I-th axis is equal to DiffStep*S[I].
67985 :
67986 : In most optimizers (and in the BC too) scaling is NOT a form of
67987 : preconditioning. It just affects stopping conditions. You should set
67988 : preconditioner by separate call to one of the MinBCSetPrec...()
67989 : functions.
67990 :
67991 : There is a special preconditioning mode, however, which uses scaling
67992 : coefficients to form diagonal preconditioning matrix. You can turn this
67993 : mode on, if you want. But you should understand that scaling is not the
67994 : same thing as preconditioning - these are two different, although related
67995 : forms of tuning solver.
67996 :
67997 : INPUT PARAMETERS:
67998 : State - structure stores algorithm state
67999 : S - array[N], non-zero scaling coefficients
68000 : S[i] may be negative, sign doesn't matter.
68001 :
68002 : -- ALGLIB --
68003 : Copyright 14.01.2011 by Bochkanov Sergey
68004 : *************************************************************************/
68005 0 : void minbcsetscale(minbcstate* state,
68006 : /* Real */ ae_vector* s,
68007 : ae_state *_state)
68008 : {
68009 : ae_int_t i;
68010 :
68011 :
68012 0 : ae_assert(s->cnt>=state->nmain, "MinBCSetScale: Length(S)<N", _state);
68013 0 : for(i=0; i<=state->nmain-1; i++)
68014 : {
68015 0 : ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "MinBCSetScale: S contains infinite or NAN elements", _state);
68016 0 : ae_assert(ae_fp_neq(s->ptr.p_double[i],(double)(0)), "MinBCSetScale: S contains zero elements", _state);
68017 0 : state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state);
68018 : }
68019 0 : }
68020 :
68021 :
68022 : /*************************************************************************
68023 : Modification of the preconditioner: preconditioning is turned off.
68024 :
68025 : INPUT PARAMETERS:
68026 : State - structure which stores algorithm state
68027 :
68028 : -- ALGLIB --
68029 : Copyright 13.10.2010 by Bochkanov Sergey
68030 : *************************************************************************/
68031 0 : void minbcsetprecdefault(minbcstate* state, ae_state *_state)
68032 : {
68033 :
68034 :
68035 0 : state->prectype = 0;
68036 0 : }
68037 :
68038 :
68039 : /*************************************************************************
68040 : Modification of the preconditioner: diagonal of approximate Hessian is
68041 : used.
68042 :
68043 : INPUT PARAMETERS:
68044 : State - structure which stores algorithm state
68045 : D - diagonal of the approximate Hessian, array[0..N-1],
68046 : (if larger, only leading N elements are used).
68047 :
68048 : NOTE 1: D[i] should be positive. Exception will be thrown otherwise.
68049 :
68050 : NOTE 2: you should pass diagonal of approximate Hessian - NOT ITS INVERSE.
68051 :
68052 : -- ALGLIB --
68053 : Copyright 13.10.2010 by Bochkanov Sergey
68054 : *************************************************************************/
68055 0 : void minbcsetprecdiag(minbcstate* state,
68056 : /* Real */ ae_vector* d,
68057 : ae_state *_state)
68058 : {
68059 : ae_int_t i;
68060 :
68061 :
68062 0 : ae_assert(d->cnt>=state->nmain, "MinBCSetPrecDiag: D is too short", _state);
68063 0 : for(i=0; i<=state->nmain-1; i++)
68064 : {
68065 0 : ae_assert(ae_isfinite(d->ptr.p_double[i], _state), "MinBCSetPrecDiag: D contains infinite or NAN elements", _state);
68066 0 : ae_assert(ae_fp_greater(d->ptr.p_double[i],(double)(0)), "MinBCSetPrecDiag: D contains non-positive elements", _state);
68067 : }
68068 0 : rvectorsetlengthatleast(&state->diagh, state->nmain, _state);
68069 0 : state->prectype = 2;
68070 0 : for(i=0; i<=state->nmain-1; i++)
68071 : {
68072 0 : state->diagh.ptr.p_double[i] = d->ptr.p_double[i];
68073 : }
68074 0 : }
68075 :
68076 :
68077 : /*************************************************************************
68078 : Modification of the preconditioner: scale-based diagonal preconditioning.
68079 :
68080 : This preconditioning mode can be useful when you don't have approximate
68081 : diagonal of Hessian, but you know that your variables are badly scaled
68082 : (for example, one variable is in [1,10], and another in [1000,100000]),
68083 : and most part of the ill-conditioning comes from different scales of vars.
68084 :
68085 : In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2),
68086 : can greatly improve convergence.
68087 :
68088 : IMPRTANT: you should set scale of your variables with MinBCSetScale()
68089 : call (before or after MinBCSetPrecScale() call). Without knowledge of
68090 : the scale of your variables scale-based preconditioner will be just unit
68091 : matrix.
68092 :
68093 : INPUT PARAMETERS:
68094 : State - structure which stores algorithm state
68095 :
68096 : -- ALGLIB --
68097 : Copyright 13.10.2010 by Bochkanov Sergey
68098 : *************************************************************************/
68099 0 : void minbcsetprecscale(minbcstate* state, ae_state *_state)
68100 : {
68101 :
68102 :
68103 0 : state->prectype = 3;
68104 0 : }
68105 :
68106 :
68107 : /*************************************************************************
68108 : This function turns on/off reporting.
68109 :
68110 : INPUT PARAMETERS:
68111 : State - structure which stores algorithm state
68112 : NeedXRep- whether iteration reports are needed or not
68113 :
68114 : If NeedXRep is True, algorithm will call rep() callback function if it is
68115 : provided to MinBCOptimize().
68116 :
68117 : -- ALGLIB --
68118 : Copyright 28.11.2010 by Bochkanov Sergey
68119 : *************************************************************************/
68120 0 : void minbcsetxrep(minbcstate* state, ae_bool needxrep, ae_state *_state)
68121 : {
68122 :
68123 :
68124 0 : state->xrep = needxrep;
68125 0 : }
68126 :
68127 :
68128 : /*************************************************************************
68129 : This function sets maximum step length
68130 :
68131 : INPUT PARAMETERS:
68132 : State - structure which stores algorithm state
68133 : StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't
68134 : want to limit step length.
68135 :
68136 : Use this subroutine when you optimize target function which contains exp()
68137 : or other fast growing functions, and optimization algorithm makes too
68138 : large steps which lead to overflow. This function allows us to reject
68139 : steps that are too large (and therefore expose us to the possible
68140 : overflow) without actually calculating function value at the x+stp*d.
68141 :
68142 : -- ALGLIB --
68143 : Copyright 02.04.2010 by Bochkanov Sergey
68144 : *************************************************************************/
68145 0 : void minbcsetstpmax(minbcstate* state, double stpmax, ae_state *_state)
68146 : {
68147 :
68148 :
68149 0 : ae_assert(ae_isfinite(stpmax, _state), "MinBCSetStpMax: StpMax is not finite!", _state);
68150 0 : ae_assert(ae_fp_greater_eq(stpmax,(double)(0)), "MinBCSetStpMax: StpMax<0!", _state);
68151 0 : state->stpmax = stpmax;
68152 0 : }
68153 :
68154 :
68155 : /*************************************************************************
68156 : NOTES:
68157 :
68158 : 1. This function has two different implementations: one which uses exact
68159 : (analytical) user-supplied gradient, and one which uses function value
68160 : only and numerically differentiates function in order to obtain
68161 : gradient.
68162 :
68163 : Depending on the specific function used to create optimizer object
68164 : (either MinBCCreate() for analytical gradient or MinBCCreateF()
68165 : for numerical differentiation) you should choose appropriate variant of
68166 : MinBCOptimize() - one which accepts function AND gradient or one
68167 : which accepts function ONLY.
68168 :
68169 : Be careful to choose variant of MinBCOptimize() which corresponds to
68170 : your optimization scheme! Table below lists different combinations of
68171 : callback (function/gradient) passed to MinBCOptimize() and specific
68172 : function used to create optimizer.
68173 :
68174 :
68175 : | USER PASSED TO MinBCOptimize()
68176 : CREATED WITH | function only | function and gradient
68177 : ------------------------------------------------------------
68178 : MinBCCreateF() | works FAILS
68179 : MinBCCreate() | FAILS works
68180 :
68181 : Here "FAIL" denotes inappropriate combinations of optimizer creation
68182 : function and MinBCOptimize() version. Attemps to use such
68183 : combination (for example, to create optimizer with MinBCCreateF()
68184 : and to pass gradient information to MinCGOptimize()) will lead to
68185 : exception being thrown. Either you did not pass gradient when it WAS
68186 : needed or you passed gradient when it was NOT needed.
68187 :
68188 : -- ALGLIB --
68189 : Copyright 28.11.2010 by Bochkanov Sergey
68190 : *************************************************************************/
68191 0 : ae_bool minbciteration(minbcstate* state, ae_state *_state)
68192 : {
68193 : ae_int_t freezeidx;
68194 : double freezeval;
68195 : double scaleddnorm;
68196 : ae_int_t n;
68197 : ae_int_t m;
68198 : ae_int_t i;
68199 : ae_int_t j;
68200 : double v;
68201 : double vv;
68202 : double v0;
68203 : ae_bool b;
68204 : ae_int_t mcinfo;
68205 : ae_int_t itidx;
68206 : double ginit;
68207 : double gdecay;
68208 : ae_bool activationstatus;
68209 : double activationstep;
68210 : ae_bool result;
68211 :
68212 :
68213 :
68214 : /*
68215 : * Reverse communication preparations
68216 : * I know it looks ugly, but it works the same way
68217 : * anywhere from C++ to Python.
68218 : *
68219 : * This code initializes locals by:
68220 : * * random values determined during code
68221 : * generation - on first subroutine call
68222 : * * values from previous call - on subsequent calls
68223 : */
68224 0 : if( state->rstate.stage>=0 )
68225 : {
68226 0 : freezeidx = state->rstate.ia.ptr.p_int[0];
68227 0 : n = state->rstate.ia.ptr.p_int[1];
68228 0 : m = state->rstate.ia.ptr.p_int[2];
68229 0 : i = state->rstate.ia.ptr.p_int[3];
68230 0 : j = state->rstate.ia.ptr.p_int[4];
68231 0 : mcinfo = state->rstate.ia.ptr.p_int[5];
68232 0 : itidx = state->rstate.ia.ptr.p_int[6];
68233 0 : b = state->rstate.ba.ptr.p_bool[0];
68234 0 : activationstatus = state->rstate.ba.ptr.p_bool[1];
68235 0 : freezeval = state->rstate.ra.ptr.p_double[0];
68236 0 : scaleddnorm = state->rstate.ra.ptr.p_double[1];
68237 0 : v = state->rstate.ra.ptr.p_double[2];
68238 0 : vv = state->rstate.ra.ptr.p_double[3];
68239 0 : v0 = state->rstate.ra.ptr.p_double[4];
68240 0 : ginit = state->rstate.ra.ptr.p_double[5];
68241 0 : gdecay = state->rstate.ra.ptr.p_double[6];
68242 0 : activationstep = state->rstate.ra.ptr.p_double[7];
68243 : }
68244 : else
68245 : {
68246 0 : freezeidx = 359;
68247 0 : n = -58;
68248 0 : m = -919;
68249 0 : i = -909;
68250 0 : j = 81;
68251 0 : mcinfo = 255;
68252 0 : itidx = 74;
68253 0 : b = ae_false;
68254 0 : activationstatus = ae_true;
68255 0 : freezeval = 205;
68256 0 : scaleddnorm = -838;
68257 0 : v = 939;
68258 0 : vv = -526;
68259 0 : v0 = 763;
68260 0 : ginit = -541;
68261 0 : gdecay = -698;
68262 0 : activationstep = -900;
68263 : }
68264 0 : if( state->rstate.stage==0 )
68265 : {
68266 0 : goto lbl_0;
68267 : }
68268 0 : if( state->rstate.stage==1 )
68269 : {
68270 0 : goto lbl_1;
68271 : }
68272 0 : if( state->rstate.stage==2 )
68273 : {
68274 0 : goto lbl_2;
68275 : }
68276 0 : if( state->rstate.stage==3 )
68277 : {
68278 0 : goto lbl_3;
68279 : }
68280 0 : if( state->rstate.stage==4 )
68281 : {
68282 0 : goto lbl_4;
68283 : }
68284 0 : if( state->rstate.stage==5 )
68285 : {
68286 0 : goto lbl_5;
68287 : }
68288 0 : if( state->rstate.stage==6 )
68289 : {
68290 0 : goto lbl_6;
68291 : }
68292 0 : if( state->rstate.stage==7 )
68293 : {
68294 0 : goto lbl_7;
68295 : }
68296 0 : if( state->rstate.stage==8 )
68297 : {
68298 0 : goto lbl_8;
68299 : }
68300 0 : if( state->rstate.stage==9 )
68301 : {
68302 0 : goto lbl_9;
68303 : }
68304 0 : if( state->rstate.stage==10 )
68305 : {
68306 0 : goto lbl_10;
68307 : }
68308 0 : if( state->rstate.stage==11 )
68309 : {
68310 0 : goto lbl_11;
68311 : }
68312 0 : if( state->rstate.stage==12 )
68313 : {
68314 0 : goto lbl_12;
68315 : }
68316 0 : if( state->rstate.stage==13 )
68317 : {
68318 0 : goto lbl_13;
68319 : }
68320 0 : if( state->rstate.stage==14 )
68321 : {
68322 0 : goto lbl_14;
68323 : }
68324 0 : if( state->rstate.stage==15 )
68325 : {
68326 0 : goto lbl_15;
68327 : }
68328 0 : if( state->rstate.stage==16 )
68329 : {
68330 0 : goto lbl_16;
68331 : }
68332 0 : if( state->rstate.stage==17 )
68333 : {
68334 0 : goto lbl_17;
68335 : }
68336 0 : if( state->rstate.stage==18 )
68337 : {
68338 0 : goto lbl_18;
68339 : }
68340 0 : if( state->rstate.stage==19 )
68341 : {
68342 0 : goto lbl_19;
68343 : }
68344 0 : if( state->rstate.stage==20 )
68345 : {
68346 0 : goto lbl_20;
68347 : }
68348 0 : if( state->rstate.stage==21 )
68349 : {
68350 0 : goto lbl_21;
68351 : }
68352 0 : if( state->rstate.stage==22 )
68353 : {
68354 0 : goto lbl_22;
68355 : }
68356 0 : if( state->rstate.stage==23 )
68357 : {
68358 0 : goto lbl_23;
68359 : }
68360 0 : if( state->rstate.stage==24 )
68361 : {
68362 0 : goto lbl_24;
68363 : }
68364 0 : if( state->rstate.stage==25 )
68365 : {
68366 0 : goto lbl_25;
68367 : }
68368 0 : if( state->rstate.stage==26 )
68369 : {
68370 0 : goto lbl_26;
68371 : }
68372 0 : if( state->rstate.stage==27 )
68373 : {
68374 0 : goto lbl_27;
68375 : }
68376 0 : if( state->rstate.stage==28 )
68377 : {
68378 0 : goto lbl_28;
68379 : }
68380 0 : if( state->rstate.stage==29 )
68381 : {
68382 0 : goto lbl_29;
68383 : }
68384 :
68385 : /*
68386 : * Routine body
68387 : */
68388 :
68389 : /*
68390 : * Algorithm parameters:
68391 : * * M number of L-BFGS corrections.
68392 : * This coefficient remains fixed during iterations.
68393 : * * GDecay desired decrease of constrained gradient during L-BFGS iterations.
68394 : * This coefficient is decreased after each L-BFGS round until
68395 : * it reaches minimum decay.
68396 : */
68397 0 : m = ae_minint(5, state->nmain, _state);
68398 0 : gdecay = minbc_initialdecay;
68399 :
68400 : /*
68401 : * Init
68402 : */
68403 0 : n = state->nmain;
68404 0 : for(i=0; i<=n-1; i++)
68405 : {
68406 0 : state->xc.ptr.p_double[i] = state->xstart.ptr.p_double[i];
68407 : }
68408 0 : if( !enforceboundaryconstraints(&state->xc, &state->bndl, &state->hasbndl, &state->bndu, &state->hasbndu, n, 0, _state) )
68409 : {
68410 :
68411 : /*
68412 : * Inconsistent constraints
68413 : */
68414 0 : state->repterminationtype = -3;
68415 0 : result = ae_false;
68416 0 : return result;
68417 : }
68418 0 : state->userterminationneeded = ae_false;
68419 0 : state->repterminationtype = 0;
68420 0 : state->repiterationscount = 0;
68421 0 : state->repnfev = 0;
68422 0 : state->repvaridx = -1;
68423 0 : rmatrixsetlengthatleast(&state->bufyk, m+1, n, _state);
68424 0 : rmatrixsetlengthatleast(&state->bufsk, m+1, n, _state);
68425 0 : rvectorsetlengthatleast(&state->bufrho, m, _state);
68426 0 : rvectorsetlengthatleast(&state->buftheta, m, _state);
68427 0 : rvectorsetlengthatleast(&state->tmp0, n, _state);
68428 0 : smoothnessmonitorinit(&state->smonitor, &state->s, n, 1, state->smoothnessguardlevel>0, _state);
68429 0 : for(i=0; i<=n-1; i++)
68430 : {
68431 0 : state->lastscaleused.ptr.p_double[i] = state->s.ptr.p_double[i];
68432 0 : state->invs.ptr.p_double[i] = 1/state->s.ptr.p_double[i];
68433 : }
68434 :
68435 : /*
68436 : * Fill TmpPrec with current preconditioner
68437 : */
68438 0 : rvectorsetlengthatleast(&state->tmpprec, n, _state);
68439 0 : for(i=0; i<=n-1; i++)
68440 : {
68441 0 : if( state->prectype==2 )
68442 : {
68443 0 : state->tmpprec.ptr.p_double[i] = 1/state->diagh.ptr.p_double[i];
68444 0 : continue;
68445 : }
68446 0 : if( state->prectype==3 )
68447 : {
68448 0 : state->tmpprec.ptr.p_double[i] = ae_sqr(state->s.ptr.p_double[i], _state);
68449 0 : continue;
68450 : }
68451 0 : state->tmpprec.ptr.p_double[i] = (double)(1);
68452 : }
68453 :
68454 : /*
68455 : * Check correctness of user-supplied gradient
68456 : */
68457 0 : minbc_clearrequestfields(state, _state);
68458 0 : if( !(ae_fp_eq(state->diffstep,(double)(0))&&ae_fp_greater(state->teststep,(double)(0))) )
68459 : {
68460 0 : goto lbl_30;
68461 : }
68462 0 : lbl_32:
68463 0 : if( !smoothnessmonitorcheckgradientatx0(&state->smonitor, &state->xc, &state->s, &state->bndl, &state->bndu, ae_true, state->teststep, _state) )
68464 : {
68465 0 : goto lbl_33;
68466 : }
68467 0 : for(i=0; i<=n-1; i++)
68468 : {
68469 0 : state->x.ptr.p_double[i] = state->smonitor.x.ptr.p_double[i];
68470 : }
68471 0 : state->needfg = ae_true;
68472 0 : state->rstate.stage = 0;
68473 0 : goto lbl_rcomm;
68474 0 : lbl_0:
68475 0 : state->needfg = ae_false;
68476 0 : state->smonitor.fi.ptr.p_double[0] = state->f;
68477 0 : for(i=0; i<=n-1; i++)
68478 : {
68479 0 : state->smonitor.j.ptr.pp_double[0][i] = state->g.ptr.p_double[i];
68480 : }
68481 0 : goto lbl_32;
68482 0 : lbl_33:
68483 0 : lbl_30:
68484 :
68485 : /*
68486 : * Main cycle of BC-PG algorithm
68487 : */
68488 0 : state->repterminationtype = 0;
68489 0 : state->lastscaledgoodstep = (double)(0);
68490 0 : state->nonmonotoniccnt = ae_round(1.5*n, _state)+5;
68491 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
68492 0 : minbc_clearrequestfields(state, _state);
68493 0 : if( ae_fp_neq(state->diffstep,(double)(0)) )
68494 : {
68495 0 : goto lbl_34;
68496 : }
68497 0 : state->needfg = ae_true;
68498 0 : state->rstate.stage = 1;
68499 0 : goto lbl_rcomm;
68500 0 : lbl_1:
68501 0 : state->needfg = ae_false;
68502 0 : goto lbl_35;
68503 0 : lbl_34:
68504 0 : state->needf = ae_true;
68505 0 : state->rstate.stage = 2;
68506 0 : goto lbl_rcomm;
68507 0 : lbl_2:
68508 0 : state->needf = ae_false;
68509 0 : lbl_35:
68510 0 : state->fc = state->f;
68511 0 : trimprepare(state->f, &state->trimthreshold, _state);
68512 0 : state->repnfev = state->repnfev+1;
68513 0 : if( !state->xrep )
68514 : {
68515 0 : goto lbl_36;
68516 : }
68517 :
68518 : /*
68519 : * Report current point
68520 : */
68521 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
68522 0 : state->f = state->fc;
68523 0 : state->xupdated = ae_true;
68524 0 : state->rstate.stage = 3;
68525 0 : goto lbl_rcomm;
68526 0 : lbl_3:
68527 0 : state->xupdated = ae_false;
68528 0 : lbl_36:
68529 0 : if( state->userterminationneeded )
68530 : {
68531 :
68532 : /*
68533 : * User requested termination
68534 : */
68535 0 : state->repterminationtype = 8;
68536 0 : result = ae_false;
68537 0 : return result;
68538 : }
68539 0 : lbl_38:
68540 : if( ae_false )
68541 : {
68542 : goto lbl_39;
68543 : }
68544 :
68545 : /*
68546 : * Steepest descent phase
68547 : *
68548 : * (a) calculate unconstrained gradient
68549 : * (b) check F/G for NAN/INF, abnormally terminate algorithm if needed
68550 : * (c) perform one steepest descent step, activating only those constraints
68551 : * which prevent us from moving outside of box-constrained area
68552 : */
68553 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
68554 0 : minbc_clearrequestfields(state, _state);
68555 0 : if( ae_fp_neq(state->diffstep,(double)(0)) )
68556 : {
68557 0 : goto lbl_40;
68558 : }
68559 :
68560 : /*
68561 : * Analytic gradient
68562 : */
68563 0 : state->needfg = ae_true;
68564 0 : state->rstate.stage = 4;
68565 0 : goto lbl_rcomm;
68566 0 : lbl_4:
68567 0 : state->needfg = ae_false;
68568 0 : goto lbl_41;
68569 0 : lbl_40:
68570 :
68571 : /*
68572 : * Numerical differentiation
68573 : */
68574 0 : state->needf = ae_true;
68575 0 : state->rstate.stage = 5;
68576 0 : goto lbl_rcomm;
68577 0 : lbl_5:
68578 0 : state->fbase = state->f;
68579 0 : i = 0;
68580 0 : lbl_42:
68581 0 : if( i>n-1 )
68582 : {
68583 0 : goto lbl_44;
68584 : }
68585 0 : v = state->x.ptr.p_double[i];
68586 0 : b = ae_false;
68587 0 : if( state->hasbndl.ptr.p_bool[i] )
68588 : {
68589 0 : b = b||ae_fp_less(v-state->diffstep*state->s.ptr.p_double[i],state->bndl.ptr.p_double[i]);
68590 : }
68591 0 : if( state->hasbndu.ptr.p_bool[i] )
68592 : {
68593 0 : b = b||ae_fp_greater(v+state->diffstep*state->s.ptr.p_double[i],state->bndu.ptr.p_double[i]);
68594 : }
68595 0 : if( b )
68596 : {
68597 0 : goto lbl_45;
68598 : }
68599 0 : state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i];
68600 0 : state->rstate.stage = 6;
68601 0 : goto lbl_rcomm;
68602 0 : lbl_6:
68603 0 : state->fm2 = state->f;
68604 0 : state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i];
68605 0 : state->rstate.stage = 7;
68606 0 : goto lbl_rcomm;
68607 0 : lbl_7:
68608 0 : state->fm1 = state->f;
68609 0 : state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i];
68610 0 : state->rstate.stage = 8;
68611 0 : goto lbl_rcomm;
68612 0 : lbl_8:
68613 0 : state->fp1 = state->f;
68614 0 : state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i];
68615 0 : state->rstate.stage = 9;
68616 0 : goto lbl_rcomm;
68617 0 : lbl_9:
68618 0 : state->fp2 = state->f;
68619 0 : state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]);
68620 0 : goto lbl_46;
68621 0 : lbl_45:
68622 0 : state->xm1 = v-state->diffstep*state->s.ptr.p_double[i];
68623 0 : state->xp1 = v+state->diffstep*state->s.ptr.p_double[i];
68624 0 : if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less(state->xm1,state->bndl.ptr.p_double[i]) )
68625 : {
68626 0 : state->xm1 = state->bndl.ptr.p_double[i];
68627 : }
68628 0 : if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater(state->xp1,state->bndu.ptr.p_double[i]) )
68629 : {
68630 0 : state->xp1 = state->bndu.ptr.p_double[i];
68631 : }
68632 0 : state->x.ptr.p_double[i] = state->xm1;
68633 0 : state->rstate.stage = 10;
68634 0 : goto lbl_rcomm;
68635 0 : lbl_10:
68636 0 : state->fm1 = state->f;
68637 0 : state->x.ptr.p_double[i] = state->xp1;
68638 0 : state->rstate.stage = 11;
68639 0 : goto lbl_rcomm;
68640 0 : lbl_11:
68641 0 : state->fp1 = state->f;
68642 0 : if( ae_fp_neq(state->xm1,state->xp1) )
68643 : {
68644 0 : state->g.ptr.p_double[i] = (state->fp1-state->fm1)/(state->xp1-state->xm1);
68645 : }
68646 : else
68647 : {
68648 0 : state->g.ptr.p_double[i] = (double)(0);
68649 : }
68650 0 : lbl_46:
68651 0 : state->x.ptr.p_double[i] = v;
68652 0 : i = i+1;
68653 0 : goto lbl_42;
68654 0 : lbl_44:
68655 0 : state->f = state->fbase;
68656 0 : state->needf = ae_false;
68657 0 : lbl_41:
68658 0 : state->fc = state->f;
68659 0 : ae_v_move(&state->ugc.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
68660 0 : ae_v_move(&state->cgc.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
68661 0 : projectgradientintobc(&state->xc, &state->cgc, &state->bndl, &state->hasbndl, &state->bndu, &state->hasbndu, n, 0, _state);
68662 0 : ginit = 0.0;
68663 0 : for(i=0; i<=n-1; i++)
68664 : {
68665 0 : ginit = ginit+ae_sqr(state->cgc.ptr.p_double[i]*state->s.ptr.p_double[i], _state);
68666 : }
68667 0 : ginit = ae_sqrt(ginit, _state);
68668 0 : if( !ae_isfinite(ginit, _state)||!ae_isfinite(state->fc, _state) )
68669 : {
68670 :
68671 : /*
68672 : * Abnormal termination - infinities in function/gradient
68673 : */
68674 0 : state->repterminationtype = -8;
68675 0 : result = ae_false;
68676 0 : return result;
68677 : }
68678 0 : if( state->userterminationneeded )
68679 : {
68680 :
68681 : /*
68682 : * User requested termination
68683 : */
68684 0 : state->repterminationtype = 8;
68685 0 : result = ae_false;
68686 0 : return result;
68687 : }
68688 0 : if( ae_fp_less_eq(ginit,state->epsg) )
68689 : {
68690 :
68691 : /*
68692 : * Gradient is small enough.
68693 : * Optimization is terminated
68694 : */
68695 0 : state->repterminationtype = 4;
68696 0 : result = ae_false;
68697 0 : return result;
68698 : }
68699 0 : for(i=0; i<=n-1; i++)
68700 : {
68701 0 : state->d.ptr.p_double[i] = -state->tmpprec.ptr.p_double[i]*state->cgc.ptr.p_double[i];
68702 : }
68703 0 : scaleddnorm = (double)(0);
68704 0 : for(i=0; i<=n-1; i++)
68705 : {
68706 0 : scaleddnorm = scaleddnorm+ae_sqr(state->d.ptr.p_double[i]/state->s.ptr.p_double[i], _state);
68707 : }
68708 0 : scaleddnorm = ae_sqrt(scaleddnorm, _state);
68709 0 : ae_assert(ae_fp_greater(scaleddnorm,(double)(0)), "MinBC: integrity check failed", _state);
68710 0 : if( ae_fp_greater(state->lastscaledgoodstep,(double)(0)) )
68711 : {
68712 0 : state->stp = state->lastscaledgoodstep/scaleddnorm;
68713 : }
68714 : else
68715 : {
68716 0 : state->stp = 1.0/scaleddnorm;
68717 : }
68718 0 : calculatestepbound(&state->xc, &state->d, 1.0, &state->bndl, &state->hasbndl, &state->bndu, &state->hasbndu, n, 0, &freezeidx, &freezeval, &state->curstpmax, _state);
68719 0 : activationstep = state->curstpmax;
68720 0 : if( freezeidx<0||ae_fp_greater(state->curstpmax,1.0E50) )
68721 : {
68722 0 : state->curstpmax = 1.0E50;
68723 : }
68724 0 : if( ae_fp_greater(state->stpmax,(double)(0)) )
68725 : {
68726 0 : state->curstpmax = ae_minreal(state->curstpmax, state->stpmax/scaleddnorm, _state);
68727 : }
68728 0 : ae_v_move(&state->xn.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
68729 0 : ae_v_move(&state->cgn.ptr.p_double[0], 1, &state->cgc.ptr.p_double[0], 1, ae_v_len(0,n-1));
68730 0 : ae_v_move(&state->ugn.ptr.p_double[0], 1, &state->ugc.ptr.p_double[0], 1, ae_v_len(0,n-1));
68731 0 : state->fn = state->fc;
68732 0 : state->mcstage = 0;
68733 0 : smoothnessmonitorstartlinesearch1u(&state->smonitor, &state->s, &state->invs, &state->xn, state->fn, &state->ugn, _state);
68734 0 : mcsrch(n, &state->xn, &state->fn, &state->cgn, &state->d, &state->stp, state->curstpmax, minbc_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state);
68735 0 : lbl_47:
68736 0 : if( state->mcstage==0 )
68737 : {
68738 0 : goto lbl_48;
68739 : }
68740 :
68741 : /*
68742 : * Copy XN to X, perform on-the-fly correction w.r.t box
68743 : * constraints (projection onto feasible set).
68744 : */
68745 0 : for(i=0; i<=n-1; i++)
68746 : {
68747 0 : state->x.ptr.p_double[i] = state->xn.ptr.p_double[i];
68748 0 : if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less(state->xn.ptr.p_double[i],state->bndl.ptr.p_double[i]) )
68749 : {
68750 0 : state->x.ptr.p_double[i] = state->bndl.ptr.p_double[i];
68751 : }
68752 0 : if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater(state->xn.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
68753 : {
68754 0 : state->x.ptr.p_double[i] = state->bndu.ptr.p_double[i];
68755 : }
68756 : }
68757 :
68758 : /*
68759 : * Gradient, either user-provided or numerical differentiation
68760 : */
68761 0 : minbc_clearrequestfields(state, _state);
68762 0 : if( ae_fp_neq(state->diffstep,(double)(0)) )
68763 : {
68764 0 : goto lbl_49;
68765 : }
68766 :
68767 : /*
68768 : * Analytic gradient
68769 : */
68770 0 : state->needfg = ae_true;
68771 0 : state->rstate.stage = 12;
68772 0 : goto lbl_rcomm;
68773 0 : lbl_12:
68774 0 : state->needfg = ae_false;
68775 0 : state->repnfev = state->repnfev+1;
68776 0 : goto lbl_50;
68777 0 : lbl_49:
68778 :
68779 : /*
68780 : * Numerical differentiation
68781 : */
68782 0 : state->needf = ae_true;
68783 0 : state->rstate.stage = 13;
68784 0 : goto lbl_rcomm;
68785 0 : lbl_13:
68786 0 : state->fbase = state->f;
68787 0 : i = 0;
68788 0 : lbl_51:
68789 0 : if( i>n-1 )
68790 : {
68791 0 : goto lbl_53;
68792 : }
68793 0 : v = state->x.ptr.p_double[i];
68794 0 : b = ae_false;
68795 0 : if( state->hasbndl.ptr.p_bool[i] )
68796 : {
68797 0 : b = b||ae_fp_less(v-state->diffstep*state->s.ptr.p_double[i],state->bndl.ptr.p_double[i]);
68798 : }
68799 0 : if( state->hasbndu.ptr.p_bool[i] )
68800 : {
68801 0 : b = b||ae_fp_greater(v+state->diffstep*state->s.ptr.p_double[i],state->bndu.ptr.p_double[i]);
68802 : }
68803 0 : if( b )
68804 : {
68805 0 : goto lbl_54;
68806 : }
68807 0 : state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i];
68808 0 : state->rstate.stage = 14;
68809 0 : goto lbl_rcomm;
68810 0 : lbl_14:
68811 0 : state->fm2 = state->f;
68812 0 : state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i];
68813 0 : state->rstate.stage = 15;
68814 0 : goto lbl_rcomm;
68815 0 : lbl_15:
68816 0 : state->fm1 = state->f;
68817 0 : state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i];
68818 0 : state->rstate.stage = 16;
68819 0 : goto lbl_rcomm;
68820 0 : lbl_16:
68821 0 : state->fp1 = state->f;
68822 0 : state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i];
68823 0 : state->rstate.stage = 17;
68824 0 : goto lbl_rcomm;
68825 0 : lbl_17:
68826 0 : state->fp2 = state->f;
68827 0 : state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]);
68828 0 : state->repnfev = state->repnfev+4;
68829 0 : goto lbl_55;
68830 0 : lbl_54:
68831 0 : state->xm1 = v-state->diffstep*state->s.ptr.p_double[i];
68832 0 : state->xp1 = v+state->diffstep*state->s.ptr.p_double[i];
68833 0 : if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less(state->xm1,state->bndl.ptr.p_double[i]) )
68834 : {
68835 0 : state->xm1 = state->bndl.ptr.p_double[i];
68836 : }
68837 0 : if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater(state->xp1,state->bndu.ptr.p_double[i]) )
68838 : {
68839 0 : state->xp1 = state->bndu.ptr.p_double[i];
68840 : }
68841 0 : state->x.ptr.p_double[i] = state->xm1;
68842 0 : state->rstate.stage = 18;
68843 0 : goto lbl_rcomm;
68844 0 : lbl_18:
68845 0 : state->fm1 = state->f;
68846 0 : state->x.ptr.p_double[i] = state->xp1;
68847 0 : state->rstate.stage = 19;
68848 0 : goto lbl_rcomm;
68849 0 : lbl_19:
68850 0 : state->fp1 = state->f;
68851 0 : if( ae_fp_neq(state->xm1,state->xp1) )
68852 : {
68853 0 : state->g.ptr.p_double[i] = (state->fp1-state->fm1)/(state->xp1-state->xm1);
68854 : }
68855 : else
68856 : {
68857 0 : state->g.ptr.p_double[i] = (double)(0);
68858 : }
68859 0 : state->repnfev = state->repnfev+2;
68860 0 : lbl_55:
68861 0 : state->x.ptr.p_double[i] = v;
68862 0 : i = i+1;
68863 0 : goto lbl_51;
68864 0 : lbl_53:
68865 0 : state->f = state->fbase;
68866 0 : state->needf = ae_false;
68867 0 : lbl_50:
68868 :
68869 : /*
68870 : * Back to MCSRCH
68871 : */
68872 0 : smoothnessmonitorenqueuepoint1u(&state->smonitor, &state->s, &state->invs, &state->d, state->stp, &state->x, state->f, &state->g, _state);
68873 0 : trimfunction(&state->f, &state->g, n, state->trimthreshold, _state);
68874 0 : state->fn = state->f;
68875 0 : ae_v_move(&state->cgn.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
68876 0 : ae_v_move(&state->ugn.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
68877 0 : for(i=0; i<=n-1; i++)
68878 : {
68879 0 : if( ae_fp_eq(state->d.ptr.p_double[i],(double)(0)) )
68880 : {
68881 0 : state->cgn.ptr.p_double[i] = (double)(0);
68882 : }
68883 : }
68884 0 : mcsrch(n, &state->xn, &state->fn, &state->cgn, &state->d, &state->stp, state->curstpmax, minbc_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state);
68885 0 : goto lbl_47;
68886 0 : lbl_48:
68887 0 : smoothnessmonitorfinalizelinesearch(&state->smonitor, _state);
68888 0 : v = state->fn;
68889 0 : for(i=0; i<=n-1; i++)
68890 : {
68891 0 : v = 0.1*v+state->ugn.ptr.p_double[i];
68892 : }
68893 0 : if( !ae_isfinite(v, _state) )
68894 : {
68895 :
68896 : /*
68897 : * Abnormal termination - infinities in function/gradient
68898 : */
68899 0 : state->repterminationtype = -8;
68900 0 : result = ae_false;
68901 0 : return result;
68902 : }
68903 0 : if( mcinfo!=1&&mcinfo!=5 )
68904 : {
68905 :
68906 : /*
68907 : * We can not find step which decreases function value. We have
68908 : * two possibilities:
68909 : * (a) numerical properties of the function do not allow us to
68910 : * find good step.
68911 : * (b) we are close to activation of some constraint, and it is
68912 : * so close that step which activates it leads to change in
68913 : * target function which is smaller than numerical noise.
68914 : *
68915 : * Optimization algorithm must be able to handle case (b), because
68916 : * inability to handle it will cause failure when algorithm
68917 : * started very close to boundary of the feasible area.
68918 : *
68919 : * In order to correctly handle such cases we allow limited amount
68920 : * of small steps which increase function value.
68921 : */
68922 0 : if( (freezeidx>=0&&ae_fp_less_eq(scaleddnorm*state->curstpmax,minbc_maxnonmonotoniclen))&&state->nonmonotoniccnt>0 )
68923 : {
68924 :
68925 : /*
68926 : * We enforce non-monotonic step:
68927 : * * Stp := CurStpMax
68928 : * * MCINFO := 5
68929 : * * XN := XC+CurStpMax*D
68930 : * * non-monotonic counter is decreased
68931 : *
68932 : * NOTE: UGN/CGN are not updated because step is so short that we assume that
68933 : * GN is approximately equal to GC.
68934 : */
68935 0 : state->stp = state->curstpmax;
68936 0 : mcinfo = 5;
68937 0 : v = state->curstpmax;
68938 0 : ae_v_move(&state->xn.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
68939 0 : ae_v_addd(&state->xn.ptr.p_double[0], 1, &state->d.ptr.p_double[0], 1, ae_v_len(0,n-1), v);
68940 0 : state->nonmonotoniccnt = state->nonmonotoniccnt-1;
68941 : }
68942 : else
68943 : {
68944 :
68945 : /*
68946 : * Numerical properties of the function does not allow
68947 : * us to solve problem. Algorithm is terminated
68948 : */
68949 0 : state->repterminationtype = 7;
68950 0 : result = ae_false;
68951 0 : return result;
68952 : }
68953 : }
68954 0 : if( state->userterminationneeded )
68955 : {
68956 :
68957 : /*
68958 : * User requested termination
68959 : */
68960 0 : state->repterminationtype = 8;
68961 0 : result = ae_false;
68962 0 : return result;
68963 : }
68964 0 : ae_assert(mcinfo!=5||ae_fp_eq(state->stp,state->curstpmax), "MinBC: integrity check failed", _state);
68965 0 : postprocessboundedstep(&state->xn, &state->xc, &state->bndl, &state->hasbndl, &state->bndu, &state->hasbndu, n, 0, freezeidx, freezeval, state->stp, activationstep, _state);
68966 0 : state->fp = state->fc;
68967 0 : state->fc = state->fn;
68968 0 : ae_v_move(&state->xp.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
68969 0 : ae_v_move(&state->xc.ptr.p_double[0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1));
68970 0 : ae_v_move(&state->cgc.ptr.p_double[0], 1, &state->cgn.ptr.p_double[0], 1, ae_v_len(0,n-1));
68971 0 : ae_v_move(&state->ugc.ptr.p_double[0], 1, &state->ugn.ptr.p_double[0], 1, ae_v_len(0,n-1));
68972 0 : if( !state->xrep )
68973 : {
68974 0 : goto lbl_56;
68975 : }
68976 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
68977 0 : minbc_clearrequestfields(state, _state);
68978 0 : state->xupdated = ae_true;
68979 0 : state->rstate.stage = 20;
68980 0 : goto lbl_rcomm;
68981 0 : lbl_20:
68982 0 : state->xupdated = ae_false;
68983 0 : lbl_56:
68984 0 : state->repiterationscount = state->repiterationscount+1;
68985 0 : if( mcinfo==1 )
68986 : {
68987 0 : v = (double)(0);
68988 0 : for(i=0; i<=n-1; i++)
68989 : {
68990 0 : v = v+ae_sqr((state->xc.ptr.p_double[i]-state->xp.ptr.p_double[i])/state->s.ptr.p_double[i], _state);
68991 : }
68992 0 : v = ae_sqrt(v, _state);
68993 0 : if( ae_fp_less_eq(v,state->epsx) )
68994 : {
68995 :
68996 : /*
68997 : * Step is small enough
68998 : */
68999 0 : state->repterminationtype = 2;
69000 0 : result = ae_false;
69001 0 : return result;
69002 : }
69003 0 : 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)) )
69004 : {
69005 :
69006 : /*
69007 : * Function change is small enough
69008 : */
69009 0 : state->repterminationtype = 1;
69010 0 : result = ae_false;
69011 0 : return result;
69012 : }
69013 : }
69014 0 : if( state->maxits>0&&state->repiterationscount>=state->maxits )
69015 : {
69016 :
69017 : /*
69018 : * Iteration counter exceeded limit
69019 : */
69020 0 : state->repterminationtype = 5;
69021 0 : result = ae_false;
69022 0 : return result;
69023 : }
69024 :
69025 : /*
69026 : * LBFGS stage:
69027 : * * during LBFGS iterations we activate new constraints, but never
69028 : * deactivate already active ones.
69029 : * * we perform at most N iterations of LBFGS before re-evaluating
69030 : * active set and restarting LBFGS.
69031 : *
69032 : * About termination:
69033 : * * LBFGS iterations can be terminated because of two reasons:
69034 : * * "termination" - non-zero termination code in RepTerminationType,
69035 : * which means that optimization is done
69036 : * * "restart" - zero RepTerminationType, which means that we
69037 : * have to re-evaluate active set and resume LBFGS stage.
69038 : * * one more option is "refresh" - to continue LBFGS iterations,
69039 : * but with all BFGS updates (Sk/Yk pairs) being dropped;
69040 : * it happens after changes in active set
69041 : */
69042 0 : ginit = 0.0;
69043 0 : for(i=0; i<=n-1; i++)
69044 : {
69045 0 : state->cgc.ptr.p_double[i] = state->ugc.ptr.p_double[i];
69046 0 : if( state->hasbndl.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndl.ptr.p_double[i]) )
69047 : {
69048 0 : state->cgc.ptr.p_double[i] = (double)(0);
69049 : }
69050 0 : if( state->hasbndu.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
69051 : {
69052 0 : state->cgc.ptr.p_double[i] = (double)(0);
69053 : }
69054 0 : ginit = ginit+ae_sqr(state->cgc.ptr.p_double[i]*state->s.ptr.p_double[i], _state);
69055 : }
69056 0 : ginit = ae_sqrt(ginit, _state);
69057 0 : state->bufsize = 0;
69058 0 : itidx = 0;
69059 0 : lbl_58:
69060 0 : if( itidx>n-1 )
69061 : {
69062 0 : goto lbl_60;
69063 : }
69064 :
69065 : /*
69066 : * At the beginning of each iteration:
69067 : * * XC stores current point
69068 : * * FC stores current function value
69069 : * * UGC stores current unconstrained gradient
69070 : * * CGC stores current constrained gradient
69071 : * * D stores constrained step direction (calculated at this block)
69072 : *
69073 : * 1. Calculate search direction D according to L-BFGS algorithm
69074 : * using constrained preconditioner to perform inner multiplication.
69075 : * 2. Evaluate scaled length of direction D; restart LBFGS if D is zero
69076 : * (it may be possible that we found minimum, but it is also possible
69077 : * that some constraints need deactivation)
69078 : * 3. If D is non-zero, try to use previous scaled step length as initial estimate for new step.
69079 : * 4. Calculate bound on step length.
69080 : */
69081 0 : ae_v_move(&state->work.ptr.p_double[0], 1, &state->cgc.ptr.p_double[0], 1, ae_v_len(0,n-1));
69082 0 : for(i=state->bufsize-1; i>=0; i--)
69083 : {
69084 0 : v = ae_v_dotproduct(&state->bufsk.ptr.pp_double[i][0], 1, &state->work.ptr.p_double[0], 1, ae_v_len(0,n-1));
69085 0 : state->buftheta.ptr.p_double[i] = v;
69086 0 : vv = v*state->bufrho.ptr.p_double[i];
69087 0 : ae_v_subd(&state->work.ptr.p_double[0], 1, &state->bufyk.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), vv);
69088 : }
69089 0 : for(i=0; i<=n-1; i++)
69090 : {
69091 0 : state->work.ptr.p_double[i] = state->tmpprec.ptr.p_double[i]*state->work.ptr.p_double[i];
69092 : }
69093 0 : for(i=0; i<=state->bufsize-1; i++)
69094 : {
69095 0 : v = ae_v_dotproduct(&state->bufyk.ptr.pp_double[i][0], 1, &state->work.ptr.p_double[0], 1, ae_v_len(0,n-1));
69096 0 : vv = state->bufrho.ptr.p_double[i]*(-v+state->buftheta.ptr.p_double[i]);
69097 0 : ae_v_addd(&state->work.ptr.p_double[0], 1, &state->bufsk.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), vv);
69098 : }
69099 0 : ae_v_moveneg(&state->d.ptr.p_double[0], 1, &state->work.ptr.p_double[0], 1, ae_v_len(0,n-1));
69100 0 : b = ae_false;
69101 0 : for(i=0; i<=n-1; i++)
69102 : {
69103 0 : b = b||((state->hasbndl.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndl.ptr.p_double[i]))&&ae_fp_neq(state->d.ptr.p_double[i],(double)(0)));
69104 0 : b = b||((state->hasbndu.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndu.ptr.p_double[i]))&&ae_fp_neq(state->d.ptr.p_double[i],(double)(0)));
69105 : }
69106 0 : ae_assert(!b, "MinBC: integrity check failed (q)", _state);
69107 0 : scaleddnorm = (double)(0);
69108 0 : for(i=0; i<=n-1; i++)
69109 : {
69110 0 : scaleddnorm = scaleddnorm+ae_sqr(state->d.ptr.p_double[i]/state->s.ptr.p_double[i], _state);
69111 : }
69112 0 : scaleddnorm = ae_sqrt(scaleddnorm, _state);
69113 0 : if( ae_fp_eq(scaleddnorm,(double)(0)) )
69114 : {
69115 :
69116 : /*
69117 : * Search direction is zero.
69118 : * Skip back to steepest descent phase.
69119 : */
69120 0 : goto lbl_60;
69121 : }
69122 0 : if( ae_fp_greater(state->lastscaledgoodstep,(double)(0)) )
69123 : {
69124 0 : state->stp = state->lastscaledgoodstep/scaleddnorm;
69125 : }
69126 : else
69127 : {
69128 0 : state->stp = 1.0/scaleddnorm;
69129 : }
69130 0 : state->curstpmax = 1.0E50;
69131 0 : if( ae_fp_greater(state->stpmax,(double)(0)) )
69132 : {
69133 0 : state->curstpmax = ae_minreal(state->curstpmax, state->stpmax/scaleddnorm, _state);
69134 : }
69135 :
69136 : /*
69137 : * Minimize G(t) = F(CONSTRAIN(XC + t*D)), with t being scalar, XC and D being vectors.
69138 : */
69139 0 : ae_v_move(&state->xn.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
69140 0 : ae_v_move(&state->cgn.ptr.p_double[0], 1, &state->cgc.ptr.p_double[0], 1, ae_v_len(0,n-1));
69141 0 : ae_v_move(&state->ugn.ptr.p_double[0], 1, &state->ugc.ptr.p_double[0], 1, ae_v_len(0,n-1));
69142 0 : state->fn = state->fc;
69143 0 : state->mcstage = 0;
69144 0 : smoothnessmonitorstartlinesearch1u(&state->smonitor, &state->s, &state->invs, &state->xn, state->fn, &state->ugn, _state);
69145 0 : mcsrch(n, &state->xn, &state->fn, &state->cgn, &state->d, &state->stp, state->curstpmax, minbc_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state);
69146 0 : lbl_61:
69147 0 : if( state->mcstage==0 )
69148 : {
69149 0 : goto lbl_62;
69150 : }
69151 :
69152 : /*
69153 : * Copy XN to X, perform on-the-fly correction w.r.t box
69154 : * constraints (projection onto feasible set).
69155 : */
69156 0 : for(i=0; i<=n-1; i++)
69157 : {
69158 0 : state->x.ptr.p_double[i] = state->xn.ptr.p_double[i];
69159 0 : if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less_eq(state->xn.ptr.p_double[i],state->bndl.ptr.p_double[i]) )
69160 : {
69161 0 : state->x.ptr.p_double[i] = state->bndl.ptr.p_double[i];
69162 : }
69163 0 : if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater_eq(state->xn.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
69164 : {
69165 0 : state->x.ptr.p_double[i] = state->bndu.ptr.p_double[i];
69166 : }
69167 : }
69168 :
69169 : /*
69170 : * Gradient, either user-provided or numerical differentiation
69171 : */
69172 0 : minbc_clearrequestfields(state, _state);
69173 0 : if( ae_fp_neq(state->diffstep,(double)(0)) )
69174 : {
69175 0 : goto lbl_63;
69176 : }
69177 :
69178 : /*
69179 : * Analytic gradient
69180 : */
69181 0 : state->needfg = ae_true;
69182 0 : state->rstate.stage = 21;
69183 0 : goto lbl_rcomm;
69184 0 : lbl_21:
69185 0 : state->needfg = ae_false;
69186 0 : state->repnfev = state->repnfev+1;
69187 0 : goto lbl_64;
69188 0 : lbl_63:
69189 :
69190 : /*
69191 : * Numerical differentiation
69192 : */
69193 0 : state->needf = ae_true;
69194 0 : state->rstate.stage = 22;
69195 0 : goto lbl_rcomm;
69196 0 : lbl_22:
69197 0 : state->fbase = state->f;
69198 0 : i = 0;
69199 0 : lbl_65:
69200 0 : if( i>n-1 )
69201 : {
69202 0 : goto lbl_67;
69203 : }
69204 0 : v = state->x.ptr.p_double[i];
69205 0 : b = ae_false;
69206 0 : if( state->hasbndl.ptr.p_bool[i] )
69207 : {
69208 0 : b = b||ae_fp_less(v-state->diffstep*state->s.ptr.p_double[i],state->bndl.ptr.p_double[i]);
69209 : }
69210 0 : if( state->hasbndu.ptr.p_bool[i] )
69211 : {
69212 0 : b = b||ae_fp_greater(v+state->diffstep*state->s.ptr.p_double[i],state->bndu.ptr.p_double[i]);
69213 : }
69214 0 : if( b )
69215 : {
69216 0 : goto lbl_68;
69217 : }
69218 0 : state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i];
69219 0 : state->rstate.stage = 23;
69220 0 : goto lbl_rcomm;
69221 0 : lbl_23:
69222 0 : state->fm2 = state->f;
69223 0 : state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i];
69224 0 : state->rstate.stage = 24;
69225 0 : goto lbl_rcomm;
69226 0 : lbl_24:
69227 0 : state->fm1 = state->f;
69228 0 : state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i];
69229 0 : state->rstate.stage = 25;
69230 0 : goto lbl_rcomm;
69231 0 : lbl_25:
69232 0 : state->fp1 = state->f;
69233 0 : state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i];
69234 0 : state->rstate.stage = 26;
69235 0 : goto lbl_rcomm;
69236 0 : lbl_26:
69237 0 : state->fp2 = state->f;
69238 0 : state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]);
69239 0 : state->repnfev = state->repnfev+4;
69240 0 : goto lbl_69;
69241 0 : lbl_68:
69242 0 : state->xm1 = v-state->diffstep*state->s.ptr.p_double[i];
69243 0 : state->xp1 = v+state->diffstep*state->s.ptr.p_double[i];
69244 0 : if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less(state->xm1,state->bndl.ptr.p_double[i]) )
69245 : {
69246 0 : state->xm1 = state->bndl.ptr.p_double[i];
69247 : }
69248 0 : if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater(state->xp1,state->bndu.ptr.p_double[i]) )
69249 : {
69250 0 : state->xp1 = state->bndu.ptr.p_double[i];
69251 : }
69252 0 : state->x.ptr.p_double[i] = state->xm1;
69253 0 : state->rstate.stage = 27;
69254 0 : goto lbl_rcomm;
69255 0 : lbl_27:
69256 0 : state->fm1 = state->f;
69257 0 : state->x.ptr.p_double[i] = state->xp1;
69258 0 : state->rstate.stage = 28;
69259 0 : goto lbl_rcomm;
69260 0 : lbl_28:
69261 0 : state->fp1 = state->f;
69262 0 : if( ae_fp_neq(state->xm1,state->xp1) )
69263 : {
69264 0 : state->g.ptr.p_double[i] = (state->fp1-state->fm1)/(state->xp1-state->xm1);
69265 : }
69266 : else
69267 : {
69268 0 : state->g.ptr.p_double[i] = (double)(0);
69269 : }
69270 0 : state->repnfev = state->repnfev+2;
69271 0 : lbl_69:
69272 0 : state->x.ptr.p_double[i] = v;
69273 0 : i = i+1;
69274 0 : goto lbl_65;
69275 0 : lbl_67:
69276 0 : state->f = state->fbase;
69277 0 : state->needf = ae_false;
69278 0 : lbl_64:
69279 :
69280 : /*
69281 : * Back to MCSRCH
69282 : */
69283 0 : smoothnessmonitorenqueuepoint1u(&state->smonitor, &state->s, &state->invs, &state->d, state->stp, &state->x, state->f, &state->g, _state);
69284 0 : trimfunction(&state->f, &state->g, n, state->trimthreshold, _state);
69285 0 : state->fn = state->f;
69286 0 : for(i=0; i<=n-1; i++)
69287 : {
69288 0 : state->ugn.ptr.p_double[i] = state->g.ptr.p_double[i];
69289 0 : state->cgn.ptr.p_double[i] = state->g.ptr.p_double[i];
69290 0 : if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less_eq(state->xn.ptr.p_double[i],state->bndl.ptr.p_double[i]) )
69291 : {
69292 0 : state->cgn.ptr.p_double[i] = (double)(0);
69293 : }
69294 0 : if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater_eq(state->xn.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
69295 : {
69296 0 : state->cgn.ptr.p_double[i] = (double)(0);
69297 : }
69298 : }
69299 0 : mcsrch(n, &state->xn, &state->fn, &state->cgn, &state->d, &state->stp, state->curstpmax, minbc_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state);
69300 0 : goto lbl_61;
69301 0 : lbl_62:
69302 0 : smoothnessmonitorfinalizelinesearch(&state->smonitor, _state);
69303 0 : for(i=0; i<=n-1; i++)
69304 : {
69305 0 : if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less_eq(state->xn.ptr.p_double[i],state->bndl.ptr.p_double[i]) )
69306 : {
69307 0 : state->xn.ptr.p_double[i] = state->bndl.ptr.p_double[i];
69308 : }
69309 0 : if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater_eq(state->xn.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
69310 : {
69311 0 : state->xn.ptr.p_double[i] = state->bndu.ptr.p_double[i];
69312 : }
69313 : }
69314 0 : ae_v_moveneg(&state->bufsk.ptr.pp_double[state->bufsize][0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
69315 0 : ae_v_moveneg(&state->bufyk.ptr.pp_double[state->bufsize][0], 1, &state->cgc.ptr.p_double[0], 1, ae_v_len(0,n-1));
69316 0 : ae_v_add(&state->bufsk.ptr.pp_double[state->bufsize][0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1));
69317 0 : ae_v_add(&state->bufyk.ptr.pp_double[state->bufsize][0], 1, &state->cgn.ptr.p_double[0], 1, ae_v_len(0,n-1));
69318 :
69319 : /*
69320 : * Handle special situations:
69321 : * * check for presence of NAN/INF in function/gradient
69322 : * * handle failure of line search
69323 : */
69324 0 : v = state->fn;
69325 0 : for(i=0; i<=n-1; i++)
69326 : {
69327 0 : v = 0.1*v+state->ugn.ptr.p_double[i];
69328 : }
69329 0 : if( !ae_isfinite(v, _state) )
69330 : {
69331 :
69332 : /*
69333 : * Abnormal termination - infinities in function/gradient
69334 : */
69335 0 : state->repterminationtype = -8;
69336 0 : result = ae_false;
69337 0 : return result;
69338 : }
69339 0 : if( state->userterminationneeded )
69340 : {
69341 :
69342 : /*
69343 : * User requested termination
69344 : */
69345 0 : state->repterminationtype = 8;
69346 0 : result = ae_false;
69347 0 : return result;
69348 : }
69349 0 : if( mcinfo!=1 )
69350 : {
69351 :
69352 : /*
69353 : * Terminate LBFGS phase
69354 : */
69355 0 : goto lbl_60;
69356 : }
69357 :
69358 : /*
69359 : * Current point is updated:
69360 : * * move XC/FC/GC to XP/FP/GP
69361 : * * move XN/FN/GN to XC/FC/GC
69362 : * * report current point and update iterations counter
69363 : * * push new pair SK/YK to LBFGS buffer
69364 : * * update length of the good step
69365 : */
69366 0 : activationstatus = ae_false;
69367 0 : for(i=0; i<=n-1; i++)
69368 : {
69369 0 : if( (state->hasbndl.ptr.p_bool[i]&&ae_fp_eq(state->xn.ptr.p_double[i],state->bndl.ptr.p_double[i]))&&ae_fp_neq(state->xn.ptr.p_double[i],state->xc.ptr.p_double[i]) )
69370 : {
69371 0 : activationstatus = ae_true;
69372 : }
69373 0 : if( (state->hasbndu.ptr.p_bool[i]&&ae_fp_eq(state->xn.ptr.p_double[i],state->bndu.ptr.p_double[i]))&&ae_fp_neq(state->xn.ptr.p_double[i],state->xc.ptr.p_double[i]) )
69374 : {
69375 0 : activationstatus = ae_true;
69376 : }
69377 : }
69378 0 : state->fp = state->fc;
69379 0 : state->fc = state->fn;
69380 0 : ae_v_move(&state->xp.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
69381 0 : ae_v_move(&state->xc.ptr.p_double[0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1));
69382 0 : ae_v_move(&state->cgc.ptr.p_double[0], 1, &state->cgn.ptr.p_double[0], 1, ae_v_len(0,n-1));
69383 0 : ae_v_move(&state->ugc.ptr.p_double[0], 1, &state->ugn.ptr.p_double[0], 1, ae_v_len(0,n-1));
69384 0 : if( !state->xrep )
69385 : {
69386 0 : goto lbl_70;
69387 : }
69388 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
69389 0 : minbc_clearrequestfields(state, _state);
69390 0 : state->xupdated = ae_true;
69391 0 : state->rstate.stage = 29;
69392 0 : goto lbl_rcomm;
69393 0 : lbl_29:
69394 0 : state->xupdated = ae_false;
69395 0 : lbl_70:
69396 0 : state->repiterationscount = state->repiterationscount+1;
69397 0 : if( state->bufsize==m )
69398 : {
69399 :
69400 : /*
69401 : * Buffer is full, shift contents by one row
69402 : */
69403 0 : for(i=0; i<=state->bufsize-1; i++)
69404 : {
69405 0 : ae_v_move(&state->bufsk.ptr.pp_double[i][0], 1, &state->bufsk.ptr.pp_double[i+1][0], 1, ae_v_len(0,n-1));
69406 0 : ae_v_move(&state->bufyk.ptr.pp_double[i][0], 1, &state->bufyk.ptr.pp_double[i+1][0], 1, ae_v_len(0,n-1));
69407 : }
69408 0 : for(i=0; i<=state->bufsize-2; i++)
69409 : {
69410 0 : state->bufrho.ptr.p_double[i] = state->bufrho.ptr.p_double[i+1];
69411 0 : state->buftheta.ptr.p_double[i] = state->buftheta.ptr.p_double[i+1];
69412 : }
69413 : }
69414 : else
69415 : {
69416 :
69417 : /*
69418 : * Buffer is not full, increase buffer size by 1
69419 : */
69420 0 : state->bufsize = state->bufsize+1;
69421 : }
69422 0 : v = ae_v_dotproduct(&state->bufyk.ptr.pp_double[state->bufsize-1][0], 1, &state->bufsk.ptr.pp_double[state->bufsize-1][0], 1, ae_v_len(0,n-1));
69423 0 : vv = ae_v_dotproduct(&state->bufyk.ptr.pp_double[state->bufsize-1][0], 1, &state->bufyk.ptr.pp_double[state->bufsize-1][0], 1, ae_v_len(0,n-1));
69424 0 : if( ae_fp_eq(v,(double)(0))||ae_fp_eq(vv,(double)(0)) )
69425 : {
69426 :
69427 : /*
69428 : * Strange internal error in LBFGS - either YK=0
69429 : * (which should not have been) or (SK,YK)=0 (again,
69430 : * unexpected). It should not take place because
69431 : * MCINFO=1, which signals "good" step. But just
69432 : * to be sure we have special branch of code which
69433 : * restarts LBFGS
69434 : */
69435 0 : goto lbl_60;
69436 : }
69437 0 : state->bufrho.ptr.p_double[state->bufsize-1] = 1/v;
69438 0 : ae_assert(state->bufsize<=m, "MinBC: internal error", _state);
69439 0 : v = (double)(0);
69440 0 : vv = (double)(0);
69441 0 : for(i=0; i<=n-1; i++)
69442 : {
69443 0 : v = v+ae_sqr((state->xc.ptr.p_double[i]-state->xp.ptr.p_double[i])/state->s.ptr.p_double[i], _state);
69444 0 : vv = vv+ae_sqr(state->xc.ptr.p_double[i]-state->xp.ptr.p_double[i], _state);
69445 : }
69446 0 : minbc_updateestimateofgoodstep(&state->lastscaledgoodstep, ae_sqrt(v, _state), _state);
69447 :
69448 : /*
69449 : * Check MaxIts-based stopping condition.
69450 : */
69451 0 : if( state->maxits>0&&state->repiterationscount>=state->maxits )
69452 : {
69453 0 : state->repterminationtype = 5;
69454 0 : result = ae_false;
69455 0 : return result;
69456 : }
69457 :
69458 : /*
69459 : * Smooth reset (LBFGS memory model is refreshed) or hard restart:
69460 : * * LBFGS model is refreshed, if line search was performed with activation of constraints
69461 : * * algorithm is restarted if scaled gradient decreased below GDecay
69462 : */
69463 0 : if( activationstatus )
69464 : {
69465 0 : state->bufsize = 0;
69466 0 : goto lbl_59;
69467 : }
69468 0 : v = 0.0;
69469 0 : for(i=0; i<=n-1; i++)
69470 : {
69471 0 : v = v+ae_sqr(state->cgc.ptr.p_double[i]*state->s.ptr.p_double[i], _state);
69472 : }
69473 0 : if( ae_fp_less(ae_sqrt(v, _state),gdecay*ginit) )
69474 : {
69475 0 : goto lbl_60;
69476 : }
69477 0 : lbl_59:
69478 0 : itidx = itidx+1;
69479 0 : goto lbl_58;
69480 0 : lbl_60:
69481 :
69482 : /*
69483 : * Decrease decay coefficient. Subsequent L-BFGS stages will
69484 : * have more stringent stopping criteria.
69485 : */
69486 0 : gdecay = ae_maxreal(gdecay*minbc_decaycorrection, minbc_mindecay, _state);
69487 0 : goto lbl_38;
69488 : lbl_39:
69489 : result = ae_false;
69490 : return result;
69491 :
69492 : /*
69493 : * Saving state
69494 : */
69495 0 : lbl_rcomm:
69496 0 : result = ae_true;
69497 0 : state->rstate.ia.ptr.p_int[0] = freezeidx;
69498 0 : state->rstate.ia.ptr.p_int[1] = n;
69499 0 : state->rstate.ia.ptr.p_int[2] = m;
69500 0 : state->rstate.ia.ptr.p_int[3] = i;
69501 0 : state->rstate.ia.ptr.p_int[4] = j;
69502 0 : state->rstate.ia.ptr.p_int[5] = mcinfo;
69503 0 : state->rstate.ia.ptr.p_int[6] = itidx;
69504 0 : state->rstate.ba.ptr.p_bool[0] = b;
69505 0 : state->rstate.ba.ptr.p_bool[1] = activationstatus;
69506 0 : state->rstate.ra.ptr.p_double[0] = freezeval;
69507 0 : state->rstate.ra.ptr.p_double[1] = scaleddnorm;
69508 0 : state->rstate.ra.ptr.p_double[2] = v;
69509 0 : state->rstate.ra.ptr.p_double[3] = vv;
69510 0 : state->rstate.ra.ptr.p_double[4] = v0;
69511 0 : state->rstate.ra.ptr.p_double[5] = ginit;
69512 0 : state->rstate.ra.ptr.p_double[6] = gdecay;
69513 0 : state->rstate.ra.ptr.p_double[7] = activationstep;
69514 0 : return result;
69515 : }
69516 :
69517 :
69518 : /*************************************************************************
69519 : This function activates/deactivates verification of the user-supplied
69520 : analytic gradient.
69521 :
69522 : Upon activation of this option OptGuard integrity checker performs
69523 : numerical differentiation of your target function at the initial point
69524 : (note: future versions may also perform check at the final point) and
69525 : compares numerical gradient with analytic one provided by you.
69526 :
69527 : If difference is too large, an error flag is set and optimization session
69528 : continues. After optimization session is over, you can retrieve the report
69529 : which stores both gradients and specific components highlighted as
69530 : suspicious by the OptGuard.
69531 :
69532 : The primary OptGuard report can be retrieved with minbcoptguardresults().
69533 :
69534 : IMPORTANT: gradient check is a high-overhead option which will cost you
69535 : about 3*N additional function evaluations. In many cases it may
69536 : cost as much as the rest of the optimization session.
69537 :
69538 : YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO
69539 : CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY.
69540 :
69541 : NOTE: unlike previous incarnation of the gradient checking code, OptGuard
69542 : does NOT interrupt optimization even if it discovers bad gradient.
69543 :
69544 : INPUT PARAMETERS:
69545 : State - structure used to store algorithm state
69546 : TestStep - verification step used for numerical differentiation:
69547 : * TestStep=0 turns verification off
69548 : * TestStep>0 activates verification
69549 : You should carefully choose TestStep. Value which is
69550 : too large (so large that function behavior is non-
69551 : cubic at this scale) will lead to false alarms. Too
69552 : short step will result in rounding errors dominating
69553 : numerical derivative.
69554 :
69555 : You may use different step for different parameters by
69556 : means of setting scale with minbcsetscale().
69557 :
69558 : === EXPLANATION ==========================================================
69559 :
69560 : In order to verify gradient algorithm performs following steps:
69561 : * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i],
69562 : where X[i] is i-th component of the initial point and S[i] is a scale
69563 : of i-th parameter
69564 : * F(X) is evaluated at these trial points
69565 : * we perform one more evaluation in the middle point of the interval
69566 : * we build cubic model using function values and derivatives at trial
69567 : points and we compare its prediction with actual value in the middle
69568 : point
69569 :
69570 : -- ALGLIB --
69571 : Copyright 15.06.2014 by Bochkanov Sergey
69572 : *************************************************************************/
69573 0 : void minbcoptguardgradient(minbcstate* state,
69574 : double teststep,
69575 : ae_state *_state)
69576 : {
69577 :
69578 :
69579 0 : ae_assert(ae_isfinite(teststep, _state), "MinBCOptGuardGradient: TestStep contains NaN or INF", _state);
69580 0 : ae_assert(ae_fp_greater_eq(teststep,(double)(0)), "MinBCOptGuardGradient: invalid argument TestStep(TestStep<0)", _state);
69581 0 : state->teststep = teststep;
69582 0 : }
69583 :
69584 :
69585 : /*************************************************************************
69586 : This function activates/deactivates nonsmoothness monitoring option of
69587 : the OptGuard integrity checker. Smoothness monitor silently observes
69588 : solution process and tries to detect ill-posed problems, i.e. ones with:
69589 : a) discontinuous target function (non-C0)
69590 : b) nonsmooth target function (non-C1)
69591 :
69592 : Smoothness monitoring does NOT interrupt optimization even if it suspects
69593 : that your problem is nonsmooth. It just sets corresponding flags in the
69594 : OptGuard report which can be retrieved after optimization is over.
69595 :
69596 : Smoothness monitoring is a moderate overhead option which often adds less
69597 : than 1% to the optimizer running time. Thus, you can use it even for large
69598 : scale problems.
69599 :
69600 : NOTE: OptGuard does NOT guarantee that it will always detect C0/C1
69601 : continuity violations.
69602 :
69603 : First, minor errors are hard to catch - say, a 0.0001 difference in
69604 : the model values at two sides of the gap may be due to discontinuity
69605 : of the model - or simply because the model has changed.
69606 :
69607 : Second, C1-violations are especially difficult to detect in a
69608 : noninvasive way. The optimizer usually performs very short steps
69609 : near the nonsmoothness, and differentiation usually introduces a
69610 : lot of numerical noise. It is hard to tell whether some tiny
69611 : discontinuity in the slope is due to real nonsmoothness or just due
69612 : to numerical noise alone.
69613 :
69614 : Our top priority was to avoid false positives, so in some rare cases
69615 : minor errors may went unnoticed (however, in most cases they can be
69616 : spotted with restart from different initial point).
69617 :
69618 : INPUT PARAMETERS:
69619 : state - algorithm state
69620 : level - monitoring level:
69621 : * 0 - monitoring is disabled
69622 : * 1 - noninvasive low-overhead monitoring; function values
69623 : and/or gradients are recorded, but OptGuard does not
69624 : try to perform additional evaluations in order to
69625 : get more information about suspicious locations.
69626 :
69627 : === EXPLANATION ==========================================================
69628 :
69629 : One major source of headache during optimization is the possibility of
69630 : the coding errors in the target function/constraints (or their gradients).
69631 : Such errors most often manifest themselves as discontinuity or
69632 : nonsmoothness of the target/constraints.
69633 :
69634 : Another frequent situation is when you try to optimize something involving
69635 : lots of min() and max() operations, i.e. nonsmooth target. Although not a
69636 : coding error, it is nonsmoothness anyway - and smooth optimizers usually
69637 : stop right after encountering nonsmoothness, well before reaching solution.
69638 :
69639 : OptGuard integrity checker helps you to catch such situations: it monitors
69640 : function values/gradients being passed to the optimizer and tries to
69641 : errors. Upon discovering suspicious pair of points it raises appropriate
69642 : flag (and allows you to continue optimization). When optimization is done,
69643 : you can study OptGuard result.
69644 :
69645 : -- ALGLIB --
69646 : Copyright 21.11.2018 by Bochkanov Sergey
69647 : *************************************************************************/
69648 0 : void minbcoptguardsmoothness(minbcstate* state,
69649 : ae_int_t level,
69650 : ae_state *_state)
69651 : {
69652 :
69653 :
69654 0 : ae_assert(level==0||level==1, "MinBCOptGuardSmoothness: unexpected value of level parameter", _state);
69655 0 : state->smoothnessguardlevel = level;
69656 0 : }
69657 :
69658 :
69659 : /*************************************************************************
69660 : Results of OptGuard integrity check, should be called after optimization
69661 : session is over.
69662 :
69663 : === PRIMARY REPORT =======================================================
69664 :
69665 : OptGuard performs several checks which are intended to catch common errors
69666 : in the implementation of nonlinear function/gradient:
69667 : * incorrect analytic gradient
69668 : * discontinuous (non-C0) target functions (constraints)
69669 : * nonsmooth (non-C1) target functions (constraints)
69670 :
69671 : Each of these checks is activated with appropriate function:
69672 : * minbcoptguardgradient() for gradient verification
69673 : * minbcoptguardsmoothness() for C0/C1 checks
69674 :
69675 : Following flags are set when these errors are suspected:
69676 : * rep.badgradsuspected, and additionally:
69677 : * rep.badgradvidx for specific variable (gradient element) suspected
69678 : * rep.badgradxbase, a point where gradient is tested
69679 : * rep.badgraduser, user-provided gradient (stored as 2D matrix with
69680 : single row in order to make report structure compatible with more
69681 : complex optimizers like MinNLC or MinLM)
69682 : * rep.badgradnum, reference gradient obtained via numerical
69683 : differentiation (stored as 2D matrix with single row in order to make
69684 : report structure compatible with more complex optimizers like MinNLC
69685 : or MinLM)
69686 : * rep.nonc0suspected
69687 : * rep.nonc1suspected
69688 :
69689 : === ADDITIONAL REPORTS/LOGS ==============================================
69690 :
69691 : Several different tests are performed to catch C0/C1 errors, you can find
69692 : out specific test signaled error by looking to:
69693 : * rep.nonc0test0positive, for non-C0 test #0
69694 : * rep.nonc1test0positive, for non-C1 test #0
69695 : * rep.nonc1test1positive, for non-C1 test #1
69696 :
69697 : Additional information (including line search logs) can be obtained by
69698 : means of:
69699 : * minbcoptguardnonc1test0results()
69700 : * minbcoptguardnonc1test1results()
69701 : which return detailed error reports, specific points where discontinuities
69702 : were found, and so on.
69703 :
69704 : ==========================================================================
69705 :
69706 : INPUT PARAMETERS:
69707 : state - algorithm state
69708 :
69709 : OUTPUT PARAMETERS:
69710 : rep - generic OptGuard report; more detailed reports can be
69711 : retrieved with other functions.
69712 :
69713 : NOTE: false negatives (nonsmooth problems are not identified as nonsmooth
69714 : ones) are possible although unlikely.
69715 :
69716 : The reason is that you need to make several evaluations around
69717 : nonsmoothness in order to accumulate enough information about
69718 : function curvature. Say, if you start right from the nonsmooth point,
69719 : optimizer simply won't get enough data to understand what is going
69720 : wrong before it terminates due to abrupt changes in the derivative.
69721 : It is also possible that "unlucky" step will move us to the
69722 : termination too quickly.
69723 :
69724 : Our current approach is to have less than 0.1% false negatives in
69725 : our test examples (measured with multiple restarts from random
69726 : points), and to have exactly 0% false positives.
69727 :
69728 : -- ALGLIB --
69729 : Copyright 21.11.2018 by Bochkanov Sergey
69730 : *************************************************************************/
69731 0 : void minbcoptguardresults(minbcstate* state,
69732 : optguardreport* rep,
69733 : ae_state *_state)
69734 : {
69735 :
69736 0 : _optguardreport_clear(rep);
69737 :
69738 0 : smoothnessmonitorexportreport(&state->smonitor, rep, _state);
69739 0 : }
69740 :
69741 :
69742 : /*************************************************************************
69743 : Detailed results of the OptGuard integrity check for nonsmoothness test #0
69744 :
69745 : Nonsmoothness (non-C1) test #0 studies function values (not gradient!)
69746 : obtained during line searches and monitors behavior of the directional
69747 : derivative estimate.
69748 :
69749 : This test is less powerful than test #1, but it does not depend on the
69750 : gradient values and thus it is more robust against artifacts introduced by
69751 : numerical differentiation.
69752 :
69753 : Two reports are returned:
69754 : * a "strongest" one, corresponding to line search which had highest
69755 : value of the nonsmoothness indicator
69756 : * a "longest" one, corresponding to line search which had more function
69757 : evaluations, and thus is more detailed
69758 :
69759 : In both cases following fields are returned:
69760 :
69761 : * positive - is TRUE when test flagged suspicious point; FALSE if test
69762 : did not notice anything (in the latter cases fields below are empty).
69763 : * x0[], d[] - arrays of length N which store initial point and direction
69764 : for line search (d[] can be normalized, but does not have to)
69765 : * stp[], f[] - arrays of length CNT which store step lengths and function
69766 : values at these points; f[i] is evaluated in x0+stp[i]*d.
69767 : * stpidxa, stpidxb - we suspect that function violates C1 continuity
69768 : between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3,
69769 : with most likely position of the violation between stpidxa+1 and
69770 : stpidxa+2.
69771 :
69772 : ==========================================================================
69773 : = SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will
69774 : = see where C1 continuity is violated.
69775 : ==========================================================================
69776 :
69777 : INPUT PARAMETERS:
69778 : state - algorithm state
69779 :
69780 : OUTPUT PARAMETERS:
69781 : strrep - C1 test #0 "strong" report
69782 : lngrep - C1 test #0 "long" report
69783 :
69784 : -- ALGLIB --
69785 : Copyright 21.11.2018 by Bochkanov Sergey
69786 : *************************************************************************/
69787 0 : void minbcoptguardnonc1test0results(minbcstate* state,
69788 : optguardnonc1test0report* strrep,
69789 : optguardnonc1test0report* lngrep,
69790 : ae_state *_state)
69791 : {
69792 :
69793 0 : _optguardnonc1test0report_clear(strrep);
69794 0 : _optguardnonc1test0report_clear(lngrep);
69795 :
69796 0 : smoothnessmonitorexportc1test0report(&state->smonitor.nonc1test0strrep, &state->lastscaleused, strrep, _state);
69797 0 : smoothnessmonitorexportc1test0report(&state->smonitor.nonc1test0lngrep, &state->lastscaleused, lngrep, _state);
69798 0 : }
69799 :
69800 :
69801 : /*************************************************************************
69802 : Detailed results of the OptGuard integrity check for nonsmoothness test #1
69803 :
69804 : Nonsmoothness (non-C1) test #1 studies individual components of the
69805 : gradient computed during line search.
69806 :
69807 : When precise analytic gradient is provided this test is more powerful than
69808 : test #0 which works with function values and ignores user-provided
69809 : gradient. However, test #0 becomes more powerful when numerical
69810 : differentiation is employed (in such cases test #1 detects higher levels
69811 : of numerical noise and becomes too conservative).
69812 :
69813 : This test also tells specific components of the gradient which violate C1
69814 : continuity, which makes it more informative than #0, which just tells that
69815 : continuity is violated.
69816 :
69817 : Two reports are returned:
69818 : * a "strongest" one, corresponding to line search which had highest
69819 : value of the nonsmoothness indicator
69820 : * a "longest" one, corresponding to line search which had more function
69821 : evaluations, and thus is more detailed
69822 :
69823 : In both cases following fields are returned:
69824 :
69825 : * positive - is TRUE when test flagged suspicious point; FALSE if test
69826 : did not notice anything (in the latter cases fields below are empty).
69827 : * vidx - is an index of the variable in [0,N) with nonsmooth derivative
69828 : * x0[], d[] - arrays of length N which store initial point and direction
69829 : for line search (d[] can be normalized, but does not have to)
69830 : * stp[], g[] - arrays of length CNT which store step lengths and gradient
69831 : values at these points; g[i] is evaluated in x0+stp[i]*d and contains
69832 : vidx-th component of the gradient.
69833 : * stpidxa, stpidxb - we suspect that function violates C1 continuity
69834 : between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3,
69835 : with most likely position of the violation between stpidxa+1 and
69836 : stpidxa+2.
69837 :
69838 : ==========================================================================
69839 : = SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will
69840 : = see where C1 continuity is violated.
69841 : ==========================================================================
69842 :
69843 : INPUT PARAMETERS:
69844 : state - algorithm state
69845 :
69846 : OUTPUT PARAMETERS:
69847 : strrep - C1 test #1 "strong" report
69848 : lngrep - C1 test #1 "long" report
69849 :
69850 : -- ALGLIB --
69851 : Copyright 21.11.2018 by Bochkanov Sergey
69852 : *************************************************************************/
69853 0 : void minbcoptguardnonc1test1results(minbcstate* state,
69854 : optguardnonc1test1report* strrep,
69855 : optguardnonc1test1report* lngrep,
69856 : ae_state *_state)
69857 : {
69858 :
69859 0 : _optguardnonc1test1report_clear(strrep);
69860 0 : _optguardnonc1test1report_clear(lngrep);
69861 :
69862 0 : smoothnessmonitorexportc1test1report(&state->smonitor.nonc1test1strrep, &state->lastscaleused, strrep, _state);
69863 0 : smoothnessmonitorexportc1test1report(&state->smonitor.nonc1test1lngrep, &state->lastscaleused, lngrep, _state);
69864 0 : }
69865 :
69866 :
69867 : /*************************************************************************
69868 : BC results
69869 :
69870 : INPUT PARAMETERS:
69871 : State - algorithm state
69872 :
69873 : OUTPUT PARAMETERS:
69874 : X - array[0..N-1], solution
69875 : Rep - optimization report. You should check Rep.TerminationType
69876 : in order to distinguish successful termination from
69877 : unsuccessful one:
69878 : * -8 internal integrity control detected infinite or
69879 : NAN values in function/gradient. Abnormal
69880 : termination signalled.
69881 : * -3 inconsistent constraints.
69882 : * 1 relative function improvement is no more than EpsF.
69883 : * 2 scaled step is no more than EpsX.
69884 : * 4 scaled gradient norm is no more than EpsG.
69885 : * 5 MaxIts steps was taken
69886 : * 8 terminated by user who called minbcrequesttermination().
69887 : X contains point which was "current accepted" when
69888 : termination request was submitted.
69889 : More information about fields of this structure can be
69890 : found in the comments on MinBCReport datatype.
69891 :
69892 : -- ALGLIB --
69893 : Copyright 28.11.2010 by Bochkanov Sergey
69894 : *************************************************************************/
69895 0 : void minbcresults(minbcstate* state,
69896 : /* Real */ ae_vector* x,
69897 : minbcreport* rep,
69898 : ae_state *_state)
69899 : {
69900 :
69901 0 : ae_vector_clear(x);
69902 0 : _minbcreport_clear(rep);
69903 :
69904 0 : minbcresultsbuf(state, x, rep, _state);
69905 0 : }
69906 :
69907 :
69908 : /*************************************************************************
69909 : BC results
69910 :
69911 : Buffered implementation of MinBCResults() which uses pre-allocated buffer
69912 : to store X[]. If buffer size is too small, it resizes buffer. It is
69913 : intended to be used in the inner cycles of performance critical algorithms
69914 : where array reallocation penalty is too large to be ignored.
69915 :
69916 : -- ALGLIB --
69917 : Copyright 28.11.2010 by Bochkanov Sergey
69918 : *************************************************************************/
69919 0 : void minbcresultsbuf(minbcstate* state,
69920 : /* Real */ ae_vector* x,
69921 : minbcreport* rep,
69922 : ae_state *_state)
69923 : {
69924 : ae_int_t i;
69925 :
69926 :
69927 0 : if( x->cnt<state->nmain )
69928 : {
69929 0 : ae_vector_set_length(x, state->nmain, _state);
69930 : }
69931 0 : rep->iterationscount = state->repiterationscount;
69932 0 : rep->nfev = state->repnfev;
69933 0 : rep->varidx = state->repvaridx;
69934 0 : rep->terminationtype = state->repterminationtype;
69935 0 : if( state->repterminationtype>0 )
69936 : {
69937 0 : ae_v_move(&x->ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,state->nmain-1));
69938 : }
69939 : else
69940 : {
69941 0 : for(i=0; i<=state->nmain-1; i++)
69942 : {
69943 0 : x->ptr.p_double[i] = _state->v_nan;
69944 : }
69945 : }
69946 0 : }
69947 :
69948 :
69949 : /*************************************************************************
69950 : This subroutine restarts algorithm from new point.
69951 : All optimization parameters (including constraints) are left unchanged.
69952 :
69953 : This function allows to solve multiple optimization problems (which
69954 : must have same number of dimensions) without object reallocation penalty.
69955 :
69956 : INPUT PARAMETERS:
69957 : State - structure previously allocated with MinBCCreate call.
69958 : X - new starting point.
69959 :
69960 : -- ALGLIB --
69961 : Copyright 28.11.2010 by Bochkanov Sergey
69962 : *************************************************************************/
69963 0 : void minbcrestartfrom(minbcstate* state,
69964 : /* Real */ ae_vector* x,
69965 : ae_state *_state)
69966 : {
69967 : ae_int_t n;
69968 :
69969 :
69970 0 : n = state->nmain;
69971 :
69972 : /*
69973 : * First, check for errors in the inputs
69974 : */
69975 0 : ae_assert(x->cnt>=n, "MinBCRestartFrom: Length(X)<N", _state);
69976 0 : ae_assert(isfinitevector(x, n, _state), "MinBCRestartFrom: X contains infinite or NaN values!", _state);
69977 :
69978 : /*
69979 : * Set XC
69980 : */
69981 0 : ae_v_move(&state->xstart.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
69982 :
69983 : /*
69984 : * prepare RComm facilities
69985 : */
69986 0 : ae_vector_set_length(&state->rstate.ia, 6+1, _state);
69987 0 : ae_vector_set_length(&state->rstate.ba, 1+1, _state);
69988 0 : ae_vector_set_length(&state->rstate.ra, 7+1, _state);
69989 0 : state->rstate.stage = -1;
69990 0 : minbc_clearrequestfields(state, _state);
69991 0 : }
69992 :
69993 :
69994 : /*************************************************************************
69995 : This subroutine submits request for termination of running optimizer. It
69996 : should be called from user-supplied callback when user decides that it is
69997 : time to "smoothly" terminate optimization process. As result, optimizer
69998 : stops at point which was "current accepted" when termination request was
69999 : submitted and returns error code 8 (successful termination).
70000 :
70001 : INPUT PARAMETERS:
70002 : State - optimizer structure
70003 :
70004 : NOTE: after request for termination optimizer may perform several
70005 : additional calls to user-supplied callbacks. It does NOT guarantee
70006 : to stop immediately - it just guarantees that these additional calls
70007 : will be discarded later.
70008 :
70009 : NOTE: calling this function on optimizer which is NOT running will have no
70010 : effect.
70011 :
70012 : NOTE: multiple calls to this function are possible. First call is counted,
70013 : subsequent calls are silently ignored.
70014 :
70015 : -- ALGLIB --
70016 : Copyright 08.10.2014 by Bochkanov Sergey
70017 : *************************************************************************/
70018 0 : void minbcrequesttermination(minbcstate* state, ae_state *_state)
70019 : {
70020 :
70021 :
70022 0 : state->userterminationneeded = ae_true;
70023 0 : }
70024 :
70025 :
70026 : /*************************************************************************
70027 : Clears request fileds (to be sure that we don't forget to clear something)
70028 : *************************************************************************/
70029 0 : static void minbc_clearrequestfields(minbcstate* state, ae_state *_state)
70030 : {
70031 :
70032 :
70033 0 : state->needf = ae_false;
70034 0 : state->needfg = ae_false;
70035 0 : state->xupdated = ae_false;
70036 0 : }
70037 :
70038 :
70039 : /*************************************************************************
70040 : Internal initialization subroutine.
70041 : *************************************************************************/
70042 0 : static void minbc_minbcinitinternal(ae_int_t n,
70043 : /* Real */ ae_vector* x,
70044 : double diffstep,
70045 : minbcstate* state,
70046 : ae_state *_state)
70047 : {
70048 : ae_frame _frame_block;
70049 : ae_int_t i;
70050 : ae_matrix c;
70051 : ae_vector ct;
70052 :
70053 0 : ae_frame_make(_state, &_frame_block);
70054 0 : memset(&c, 0, sizeof(c));
70055 0 : memset(&ct, 0, sizeof(ct));
70056 0 : ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
70057 0 : ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
70058 :
70059 :
70060 : /*
70061 : * Initialize
70062 : */
70063 0 : state->teststep = (double)(0);
70064 0 : state->smoothnessguardlevel = 0;
70065 0 : smoothnessmonitorinit(&state->smonitor, &state->s, 0, 0, ae_false, _state);
70066 0 : state->nmain = n;
70067 0 : state->diffstep = diffstep;
70068 0 : rvectorsetlengthatleast(&state->bndl, n, _state);
70069 0 : bvectorsetlengthatleast(&state->hasbndl, n, _state);
70070 0 : rvectorsetlengthatleast(&state->bndu, n, _state);
70071 0 : bvectorsetlengthatleast(&state->hasbndu, n, _state);
70072 0 : rvectorsetlengthatleast(&state->xstart, n, _state);
70073 0 : rvectorsetlengthatleast(&state->xc, n, _state);
70074 0 : rvectorsetlengthatleast(&state->cgc, n, _state);
70075 0 : rvectorsetlengthatleast(&state->ugc, n, _state);
70076 0 : rvectorsetlengthatleast(&state->xn, n, _state);
70077 0 : rvectorsetlengthatleast(&state->cgn, n, _state);
70078 0 : rvectorsetlengthatleast(&state->ugn, n, _state);
70079 0 : rvectorsetlengthatleast(&state->xp, n, _state);
70080 0 : rvectorsetlengthatleast(&state->d, n, _state);
70081 0 : rvectorsetlengthatleast(&state->s, n, _state);
70082 0 : rvectorsetlengthatleast(&state->invs, n, _state);
70083 0 : rvectorsetlengthatleast(&state->lastscaleused, n, _state);
70084 0 : rvectorsetlengthatleast(&state->x, n, _state);
70085 0 : rvectorsetlengthatleast(&state->g, n, _state);
70086 0 : rvectorsetlengthatleast(&state->work, n, _state);
70087 0 : for(i=0; i<=n-1; i++)
70088 : {
70089 0 : state->bndl.ptr.p_double[i] = _state->v_neginf;
70090 0 : state->hasbndl.ptr.p_bool[i] = ae_false;
70091 0 : state->bndu.ptr.p_double[i] = _state->v_posinf;
70092 0 : state->hasbndu.ptr.p_bool[i] = ae_false;
70093 0 : state->s.ptr.p_double[i] = 1.0;
70094 0 : state->invs.ptr.p_double[i] = 1.0;
70095 0 : state->lastscaleused.ptr.p_double[i] = 1.0;
70096 : }
70097 0 : minbcsetcond(state, 0.0, 0.0, 0.0, 0, _state);
70098 0 : minbcsetxrep(state, ae_false, _state);
70099 0 : minbcsetstpmax(state, 0.0, _state);
70100 0 : minbcsetprecdefault(state, _state);
70101 0 : minbcrestartfrom(state, x, _state);
70102 0 : ae_frame_leave(_state);
70103 0 : }
70104 :
70105 :
70106 : /*************************************************************************
70107 : This subroutine updates estimate of the good step length given:
70108 : 1) previous estimate
70109 : 2) new length of the good step
70110 :
70111 : It makes sure that estimate does not change too rapidly - ratio of new and
70112 : old estimates will be at least 0.01, at most 100.0
70113 :
70114 : In case previous estimate of good step is zero (no estimate), new estimate
70115 : is used unconditionally.
70116 :
70117 : -- ALGLIB --
70118 : Copyright 16.01.2013 by Bochkanov Sergey
70119 : *************************************************************************/
70120 0 : static void minbc_updateestimateofgoodstep(double* estimate,
70121 : double newstep,
70122 : ae_state *_state)
70123 : {
70124 :
70125 :
70126 0 : if( ae_fp_eq(*estimate,(double)(0)) )
70127 : {
70128 0 : *estimate = newstep;
70129 0 : return;
70130 : }
70131 0 : if( ae_fp_less(newstep,*estimate*0.01) )
70132 : {
70133 0 : *estimate = *estimate*0.01;
70134 0 : return;
70135 : }
70136 0 : if( ae_fp_greater(newstep,*estimate*100) )
70137 : {
70138 0 : *estimate = *estimate*100;
70139 0 : return;
70140 : }
70141 0 : *estimate = newstep;
70142 : }
70143 :
70144 :
70145 0 : void _minbcstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
70146 : {
70147 0 : minbcstate *p = (minbcstate*)_p;
70148 0 : ae_touch_ptr((void*)p);
70149 0 : ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic);
70150 0 : ae_vector_init(&p->diagh, 0, DT_REAL, _state, make_automatic);
70151 0 : ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
70152 0 : ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic);
70153 0 : _rcommstate_init(&p->rstate, _state, make_automatic);
70154 0 : ae_vector_init(&p->xc, 0, DT_REAL, _state, make_automatic);
70155 0 : ae_vector_init(&p->ugc, 0, DT_REAL, _state, make_automatic);
70156 0 : ae_vector_init(&p->cgc, 0, DT_REAL, _state, make_automatic);
70157 0 : ae_vector_init(&p->xn, 0, DT_REAL, _state, make_automatic);
70158 0 : ae_vector_init(&p->ugn, 0, DT_REAL, _state, make_automatic);
70159 0 : ae_vector_init(&p->cgn, 0, DT_REAL, _state, make_automatic);
70160 0 : ae_vector_init(&p->xp, 0, DT_REAL, _state, make_automatic);
70161 0 : ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic);
70162 0 : ae_vector_init(&p->hasbndl, 0, DT_BOOL, _state, make_automatic);
70163 0 : ae_vector_init(&p->hasbndu, 0, DT_BOOL, _state, make_automatic);
70164 0 : ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic);
70165 0 : ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic);
70166 0 : ae_vector_init(&p->xstart, 0, DT_REAL, _state, make_automatic);
70167 0 : ae_vector_init(&p->tmpprec, 0, DT_REAL, _state, make_automatic);
70168 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
70169 0 : ae_vector_init(&p->work, 0, DT_REAL, _state, make_automatic);
70170 0 : _linminstate_init(&p->lstate, _state, make_automatic);
70171 0 : ae_matrix_init(&p->bufyk, 0, 0, DT_REAL, _state, make_automatic);
70172 0 : ae_matrix_init(&p->bufsk, 0, 0, DT_REAL, _state, make_automatic);
70173 0 : ae_vector_init(&p->bufrho, 0, DT_REAL, _state, make_automatic);
70174 0 : ae_vector_init(&p->buftheta, 0, DT_REAL, _state, make_automatic);
70175 0 : _smoothnessmonitor_init(&p->smonitor, _state, make_automatic);
70176 0 : ae_vector_init(&p->lastscaleused, 0, DT_REAL, _state, make_automatic);
70177 0 : ae_vector_init(&p->invs, 0, DT_REAL, _state, make_automatic);
70178 0 : }
70179 :
70180 :
70181 0 : void _minbcstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
70182 : {
70183 0 : minbcstate *dst = (minbcstate*)_dst;
70184 0 : minbcstate *src = (minbcstate*)_src;
70185 0 : dst->nmain = src->nmain;
70186 0 : dst->epsg = src->epsg;
70187 0 : dst->epsf = src->epsf;
70188 0 : dst->epsx = src->epsx;
70189 0 : dst->maxits = src->maxits;
70190 0 : dst->xrep = src->xrep;
70191 0 : dst->stpmax = src->stpmax;
70192 0 : dst->diffstep = src->diffstep;
70193 0 : ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic);
70194 0 : dst->prectype = src->prectype;
70195 0 : ae_vector_init_copy(&dst->diagh, &src->diagh, _state, make_automatic);
70196 0 : ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
70197 0 : dst->f = src->f;
70198 0 : ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic);
70199 0 : dst->needf = src->needf;
70200 0 : dst->needfg = src->needfg;
70201 0 : dst->xupdated = src->xupdated;
70202 0 : dst->userterminationneeded = src->userterminationneeded;
70203 0 : _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic);
70204 0 : ae_vector_init_copy(&dst->xc, &src->xc, _state, make_automatic);
70205 0 : ae_vector_init_copy(&dst->ugc, &src->ugc, _state, make_automatic);
70206 0 : ae_vector_init_copy(&dst->cgc, &src->cgc, _state, make_automatic);
70207 0 : ae_vector_init_copy(&dst->xn, &src->xn, _state, make_automatic);
70208 0 : ae_vector_init_copy(&dst->ugn, &src->ugn, _state, make_automatic);
70209 0 : ae_vector_init_copy(&dst->cgn, &src->cgn, _state, make_automatic);
70210 0 : ae_vector_init_copy(&dst->xp, &src->xp, _state, make_automatic);
70211 0 : dst->fc = src->fc;
70212 0 : dst->fn = src->fn;
70213 0 : dst->fp = src->fp;
70214 0 : ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic);
70215 0 : dst->lastscaledgoodstep = src->lastscaledgoodstep;
70216 0 : ae_vector_init_copy(&dst->hasbndl, &src->hasbndl, _state, make_automatic);
70217 0 : ae_vector_init_copy(&dst->hasbndu, &src->hasbndu, _state, make_automatic);
70218 0 : ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic);
70219 0 : ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic);
70220 0 : dst->repiterationscount = src->repiterationscount;
70221 0 : dst->repnfev = src->repnfev;
70222 0 : dst->repvaridx = src->repvaridx;
70223 0 : dst->repterminationtype = src->repterminationtype;
70224 0 : ae_vector_init_copy(&dst->xstart, &src->xstart, _state, make_automatic);
70225 0 : dst->fbase = src->fbase;
70226 0 : dst->fm2 = src->fm2;
70227 0 : dst->fm1 = src->fm1;
70228 0 : dst->fp1 = src->fp1;
70229 0 : dst->fp2 = src->fp2;
70230 0 : dst->xm1 = src->xm1;
70231 0 : dst->xp1 = src->xp1;
70232 0 : dst->gm1 = src->gm1;
70233 0 : dst->gp1 = src->gp1;
70234 0 : ae_vector_init_copy(&dst->tmpprec, &src->tmpprec, _state, make_automatic);
70235 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
70236 0 : dst->nfev = src->nfev;
70237 0 : dst->mcstage = src->mcstage;
70238 0 : dst->stp = src->stp;
70239 0 : dst->curstpmax = src->curstpmax;
70240 0 : ae_vector_init_copy(&dst->work, &src->work, _state, make_automatic);
70241 0 : _linminstate_init_copy(&dst->lstate, &src->lstate, _state, make_automatic);
70242 0 : dst->trimthreshold = src->trimthreshold;
70243 0 : dst->nonmonotoniccnt = src->nonmonotoniccnt;
70244 0 : ae_matrix_init_copy(&dst->bufyk, &src->bufyk, _state, make_automatic);
70245 0 : ae_matrix_init_copy(&dst->bufsk, &src->bufsk, _state, make_automatic);
70246 0 : ae_vector_init_copy(&dst->bufrho, &src->bufrho, _state, make_automatic);
70247 0 : ae_vector_init_copy(&dst->buftheta, &src->buftheta, _state, make_automatic);
70248 0 : dst->bufsize = src->bufsize;
70249 0 : dst->teststep = src->teststep;
70250 0 : dst->smoothnessguardlevel = src->smoothnessguardlevel;
70251 0 : _smoothnessmonitor_init_copy(&dst->smonitor, &src->smonitor, _state, make_automatic);
70252 0 : ae_vector_init_copy(&dst->lastscaleused, &src->lastscaleused, _state, make_automatic);
70253 0 : ae_vector_init_copy(&dst->invs, &src->invs, _state, make_automatic);
70254 0 : }
70255 :
70256 :
70257 0 : void _minbcstate_clear(void* _p)
70258 : {
70259 0 : minbcstate *p = (minbcstate*)_p;
70260 0 : ae_touch_ptr((void*)p);
70261 0 : ae_vector_clear(&p->s);
70262 0 : ae_vector_clear(&p->diagh);
70263 0 : ae_vector_clear(&p->x);
70264 0 : ae_vector_clear(&p->g);
70265 0 : _rcommstate_clear(&p->rstate);
70266 0 : ae_vector_clear(&p->xc);
70267 0 : ae_vector_clear(&p->ugc);
70268 0 : ae_vector_clear(&p->cgc);
70269 0 : ae_vector_clear(&p->xn);
70270 0 : ae_vector_clear(&p->ugn);
70271 0 : ae_vector_clear(&p->cgn);
70272 0 : ae_vector_clear(&p->xp);
70273 0 : ae_vector_clear(&p->d);
70274 0 : ae_vector_clear(&p->hasbndl);
70275 0 : ae_vector_clear(&p->hasbndu);
70276 0 : ae_vector_clear(&p->bndl);
70277 0 : ae_vector_clear(&p->bndu);
70278 0 : ae_vector_clear(&p->xstart);
70279 0 : ae_vector_clear(&p->tmpprec);
70280 0 : ae_vector_clear(&p->tmp0);
70281 0 : ae_vector_clear(&p->work);
70282 0 : _linminstate_clear(&p->lstate);
70283 0 : ae_matrix_clear(&p->bufyk);
70284 0 : ae_matrix_clear(&p->bufsk);
70285 0 : ae_vector_clear(&p->bufrho);
70286 0 : ae_vector_clear(&p->buftheta);
70287 0 : _smoothnessmonitor_clear(&p->smonitor);
70288 0 : ae_vector_clear(&p->lastscaleused);
70289 0 : ae_vector_clear(&p->invs);
70290 0 : }
70291 :
70292 :
70293 0 : void _minbcstate_destroy(void* _p)
70294 : {
70295 0 : minbcstate *p = (minbcstate*)_p;
70296 0 : ae_touch_ptr((void*)p);
70297 0 : ae_vector_destroy(&p->s);
70298 0 : ae_vector_destroy(&p->diagh);
70299 0 : ae_vector_destroy(&p->x);
70300 0 : ae_vector_destroy(&p->g);
70301 0 : _rcommstate_destroy(&p->rstate);
70302 0 : ae_vector_destroy(&p->xc);
70303 0 : ae_vector_destroy(&p->ugc);
70304 0 : ae_vector_destroy(&p->cgc);
70305 0 : ae_vector_destroy(&p->xn);
70306 0 : ae_vector_destroy(&p->ugn);
70307 0 : ae_vector_destroy(&p->cgn);
70308 0 : ae_vector_destroy(&p->xp);
70309 0 : ae_vector_destroy(&p->d);
70310 0 : ae_vector_destroy(&p->hasbndl);
70311 0 : ae_vector_destroy(&p->hasbndu);
70312 0 : ae_vector_destroy(&p->bndl);
70313 0 : ae_vector_destroy(&p->bndu);
70314 0 : ae_vector_destroy(&p->xstart);
70315 0 : ae_vector_destroy(&p->tmpprec);
70316 0 : ae_vector_destroy(&p->tmp0);
70317 0 : ae_vector_destroy(&p->work);
70318 0 : _linminstate_destroy(&p->lstate);
70319 0 : ae_matrix_destroy(&p->bufyk);
70320 0 : ae_matrix_destroy(&p->bufsk);
70321 0 : ae_vector_destroy(&p->bufrho);
70322 0 : ae_vector_destroy(&p->buftheta);
70323 0 : _smoothnessmonitor_destroy(&p->smonitor);
70324 0 : ae_vector_destroy(&p->lastscaleused);
70325 0 : ae_vector_destroy(&p->invs);
70326 0 : }
70327 :
70328 :
70329 0 : void _minbcreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
70330 : {
70331 0 : minbcreport *p = (minbcreport*)_p;
70332 0 : ae_touch_ptr((void*)p);
70333 0 : }
70334 :
70335 :
70336 0 : void _minbcreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
70337 : {
70338 0 : minbcreport *dst = (minbcreport*)_dst;
70339 0 : minbcreport *src = (minbcreport*)_src;
70340 0 : dst->iterationscount = src->iterationscount;
70341 0 : dst->nfev = src->nfev;
70342 0 : dst->varidx = src->varidx;
70343 0 : dst->terminationtype = src->terminationtype;
70344 0 : }
70345 :
70346 :
70347 0 : void _minbcreport_clear(void* _p)
70348 : {
70349 0 : minbcreport *p = (minbcreport*)_p;
70350 0 : ae_touch_ptr((void*)p);
70351 0 : }
70352 :
70353 :
70354 0 : void _minbcreport_destroy(void* _p)
70355 : {
70356 0 : minbcreport *p = (minbcreport*)_p;
70357 0 : ae_touch_ptr((void*)p);
70358 0 : }
70359 :
70360 :
70361 : #endif
70362 : #if defined(AE_COMPILE_MINNS) || !defined(AE_PARTIAL_BUILD)
70363 :
70364 :
70365 : /*************************************************************************
70366 : NONSMOOTH NONCONVEX OPTIMIZATION
70367 : SUBJECT TO BOX/LINEAR/NONLINEAR-NONSMOOTH CONSTRAINTS
70368 :
70369 : DESCRIPTION:
70370 :
70371 : The subroutine minimizes function F(x) of N arguments subject to any
70372 : combination of:
70373 : * bound constraints
70374 : * linear inequality constraints
70375 : * linear equality constraints
70376 : * nonlinear equality constraints Gi(x)=0
70377 : * nonlinear inequality constraints Hi(x)<=0
70378 :
70379 : IMPORTANT: see MinNSSetAlgoAGS for important information on performance
70380 : restrictions of AGS solver.
70381 :
70382 : REQUIREMENTS:
70383 : * starting point X0 must be feasible or not too far away from the feasible
70384 : set
70385 : * F(), G(), H() are continuous, locally Lipschitz and continuously (but
70386 : not necessarily twice) differentiable in an open dense subset of R^N.
70387 : Functions F(), G() and H() may be nonsmooth and non-convex.
70388 : Informally speaking, it means that functions are composed of large
70389 : differentiable "patches" with nonsmoothness having place only at the
70390 : boundaries between these "patches".
70391 : Most real-life nonsmooth functions satisfy these requirements. Say,
70392 : anything which involves finite number of abs(), min() and max() is very
70393 : likely to pass the test.
70394 : Say, it is possible to optimize anything of the following:
70395 : * f=abs(x0)+2*abs(x1)
70396 : * f=max(x0,x1)
70397 : * f=sin(max(x0,x1)+abs(x2))
70398 : * for nonlinearly constrained problems: F() must be bounded from below
70399 : without nonlinear constraints (this requirement is due to the fact that,
70400 : contrary to box and linear constraints, nonlinear ones require special
70401 : handling).
70402 : * user must provide function value and gradient for F(), H(), G() at all
70403 : points where function/gradient can be calculated. If optimizer requires
70404 : value exactly at the boundary between "patches" (say, at x=0 for f=abs(x)),
70405 : where gradient is not defined, user may resolve tie arbitrarily (in our
70406 : case - return +1 or -1 at its discretion).
70407 : * NS solver supports numerical differentiation, i.e. it may differentiate
70408 : your function for you, but it results in 2N increase of function
70409 : evaluations. Not recommended unless you solve really small problems. See
70410 : minnscreatef() for more information on this functionality.
70411 :
70412 : USAGE:
70413 :
70414 : 1. User initializes algorithm state with MinNSCreate() call and chooses
70415 : what NLC solver to use. There is some solver which is used by default,
70416 : with default settings, but you should NOT rely on default choice. It
70417 : may change in future releases of ALGLIB without notice, and no one can
70418 : guarantee that new solver will be able to solve your problem with
70419 : default settings.
70420 :
70421 : From the other side, if you choose solver explicitly, you can be pretty
70422 : sure that it will work with new ALGLIB releases.
70423 :
70424 : In the current release following solvers can be used:
70425 : * AGS solver (activated with MinNSSetAlgoAGS() function)
70426 :
70427 : 2. User adds boundary and/or linear and/or nonlinear constraints by means
70428 : of calling one of the following functions:
70429 : a) MinNSSetBC() for boundary constraints
70430 : b) MinNSSetLC() for linear constraints
70431 : c) MinNSSetNLC() for nonlinear constraints
70432 : You may combine (a), (b) and (c) in one optimization problem.
70433 :
70434 : 3. User sets scale of the variables with MinNSSetScale() function. It is
70435 : VERY important to set scale of the variables, because nonlinearly
70436 : constrained problems are hard to solve when variables are badly scaled.
70437 :
70438 : 4. User sets stopping conditions with MinNSSetCond().
70439 :
70440 : 5. Finally, user calls MinNSOptimize() function which takes algorithm
70441 : state and pointer (delegate, etc) to callback function which calculates
70442 : F/G/H.
70443 :
70444 : 7. User calls MinNSResults() to get solution
70445 :
70446 : 8. Optionally user may call MinNSRestartFrom() to solve another problem
70447 : with same N but another starting point. MinNSRestartFrom() allows to
70448 : reuse already initialized structure.
70449 :
70450 :
70451 : INPUT PARAMETERS:
70452 : N - problem dimension, N>0:
70453 : * if given, only leading N elements of X are used
70454 : * if not given, automatically determined from size of X
70455 : X - starting point, array[N]:
70456 : * it is better to set X to a feasible point
70457 : * but X can be infeasible, in which case algorithm will try
70458 : to find feasible point first, using X as initial
70459 : approximation.
70460 :
70461 : OUTPUT PARAMETERS:
70462 : State - structure stores algorithm state
70463 :
70464 : NOTE: minnscreatef() function may be used if you do not have analytic
70465 : gradient. This function creates solver which uses numerical
70466 : differentiation with user-specified step.
70467 :
70468 : -- ALGLIB --
70469 : Copyright 18.05.2015 by Bochkanov Sergey
70470 : *************************************************************************/
70471 0 : void minnscreate(ae_int_t n,
70472 : /* Real */ ae_vector* x,
70473 : minnsstate* state,
70474 : ae_state *_state)
70475 : {
70476 :
70477 0 : _minnsstate_clear(state);
70478 :
70479 0 : ae_assert(n>=1, "MinNSCreate: N<1", _state);
70480 0 : ae_assert(x->cnt>=n, "MinNSCreate: Length(X)<N", _state);
70481 0 : ae_assert(isfinitevector(x, n, _state), "MinNSCreate: X contains infinite or NaN values", _state);
70482 0 : minns_minnsinitinternal(n, x, 0.0, state, _state);
70483 0 : }
70484 :
70485 :
70486 : /*************************************************************************
70487 : Version of minnscreatef() which uses numerical differentiation. I.e., you
70488 : do not have to calculate derivatives yourself. However, this version needs
70489 : 2N times more function evaluations.
70490 :
70491 : 2-point differentiation formula is used, because more precise 4-point
70492 : formula is unstable when used on non-smooth functions.
70493 :
70494 : INPUT PARAMETERS:
70495 : N - problem dimension, N>0:
70496 : * if given, only leading N elements of X are used
70497 : * if not given, automatically determined from size of X
70498 : X - starting point, array[N]:
70499 : * it is better to set X to a feasible point
70500 : * but X can be infeasible, in which case algorithm will try
70501 : to find feasible point first, using X as initial
70502 : approximation.
70503 : DiffStep- differentiation step, DiffStep>0. Algorithm performs
70504 : numerical differentiation with step for I-th variable
70505 : being equal to DiffStep*S[I] (here S[] is a scale vector,
70506 : set by minnssetscale() function).
70507 : Do not use too small steps, because it may lead to
70508 : catastrophic cancellation during intermediate calculations.
70509 :
70510 : OUTPUT PARAMETERS:
70511 : State - structure stores algorithm state
70512 :
70513 : -- ALGLIB --
70514 : Copyright 18.05.2015 by Bochkanov Sergey
70515 : *************************************************************************/
70516 0 : void minnscreatef(ae_int_t n,
70517 : /* Real */ ae_vector* x,
70518 : double diffstep,
70519 : minnsstate* state,
70520 : ae_state *_state)
70521 : {
70522 :
70523 0 : _minnsstate_clear(state);
70524 :
70525 0 : ae_assert(n>=1, "MinNSCreateF: N<1", _state);
70526 0 : ae_assert(x->cnt>=n, "MinNSCreateF: Length(X)<N", _state);
70527 0 : ae_assert(isfinitevector(x, n, _state), "MinNSCreateF: X contains infinite or NaN values", _state);
70528 0 : ae_assert(ae_isfinite(diffstep, _state), "MinNSCreateF: DiffStep is infinite or NaN!", _state);
70529 0 : ae_assert(ae_fp_greater(diffstep,(double)(0)), "MinNSCreateF: DiffStep is non-positive!", _state);
70530 0 : minns_minnsinitinternal(n, x, diffstep, state, _state);
70531 0 : }
70532 :
70533 :
70534 : /*************************************************************************
70535 : This function sets boundary constraints.
70536 :
70537 : Boundary constraints are inactive by default (after initial creation).
70538 : They are preserved after algorithm restart with minnsrestartfrom().
70539 :
70540 : INPUT PARAMETERS:
70541 : State - structure stores algorithm state
70542 : BndL - lower bounds, array[N].
70543 : If some (all) variables are unbounded, you may specify
70544 : very small number or -INF.
70545 : BndU - upper bounds, array[N].
70546 : If some (all) variables are unbounded, you may specify
70547 : very large number or +INF.
70548 :
70549 : NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th
70550 : variable will be "frozen" at X[i]=BndL[i]=BndU[i].
70551 :
70552 : NOTE 2: AGS solver has following useful properties:
70553 : * bound constraints are always satisfied exactly
70554 : * function is evaluated only INSIDE area specified by bound constraints,
70555 : even when numerical differentiation is used (algorithm adjusts nodes
70556 : according to boundary constraints)
70557 :
70558 : -- ALGLIB --
70559 : Copyright 18.05.2015 by Bochkanov Sergey
70560 : *************************************************************************/
70561 0 : void minnssetbc(minnsstate* state,
70562 : /* Real */ ae_vector* bndl,
70563 : /* Real */ ae_vector* bndu,
70564 : ae_state *_state)
70565 : {
70566 : ae_int_t i;
70567 : ae_int_t n;
70568 :
70569 :
70570 0 : n = state->n;
70571 0 : ae_assert(bndl->cnt>=n, "MinNSSetBC: Length(BndL)<N", _state);
70572 0 : ae_assert(bndu->cnt>=n, "MinNSSetBC: Length(BndU)<N", _state);
70573 0 : for(i=0; i<=n-1; i++)
70574 : {
70575 0 : ae_assert(ae_isfinite(bndl->ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "MinNSSetBC: BndL contains NAN or +INF", _state);
70576 0 : ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "MinNSSetBC: BndL contains NAN or -INF", _state);
70577 0 : state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i];
70578 0 : state->hasbndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state);
70579 0 : state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i];
70580 0 : state->hasbndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state);
70581 : }
70582 0 : }
70583 :
70584 :
70585 : /*************************************************************************
70586 : This function sets linear constraints.
70587 :
70588 : Linear constraints are inactive by default (after initial creation).
70589 : They are preserved after algorithm restart with minnsrestartfrom().
70590 :
70591 : INPUT PARAMETERS:
70592 : State - structure previously allocated with minnscreate() call.
70593 : C - linear constraints, array[K,N+1].
70594 : Each row of C represents one constraint, either equality
70595 : or inequality (see below):
70596 : * first N elements correspond to coefficients,
70597 : * last element corresponds to the right part.
70598 : All elements of C (including right part) must be finite.
70599 : CT - type of constraints, array[K]:
70600 : * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
70601 : * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
70602 : * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
70603 : K - number of equality/inequality constraints, K>=0:
70604 : * if given, only leading K elements of C/CT are used
70605 : * if not given, automatically determined from sizes of C/CT
70606 :
70607 : NOTE: linear (non-bound) constraints are satisfied only approximately:
70608 :
70609 : * there always exists some minor violation (about current sampling radius
70610 : in magnitude during optimization, about EpsX in the solution) due to use
70611 : of penalty method to handle constraints.
70612 : * numerical differentiation, if used, may lead to function evaluations
70613 : outside of the feasible area, because algorithm does NOT change
70614 : numerical differentiation formula according to linear constraints.
70615 :
70616 : If you want constraints to be satisfied exactly, try to reformulate your
70617 : problem in such manner that all constraints will become boundary ones
70618 : (this kind of constraints is always satisfied exactly, both in the final
70619 : solution and in all intermediate points).
70620 :
70621 : -- ALGLIB --
70622 : Copyright 18.05.2015 by Bochkanov Sergey
70623 : *************************************************************************/
70624 0 : void minnssetlc(minnsstate* state,
70625 : /* Real */ ae_matrix* c,
70626 : /* Integer */ ae_vector* ct,
70627 : ae_int_t k,
70628 : ae_state *_state)
70629 : {
70630 : ae_int_t n;
70631 : ae_int_t i;
70632 :
70633 :
70634 0 : n = state->n;
70635 :
70636 : /*
70637 : * First, check for errors in the inputs
70638 : */
70639 0 : ae_assert(k>=0, "MinNSSetLC: K<0", _state);
70640 0 : ae_assert(c->cols>=n+1||k==0, "MinNSSetLC: Cols(C)<N+1", _state);
70641 0 : ae_assert(c->rows>=k, "MinNSSetLC: Rows(C)<K", _state);
70642 0 : ae_assert(ct->cnt>=k, "MinNSSetLC: Length(CT)<K", _state);
70643 0 : ae_assert(apservisfinitematrix(c, k, n+1, _state), "MinNSSetLC: C contains infinite or NaN values!", _state);
70644 :
70645 : /*
70646 : * Handle zero K
70647 : */
70648 0 : if( k==0 )
70649 : {
70650 0 : state->nec = 0;
70651 0 : state->nic = 0;
70652 0 : return;
70653 : }
70654 :
70655 : /*
70656 : * Equality constraints are stored first, in the upper
70657 : * NEC rows of State.CLEIC matrix. Inequality constraints
70658 : * are stored in the next NIC rows.
70659 : *
70660 : * NOTE: we convert inequality constraints to the form
70661 : * A*x<=b before copying them.
70662 : */
70663 0 : rmatrixsetlengthatleast(&state->cleic, k, n+1, _state);
70664 0 : state->nec = 0;
70665 0 : state->nic = 0;
70666 0 : for(i=0; i<=k-1; i++)
70667 : {
70668 0 : if( ct->ptr.p_int[i]==0 )
70669 : {
70670 0 : ae_v_move(&state->cleic.ptr.pp_double[state->nec][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n));
70671 0 : state->nec = state->nec+1;
70672 : }
70673 : }
70674 0 : for(i=0; i<=k-1; i++)
70675 : {
70676 0 : if( ct->ptr.p_int[i]!=0 )
70677 : {
70678 0 : if( ct->ptr.p_int[i]>0 )
70679 : {
70680 0 : 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));
70681 : }
70682 : else
70683 : {
70684 0 : 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));
70685 : }
70686 0 : state->nic = state->nic+1;
70687 : }
70688 : }
70689 : }
70690 :
70691 :
70692 : /*************************************************************************
70693 : This function sets nonlinear constraints.
70694 :
70695 : In fact, this function sets NUMBER of nonlinear constraints. Constraints
70696 : itself (constraint functions) are passed to minnsoptimize() method. This
70697 : method requires user-defined vector function F[] and its Jacobian J[],
70698 : where:
70699 : * first component of F[] and first row of Jacobian J[] correspond to
70700 : function being minimized
70701 : * next NLEC components of F[] (and rows of J) correspond to nonlinear
70702 : equality constraints G_i(x)=0
70703 : * next NLIC components of F[] (and rows of J) correspond to nonlinear
70704 : inequality constraints H_i(x)<=0
70705 :
70706 : NOTE: you may combine nonlinear constraints with linear/boundary ones. If
70707 : your problem has mixed constraints, you may explicitly specify some
70708 : of them as linear ones. It may help optimizer to handle them more
70709 : efficiently.
70710 :
70711 : INPUT PARAMETERS:
70712 : State - structure previously allocated with minnscreate() call.
70713 : NLEC - number of Non-Linear Equality Constraints (NLEC), >=0
70714 : NLIC - number of Non-Linear Inquality Constraints (NLIC), >=0
70715 :
70716 : NOTE 1: nonlinear constraints are satisfied only approximately! It is
70717 : possible that algorithm will evaluate function outside of
70718 : the feasible area!
70719 :
70720 : NOTE 2: algorithm scales variables according to scale specified by
70721 : minnssetscale() function, so it can handle problems with badly
70722 : scaled variables (as long as we KNOW their scales).
70723 :
70724 : However, there is no way to automatically scale nonlinear
70725 : constraints Gi(x) and Hi(x). Inappropriate scaling of Gi/Hi may
70726 : ruin convergence. Solving problem with constraint "1000*G0(x)=0"
70727 : is NOT same as solving it with constraint "0.001*G0(x)=0".
70728 :
70729 : It means that YOU are the one who is responsible for correct
70730 : scaling of nonlinear constraints Gi(x) and Hi(x). We recommend you
70731 : to scale nonlinear constraints in such way that I-th component of
70732 : dG/dX (or dH/dx) has approximately unit magnitude (for problems
70733 : with unit scale) or has magnitude approximately equal to 1/S[i]
70734 : (where S is a scale set by minnssetscale() function).
70735 :
70736 : NOTE 3: nonlinear constraints are always hard to handle, no matter what
70737 : algorithm you try to use. Even basic box/linear constraints modify
70738 : function curvature by adding valleys and ridges. However,
70739 : nonlinear constraints add valleys which are very hard to follow
70740 : due to their "curved" nature.
70741 :
70742 : It means that optimization with single nonlinear constraint may be
70743 : significantly slower than optimization with multiple linear ones.
70744 : It is normal situation, and we recommend you to carefully choose
70745 : Rho parameter of minnssetalgoags(), because too large value may
70746 : slow down convergence.
70747 :
70748 :
70749 : -- ALGLIB --
70750 : Copyright 18.05.2015 by Bochkanov Sergey
70751 : *************************************************************************/
70752 0 : void minnssetnlc(minnsstate* state,
70753 : ae_int_t nlec,
70754 : ae_int_t nlic,
70755 : ae_state *_state)
70756 : {
70757 :
70758 :
70759 0 : ae_assert(nlec>=0, "MinNSSetNLC: NLEC<0", _state);
70760 0 : ae_assert(nlic>=0, "MinNSSetNLC: NLIC<0", _state);
70761 0 : state->ng = nlec;
70762 0 : state->nh = nlic;
70763 0 : ae_vector_set_length(&state->fi, 1+state->ng+state->nh, _state);
70764 0 : ae_matrix_set_length(&state->j, 1+state->ng+state->nh, state->n, _state);
70765 0 : }
70766 :
70767 :
70768 : /*************************************************************************
70769 : This function sets stopping conditions for iterations of optimizer.
70770 :
70771 : INPUT PARAMETERS:
70772 : State - structure which stores algorithm state
70773 : EpsX - >=0
70774 : The AGS solver finishes its work if on k+1-th iteration
70775 : sampling radius decreases below EpsX.
70776 : MaxIts - maximum number of iterations. If MaxIts=0, the number of
70777 : iterations is unlimited.
70778 :
70779 : Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic
70780 : stopping criterion selection. We do not recommend you to rely on default
70781 : choice in production code.
70782 :
70783 : -- ALGLIB --
70784 : Copyright 18.05.2015 by Bochkanov Sergey
70785 : *************************************************************************/
70786 0 : void minnssetcond(minnsstate* state,
70787 : double epsx,
70788 : ae_int_t maxits,
70789 : ae_state *_state)
70790 : {
70791 :
70792 :
70793 0 : ae_assert(ae_isfinite(epsx, _state), "MinNSSetCond: EpsX is not finite number", _state);
70794 0 : ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "MinNSSetCond: negative EpsX", _state);
70795 0 : ae_assert(maxits>=0, "MinNSSetCond: negative MaxIts!", _state);
70796 0 : if( ae_fp_eq(epsx,(double)(0))&&maxits==0 )
70797 : {
70798 0 : epsx = 1.0E-6;
70799 : }
70800 0 : state->epsx = epsx;
70801 0 : state->maxits = maxits;
70802 0 : }
70803 :
70804 :
70805 : /*************************************************************************
70806 : This function sets scaling coefficients for NLC optimizer.
70807 :
70808 : ALGLIB optimizers use scaling matrices to test stopping conditions (step
70809 : size and gradient are scaled before comparison with tolerances). Scale of
70810 : the I-th variable is a translation invariant measure of:
70811 : a) "how large" the variable is
70812 : b) how large the step should be to make significant changes in the function
70813 :
70814 : Scaling is also used by finite difference variant of the optimizer - step
70815 : along I-th axis is equal to DiffStep*S[I].
70816 :
70817 : INPUT PARAMETERS:
70818 : State - structure stores algorithm state
70819 : S - array[N], non-zero scaling coefficients
70820 : S[i] may be negative, sign doesn't matter.
70821 :
70822 : -- ALGLIB --
70823 : Copyright 18.05.2015 by Bochkanov Sergey
70824 : *************************************************************************/
70825 0 : void minnssetscale(minnsstate* state,
70826 : /* Real */ ae_vector* s,
70827 : ae_state *_state)
70828 : {
70829 : ae_int_t i;
70830 :
70831 :
70832 0 : ae_assert(s->cnt>=state->n, "MinNSSetScale: Length(S)<N", _state);
70833 0 : for(i=0; i<=state->n-1; i++)
70834 : {
70835 0 : ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "MinNSSetScale: S contains infinite or NAN elements", _state);
70836 0 : ae_assert(ae_fp_neq(s->ptr.p_double[i],(double)(0)), "MinNSSetScale: S contains zero elements", _state);
70837 0 : state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state);
70838 : }
70839 0 : }
70840 :
70841 :
70842 : /*************************************************************************
70843 : This function tells MinNS unit to use AGS (adaptive gradient sampling)
70844 : algorithm for nonsmooth constrained optimization. This algorithm is a
70845 : slight modification of one described in "An Adaptive Gradient Sampling
70846 : Algorithm for Nonsmooth Optimization" by Frank E. Curtisy and Xiaocun Quez.
70847 :
70848 : This optimizer has following benefits and drawbacks:
70849 : + robustness; it can be used with nonsmooth and nonconvex functions.
70850 : + relatively easy tuning; most of the metaparameters are easy to select.
70851 : - it has convergence of steepest descent, slower than CG/LBFGS.
70852 : - each iteration involves evaluation of ~2N gradient values and solution
70853 : of 2Nx2N quadratic programming problem, which limits applicability of
70854 : algorithm by small-scale problems (up to 50-100).
70855 :
70856 : IMPORTANT: this algorithm has convergence guarantees, i.e. it will
70857 : steadily move towards some stationary point of the function.
70858 :
70859 : However, "stationary point" does not always mean "solution".
70860 : Nonsmooth problems often have "flat spots", i.e. areas where
70861 : function do not change at all. Such "flat spots" are stationary
70862 : points by definition, and algorithm may be caught here.
70863 :
70864 : Nonsmooth CONVEX tasks are not prone to this problem. Say, if
70865 : your function has form f()=MAX(f0,f1,...), and f_i are convex,
70866 : then f() is convex too and you have guaranteed convergence to
70867 : solution.
70868 :
70869 : INPUT PARAMETERS:
70870 : State - structure which stores algorithm state
70871 : Radius - initial sampling radius, >=0.
70872 :
70873 : Internally multiplied by vector of per-variable scales
70874 : specified by minnssetscale()).
70875 :
70876 : You should select relatively large sampling radius, roughly
70877 : proportional to scaled length of the first steps of the
70878 : algorithm. Something close to 0.1 in magnitude should be
70879 : good for most problems.
70880 :
70881 : AGS solver can automatically decrease radius, so too large
70882 : radius is not a problem (assuming that you won't choose
70883 : so large radius that algorithm will sample function in
70884 : too far away points, where gradient value is irrelevant).
70885 :
70886 : Too small radius won't cause algorithm to fail, but it may
70887 : slow down algorithm (it may have to perform too short
70888 : steps).
70889 : Penalty - penalty coefficient for nonlinear constraints:
70890 : * for problem with nonlinear constraints should be some
70891 : problem-specific positive value, large enough that
70892 : penalty term changes shape of the function.
70893 : Starting from some problem-specific value penalty
70894 : coefficient becomes large enough to exactly enforce
70895 : nonlinear constraints; larger values do not improve
70896 : precision.
70897 : Increasing it too much may slow down convergence, so you
70898 : should choose it carefully.
70899 : * can be zero for problems WITHOUT nonlinear constraints
70900 : (i.e. for unconstrained ones or ones with just box or
70901 : linear constraints)
70902 : * if you specify zero value for problem with at least one
70903 : nonlinear constraint, algorithm will terminate with
70904 : error code -1.
70905 :
70906 : ALGORITHM OUTLINE
70907 :
70908 : The very basic outline of unconstrained AGS algorithm is given below:
70909 :
70910 : 0. If sampling radius is below EpsX or we performed more then MaxIts
70911 : iterations - STOP.
70912 : 1. sample O(N) gradient values at random locations around current point;
70913 : informally speaking, this sample is an implicit piecewise linear model
70914 : of the function, although algorithm formulation does not mention that
70915 : explicitly
70916 : 2. solve quadratic programming problem in order to find descent direction
70917 : 3. if QP solver tells us that we are near solution, decrease sampling
70918 : radius and move to (0)
70919 : 4. perform backtracking line search
70920 : 5. after moving to new point, goto (0)
70921 :
70922 : As for the constraints:
70923 : * box constraints are handled exactly by modification of the function
70924 : being minimized
70925 : * linear/nonlinear constraints are handled by adding L1 penalty. Because
70926 : our solver can handle nonsmoothness, we can use L1 penalty function,
70927 : which is an exact one (i.e. exact solution is returned under such
70928 : penalty).
70929 : * penalty coefficient for linear constraints is chosen automatically;
70930 : however, penalty coefficient for nonlinear constraints must be specified
70931 : by user.
70932 :
70933 : -- ALGLIB --
70934 : Copyright 18.05.2015 by Bochkanov Sergey
70935 : *************************************************************************/
70936 0 : void minnssetalgoags(minnsstate* state,
70937 : double radius,
70938 : double penalty,
70939 : ae_state *_state)
70940 : {
70941 :
70942 :
70943 0 : ae_assert(ae_isfinite(radius, _state), "MinNSSetAlgoAGS: Radius is not finite", _state);
70944 0 : ae_assert(ae_fp_greater(radius,(double)(0)), "MinNSSetAlgoAGS: Radius<=0", _state);
70945 0 : ae_assert(ae_isfinite(penalty, _state), "MinNSSetAlgoAGS: Penalty is not finite", _state);
70946 0 : ae_assert(ae_fp_greater_eq(penalty,0.0), "MinNSSetAlgoAGS: Penalty<0", _state);
70947 0 : state->agsrhononlinear = penalty;
70948 0 : state->agsradius = radius;
70949 0 : state->solvertype = 0;
70950 0 : }
70951 :
70952 :
70953 : /*************************************************************************
70954 : This function turns on/off reporting.
70955 :
70956 : INPUT PARAMETERS:
70957 : State - structure which stores algorithm state
70958 : NeedXRep- whether iteration reports are needed or not
70959 :
70960 : If NeedXRep is True, algorithm will call rep() callback function if it is
70961 : provided to minnsoptimize().
70962 :
70963 : -- ALGLIB --
70964 : Copyright 28.11.2010 by Bochkanov Sergey
70965 : *************************************************************************/
70966 0 : void minnssetxrep(minnsstate* state, ae_bool needxrep, ae_state *_state)
70967 : {
70968 :
70969 :
70970 0 : state->xrep = needxrep;
70971 0 : }
70972 :
70973 :
70974 : /*************************************************************************
70975 : This subroutine submits request for termination of running optimizer. It
70976 : should be called from user-supplied callback when user decides that it is
70977 : time to "smoothly" terminate optimization process. As result, optimizer
70978 : stops at point which was "current accepted" when termination request was
70979 : submitted and returns error code 8 (successful termination).
70980 :
70981 : INPUT PARAMETERS:
70982 : State - optimizer structure
70983 :
70984 : NOTE: after request for termination optimizer may perform several
70985 : additional calls to user-supplied callbacks. It does NOT guarantee
70986 : to stop immediately - it just guarantees that these additional calls
70987 : will be discarded later.
70988 :
70989 : NOTE: calling this function on optimizer which is NOT running will have no
70990 : effect.
70991 :
70992 : NOTE: multiple calls to this function are possible. First call is counted,
70993 : subsequent calls are silently ignored.
70994 :
70995 : -- ALGLIB --
70996 : Copyright 18.05.2015 by Bochkanov Sergey
70997 : *************************************************************************/
70998 0 : void minnsrequesttermination(minnsstate* state, ae_state *_state)
70999 : {
71000 :
71001 :
71002 0 : state->userterminationneeded = ae_true;
71003 0 : }
71004 :
71005 :
71006 : /*************************************************************************
71007 :
71008 : NOTES:
71009 :
71010 : 1. This function has two different implementations: one which uses exact
71011 : (analytical) user-supplied Jacobian, and one which uses only function
71012 : vector and numerically differentiates function in order to obtain
71013 : gradient.
71014 :
71015 : Depending on the specific function used to create optimizer object
71016 : you should choose appropriate variant of minnsoptimize() - one which
71017 : accepts function AND Jacobian or one which accepts ONLY function.
71018 :
71019 : Be careful to choose variant of minnsoptimize() which corresponds to
71020 : your optimization scheme! Table below lists different combinations of
71021 : callback (function/gradient) passed to minnsoptimize() and specific
71022 : function used to create optimizer.
71023 :
71024 :
71025 : | USER PASSED TO minnsoptimize()
71026 : CREATED WITH | function only | function and gradient
71027 : ------------------------------------------------------------
71028 : minnscreatef() | works FAILS
71029 : minnscreate() | FAILS works
71030 :
71031 : Here "FAILS" denotes inappropriate combinations of optimizer creation
71032 : function and minnsoptimize() version. Attemps to use such
71033 : combination will lead to exception. Either you did not pass gradient
71034 : when it WAS needed or you passed gradient when it was NOT needed.
71035 :
71036 : -- ALGLIB --
71037 : Copyright 18.05.2015 by Bochkanov Sergey
71038 : *************************************************************************/
71039 0 : ae_bool minnsiteration(minnsstate* state, ae_state *_state)
71040 : {
71041 : ae_int_t i;
71042 : ae_int_t k;
71043 : ae_int_t n;
71044 : ae_int_t ng;
71045 : ae_int_t nh;
71046 : double v;
71047 : double xp;
71048 : double xm;
71049 : ae_bool result;
71050 :
71051 :
71052 :
71053 : /*
71054 : * Reverse communication preparations
71055 : * I know it looks ugly, but it works the same way
71056 : * anywhere from C++ to Python.
71057 : *
71058 : * This code initializes locals by:
71059 : * * random values determined during code
71060 : * generation - on first subroutine call
71061 : * * values from previous call - on subsequent calls
71062 : */
71063 0 : if( state->rstate.stage>=0 )
71064 : {
71065 0 : i = state->rstate.ia.ptr.p_int[0];
71066 0 : k = state->rstate.ia.ptr.p_int[1];
71067 0 : n = state->rstate.ia.ptr.p_int[2];
71068 0 : ng = state->rstate.ia.ptr.p_int[3];
71069 0 : nh = state->rstate.ia.ptr.p_int[4];
71070 0 : v = state->rstate.ra.ptr.p_double[0];
71071 0 : xp = state->rstate.ra.ptr.p_double[1];
71072 0 : xm = state->rstate.ra.ptr.p_double[2];
71073 : }
71074 : else
71075 : {
71076 0 : i = 359;
71077 0 : k = -58;
71078 0 : n = -919;
71079 0 : ng = -909;
71080 0 : nh = 81;
71081 0 : v = 255;
71082 0 : xp = 74;
71083 0 : xm = -788;
71084 : }
71085 0 : if( state->rstate.stage==0 )
71086 : {
71087 0 : goto lbl_0;
71088 : }
71089 0 : if( state->rstate.stage==1 )
71090 : {
71091 0 : goto lbl_1;
71092 : }
71093 0 : if( state->rstate.stage==2 )
71094 : {
71095 0 : goto lbl_2;
71096 : }
71097 0 : if( state->rstate.stage==3 )
71098 : {
71099 0 : goto lbl_3;
71100 : }
71101 :
71102 : /*
71103 : * Routine body
71104 : */
71105 :
71106 : /*
71107 : * Init
71108 : */
71109 0 : state->replcerr = 0.0;
71110 0 : state->repnlcerr = 0.0;
71111 0 : state->repterminationtype = 0;
71112 0 : state->repinneriterationscount = 0;
71113 0 : state->repouteriterationscount = 0;
71114 0 : state->repnfev = 0;
71115 0 : state->repvaridx = 0;
71116 0 : state->repfuncidx = 0;
71117 0 : state->userterminationneeded = ae_false;
71118 0 : state->dbgncholesky = 0;
71119 0 : n = state->n;
71120 0 : ng = state->ng;
71121 0 : nh = state->nh;
71122 0 : minns_clearrequestfields(state, _state);
71123 :
71124 : /*
71125 : * AGS solver
71126 : */
71127 0 : if( state->solvertype!=0 )
71128 : {
71129 0 : goto lbl_4;
71130 : }
71131 0 : if( ae_fp_neq(state->diffstep,(double)(0)) )
71132 : {
71133 0 : rvectorsetlengthatleast(&state->xbase, n, _state);
71134 0 : rvectorsetlengthatleast(&state->fm, 1+ng+nh, _state);
71135 0 : rvectorsetlengthatleast(&state->fp, 1+ng+nh, _state);
71136 : }
71137 0 : ae_vector_set_length(&state->rstateags.ia, 13+1, _state);
71138 0 : ae_vector_set_length(&state->rstateags.ba, 3+1, _state);
71139 0 : ae_vector_set_length(&state->rstateags.ra, 9+1, _state);
71140 0 : state->rstateags.stage = -1;
71141 0 : lbl_6:
71142 0 : if( !minns_agsiteration(state, _state) )
71143 : {
71144 0 : goto lbl_7;
71145 : }
71146 :
71147 : /*
71148 : * Numerical differentiation (if needed) - intercept NeedFiJ
71149 : * request and replace it by sequence of NeedFi requests
71150 : */
71151 0 : if( !(ae_fp_neq(state->diffstep,(double)(0))&&state->needfij) )
71152 : {
71153 0 : goto lbl_8;
71154 : }
71155 0 : state->needfij = ae_false;
71156 0 : state->needfi = ae_true;
71157 0 : ae_v_move(&state->xbase.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1));
71158 0 : k = 0;
71159 0 : lbl_10:
71160 0 : if( k>n-1 )
71161 : {
71162 0 : goto lbl_12;
71163 : }
71164 0 : v = state->xbase.ptr.p_double[k];
71165 0 : xm = v-state->diffstep*state->s.ptr.p_double[k];
71166 0 : xp = v+state->diffstep*state->s.ptr.p_double[k];
71167 0 : if( state->hasbndl.ptr.p_bool[k]&&ae_fp_less(xm,state->bndl.ptr.p_double[k]) )
71168 : {
71169 0 : xm = state->bndl.ptr.p_double[k];
71170 : }
71171 0 : if( state->hasbndu.ptr.p_bool[k]&&ae_fp_greater(xp,state->bndu.ptr.p_double[k]) )
71172 : {
71173 0 : xp = state->bndu.ptr.p_double[k];
71174 : }
71175 0 : ae_assert(ae_fp_less_eq(xm,xp), "MinNS: integrity check failed", _state);
71176 0 : if( ae_fp_eq(xm,xp) )
71177 : {
71178 0 : goto lbl_13;
71179 : }
71180 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
71181 0 : state->x.ptr.p_double[k] = xm;
71182 0 : state->rstate.stage = 0;
71183 0 : goto lbl_rcomm;
71184 0 : lbl_0:
71185 0 : ae_v_move(&state->fm.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh));
71186 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
71187 0 : state->x.ptr.p_double[k] = xp;
71188 0 : state->rstate.stage = 1;
71189 0 : goto lbl_rcomm;
71190 0 : lbl_1:
71191 0 : ae_v_move(&state->fp.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,ng+nh));
71192 0 : ae_v_move(&state->j.ptr.pp_double[0][k], state->j.stride, &state->fp.ptr.p_double[0], 1, ae_v_len(0,ng+nh));
71193 0 : ae_v_sub(&state->j.ptr.pp_double[0][k], state->j.stride, &state->fm.ptr.p_double[0], 1, ae_v_len(0,ng+nh));
71194 0 : v = 1/(xp-xm);
71195 0 : ae_v_muld(&state->j.ptr.pp_double[0][k], state->j.stride, ae_v_len(0,ng+nh), v);
71196 0 : state->repnfev = state->repnfev+2;
71197 0 : goto lbl_14;
71198 0 : lbl_13:
71199 0 : for(i=0; i<=ng+nh; i++)
71200 : {
71201 0 : state->j.ptr.pp_double[i][k] = 0.0;
71202 : }
71203 0 : lbl_14:
71204 0 : k = k+1;
71205 0 : goto lbl_10;
71206 0 : lbl_12:
71207 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
71208 0 : state->rstate.stage = 2;
71209 0 : goto lbl_rcomm;
71210 0 : lbl_2:
71211 :
71212 : /*
71213 : * Restore previous values of fields and continue
71214 : */
71215 0 : state->needfi = ae_false;
71216 0 : state->needfij = ae_true;
71217 0 : goto lbl_6;
71218 0 : lbl_8:
71219 :
71220 : /*
71221 : * Forward request to caller
71222 : */
71223 0 : state->rstate.stage = 3;
71224 0 : goto lbl_rcomm;
71225 0 : lbl_3:
71226 0 : inc(&state->repnfev, _state);
71227 0 : goto lbl_6;
71228 0 : lbl_7:
71229 0 : result = ae_false;
71230 0 : return result;
71231 0 : lbl_4:
71232 0 : result = ae_false;
71233 0 : return result;
71234 :
71235 : /*
71236 : * Saving state
71237 : */
71238 0 : lbl_rcomm:
71239 0 : result = ae_true;
71240 0 : state->rstate.ia.ptr.p_int[0] = i;
71241 0 : state->rstate.ia.ptr.p_int[1] = k;
71242 0 : state->rstate.ia.ptr.p_int[2] = n;
71243 0 : state->rstate.ia.ptr.p_int[3] = ng;
71244 0 : state->rstate.ia.ptr.p_int[4] = nh;
71245 0 : state->rstate.ra.ptr.p_double[0] = v;
71246 0 : state->rstate.ra.ptr.p_double[1] = xp;
71247 0 : state->rstate.ra.ptr.p_double[2] = xm;
71248 0 : return result;
71249 : }
71250 :
71251 :
71252 : /*************************************************************************
71253 : MinNS results
71254 :
71255 : INPUT PARAMETERS:
71256 : State - algorithm state
71257 :
71258 : OUTPUT PARAMETERS:
71259 : X - array[0..N-1], solution
71260 : Rep - optimization report. You should check Rep.TerminationType
71261 : in order to distinguish successful termination from
71262 : unsuccessful one:
71263 : * -8 internal integrity control detected infinite or
71264 : NAN values in function/gradient. Abnormal
71265 : termination signalled.
71266 : * -3 box constraints are inconsistent
71267 : * -1 inconsistent parameters were passed:
71268 : * penalty parameter for minnssetalgoags() is zero,
71269 : but we have nonlinear constraints set by minnssetnlc()
71270 : * 2 sampling radius decreased below epsx
71271 : * 7 stopping conditions are too stringent,
71272 : further improvement is impossible,
71273 : X contains best point found so far.
71274 : * 8 User requested termination via minnsrequesttermination()
71275 :
71276 : -- ALGLIB --
71277 : Copyright 18.05.2015 by Bochkanov Sergey
71278 : *************************************************************************/
71279 0 : void minnsresults(minnsstate* state,
71280 : /* Real */ ae_vector* x,
71281 : minnsreport* rep,
71282 : ae_state *_state)
71283 : {
71284 :
71285 0 : ae_vector_clear(x);
71286 0 : _minnsreport_clear(rep);
71287 :
71288 0 : minnsresultsbuf(state, x, rep, _state);
71289 0 : }
71290 :
71291 :
71292 : /*************************************************************************
71293 :
71294 : Buffered implementation of minnsresults() which uses pre-allocated buffer
71295 : to store X[]. If buffer size is too small, it resizes buffer. It is
71296 : intended to be used in the inner cycles of performance critical algorithms
71297 : where array reallocation penalty is too large to be ignored.
71298 :
71299 : -- ALGLIB --
71300 : Copyright 18.05.2015 by Bochkanov Sergey
71301 : *************************************************************************/
71302 0 : void minnsresultsbuf(minnsstate* state,
71303 : /* Real */ ae_vector* x,
71304 : minnsreport* rep,
71305 : ae_state *_state)
71306 : {
71307 : ae_int_t i;
71308 :
71309 :
71310 0 : if( x->cnt<state->n )
71311 : {
71312 0 : ae_vector_set_length(x, state->n, _state);
71313 : }
71314 0 : rep->iterationscount = state->repinneriterationscount;
71315 0 : rep->nfev = state->repnfev;
71316 0 : rep->varidx = state->repvaridx;
71317 0 : rep->funcidx = state->repfuncidx;
71318 0 : rep->terminationtype = state->repterminationtype;
71319 0 : rep->cerr = ae_maxreal(state->replcerr, state->repnlcerr, _state);
71320 0 : rep->lcerr = state->replcerr;
71321 0 : rep->nlcerr = state->repnlcerr;
71322 0 : if( state->repterminationtype>0 )
71323 : {
71324 0 : ae_v_move(&x->ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,state->n-1));
71325 : }
71326 : else
71327 : {
71328 0 : for(i=0; i<=state->n-1; i++)
71329 : {
71330 0 : x->ptr.p_double[i] = _state->v_nan;
71331 : }
71332 : }
71333 0 : }
71334 :
71335 :
71336 : /*************************************************************************
71337 : This subroutine restarts algorithm from new point.
71338 : All optimization parameters (including constraints) are left unchanged.
71339 :
71340 : This function allows to solve multiple optimization problems (which
71341 : must have same number of dimensions) without object reallocation penalty.
71342 :
71343 : INPUT PARAMETERS:
71344 : State - structure previously allocated with minnscreate() call.
71345 : X - new starting point.
71346 :
71347 : -- ALGLIB --
71348 : Copyright 18.05.2015 by Bochkanov Sergey
71349 : *************************************************************************/
71350 0 : void minnsrestartfrom(minnsstate* state,
71351 : /* Real */ ae_vector* x,
71352 : ae_state *_state)
71353 : {
71354 : ae_int_t n;
71355 :
71356 :
71357 0 : n = state->n;
71358 :
71359 : /*
71360 : * First, check for errors in the inputs
71361 : */
71362 0 : ae_assert(x->cnt>=n, "MinNSRestartFrom: Length(X)<N", _state);
71363 0 : ae_assert(isfinitevector(x, n, _state), "MinNSRestartFrom: X contains infinite or NaN values!", _state);
71364 :
71365 : /*
71366 : * Set XC
71367 : */
71368 0 : ae_v_move(&state->xstart.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
71369 :
71370 : /*
71371 : * prepare RComm facilities
71372 : */
71373 0 : ae_vector_set_length(&state->rstate.ia, 4+1, _state);
71374 0 : ae_vector_set_length(&state->rstate.ra, 2+1, _state);
71375 0 : state->rstate.stage = -1;
71376 0 : minns_clearrequestfields(state, _state);
71377 0 : }
71378 :
71379 :
71380 : /*************************************************************************
71381 : Clears request fileds (to be sure that we don't forget to clear something)
71382 : *************************************************************************/
71383 0 : static void minns_clearrequestfields(minnsstate* state, ae_state *_state)
71384 : {
71385 :
71386 :
71387 0 : state->needfi = ae_false;
71388 0 : state->needfij = ae_false;
71389 0 : state->xupdated = ae_false;
71390 0 : }
71391 :
71392 :
71393 : /*************************************************************************
71394 : Internal initialization subroutine.
71395 : Sets default NLC solver with default criteria.
71396 : *************************************************************************/
71397 0 : static void minns_minnsinitinternal(ae_int_t n,
71398 : /* Real */ ae_vector* x,
71399 : double diffstep,
71400 : minnsstate* state,
71401 : ae_state *_state)
71402 : {
71403 : ae_frame _frame_block;
71404 : ae_int_t i;
71405 : ae_matrix c;
71406 : ae_vector ct;
71407 :
71408 0 : ae_frame_make(_state, &_frame_block);
71409 0 : memset(&c, 0, sizeof(c));
71410 0 : memset(&ct, 0, sizeof(ct));
71411 0 : ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
71412 0 : ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
71413 :
71414 0 : state->agsinitstp = 0.2;
71415 0 : state->agsstattold = 1.0E-10;
71416 0 : state->agsshortstpabs = 1.0E-10;
71417 0 : state->agsshortstprel = 0.75;
71418 0 : state->agsshortf = 10*ae_machineepsilon;
71419 0 : state->agsrhononlinear = 0.0;
71420 0 : state->agsraddecay = 0.2;
71421 0 : state->agsalphadecay = 0.5;
71422 0 : state->agsdecrease = 0.1;
71423 0 : state->agsmaxraddecays = 50;
71424 0 : state->agsmaxbacktrack = 20;
71425 0 : state->agsmaxbacktracknonfull = 8;
71426 0 : state->agspenaltylevel = 50.0;
71427 0 : state->agspenaltyincrease = 100.0;
71428 0 : state->agsminupdate = ae_maxint(5, n/2, _state);
71429 0 : state->agssamplesize = ae_maxint(2*n+1, state->agsminupdate+1, _state);
71430 0 : state->agsshortlimit = 4+state->agssamplesize/state->agsminupdate;
71431 :
71432 : /*
71433 : * Initialize other params
71434 : */
71435 0 : state->n = n;
71436 0 : state->diffstep = diffstep;
71437 0 : ae_vector_set_length(&state->bndl, n, _state);
71438 0 : ae_vector_set_length(&state->hasbndl, n, _state);
71439 0 : ae_vector_set_length(&state->bndu, n, _state);
71440 0 : ae_vector_set_length(&state->hasbndu, n, _state);
71441 0 : ae_vector_set_length(&state->s, n, _state);
71442 0 : ae_vector_set_length(&state->xstart, n, _state);
71443 0 : ae_vector_set_length(&state->xc, n, _state);
71444 0 : ae_vector_set_length(&state->xn, n, _state);
71445 0 : ae_vector_set_length(&state->d, n, _state);
71446 0 : ae_vector_set_length(&state->x, n, _state);
71447 0 : for(i=0; i<=n-1; i++)
71448 : {
71449 0 : state->bndl.ptr.p_double[i] = _state->v_neginf;
71450 0 : state->hasbndl.ptr.p_bool[i] = ae_false;
71451 0 : state->bndu.ptr.p_double[i] = _state->v_posinf;
71452 0 : state->hasbndu.ptr.p_bool[i] = ae_false;
71453 0 : state->s.ptr.p_double[i] = 1.0;
71454 0 : state->xstart.ptr.p_double[i] = x->ptr.p_double[i];
71455 0 : state->xc.ptr.p_double[i] = x->ptr.p_double[i];
71456 : }
71457 0 : minnssetlc(state, &c, &ct, 0, _state);
71458 0 : minnssetnlc(state, 0, 0, _state);
71459 0 : minnssetcond(state, 0.0, 0, _state);
71460 0 : minnssetxrep(state, ae_false, _state);
71461 0 : minnssetalgoags(state, 0.1, 1000.0, _state);
71462 0 : minnsrestartfrom(state, x, _state);
71463 0 : ae_frame_leave(_state);
71464 0 : }
71465 :
71466 :
71467 : /*************************************************************************
71468 : This function performs actual processing for AUL algorith. It expects that
71469 : caller redirects its reverse communication requests NeedFiJ/XUpdated to
71470 : external user who will provide analytic derivative (or handle reports about
71471 : progress).
71472 :
71473 : In case external user does not have analytic derivative, it is responsibility
71474 : of caller to intercept NeedFiJ request and replace it with appropriate
71475 : numerical differentiation scheme.
71476 :
71477 : -- ALGLIB --
71478 : Copyright 06.06.2015 by Bochkanov Sergey
71479 : *************************************************************************/
71480 0 : static ae_bool minns_agsiteration(minnsstate* state, ae_state *_state)
71481 : {
71482 : ae_int_t n;
71483 : ae_int_t nec;
71484 : ae_int_t nic;
71485 : ae_int_t ng;
71486 : ae_int_t nh;
71487 : ae_int_t i;
71488 : ae_int_t j;
71489 : ae_int_t k;
71490 : double radius0;
71491 : double radius;
71492 : ae_int_t radiusdecays;
71493 : double alpha;
71494 : double recommendedstep;
71495 : double dnrm;
71496 : double dg;
71497 : double v;
71498 : double vv;
71499 : ae_int_t maxsamplesize;
71500 : ae_int_t cursamplesize;
71501 : double v0;
71502 : double v1;
71503 : ae_bool restartneeded;
71504 : ae_bool b;
71505 : ae_bool alphadecreased;
71506 : ae_int_t shortstepscnt;
71507 : ae_int_t backtrackits;
71508 : ae_int_t maxbacktrackits;
71509 : ae_bool fullsample;
71510 : ae_bool result;
71511 :
71512 :
71513 :
71514 : /*
71515 : * Reverse communication preparations
71516 : * I know it looks ugly, but it works the same way
71517 : * anywhere from C++ to Python.
71518 : *
71519 : * This code initializes locals by:
71520 : * * random values determined during code
71521 : * generation - on first subroutine call
71522 : * * values from previous call - on subsequent calls
71523 : */
71524 0 : if( state->rstateags.stage>=0 )
71525 : {
71526 0 : n = state->rstateags.ia.ptr.p_int[0];
71527 0 : nec = state->rstateags.ia.ptr.p_int[1];
71528 0 : nic = state->rstateags.ia.ptr.p_int[2];
71529 0 : ng = state->rstateags.ia.ptr.p_int[3];
71530 0 : nh = state->rstateags.ia.ptr.p_int[4];
71531 0 : i = state->rstateags.ia.ptr.p_int[5];
71532 0 : j = state->rstateags.ia.ptr.p_int[6];
71533 0 : k = state->rstateags.ia.ptr.p_int[7];
71534 0 : radiusdecays = state->rstateags.ia.ptr.p_int[8];
71535 0 : maxsamplesize = state->rstateags.ia.ptr.p_int[9];
71536 0 : cursamplesize = state->rstateags.ia.ptr.p_int[10];
71537 0 : shortstepscnt = state->rstateags.ia.ptr.p_int[11];
71538 0 : backtrackits = state->rstateags.ia.ptr.p_int[12];
71539 0 : maxbacktrackits = state->rstateags.ia.ptr.p_int[13];
71540 0 : restartneeded = state->rstateags.ba.ptr.p_bool[0];
71541 0 : b = state->rstateags.ba.ptr.p_bool[1];
71542 0 : alphadecreased = state->rstateags.ba.ptr.p_bool[2];
71543 0 : fullsample = state->rstateags.ba.ptr.p_bool[3];
71544 0 : radius0 = state->rstateags.ra.ptr.p_double[0];
71545 0 : radius = state->rstateags.ra.ptr.p_double[1];
71546 0 : alpha = state->rstateags.ra.ptr.p_double[2];
71547 0 : recommendedstep = state->rstateags.ra.ptr.p_double[3];
71548 0 : dnrm = state->rstateags.ra.ptr.p_double[4];
71549 0 : dg = state->rstateags.ra.ptr.p_double[5];
71550 0 : v = state->rstateags.ra.ptr.p_double[6];
71551 0 : vv = state->rstateags.ra.ptr.p_double[7];
71552 0 : v0 = state->rstateags.ra.ptr.p_double[8];
71553 0 : v1 = state->rstateags.ra.ptr.p_double[9];
71554 : }
71555 : else
71556 : {
71557 0 : n = 809;
71558 0 : nec = 205;
71559 0 : nic = -838;
71560 0 : ng = 939;
71561 0 : nh = -526;
71562 0 : i = 763;
71563 0 : j = -541;
71564 0 : k = -698;
71565 0 : radiusdecays = -900;
71566 0 : maxsamplesize = -318;
71567 0 : cursamplesize = -940;
71568 0 : shortstepscnt = 1016;
71569 0 : backtrackits = -229;
71570 0 : maxbacktrackits = -536;
71571 0 : restartneeded = ae_true;
71572 0 : b = ae_true;
71573 0 : alphadecreased = ae_false;
71574 0 : fullsample = ae_false;
71575 0 : radius0 = -722;
71576 0 : radius = -413;
71577 0 : alpha = -461;
71578 0 : recommendedstep = 927;
71579 0 : dnrm = 201;
71580 0 : dg = 922;
71581 0 : v = -154;
71582 0 : vv = 306;
71583 0 : v0 = -1011;
71584 0 : v1 = 951;
71585 : }
71586 0 : if( state->rstateags.stage==0 )
71587 : {
71588 0 : goto lbl_0;
71589 : }
71590 0 : if( state->rstateags.stage==1 )
71591 : {
71592 0 : goto lbl_1;
71593 : }
71594 0 : if( state->rstateags.stage==2 )
71595 : {
71596 0 : goto lbl_2;
71597 : }
71598 0 : if( state->rstateags.stage==3 )
71599 : {
71600 0 : goto lbl_3;
71601 : }
71602 :
71603 : /*
71604 : * Routine body
71605 : */
71606 0 : ae_assert(state->solvertype==0, "MinNS: internal error", _state);
71607 0 : n = state->n;
71608 0 : nec = state->nec;
71609 0 : nic = state->nic;
71610 0 : ng = state->ng;
71611 0 : nh = state->nh;
71612 :
71613 : /*
71614 : * Check consistency of parameters
71615 : */
71616 0 : if( ng+nh>0&&ae_fp_eq(state->agsrhononlinear,(double)(0)) )
71617 : {
71618 0 : state->repterminationtype = -1;
71619 0 : result = ae_false;
71620 0 : return result;
71621 : }
71622 :
71623 : /*
71624 : * Allocate arrays.
71625 : */
71626 0 : rvectorsetlengthatleast(&state->colmax, n, _state);
71627 0 : rvectorsetlengthatleast(&state->diagh, n, _state);
71628 0 : rvectorsetlengthatleast(&state->signmin, n, _state);
71629 0 : rvectorsetlengthatleast(&state->signmax, n, _state);
71630 0 : maxsamplesize = state->agssamplesize;
71631 0 : rmatrixsetlengthatleast(&state->samplex, maxsamplesize+1, n, _state);
71632 0 : rmatrixsetlengthatleast(&state->samplegm, maxsamplesize+1, n, _state);
71633 0 : rmatrixsetlengthatleast(&state->samplegmbc, maxsamplesize+1, n, _state);
71634 0 : rvectorsetlengthatleast(&state->samplef, maxsamplesize+1, _state);
71635 0 : rvectorsetlengthatleast(&state->samplef0, maxsamplesize+1, _state);
71636 0 : rvectorsetlengthatleast(&state->grs, n, _state);
71637 :
71638 : /*
71639 : * Prepare optimizer
71640 : */
71641 0 : rvectorsetlengthatleast(&state->tmp0, maxsamplesize, _state);
71642 0 : rvectorsetlengthatleast(&state->tmp1, maxsamplesize, _state);
71643 0 : ivectorsetlengthatleast(&state->tmp3, 1, _state);
71644 0 : rmatrixsetlengthatleast(&state->tmp2, 1, maxsamplesize+1, _state);
71645 0 : for(i=0; i<=maxsamplesize-1; i++)
71646 : {
71647 0 : state->tmp0.ptr.p_double[i] = 0.0;
71648 0 : state->tmp1.ptr.p_double[i] = _state->v_posinf;
71649 : }
71650 :
71651 : /*
71652 : * Prepare RNG, seed it with fixed values so
71653 : * that each run on same problem yeilds same results
71654 : */
71655 0 : hqrndseed(7235, 98532, &state->agsrs, _state);
71656 :
71657 : /*
71658 : * Prepare initial point subject to current bound constraints and
71659 : * perform scaling of bound constraints, linear constraints, point itself
71660 : */
71661 0 : rvectorsetlengthatleast(&state->scaledbndl, n, _state);
71662 0 : rvectorsetlengthatleast(&state->scaledbndu, n, _state);
71663 0 : for(i=0; i<=n-1; i++)
71664 : {
71665 :
71666 : /*
71667 : * Check and scale constraints
71668 : */
71669 0 : if( (state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i])&&ae_fp_less(state->bndu.ptr.p_double[i],state->bndl.ptr.p_double[i]) )
71670 : {
71671 0 : state->repterminationtype = -3;
71672 0 : result = ae_false;
71673 0 : return result;
71674 : }
71675 0 : if( state->hasbndl.ptr.p_bool[i] )
71676 : {
71677 0 : state->scaledbndl.ptr.p_double[i] = state->bndl.ptr.p_double[i]/state->s.ptr.p_double[i];
71678 : }
71679 : else
71680 : {
71681 0 : state->scaledbndl.ptr.p_double[i] = _state->v_neginf;
71682 : }
71683 0 : if( state->hasbndu.ptr.p_bool[i] )
71684 : {
71685 0 : state->scaledbndu.ptr.p_double[i] = state->bndu.ptr.p_double[i]/state->s.ptr.p_double[i];
71686 : }
71687 : else
71688 : {
71689 0 : state->scaledbndu.ptr.p_double[i] = _state->v_posinf;
71690 : }
71691 0 : if( state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i] )
71692 : {
71693 0 : ae_assert(ae_fp_less_eq(state->scaledbndl.ptr.p_double[i],state->scaledbndu.ptr.p_double[i]), "MinNS: integrity check failed", _state);
71694 : }
71695 0 : 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]) )
71696 : {
71697 0 : ae_assert(ae_fp_eq(state->scaledbndl.ptr.p_double[i],state->scaledbndu.ptr.p_double[i]), "MinNS: integrity check failed", _state);
71698 : }
71699 :
71700 : /*
71701 : * Scale and constrain point
71702 : */
71703 0 : state->xc.ptr.p_double[i] = state->xstart.ptr.p_double[i];
71704 0 : if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less_eq(state->xc.ptr.p_double[i],state->bndl.ptr.p_double[i]) )
71705 : {
71706 0 : state->xc.ptr.p_double[i] = state->scaledbndl.ptr.p_double[i];
71707 0 : continue;
71708 : }
71709 0 : if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater_eq(state->xc.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
71710 : {
71711 0 : state->xc.ptr.p_double[i] = state->scaledbndu.ptr.p_double[i];
71712 0 : continue;
71713 : }
71714 0 : state->xc.ptr.p_double[i] = state->xc.ptr.p_double[i]/state->s.ptr.p_double[i];
71715 0 : if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less_eq(state->xc.ptr.p_double[i],state->scaledbndl.ptr.p_double[i]) )
71716 : {
71717 0 : state->xc.ptr.p_double[i] = state->scaledbndl.ptr.p_double[i];
71718 : }
71719 0 : if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater_eq(state->xc.ptr.p_double[i],state->scaledbndu.ptr.p_double[i]) )
71720 : {
71721 0 : state->xc.ptr.p_double[i] = state->scaledbndu.ptr.p_double[i];
71722 : }
71723 : }
71724 0 : rmatrixsetlengthatleast(&state->scaledcleic, nec+nic, n+1, _state);
71725 0 : rvectorsetlengthatleast(&state->rholinear, nec+nic, _state);
71726 0 : for(i=0; i<=nec+nic-1; i++)
71727 : {
71728 :
71729 : /*
71730 : * Initial value of penalty coefficient is zero
71731 : */
71732 0 : state->rholinear.ptr.p_double[i] = 0.0;
71733 :
71734 : /*
71735 : * Scale and normalize linear constraints
71736 : */
71737 0 : vv = 0.0;
71738 0 : for(j=0; j<=n-1; j++)
71739 : {
71740 0 : v = state->cleic.ptr.pp_double[i][j]*state->s.ptr.p_double[j];
71741 0 : state->scaledcleic.ptr.pp_double[i][j] = v;
71742 0 : vv = vv+v*v;
71743 : }
71744 0 : vv = ae_sqrt(vv, _state);
71745 0 : state->scaledcleic.ptr.pp_double[i][n] = state->cleic.ptr.pp_double[i][n];
71746 0 : if( ae_fp_greater(vv,(double)(0)) )
71747 : {
71748 0 : for(j=0; j<=n; j++)
71749 : {
71750 0 : state->scaledcleic.ptr.pp_double[i][j] = state->scaledcleic.ptr.pp_double[i][j]/vv;
71751 : }
71752 : }
71753 : }
71754 :
71755 : /*
71756 : * Main cycle
71757 : *
71758 : * We maintain several variables during iteration:
71759 : * * RecommendedStep- current estimate of recommended step length;
71760 : * must be Radius0 on first entry
71761 : * * Radius - current sampling radius
71762 : * * CurSampleSize - current sample size (may change in future versions)
71763 : * * FullSample - whether we have full sample, or only partial one
71764 : * * RadiusDecays - total number of decreases performed for sampling radius
71765 : */
71766 0 : radius = state->agsradius;
71767 0 : radius0 = radius;
71768 0 : recommendedstep = ae_minreal(radius0, state->agsinitstp, _state);
71769 0 : cursamplesize = 1;
71770 0 : radiusdecays = 0;
71771 0 : shortstepscnt = 0;
71772 0 : fullsample = ae_false;
71773 0 : lbl_4:
71774 : if( ae_false )
71775 : {
71776 : goto lbl_5;
71777 : }
71778 :
71779 : /*
71780 : * First phase of iteration - central point:
71781 : *
71782 : * 1. evaluate function at central point - first entry in sample.
71783 : * Its status is ignored, it is always recalculated.
71784 : * 2. report point and check gradient/function value for NAN/INF
71785 : * 3. check penalty coefficients for linear terms; increase them
71786 : * if directional derivative of function being optimized (not
71787 : * merit function!) is larger than derivative of penalty.
71788 : * 4. update report on constraint violation
71789 : */
71790 0 : cursamplesize = ae_maxint(cursamplesize, 1, _state);
71791 0 : ae_v_move(&state->samplex.ptr.pp_double[0][0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
71792 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
71793 0 : minns_unscalepointbc(state, &state->x, _state);
71794 0 : minns_clearrequestfields(state, _state);
71795 0 : state->needfij = ae_true;
71796 0 : state->rstateags.stage = 0;
71797 0 : goto lbl_rcomm;
71798 0 : lbl_0:
71799 0 : state->needfij = ae_false;
71800 0 : state->replcerr = 0.0;
71801 0 : for(i=0; i<=nec+nic-1; i++)
71802 : {
71803 0 : v = -state->scaledcleic.ptr.pp_double[i][n];
71804 0 : for(j=0; j<=n-1; j++)
71805 : {
71806 0 : v = v+state->scaledcleic.ptr.pp_double[i][j]*state->xc.ptr.p_double[j];
71807 : }
71808 0 : if( i>=nec&&ae_fp_less_eq(v,(double)(0)) )
71809 : {
71810 0 : continue;
71811 : }
71812 0 : state->replcerr = ae_maxreal(state->replcerr, ae_fabs(v, _state), _state);
71813 : }
71814 0 : state->repnlcerr = 0.0;
71815 0 : for(i=1; i<=ng+nh; i++)
71816 : {
71817 0 : v = state->fi.ptr.p_double[i];
71818 0 : if( i>ng&&ae_fp_less_eq(v,(double)(0)) )
71819 : {
71820 0 : continue;
71821 : }
71822 0 : state->repnlcerr = ae_maxreal(state->repnlcerr, ae_fabs(v, _state), _state);
71823 : }
71824 0 : for(j=0; j<=n-1; j++)
71825 : {
71826 0 : state->grs.ptr.p_double[j] = state->j.ptr.pp_double[0][j]*state->s.ptr.p_double[j];
71827 : }
71828 0 : minns_generatemeritfunction(state, 0, _state);
71829 0 : if( !state->xrep )
71830 : {
71831 0 : goto lbl_6;
71832 : }
71833 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
71834 0 : state->f = state->samplef0.ptr.p_double[0];
71835 0 : minns_unscalepointbc(state, &state->x, _state);
71836 0 : minns_clearrequestfields(state, _state);
71837 0 : state->xupdated = ae_true;
71838 0 : state->rstateags.stage = 1;
71839 0 : goto lbl_rcomm;
71840 0 : lbl_1:
71841 0 : state->xupdated = ae_false;
71842 0 : lbl_6:
71843 0 : if( state->userterminationneeded )
71844 : {
71845 :
71846 : /*
71847 : * User requested termination
71848 : */
71849 0 : state->repterminationtype = 8;
71850 0 : goto lbl_5;
71851 : }
71852 0 : v = (double)(0);
71853 0 : for(i=0; i<=n-1; i++)
71854 : {
71855 0 : v = v+ae_sqr(state->samplegm.ptr.pp_double[0][i], _state);
71856 : }
71857 0 : if( !ae_isfinite(v, _state)||!ae_isfinite(state->samplef.ptr.p_double[0], _state) )
71858 : {
71859 :
71860 : /*
71861 : * Abnormal termination - infinities in function/gradient
71862 : */
71863 0 : state->repterminationtype = -8;
71864 0 : goto lbl_5;
71865 : }
71866 0 : restartneeded = ae_false;
71867 0 : for(i=0; i<=nec+nic-1; i++)
71868 : {
71869 :
71870 : /*
71871 : * Evaluate penalty function.
71872 : *
71873 : * Skip update if penalty is satisfied exactly (this check
71874 : * also covers situations when I-th row is exactly zero).
71875 : */
71876 0 : v = -state->scaledcleic.ptr.pp_double[i][n];
71877 0 : for(j=0; j<=n-1; j++)
71878 : {
71879 0 : v = v+state->scaledcleic.ptr.pp_double[i][j]*state->xc.ptr.p_double[j];
71880 : }
71881 0 : if( i<nec&&ae_fp_eq(v,(double)(0)) )
71882 : {
71883 0 : continue;
71884 : }
71885 0 : if( i>=nec&&ae_fp_less_eq(v,(double)(0)) )
71886 : {
71887 0 : continue;
71888 : }
71889 :
71890 : /*
71891 : * Calculate directional derivative, compare it with threshold.
71892 : *
71893 : * NOTE: we rely on the fact that ScaledCLEIC is normalized
71894 : */
71895 0 : ae_assert(ae_fp_greater(state->agspenaltylevel,1.0), "MinNS: integrity error", _state);
71896 0 : ae_assert(ae_fp_greater(state->agspenaltyincrease,state->agspenaltylevel), "MinNS: integrity error", _state);
71897 0 : v = 0.0;
71898 0 : for(j=0; j<=n-1; j++)
71899 : {
71900 0 : v = v+state->grs.ptr.p_double[j]*state->scaledcleic.ptr.pp_double[i][j];
71901 : }
71902 0 : v = ae_fabs(v, _state);
71903 0 : if( ae_fp_greater(v*state->agspenaltylevel,state->rholinear.ptr.p_double[i]) )
71904 : {
71905 0 : state->rholinear.ptr.p_double[i] = v*state->agspenaltyincrease;
71906 0 : restartneeded = ae_true;
71907 : }
71908 : }
71909 0 : if( restartneeded )
71910 : {
71911 0 : cursamplesize = 0;
71912 0 : goto lbl_4;
71913 : }
71914 :
71915 : /*
71916 : * Check stopping conditions.
71917 : */
71918 0 : if( radiusdecays>=state->agsmaxraddecays )
71919 : {
71920 :
71921 : /*
71922 : * Too many attempts to decrease radius
71923 : */
71924 0 : state->repterminationtype = 7;
71925 0 : goto lbl_5;
71926 : }
71927 0 : if( state->repinneriterationscount>=state->maxits&&state->maxits>0 )
71928 : {
71929 :
71930 : /*
71931 : * Too many iterations
71932 : */
71933 0 : state->repterminationtype = 5;
71934 0 : goto lbl_5;
71935 : }
71936 0 : if( ae_fp_less_eq(radius,state->epsx*state->agsraddecay) )
71937 : {
71938 :
71939 : /*
71940 : * Radius is smaller than required step tolerance multiplied by radius decay.
71941 : *
71942 : * Additional decay is required in order to make sure that optimization session
71943 : * with radius equal to EpsX was successfully done.
71944 : */
71945 0 : state->repterminationtype = 2;
71946 0 : goto lbl_5;
71947 : }
71948 :
71949 : /*
71950 : * Update sample:
71951 : *
71952 : * 1. invalidate entries which are too far away from XC
71953 : * and move all valid entries to beginning of the sample.
71954 : * 2. add new entries until we have AGSSampleSize
71955 : * items in our sample. We remove oldest entries from
71956 : * sample until we have enough place to add at least
71957 : * AGSMinUpdate items.
71958 : * 3. prepare "modified" gradient sample with respect to
71959 : * boundary constraints.
71960 : */
71961 0 : ae_assert(cursamplesize>=1, "MinNS: integrity check failed", _state);
71962 0 : k = 1;
71963 0 : for(i=1; i<=cursamplesize-1; i++)
71964 : {
71965 :
71966 : /*
71967 : * If entry is outside of Radius-ball around XC, discard it.
71968 : */
71969 0 : v = 0.0;
71970 0 : for(j=0; j<=n-1; j++)
71971 : {
71972 0 : v = ae_maxreal(v, ae_fabs(state->samplex.ptr.pp_double[i][j]-state->xc.ptr.p_double[j], _state), _state);
71973 : }
71974 0 : if( ae_fp_greater(v,radius) )
71975 : {
71976 0 : continue;
71977 : }
71978 :
71979 : /*
71980 : * If central point is exactly at boundary, and corresponding
71981 : * component of entry is OUT of boundary, entry is discarded.
71982 : */
71983 0 : b = ae_false;
71984 0 : for(j=0; j<=n-1; j++)
71985 : {
71986 0 : b = b||((state->hasbndl.ptr.p_bool[j]&&ae_fp_eq(state->xc.ptr.p_double[j],state->scaledbndl.ptr.p_double[j]))&&ae_fp_neq(state->samplex.ptr.pp_double[i][j],state->scaledbndl.ptr.p_double[j]));
71987 0 : b = b||((state->hasbndu.ptr.p_bool[j]&&ae_fp_eq(state->xc.ptr.p_double[j],state->scaledbndu.ptr.p_double[j]))&&ae_fp_neq(state->samplex.ptr.pp_double[i][j],state->scaledbndu.ptr.p_double[j]));
71988 : }
71989 0 : if( b )
71990 : {
71991 0 : continue;
71992 : }
71993 :
71994 : /*
71995 : * Move to the beginning
71996 : */
71997 0 : ae_v_move(&state->samplex.ptr.pp_double[k][0], 1, &state->samplex.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
71998 0 : ae_v_move(&state->samplegm.ptr.pp_double[k][0], 1, &state->samplegm.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
71999 0 : state->samplef.ptr.p_double[k] = state->samplef.ptr.p_double[i];
72000 0 : state->samplef0.ptr.p_double[k] = state->samplef0.ptr.p_double[i];
72001 0 : k = k+1;
72002 : }
72003 0 : cursamplesize = k;
72004 0 : if( state->agssamplesize-cursamplesize<state->agsminupdate )
72005 : {
72006 :
72007 : /*
72008 : * Remove oldest entries
72009 : */
72010 0 : k = state->agsminupdate-(state->agssamplesize-cursamplesize);
72011 0 : ae_assert(k<=cursamplesize-1, "MinNS: integrity check failed", _state);
72012 0 : for(i=1; i<=cursamplesize-k-1; i++)
72013 : {
72014 0 : ae_v_move(&state->samplex.ptr.pp_double[i][0], 1, &state->samplex.ptr.pp_double[i+k][0], 1, ae_v_len(0,n-1));
72015 0 : ae_v_move(&state->samplegm.ptr.pp_double[i][0], 1, &state->samplegm.ptr.pp_double[i+k][0], 1, ae_v_len(0,n-1));
72016 0 : state->samplef.ptr.p_double[i] = state->samplef.ptr.p_double[i+k];
72017 0 : state->samplef0.ptr.p_double[i] = state->samplef0.ptr.p_double[i+k];
72018 : }
72019 0 : cursamplesize = cursamplesize-k;
72020 : }
72021 0 : k = 0;
72022 0 : i = cursamplesize;
72023 0 : lbl_8:
72024 0 : if( i>ae_minint(cursamplesize+state->agsminupdate, state->agssamplesize, _state)-1 )
72025 : {
72026 0 : goto lbl_10;
72027 : }
72028 0 : for(j=0; j<=n-1; j++)
72029 : {
72030 :
72031 : /*
72032 : * Undistorted position
72033 : */
72034 0 : state->samplex.ptr.pp_double[i][j] = state->xc.ptr.p_double[j];
72035 :
72036 : /*
72037 : * Do not apply distortion, if we are exactly at boundary constraint.
72038 : */
72039 0 : if( (state->hasbndl.ptr.p_bool[j]&&state->hasbndu.ptr.p_bool[j])&&ae_fp_eq(state->scaledbndl.ptr.p_double[j],state->scaledbndu.ptr.p_double[j]) )
72040 : {
72041 0 : continue;
72042 : }
72043 0 : if( state->hasbndl.ptr.p_bool[j]&&ae_fp_eq(state->samplex.ptr.pp_double[i][j],state->scaledbndl.ptr.p_double[j]) )
72044 : {
72045 0 : continue;
72046 : }
72047 0 : if( state->hasbndu.ptr.p_bool[j]&&ae_fp_eq(state->samplex.ptr.pp_double[i][j],state->scaledbndu.ptr.p_double[j]) )
72048 : {
72049 0 : continue;
72050 : }
72051 :
72052 : /*
72053 : * Apply distortion
72054 : */
72055 0 : if( ae_fp_greater_eq(hqrnduniformr(&state->agsrs, _state),0.5) )
72056 : {
72057 :
72058 : /*
72059 : * Sample at the left side with 50% probability
72060 : */
72061 0 : v0 = state->samplex.ptr.pp_double[i][j]-radius;
72062 0 : v1 = state->samplex.ptr.pp_double[i][j];
72063 0 : if( state->hasbndl.ptr.p_bool[j] )
72064 : {
72065 0 : v0 = ae_maxreal(state->scaledbndl.ptr.p_double[j], v0, _state);
72066 : }
72067 : }
72068 : else
72069 : {
72070 :
72071 : /*
72072 : * Sample at the right side with 50% probability
72073 : */
72074 0 : v0 = state->samplex.ptr.pp_double[i][j];
72075 0 : v1 = state->samplex.ptr.pp_double[i][j]+radius;
72076 0 : if( state->hasbndu.ptr.p_bool[j] )
72077 : {
72078 0 : v1 = ae_minreal(state->scaledbndu.ptr.p_double[j], v1, _state);
72079 : }
72080 : }
72081 0 : ae_assert(ae_fp_greater_eq(v1,v0), "MinNS: integrity check failed", _state);
72082 0 : state->samplex.ptr.pp_double[i][j] = boundval(v0+(v1-v0)*hqrnduniformr(&state->agsrs, _state), v0, v1, _state);
72083 : }
72084 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->samplex.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
72085 0 : minns_unscalepointbc(state, &state->x, _state);
72086 0 : minns_clearrequestfields(state, _state);
72087 0 : state->needfij = ae_true;
72088 0 : state->rstateags.stage = 2;
72089 0 : goto lbl_rcomm;
72090 0 : lbl_2:
72091 0 : state->needfij = ae_false;
72092 0 : minns_generatemeritfunction(state, i, _state);
72093 0 : k = k+1;
72094 0 : i = i+1;
72095 0 : goto lbl_8;
72096 0 : lbl_10:
72097 0 : cursamplesize = cursamplesize+k;
72098 0 : fullsample = cursamplesize==state->agssamplesize;
72099 0 : for(j=0; j<=cursamplesize-1; j++)
72100 : {
72101 :
72102 : /*
72103 : * For J-th element in gradient sample, process all of its components
72104 : * and modify them according to status of box constraints
72105 : */
72106 0 : for(i=0; i<=n-1; i++)
72107 : {
72108 0 : ae_assert(!state->hasbndl.ptr.p_bool[i]||ae_fp_greater_eq(state->xc.ptr.p_double[i],state->scaledbndl.ptr.p_double[i]), "MinNS: integrity error", _state);
72109 0 : ae_assert(!state->hasbndu.ptr.p_bool[i]||ae_fp_less_eq(state->xc.ptr.p_double[i],state->scaledbndu.ptr.p_double[i]), "MinNS: integrity error", _state);
72110 0 : state->samplegmbc.ptr.pp_double[j][i] = state->samplegm.ptr.pp_double[j][i];
72111 0 : if( (state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i])&&ae_fp_eq(state->scaledbndl.ptr.p_double[i],state->scaledbndu.ptr.p_double[i]) )
72112 : {
72113 :
72114 : /*
72115 : * I-th box constraint is of equality type (lower bound matches upper one).
72116 : * Simplest case, always active.
72117 : */
72118 0 : state->samplegmbc.ptr.pp_double[j][i] = 0.0;
72119 0 : continue;
72120 : }
72121 0 : if( state->hasbndl.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->scaledbndl.ptr.p_double[i]) )
72122 : {
72123 :
72124 : /*
72125 : * We are at lower bound.
72126 : *
72127 : * A bit more complex:
72128 : * * first, we have to activate/deactivate constraint depending on gradient at XC
72129 : * * second, in any case, I-th column of gradient sample must be non-positive
72130 : */
72131 0 : if( ae_fp_greater_eq(state->samplegm.ptr.pp_double[0][i],0.0) )
72132 : {
72133 0 : state->samplegmbc.ptr.pp_double[j][i] = 0.0;
72134 : }
72135 0 : state->samplegmbc.ptr.pp_double[j][i] = ae_minreal(state->samplegmbc.ptr.pp_double[j][i], 0.0, _state);
72136 0 : continue;
72137 : }
72138 0 : if( state->hasbndu.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->scaledbndu.ptr.p_double[i]) )
72139 : {
72140 :
72141 : /*
72142 : * We are at upper bound.
72143 : *
72144 : * A bit more complex:
72145 : * * first, we have to activate/deactivate constraint depending on gradient at XC
72146 : * * second, in any case, I-th column of gradient sample must be non-negative
72147 : */
72148 0 : if( ae_fp_less_eq(state->samplegm.ptr.pp_double[0][i],0.0) )
72149 : {
72150 0 : state->samplegmbc.ptr.pp_double[j][i] = 0.0;
72151 : }
72152 0 : state->samplegmbc.ptr.pp_double[j][i] = ae_maxreal(state->samplegmbc.ptr.pp_double[j][i], 0.0, _state);
72153 0 : continue;
72154 : }
72155 : }
72156 : }
72157 :
72158 : /*
72159 : * Calculate diagonal Hessian.
72160 : *
72161 : * This Hessian serves two purposes:
72162 : * * first, it improves performance of gradient descent step
72163 : * * second, it improves condition number of QP subproblem
72164 : * solved to determine step
72165 : *
72166 : * The idea is that for each variable we check whether sample
72167 : * includes entries with alternating sign of gradient:
72168 : * * if gradients with different signs are present, Hessian
72169 : * component is set to M/R, where M is a maximum magnitude
72170 : * of corresponding gradient component, R is a sampling radius.
72171 : * Note that sign=0 and sign=1 are treated as different ones
72172 : * * if all gradients have same sign, Hessian component is
72173 : * set to M/R0, where R0 is initial sampling radius.
72174 : */
72175 0 : for(j=0; j<=n-1; j++)
72176 : {
72177 0 : state->colmax.ptr.p_double[j] = 0.0;
72178 0 : state->signmin.ptr.p_double[j] = (double)(1);
72179 0 : state->signmax.ptr.p_double[j] = (double)(-1);
72180 : }
72181 0 : for(i=0; i<=cursamplesize-1; i++)
72182 : {
72183 0 : for(j=0; j<=n-1; j++)
72184 : {
72185 0 : v = state->samplegmbc.ptr.pp_double[i][j];
72186 0 : state->colmax.ptr.p_double[j] = ae_maxreal(state->colmax.ptr.p_double[j], ae_fabs(v, _state), _state);
72187 0 : state->signmin.ptr.p_double[j] = ae_minreal(state->signmin.ptr.p_double[j], (double)(ae_sign(v, _state)), _state);
72188 0 : state->signmax.ptr.p_double[j] = ae_maxreal(state->signmax.ptr.p_double[j], (double)(ae_sign(v, _state)), _state);
72189 : }
72190 : }
72191 0 : for(j=0; j<=n-1; j++)
72192 : {
72193 0 : if( ae_fp_neq(state->signmin.ptr.p_double[j],state->signmax.ptr.p_double[j]) )
72194 : {
72195 :
72196 : /*
72197 : * Alternating signs of gradient - step is proportional to current sampling radius
72198 : */
72199 0 : ae_assert(ae_fp_neq(state->colmax.ptr.p_double[j],(double)(0)), "MinNS: integrity check failed", _state);
72200 0 : ae_assert(ae_fp_neq(radius,(double)(0)), "MinNS: integrity check failed", _state);
72201 0 : state->diagh.ptr.p_double[j] = state->colmax.ptr.p_double[j]/radius;
72202 0 : continue;
72203 : }
72204 0 : if( ae_fp_neq(state->colmax.ptr.p_double[j],(double)(0)) )
72205 : {
72206 :
72207 : /*
72208 : * Non-alternating sign of gradient, but non-zero.
72209 : * Step is proportional to initial sampling radius
72210 : */
72211 0 : ae_assert(ae_fp_neq(radius0,(double)(0)), "MinNS: integrity check failed", _state);
72212 0 : state->diagh.ptr.p_double[j] = state->colmax.ptr.p_double[j]/radius0;
72213 0 : continue;
72214 : }
72215 0 : state->diagh.ptr.p_double[j] = (double)(1);
72216 : }
72217 :
72218 : /*
72219 : * PROJECTION PHASE
72220 : *
72221 : * We project zero vector on convex hull of gradient sample.
72222 : * If projection is small enough, we decrease radius and restart.
72223 : * Otherwise, this phase returns search direction in State.D.
72224 : *
72225 : * NOTE: because we use iterative solver, it may have trouble
72226 : * dealing with ill-conditioned problems. So we also employ
72227 : * second, backup test for stationarity - when too many
72228 : * subsequent backtracking searches resulted in short steps.
72229 : */
72230 0 : minns_solveqp(&state->samplegmbc, &state->diagh, cursamplesize, n, &state->tmp0, &state->dbgncholesky, &state->nsqp, _state);
72231 0 : for(j=0; j<=n-1; j++)
72232 : {
72233 0 : state->d.ptr.p_double[j] = 0.0;
72234 : }
72235 0 : for(i=0; i<=cursamplesize-1; i++)
72236 : {
72237 0 : v = state->tmp0.ptr.p_double[i];
72238 0 : ae_v_addd(&state->d.ptr.p_double[0], 1, &state->samplegmbc.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v);
72239 : }
72240 0 : v = 0.0;
72241 0 : for(j=0; j<=n-1; j++)
72242 : {
72243 0 : v = ae_maxreal(v, ae_fabs(state->d.ptr.p_double[j]/coalesce(state->colmax.ptr.p_double[j], 1.0, _state), _state), _state);
72244 : }
72245 0 : if( ae_fp_less_eq(v,state->agsstattold) )
72246 : {
72247 :
72248 : /*
72249 : * Stationarity test succeded.
72250 : * Decrease radius and restart.
72251 : *
72252 : * NOTE: we also clear ShortStepsCnt on restart
72253 : */
72254 0 : radius = radius*state->agsraddecay;
72255 0 : shortstepscnt = 0;
72256 0 : inc(&radiusdecays, _state);
72257 0 : inc(&state->repinneriterationscount, _state);
72258 0 : goto lbl_4;
72259 : }
72260 0 : for(i=0; i<=n-1; i++)
72261 : {
72262 0 : state->d.ptr.p_double[i] = -state->d.ptr.p_double[i]/state->diagh.ptr.p_double[i];
72263 : }
72264 :
72265 : /*
72266 : * Perform backtracking line search.
72267 : * Update initial step length depending on search results.
72268 : * Here we assume that D is non-zero.
72269 : *
72270 : * NOTE: if AGSShortLimit subsequent line searches resulted
72271 : * in steps shorter than AGSStatTolStp, we decrease radius.
72272 : */
72273 0 : dnrm = 0.0;
72274 0 : dg = 0.0;
72275 0 : for(i=0; i<=n-1; i++)
72276 : {
72277 0 : dnrm = dnrm+ae_sqr(state->d.ptr.p_double[i], _state);
72278 0 : dg = dg+state->d.ptr.p_double[i]*state->samplegmbc.ptr.pp_double[0][i];
72279 : }
72280 0 : dnrm = ae_sqrt(dnrm, _state);
72281 0 : ae_assert(ae_fp_greater(dnrm,(double)(0)), "MinNS: integrity error", _state);
72282 0 : alpha = recommendedstep/dnrm;
72283 0 : alphadecreased = ae_false;
72284 0 : backtrackits = 0;
72285 0 : if( fullsample )
72286 : {
72287 0 : maxbacktrackits = state->agsmaxbacktrack;
72288 : }
72289 : else
72290 : {
72291 0 : maxbacktrackits = state->agsmaxbacktracknonfull;
72292 : }
72293 0 : lbl_11:
72294 : if( ae_false )
72295 : {
72296 : goto lbl_12;
72297 : }
72298 :
72299 : /*
72300 : * Prepare XN and evaluate merit function at XN
72301 : */
72302 0 : ae_v_move(&state->xn.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
72303 0 : ae_v_addd(&state->xn.ptr.p_double[0], 1, &state->d.ptr.p_double[0], 1, ae_v_len(0,n-1), alpha);
72304 0 : enforceboundaryconstraints(&state->xn, &state->scaledbndl, &state->hasbndl, &state->scaledbndu, &state->hasbndu, n, 0, _state);
72305 0 : ae_v_move(&state->samplex.ptr.pp_double[maxsamplesize][0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1));
72306 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1));
72307 0 : minns_unscalepointbc(state, &state->x, _state);
72308 0 : minns_clearrequestfields(state, _state);
72309 0 : state->needfij = ae_true;
72310 0 : state->rstateags.stage = 3;
72311 0 : goto lbl_rcomm;
72312 0 : lbl_3:
72313 0 : state->needfij = ae_false;
72314 0 : minns_generatemeritfunction(state, maxsamplesize, _state);
72315 :
72316 : /*
72317 : * Check sufficient decrease condition
72318 : */
72319 0 : ae_assert(ae_fp_greater(dnrm,(double)(0)), "MinNS: integrity error", _state);
72320 0 : if( ae_fp_less_eq(state->samplef.ptr.p_double[maxsamplesize],state->samplef.ptr.p_double[0]+alpha*state->agsdecrease*dg) )
72321 : {
72322 0 : goto lbl_12;
72323 : }
72324 :
72325 : /*
72326 : * Decrease Alpha
72327 : */
72328 0 : alpha = alpha*state->agsalphadecay;
72329 0 : alphadecreased = ae_true;
72330 :
72331 : /*
72332 : * Update and check iterations counter.
72333 : */
72334 0 : inc(&backtrackits, _state);
72335 0 : if( backtrackits>=maxbacktrackits )
72336 : {
72337 :
72338 : /*
72339 : * Too many backtracking searches performed without success.
72340 : * Terminate iterations.
72341 : */
72342 0 : alpha = 0.0;
72343 0 : alphadecreased = ae_true;
72344 0 : ae_v_move(&state->xn.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
72345 0 : goto lbl_12;
72346 : }
72347 0 : goto lbl_11;
72348 0 : lbl_12:
72349 0 : if( (ae_fp_less_eq(alpha*dnrm,state->agsshortstpabs)||ae_fp_less_eq(alpha*dnrm,state->agsshortstprel*radius))||ae_fp_less_eq(ae_fabs(state->samplef.ptr.p_double[0]-state->samplef.ptr.p_double[maxsamplesize], _state),state->agsshortf) )
72350 : {
72351 0 : inc(&shortstepscnt, _state);
72352 : }
72353 : else
72354 : {
72355 0 : shortstepscnt = 0;
72356 : }
72357 0 : if( shortstepscnt>=state->agsshortlimit )
72358 : {
72359 :
72360 : /*
72361 : * Too many subsequent short steps.
72362 : *
72363 : * It may be possible that optimizer is unable to find out
72364 : * that we have to decrease radius because of ill-conditioned
72365 : * gradients.
72366 : *
72367 : * Decrease radius and restart.
72368 : */
72369 0 : radius = radius*state->agsraddecay;
72370 0 : shortstepscnt = 0;
72371 0 : inc(&radiusdecays, _state);
72372 0 : inc(&state->repinneriterationscount, _state);
72373 0 : goto lbl_4;
72374 : }
72375 0 : if( !alphadecreased )
72376 : {
72377 0 : recommendedstep = recommendedstep*2.0;
72378 : }
72379 0 : if( alphadecreased&&fullsample )
72380 : {
72381 0 : recommendedstep = recommendedstep*0.5;
72382 : }
72383 :
72384 : /*
72385 : * Next iteration
72386 : */
72387 0 : ae_v_move(&state->xc.ptr.p_double[0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1));
72388 0 : inc(&state->repinneriterationscount, _state);
72389 0 : goto lbl_4;
72390 0 : lbl_5:
72391 :
72392 : /*
72393 : * Convert back from scaled to unscaled representation
72394 : */
72395 0 : minns_unscalepointbc(state, &state->xc, _state);
72396 0 : result = ae_false;
72397 0 : return result;
72398 :
72399 : /*
72400 : * Saving state
72401 : */
72402 0 : lbl_rcomm:
72403 0 : result = ae_true;
72404 0 : state->rstateags.ia.ptr.p_int[0] = n;
72405 0 : state->rstateags.ia.ptr.p_int[1] = nec;
72406 0 : state->rstateags.ia.ptr.p_int[2] = nic;
72407 0 : state->rstateags.ia.ptr.p_int[3] = ng;
72408 0 : state->rstateags.ia.ptr.p_int[4] = nh;
72409 0 : state->rstateags.ia.ptr.p_int[5] = i;
72410 0 : state->rstateags.ia.ptr.p_int[6] = j;
72411 0 : state->rstateags.ia.ptr.p_int[7] = k;
72412 0 : state->rstateags.ia.ptr.p_int[8] = radiusdecays;
72413 0 : state->rstateags.ia.ptr.p_int[9] = maxsamplesize;
72414 0 : state->rstateags.ia.ptr.p_int[10] = cursamplesize;
72415 0 : state->rstateags.ia.ptr.p_int[11] = shortstepscnt;
72416 0 : state->rstateags.ia.ptr.p_int[12] = backtrackits;
72417 0 : state->rstateags.ia.ptr.p_int[13] = maxbacktrackits;
72418 0 : state->rstateags.ba.ptr.p_bool[0] = restartneeded;
72419 0 : state->rstateags.ba.ptr.p_bool[1] = b;
72420 0 : state->rstateags.ba.ptr.p_bool[2] = alphadecreased;
72421 0 : state->rstateags.ba.ptr.p_bool[3] = fullsample;
72422 0 : state->rstateags.ra.ptr.p_double[0] = radius0;
72423 0 : state->rstateags.ra.ptr.p_double[1] = radius;
72424 0 : state->rstateags.ra.ptr.p_double[2] = alpha;
72425 0 : state->rstateags.ra.ptr.p_double[3] = recommendedstep;
72426 0 : state->rstateags.ra.ptr.p_double[4] = dnrm;
72427 0 : state->rstateags.ra.ptr.p_double[5] = dg;
72428 0 : state->rstateags.ra.ptr.p_double[6] = v;
72429 0 : state->rstateags.ra.ptr.p_double[7] = vv;
72430 0 : state->rstateags.ra.ptr.p_double[8] = v0;
72431 0 : state->rstateags.ra.ptr.p_double[9] = v1;
72432 0 : return result;
72433 : }
72434 :
72435 :
72436 : /*************************************************************************
72437 : This function calculates merit function (target function + penalties for
72438 : violation of non-box constraints), using State.X (unscaled), State.Fi,
72439 : State.J (unscaled) and State.SampleX (scaled) as inputs.
72440 :
72441 : Results are loaded:
72442 : * target function value - to State.SampleF0[SampleIdx]
72443 : * merit function value - to State.SampleF[SampleIdx]
72444 : * gradient of merit function - to State.SampleGM[SampleIdx]
72445 :
72446 : -- ALGLIB --
72447 : Copyright 02.06.2015 by Bochkanov Sergey
72448 : *************************************************************************/
72449 0 : static void minns_generatemeritfunction(minnsstate* state,
72450 : ae_int_t sampleidx,
72451 : ae_state *_state)
72452 : {
72453 : ae_int_t n;
72454 : ae_int_t i;
72455 : ae_int_t j;
72456 : ae_int_t nec;
72457 : ae_int_t nic;
72458 : ae_int_t ng;
72459 : ae_int_t nh;
72460 : double v;
72461 : double s;
72462 :
72463 :
72464 0 : n = state->n;
72465 0 : nec = state->nec;
72466 0 : nic = state->nic;
72467 0 : ng = state->ng;
72468 0 : nh = state->nh;
72469 :
72470 : /*
72471 : * Integrity check
72472 : */
72473 0 : for(i=0; i<=n-1; i++)
72474 : {
72475 0 : ae_assert(!state->hasbndl.ptr.p_bool[i]||ae_fp_greater_eq(state->x.ptr.p_double[i],state->bndl.ptr.p_double[i]), "MinNS: integrity error", _state);
72476 0 : ae_assert(!state->hasbndu.ptr.p_bool[i]||ae_fp_less_eq(state->x.ptr.p_double[i],state->bndu.ptr.p_double[i]), "MinNS: integrity error", _state);
72477 : }
72478 :
72479 : /*
72480 : * Prepare "raw" function
72481 : */
72482 0 : state->samplef.ptr.p_double[sampleidx] = state->fi.ptr.p_double[0];
72483 0 : state->samplef0.ptr.p_double[sampleidx] = state->fi.ptr.p_double[0];
72484 0 : for(j=0; j<=n-1; j++)
72485 : {
72486 0 : state->samplegm.ptr.pp_double[sampleidx][j] = state->j.ptr.pp_double[0][j]*state->s.ptr.p_double[j];
72487 : }
72488 :
72489 : /*
72490 : * Modify merit function with linear constraints
72491 : */
72492 0 : for(i=0; i<=nec+nic-1; i++)
72493 : {
72494 0 : v = -state->scaledcleic.ptr.pp_double[i][n];
72495 0 : for(j=0; j<=n-1; j++)
72496 : {
72497 0 : v = v+state->scaledcleic.ptr.pp_double[i][j]*state->samplex.ptr.pp_double[sampleidx][j];
72498 : }
72499 0 : if( i>=nec&&ae_fp_less(v,(double)(0)) )
72500 : {
72501 0 : continue;
72502 : }
72503 0 : state->samplef.ptr.p_double[sampleidx] = state->samplef.ptr.p_double[sampleidx]+state->rholinear.ptr.p_double[i]*ae_fabs(v, _state);
72504 0 : s = (double)(ae_sign(v, _state));
72505 0 : for(j=0; j<=n-1; j++)
72506 : {
72507 0 : state->samplegm.ptr.pp_double[sampleidx][j] = state->samplegm.ptr.pp_double[sampleidx][j]+state->rholinear.ptr.p_double[i]*s*state->scaledcleic.ptr.pp_double[i][j];
72508 : }
72509 : }
72510 :
72511 : /*
72512 : * Modify merit function with nonlinear constraints
72513 : */
72514 0 : for(i=1; i<=ng+nh; i++)
72515 : {
72516 0 : v = state->fi.ptr.p_double[i];
72517 0 : if( i<=ng&&ae_fp_eq(v,(double)(0)) )
72518 : {
72519 0 : continue;
72520 : }
72521 0 : if( i>ng&&ae_fp_less_eq(v,(double)(0)) )
72522 : {
72523 0 : continue;
72524 : }
72525 0 : state->samplef.ptr.p_double[sampleidx] = state->samplef.ptr.p_double[sampleidx]+state->agsrhononlinear*ae_fabs(v, _state);
72526 0 : s = (double)(ae_sign(v, _state));
72527 0 : for(j=0; j<=n-1; j++)
72528 : {
72529 0 : state->samplegm.ptr.pp_double[sampleidx][j] = state->samplegm.ptr.pp_double[sampleidx][j]+state->agsrhononlinear*s*state->j.ptr.pp_double[i][j]*state->s.ptr.p_double[j];
72530 : }
72531 : }
72532 0 : }
72533 :
72534 :
72535 : /*************************************************************************
72536 : This function performs transformation of X from scaled coordinates to
72537 : unscaled ones, paying special attention to box constraints:
72538 : * points which were exactly at the boundary before scaling will be mapped
72539 : to corresponding boundary after scaling
72540 : * in any case, unscaled box constraints will be satisfied
72541 :
72542 : -- ALGLIB --
72543 : Copyright 02.06.2015 by Bochkanov Sergey
72544 : *************************************************************************/
72545 0 : static void minns_unscalepointbc(minnsstate* state,
72546 : /* Real */ ae_vector* x,
72547 : ae_state *_state)
72548 : {
72549 : ae_int_t i;
72550 :
72551 :
72552 0 : for(i=0; i<=state->n-1; i++)
72553 : {
72554 0 : if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less_eq(x->ptr.p_double[i],state->scaledbndl.ptr.p_double[i]) )
72555 : {
72556 0 : x->ptr.p_double[i] = state->bndl.ptr.p_double[i];
72557 0 : continue;
72558 : }
72559 0 : if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater_eq(x->ptr.p_double[i],state->scaledbndu.ptr.p_double[i]) )
72560 : {
72561 0 : x->ptr.p_double[i] = state->bndu.ptr.p_double[i];
72562 0 : continue;
72563 : }
72564 0 : x->ptr.p_double[i] = x->ptr.p_double[i]*state->s.ptr.p_double[i];
72565 0 : if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less_eq(x->ptr.p_double[i],state->bndl.ptr.p_double[i]) )
72566 : {
72567 0 : x->ptr.p_double[i] = state->bndl.ptr.p_double[i];
72568 : }
72569 0 : if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater_eq(x->ptr.p_double[i],state->bndu.ptr.p_double[i]) )
72570 : {
72571 0 : x->ptr.p_double[i] = state->bndu.ptr.p_double[i];
72572 : }
72573 : }
72574 0 : }
72575 :
72576 :
72577 : /*************************************************************************
72578 : This function solves QP problem of the form
72579 :
72580 : [ ]
72581 : min [ 0.5*c'*(G*inv(H)*G')*c ] s.t. c[i]>=0, SUM(c[i])=1.0
72582 : [ ]
72583 :
72584 : where G is stored in SampleG[] array, diagonal H is stored in DiagH[].
72585 :
72586 : DbgNCholesky is incremented every time we perform Cholesky decomposition.
72587 :
72588 : -- ALGLIB --
72589 : Copyright 02.06.2015 by Bochkanov Sergey
72590 : *************************************************************************/
72591 0 : static void minns_solveqp(/* Real */ ae_matrix* sampleg,
72592 : /* Real */ ae_vector* diagh,
72593 : ae_int_t nsample,
72594 : ae_int_t nvars,
72595 : /* Real */ ae_vector* coeffs,
72596 : ae_int_t* dbgncholesky,
72597 : minnsqp* state,
72598 : ae_state *_state)
72599 : {
72600 : ae_int_t i;
72601 : ae_int_t j;
72602 : ae_int_t k;
72603 : double v;
72604 : double vv;
72605 : ae_int_t n;
72606 : ae_int_t idx0;
72607 : ae_int_t idx1;
72608 : ae_int_t ncandbnd;
72609 : ae_int_t innerits;
72610 : ae_int_t outerits;
72611 : double dnrm;
72612 : double stp;
72613 : double stpmax;
72614 : ae_int_t actidx;
72615 : double dtol;
72616 : ae_bool kickneeded;
72617 : double kicklength;
72618 : double lambdav;
72619 : double maxdiag;
72620 : ae_bool wasactivation;
72621 : ae_bool werechanges;
72622 : ae_int_t termcnt;
72623 :
72624 :
72625 0 : n = nsample;
72626 :
72627 : /*
72628 : * Allocate arrays, prepare data
72629 : */
72630 0 : rvectorsetlengthatleast(coeffs, n, _state);
72631 0 : rvectorsetlengthatleast(&state->xc, n, _state);
72632 0 : rvectorsetlengthatleast(&state->xn, n, _state);
72633 0 : rvectorsetlengthatleast(&state->x0, n, _state);
72634 0 : rvectorsetlengthatleast(&state->gc, n, _state);
72635 0 : rvectorsetlengthatleast(&state->d, n, _state);
72636 0 : rmatrixsetlengthatleast(&state->uh, n, n, _state);
72637 0 : rmatrixsetlengthatleast(&state->ch, n, n, _state);
72638 0 : rmatrixsetlengthatleast(&state->rk, nsample, nvars, _state);
72639 0 : rvectorsetlengthatleast(&state->invutc, n, _state);
72640 0 : rvectorsetlengthatleast(&state->tmp0, n, _state);
72641 0 : bvectorsetlengthatleast(&state->tmpb, n, _state);
72642 0 : for(i=0; i<=n-1; i++)
72643 : {
72644 0 : state->xc.ptr.p_double[i] = 1.0/n;
72645 0 : coeffs->ptr.p_double[i] = 1.0/n;
72646 : }
72647 0 : for(i=0; i<=nsample-1; i++)
72648 : {
72649 0 : for(j=0; j<=nvars-1; j++)
72650 : {
72651 0 : state->rk.ptr.pp_double[i][j] = sampleg->ptr.pp_double[i][j]/ae_sqrt(diagh->ptr.p_double[j], _state);
72652 : }
72653 : }
72654 0 : rmatrixsyrk(nsample, nvars, 1.0, &state->rk, 0, 0, 0, 0.0, &state->uh, 0, 0, ae_true, _state);
72655 0 : maxdiag = 0.0;
72656 0 : for(i=0; i<=nsample-1; i++)
72657 : {
72658 0 : maxdiag = ae_maxreal(maxdiag, state->uh.ptr.pp_double[i][i], _state);
72659 : }
72660 0 : maxdiag = coalesce(maxdiag, 1.0, _state);
72661 :
72662 : /*
72663 : * Main cycle:
72664 : */
72665 0 : innerits = 0;
72666 0 : outerits = 0;
72667 0 : dtol = 1.0E5*ae_machineepsilon;
72668 0 : kicklength = ae_machineepsilon;
72669 0 : lambdav = 1.0E5*ae_machineepsilon;
72670 0 : termcnt = 0;
72671 : for(;;)
72672 : {
72673 :
72674 : /*
72675 : * Save current point to X0
72676 : */
72677 0 : ae_v_move(&state->x0.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
72678 :
72679 : /*
72680 : * Calculate gradient at initial point, solve NNLS problem
72681 : * to determine descent direction D subject to constraints.
72682 : *
72683 : * In order to do so we solve following constrained
72684 : * minimization problem:
72685 : * ( )^2
72686 : * min ( SUM(lambda[i]*A[i]) + G )
72687 : * ( )
72688 : * Here:
72689 : * * G is a gradient (column vector)
72690 : * * A[i] is a column vector of I-th constraint
72691 : * * lambda[i] is a Lagrange multiplier corresponding to I-th constraint
72692 : *
72693 : * NOTE: all A[i] except for last one have only one element being set,
72694 : * so we rely on sparse capabilities of NNLS solver. However,
72695 : * in order to use these capabilities we have to reorder variables
72696 : * in such way that sparse ones come first.
72697 : *
72698 : * After finding lambda[] coefficients, we can find constrained descent
72699 : * direction by subtracting lambda[i]*A[i] from D=-G. We make use of the
72700 : * fact that first NCandBnd columns are just columns of identity matrix,
72701 : * so we can perform exact projection by explicitly setting elements of D
72702 : * to zeros.
72703 : */
72704 0 : minns_qpcalculategradfunc(sampleg, diagh, nsample, nvars, &state->xc, &state->gc, &state->fc, &state->tmp0, _state);
72705 0 : ivectorsetlengthatleast(&state->tmpidx, n, _state);
72706 0 : rvectorsetlengthatleast(&state->tmpd, n, _state);
72707 0 : rmatrixsetlengthatleast(&state->tmpc2, n, 1, _state);
72708 0 : idx0 = 0;
72709 0 : ncandbnd = 0;
72710 0 : for(i=0; i<=n-1; i++)
72711 : {
72712 0 : if( ae_fp_eq(state->xc.ptr.p_double[i],0.0) )
72713 : {
72714 0 : ncandbnd = ncandbnd+1;
72715 : }
72716 : }
72717 0 : idx1 = ncandbnd;
72718 0 : for(i=0; i<=n-1; i++)
72719 : {
72720 0 : if( ae_fp_eq(state->xc.ptr.p_double[i],0.0) )
72721 : {
72722 :
72723 : /*
72724 : * Candidate for activation of boundary constraint,
72725 : * comes first.
72726 : *
72727 : * NOTE: multiplication by -1 is due to the fact that
72728 : * it is lower bound, and has specific direction
72729 : * of constraint gradient.
72730 : */
72731 0 : state->tmpidx.ptr.p_int[idx0] = i;
72732 0 : state->tmpd.ptr.p_double[idx0] = (-state->gc.ptr.p_double[i])*(-1);
72733 0 : state->tmpc2.ptr.pp_double[idx0][0] = 1.0*(-1);
72734 0 : idx0 = idx0+1;
72735 : }
72736 : else
72737 : {
72738 :
72739 : /*
72740 : * We are far away from boundary.
72741 : */
72742 0 : state->tmpidx.ptr.p_int[idx1] = i;
72743 0 : state->tmpd.ptr.p_double[idx1] = -state->gc.ptr.p_double[i];
72744 0 : state->tmpc2.ptr.pp_double[idx1][0] = 1.0;
72745 0 : idx1 = idx1+1;
72746 : }
72747 : }
72748 0 : ae_assert(idx0==ncandbnd, "MinNSQP: integrity check failed", _state);
72749 0 : ae_assert(idx1==n, "MinNSQP: integrity check failed", _state);
72750 0 : snnlsinit(n, 1, n, &state->nnls, _state);
72751 0 : snnlssetproblem(&state->nnls, &state->tmpc2, &state->tmpd, ncandbnd, 1, n, _state);
72752 0 : snnlsdropnnc(&state->nnls, ncandbnd, _state);
72753 0 : snnlssolve(&state->nnls, &state->tmplambdas, _state);
72754 0 : for(i=0; i<=n-1; i++)
72755 : {
72756 0 : state->d.ptr.p_double[i] = -state->gc.ptr.p_double[i]-state->tmplambdas.ptr.p_double[ncandbnd];
72757 : }
72758 0 : for(i=0; i<=ncandbnd-1; i++)
72759 : {
72760 0 : if( ae_fp_greater(state->tmplambdas.ptr.p_double[i],(double)(0)) )
72761 : {
72762 0 : state->d.ptr.p_double[state->tmpidx.ptr.p_int[i]] = 0.0;
72763 : }
72764 : }
72765 :
72766 : /*
72767 : * Additional stage to "polish" D (improve situation
72768 : * with sum-to-one constraint and boundary constraints)
72769 : * and to perform additional integrity check.
72770 : *
72771 : * After this stage we are pretty sure that:
72772 : * * if x[i]=0.0, then d[i]>=0.0
72773 : * * if d[i]<0.0, then x[i]>0.0
72774 : */
72775 0 : v = 0.0;
72776 0 : vv = 0.0;
72777 0 : for(i=0; i<=n-1; i++)
72778 : {
72779 0 : if( ae_fp_eq(state->xc.ptr.p_double[i],0.0)&&ae_fp_less(state->d.ptr.p_double[i],0.0) )
72780 : {
72781 0 : state->d.ptr.p_double[i] = 0.0;
72782 : }
72783 0 : v = v+state->d.ptr.p_double[i];
72784 0 : vv = ae_maxreal(vv, ae_fabs(state->gc.ptr.p_double[i], _state), _state);
72785 : }
72786 0 : ae_assert(ae_fp_less(ae_fabs(v, _state),1.0E5*ae_sqrt((double)(n), _state)*ae_machineepsilon*ae_maxreal(vv, 1.0, _state)), "MinNSQP: integrity check failed", _state);
72787 :
72788 : /*
72789 : * Decide whether we need "kick" stage: special stage
72790 : * that moves us away from boundary constraints which are
72791 : * not strictly active (i.e. such constraints that x[i]=0.0 and d[i]>0).
72792 : *
72793 : * If we need kick stage, we make a kick - and restart iteration.
72794 : * If not, after this block we can rely on the fact that
72795 : * for all x[i]=0.0 we have d[i]=0.0
72796 : */
72797 0 : kickneeded = ae_false;
72798 0 : for(i=0; i<=n-1; i++)
72799 : {
72800 0 : if( ae_fp_eq(state->xc.ptr.p_double[i],0.0)&&ae_fp_greater(state->d.ptr.p_double[i],0.0) )
72801 : {
72802 0 : kickneeded = ae_true;
72803 : }
72804 : }
72805 0 : if( kickneeded )
72806 : {
72807 :
72808 : /*
72809 : * Perform kick.
72810 : * Restart.
72811 : * Do not increase outer iterations counter.
72812 : */
72813 0 : v = 0.0;
72814 0 : for(i=0; i<=n-1; i++)
72815 : {
72816 0 : if( ae_fp_eq(state->xc.ptr.p_double[i],0.0)&&ae_fp_greater(state->d.ptr.p_double[i],0.0) )
72817 : {
72818 0 : state->xc.ptr.p_double[i] = state->xc.ptr.p_double[i]+kicklength;
72819 : }
72820 0 : v = v+state->xc.ptr.p_double[i];
72821 : }
72822 0 : ae_assert(ae_fp_greater(v,0.0), "MinNSQP: integrity check failed", _state);
72823 0 : for(i=0; i<=n-1; i++)
72824 : {
72825 0 : state->xc.ptr.p_double[i] = state->xc.ptr.p_double[i]/v;
72826 : }
72827 0 : inc(&innerits, _state);
72828 0 : continue;
72829 : }
72830 :
72831 : /*
72832 : * Calculate Cholesky decomposition of constrained Hessian
72833 : * for Newton phase.
72834 : */
72835 : for(;;)
72836 : {
72837 0 : for(i=0; i<=n-1; i++)
72838 : {
72839 :
72840 : /*
72841 : * Diagonal element
72842 : */
72843 0 : if( ae_fp_greater(state->xc.ptr.p_double[i],0.0) )
72844 : {
72845 0 : state->ch.ptr.pp_double[i][i] = state->uh.ptr.pp_double[i][i]+lambdav*maxdiag;
72846 : }
72847 : else
72848 : {
72849 0 : state->ch.ptr.pp_double[i][i] = 1.0;
72850 : }
72851 :
72852 : /*
72853 : * Offdiagonal elements
72854 : */
72855 0 : for(j=i+1; j<=n-1; j++)
72856 : {
72857 0 : if( ae_fp_greater(state->xc.ptr.p_double[i],0.0)&&ae_fp_greater(state->xc.ptr.p_double[j],0.0) )
72858 : {
72859 0 : state->ch.ptr.pp_double[i][j] = state->uh.ptr.pp_double[i][j];
72860 : }
72861 : else
72862 : {
72863 0 : state->ch.ptr.pp_double[i][j] = 0.0;
72864 : }
72865 : }
72866 : }
72867 0 : inc(dbgncholesky, _state);
72868 0 : if( !spdmatrixcholeskyrec(&state->ch, 0, n, ae_true, &state->tmp0, _state) )
72869 : {
72870 :
72871 : /*
72872 : * Cholesky decomposition failed.
72873 : * Increase LambdaV and repeat iteration.
72874 : * Do not increase outer iterations counter.
72875 : */
72876 0 : lambdav = lambdav*10;
72877 0 : continue;
72878 : }
72879 0 : break;
72880 : }
72881 :
72882 : /*
72883 : * Newton phase
72884 : */
72885 : for(;;)
72886 : {
72887 :
72888 : /*
72889 : * Calculate constrained (equality and sum-to-one) descent direction D.
72890 : *
72891 : * Here we use Sherman-Morrison update to calculate direction subject to
72892 : * sum-to-one constraint.
72893 : */
72894 0 : minns_qpcalculategradfunc(sampleg, diagh, nsample, nvars, &state->xc, &state->gc, &state->fc, &state->tmp0, _state);
72895 0 : for(i=0; i<=n-1; i++)
72896 : {
72897 0 : if( ae_fp_greater(state->xc.ptr.p_double[i],0.0) )
72898 : {
72899 0 : state->invutc.ptr.p_double[i] = 1.0;
72900 0 : state->d.ptr.p_double[i] = -state->gc.ptr.p_double[i];
72901 : }
72902 : else
72903 : {
72904 0 : state->invutc.ptr.p_double[i] = 0.0;
72905 0 : state->d.ptr.p_double[i] = 0.0;
72906 : }
72907 : }
72908 0 : minns_qpsolveut(&state->ch, n, &state->invutc, _state);
72909 0 : minns_qpsolveut(&state->ch, n, &state->d, _state);
72910 0 : v = 0.0;
72911 0 : vv = 0.0;
72912 0 : for(i=0; i<=n-1; i++)
72913 : {
72914 0 : vv = vv+ae_sqr(state->invutc.ptr.p_double[i], _state);
72915 0 : v = v+state->invutc.ptr.p_double[i]*state->d.ptr.p_double[i];
72916 : }
72917 0 : for(i=0; i<=n-1; i++)
72918 : {
72919 0 : state->d.ptr.p_double[i] = state->d.ptr.p_double[i]-v/vv*state->invutc.ptr.p_double[i];
72920 : }
72921 0 : minns_qpsolveu(&state->ch, n, &state->d, _state);
72922 0 : v = 0.0;
72923 0 : k = 0;
72924 0 : for(i=0; i<=n-1; i++)
72925 : {
72926 0 : v = v+state->d.ptr.p_double[i];
72927 0 : if( ae_fp_neq(state->d.ptr.p_double[i],0.0) )
72928 : {
72929 0 : k = k+1;
72930 : }
72931 : }
72932 0 : if( k>0&&ae_fp_greater(v,0.0) )
72933 : {
72934 0 : vv = v/k;
72935 0 : for(i=0; i<=n-1; i++)
72936 : {
72937 0 : if( ae_fp_neq(state->d.ptr.p_double[i],0.0) )
72938 : {
72939 0 : state->d.ptr.p_double[i] = state->d.ptr.p_double[i]-vv;
72940 : }
72941 : }
72942 : }
72943 :
72944 : /*
72945 : * Calculate length of D, maximum step and component which is
72946 : * activated by this step.
72947 : *
72948 : * Break if D is exactly zero. We do not break here if DNrm is
72949 : * small - this check is performed later. It is important to
72950 : * perform last step with nearly-zero D, it allows us to have
72951 : * extra-precision in solution which is often needed for convergence
72952 : * of AGS algorithm.
72953 : */
72954 0 : dnrm = 0.0;
72955 0 : for(i=0; i<=n-1; i++)
72956 : {
72957 0 : dnrm = dnrm+ae_sqr(state->d.ptr.p_double[i], _state);
72958 : }
72959 0 : dnrm = ae_sqrt(dnrm, _state);
72960 0 : actidx = -1;
72961 0 : stpmax = 1.0E50;
72962 0 : for(i=0; i<=n-1; i++)
72963 : {
72964 0 : if( ae_fp_less(state->d.ptr.p_double[i],0.0) )
72965 : {
72966 0 : v = stpmax;
72967 0 : stpmax = safeminposrv(state->xc.ptr.p_double[i], -state->d.ptr.p_double[i], stpmax, _state);
72968 0 : if( ae_fp_less(stpmax,v) )
72969 : {
72970 0 : actidx = i;
72971 : }
72972 : }
72973 : }
72974 0 : if( ae_fp_eq(dnrm,0.0) )
72975 : {
72976 0 : break;
72977 : }
72978 :
72979 : /*
72980 : * Calculate trial function value at unconstrained full step.
72981 : * If trial value is greater or equal to FC, terminate iterations.
72982 : */
72983 0 : for(i=0; i<=n-1; i++)
72984 : {
72985 0 : state->xn.ptr.p_double[i] = state->xc.ptr.p_double[i]+1.0*state->d.ptr.p_double[i];
72986 : }
72987 0 : minns_qpcalculatefunc(sampleg, diagh, nsample, nvars, &state->xn, &state->fn, &state->tmp0, _state);
72988 0 : if( ae_fp_greater_eq(state->fn,state->fc) )
72989 : {
72990 0 : break;
72991 : }
72992 :
72993 : /*
72994 : * Perform step
72995 : * Update Hessian
72996 : * Update XC
72997 : *
72998 : * Break if:
72999 : * a) no constraint was activated
73000 : * b) norm of D is small enough
73001 : */
73002 0 : stp = ae_minreal(1.0, stpmax, _state);
73003 0 : for(i=0; i<=n-1; i++)
73004 : {
73005 0 : state->xn.ptr.p_double[i] = ae_maxreal(state->xc.ptr.p_double[i]+stp*state->d.ptr.p_double[i], 0.0, _state);
73006 : }
73007 0 : if( ae_fp_eq(stp,stpmax)&&actidx>=0 )
73008 : {
73009 0 : state->xn.ptr.p_double[actidx] = 0.0;
73010 : }
73011 0 : wasactivation = ae_false;
73012 0 : for(i=0; i<=n-1; i++)
73013 : {
73014 0 : state->tmpb.ptr.p_bool[i] = ae_fp_eq(state->xn.ptr.p_double[i],0.0)&&ae_fp_neq(state->xc.ptr.p_double[i],0.0);
73015 0 : wasactivation = wasactivation||state->tmpb.ptr.p_bool[i];
73016 : }
73017 0 : ae_v_move(&state->xc.ptr.p_double[0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1));
73018 0 : if( !wasactivation )
73019 : {
73020 0 : break;
73021 : }
73022 0 : if( ae_fp_less_eq(dnrm,dtol) )
73023 : {
73024 0 : break;
73025 : }
73026 0 : spdmatrixcholeskyupdatefixbuf(&state->ch, n, ae_true, &state->tmpb, &state->tmp0, _state);
73027 : }
73028 :
73029 : /*
73030 : * Compare status of boundary constraints - if nothing changed during
73031 : * last outer iteration, TermCnt is increased. Otherwise it is reset
73032 : * to zero.
73033 : *
73034 : * When TermCnt is large enough, we terminate algorithm.
73035 : */
73036 0 : werechanges = ae_false;
73037 0 : for(i=0; i<=n-1; i++)
73038 : {
73039 0 : werechanges = werechanges||ae_sign(state->x0.ptr.p_double[i], _state)!=ae_sign(state->xc.ptr.p_double[i], _state);
73040 : }
73041 0 : if( !werechanges )
73042 : {
73043 0 : inc(&termcnt, _state);
73044 : }
73045 : else
73046 : {
73047 0 : termcnt = 0;
73048 : }
73049 0 : if( termcnt>=2 )
73050 : {
73051 0 : break;
73052 : }
73053 :
73054 : /*
73055 : * Increase number of outer iterations.
73056 : * Break if we performed too many.
73057 : */
73058 0 : inc(&outerits, _state);
73059 0 : if( outerits==10 )
73060 : {
73061 0 : break;
73062 : }
73063 : }
73064 :
73065 : /*
73066 : * Store result
73067 : */
73068 0 : for(i=0; i<=n-1; i++)
73069 : {
73070 0 : coeffs->ptr.p_double[i] = state->xc.ptr.p_double[i];
73071 : }
73072 0 : }
73073 :
73074 :
73075 : /*************************************************************************
73076 : Function/gradient calculation for QP solver.
73077 :
73078 : -- ALGLIB --
73079 : Copyright 02.06.2015 by Bochkanov Sergey
73080 : *************************************************************************/
73081 0 : static void minns_qpcalculategradfunc(/* Real */ ae_matrix* sampleg,
73082 : /* Real */ ae_vector* diagh,
73083 : ae_int_t nsample,
73084 : ae_int_t nvars,
73085 : /* Real */ ae_vector* coeffs,
73086 : /* Real */ ae_vector* g,
73087 : double* f,
73088 : /* Real */ ae_vector* tmp,
73089 : ae_state *_state)
73090 : {
73091 : ae_int_t i;
73092 : ae_int_t j;
73093 : double v;
73094 :
73095 0 : *f = 0;
73096 :
73097 0 : rvectorsetlengthatleast(g, nsample, _state);
73098 0 : rvectorsetlengthatleast(tmp, nvars, _state);
73099 :
73100 : /*
73101 : * Calculate GS*p
73102 : */
73103 0 : for(j=0; j<=nvars-1; j++)
73104 : {
73105 0 : tmp->ptr.p_double[j] = 0.0;
73106 : }
73107 0 : for(i=0; i<=nsample-1; i++)
73108 : {
73109 0 : v = coeffs->ptr.p_double[i];
73110 0 : ae_v_addd(&tmp->ptr.p_double[0], 1, &sampleg->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1), v);
73111 : }
73112 :
73113 : /*
73114 : * Calculate F
73115 : */
73116 0 : *f = 0.0;
73117 0 : for(i=0; i<=nvars-1; i++)
73118 : {
73119 0 : *f = *f+0.5*ae_sqr(tmp->ptr.p_double[i], _state)/diagh->ptr.p_double[i];
73120 : }
73121 :
73122 : /*
73123 : * Multiply by inverse Hessian
73124 : */
73125 0 : for(i=0; i<=nvars-1; i++)
73126 : {
73127 0 : tmp->ptr.p_double[i] = tmp->ptr.p_double[i]/diagh->ptr.p_double[i];
73128 : }
73129 :
73130 : /*
73131 : * Function gradient
73132 : */
73133 0 : for(i=0; i<=nsample-1; i++)
73134 : {
73135 0 : v = ae_v_dotproduct(&sampleg->ptr.pp_double[i][0], 1, &tmp->ptr.p_double[0], 1, ae_v_len(0,nvars-1));
73136 0 : g->ptr.p_double[i] = v;
73137 : }
73138 0 : }
73139 :
73140 :
73141 : /*************************************************************************
73142 : Function calculation for QP solver.
73143 :
73144 : -- ALGLIB --
73145 : Copyright 02.06.2015 by Bochkanov Sergey
73146 : *************************************************************************/
73147 0 : static void minns_qpcalculatefunc(/* Real */ ae_matrix* sampleg,
73148 : /* Real */ ae_vector* diagh,
73149 : ae_int_t nsample,
73150 : ae_int_t nvars,
73151 : /* Real */ ae_vector* coeffs,
73152 : double* f,
73153 : /* Real */ ae_vector* tmp,
73154 : ae_state *_state)
73155 : {
73156 : ae_int_t i;
73157 : ae_int_t j;
73158 : double v;
73159 :
73160 0 : *f = 0;
73161 :
73162 0 : rvectorsetlengthatleast(tmp, nvars, _state);
73163 :
73164 : /*
73165 : * Calculate GS*p
73166 : */
73167 0 : for(j=0; j<=nvars-1; j++)
73168 : {
73169 0 : tmp->ptr.p_double[j] = 0.0;
73170 : }
73171 0 : for(i=0; i<=nsample-1; i++)
73172 : {
73173 0 : v = coeffs->ptr.p_double[i];
73174 0 : ae_v_addd(&tmp->ptr.p_double[0], 1, &sampleg->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1), v);
73175 : }
73176 :
73177 : /*
73178 : * Calculate F
73179 : */
73180 0 : *f = 0.0;
73181 0 : for(i=0; i<=nvars-1; i++)
73182 : {
73183 0 : *f = *f+0.5*ae_sqr(tmp->ptr.p_double[i], _state)/diagh->ptr.p_double[i];
73184 : }
73185 0 : }
73186 :
73187 :
73188 : /*************************************************************************
73189 : Triangular solver for QP solver.
73190 :
73191 : -- ALGLIB --
73192 : Copyright 02.06.2015 by Bochkanov Sergey
73193 : *************************************************************************/
73194 0 : static void minns_qpsolveu(/* Real */ ae_matrix* a,
73195 : ae_int_t n,
73196 : /* Real */ ae_vector* x,
73197 : ae_state *_state)
73198 : {
73199 : ae_int_t i;
73200 : ae_int_t j;
73201 : double v;
73202 :
73203 :
73204 :
73205 : /*
73206 : * A^(-1)*X
73207 : */
73208 0 : for(i=n-1; i>=0; i--)
73209 : {
73210 0 : v = x->ptr.p_double[i];
73211 0 : for(j=i+1; j<=n-1; j++)
73212 : {
73213 0 : v = v-a->ptr.pp_double[i][j]*x->ptr.p_double[j];
73214 : }
73215 0 : x->ptr.p_double[i] = v/a->ptr.pp_double[i][i];
73216 : }
73217 0 : }
73218 :
73219 :
73220 : /*************************************************************************
73221 : Triangular solver for QP solver.
73222 :
73223 : -- ALGLIB --
73224 : Copyright 02.06.2015 by Bochkanov Sergey
73225 : *************************************************************************/
73226 0 : static void minns_qpsolveut(/* Real */ ae_matrix* a,
73227 : ae_int_t n,
73228 : /* Real */ ae_vector* x,
73229 : ae_state *_state)
73230 : {
73231 : ae_int_t i;
73232 : ae_int_t j;
73233 : double v;
73234 :
73235 :
73236 :
73237 : /*
73238 : * A^(-T)*X
73239 : */
73240 0 : for(i=0; i<=n-1; i++)
73241 : {
73242 0 : x->ptr.p_double[i] = x->ptr.p_double[i]/a->ptr.pp_double[i][i];
73243 0 : v = x->ptr.p_double[i];
73244 0 : for(j=i+1; j<=n-1; j++)
73245 : {
73246 0 : x->ptr.p_double[j] = x->ptr.p_double[j]-a->ptr.pp_double[i][j]*v;
73247 : }
73248 : }
73249 0 : }
73250 :
73251 :
73252 0 : void _minnsqp_init(void* _p, ae_state *_state, ae_bool make_automatic)
73253 : {
73254 0 : minnsqp *p = (minnsqp*)_p;
73255 0 : ae_touch_ptr((void*)p);
73256 0 : ae_vector_init(&p->xc, 0, DT_REAL, _state, make_automatic);
73257 0 : ae_vector_init(&p->xn, 0, DT_REAL, _state, make_automatic);
73258 0 : ae_vector_init(&p->x0, 0, DT_REAL, _state, make_automatic);
73259 0 : ae_vector_init(&p->gc, 0, DT_REAL, _state, make_automatic);
73260 0 : ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic);
73261 0 : ae_matrix_init(&p->uh, 0, 0, DT_REAL, _state, make_automatic);
73262 0 : ae_matrix_init(&p->ch, 0, 0, DT_REAL, _state, make_automatic);
73263 0 : ae_matrix_init(&p->rk, 0, 0, DT_REAL, _state, make_automatic);
73264 0 : ae_vector_init(&p->invutc, 0, DT_REAL, _state, make_automatic);
73265 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
73266 0 : ae_vector_init(&p->tmpidx, 0, DT_INT, _state, make_automatic);
73267 0 : ae_vector_init(&p->tmpd, 0, DT_REAL, _state, make_automatic);
73268 0 : ae_vector_init(&p->tmpc, 0, DT_REAL, _state, make_automatic);
73269 0 : ae_vector_init(&p->tmplambdas, 0, DT_REAL, _state, make_automatic);
73270 0 : ae_matrix_init(&p->tmpc2, 0, 0, DT_REAL, _state, make_automatic);
73271 0 : ae_vector_init(&p->tmpb, 0, DT_BOOL, _state, make_automatic);
73272 0 : _snnlssolver_init(&p->nnls, _state, make_automatic);
73273 0 : }
73274 :
73275 :
73276 0 : void _minnsqp_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
73277 : {
73278 0 : minnsqp *dst = (minnsqp*)_dst;
73279 0 : minnsqp *src = (minnsqp*)_src;
73280 0 : dst->fc = src->fc;
73281 0 : dst->fn = src->fn;
73282 0 : ae_vector_init_copy(&dst->xc, &src->xc, _state, make_automatic);
73283 0 : ae_vector_init_copy(&dst->xn, &src->xn, _state, make_automatic);
73284 0 : ae_vector_init_copy(&dst->x0, &src->x0, _state, make_automatic);
73285 0 : ae_vector_init_copy(&dst->gc, &src->gc, _state, make_automatic);
73286 0 : ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic);
73287 0 : ae_matrix_init_copy(&dst->uh, &src->uh, _state, make_automatic);
73288 0 : ae_matrix_init_copy(&dst->ch, &src->ch, _state, make_automatic);
73289 0 : ae_matrix_init_copy(&dst->rk, &src->rk, _state, make_automatic);
73290 0 : ae_vector_init_copy(&dst->invutc, &src->invutc, _state, make_automatic);
73291 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
73292 0 : ae_vector_init_copy(&dst->tmpidx, &src->tmpidx, _state, make_automatic);
73293 0 : ae_vector_init_copy(&dst->tmpd, &src->tmpd, _state, make_automatic);
73294 0 : ae_vector_init_copy(&dst->tmpc, &src->tmpc, _state, make_automatic);
73295 0 : ae_vector_init_copy(&dst->tmplambdas, &src->tmplambdas, _state, make_automatic);
73296 0 : ae_matrix_init_copy(&dst->tmpc2, &src->tmpc2, _state, make_automatic);
73297 0 : ae_vector_init_copy(&dst->tmpb, &src->tmpb, _state, make_automatic);
73298 0 : _snnlssolver_init_copy(&dst->nnls, &src->nnls, _state, make_automatic);
73299 0 : }
73300 :
73301 :
73302 0 : void _minnsqp_clear(void* _p)
73303 : {
73304 0 : minnsqp *p = (minnsqp*)_p;
73305 0 : ae_touch_ptr((void*)p);
73306 0 : ae_vector_clear(&p->xc);
73307 0 : ae_vector_clear(&p->xn);
73308 0 : ae_vector_clear(&p->x0);
73309 0 : ae_vector_clear(&p->gc);
73310 0 : ae_vector_clear(&p->d);
73311 0 : ae_matrix_clear(&p->uh);
73312 0 : ae_matrix_clear(&p->ch);
73313 0 : ae_matrix_clear(&p->rk);
73314 0 : ae_vector_clear(&p->invutc);
73315 0 : ae_vector_clear(&p->tmp0);
73316 0 : ae_vector_clear(&p->tmpidx);
73317 0 : ae_vector_clear(&p->tmpd);
73318 0 : ae_vector_clear(&p->tmpc);
73319 0 : ae_vector_clear(&p->tmplambdas);
73320 0 : ae_matrix_clear(&p->tmpc2);
73321 0 : ae_vector_clear(&p->tmpb);
73322 0 : _snnlssolver_clear(&p->nnls);
73323 0 : }
73324 :
73325 :
73326 0 : void _minnsqp_destroy(void* _p)
73327 : {
73328 0 : minnsqp *p = (minnsqp*)_p;
73329 0 : ae_touch_ptr((void*)p);
73330 0 : ae_vector_destroy(&p->xc);
73331 0 : ae_vector_destroy(&p->xn);
73332 0 : ae_vector_destroy(&p->x0);
73333 0 : ae_vector_destroy(&p->gc);
73334 0 : ae_vector_destroy(&p->d);
73335 0 : ae_matrix_destroy(&p->uh);
73336 0 : ae_matrix_destroy(&p->ch);
73337 0 : ae_matrix_destroy(&p->rk);
73338 0 : ae_vector_destroy(&p->invutc);
73339 0 : ae_vector_destroy(&p->tmp0);
73340 0 : ae_vector_destroy(&p->tmpidx);
73341 0 : ae_vector_destroy(&p->tmpd);
73342 0 : ae_vector_destroy(&p->tmpc);
73343 0 : ae_vector_destroy(&p->tmplambdas);
73344 0 : ae_matrix_destroy(&p->tmpc2);
73345 0 : ae_vector_destroy(&p->tmpb);
73346 0 : _snnlssolver_destroy(&p->nnls);
73347 0 : }
73348 :
73349 :
73350 0 : void _minnsstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
73351 : {
73352 0 : minnsstate *p = (minnsstate*)_p;
73353 0 : ae_touch_ptr((void*)p);
73354 0 : ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic);
73355 0 : ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic);
73356 0 : ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic);
73357 0 : ae_vector_init(&p->hasbndl, 0, DT_BOOL, _state, make_automatic);
73358 0 : ae_vector_init(&p->hasbndu, 0, DT_BOOL, _state, make_automatic);
73359 0 : ae_matrix_init(&p->cleic, 0, 0, DT_REAL, _state, make_automatic);
73360 0 : ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
73361 0 : ae_vector_init(&p->fi, 0, DT_REAL, _state, make_automatic);
73362 0 : ae_matrix_init(&p->j, 0, 0, DT_REAL, _state, make_automatic);
73363 0 : _rcommstate_init(&p->rstate, _state, make_automatic);
73364 0 : _rcommstate_init(&p->rstateags, _state, make_automatic);
73365 0 : _hqrndstate_init(&p->agsrs, _state, make_automatic);
73366 0 : ae_vector_init(&p->xstart, 0, DT_REAL, _state, make_automatic);
73367 0 : ae_vector_init(&p->xc, 0, DT_REAL, _state, make_automatic);
73368 0 : ae_vector_init(&p->xn, 0, DT_REAL, _state, make_automatic);
73369 0 : ae_vector_init(&p->grs, 0, DT_REAL, _state, make_automatic);
73370 0 : ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic);
73371 0 : ae_vector_init(&p->colmax, 0, DT_REAL, _state, make_automatic);
73372 0 : ae_vector_init(&p->diagh, 0, DT_REAL, _state, make_automatic);
73373 0 : ae_vector_init(&p->signmin, 0, DT_REAL, _state, make_automatic);
73374 0 : ae_vector_init(&p->signmax, 0, DT_REAL, _state, make_automatic);
73375 0 : ae_vector_init(&p->scaledbndl, 0, DT_REAL, _state, make_automatic);
73376 0 : ae_vector_init(&p->scaledbndu, 0, DT_REAL, _state, make_automatic);
73377 0 : ae_matrix_init(&p->scaledcleic, 0, 0, DT_REAL, _state, make_automatic);
73378 0 : ae_vector_init(&p->rholinear, 0, DT_REAL, _state, make_automatic);
73379 0 : ae_matrix_init(&p->samplex, 0, 0, DT_REAL, _state, make_automatic);
73380 0 : ae_matrix_init(&p->samplegm, 0, 0, DT_REAL, _state, make_automatic);
73381 0 : ae_matrix_init(&p->samplegmbc, 0, 0, DT_REAL, _state, make_automatic);
73382 0 : ae_vector_init(&p->samplef, 0, DT_REAL, _state, make_automatic);
73383 0 : ae_vector_init(&p->samplef0, 0, DT_REAL, _state, make_automatic);
73384 0 : _minnsqp_init(&p->nsqp, _state, make_automatic);
73385 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
73386 0 : ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic);
73387 0 : ae_matrix_init(&p->tmp2, 0, 0, DT_REAL, _state, make_automatic);
73388 0 : ae_vector_init(&p->tmp3, 0, DT_INT, _state, make_automatic);
73389 0 : ae_vector_init(&p->xbase, 0, DT_REAL, _state, make_automatic);
73390 0 : ae_vector_init(&p->fp, 0, DT_REAL, _state, make_automatic);
73391 0 : ae_vector_init(&p->fm, 0, DT_REAL, _state, make_automatic);
73392 0 : }
73393 :
73394 :
73395 0 : void _minnsstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
73396 : {
73397 0 : minnsstate *dst = (minnsstate*)_dst;
73398 0 : minnsstate *src = (minnsstate*)_src;
73399 0 : dst->solvertype = src->solvertype;
73400 0 : dst->n = src->n;
73401 0 : dst->epsx = src->epsx;
73402 0 : dst->maxits = src->maxits;
73403 0 : dst->xrep = src->xrep;
73404 0 : dst->diffstep = src->diffstep;
73405 0 : ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic);
73406 0 : ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic);
73407 0 : ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic);
73408 0 : ae_vector_init_copy(&dst->hasbndl, &src->hasbndl, _state, make_automatic);
73409 0 : ae_vector_init_copy(&dst->hasbndu, &src->hasbndu, _state, make_automatic);
73410 0 : dst->nec = src->nec;
73411 0 : dst->nic = src->nic;
73412 0 : ae_matrix_init_copy(&dst->cleic, &src->cleic, _state, make_automatic);
73413 0 : dst->ng = src->ng;
73414 0 : dst->nh = src->nh;
73415 0 : ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
73416 0 : dst->f = src->f;
73417 0 : ae_vector_init_copy(&dst->fi, &src->fi, _state, make_automatic);
73418 0 : ae_matrix_init_copy(&dst->j, &src->j, _state, make_automatic);
73419 0 : dst->needfij = src->needfij;
73420 0 : dst->needfi = src->needfi;
73421 0 : dst->xupdated = src->xupdated;
73422 0 : _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic);
73423 0 : _rcommstate_init_copy(&dst->rstateags, &src->rstateags, _state, make_automatic);
73424 0 : _hqrndstate_init_copy(&dst->agsrs, &src->agsrs, _state, make_automatic);
73425 0 : dst->agsradius = src->agsradius;
73426 0 : dst->agssamplesize = src->agssamplesize;
73427 0 : dst->agsraddecay = src->agsraddecay;
73428 0 : dst->agsalphadecay = src->agsalphadecay;
73429 0 : dst->agsdecrease = src->agsdecrease;
73430 0 : dst->agsinitstp = src->agsinitstp;
73431 0 : dst->agsstattold = src->agsstattold;
73432 0 : dst->agsshortstpabs = src->agsshortstpabs;
73433 0 : dst->agsshortstprel = src->agsshortstprel;
73434 0 : dst->agsshortf = src->agsshortf;
73435 0 : dst->agsshortlimit = src->agsshortlimit;
73436 0 : dst->agsrhononlinear = src->agsrhononlinear;
73437 0 : dst->agsminupdate = src->agsminupdate;
73438 0 : dst->agsmaxraddecays = src->agsmaxraddecays;
73439 0 : dst->agsmaxbacktrack = src->agsmaxbacktrack;
73440 0 : dst->agsmaxbacktracknonfull = src->agsmaxbacktracknonfull;
73441 0 : dst->agspenaltylevel = src->agspenaltylevel;
73442 0 : dst->agspenaltyincrease = src->agspenaltyincrease;
73443 0 : ae_vector_init_copy(&dst->xstart, &src->xstart, _state, make_automatic);
73444 0 : ae_vector_init_copy(&dst->xc, &src->xc, _state, make_automatic);
73445 0 : ae_vector_init_copy(&dst->xn, &src->xn, _state, make_automatic);
73446 0 : ae_vector_init_copy(&dst->grs, &src->grs, _state, make_automatic);
73447 0 : ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic);
73448 0 : ae_vector_init_copy(&dst->colmax, &src->colmax, _state, make_automatic);
73449 0 : ae_vector_init_copy(&dst->diagh, &src->diagh, _state, make_automatic);
73450 0 : ae_vector_init_copy(&dst->signmin, &src->signmin, _state, make_automatic);
73451 0 : ae_vector_init_copy(&dst->signmax, &src->signmax, _state, make_automatic);
73452 0 : dst->userterminationneeded = src->userterminationneeded;
73453 0 : ae_vector_init_copy(&dst->scaledbndl, &src->scaledbndl, _state, make_automatic);
73454 0 : ae_vector_init_copy(&dst->scaledbndu, &src->scaledbndu, _state, make_automatic);
73455 0 : ae_matrix_init_copy(&dst->scaledcleic, &src->scaledcleic, _state, make_automatic);
73456 0 : ae_vector_init_copy(&dst->rholinear, &src->rholinear, _state, make_automatic);
73457 0 : ae_matrix_init_copy(&dst->samplex, &src->samplex, _state, make_automatic);
73458 0 : ae_matrix_init_copy(&dst->samplegm, &src->samplegm, _state, make_automatic);
73459 0 : ae_matrix_init_copy(&dst->samplegmbc, &src->samplegmbc, _state, make_automatic);
73460 0 : ae_vector_init_copy(&dst->samplef, &src->samplef, _state, make_automatic);
73461 0 : ae_vector_init_copy(&dst->samplef0, &src->samplef0, _state, make_automatic);
73462 0 : _minnsqp_init_copy(&dst->nsqp, &src->nsqp, _state, make_automatic);
73463 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
73464 0 : ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic);
73465 0 : ae_matrix_init_copy(&dst->tmp2, &src->tmp2, _state, make_automatic);
73466 0 : ae_vector_init_copy(&dst->tmp3, &src->tmp3, _state, make_automatic);
73467 0 : ae_vector_init_copy(&dst->xbase, &src->xbase, _state, make_automatic);
73468 0 : ae_vector_init_copy(&dst->fp, &src->fp, _state, make_automatic);
73469 0 : ae_vector_init_copy(&dst->fm, &src->fm, _state, make_automatic);
73470 0 : dst->repinneriterationscount = src->repinneriterationscount;
73471 0 : dst->repouteriterationscount = src->repouteriterationscount;
73472 0 : dst->repnfev = src->repnfev;
73473 0 : dst->repvaridx = src->repvaridx;
73474 0 : dst->repfuncidx = src->repfuncidx;
73475 0 : dst->repterminationtype = src->repterminationtype;
73476 0 : dst->replcerr = src->replcerr;
73477 0 : dst->repnlcerr = src->repnlcerr;
73478 0 : dst->dbgncholesky = src->dbgncholesky;
73479 0 : }
73480 :
73481 :
73482 0 : void _minnsstate_clear(void* _p)
73483 : {
73484 0 : minnsstate *p = (minnsstate*)_p;
73485 0 : ae_touch_ptr((void*)p);
73486 0 : ae_vector_clear(&p->s);
73487 0 : ae_vector_clear(&p->bndl);
73488 0 : ae_vector_clear(&p->bndu);
73489 0 : ae_vector_clear(&p->hasbndl);
73490 0 : ae_vector_clear(&p->hasbndu);
73491 0 : ae_matrix_clear(&p->cleic);
73492 0 : ae_vector_clear(&p->x);
73493 0 : ae_vector_clear(&p->fi);
73494 0 : ae_matrix_clear(&p->j);
73495 0 : _rcommstate_clear(&p->rstate);
73496 0 : _rcommstate_clear(&p->rstateags);
73497 0 : _hqrndstate_clear(&p->agsrs);
73498 0 : ae_vector_clear(&p->xstart);
73499 0 : ae_vector_clear(&p->xc);
73500 0 : ae_vector_clear(&p->xn);
73501 0 : ae_vector_clear(&p->grs);
73502 0 : ae_vector_clear(&p->d);
73503 0 : ae_vector_clear(&p->colmax);
73504 0 : ae_vector_clear(&p->diagh);
73505 0 : ae_vector_clear(&p->signmin);
73506 0 : ae_vector_clear(&p->signmax);
73507 0 : ae_vector_clear(&p->scaledbndl);
73508 0 : ae_vector_clear(&p->scaledbndu);
73509 0 : ae_matrix_clear(&p->scaledcleic);
73510 0 : ae_vector_clear(&p->rholinear);
73511 0 : ae_matrix_clear(&p->samplex);
73512 0 : ae_matrix_clear(&p->samplegm);
73513 0 : ae_matrix_clear(&p->samplegmbc);
73514 0 : ae_vector_clear(&p->samplef);
73515 0 : ae_vector_clear(&p->samplef0);
73516 0 : _minnsqp_clear(&p->nsqp);
73517 0 : ae_vector_clear(&p->tmp0);
73518 0 : ae_vector_clear(&p->tmp1);
73519 0 : ae_matrix_clear(&p->tmp2);
73520 0 : ae_vector_clear(&p->tmp3);
73521 0 : ae_vector_clear(&p->xbase);
73522 0 : ae_vector_clear(&p->fp);
73523 0 : ae_vector_clear(&p->fm);
73524 0 : }
73525 :
73526 :
73527 0 : void _minnsstate_destroy(void* _p)
73528 : {
73529 0 : minnsstate *p = (minnsstate*)_p;
73530 0 : ae_touch_ptr((void*)p);
73531 0 : ae_vector_destroy(&p->s);
73532 0 : ae_vector_destroy(&p->bndl);
73533 0 : ae_vector_destroy(&p->bndu);
73534 0 : ae_vector_destroy(&p->hasbndl);
73535 0 : ae_vector_destroy(&p->hasbndu);
73536 0 : ae_matrix_destroy(&p->cleic);
73537 0 : ae_vector_destroy(&p->x);
73538 0 : ae_vector_destroy(&p->fi);
73539 0 : ae_matrix_destroy(&p->j);
73540 0 : _rcommstate_destroy(&p->rstate);
73541 0 : _rcommstate_destroy(&p->rstateags);
73542 0 : _hqrndstate_destroy(&p->agsrs);
73543 0 : ae_vector_destroy(&p->xstart);
73544 0 : ae_vector_destroy(&p->xc);
73545 0 : ae_vector_destroy(&p->xn);
73546 0 : ae_vector_destroy(&p->grs);
73547 0 : ae_vector_destroy(&p->d);
73548 0 : ae_vector_destroy(&p->colmax);
73549 0 : ae_vector_destroy(&p->diagh);
73550 0 : ae_vector_destroy(&p->signmin);
73551 0 : ae_vector_destroy(&p->signmax);
73552 0 : ae_vector_destroy(&p->scaledbndl);
73553 0 : ae_vector_destroy(&p->scaledbndu);
73554 0 : ae_matrix_destroy(&p->scaledcleic);
73555 0 : ae_vector_destroy(&p->rholinear);
73556 0 : ae_matrix_destroy(&p->samplex);
73557 0 : ae_matrix_destroy(&p->samplegm);
73558 0 : ae_matrix_destroy(&p->samplegmbc);
73559 0 : ae_vector_destroy(&p->samplef);
73560 0 : ae_vector_destroy(&p->samplef0);
73561 0 : _minnsqp_destroy(&p->nsqp);
73562 0 : ae_vector_destroy(&p->tmp0);
73563 0 : ae_vector_destroy(&p->tmp1);
73564 0 : ae_matrix_destroy(&p->tmp2);
73565 0 : ae_vector_destroy(&p->tmp3);
73566 0 : ae_vector_destroy(&p->xbase);
73567 0 : ae_vector_destroy(&p->fp);
73568 0 : ae_vector_destroy(&p->fm);
73569 0 : }
73570 :
73571 :
73572 0 : void _minnsreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
73573 : {
73574 0 : minnsreport *p = (minnsreport*)_p;
73575 0 : ae_touch_ptr((void*)p);
73576 0 : }
73577 :
73578 :
73579 0 : void _minnsreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
73580 : {
73581 0 : minnsreport *dst = (minnsreport*)_dst;
73582 0 : minnsreport *src = (minnsreport*)_src;
73583 0 : dst->iterationscount = src->iterationscount;
73584 0 : dst->nfev = src->nfev;
73585 0 : dst->cerr = src->cerr;
73586 0 : dst->lcerr = src->lcerr;
73587 0 : dst->nlcerr = src->nlcerr;
73588 0 : dst->terminationtype = src->terminationtype;
73589 0 : dst->varidx = src->varidx;
73590 0 : dst->funcidx = src->funcidx;
73591 0 : }
73592 :
73593 :
73594 0 : void _minnsreport_clear(void* _p)
73595 : {
73596 0 : minnsreport *p = (minnsreport*)_p;
73597 0 : ae_touch_ptr((void*)p);
73598 0 : }
73599 :
73600 :
73601 0 : void _minnsreport_destroy(void* _p)
73602 : {
73603 0 : minnsreport *p = (minnsreport*)_p;
73604 0 : ae_touch_ptr((void*)p);
73605 0 : }
73606 :
73607 :
73608 : #endif
73609 : #if defined(AE_COMPILE_MINCOMP) || !defined(AE_PARTIAL_BUILD)
73610 :
73611 :
73612 : /*************************************************************************
73613 : Obsolete function, use MinLBFGSSetPrecDefault() instead.
73614 :
73615 : -- ALGLIB --
73616 : Copyright 13.10.2010 by Bochkanov Sergey
73617 : *************************************************************************/
73618 0 : void minlbfgssetdefaultpreconditioner(minlbfgsstate* state,
73619 : ae_state *_state)
73620 : {
73621 :
73622 :
73623 0 : minlbfgssetprecdefault(state, _state);
73624 0 : }
73625 :
73626 :
73627 : /*************************************************************************
73628 : Obsolete function, use MinLBFGSSetCholeskyPreconditioner() instead.
73629 :
73630 : -- ALGLIB --
73631 : Copyright 13.10.2010 by Bochkanov Sergey
73632 : *************************************************************************/
73633 0 : void minlbfgssetcholeskypreconditioner(minlbfgsstate* state,
73634 : /* Real */ ae_matrix* p,
73635 : ae_bool isupper,
73636 : ae_state *_state)
73637 : {
73638 :
73639 :
73640 0 : minlbfgssetpreccholesky(state, p, isupper, _state);
73641 0 : }
73642 :
73643 :
73644 : /*************************************************************************
73645 : This is obsolete function which was used by previous version of the BLEIC
73646 : optimizer. It does nothing in the current version of BLEIC.
73647 :
73648 : -- ALGLIB --
73649 : Copyright 28.11.2010 by Bochkanov Sergey
73650 : *************************************************************************/
73651 0 : void minbleicsetbarrierwidth(minbleicstate* state,
73652 : double mu,
73653 : ae_state *_state)
73654 : {
73655 :
73656 :
73657 0 : }
73658 :
73659 :
73660 : /*************************************************************************
73661 : This is obsolete function which was used by previous version of the BLEIC
73662 : optimizer. It does nothing in the current version of BLEIC.
73663 :
73664 : -- ALGLIB --
73665 : Copyright 28.11.2010 by Bochkanov Sergey
73666 : *************************************************************************/
73667 0 : void minbleicsetbarrierdecay(minbleicstate* state,
73668 : double mudecay,
73669 : ae_state *_state)
73670 : {
73671 :
73672 :
73673 0 : }
73674 :
73675 :
73676 : /*************************************************************************
73677 : Obsolete optimization algorithm.
73678 : Was replaced by MinBLEIC subpackage.
73679 :
73680 : -- ALGLIB --
73681 : Copyright 25.03.2010 by Bochkanov Sergey
73682 : *************************************************************************/
73683 0 : void minasacreate(ae_int_t n,
73684 : /* Real */ ae_vector* x,
73685 : /* Real */ ae_vector* bndl,
73686 : /* Real */ ae_vector* bndu,
73687 : minasastate* state,
73688 : ae_state *_state)
73689 : {
73690 : ae_int_t i;
73691 :
73692 0 : _minasastate_clear(state);
73693 :
73694 0 : ae_assert(n>=1, "MinASA: N too small!", _state);
73695 0 : ae_assert(x->cnt>=n, "MinCGCreate: Length(X)<N!", _state);
73696 0 : ae_assert(isfinitevector(x, n, _state), "MinCGCreate: X contains infinite or NaN values!", _state);
73697 0 : ae_assert(bndl->cnt>=n, "MinCGCreate: Length(BndL)<N!", _state);
73698 0 : ae_assert(isfinitevector(bndl, n, _state), "MinCGCreate: BndL contains infinite or NaN values!", _state);
73699 0 : ae_assert(bndu->cnt>=n, "MinCGCreate: Length(BndU)<N!", _state);
73700 0 : ae_assert(isfinitevector(bndu, n, _state), "MinCGCreate: BndU contains infinite or NaN values!", _state);
73701 0 : for(i=0; i<=n-1; i++)
73702 : {
73703 0 : ae_assert(ae_fp_less_eq(bndl->ptr.p_double[i],bndu->ptr.p_double[i]), "MinASA: inconsistent bounds!", _state);
73704 0 : ae_assert(ae_fp_less_eq(bndl->ptr.p_double[i],x->ptr.p_double[i]), "MinASA: infeasible X!", _state);
73705 0 : ae_assert(ae_fp_less_eq(x->ptr.p_double[i],bndu->ptr.p_double[i]), "MinASA: infeasible X!", _state);
73706 : }
73707 :
73708 : /*
73709 : * Initialize
73710 : */
73711 0 : state->n = n;
73712 0 : minasasetcond(state, (double)(0), (double)(0), (double)(0), 0, _state);
73713 0 : minasasetxrep(state, ae_false, _state);
73714 0 : minasasetstpmax(state, (double)(0), _state);
73715 0 : minasasetalgorithm(state, -1, _state);
73716 0 : ae_vector_set_length(&state->bndl, n, _state);
73717 0 : ae_vector_set_length(&state->bndu, n, _state);
73718 0 : ae_vector_set_length(&state->ak, n, _state);
73719 0 : ae_vector_set_length(&state->xk, n, _state);
73720 0 : ae_vector_set_length(&state->dk, n, _state);
73721 0 : ae_vector_set_length(&state->an, n, _state);
73722 0 : ae_vector_set_length(&state->xn, n, _state);
73723 0 : ae_vector_set_length(&state->dn, n, _state);
73724 0 : ae_vector_set_length(&state->x, n, _state);
73725 0 : ae_vector_set_length(&state->d, n, _state);
73726 0 : ae_vector_set_length(&state->g, n, _state);
73727 0 : ae_vector_set_length(&state->gc, n, _state);
73728 0 : ae_vector_set_length(&state->work, n, _state);
73729 0 : ae_vector_set_length(&state->yk, n, _state);
73730 0 : minasarestartfrom(state, x, bndl, bndu, _state);
73731 0 : }
73732 :
73733 :
73734 : /*************************************************************************
73735 : Obsolete optimization algorithm.
73736 : Was replaced by MinBLEIC subpackage.
73737 :
73738 : -- ALGLIB --
73739 : Copyright 02.04.2010 by Bochkanov Sergey
73740 : *************************************************************************/
73741 0 : void minasasetcond(minasastate* state,
73742 : double epsg,
73743 : double epsf,
73744 : double epsx,
73745 : ae_int_t maxits,
73746 : ae_state *_state)
73747 : {
73748 :
73749 :
73750 0 : ae_assert(ae_isfinite(epsg, _state), "MinASASetCond: EpsG is not finite number!", _state);
73751 0 : ae_assert(ae_fp_greater_eq(epsg,(double)(0)), "MinASASetCond: negative EpsG!", _state);
73752 0 : ae_assert(ae_isfinite(epsf, _state), "MinASASetCond: EpsF is not finite number!", _state);
73753 0 : ae_assert(ae_fp_greater_eq(epsf,(double)(0)), "MinASASetCond: negative EpsF!", _state);
73754 0 : ae_assert(ae_isfinite(epsx, _state), "MinASASetCond: EpsX is not finite number!", _state);
73755 0 : ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "MinASASetCond: negative EpsX!", _state);
73756 0 : ae_assert(maxits>=0, "MinASASetCond: negative MaxIts!", _state);
73757 0 : if( ((ae_fp_eq(epsg,(double)(0))&&ae_fp_eq(epsf,(double)(0)))&&ae_fp_eq(epsx,(double)(0)))&&maxits==0 )
73758 : {
73759 0 : epsx = 1.0E-6;
73760 : }
73761 0 : state->epsg = epsg;
73762 0 : state->epsf = epsf;
73763 0 : state->epsx = epsx;
73764 0 : state->maxits = maxits;
73765 0 : }
73766 :
73767 :
73768 : /*************************************************************************
73769 : Obsolete optimization algorithm.
73770 : Was replaced by MinBLEIC subpackage.
73771 :
73772 : -- ALGLIB --
73773 : Copyright 02.04.2010 by Bochkanov Sergey
73774 : *************************************************************************/
73775 0 : void minasasetxrep(minasastate* state, ae_bool needxrep, ae_state *_state)
73776 : {
73777 :
73778 :
73779 0 : state->xrep = needxrep;
73780 0 : }
73781 :
73782 :
73783 : /*************************************************************************
73784 : Obsolete optimization algorithm.
73785 : Was replaced by MinBLEIC subpackage.
73786 :
73787 : -- ALGLIB --
73788 : Copyright 02.04.2010 by Bochkanov Sergey
73789 : *************************************************************************/
73790 0 : void minasasetalgorithm(minasastate* state,
73791 : ae_int_t algotype,
73792 : ae_state *_state)
73793 : {
73794 :
73795 :
73796 0 : ae_assert(algotype>=-1&&algotype<=1, "MinASASetAlgorithm: incorrect AlgoType!", _state);
73797 0 : if( algotype==-1 )
73798 : {
73799 0 : algotype = 1;
73800 : }
73801 0 : state->cgtype = algotype;
73802 0 : }
73803 :
73804 :
73805 : /*************************************************************************
73806 : Obsolete optimization algorithm.
73807 : Was replaced by MinBLEIC subpackage.
73808 :
73809 : -- ALGLIB --
73810 : Copyright 02.04.2010 by Bochkanov Sergey
73811 : *************************************************************************/
73812 0 : void minasasetstpmax(minasastate* state, double stpmax, ae_state *_state)
73813 : {
73814 :
73815 :
73816 0 : ae_assert(ae_isfinite(stpmax, _state), "MinASASetStpMax: StpMax is not finite!", _state);
73817 0 : ae_assert(ae_fp_greater_eq(stpmax,(double)(0)), "MinASASetStpMax: StpMax<0!", _state);
73818 0 : state->stpmax = stpmax;
73819 0 : }
73820 :
73821 :
73822 : /*************************************************************************
73823 :
73824 : -- ALGLIB --
73825 : Copyright 20.03.2009 by Bochkanov Sergey
73826 : *************************************************************************/
73827 0 : ae_bool minasaiteration(minasastate* state, ae_state *_state)
73828 : {
73829 : ae_int_t n;
73830 : ae_int_t i;
73831 : double betak;
73832 : double v;
73833 : double vv;
73834 : ae_int_t mcinfo;
73835 : ae_bool b;
73836 : ae_bool stepfound;
73837 : ae_int_t diffcnt;
73838 : ae_bool result;
73839 :
73840 :
73841 :
73842 : /*
73843 : * Reverse communication preparations
73844 : * I know it looks ugly, but it works the same way
73845 : * anywhere from C++ to Python.
73846 : *
73847 : * This code initializes locals by:
73848 : * * random values determined during code
73849 : * generation - on first subroutine call
73850 : * * values from previous call - on subsequent calls
73851 : */
73852 0 : if( state->rstate.stage>=0 )
73853 : {
73854 0 : n = state->rstate.ia.ptr.p_int[0];
73855 0 : i = state->rstate.ia.ptr.p_int[1];
73856 0 : mcinfo = state->rstate.ia.ptr.p_int[2];
73857 0 : diffcnt = state->rstate.ia.ptr.p_int[3];
73858 0 : b = state->rstate.ba.ptr.p_bool[0];
73859 0 : stepfound = state->rstate.ba.ptr.p_bool[1];
73860 0 : betak = state->rstate.ra.ptr.p_double[0];
73861 0 : v = state->rstate.ra.ptr.p_double[1];
73862 0 : vv = state->rstate.ra.ptr.p_double[2];
73863 : }
73864 : else
73865 : {
73866 0 : n = 359;
73867 0 : i = -58;
73868 0 : mcinfo = -919;
73869 0 : diffcnt = -909;
73870 0 : b = ae_true;
73871 0 : stepfound = ae_true;
73872 0 : betak = 74;
73873 0 : v = -788;
73874 0 : vv = 809;
73875 : }
73876 0 : if( state->rstate.stage==0 )
73877 : {
73878 0 : goto lbl_0;
73879 : }
73880 0 : if( state->rstate.stage==1 )
73881 : {
73882 0 : goto lbl_1;
73883 : }
73884 0 : if( state->rstate.stage==2 )
73885 : {
73886 0 : goto lbl_2;
73887 : }
73888 0 : if( state->rstate.stage==3 )
73889 : {
73890 0 : goto lbl_3;
73891 : }
73892 0 : if( state->rstate.stage==4 )
73893 : {
73894 0 : goto lbl_4;
73895 : }
73896 0 : if( state->rstate.stage==5 )
73897 : {
73898 0 : goto lbl_5;
73899 : }
73900 0 : if( state->rstate.stage==6 )
73901 : {
73902 0 : goto lbl_6;
73903 : }
73904 0 : if( state->rstate.stage==7 )
73905 : {
73906 0 : goto lbl_7;
73907 : }
73908 0 : if( state->rstate.stage==8 )
73909 : {
73910 0 : goto lbl_8;
73911 : }
73912 0 : if( state->rstate.stage==9 )
73913 : {
73914 0 : goto lbl_9;
73915 : }
73916 0 : if( state->rstate.stage==10 )
73917 : {
73918 0 : goto lbl_10;
73919 : }
73920 0 : if( state->rstate.stage==11 )
73921 : {
73922 0 : goto lbl_11;
73923 : }
73924 0 : if( state->rstate.stage==12 )
73925 : {
73926 0 : goto lbl_12;
73927 : }
73928 0 : if( state->rstate.stage==13 )
73929 : {
73930 0 : goto lbl_13;
73931 : }
73932 0 : if( state->rstate.stage==14 )
73933 : {
73934 0 : goto lbl_14;
73935 : }
73936 :
73937 : /*
73938 : * Routine body
73939 : */
73940 :
73941 : /*
73942 : * Prepare
73943 : */
73944 0 : n = state->n;
73945 0 : state->repterminationtype = 0;
73946 0 : state->repiterationscount = 0;
73947 0 : state->repnfev = 0;
73948 0 : state->debugrestartscount = 0;
73949 0 : state->cgtype = 1;
73950 0 : ae_v_move(&state->xk.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1));
73951 0 : for(i=0; i<=n-1; i++)
73952 : {
73953 0 : 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]) )
73954 : {
73955 0 : state->ak.ptr.p_double[i] = (double)(0);
73956 : }
73957 : else
73958 : {
73959 0 : state->ak.ptr.p_double[i] = (double)(1);
73960 : }
73961 : }
73962 0 : state->mu = 0.1;
73963 0 : state->curalgo = 0;
73964 :
73965 : /*
73966 : * Calculate F/G, initialize algorithm
73967 : */
73968 0 : mincomp_clearrequestfields(state, _state);
73969 0 : state->needfg = ae_true;
73970 0 : state->rstate.stage = 0;
73971 0 : goto lbl_rcomm;
73972 0 : lbl_0:
73973 0 : state->needfg = ae_false;
73974 0 : if( !state->xrep )
73975 : {
73976 0 : goto lbl_15;
73977 : }
73978 :
73979 : /*
73980 : * progress report
73981 : */
73982 0 : mincomp_clearrequestfields(state, _state);
73983 0 : state->xupdated = ae_true;
73984 0 : state->rstate.stage = 1;
73985 0 : goto lbl_rcomm;
73986 0 : lbl_1:
73987 0 : state->xupdated = ae_false;
73988 0 : lbl_15:
73989 0 : if( ae_fp_less_eq(mincomp_asaboundedantigradnorm(state, _state),state->epsg) )
73990 : {
73991 0 : state->repterminationtype = 4;
73992 0 : result = ae_false;
73993 0 : return result;
73994 : }
73995 0 : state->repnfev = state->repnfev+1;
73996 :
73997 : /*
73998 : * Main cycle
73999 : *
74000 : * At the beginning of new iteration:
74001 : * * CurAlgo stores current algorithm selector
74002 : * * State.XK, State.F and State.G store current X/F/G
74003 : * * State.AK stores current set of active constraints
74004 : */
74005 0 : lbl_17:
74006 : if( ae_false )
74007 : {
74008 : goto lbl_18;
74009 : }
74010 :
74011 : /*
74012 : * GPA algorithm
74013 : */
74014 0 : if( state->curalgo!=0 )
74015 : {
74016 0 : goto lbl_19;
74017 : }
74018 0 : state->k = 0;
74019 0 : state->acount = 0;
74020 0 : lbl_21:
74021 : if( ae_false )
74022 : {
74023 : goto lbl_22;
74024 : }
74025 :
74026 : /*
74027 : * Determine Dk = proj(xk - gk)-xk
74028 : */
74029 0 : for(i=0; i<=n-1; i++)
74030 : {
74031 0 : 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];
74032 : }
74033 :
74034 : /*
74035 : * Armijo line search.
74036 : * * exact search with alpha=1 is tried first,
74037 : * 'exact' means that we evaluate f() EXACTLY at
74038 : * bound(x-g,bndl,bndu), without intermediate floating
74039 : * point operations.
74040 : * * alpha<1 are tried if explicit search wasn't successful
74041 : * Result is placed into XN.
74042 : *
74043 : * Two types of search are needed because we can't
74044 : * just use second type with alpha=1 because in finite
74045 : * precision arithmetics (x1-x0)+x0 may differ from x1.
74046 : * So while x1 is correctly bounded (it lie EXACTLY on
74047 : * boundary, if it is active), (x1-x0)+x0 may be
74048 : * not bounded.
74049 : */
74050 0 : v = ae_v_dotproduct(&state->d.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
74051 0 : state->dginit = v;
74052 0 : state->finit = state->f;
74053 0 : if( !(ae_fp_less_eq(mincomp_asad1norm(state, _state),state->stpmax)||ae_fp_eq(state->stpmax,(double)(0))) )
74054 : {
74055 0 : goto lbl_23;
74056 : }
74057 :
74058 : /*
74059 : * Try alpha=1 step first
74060 : */
74061 0 : for(i=0; i<=n-1; i++)
74062 : {
74063 0 : 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);
74064 : }
74065 0 : mincomp_clearrequestfields(state, _state);
74066 0 : state->needfg = ae_true;
74067 0 : state->rstate.stage = 2;
74068 0 : goto lbl_rcomm;
74069 0 : lbl_2:
74070 0 : state->needfg = ae_false;
74071 0 : state->repnfev = state->repnfev+1;
74072 0 : stepfound = ae_fp_less_eq(state->f,state->finit+mincomp_gpaftol*state->dginit);
74073 0 : goto lbl_24;
74074 0 : lbl_23:
74075 0 : stepfound = ae_false;
74076 0 : lbl_24:
74077 0 : if( !stepfound )
74078 : {
74079 0 : goto lbl_25;
74080 : }
74081 :
74082 : /*
74083 : * we are at the boundary(ies)
74084 : */
74085 0 : ae_v_move(&state->xn.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1));
74086 0 : state->stp = (double)(1);
74087 0 : goto lbl_26;
74088 0 : lbl_25:
74089 :
74090 : /*
74091 : * alpha=1 is too large, try smaller values
74092 : */
74093 0 : state->stp = (double)(1);
74094 0 : linminnormalized(&state->d, &state->stp, n, _state);
74095 0 : state->dginit = state->dginit/state->stp;
74096 0 : state->stp = mincomp_gpadecay*state->stp;
74097 0 : if( ae_fp_greater(state->stpmax,(double)(0)) )
74098 : {
74099 0 : state->stp = ae_minreal(state->stp, state->stpmax, _state);
74100 : }
74101 0 : lbl_27:
74102 : if( ae_false )
74103 : {
74104 : goto lbl_28;
74105 : }
74106 0 : v = state->stp;
74107 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xk.ptr.p_double[0], 1, ae_v_len(0,n-1));
74108 0 : ae_v_addd(&state->x.ptr.p_double[0], 1, &state->d.ptr.p_double[0], 1, ae_v_len(0,n-1), v);
74109 0 : mincomp_clearrequestfields(state, _state);
74110 0 : state->needfg = ae_true;
74111 0 : state->rstate.stage = 3;
74112 0 : goto lbl_rcomm;
74113 0 : lbl_3:
74114 0 : state->needfg = ae_false;
74115 0 : state->repnfev = state->repnfev+1;
74116 0 : if( ae_fp_less_eq(state->stp,mincomp_stpmin) )
74117 : {
74118 0 : goto lbl_28;
74119 : }
74120 0 : if( ae_fp_less_eq(state->f,state->finit+state->stp*mincomp_gpaftol*state->dginit) )
74121 : {
74122 0 : goto lbl_28;
74123 : }
74124 0 : state->stp = state->stp*mincomp_gpadecay;
74125 0 : goto lbl_27;
74126 0 : lbl_28:
74127 0 : ae_v_move(&state->xn.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1));
74128 0 : lbl_26:
74129 0 : state->repiterationscount = state->repiterationscount+1;
74130 0 : if( !state->xrep )
74131 : {
74132 0 : goto lbl_29;
74133 : }
74134 :
74135 : /*
74136 : * progress report
74137 : */
74138 0 : mincomp_clearrequestfields(state, _state);
74139 0 : state->xupdated = ae_true;
74140 0 : state->rstate.stage = 4;
74141 0 : goto lbl_rcomm;
74142 0 : lbl_4:
74143 0 : state->xupdated = ae_false;
74144 0 : lbl_29:
74145 :
74146 : /*
74147 : * Calculate new set of active constraints.
74148 : * Reset counter if active set was changed.
74149 : * Prepare for the new iteration
74150 : */
74151 0 : for(i=0; i<=n-1; i++)
74152 : {
74153 0 : 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]) )
74154 : {
74155 0 : state->an.ptr.p_double[i] = (double)(0);
74156 : }
74157 : else
74158 : {
74159 0 : state->an.ptr.p_double[i] = (double)(1);
74160 : }
74161 : }
74162 0 : for(i=0; i<=n-1; i++)
74163 : {
74164 0 : if( ae_fp_neq(state->ak.ptr.p_double[i],state->an.ptr.p_double[i]) )
74165 : {
74166 0 : state->acount = -1;
74167 0 : break;
74168 : }
74169 : }
74170 0 : state->acount = state->acount+1;
74171 0 : ae_v_move(&state->xk.ptr.p_double[0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1));
74172 0 : ae_v_move(&state->ak.ptr.p_double[0], 1, &state->an.ptr.p_double[0], 1, ae_v_len(0,n-1));
74173 :
74174 : /*
74175 : * Stopping conditions
74176 : */
74177 0 : if( !(state->repiterationscount>=state->maxits&&state->maxits>0) )
74178 : {
74179 0 : goto lbl_31;
74180 : }
74181 :
74182 : /*
74183 : * Too many iterations
74184 : */
74185 0 : state->repterminationtype = 5;
74186 0 : if( !state->xrep )
74187 : {
74188 0 : goto lbl_33;
74189 : }
74190 0 : mincomp_clearrequestfields(state, _state);
74191 0 : state->xupdated = ae_true;
74192 0 : state->rstate.stage = 5;
74193 0 : goto lbl_rcomm;
74194 0 : lbl_5:
74195 0 : state->xupdated = ae_false;
74196 0 : lbl_33:
74197 0 : result = ae_false;
74198 0 : return result;
74199 0 : lbl_31:
74200 0 : if( ae_fp_greater(mincomp_asaboundedantigradnorm(state, _state),state->epsg) )
74201 : {
74202 0 : goto lbl_35;
74203 : }
74204 :
74205 : /*
74206 : * Gradient is small enough
74207 : */
74208 0 : state->repterminationtype = 4;
74209 0 : if( !state->xrep )
74210 : {
74211 0 : goto lbl_37;
74212 : }
74213 0 : mincomp_clearrequestfields(state, _state);
74214 0 : state->xupdated = ae_true;
74215 0 : state->rstate.stage = 6;
74216 0 : goto lbl_rcomm;
74217 0 : lbl_6:
74218 0 : state->xupdated = ae_false;
74219 0 : lbl_37:
74220 0 : result = ae_false;
74221 0 : return result;
74222 0 : lbl_35:
74223 0 : v = ae_v_dotproduct(&state->d.ptr.p_double[0], 1, &state->d.ptr.p_double[0], 1, ae_v_len(0,n-1));
74224 0 : if( ae_fp_greater(ae_sqrt(v, _state)*state->stp,state->epsx) )
74225 : {
74226 0 : goto lbl_39;
74227 : }
74228 :
74229 : /*
74230 : * Step size is too small, no further improvement is
74231 : * possible
74232 : */
74233 0 : state->repterminationtype = 2;
74234 0 : if( !state->xrep )
74235 : {
74236 0 : goto lbl_41;
74237 : }
74238 0 : mincomp_clearrequestfields(state, _state);
74239 0 : state->xupdated = ae_true;
74240 0 : state->rstate.stage = 7;
74241 0 : goto lbl_rcomm;
74242 0 : lbl_7:
74243 0 : state->xupdated = ae_false;
74244 0 : lbl_41:
74245 0 : result = ae_false;
74246 0 : return result;
74247 0 : lbl_39:
74248 0 : 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)) )
74249 : {
74250 0 : goto lbl_43;
74251 : }
74252 :
74253 : /*
74254 : * F(k+1)-F(k) is small enough
74255 : */
74256 0 : state->repterminationtype = 1;
74257 0 : if( !state->xrep )
74258 : {
74259 0 : goto lbl_45;
74260 : }
74261 0 : mincomp_clearrequestfields(state, _state);
74262 0 : state->xupdated = ae_true;
74263 0 : state->rstate.stage = 8;
74264 0 : goto lbl_rcomm;
74265 0 : lbl_8:
74266 0 : state->xupdated = ae_false;
74267 0 : lbl_45:
74268 0 : result = ae_false;
74269 0 : return result;
74270 0 : lbl_43:
74271 :
74272 : /*
74273 : * Decide - should we switch algorithm or not
74274 : */
74275 0 : if( mincomp_asauisempty(state, _state) )
74276 : {
74277 0 : if( ae_fp_greater_eq(mincomp_asaginorm(state, _state),state->mu*mincomp_asad1norm(state, _state)) )
74278 : {
74279 0 : state->curalgo = 1;
74280 0 : goto lbl_22;
74281 : }
74282 : else
74283 : {
74284 0 : state->mu = state->mu*mincomp_asarho;
74285 : }
74286 : }
74287 : else
74288 : {
74289 0 : if( state->acount==mincomp_n1 )
74290 : {
74291 0 : if( ae_fp_greater_eq(mincomp_asaginorm(state, _state),state->mu*mincomp_asad1norm(state, _state)) )
74292 : {
74293 0 : state->curalgo = 1;
74294 0 : goto lbl_22;
74295 : }
74296 : }
74297 : }
74298 :
74299 : /*
74300 : * Next iteration
74301 : */
74302 0 : state->k = state->k+1;
74303 0 : goto lbl_21;
74304 0 : lbl_22:
74305 0 : lbl_19:
74306 :
74307 : /*
74308 : * CG algorithm
74309 : */
74310 0 : if( state->curalgo!=1 )
74311 : {
74312 0 : goto lbl_47;
74313 : }
74314 :
74315 : /*
74316 : * first, check that there are non-active constraints.
74317 : * move to GPA algorithm, if all constraints are active
74318 : */
74319 0 : b = ae_true;
74320 0 : for(i=0; i<=n-1; i++)
74321 : {
74322 0 : if( ae_fp_neq(state->ak.ptr.p_double[i],(double)(0)) )
74323 : {
74324 0 : b = ae_false;
74325 0 : break;
74326 : }
74327 : }
74328 0 : if( b )
74329 : {
74330 0 : state->curalgo = 0;
74331 0 : goto lbl_17;
74332 : }
74333 :
74334 : /*
74335 : * CG iterations
74336 : */
74337 0 : state->fold = state->f;
74338 0 : ae_v_move(&state->xk.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1));
74339 0 : for(i=0; i<=n-1; i++)
74340 : {
74341 0 : state->dk.ptr.p_double[i] = -state->g.ptr.p_double[i]*state->ak.ptr.p_double[i];
74342 0 : state->gc.ptr.p_double[i] = state->g.ptr.p_double[i]*state->ak.ptr.p_double[i];
74343 : }
74344 0 : lbl_49:
74345 : if( ae_false )
74346 : {
74347 : goto lbl_50;
74348 : }
74349 :
74350 : /*
74351 : * Store G[k] for later calculation of Y[k]
74352 : */
74353 0 : for(i=0; i<=n-1; i++)
74354 : {
74355 0 : state->yk.ptr.p_double[i] = -state->gc.ptr.p_double[i];
74356 : }
74357 :
74358 : /*
74359 : * Make a CG step in direction given by DK[]:
74360 : * * calculate step. Step projection into feasible set
74361 : * is used. It has several benefits: a) step may be
74362 : * found with usual line search, b) multiple constraints
74363 : * may be activated with one step, c) activated constraints
74364 : * are detected in a natural way - just compare x[i] with
74365 : * bounds
74366 : * * update active set, set B to True, if there
74367 : * were changes in the set.
74368 : */
74369 0 : ae_v_move(&state->d.ptr.p_double[0], 1, &state->dk.ptr.p_double[0], 1, ae_v_len(0,n-1));
74370 0 : ae_v_move(&state->xn.ptr.p_double[0], 1, &state->xk.ptr.p_double[0], 1, ae_v_len(0,n-1));
74371 0 : state->mcstage = 0;
74372 0 : state->stp = (double)(1);
74373 0 : linminnormalized(&state->d, &state->stp, n, _state);
74374 0 : if( ae_fp_neq(state->laststep,(double)(0)) )
74375 : {
74376 0 : state->stp = state->laststep;
74377 : }
74378 0 : 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);
74379 0 : lbl_51:
74380 0 : if( state->mcstage==0 )
74381 : {
74382 0 : goto lbl_52;
74383 : }
74384 :
74385 : /*
74386 : * preprocess data: bound State.XN so it belongs to the
74387 : * feasible set and store it in the State.X
74388 : */
74389 0 : for(i=0; i<=n-1; i++)
74390 : {
74391 0 : 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);
74392 : }
74393 :
74394 : /*
74395 : * RComm
74396 : */
74397 0 : mincomp_clearrequestfields(state, _state);
74398 0 : state->needfg = ae_true;
74399 0 : state->rstate.stage = 9;
74400 0 : goto lbl_rcomm;
74401 0 : lbl_9:
74402 0 : state->needfg = ae_false;
74403 :
74404 : /*
74405 : * postprocess data: zero components of G corresponding to
74406 : * the active constraints
74407 : */
74408 0 : for(i=0; i<=n-1; i++)
74409 : {
74410 0 : 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]) )
74411 : {
74412 0 : state->gc.ptr.p_double[i] = (double)(0);
74413 : }
74414 : else
74415 : {
74416 0 : state->gc.ptr.p_double[i] = state->g.ptr.p_double[i];
74417 : }
74418 : }
74419 0 : 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);
74420 0 : goto lbl_51;
74421 0 : lbl_52:
74422 0 : diffcnt = 0;
74423 0 : for(i=0; i<=n-1; i++)
74424 : {
74425 :
74426 : /*
74427 : * XN contains unprojected result, project it,
74428 : * save copy to X (will be used for progress reporting)
74429 : */
74430 0 : 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);
74431 :
74432 : /*
74433 : * update active set
74434 : */
74435 0 : 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]) )
74436 : {
74437 0 : state->an.ptr.p_double[i] = (double)(0);
74438 : }
74439 : else
74440 : {
74441 0 : state->an.ptr.p_double[i] = (double)(1);
74442 : }
74443 0 : if( ae_fp_neq(state->an.ptr.p_double[i],state->ak.ptr.p_double[i]) )
74444 : {
74445 0 : diffcnt = diffcnt+1;
74446 : }
74447 0 : state->ak.ptr.p_double[i] = state->an.ptr.p_double[i];
74448 : }
74449 0 : ae_v_move(&state->xk.ptr.p_double[0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1));
74450 0 : state->repnfev = state->repnfev+state->nfev;
74451 0 : state->repiterationscount = state->repiterationscount+1;
74452 0 : if( !state->xrep )
74453 : {
74454 0 : goto lbl_53;
74455 : }
74456 :
74457 : /*
74458 : * progress report
74459 : */
74460 0 : mincomp_clearrequestfields(state, _state);
74461 0 : state->xupdated = ae_true;
74462 0 : state->rstate.stage = 10;
74463 0 : goto lbl_rcomm;
74464 0 : lbl_10:
74465 0 : state->xupdated = ae_false;
74466 0 : lbl_53:
74467 :
74468 : /*
74469 : * Update info about step length
74470 : */
74471 0 : v = ae_v_dotproduct(&state->d.ptr.p_double[0], 1, &state->d.ptr.p_double[0], 1, ae_v_len(0,n-1));
74472 0 : state->laststep = ae_sqrt(v, _state)*state->stp;
74473 :
74474 : /*
74475 : * Check stopping conditions.
74476 : */
74477 0 : if( ae_fp_greater(mincomp_asaboundedantigradnorm(state, _state),state->epsg) )
74478 : {
74479 0 : goto lbl_55;
74480 : }
74481 :
74482 : /*
74483 : * Gradient is small enough
74484 : */
74485 0 : state->repterminationtype = 4;
74486 0 : if( !state->xrep )
74487 : {
74488 0 : goto lbl_57;
74489 : }
74490 0 : mincomp_clearrequestfields(state, _state);
74491 0 : state->xupdated = ae_true;
74492 0 : state->rstate.stage = 11;
74493 0 : goto lbl_rcomm;
74494 0 : lbl_11:
74495 0 : state->xupdated = ae_false;
74496 0 : lbl_57:
74497 0 : result = ae_false;
74498 0 : return result;
74499 0 : lbl_55:
74500 0 : if( !(state->repiterationscount>=state->maxits&&state->maxits>0) )
74501 : {
74502 0 : goto lbl_59;
74503 : }
74504 :
74505 : /*
74506 : * Too many iterations
74507 : */
74508 0 : state->repterminationtype = 5;
74509 0 : if( !state->xrep )
74510 : {
74511 0 : goto lbl_61;
74512 : }
74513 0 : mincomp_clearrequestfields(state, _state);
74514 0 : state->xupdated = ae_true;
74515 0 : state->rstate.stage = 12;
74516 0 : goto lbl_rcomm;
74517 0 : lbl_12:
74518 0 : state->xupdated = ae_false;
74519 0 : lbl_61:
74520 0 : result = ae_false;
74521 0 : return result;
74522 0 : lbl_59:
74523 0 : if( !(ae_fp_greater_eq(mincomp_asaginorm(state, _state),state->mu*mincomp_asad1norm(state, _state))&&diffcnt==0) )
74524 : {
74525 0 : goto lbl_63;
74526 : }
74527 :
74528 : /*
74529 : * These conditions (EpsF/EpsX) are explicitly or implicitly
74530 : * related to the current step size and influenced
74531 : * by changes in the active constraints.
74532 : *
74533 : * For these reasons they are checked only when we don't
74534 : * want to 'unstick' at the end of the iteration and there
74535 : * were no changes in the active set.
74536 : *
74537 : * NOTE: consition |G|>=Mu*|D1| must be exactly opposite
74538 : * to the condition used to switch back to GPA. At least
74539 : * one inequality must be strict, otherwise infinite cycle
74540 : * may occur when |G|=Mu*|D1| (we DON'T test stopping
74541 : * conditions and we DON'T switch to GPA, so we cycle
74542 : * indefinitely).
74543 : */
74544 0 : 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)) )
74545 : {
74546 0 : goto lbl_65;
74547 : }
74548 :
74549 : /*
74550 : * F(k+1)-F(k) is small enough
74551 : */
74552 0 : state->repterminationtype = 1;
74553 0 : if( !state->xrep )
74554 : {
74555 0 : goto lbl_67;
74556 : }
74557 0 : mincomp_clearrequestfields(state, _state);
74558 0 : state->xupdated = ae_true;
74559 0 : state->rstate.stage = 13;
74560 0 : goto lbl_rcomm;
74561 0 : lbl_13:
74562 0 : state->xupdated = ae_false;
74563 0 : lbl_67:
74564 0 : result = ae_false;
74565 0 : return result;
74566 0 : lbl_65:
74567 0 : if( ae_fp_greater(state->laststep,state->epsx) )
74568 : {
74569 0 : goto lbl_69;
74570 : }
74571 :
74572 : /*
74573 : * X(k+1)-X(k) is small enough
74574 : */
74575 0 : state->repterminationtype = 2;
74576 0 : if( !state->xrep )
74577 : {
74578 0 : goto lbl_71;
74579 : }
74580 0 : mincomp_clearrequestfields(state, _state);
74581 0 : state->xupdated = ae_true;
74582 0 : state->rstate.stage = 14;
74583 0 : goto lbl_rcomm;
74584 0 : lbl_14:
74585 0 : state->xupdated = ae_false;
74586 0 : lbl_71:
74587 0 : result = ae_false;
74588 0 : return result;
74589 0 : lbl_69:
74590 0 : lbl_63:
74591 :
74592 : /*
74593 : * Check conditions for switching
74594 : */
74595 0 : if( ae_fp_less(mincomp_asaginorm(state, _state),state->mu*mincomp_asad1norm(state, _state)) )
74596 : {
74597 0 : state->curalgo = 0;
74598 0 : goto lbl_50;
74599 : }
74600 0 : if( diffcnt>0 )
74601 : {
74602 0 : if( mincomp_asauisempty(state, _state)||diffcnt>=mincomp_n2 )
74603 : {
74604 0 : state->curalgo = 1;
74605 : }
74606 : else
74607 : {
74608 0 : state->curalgo = 0;
74609 : }
74610 0 : goto lbl_50;
74611 : }
74612 :
74613 : /*
74614 : * Calculate D(k+1)
74615 : *
74616 : * Line search may result in:
74617 : * * maximum feasible step being taken (already processed)
74618 : * * point satisfying Wolfe conditions
74619 : * * some kind of error (CG is restarted by assigning 0.0 to Beta)
74620 : */
74621 0 : if( mcinfo==1 )
74622 : {
74623 :
74624 : /*
74625 : * Standard Wolfe conditions are satisfied:
74626 : * * calculate Y[K] and BetaK
74627 : */
74628 0 : ae_v_add(&state->yk.ptr.p_double[0], 1, &state->gc.ptr.p_double[0], 1, ae_v_len(0,n-1));
74629 0 : vv = ae_v_dotproduct(&state->yk.ptr.p_double[0], 1, &state->dk.ptr.p_double[0], 1, ae_v_len(0,n-1));
74630 0 : v = ae_v_dotproduct(&state->gc.ptr.p_double[0], 1, &state->gc.ptr.p_double[0], 1, ae_v_len(0,n-1));
74631 0 : state->betady = v/vv;
74632 0 : v = ae_v_dotproduct(&state->gc.ptr.p_double[0], 1, &state->yk.ptr.p_double[0], 1, ae_v_len(0,n-1));
74633 0 : state->betahs = v/vv;
74634 0 : if( state->cgtype==0 )
74635 : {
74636 0 : betak = state->betady;
74637 : }
74638 0 : if( state->cgtype==1 )
74639 : {
74640 0 : betak = ae_maxreal((double)(0), ae_minreal(state->betady, state->betahs, _state), _state);
74641 : }
74642 : }
74643 : else
74644 : {
74645 :
74646 : /*
74647 : * Something is wrong (may be function is too wild or too flat).
74648 : *
74649 : * We'll set BetaK=0, which will restart CG algorithm.
74650 : * We can stop later (during normal checks) if stopping conditions are met.
74651 : */
74652 0 : betak = (double)(0);
74653 0 : state->debugrestartscount = state->debugrestartscount+1;
74654 : }
74655 0 : ae_v_moveneg(&state->dn.ptr.p_double[0], 1, &state->gc.ptr.p_double[0], 1, ae_v_len(0,n-1));
74656 0 : ae_v_addd(&state->dn.ptr.p_double[0], 1, &state->dk.ptr.p_double[0], 1, ae_v_len(0,n-1), betak);
74657 0 : ae_v_move(&state->dk.ptr.p_double[0], 1, &state->dn.ptr.p_double[0], 1, ae_v_len(0,n-1));
74658 :
74659 : /*
74660 : * update other information
74661 : */
74662 0 : state->fold = state->f;
74663 0 : state->k = state->k+1;
74664 0 : goto lbl_49;
74665 0 : lbl_50:
74666 0 : lbl_47:
74667 0 : goto lbl_17;
74668 : lbl_18:
74669 : result = ae_false;
74670 : return result;
74671 :
74672 : /*
74673 : * Saving state
74674 : */
74675 0 : lbl_rcomm:
74676 0 : result = ae_true;
74677 0 : state->rstate.ia.ptr.p_int[0] = n;
74678 0 : state->rstate.ia.ptr.p_int[1] = i;
74679 0 : state->rstate.ia.ptr.p_int[2] = mcinfo;
74680 0 : state->rstate.ia.ptr.p_int[3] = diffcnt;
74681 0 : state->rstate.ba.ptr.p_bool[0] = b;
74682 0 : state->rstate.ba.ptr.p_bool[1] = stepfound;
74683 0 : state->rstate.ra.ptr.p_double[0] = betak;
74684 0 : state->rstate.ra.ptr.p_double[1] = v;
74685 0 : state->rstate.ra.ptr.p_double[2] = vv;
74686 0 : return result;
74687 : }
74688 :
74689 :
74690 : /*************************************************************************
74691 : Obsolete optimization algorithm.
74692 : Was replaced by MinBLEIC subpackage.
74693 :
74694 : -- ALGLIB --
74695 : Copyright 20.03.2009 by Bochkanov Sergey
74696 : *************************************************************************/
74697 0 : void minasaresults(minasastate* state,
74698 : /* Real */ ae_vector* x,
74699 : minasareport* rep,
74700 : ae_state *_state)
74701 : {
74702 :
74703 0 : ae_vector_clear(x);
74704 0 : _minasareport_clear(rep);
74705 :
74706 0 : minasaresultsbuf(state, x, rep, _state);
74707 0 : }
74708 :
74709 :
74710 : /*************************************************************************
74711 : Obsolete optimization algorithm.
74712 : Was replaced by MinBLEIC subpackage.
74713 :
74714 : -- ALGLIB --
74715 : Copyright 20.03.2009 by Bochkanov Sergey
74716 : *************************************************************************/
74717 0 : void minasaresultsbuf(minasastate* state,
74718 : /* Real */ ae_vector* x,
74719 : minasareport* rep,
74720 : ae_state *_state)
74721 : {
74722 : ae_int_t i;
74723 :
74724 :
74725 0 : if( x->cnt<state->n )
74726 : {
74727 0 : ae_vector_set_length(x, state->n, _state);
74728 : }
74729 0 : ae_v_move(&x->ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,state->n-1));
74730 0 : rep->iterationscount = state->repiterationscount;
74731 0 : rep->nfev = state->repnfev;
74732 0 : rep->terminationtype = state->repterminationtype;
74733 0 : rep->activeconstraints = 0;
74734 0 : for(i=0; i<=state->n-1; i++)
74735 : {
74736 0 : if( ae_fp_eq(state->ak.ptr.p_double[i],(double)(0)) )
74737 : {
74738 0 : rep->activeconstraints = rep->activeconstraints+1;
74739 : }
74740 : }
74741 0 : }
74742 :
74743 :
74744 : /*************************************************************************
74745 : Obsolete optimization algorithm.
74746 : Was replaced by MinBLEIC subpackage.
74747 :
74748 : -- ALGLIB --
74749 : Copyright 30.07.2010 by Bochkanov Sergey
74750 : *************************************************************************/
74751 0 : void minasarestartfrom(minasastate* state,
74752 : /* Real */ ae_vector* x,
74753 : /* Real */ ae_vector* bndl,
74754 : /* Real */ ae_vector* bndu,
74755 : ae_state *_state)
74756 : {
74757 :
74758 :
74759 0 : ae_assert(x->cnt>=state->n, "MinASARestartFrom: Length(X)<N!", _state);
74760 0 : ae_assert(isfinitevector(x, state->n, _state), "MinASARestartFrom: X contains infinite or NaN values!", _state);
74761 0 : ae_assert(bndl->cnt>=state->n, "MinASARestartFrom: Length(BndL)<N!", _state);
74762 0 : ae_assert(isfinitevector(bndl, state->n, _state), "MinASARestartFrom: BndL contains infinite or NaN values!", _state);
74763 0 : ae_assert(bndu->cnt>=state->n, "MinASARestartFrom: Length(BndU)<N!", _state);
74764 0 : ae_assert(isfinitevector(bndu, state->n, _state), "MinASARestartFrom: BndU contains infinite or NaN values!", _state);
74765 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,state->n-1));
74766 0 : ae_v_move(&state->bndl.ptr.p_double[0], 1, &bndl->ptr.p_double[0], 1, ae_v_len(0,state->n-1));
74767 0 : ae_v_move(&state->bndu.ptr.p_double[0], 1, &bndu->ptr.p_double[0], 1, ae_v_len(0,state->n-1));
74768 0 : state->laststep = (double)(0);
74769 0 : ae_vector_set_length(&state->rstate.ia, 3+1, _state);
74770 0 : ae_vector_set_length(&state->rstate.ba, 1+1, _state);
74771 0 : ae_vector_set_length(&state->rstate.ra, 2+1, _state);
74772 0 : state->rstate.stage = -1;
74773 0 : mincomp_clearrequestfields(state, _state);
74774 0 : }
74775 :
74776 :
74777 : /*************************************************************************
74778 : Returns norm of bounded anti-gradient.
74779 :
74780 : Bounded antigradient is a vector obtained from anti-gradient by zeroing
74781 : components which point outwards:
74782 : result = norm(v)
74783 : v[i]=0 if ((-g[i]<0)and(x[i]=bndl[i])) or
74784 : ((-g[i]>0)and(x[i]=bndu[i]))
74785 : v[i]=-g[i] otherwise
74786 :
74787 : This function may be used to check a stopping criterion.
74788 :
74789 : -- ALGLIB --
74790 : Copyright 20.03.2009 by Bochkanov Sergey
74791 : *************************************************************************/
74792 0 : static double mincomp_asaboundedantigradnorm(minasastate* state,
74793 : ae_state *_state)
74794 : {
74795 : ae_int_t i;
74796 : double v;
74797 : double result;
74798 :
74799 :
74800 0 : result = (double)(0);
74801 0 : for(i=0; i<=state->n-1; i++)
74802 : {
74803 0 : v = -state->g.ptr.p_double[i];
74804 0 : 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],(double)(0)) )
74805 : {
74806 0 : v = (double)(0);
74807 : }
74808 0 : 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],(double)(0)) )
74809 : {
74810 0 : v = (double)(0);
74811 : }
74812 0 : result = result+ae_sqr(v, _state);
74813 : }
74814 0 : result = ae_sqrt(result, _state);
74815 0 : return result;
74816 : }
74817 :
74818 :
74819 : /*************************************************************************
74820 : Returns norm of GI(x).
74821 :
74822 : GI(x) is a gradient vector whose components associated with active
74823 : constraints are zeroed. It differs from bounded anti-gradient because
74824 : components of GI(x) are zeroed independently of sign(g[i]), and
74825 : anti-gradient's components are zeroed with respect to both constraint and
74826 : sign.
74827 :
74828 : -- ALGLIB --
74829 : Copyright 20.03.2009 by Bochkanov Sergey
74830 : *************************************************************************/
74831 0 : static double mincomp_asaginorm(minasastate* state, ae_state *_state)
74832 : {
74833 : ae_int_t i;
74834 : double result;
74835 :
74836 :
74837 0 : result = (double)(0);
74838 0 : for(i=0; i<=state->n-1; i++)
74839 : {
74840 0 : 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]) )
74841 : {
74842 0 : result = result+ae_sqr(state->g.ptr.p_double[i], _state);
74843 : }
74844 : }
74845 0 : result = ae_sqrt(result, _state);
74846 0 : return result;
74847 : }
74848 :
74849 :
74850 : /*************************************************************************
74851 : Returns norm(D1(State.X))
74852 :
74853 : For a meaning of D1 see 'NEW ACTIVE SET ALGORITHM FOR BOX CONSTRAINED
74854 : OPTIMIZATION' by WILLIAM W. HAGER AND HONGCHAO ZHANG.
74855 :
74856 : -- ALGLIB --
74857 : Copyright 20.03.2009 by Bochkanov Sergey
74858 : *************************************************************************/
74859 0 : static double mincomp_asad1norm(minasastate* state, ae_state *_state)
74860 : {
74861 : ae_int_t i;
74862 : double result;
74863 :
74864 :
74865 0 : result = (double)(0);
74866 0 : for(i=0; i<=state->n-1; i++)
74867 : {
74868 0 : 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);
74869 : }
74870 0 : result = ae_sqrt(result, _state);
74871 0 : return result;
74872 : }
74873 :
74874 :
74875 : /*************************************************************************
74876 : Returns True, if U set is empty.
74877 :
74878 : * State.X is used as point,
74879 : * State.G - as gradient,
74880 : * D is calculated within function (because State.D may have different
74881 : meaning depending on current optimization algorithm)
74882 :
74883 : For a meaning of U see 'NEW ACTIVE SET ALGORITHM FOR BOX CONSTRAINED
74884 : OPTIMIZATION' by WILLIAM W. HAGER AND HONGCHAO ZHANG.
74885 :
74886 : -- ALGLIB --
74887 : Copyright 20.03.2009 by Bochkanov Sergey
74888 : *************************************************************************/
74889 0 : static ae_bool mincomp_asauisempty(minasastate* state, ae_state *_state)
74890 : {
74891 : ae_int_t i;
74892 : double d;
74893 : double d2;
74894 : double d32;
74895 : ae_bool result;
74896 :
74897 :
74898 0 : d = mincomp_asad1norm(state, _state);
74899 0 : d2 = ae_sqrt(d, _state);
74900 0 : d32 = d*d2;
74901 0 : result = ae_true;
74902 0 : for(i=0; i<=state->n-1; i++)
74903 : {
74904 0 : 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) )
74905 : {
74906 0 : result = ae_false;
74907 0 : return result;
74908 : }
74909 : }
74910 0 : return result;
74911 : }
74912 :
74913 :
74914 : /*************************************************************************
74915 : Clears request fileds (to be sure that we don't forgot to clear something)
74916 : *************************************************************************/
74917 0 : static void mincomp_clearrequestfields(minasastate* state,
74918 : ae_state *_state)
74919 : {
74920 :
74921 :
74922 0 : state->needfg = ae_false;
74923 0 : state->xupdated = ae_false;
74924 0 : }
74925 :
74926 :
74927 0 : void _minasastate_init(void* _p, ae_state *_state, ae_bool make_automatic)
74928 : {
74929 0 : minasastate *p = (minasastate*)_p;
74930 0 : ae_touch_ptr((void*)p);
74931 0 : ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic);
74932 0 : ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic);
74933 0 : ae_vector_init(&p->ak, 0, DT_REAL, _state, make_automatic);
74934 0 : ae_vector_init(&p->xk, 0, DT_REAL, _state, make_automatic);
74935 0 : ae_vector_init(&p->dk, 0, DT_REAL, _state, make_automatic);
74936 0 : ae_vector_init(&p->an, 0, DT_REAL, _state, make_automatic);
74937 0 : ae_vector_init(&p->xn, 0, DT_REAL, _state, make_automatic);
74938 0 : ae_vector_init(&p->dn, 0, DT_REAL, _state, make_automatic);
74939 0 : ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic);
74940 0 : ae_vector_init(&p->work, 0, DT_REAL, _state, make_automatic);
74941 0 : ae_vector_init(&p->yk, 0, DT_REAL, _state, make_automatic);
74942 0 : ae_vector_init(&p->gc, 0, DT_REAL, _state, make_automatic);
74943 0 : ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
74944 0 : ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic);
74945 0 : _rcommstate_init(&p->rstate, _state, make_automatic);
74946 0 : _linminstate_init(&p->lstate, _state, make_automatic);
74947 0 : }
74948 :
74949 :
74950 0 : void _minasastate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
74951 : {
74952 0 : minasastate *dst = (minasastate*)_dst;
74953 0 : minasastate *src = (minasastate*)_src;
74954 0 : dst->n = src->n;
74955 0 : dst->epsg = src->epsg;
74956 0 : dst->epsf = src->epsf;
74957 0 : dst->epsx = src->epsx;
74958 0 : dst->maxits = src->maxits;
74959 0 : dst->xrep = src->xrep;
74960 0 : dst->stpmax = src->stpmax;
74961 0 : dst->cgtype = src->cgtype;
74962 0 : dst->k = src->k;
74963 0 : dst->nfev = src->nfev;
74964 0 : dst->mcstage = src->mcstage;
74965 0 : ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic);
74966 0 : ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic);
74967 0 : dst->curalgo = src->curalgo;
74968 0 : dst->acount = src->acount;
74969 0 : dst->mu = src->mu;
74970 0 : dst->finit = src->finit;
74971 0 : dst->dginit = src->dginit;
74972 0 : ae_vector_init_copy(&dst->ak, &src->ak, _state, make_automatic);
74973 0 : ae_vector_init_copy(&dst->xk, &src->xk, _state, make_automatic);
74974 0 : ae_vector_init_copy(&dst->dk, &src->dk, _state, make_automatic);
74975 0 : ae_vector_init_copy(&dst->an, &src->an, _state, make_automatic);
74976 0 : ae_vector_init_copy(&dst->xn, &src->xn, _state, make_automatic);
74977 0 : ae_vector_init_copy(&dst->dn, &src->dn, _state, make_automatic);
74978 0 : ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic);
74979 0 : dst->fold = src->fold;
74980 0 : dst->stp = src->stp;
74981 0 : ae_vector_init_copy(&dst->work, &src->work, _state, make_automatic);
74982 0 : ae_vector_init_copy(&dst->yk, &src->yk, _state, make_automatic);
74983 0 : ae_vector_init_copy(&dst->gc, &src->gc, _state, make_automatic);
74984 0 : dst->laststep = src->laststep;
74985 0 : ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
74986 0 : dst->f = src->f;
74987 0 : ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic);
74988 0 : dst->needfg = src->needfg;
74989 0 : dst->xupdated = src->xupdated;
74990 0 : _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic);
74991 0 : dst->repiterationscount = src->repiterationscount;
74992 0 : dst->repnfev = src->repnfev;
74993 0 : dst->repterminationtype = src->repterminationtype;
74994 0 : dst->debugrestartscount = src->debugrestartscount;
74995 0 : _linminstate_init_copy(&dst->lstate, &src->lstate, _state, make_automatic);
74996 0 : dst->betahs = src->betahs;
74997 0 : dst->betady = src->betady;
74998 0 : }
74999 :
75000 :
75001 0 : void _minasastate_clear(void* _p)
75002 : {
75003 0 : minasastate *p = (minasastate*)_p;
75004 0 : ae_touch_ptr((void*)p);
75005 0 : ae_vector_clear(&p->bndl);
75006 0 : ae_vector_clear(&p->bndu);
75007 0 : ae_vector_clear(&p->ak);
75008 0 : ae_vector_clear(&p->xk);
75009 0 : ae_vector_clear(&p->dk);
75010 0 : ae_vector_clear(&p->an);
75011 0 : ae_vector_clear(&p->xn);
75012 0 : ae_vector_clear(&p->dn);
75013 0 : ae_vector_clear(&p->d);
75014 0 : ae_vector_clear(&p->work);
75015 0 : ae_vector_clear(&p->yk);
75016 0 : ae_vector_clear(&p->gc);
75017 0 : ae_vector_clear(&p->x);
75018 0 : ae_vector_clear(&p->g);
75019 0 : _rcommstate_clear(&p->rstate);
75020 0 : _linminstate_clear(&p->lstate);
75021 0 : }
75022 :
75023 :
75024 0 : void _minasastate_destroy(void* _p)
75025 : {
75026 0 : minasastate *p = (minasastate*)_p;
75027 0 : ae_touch_ptr((void*)p);
75028 0 : ae_vector_destroy(&p->bndl);
75029 0 : ae_vector_destroy(&p->bndu);
75030 0 : ae_vector_destroy(&p->ak);
75031 0 : ae_vector_destroy(&p->xk);
75032 0 : ae_vector_destroy(&p->dk);
75033 0 : ae_vector_destroy(&p->an);
75034 0 : ae_vector_destroy(&p->xn);
75035 0 : ae_vector_destroy(&p->dn);
75036 0 : ae_vector_destroy(&p->d);
75037 0 : ae_vector_destroy(&p->work);
75038 0 : ae_vector_destroy(&p->yk);
75039 0 : ae_vector_destroy(&p->gc);
75040 0 : ae_vector_destroy(&p->x);
75041 0 : ae_vector_destroy(&p->g);
75042 0 : _rcommstate_destroy(&p->rstate);
75043 0 : _linminstate_destroy(&p->lstate);
75044 0 : }
75045 :
75046 :
75047 0 : void _minasareport_init(void* _p, ae_state *_state, ae_bool make_automatic)
75048 : {
75049 0 : minasareport *p = (minasareport*)_p;
75050 0 : ae_touch_ptr((void*)p);
75051 0 : }
75052 :
75053 :
75054 0 : void _minasareport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
75055 : {
75056 0 : minasareport *dst = (minasareport*)_dst;
75057 0 : minasareport *src = (minasareport*)_src;
75058 0 : dst->iterationscount = src->iterationscount;
75059 0 : dst->nfev = src->nfev;
75060 0 : dst->terminationtype = src->terminationtype;
75061 0 : dst->activeconstraints = src->activeconstraints;
75062 0 : }
75063 :
75064 :
75065 0 : void _minasareport_clear(void* _p)
75066 : {
75067 0 : minasareport *p = (minasareport*)_p;
75068 0 : ae_touch_ptr((void*)p);
75069 0 : }
75070 :
75071 :
75072 0 : void _minasareport_destroy(void* _p)
75073 : {
75074 0 : minasareport *p = (minasareport*)_p;
75075 0 : ae_touch_ptr((void*)p);
75076 0 : }
75077 :
75078 :
75079 : #endif
75080 : #if defined(AE_COMPILE_MINCG) || !defined(AE_PARTIAL_BUILD)
75081 :
75082 :
75083 : /*************************************************************************
75084 : NONLINEAR CONJUGATE GRADIENT METHOD
75085 :
75086 : DESCRIPTION:
75087 : The subroutine minimizes function F(x) of N arguments by using one of the
75088 : nonlinear conjugate gradient methods.
75089 :
75090 : These CG methods are globally convergent (even on non-convex functions) as
75091 : long as grad(f) is Lipschitz continuous in a some neighborhood of the
75092 : L = { x : f(x)<=f(x0) }.
75093 :
75094 :
75095 : REQUIREMENTS:
75096 : Algorithm will request following information during its operation:
75097 : * function value F and its gradient G (simultaneously) at given point X
75098 :
75099 :
75100 : USAGE:
75101 : 1. User initializes algorithm state with MinCGCreate() call
75102 : 2. User tunes solver parameters with MinCGSetCond(), MinCGSetStpMax() and
75103 : other functions
75104 : 3. User calls MinCGOptimize() function which takes algorithm state and
75105 : pointer (delegate, etc.) to callback function which calculates F/G.
75106 : 4. User calls MinCGResults() to get solution
75107 : 5. Optionally, user may call MinCGRestartFrom() to solve another problem
75108 : with same N but another starting point and/or another function.
75109 : MinCGRestartFrom() allows to reuse already initialized structure.
75110 :
75111 :
75112 : INPUT PARAMETERS:
75113 : N - problem dimension, N>0:
75114 : * if given, only leading N elements of X are used
75115 : * if not given, automatically determined from size of X
75116 : X - starting point, array[0..N-1].
75117 :
75118 : OUTPUT PARAMETERS:
75119 : State - structure which stores algorithm state
75120 :
75121 : -- ALGLIB --
75122 : Copyright 25.03.2010 by Bochkanov Sergey
75123 : *************************************************************************/
75124 0 : void mincgcreate(ae_int_t n,
75125 : /* Real */ ae_vector* x,
75126 : mincgstate* state,
75127 : ae_state *_state)
75128 : {
75129 :
75130 0 : _mincgstate_clear(state);
75131 :
75132 0 : ae_assert(n>=1, "MinCGCreate: N too small!", _state);
75133 0 : ae_assert(x->cnt>=n, "MinCGCreate: Length(X)<N!", _state);
75134 0 : ae_assert(isfinitevector(x, n, _state), "MinCGCreate: X contains infinite or NaN values!", _state);
75135 0 : mincg_mincginitinternal(n, 0.0, state, _state);
75136 0 : mincgrestartfrom(state, x, _state);
75137 0 : }
75138 :
75139 :
75140 : /*************************************************************************
75141 : The subroutine is finite difference variant of MinCGCreate(). It uses
75142 : finite differences in order to differentiate target function.
75143 :
75144 : Description below contains information which is specific to this function
75145 : only. We recommend to read comments on MinCGCreate() in order to get more
75146 : information about creation of CG optimizer.
75147 :
75148 : INPUT PARAMETERS:
75149 : N - problem dimension, N>0:
75150 : * if given, only leading N elements of X are used
75151 : * if not given, automatically determined from size of X
75152 : X - starting point, array[0..N-1].
75153 : DiffStep- differentiation step, >0
75154 :
75155 : OUTPUT PARAMETERS:
75156 : State - structure which stores algorithm state
75157 :
75158 : NOTES:
75159 : 1. algorithm uses 4-point central formula for differentiation.
75160 : 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
75161 : S[] is scaling vector which can be set by MinCGSetScale() call.
75162 : 3. we recommend you to use moderate values of differentiation step. Too
75163 : large step will result in too large truncation errors, while too small
75164 : step will result in too large numerical errors. 1.0E-6 can be good
75165 : value to start with.
75166 : 4. Numerical differentiation is very inefficient - one gradient
75167 : calculation needs 4*N function evaluations. This function will work for
75168 : any N - either small (1...10), moderate (10...100) or large (100...).
75169 : However, performance penalty will be too severe for any N's except for
75170 : small ones.
75171 : We should also say that code which relies on numerical differentiation
75172 : is less robust and precise. L-BFGS needs exact gradient values.
75173 : Imprecise gradient may slow down convergence, especially on highly
75174 : nonlinear problems.
75175 : Thus we recommend to use this function for fast prototyping on small-
75176 : dimensional problems only, and to implement analytical gradient as soon
75177 : as possible.
75178 :
75179 : -- ALGLIB --
75180 : Copyright 16.05.2011 by Bochkanov Sergey
75181 : *************************************************************************/
75182 0 : void mincgcreatef(ae_int_t n,
75183 : /* Real */ ae_vector* x,
75184 : double diffstep,
75185 : mincgstate* state,
75186 : ae_state *_state)
75187 : {
75188 :
75189 0 : _mincgstate_clear(state);
75190 :
75191 0 : ae_assert(n>=1, "MinCGCreateF: N too small!", _state);
75192 0 : ae_assert(x->cnt>=n, "MinCGCreateF: Length(X)<N!", _state);
75193 0 : ae_assert(isfinitevector(x, n, _state), "MinCGCreateF: X contains infinite or NaN values!", _state);
75194 0 : ae_assert(ae_isfinite(diffstep, _state), "MinCGCreateF: DiffStep is infinite or NaN!", _state);
75195 0 : ae_assert(ae_fp_greater(diffstep,(double)(0)), "MinCGCreateF: DiffStep is non-positive!", _state);
75196 0 : mincg_mincginitinternal(n, diffstep, state, _state);
75197 0 : mincgrestartfrom(state, x, _state);
75198 0 : }
75199 :
75200 :
75201 : /*************************************************************************
75202 : This function sets stopping conditions for CG optimization algorithm.
75203 :
75204 : INPUT PARAMETERS:
75205 : State - structure which stores algorithm state
75206 : EpsG - >=0
75207 : The subroutine finishes its work if the condition
75208 : |v|<EpsG is satisfied, where:
75209 : * |.| means Euclidian norm
75210 : * v - scaled gradient vector, v[i]=g[i]*s[i]
75211 : * g - gradient
75212 : * s - scaling coefficients set by MinCGSetScale()
75213 : EpsF - >=0
75214 : The subroutine finishes its work if on k+1-th iteration
75215 : the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
75216 : is satisfied.
75217 : EpsX - >=0
75218 : The subroutine finishes its work if on k+1-th iteration
75219 : the condition |v|<=EpsX is fulfilled, where:
75220 : * |.| means Euclidian norm
75221 : * v - scaled step vector, v[i]=dx[i]/s[i]
75222 : * dx - ste pvector, dx=X(k+1)-X(k)
75223 : * s - scaling coefficients set by MinCGSetScale()
75224 : MaxIts - maximum number of iterations. If MaxIts=0, the number of
75225 : iterations is unlimited.
75226 :
75227 : Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to
75228 : automatic stopping criterion selection (small EpsX).
75229 :
75230 : -- ALGLIB --
75231 : Copyright 02.04.2010 by Bochkanov Sergey
75232 : *************************************************************************/
75233 0 : void mincgsetcond(mincgstate* state,
75234 : double epsg,
75235 : double epsf,
75236 : double epsx,
75237 : ae_int_t maxits,
75238 : ae_state *_state)
75239 : {
75240 :
75241 :
75242 0 : ae_assert(ae_isfinite(epsg, _state), "MinCGSetCond: EpsG is not finite number!", _state);
75243 0 : ae_assert(ae_fp_greater_eq(epsg,(double)(0)), "MinCGSetCond: negative EpsG!", _state);
75244 0 : ae_assert(ae_isfinite(epsf, _state), "MinCGSetCond: EpsF is not finite number!", _state);
75245 0 : ae_assert(ae_fp_greater_eq(epsf,(double)(0)), "MinCGSetCond: negative EpsF!", _state);
75246 0 : ae_assert(ae_isfinite(epsx, _state), "MinCGSetCond: EpsX is not finite number!", _state);
75247 0 : ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "MinCGSetCond: negative EpsX!", _state);
75248 0 : ae_assert(maxits>=0, "MinCGSetCond: negative MaxIts!", _state);
75249 0 : if( ((ae_fp_eq(epsg,(double)(0))&&ae_fp_eq(epsf,(double)(0)))&&ae_fp_eq(epsx,(double)(0)))&&maxits==0 )
75250 : {
75251 0 : epsx = 1.0E-6;
75252 : }
75253 0 : state->epsg = epsg;
75254 0 : state->epsf = epsf;
75255 0 : state->epsx = epsx;
75256 0 : state->maxits = maxits;
75257 0 : }
75258 :
75259 :
75260 : /*************************************************************************
75261 : This function sets scaling coefficients for CG optimizer.
75262 :
75263 : ALGLIB optimizers use scaling matrices to test stopping conditions (step
75264 : size and gradient are scaled before comparison with tolerances). Scale of
75265 : the I-th variable is a translation invariant measure of:
75266 : a) "how large" the variable is
75267 : b) how large the step should be to make significant changes in the function
75268 :
75269 : Scaling is also used by finite difference variant of CG optimizer - step
75270 : along I-th axis is equal to DiffStep*S[I].
75271 :
75272 : In most optimizers (and in the CG too) scaling is NOT a form of
75273 : preconditioning. It just affects stopping conditions. You should set
75274 : preconditioner by separate call to one of the MinCGSetPrec...() functions.
75275 :
75276 : There is special preconditioning mode, however, which uses scaling
75277 : coefficients to form diagonal preconditioning matrix. You can turn this
75278 : mode on, if you want. But you should understand that scaling is not the
75279 : same thing as preconditioning - these are two different, although related
75280 : forms of tuning solver.
75281 :
75282 : INPUT PARAMETERS:
75283 : State - structure stores algorithm state
75284 : S - array[N], non-zero scaling coefficients
75285 : S[i] may be negative, sign doesn't matter.
75286 :
75287 : -- ALGLIB --
75288 : Copyright 14.01.2011 by Bochkanov Sergey
75289 : *************************************************************************/
75290 0 : void mincgsetscale(mincgstate* state,
75291 : /* Real */ ae_vector* s,
75292 : ae_state *_state)
75293 : {
75294 : ae_int_t i;
75295 :
75296 :
75297 0 : ae_assert(s->cnt>=state->n, "MinCGSetScale: Length(S)<N", _state);
75298 0 : for(i=0; i<=state->n-1; i++)
75299 : {
75300 0 : ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "MinCGSetScale: S contains infinite or NAN elements", _state);
75301 0 : ae_assert(ae_fp_neq(s->ptr.p_double[i],(double)(0)), "MinCGSetScale: S contains zero elements", _state);
75302 0 : state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state);
75303 : }
75304 0 : }
75305 :
75306 :
75307 : /*************************************************************************
75308 : This function turns on/off reporting.
75309 :
75310 : INPUT PARAMETERS:
75311 : State - structure which stores algorithm state
75312 : NeedXRep- whether iteration reports are needed or not
75313 :
75314 : If NeedXRep is True, algorithm will call rep() callback function if it is
75315 : provided to MinCGOptimize().
75316 :
75317 : -- ALGLIB --
75318 : Copyright 02.04.2010 by Bochkanov Sergey
75319 : *************************************************************************/
75320 0 : void mincgsetxrep(mincgstate* state, ae_bool needxrep, ae_state *_state)
75321 : {
75322 :
75323 :
75324 0 : state->xrep = needxrep;
75325 0 : }
75326 :
75327 :
75328 : /*************************************************************************
75329 : This function turns on/off line search reports.
75330 : These reports are described in more details in developer-only comments on
75331 : MinCGState object.
75332 :
75333 : INPUT PARAMETERS:
75334 : State - structure which stores algorithm state
75335 : NeedDRep- whether line search reports are needed or not
75336 :
75337 : This function is intended for private use only. Turning it on artificially
75338 : may cause program failure.
75339 :
75340 : -- ALGLIB --
75341 : Copyright 02.04.2010 by Bochkanov Sergey
75342 : *************************************************************************/
75343 0 : void mincgsetdrep(mincgstate* state, ae_bool needdrep, ae_state *_state)
75344 : {
75345 :
75346 :
75347 0 : state->drep = needdrep;
75348 0 : }
75349 :
75350 :
75351 : /*************************************************************************
75352 : This function sets CG algorithm.
75353 :
75354 : INPUT PARAMETERS:
75355 : State - structure which stores algorithm state
75356 : CGType - algorithm type:
75357 : * -1 automatic selection of the best algorithm
75358 : * 0 DY (Dai and Yuan) algorithm
75359 : * 1 Hybrid DY-HS algorithm
75360 :
75361 : -- ALGLIB --
75362 : Copyright 02.04.2010 by Bochkanov Sergey
75363 : *************************************************************************/
75364 0 : void mincgsetcgtype(mincgstate* state, ae_int_t cgtype, ae_state *_state)
75365 : {
75366 :
75367 :
75368 0 : ae_assert(cgtype>=-1&&cgtype<=1, "MinCGSetCGType: incorrect CGType!", _state);
75369 0 : if( cgtype==-1 )
75370 : {
75371 0 : cgtype = 1;
75372 : }
75373 0 : state->cgtype = cgtype;
75374 0 : }
75375 :
75376 :
75377 : /*************************************************************************
75378 : This function sets maximum step length
75379 :
75380 : INPUT PARAMETERS:
75381 : State - structure which stores algorithm state
75382 : StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't
75383 : want to limit step length.
75384 :
75385 : Use this subroutine when you optimize target function which contains exp()
75386 : or other fast growing functions, and optimization algorithm makes too
75387 : large steps which leads to overflow. This function allows us to reject
75388 : steps that are too large (and therefore expose us to the possible
75389 : overflow) without actually calculating function value at the x+stp*d.
75390 :
75391 : -- ALGLIB --
75392 : Copyright 02.04.2010 by Bochkanov Sergey
75393 : *************************************************************************/
75394 0 : void mincgsetstpmax(mincgstate* state, double stpmax, ae_state *_state)
75395 : {
75396 :
75397 :
75398 0 : ae_assert(ae_isfinite(stpmax, _state), "MinCGSetStpMax: StpMax is not finite!", _state);
75399 0 : ae_assert(ae_fp_greater_eq(stpmax,(double)(0)), "MinCGSetStpMax: StpMax<0!", _state);
75400 0 : state->stpmax = stpmax;
75401 0 : }
75402 :
75403 :
75404 : /*************************************************************************
75405 : This function allows to suggest initial step length to the CG algorithm.
75406 :
75407 : Suggested step length is used as starting point for the line search. It
75408 : can be useful when you have badly scaled problem, i.e. when ||grad||
75409 : (which is used as initial estimate for the first step) is many orders of
75410 : magnitude different from the desired step.
75411 :
75412 : Line search may fail on such problems without good estimate of initial
75413 : step length. Imagine, for example, problem with ||grad||=10^50 and desired
75414 : step equal to 0.1 Line search function will use 10^50 as initial step,
75415 : then it will decrease step length by 2 (up to 20 attempts) and will get
75416 : 10^44, which is still too large.
75417 :
75418 : This function allows us to tell than line search should be started from
75419 : some moderate step length, like 1.0, so algorithm will be able to detect
75420 : desired step length in a several searches.
75421 :
75422 : Default behavior (when no step is suggested) is to use preconditioner, if
75423 : it is available, to generate initial estimate of step length.
75424 :
75425 : This function influences only first iteration of algorithm. It should be
75426 : called between MinCGCreate/MinCGRestartFrom() call and MinCGOptimize call.
75427 : Suggested step is ignored if you have preconditioner.
75428 :
75429 : INPUT PARAMETERS:
75430 : State - structure used to store algorithm state.
75431 : Stp - initial estimate of the step length.
75432 : Can be zero (no estimate).
75433 :
75434 : -- ALGLIB --
75435 : Copyright 30.07.2010 by Bochkanov Sergey
75436 : *************************************************************************/
75437 0 : void mincgsuggeststep(mincgstate* state, double stp, ae_state *_state)
75438 : {
75439 :
75440 :
75441 0 : ae_assert(ae_isfinite(stp, _state), "MinCGSuggestStep: Stp is infinite or NAN", _state);
75442 0 : ae_assert(ae_fp_greater_eq(stp,(double)(0)), "MinCGSuggestStep: Stp<0", _state);
75443 0 : state->suggestedstep = stp;
75444 0 : }
75445 :
75446 :
75447 : /*************************************************************************
75448 : This developer-only function allows to retrieve unscaled (!) length of
75449 : last good step (i.e. step which resulted in sufficient decrease of target
75450 : function).
75451 :
75452 : It can be used in for solution of sequential optimization subproblems,
75453 : where MinCGSuggestStep() is called with length of previous step as
75454 : parameter.
75455 :
75456 : INPUT PARAMETERS:
75457 : State - structure used to store algorithm state.
75458 :
75459 : RESULT:
75460 : length of last good step being accepted
75461 :
75462 : NOTE:
75463 : result of this function is undefined if you called it before
75464 :
75465 : -- ALGLIB --
75466 : Copyright 30.07.2010 by Bochkanov Sergey
75467 : *************************************************************************/
75468 0 : double mincglastgoodstep(mincgstate* state, ae_state *_state)
75469 : {
75470 : double result;
75471 :
75472 :
75473 0 : result = state->lastgoodstep;
75474 0 : return result;
75475 : }
75476 :
75477 :
75478 : /*************************************************************************
75479 : Modification of the preconditioner: preconditioning is turned off.
75480 :
75481 : INPUT PARAMETERS:
75482 : State - structure which stores algorithm state
75483 :
75484 : NOTE: you can change preconditioner "on the fly", during algorithm
75485 : iterations.
75486 :
75487 : -- ALGLIB --
75488 : Copyright 13.10.2010 by Bochkanov Sergey
75489 : *************************************************************************/
75490 0 : void mincgsetprecdefault(mincgstate* state, ae_state *_state)
75491 : {
75492 :
75493 :
75494 0 : state->prectype = 0;
75495 0 : state->innerresetneeded = ae_true;
75496 0 : }
75497 :
75498 :
75499 : /*************************************************************************
75500 : Modification of the preconditioner: diagonal of approximate Hessian is
75501 : used.
75502 :
75503 : INPUT PARAMETERS:
75504 : State - structure which stores algorithm state
75505 : D - diagonal of the approximate Hessian, array[0..N-1],
75506 : (if larger, only leading N elements are used).
75507 :
75508 : NOTE: you can change preconditioner "on the fly", during algorithm
75509 : iterations.
75510 :
75511 : NOTE 2: D[i] should be positive. Exception will be thrown otherwise.
75512 :
75513 : NOTE 3: you should pass diagonal of approximate Hessian - NOT ITS INVERSE.
75514 :
75515 : -- ALGLIB --
75516 : Copyright 13.10.2010 by Bochkanov Sergey
75517 : *************************************************************************/
75518 0 : void mincgsetprecdiag(mincgstate* state,
75519 : /* Real */ ae_vector* d,
75520 : ae_state *_state)
75521 : {
75522 : ae_int_t i;
75523 :
75524 :
75525 0 : ae_assert(d->cnt>=state->n, "MinCGSetPrecDiag: D is too short", _state);
75526 0 : for(i=0; i<=state->n-1; i++)
75527 : {
75528 0 : ae_assert(ae_isfinite(d->ptr.p_double[i], _state), "MinCGSetPrecDiag: D contains infinite or NAN elements", _state);
75529 0 : ae_assert(ae_fp_greater(d->ptr.p_double[i],(double)(0)), "MinCGSetPrecDiag: D contains non-positive elements", _state);
75530 : }
75531 0 : mincgsetprecdiagfast(state, d, _state);
75532 0 : }
75533 :
75534 :
75535 : /*************************************************************************
75536 : Modification of the preconditioner: scale-based diagonal preconditioning.
75537 :
75538 : This preconditioning mode can be useful when you don't have approximate
75539 : diagonal of Hessian, but you know that your variables are badly scaled
75540 : (for example, one variable is in [1,10], and another in [1000,100000]),
75541 : and most part of the ill-conditioning comes from different scales of vars.
75542 :
75543 : In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2),
75544 : can greatly improve convergence.
75545 :
75546 : IMPRTANT: you should set scale of your variables with MinCGSetScale() call
75547 : (before or after MinCGSetPrecScale() call). Without knowledge of the scale
75548 : of your variables scale-based preconditioner will be just unit matrix.
75549 :
75550 : INPUT PARAMETERS:
75551 : State - structure which stores algorithm state
75552 :
75553 : NOTE: you can change preconditioner "on the fly", during algorithm
75554 : iterations.
75555 :
75556 : -- ALGLIB --
75557 : Copyright 13.10.2010 by Bochkanov Sergey
75558 : *************************************************************************/
75559 0 : void mincgsetprecscale(mincgstate* state, ae_state *_state)
75560 : {
75561 :
75562 :
75563 0 : state->prectype = 3;
75564 0 : state->innerresetneeded = ae_true;
75565 0 : }
75566 :
75567 :
75568 : /*************************************************************************
75569 : NOTES:
75570 :
75571 : 1. This function has two different implementations: one which uses exact
75572 : (analytical) user-supplied gradient, and one which uses function value
75573 : only and numerically differentiates function in order to obtain
75574 : gradient.
75575 :
75576 : Depending on the specific function used to create optimizer object
75577 : (either MinCGCreate() for analytical gradient or MinCGCreateF() for
75578 : numerical differentiation) you should choose appropriate variant of
75579 : MinCGOptimize() - one which accepts function AND gradient or one which
75580 : accepts function ONLY.
75581 :
75582 : Be careful to choose variant of MinCGOptimize() which corresponds to
75583 : your optimization scheme! Table below lists different combinations of
75584 : callback (function/gradient) passed to MinCGOptimize() and specific
75585 : function used to create optimizer.
75586 :
75587 :
75588 : | USER PASSED TO MinCGOptimize()
75589 : CREATED WITH | function only | function and gradient
75590 : ------------------------------------------------------------
75591 : MinCGCreateF() | work FAIL
75592 : MinCGCreate() | FAIL work
75593 :
75594 : Here "FAIL" denotes inappropriate combinations of optimizer creation
75595 : function and MinCGOptimize() version. Attemps to use such combination
75596 : (for example, to create optimizer with MinCGCreateF() and to pass
75597 : gradient information to MinCGOptimize()) will lead to exception being
75598 : thrown. Either you did not pass gradient when it WAS needed or you
75599 : passed gradient when it was NOT needed.
75600 :
75601 : -- ALGLIB --
75602 : Copyright 20.04.2009 by Bochkanov Sergey
75603 : *************************************************************************/
75604 0 : ae_bool mincgiteration(mincgstate* state, ae_state *_state)
75605 : {
75606 : ae_int_t n;
75607 : ae_int_t i;
75608 : double betak;
75609 : double v;
75610 : double vv;
75611 : ae_bool result;
75612 :
75613 :
75614 :
75615 : /*
75616 : * Reverse communication preparations
75617 : * I know it looks ugly, but it works the same way
75618 : * anywhere from C++ to Python.
75619 : *
75620 : * This code initializes locals by:
75621 : * * random values determined during code
75622 : * generation - on first subroutine call
75623 : * * values from previous call - on subsequent calls
75624 : */
75625 0 : if( state->rstate.stage>=0 )
75626 : {
75627 0 : n = state->rstate.ia.ptr.p_int[0];
75628 0 : i = state->rstate.ia.ptr.p_int[1];
75629 0 : betak = state->rstate.ra.ptr.p_double[0];
75630 0 : v = state->rstate.ra.ptr.p_double[1];
75631 0 : vv = state->rstate.ra.ptr.p_double[2];
75632 : }
75633 : else
75634 : {
75635 0 : n = 359;
75636 0 : i = -58;
75637 0 : betak = -919;
75638 0 : v = -909;
75639 0 : vv = 81;
75640 : }
75641 0 : if( state->rstate.stage==0 )
75642 : {
75643 0 : goto lbl_0;
75644 : }
75645 0 : if( state->rstate.stage==1 )
75646 : {
75647 0 : goto lbl_1;
75648 : }
75649 0 : if( state->rstate.stage==2 )
75650 : {
75651 0 : goto lbl_2;
75652 : }
75653 0 : if( state->rstate.stage==3 )
75654 : {
75655 0 : goto lbl_3;
75656 : }
75657 0 : if( state->rstate.stage==4 )
75658 : {
75659 0 : goto lbl_4;
75660 : }
75661 0 : if( state->rstate.stage==5 )
75662 : {
75663 0 : goto lbl_5;
75664 : }
75665 0 : if( state->rstate.stage==6 )
75666 : {
75667 0 : goto lbl_6;
75668 : }
75669 0 : if( state->rstate.stage==7 )
75670 : {
75671 0 : goto lbl_7;
75672 : }
75673 0 : if( state->rstate.stage==8 )
75674 : {
75675 0 : goto lbl_8;
75676 : }
75677 0 : if( state->rstate.stage==9 )
75678 : {
75679 0 : goto lbl_9;
75680 : }
75681 0 : if( state->rstate.stage==10 )
75682 : {
75683 0 : goto lbl_10;
75684 : }
75685 0 : if( state->rstate.stage==11 )
75686 : {
75687 0 : goto lbl_11;
75688 : }
75689 0 : if( state->rstate.stage==12 )
75690 : {
75691 0 : goto lbl_12;
75692 : }
75693 0 : if( state->rstate.stage==13 )
75694 : {
75695 0 : goto lbl_13;
75696 : }
75697 0 : if( state->rstate.stage==14 )
75698 : {
75699 0 : goto lbl_14;
75700 : }
75701 0 : if( state->rstate.stage==15 )
75702 : {
75703 0 : goto lbl_15;
75704 : }
75705 0 : if( state->rstate.stage==16 )
75706 : {
75707 0 : goto lbl_16;
75708 : }
75709 0 : if( state->rstate.stage==17 )
75710 : {
75711 0 : goto lbl_17;
75712 : }
75713 :
75714 : /*
75715 : * Routine body
75716 : */
75717 :
75718 : /*
75719 : * Prepare
75720 : */
75721 0 : n = state->n;
75722 0 : state->terminationneeded = ae_false;
75723 0 : state->userterminationneeded = ae_false;
75724 0 : state->repterminationtype = 0;
75725 0 : state->repiterationscount = 0;
75726 0 : state->repnfev = 0;
75727 0 : state->debugrestartscount = 0;
75728 0 : smoothnessmonitorinit(&state->smonitor, &state->s, n, 1, state->smoothnessguardlevel>0, _state);
75729 0 : rvectorsetlengthatleast(&state->invs, n, _state);
75730 0 : for(i=0; i<=n-1; i++)
75731 : {
75732 0 : state->lastscaleused.ptr.p_double[i] = state->s.ptr.p_double[i];
75733 0 : state->invs.ptr.p_double[i] = 1/state->s.ptr.p_double[i];
75734 : }
75735 :
75736 : /*
75737 : * Check, that transferred derivative value is right
75738 : */
75739 0 : mincg_clearrequestfields(state, _state);
75740 0 : if( !(ae_fp_eq(state->diffstep,(double)(0))&&ae_fp_greater(state->teststep,(double)(0))) )
75741 : {
75742 0 : goto lbl_18;
75743 : }
75744 0 : lbl_20:
75745 0 : if( !smoothnessmonitorcheckgradientatx0(&state->smonitor, &state->xbase, &state->s, &state->s, &state->s, ae_false, state->teststep, _state) )
75746 : {
75747 0 : goto lbl_21;
75748 : }
75749 0 : for(i=0; i<=n-1; i++)
75750 : {
75751 0 : state->x.ptr.p_double[i] = state->smonitor.x.ptr.p_double[i];
75752 : }
75753 0 : state->needfg = ae_true;
75754 0 : state->rstate.stage = 0;
75755 0 : goto lbl_rcomm;
75756 0 : lbl_0:
75757 0 : state->needfg = ae_false;
75758 0 : state->smonitor.fi.ptr.p_double[0] = state->f;
75759 0 : for(i=0; i<=n-1; i++)
75760 : {
75761 0 : state->smonitor.j.ptr.pp_double[0][i] = state->g.ptr.p_double[i];
75762 : }
75763 0 : goto lbl_20;
75764 0 : lbl_21:
75765 0 : lbl_18:
75766 :
75767 : /*
75768 : * Preparations continue:
75769 : * * set XK
75770 : * * calculate F/G
75771 : * * set DK to -G
75772 : * * powerup algo (it may change preconditioner)
75773 : * * apply preconditioner to DK
75774 : * * report update of X
75775 : * * check stopping conditions for G
75776 : */
75777 0 : for(i=0; i<=n-1; i++)
75778 : {
75779 0 : state->x.ptr.p_double[i] = state->xbase.ptr.p_double[i];
75780 : }
75781 0 : ae_v_move(&state->xk.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1));
75782 0 : mincg_clearrequestfields(state, _state);
75783 0 : if( ae_fp_neq(state->diffstep,(double)(0)) )
75784 : {
75785 0 : goto lbl_22;
75786 : }
75787 0 : state->needfg = ae_true;
75788 0 : state->rstate.stage = 1;
75789 0 : goto lbl_rcomm;
75790 0 : lbl_1:
75791 0 : state->needfg = ae_false;
75792 0 : goto lbl_23;
75793 0 : lbl_22:
75794 0 : state->needf = ae_true;
75795 0 : state->rstate.stage = 2;
75796 0 : goto lbl_rcomm;
75797 0 : lbl_2:
75798 0 : state->fbase = state->f;
75799 0 : i = 0;
75800 0 : lbl_24:
75801 0 : if( i>n-1 )
75802 : {
75803 0 : goto lbl_26;
75804 : }
75805 0 : v = state->x.ptr.p_double[i];
75806 0 : state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i];
75807 0 : state->rstate.stage = 3;
75808 0 : goto lbl_rcomm;
75809 0 : lbl_3:
75810 0 : state->fm2 = state->f;
75811 0 : state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i];
75812 0 : state->rstate.stage = 4;
75813 0 : goto lbl_rcomm;
75814 0 : lbl_4:
75815 0 : state->fm1 = state->f;
75816 0 : state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i];
75817 0 : state->rstate.stage = 5;
75818 0 : goto lbl_rcomm;
75819 0 : lbl_5:
75820 0 : state->fp1 = state->f;
75821 0 : state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i];
75822 0 : state->rstate.stage = 6;
75823 0 : goto lbl_rcomm;
75824 0 : lbl_6:
75825 0 : state->fp2 = state->f;
75826 0 : state->x.ptr.p_double[i] = v;
75827 0 : state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]);
75828 0 : i = i+1;
75829 0 : goto lbl_24;
75830 0 : lbl_26:
75831 0 : state->f = state->fbase;
75832 0 : state->needf = ae_false;
75833 0 : lbl_23:
75834 0 : if( !state->drep )
75835 : {
75836 0 : goto lbl_27;
75837 : }
75838 :
75839 : /*
75840 : * Report algorithm powerup (if needed)
75841 : */
75842 0 : mincg_clearrequestfields(state, _state);
75843 0 : state->algpowerup = ae_true;
75844 0 : state->rstate.stage = 7;
75845 0 : goto lbl_rcomm;
75846 0 : lbl_7:
75847 0 : state->algpowerup = ae_false;
75848 0 : lbl_27:
75849 0 : trimprepare(state->f, &state->trimthreshold, _state);
75850 0 : ae_v_moveneg(&state->dk.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
75851 0 : mincg_preconditionedmultiply(state, &state->dk, &state->work0, &state->work1, _state);
75852 0 : if( !state->xrep )
75853 : {
75854 0 : goto lbl_29;
75855 : }
75856 0 : mincg_clearrequestfields(state, _state);
75857 0 : state->xupdated = ae_true;
75858 0 : state->rstate.stage = 8;
75859 0 : goto lbl_rcomm;
75860 0 : lbl_8:
75861 0 : state->xupdated = ae_false;
75862 0 : lbl_29:
75863 0 : if( state->terminationneeded||state->userterminationneeded )
75864 : {
75865 :
75866 : /*
75867 : * Combined termination point for "internal" termination by TerminationNeeded flag
75868 : * and for "user" termination by MinCGRequestTermination() (UserTerminationNeeded flag).
75869 : * In this location rules for both of methods are same, thus only one exit point is needed.
75870 : */
75871 0 : ae_v_move(&state->xn.ptr.p_double[0], 1, &state->xk.ptr.p_double[0], 1, ae_v_len(0,n-1));
75872 0 : state->repterminationtype = 8;
75873 0 : result = ae_false;
75874 0 : return result;
75875 : }
75876 0 : v = (double)(0);
75877 0 : for(i=0; i<=n-1; i++)
75878 : {
75879 0 : v = v+ae_sqr(state->g.ptr.p_double[i]*state->s.ptr.p_double[i], _state);
75880 : }
75881 0 : if( ae_fp_less_eq(ae_sqrt(v, _state),state->epsg) )
75882 : {
75883 0 : ae_v_move(&state->xn.ptr.p_double[0], 1, &state->xk.ptr.p_double[0], 1, ae_v_len(0,n-1));
75884 0 : state->repterminationtype = 4;
75885 0 : result = ae_false;
75886 0 : return result;
75887 : }
75888 0 : state->repnfev = 1;
75889 0 : state->k = 0;
75890 0 : state->fold = state->f;
75891 :
75892 : /*
75893 : * Choose initial step.
75894 : * Apply preconditioner, if we have something other than default.
75895 : */
75896 0 : if( state->prectype==2||state->prectype==3 )
75897 : {
75898 :
75899 : /*
75900 : * because we use preconditioner, step length must be equal
75901 : * to the norm of DK
75902 : */
75903 0 : v = ae_v_dotproduct(&state->dk.ptr.p_double[0], 1, &state->dk.ptr.p_double[0], 1, ae_v_len(0,n-1));
75904 0 : state->lastgoodstep = ae_sqrt(v, _state);
75905 : }
75906 : else
75907 : {
75908 :
75909 : /*
75910 : * No preconditioner is used, we try to use suggested step
75911 : */
75912 0 : if( ae_fp_greater(state->suggestedstep,(double)(0)) )
75913 : {
75914 0 : state->lastgoodstep = state->suggestedstep;
75915 : }
75916 : else
75917 : {
75918 0 : state->lastgoodstep = 1.0;
75919 : }
75920 : }
75921 :
75922 : /*
75923 : * Main cycle
75924 : */
75925 0 : state->rstimer = mincg_rscountdownlen;
75926 0 : lbl_31:
75927 : if( ae_false )
75928 : {
75929 : goto lbl_32;
75930 : }
75931 :
75932 : /*
75933 : * * clear reset flag
75934 : * * clear termination flag
75935 : * * store G[k] for later calculation of Y[k]
75936 : * * prepare starting point and direction and step length for line search
75937 : */
75938 0 : state->innerresetneeded = ae_false;
75939 0 : state->terminationneeded = ae_false;
75940 0 : ae_v_moveneg(&state->yk.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
75941 0 : ae_v_move(&state->d.ptr.p_double[0], 1, &state->dk.ptr.p_double[0], 1, ae_v_len(0,n-1));
75942 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xk.ptr.p_double[0], 1, ae_v_len(0,n-1));
75943 0 : state->mcstage = 0;
75944 0 : state->stp = 1.0;
75945 0 : linminnormalized(&state->d, &state->stp, n, _state);
75946 0 : if( ae_fp_neq(state->lastgoodstep,(double)(0)) )
75947 : {
75948 0 : state->stp = state->lastgoodstep;
75949 : }
75950 0 : state->curstpmax = state->stpmax;
75951 :
75952 : /*
75953 : * Report beginning of line search (if needed)
75954 : * Terminate algorithm, if user request was detected
75955 : */
75956 0 : if( !state->drep )
75957 : {
75958 0 : goto lbl_33;
75959 : }
75960 0 : mincg_clearrequestfields(state, _state);
75961 0 : state->lsstart = ae_true;
75962 0 : state->rstate.stage = 9;
75963 0 : goto lbl_rcomm;
75964 0 : lbl_9:
75965 0 : state->lsstart = ae_false;
75966 0 : lbl_33:
75967 0 : if( state->terminationneeded )
75968 : {
75969 0 : ae_v_move(&state->xn.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1));
75970 0 : state->repterminationtype = 8;
75971 0 : result = ae_false;
75972 0 : return result;
75973 : }
75974 :
75975 : /*
75976 : * Minimization along D
75977 : */
75978 0 : smoothnessmonitorstartlinesearch1u(&state->smonitor, &state->s, &state->invs, &state->x, state->f, &state->g, _state);
75979 0 : 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);
75980 0 : lbl_35:
75981 0 : if( state->mcstage==0 )
75982 : {
75983 0 : goto lbl_36;
75984 : }
75985 :
75986 : /*
75987 : * Calculate function/gradient using either
75988 : * analytical gradient supplied by user
75989 : * or finite difference approximation.
75990 : *
75991 : * "Trim" function in order to handle near-singularity points.
75992 : */
75993 0 : mincg_clearrequestfields(state, _state);
75994 0 : if( ae_fp_neq(state->diffstep,(double)(0)) )
75995 : {
75996 0 : goto lbl_37;
75997 : }
75998 0 : state->needfg = ae_true;
75999 0 : state->rstate.stage = 10;
76000 0 : goto lbl_rcomm;
76001 0 : lbl_10:
76002 0 : state->needfg = ae_false;
76003 0 : goto lbl_38;
76004 0 : lbl_37:
76005 0 : state->needf = ae_true;
76006 0 : state->rstate.stage = 11;
76007 0 : goto lbl_rcomm;
76008 0 : lbl_11:
76009 0 : state->fbase = state->f;
76010 0 : i = 0;
76011 0 : lbl_39:
76012 0 : if( i>n-1 )
76013 : {
76014 0 : goto lbl_41;
76015 : }
76016 0 : v = state->x.ptr.p_double[i];
76017 0 : state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i];
76018 0 : state->rstate.stage = 12;
76019 0 : goto lbl_rcomm;
76020 0 : lbl_12:
76021 0 : state->fm2 = state->f;
76022 0 : state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i];
76023 0 : state->rstate.stage = 13;
76024 0 : goto lbl_rcomm;
76025 0 : lbl_13:
76026 0 : state->fm1 = state->f;
76027 0 : state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i];
76028 0 : state->rstate.stage = 14;
76029 0 : goto lbl_rcomm;
76030 0 : lbl_14:
76031 0 : state->fp1 = state->f;
76032 0 : state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i];
76033 0 : state->rstate.stage = 15;
76034 0 : goto lbl_rcomm;
76035 0 : lbl_15:
76036 0 : state->fp2 = state->f;
76037 0 : state->x.ptr.p_double[i] = v;
76038 0 : state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]);
76039 0 : i = i+1;
76040 0 : goto lbl_39;
76041 0 : lbl_41:
76042 0 : state->f = state->fbase;
76043 0 : state->needf = ae_false;
76044 0 : lbl_38:
76045 0 : smoothnessmonitorenqueuepoint1u(&state->smonitor, &state->s, &state->invs, &state->d, state->stp, &state->x, state->f, &state->g, _state);
76046 0 : trimfunction(&state->f, &state->g, n, state->trimthreshold, _state);
76047 :
76048 : /*
76049 : * Call MCSRCH again
76050 : */
76051 0 : 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);
76052 0 : goto lbl_35;
76053 0 : lbl_36:
76054 0 : smoothnessmonitorfinalizelinesearch(&state->smonitor, _state);
76055 :
76056 : /*
76057 : * * terminate algorithm if "user" request for detected
76058 : * * report end of line search
76059 : * * store current point to XN
76060 : * * report iteration
76061 : * * terminate algorithm if "internal" request was detected
76062 : */
76063 0 : if( state->userterminationneeded )
76064 : {
76065 0 : ae_v_move(&state->xn.ptr.p_double[0], 1, &state->xk.ptr.p_double[0], 1, ae_v_len(0,n-1));
76066 0 : state->repterminationtype = 8;
76067 0 : result = ae_false;
76068 0 : return result;
76069 : }
76070 0 : if( !state->drep )
76071 : {
76072 0 : goto lbl_42;
76073 : }
76074 :
76075 : /*
76076 : * Report end of line search (if needed)
76077 : */
76078 0 : mincg_clearrequestfields(state, _state);
76079 0 : state->lsend = ae_true;
76080 0 : state->rstate.stage = 16;
76081 0 : goto lbl_rcomm;
76082 0 : lbl_16:
76083 0 : state->lsend = ae_false;
76084 0 : lbl_42:
76085 0 : ae_v_move(&state->xn.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1));
76086 0 : if( !state->xrep )
76087 : {
76088 0 : goto lbl_44;
76089 : }
76090 0 : mincg_clearrequestfields(state, _state);
76091 0 : state->xupdated = ae_true;
76092 0 : state->rstate.stage = 17;
76093 0 : goto lbl_rcomm;
76094 0 : lbl_17:
76095 0 : state->xupdated = ae_false;
76096 0 : lbl_44:
76097 0 : if( state->terminationneeded )
76098 : {
76099 0 : ae_v_move(&state->xn.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1));
76100 0 : state->repterminationtype = 8;
76101 0 : result = ae_false;
76102 0 : return result;
76103 : }
76104 :
76105 : /*
76106 : * Line search is finished.
76107 : * * calculate BetaK
76108 : * * calculate DN
76109 : * * update timers
76110 : * * calculate step length:
76111 : * * LastScaledStep is ALWAYS calculated because it is used in the stopping criteria
76112 : * * LastGoodStep is updated only when MCINFO is equal to 1 (Wolfe conditions hold).
76113 : * See below for more explanation.
76114 : */
76115 0 : if( state->mcinfo==1&&!state->innerresetneeded )
76116 : {
76117 :
76118 : /*
76119 : * Standard Wolfe conditions hold
76120 : * Calculate Y[K] and D[K]'*Y[K]
76121 : */
76122 0 : ae_v_add(&state->yk.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
76123 0 : vv = ae_v_dotproduct(&state->yk.ptr.p_double[0], 1, &state->dk.ptr.p_double[0], 1, ae_v_len(0,n-1));
76124 :
76125 : /*
76126 : * Calculate BetaK according to DY formula
76127 : */
76128 0 : v = mincg_preconditionedmultiply2(state, &state->g, &state->g, &state->work0, &state->work1, _state);
76129 0 : state->betady = v/vv;
76130 :
76131 : /*
76132 : * Calculate BetaK according to HS formula
76133 : */
76134 0 : v = mincg_preconditionedmultiply2(state, &state->g, &state->yk, &state->work0, &state->work1, _state);
76135 0 : state->betahs = v/vv;
76136 :
76137 : /*
76138 : * Choose BetaK
76139 : */
76140 0 : if( state->cgtype==0 )
76141 : {
76142 0 : betak = state->betady;
76143 : }
76144 0 : if( state->cgtype==1 )
76145 : {
76146 0 : betak = ae_maxreal((double)(0), ae_minreal(state->betady, state->betahs, _state), _state);
76147 : }
76148 : }
76149 : else
76150 : {
76151 :
76152 : /*
76153 : * Something is wrong (may be function is too wild or too flat)
76154 : * or we just have to restart algo.
76155 : *
76156 : * We'll set BetaK=0, which will restart CG algorithm.
76157 : * We can stop later (during normal checks) if stopping conditions are met.
76158 : */
76159 0 : betak = (double)(0);
76160 0 : state->debugrestartscount = state->debugrestartscount+1;
76161 : }
76162 0 : if( state->repiterationscount>0&&state->repiterationscount%(3+n)==0 )
76163 : {
76164 :
76165 : /*
76166 : * clear Beta every N iterations
76167 : */
76168 0 : betak = (double)(0);
76169 : }
76170 0 : if( state->mcinfo==1||state->mcinfo==5 )
76171 : {
76172 0 : state->rstimer = mincg_rscountdownlen;
76173 : }
76174 : else
76175 : {
76176 0 : state->rstimer = state->rstimer-1;
76177 : }
76178 0 : ae_v_moveneg(&state->dn.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
76179 0 : mincg_preconditionedmultiply(state, &state->dn, &state->work0, &state->work1, _state);
76180 0 : ae_v_addd(&state->dn.ptr.p_double[0], 1, &state->dk.ptr.p_double[0], 1, ae_v_len(0,n-1), betak);
76181 0 : state->lastscaledstep = 0.0;
76182 0 : for(i=0; i<=n-1; i++)
76183 : {
76184 0 : state->lastscaledstep = state->lastscaledstep+ae_sqr(state->d.ptr.p_double[i]/state->s.ptr.p_double[i], _state);
76185 : }
76186 0 : state->lastscaledstep = state->stp*ae_sqrt(state->lastscaledstep, _state);
76187 0 : if( state->mcinfo==1 )
76188 : {
76189 :
76190 : /*
76191 : * Step is good (Wolfe conditions hold), update LastGoodStep.
76192 : *
76193 : * This check for MCINFO=1 is essential because sometimes in the
76194 : * constrained optimization setting we may take very short steps
76195 : * (like 1E-15) because we were very close to boundary of the
76196 : * feasible area. Such short step does not mean that we've converged
76197 : * to the solution - it was so short because we were close to the
76198 : * boundary and there was a limit on step length.
76199 : *
76200 : * So having such short step is quite normal situation. However, we
76201 : * should NOT start next iteration from step whose initial length is
76202 : * estimated as 1E-15 because it may lead to the failure of the
76203 : * linear minimizer (step is too short, function does not changes,
76204 : * line search stagnates).
76205 : */
76206 0 : state->lastgoodstep = (double)(0);
76207 0 : for(i=0; i<=n-1; i++)
76208 : {
76209 0 : state->lastgoodstep = state->lastgoodstep+ae_sqr(state->d.ptr.p_double[i], _state);
76210 : }
76211 0 : state->lastgoodstep = state->stp*ae_sqrt(state->lastgoodstep, _state);
76212 : }
76213 :
76214 : /*
76215 : * Update information.
76216 : * Check stopping conditions.
76217 : */
76218 0 : v = (double)(0);
76219 0 : for(i=0; i<=n-1; i++)
76220 : {
76221 0 : v = v+ae_sqr(state->g.ptr.p_double[i]*state->s.ptr.p_double[i], _state);
76222 : }
76223 0 : if( !ae_isfinite(v, _state)||!ae_isfinite(state->f, _state) )
76224 : {
76225 :
76226 : /*
76227 : * Abnormal termination - infinities in function/gradient
76228 : */
76229 0 : state->repterminationtype = -8;
76230 0 : result = ae_false;
76231 0 : return result;
76232 : }
76233 0 : state->repnfev = state->repnfev+state->nfev;
76234 0 : state->repiterationscount = state->repiterationscount+1;
76235 0 : if( state->repiterationscount>=state->maxits&&state->maxits>0 )
76236 : {
76237 :
76238 : /*
76239 : * Too many iterations
76240 : */
76241 0 : state->repterminationtype = 5;
76242 0 : result = ae_false;
76243 0 : return result;
76244 : }
76245 0 : if( ae_fp_less_eq(ae_sqrt(v, _state),state->epsg) )
76246 : {
76247 :
76248 : /*
76249 : * Gradient is small enough
76250 : */
76251 0 : state->repterminationtype = 4;
76252 0 : result = ae_false;
76253 0 : return result;
76254 : }
76255 0 : if( !state->innerresetneeded )
76256 : {
76257 :
76258 : /*
76259 : * These conditions are checked only when no inner reset was requested by user
76260 : */
76261 0 : 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)) )
76262 : {
76263 :
76264 : /*
76265 : * F(k+1)-F(k) is small enough
76266 : */
76267 0 : state->repterminationtype = 1;
76268 0 : result = ae_false;
76269 0 : return result;
76270 : }
76271 0 : if( ae_fp_less_eq(state->lastscaledstep,state->epsx) )
76272 : {
76273 :
76274 : /*
76275 : * X(k+1)-X(k) is small enough
76276 : */
76277 0 : state->repterminationtype = 2;
76278 0 : result = ae_false;
76279 0 : return result;
76280 : }
76281 : }
76282 0 : if( state->rstimer<=0 )
76283 : {
76284 :
76285 : /*
76286 : * Too many subsequent restarts
76287 : */
76288 0 : state->repterminationtype = 7;
76289 0 : result = ae_false;
76290 0 : return result;
76291 : }
76292 :
76293 : /*
76294 : * Shift Xk/Dk, update other information
76295 : */
76296 0 : ae_v_move(&state->xk.ptr.p_double[0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1));
76297 0 : ae_v_move(&state->dk.ptr.p_double[0], 1, &state->dn.ptr.p_double[0], 1, ae_v_len(0,n-1));
76298 0 : state->fold = state->f;
76299 0 : state->k = state->k+1;
76300 0 : goto lbl_31;
76301 : lbl_32:
76302 : result = ae_false;
76303 : return result;
76304 :
76305 : /*
76306 : * Saving state
76307 : */
76308 0 : lbl_rcomm:
76309 0 : result = ae_true;
76310 0 : state->rstate.ia.ptr.p_int[0] = n;
76311 0 : state->rstate.ia.ptr.p_int[1] = i;
76312 0 : state->rstate.ra.ptr.p_double[0] = betak;
76313 0 : state->rstate.ra.ptr.p_double[1] = v;
76314 0 : state->rstate.ra.ptr.p_double[2] = vv;
76315 0 : return result;
76316 : }
76317 :
76318 :
76319 : /*************************************************************************
76320 : This function activates/deactivates verification of the user-supplied
76321 : analytic gradient.
76322 :
76323 : Upon activation of this option OptGuard integrity checker performs
76324 : numerical differentiation of your target function at the initial point
76325 : (note: future versions may also perform check at the final point) and
76326 : compares numerical gradient with analytic one provided by you.
76327 :
76328 : If difference is too large, an error flag is set and optimization session
76329 : continues. After optimization session is over, you can retrieve the report
76330 : which stores both gradients and specific components highlighted as
76331 : suspicious by the OptGuard.
76332 :
76333 : The primary OptGuard report can be retrieved with mincgoptguardresults().
76334 :
76335 : IMPORTANT: gradient check is a high-overhead option which will cost you
76336 : about 3*N additional function evaluations. In many cases it may
76337 : cost as much as the rest of the optimization session.
76338 :
76339 : YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO
76340 : CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY.
76341 :
76342 : NOTE: unlike previous incarnation of the gradient checking code, OptGuard
76343 : does NOT interrupt optimization even if it discovers bad gradient.
76344 :
76345 : INPUT PARAMETERS:
76346 : State - structure used to store algorithm state
76347 : TestStep - verification step used for numerical differentiation:
76348 : * TestStep=0 turns verification off
76349 : * TestStep>0 activates verification
76350 : You should carefully choose TestStep. Value which is
76351 : too large (so large that function behavior is non-
76352 : cubic at this scale) will lead to false alarms. Too
76353 : short step will result in rounding errors dominating
76354 : numerical derivative.
76355 :
76356 : You may use different step for different parameters by
76357 : means of setting scale with mincgsetscale().
76358 :
76359 : === EXPLANATION ==========================================================
76360 :
76361 : In order to verify gradient algorithm performs following steps:
76362 : * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i],
76363 : where X[i] is i-th component of the initial point and S[i] is a scale
76364 : of i-th parameter
76365 : * F(X) is evaluated at these trial points
76366 : * we perform one more evaluation in the middle point of the interval
76367 : * we build cubic model using function values and derivatives at trial
76368 : points and we compare its prediction with actual value in the middle
76369 : point
76370 :
76371 : -- ALGLIB --
76372 : Copyright 15.06.2014 by Bochkanov Sergey
76373 : *************************************************************************/
76374 0 : void mincgoptguardgradient(mincgstate* state,
76375 : double teststep,
76376 : ae_state *_state)
76377 : {
76378 :
76379 :
76380 0 : ae_assert(ae_isfinite(teststep, _state), "MinCGOptGuardGradient: TestStep contains NaN or INF", _state);
76381 0 : ae_assert(ae_fp_greater_eq(teststep,(double)(0)), "MinCGOptGuardGradient: invalid argument TestStep(TestStep<0)", _state);
76382 0 : state->teststep = teststep;
76383 0 : }
76384 :
76385 :
76386 : /*************************************************************************
76387 : This function activates/deactivates nonsmoothness monitoring option of
76388 : the OptGuard integrity checker. Smoothness monitor silently observes
76389 : solution process and tries to detect ill-posed problems, i.e. ones with:
76390 : a) discontinuous target function (non-C0)
76391 : b) nonsmooth target function (non-C1)
76392 :
76393 : Smoothness monitoring does NOT interrupt optimization even if it suspects
76394 : that your problem is nonsmooth. It just sets corresponding flags in the
76395 : OptGuard report which can be retrieved after optimization is over.
76396 :
76397 : Smoothness monitoring is a moderate overhead option which often adds less
76398 : than 1% to the optimizer running time. Thus, you can use it even for large
76399 : scale problems.
76400 :
76401 : NOTE: OptGuard does NOT guarantee that it will always detect C0/C1
76402 : continuity violations.
76403 :
76404 : First, minor errors are hard to catch - say, a 0.0001 difference in
76405 : the model values at two sides of the gap may be due to discontinuity
76406 : of the model - or simply because the model has changed.
76407 :
76408 : Second, C1-violations are especially difficult to detect in a
76409 : noninvasive way. The optimizer usually performs very short steps
76410 : near the nonsmoothness, and differentiation usually introduces a
76411 : lot of numerical noise. It is hard to tell whether some tiny
76412 : discontinuity in the slope is due to real nonsmoothness or just due
76413 : to numerical noise alone.
76414 :
76415 : Our top priority was to avoid false positives, so in some rare cases
76416 : minor errors may went unnoticed (however, in most cases they can be
76417 : spotted with restart from different initial point).
76418 :
76419 : INPUT PARAMETERS:
76420 : state - algorithm state
76421 : level - monitoring level:
76422 : * 0 - monitoring is disabled
76423 : * 1 - noninvasive low-overhead monitoring; function values
76424 : and/or gradients are recorded, but OptGuard does not
76425 : try to perform additional evaluations in order to
76426 : get more information about suspicious locations.
76427 :
76428 : === EXPLANATION ==========================================================
76429 :
76430 : One major source of headache during optimization is the possibility of
76431 : the coding errors in the target function/constraints (or their gradients).
76432 : Such errors most often manifest themselves as discontinuity or
76433 : nonsmoothness of the target/constraints.
76434 :
76435 : Another frequent situation is when you try to optimize something involving
76436 : lots of min() and max() operations, i.e. nonsmooth target. Although not a
76437 : coding error, it is nonsmoothness anyway - and smooth optimizers usually
76438 : stop right after encountering nonsmoothness, well before reaching solution.
76439 :
76440 : OptGuard integrity checker helps you to catch such situations: it monitors
76441 : function values/gradients being passed to the optimizer and tries to
76442 : errors. Upon discovering suspicious pair of points it raises appropriate
76443 : flag (and allows you to continue optimization). When optimization is done,
76444 : you can study OptGuard result.
76445 :
76446 : -- ALGLIB --
76447 : Copyright 21.11.2018 by Bochkanov Sergey
76448 : *************************************************************************/
76449 0 : void mincgoptguardsmoothness(mincgstate* state,
76450 : ae_int_t level,
76451 : ae_state *_state)
76452 : {
76453 :
76454 :
76455 0 : ae_assert(level==0||level==1, "MinCGOptGuardSmoothness: unexpected value of level parameter", _state);
76456 0 : state->smoothnessguardlevel = level;
76457 0 : }
76458 :
76459 :
76460 : /*************************************************************************
76461 : Results of OptGuard integrity check, should be called after optimization
76462 : session is over.
76463 :
76464 : === PRIMARY REPORT =======================================================
76465 :
76466 : OptGuard performs several checks which are intended to catch common errors
76467 : in the implementation of nonlinear function/gradient:
76468 : * incorrect analytic gradient
76469 : * discontinuous (non-C0) target functions (constraints)
76470 : * nonsmooth (non-C1) target functions (constraints)
76471 :
76472 : Each of these checks is activated with appropriate function:
76473 : * mincgoptguardgradient() for gradient verification
76474 : * mincgoptguardsmoothness() for C0/C1 checks
76475 :
76476 : Following flags are set when these errors are suspected:
76477 : * rep.badgradsuspected, and additionally:
76478 : * rep.badgradvidx for specific variable (gradient element) suspected
76479 : * rep.badgradxbase, a point where gradient is tested
76480 : * rep.badgraduser, user-provided gradient (stored as 2D matrix with
76481 : single row in order to make report structure compatible with more
76482 : complex optimizers like MinNLC or MinLM)
76483 : * rep.badgradnum, reference gradient obtained via numerical
76484 : differentiation (stored as 2D matrix with single row in order to make
76485 : report structure compatible with more complex optimizers like MinNLC
76486 : or MinLM)
76487 : * rep.nonc0suspected
76488 : * rep.nonc1suspected
76489 :
76490 : === ADDITIONAL REPORTS/LOGS ==============================================
76491 :
76492 : Several different tests are performed to catch C0/C1 errors, you can find
76493 : out specific test signaled error by looking to:
76494 : * rep.nonc0test0positive, for non-C0 test #0
76495 : * rep.nonc1test0positive, for non-C1 test #0
76496 : * rep.nonc1test1positive, for non-C1 test #1
76497 :
76498 : Additional information (including line search logs) can be obtained by
76499 : means of:
76500 : * mincgoptguardnonc1test0results()
76501 : * mincgoptguardnonc1test1results()
76502 : which return detailed error reports, specific points where discontinuities
76503 : were found, and so on.
76504 :
76505 : ==========================================================================
76506 :
76507 : INPUT PARAMETERS:
76508 : state - algorithm state
76509 :
76510 : OUTPUT PARAMETERS:
76511 : rep - generic OptGuard report; more detailed reports can be
76512 : retrieved with other functions.
76513 :
76514 : NOTE: false negatives (nonsmooth problems are not identified as nonsmooth
76515 : ones) are possible although unlikely.
76516 :
76517 : The reason is that you need to make several evaluations around
76518 : nonsmoothness in order to accumulate enough information about
76519 : function curvature. Say, if you start right from the nonsmooth point,
76520 : optimizer simply won't get enough data to understand what is going
76521 : wrong before it terminates due to abrupt changes in the derivative.
76522 : It is also possible that "unlucky" step will move us to the
76523 : termination too quickly.
76524 :
76525 : Our current approach is to have less than 0.1% false negatives in
76526 : our test examples (measured with multiple restarts from random
76527 : points), and to have exactly 0% false positives.
76528 :
76529 : -- ALGLIB --
76530 : Copyright 21.11.2018 by Bochkanov Sergey
76531 : *************************************************************************/
76532 0 : void mincgoptguardresults(mincgstate* state,
76533 : optguardreport* rep,
76534 : ae_state *_state)
76535 : {
76536 :
76537 0 : _optguardreport_clear(rep);
76538 :
76539 0 : smoothnessmonitorexportreport(&state->smonitor, rep, _state);
76540 0 : }
76541 :
76542 :
76543 : /*************************************************************************
76544 : Detailed results of the OptGuard integrity check for nonsmoothness test #0
76545 :
76546 : Nonsmoothness (non-C1) test #0 studies function values (not gradient!)
76547 : obtained during line searches and monitors behavior of the directional
76548 : derivative estimate.
76549 :
76550 : This test is less powerful than test #1, but it does not depend on the
76551 : gradient values and thus it is more robust against artifacts introduced by
76552 : numerical differentiation.
76553 :
76554 : Two reports are returned:
76555 : * a "strongest" one, corresponding to line search which had highest
76556 : value of the nonsmoothness indicator
76557 : * a "longest" one, corresponding to line search which had more function
76558 : evaluations, and thus is more detailed
76559 :
76560 : In both cases following fields are returned:
76561 :
76562 : * positive - is TRUE when test flagged suspicious point; FALSE if test
76563 : did not notice anything (in the latter cases fields below are empty).
76564 : * x0[], d[] - arrays of length N which store initial point and direction
76565 : for line search (d[] can be normalized, but does not have to)
76566 : * stp[], f[] - arrays of length CNT which store step lengths and function
76567 : values at these points; f[i] is evaluated in x0+stp[i]*d.
76568 : * stpidxa, stpidxb - we suspect that function violates C1 continuity
76569 : between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3,
76570 : with most likely position of the violation between stpidxa+1 and
76571 : stpidxa+2.
76572 :
76573 : ==========================================================================
76574 : = SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will
76575 : = see where C1 continuity is violated.
76576 : ==========================================================================
76577 :
76578 : INPUT PARAMETERS:
76579 : state - algorithm state
76580 :
76581 : OUTPUT PARAMETERS:
76582 : strrep - C1 test #0 "strong" report
76583 : lngrep - C1 test #0 "long" report
76584 :
76585 : -- ALGLIB --
76586 : Copyright 21.11.2018 by Bochkanov Sergey
76587 : *************************************************************************/
76588 0 : void mincgoptguardnonc1test0results(mincgstate* state,
76589 : optguardnonc1test0report* strrep,
76590 : optguardnonc1test0report* lngrep,
76591 : ae_state *_state)
76592 : {
76593 :
76594 0 : _optguardnonc1test0report_clear(strrep);
76595 0 : _optguardnonc1test0report_clear(lngrep);
76596 :
76597 0 : smoothnessmonitorexportc1test0report(&state->smonitor.nonc1test0strrep, &state->lastscaleused, strrep, _state);
76598 0 : smoothnessmonitorexportc1test0report(&state->smonitor.nonc1test0lngrep, &state->lastscaleused, lngrep, _state);
76599 0 : }
76600 :
76601 :
76602 : /*************************************************************************
76603 : Detailed results of the OptGuard integrity check for nonsmoothness test #1
76604 :
76605 : Nonsmoothness (non-C1) test #1 studies individual components of the
76606 : gradient computed during line search.
76607 :
76608 : When precise analytic gradient is provided this test is more powerful than
76609 : test #0 which works with function values and ignores user-provided
76610 : gradient. However, test #0 becomes more powerful when numerical
76611 : differentiation is employed (in such cases test #1 detects higher levels
76612 : of numerical noise and becomes too conservative).
76613 :
76614 : This test also tells specific components of the gradient which violate C1
76615 : continuity, which makes it more informative than #0, which just tells that
76616 : continuity is violated.
76617 :
76618 : Two reports are returned:
76619 : * a "strongest" one, corresponding to line search which had highest
76620 : value of the nonsmoothness indicator
76621 : * a "longest" one, corresponding to line search which had more function
76622 : evaluations, and thus is more detailed
76623 :
76624 : In both cases following fields are returned:
76625 :
76626 : * positive - is TRUE when test flagged suspicious point; FALSE if test
76627 : did not notice anything (in the latter cases fields below are empty).
76628 : * vidx - is an index of the variable in [0,N) with nonsmooth derivative
76629 : * x0[], d[] - arrays of length N which store initial point and direction
76630 : for line search (d[] can be normalized, but does not have to)
76631 : * stp[], g[] - arrays of length CNT which store step lengths and gradient
76632 : values at these points; g[i] is evaluated in x0+stp[i]*d and contains
76633 : vidx-th component of the gradient.
76634 : * stpidxa, stpidxb - we suspect that function violates C1 continuity
76635 : between steps #stpidxa and #stpidxb (usually we have stpidxb=stpidxa+3,
76636 : with most likely position of the violation between stpidxa+1 and
76637 : stpidxa+2.
76638 :
76639 : ==========================================================================
76640 : = SHORTLY SPEAKING: build a 2D plot of (stp,f) and look at it - you will
76641 : = see where C1 continuity is violated.
76642 : ==========================================================================
76643 :
76644 : INPUT PARAMETERS:
76645 : state - algorithm state
76646 :
76647 : OUTPUT PARAMETERS:
76648 : strrep - C1 test #1 "strong" report
76649 : lngrep - C1 test #1 "long" report
76650 :
76651 : -- ALGLIB --
76652 : Copyright 21.11.2018 by Bochkanov Sergey
76653 : *************************************************************************/
76654 0 : void mincgoptguardnonc1test1results(mincgstate* state,
76655 : optguardnonc1test1report* strrep,
76656 : optguardnonc1test1report* lngrep,
76657 : ae_state *_state)
76658 : {
76659 :
76660 0 : _optguardnonc1test1report_clear(strrep);
76661 0 : _optguardnonc1test1report_clear(lngrep);
76662 :
76663 0 : smoothnessmonitorexportc1test1report(&state->smonitor.nonc1test1strrep, &state->lastscaleused, strrep, _state);
76664 0 : smoothnessmonitorexportc1test1report(&state->smonitor.nonc1test1lngrep, &state->lastscaleused, lngrep, _state);
76665 0 : }
76666 :
76667 :
76668 : /*************************************************************************
76669 : Conjugate gradient results
76670 :
76671 : INPUT PARAMETERS:
76672 : State - algorithm state
76673 :
76674 : OUTPUT PARAMETERS:
76675 : X - array[0..N-1], solution
76676 : Rep - optimization report:
76677 : * Rep.TerminationType completetion code:
76678 : * -8 internal integrity control detected infinite
76679 : or NAN values in function/gradient. Abnormal
76680 : termination signalled.
76681 : * -7 gradient verification failed.
76682 : See MinCGSetGradientCheck() for more information.
76683 : * 1 relative function improvement is no more than
76684 : EpsF.
76685 : * 2 relative step is no more than EpsX.
76686 : * 4 gradient norm is no more than EpsG
76687 : * 5 MaxIts steps was taken
76688 : * 7 stopping conditions are too stringent,
76689 : further improvement is impossible,
76690 : we return best X found so far
76691 : * 8 terminated by user
76692 : * Rep.IterationsCount contains iterations count
76693 : * NFEV countains number of function calculations
76694 :
76695 : -- ALGLIB --
76696 : Copyright 20.04.2009 by Bochkanov Sergey
76697 : *************************************************************************/
76698 0 : void mincgresults(mincgstate* state,
76699 : /* Real */ ae_vector* x,
76700 : mincgreport* rep,
76701 : ae_state *_state)
76702 : {
76703 :
76704 0 : ae_vector_clear(x);
76705 0 : _mincgreport_clear(rep);
76706 :
76707 0 : mincgresultsbuf(state, x, rep, _state);
76708 0 : }
76709 :
76710 :
76711 : /*************************************************************************
76712 : Conjugate gradient results
76713 :
76714 : Buffered implementation of MinCGResults(), which uses pre-allocated buffer
76715 : to store X[]. If buffer size is too small, it resizes buffer. It is
76716 : intended to be used in the inner cycles of performance critical algorithms
76717 : where array reallocation penalty is too large to be ignored.
76718 :
76719 : -- ALGLIB --
76720 : Copyright 20.04.2009 by Bochkanov Sergey
76721 : *************************************************************************/
76722 0 : void mincgresultsbuf(mincgstate* state,
76723 : /* Real */ ae_vector* x,
76724 : mincgreport* rep,
76725 : ae_state *_state)
76726 : {
76727 :
76728 :
76729 0 : if( x->cnt<state->n )
76730 : {
76731 0 : ae_vector_set_length(x, state->n, _state);
76732 : }
76733 0 : ae_v_move(&x->ptr.p_double[0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,state->n-1));
76734 0 : rep->iterationscount = state->repiterationscount;
76735 0 : rep->nfev = state->repnfev;
76736 0 : rep->terminationtype = state->repterminationtype;
76737 0 : }
76738 :
76739 :
76740 : /*************************************************************************
76741 : This subroutine restarts CG algorithm from new point. All optimization
76742 : parameters are left unchanged.
76743 :
76744 : This function allows to solve multiple optimization problems (which
76745 : must have same number of dimensions) without object reallocation penalty.
76746 :
76747 : INPUT PARAMETERS:
76748 : State - structure used to store algorithm state.
76749 : X - new starting point.
76750 :
76751 : -- ALGLIB --
76752 : Copyright 30.07.2010 by Bochkanov Sergey
76753 : *************************************************************************/
76754 0 : void mincgrestartfrom(mincgstate* state,
76755 : /* Real */ ae_vector* x,
76756 : ae_state *_state)
76757 : {
76758 :
76759 :
76760 0 : ae_assert(x->cnt>=state->n, "MinCGRestartFrom: Length(X)<N!", _state);
76761 0 : ae_assert(isfinitevector(x, state->n, _state), "MinCGCreate: X contains infinite or NaN values!", _state);
76762 0 : ae_v_move(&state->xbase.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,state->n-1));
76763 0 : mincgsuggeststep(state, 0.0, _state);
76764 0 : ae_vector_set_length(&state->rstate.ia, 1+1, _state);
76765 0 : ae_vector_set_length(&state->rstate.ra, 2+1, _state);
76766 0 : state->rstate.stage = -1;
76767 0 : mincg_clearrequestfields(state, _state);
76768 0 : }
76769 :
76770 :
76771 : /*************************************************************************
76772 : This subroutine submits request for termination of running optimizer. It
76773 : should be called from user-supplied callback when user decides that it is
76774 : time to "smoothly" terminate optimization process. As result, optimizer
76775 : stops at point which was "current accepted" when termination request was
76776 : submitted and returns error code 8 (successful termination).
76777 :
76778 : INPUT PARAMETERS:
76779 : State - optimizer structure
76780 :
76781 : NOTE: after request for termination optimizer may perform several
76782 : additional calls to user-supplied callbacks. It does NOT guarantee
76783 : to stop immediately - it just guarantees that these additional calls
76784 : will be discarded later.
76785 :
76786 : NOTE: calling this function on optimizer which is NOT running will have no
76787 : effect.
76788 :
76789 : NOTE: multiple calls to this function are possible. First call is counted,
76790 : subsequent calls are silently ignored.
76791 :
76792 : -- ALGLIB --
76793 : Copyright 08.10.2014 by Bochkanov Sergey
76794 : *************************************************************************/
76795 0 : void mincgrequesttermination(mincgstate* state, ae_state *_state)
76796 : {
76797 :
76798 :
76799 0 : state->userterminationneeded = ae_true;
76800 0 : }
76801 :
76802 :
76803 : /*************************************************************************
76804 : Faster version of MinCGSetPrecDiag(), for time-critical parts of code,
76805 : without safety checks.
76806 :
76807 : -- ALGLIB --
76808 : Copyright 13.10.2010 by Bochkanov Sergey
76809 : *************************************************************************/
76810 0 : void mincgsetprecdiagfast(mincgstate* state,
76811 : /* Real */ ae_vector* d,
76812 : ae_state *_state)
76813 : {
76814 : ae_int_t i;
76815 :
76816 :
76817 0 : rvectorsetlengthatleast(&state->diagh, state->n, _state);
76818 0 : rvectorsetlengthatleast(&state->diaghl2, state->n, _state);
76819 0 : state->prectype = 2;
76820 0 : state->vcnt = 0;
76821 0 : state->innerresetneeded = ae_true;
76822 0 : for(i=0; i<=state->n-1; i++)
76823 : {
76824 0 : state->diagh.ptr.p_double[i] = d->ptr.p_double[i];
76825 0 : state->diaghl2.ptr.p_double[i] = 0.0;
76826 : }
76827 0 : }
76828 :
76829 :
76830 : /*************************************************************************
76831 : This function sets low-rank preconditioner for Hessian matrix H=D+V'*C*V,
76832 : where:
76833 : * H is a Hessian matrix, which is approximated by D/V/C
76834 : * D=D1+D2 is a diagonal matrix, which includes two positive definite terms:
76835 : * constant term D1 (is not updated or infrequently updated)
76836 : * variable term D2 (can be cheaply updated from iteration to iteration)
76837 : * V is a low-rank correction
76838 : * C is a diagonal factor of low-rank correction
76839 :
76840 : Preconditioner P is calculated using approximate Woodburry formula:
76841 : P = D^(-1) - D^(-1)*V'*(C^(-1)+V*D1^(-1)*V')^(-1)*V*D^(-1)
76842 : = D^(-1) - D^(-1)*VC'*VC*D^(-1),
76843 : where
76844 : VC = sqrt(B)*V
76845 : B = (C^(-1)+V*D1^(-1)*V')^(-1)
76846 :
76847 : Note that B is calculated using constant term (D1) only, which allows us
76848 : to update D2 without recalculation of B or VC. Such preconditioner is
76849 : exact when D2 is zero. When D2 is non-zero, it is only approximation, but
76850 : very good and cheap one.
76851 :
76852 : This function accepts D1, V, C.
76853 : D2 is set to zero by default.
76854 :
76855 : Cost of this update is O(N*VCnt*VCnt), but D2 can be updated in just O(N)
76856 : by MinCGSetPrecVarPart.
76857 :
76858 : -- ALGLIB --
76859 : Copyright 13.10.2010 by Bochkanov Sergey
76860 : *************************************************************************/
76861 0 : void mincgsetpreclowrankfast(mincgstate* state,
76862 : /* Real */ ae_vector* d1,
76863 : /* Real */ ae_vector* c,
76864 : /* Real */ ae_matrix* v,
76865 : ae_int_t vcnt,
76866 : ae_state *_state)
76867 : {
76868 : ae_frame _frame_block;
76869 : ae_int_t i;
76870 : ae_int_t j;
76871 : ae_int_t k;
76872 : ae_int_t n;
76873 : double t;
76874 : ae_matrix b;
76875 :
76876 0 : ae_frame_make(_state, &_frame_block);
76877 0 : memset(&b, 0, sizeof(b));
76878 0 : ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true);
76879 :
76880 0 : if( vcnt==0 )
76881 : {
76882 0 : mincgsetprecdiagfast(state, d1, _state);
76883 0 : ae_frame_leave(_state);
76884 0 : return;
76885 : }
76886 0 : n = state->n;
76887 0 : ae_matrix_set_length(&b, vcnt, vcnt, _state);
76888 0 : rvectorsetlengthatleast(&state->diagh, n, _state);
76889 0 : rvectorsetlengthatleast(&state->diaghl2, n, _state);
76890 0 : rmatrixsetlengthatleast(&state->vcorr, vcnt, n, _state);
76891 0 : state->prectype = 2;
76892 0 : state->vcnt = vcnt;
76893 0 : state->innerresetneeded = ae_true;
76894 0 : for(i=0; i<=n-1; i++)
76895 : {
76896 0 : state->diagh.ptr.p_double[i] = d1->ptr.p_double[i];
76897 0 : state->diaghl2.ptr.p_double[i] = 0.0;
76898 : }
76899 0 : for(i=0; i<=vcnt-1; i++)
76900 : {
76901 0 : for(j=i; j<=vcnt-1; j++)
76902 : {
76903 0 : t = (double)(0);
76904 0 : for(k=0; k<=n-1; k++)
76905 : {
76906 0 : t = t+v->ptr.pp_double[i][k]*v->ptr.pp_double[j][k]/d1->ptr.p_double[k];
76907 : }
76908 0 : b.ptr.pp_double[i][j] = t;
76909 : }
76910 0 : b.ptr.pp_double[i][i] = b.ptr.pp_double[i][i]+1.0/c->ptr.p_double[i];
76911 : }
76912 0 : if( !spdmatrixcholeskyrec(&b, 0, vcnt, ae_true, &state->work0, _state) )
76913 : {
76914 0 : state->vcnt = 0;
76915 0 : ae_frame_leave(_state);
76916 0 : return;
76917 : }
76918 0 : for(i=0; i<=vcnt-1; i++)
76919 : {
76920 0 : ae_v_move(&state->vcorr.ptr.pp_double[i][0], 1, &v->ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
76921 0 : for(j=0; j<=i-1; j++)
76922 : {
76923 0 : t = b.ptr.pp_double[j][i];
76924 0 : 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);
76925 : }
76926 0 : t = 1/b.ptr.pp_double[i][i];
76927 0 : ae_v_muld(&state->vcorr.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), t);
76928 : }
76929 0 : ae_frame_leave(_state);
76930 : }
76931 :
76932 :
76933 : /*************************************************************************
76934 : This function updates variable part (diagonal matrix D2)
76935 : of low-rank preconditioner.
76936 :
76937 : This update is very cheap and takes just O(N) time.
76938 :
76939 : It has no effect with default preconditioner.
76940 :
76941 : -- ALGLIB --
76942 : Copyright 13.10.2010 by Bochkanov Sergey
76943 : *************************************************************************/
76944 0 : void mincgsetprecvarpart(mincgstate* state,
76945 : /* Real */ ae_vector* d2,
76946 : ae_state *_state)
76947 : {
76948 : ae_int_t i;
76949 : ae_int_t n;
76950 :
76951 :
76952 0 : n = state->n;
76953 0 : for(i=0; i<=n-1; i++)
76954 : {
76955 0 : state->diaghl2.ptr.p_double[i] = d2->ptr.p_double[i];
76956 : }
76957 0 : }
76958 :
76959 :
76960 : /*************************************************************************
76961 : Clears request fileds (to be sure that we don't forgot to clear something)
76962 : *************************************************************************/
76963 0 : static void mincg_clearrequestfields(mincgstate* state, ae_state *_state)
76964 : {
76965 :
76966 :
76967 0 : state->needf = ae_false;
76968 0 : state->needfg = ae_false;
76969 0 : state->xupdated = ae_false;
76970 0 : state->lsstart = ae_false;
76971 0 : state->lsend = ae_false;
76972 0 : state->algpowerup = ae_false;
76973 0 : }
76974 :
76975 :
76976 : /*************************************************************************
76977 : This function calculates preconditioned product H^(-1)*x and stores result
76978 : back into X. Work0[] and Work1[] are used as temporaries (size must be at
76979 : least N; this function doesn't allocate arrays).
76980 :
76981 : -- ALGLIB --
76982 : Copyright 13.10.2010 by Bochkanov Sergey
76983 : *************************************************************************/
76984 0 : static void mincg_preconditionedmultiply(mincgstate* state,
76985 : /* Real */ ae_vector* x,
76986 : /* Real */ ae_vector* work0,
76987 : /* Real */ ae_vector* work1,
76988 : ae_state *_state)
76989 : {
76990 : ae_int_t i;
76991 : ae_int_t n;
76992 : ae_int_t vcnt;
76993 : double v;
76994 :
76995 :
76996 0 : n = state->n;
76997 0 : vcnt = state->vcnt;
76998 0 : if( state->prectype==0 )
76999 : {
77000 0 : return;
77001 : }
77002 0 : if( state->prectype==3 )
77003 : {
77004 0 : for(i=0; i<=n-1; i++)
77005 : {
77006 0 : x->ptr.p_double[i] = x->ptr.p_double[i]*state->s.ptr.p_double[i]*state->s.ptr.p_double[i];
77007 : }
77008 0 : return;
77009 : }
77010 0 : ae_assert(state->prectype==2, "MinCG: internal error (unexpected PrecType)", _state);
77011 :
77012 : /*
77013 : * handle part common for VCnt=0 and VCnt<>0
77014 : */
77015 0 : for(i=0; i<=n-1; i++)
77016 : {
77017 0 : x->ptr.p_double[i] = x->ptr.p_double[i]/(state->diagh.ptr.p_double[i]+state->diaghl2.ptr.p_double[i]);
77018 : }
77019 :
77020 : /*
77021 : * if VCnt>0
77022 : */
77023 0 : if( vcnt>0 )
77024 : {
77025 0 : for(i=0; i<=vcnt-1; i++)
77026 : {
77027 0 : v = ae_v_dotproduct(&state->vcorr.ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
77028 0 : work0->ptr.p_double[i] = v;
77029 : }
77030 0 : for(i=0; i<=n-1; i++)
77031 : {
77032 0 : work1->ptr.p_double[i] = (double)(0);
77033 : }
77034 0 : for(i=0; i<=vcnt-1; i++)
77035 : {
77036 0 : v = work0->ptr.p_double[i];
77037 0 : 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);
77038 : }
77039 0 : for(i=0; i<=n-1; i++)
77040 : {
77041 0 : 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]);
77042 : }
77043 : }
77044 : }
77045 :
77046 :
77047 : /*************************************************************************
77048 : This function calculates preconditioned product x'*H^(-1)*y. Work0[] and
77049 : Work1[] are used as temporaries (size must be at least N; this function
77050 : doesn't allocate arrays).
77051 :
77052 : -- ALGLIB --
77053 : Copyright 13.10.2010 by Bochkanov Sergey
77054 : *************************************************************************/
77055 0 : static double mincg_preconditionedmultiply2(mincgstate* state,
77056 : /* Real */ ae_vector* x,
77057 : /* Real */ ae_vector* y,
77058 : /* Real */ ae_vector* work0,
77059 : /* Real */ ae_vector* work1,
77060 : ae_state *_state)
77061 : {
77062 : ae_int_t i;
77063 : ae_int_t n;
77064 : ae_int_t vcnt;
77065 : double v0;
77066 : double v1;
77067 : double result;
77068 :
77069 :
77070 0 : n = state->n;
77071 0 : vcnt = state->vcnt;
77072 :
77073 : /*
77074 : * no preconditioning
77075 : */
77076 0 : if( state->prectype==0 )
77077 : {
77078 0 : v0 = ae_v_dotproduct(&x->ptr.p_double[0], 1, &y->ptr.p_double[0], 1, ae_v_len(0,n-1));
77079 0 : result = v0;
77080 0 : return result;
77081 : }
77082 0 : if( state->prectype==3 )
77083 : {
77084 0 : result = (double)(0);
77085 0 : for(i=0; i<=n-1; i++)
77086 : {
77087 0 : result = result+x->ptr.p_double[i]*state->s.ptr.p_double[i]*state->s.ptr.p_double[i]*y->ptr.p_double[i];
77088 : }
77089 0 : return result;
77090 : }
77091 0 : ae_assert(state->prectype==2, "MinCG: internal error (unexpected PrecType)", _state);
77092 :
77093 : /*
77094 : * low rank preconditioning
77095 : */
77096 0 : result = 0.0;
77097 0 : for(i=0; i<=n-1; i++)
77098 : {
77099 0 : result = result+x->ptr.p_double[i]*y->ptr.p_double[i]/(state->diagh.ptr.p_double[i]+state->diaghl2.ptr.p_double[i]);
77100 : }
77101 0 : if( vcnt>0 )
77102 : {
77103 0 : for(i=0; i<=n-1; i++)
77104 : {
77105 0 : work0->ptr.p_double[i] = x->ptr.p_double[i]/(state->diagh.ptr.p_double[i]+state->diaghl2.ptr.p_double[i]);
77106 0 : work1->ptr.p_double[i] = y->ptr.p_double[i]/(state->diagh.ptr.p_double[i]+state->diaghl2.ptr.p_double[i]);
77107 : }
77108 0 : for(i=0; i<=vcnt-1; i++)
77109 : {
77110 0 : v0 = ae_v_dotproduct(&work0->ptr.p_double[0], 1, &state->vcorr.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
77111 0 : v1 = ae_v_dotproduct(&work1->ptr.p_double[0], 1, &state->vcorr.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
77112 0 : result = result-v0*v1;
77113 : }
77114 : }
77115 0 : return result;
77116 : }
77117 :
77118 :
77119 : /*************************************************************************
77120 : Internal initialization subroutine
77121 :
77122 : -- ALGLIB --
77123 : Copyright 16.05.2011 by Bochkanov Sergey
77124 : *************************************************************************/
77125 0 : static void mincg_mincginitinternal(ae_int_t n,
77126 : double diffstep,
77127 : mincgstate* state,
77128 : ae_state *_state)
77129 : {
77130 : ae_int_t i;
77131 :
77132 :
77133 :
77134 : /*
77135 : * Initialize
77136 : */
77137 0 : state->teststep = (double)(0);
77138 0 : state->smoothnessguardlevel = 0;
77139 0 : smoothnessmonitorinit(&state->smonitor, &state->s, 0, 0, ae_false, _state);
77140 0 : state->n = n;
77141 0 : state->diffstep = diffstep;
77142 0 : state->lastgoodstep = (double)(0);
77143 0 : mincgsetcond(state, (double)(0), (double)(0), (double)(0), 0, _state);
77144 0 : mincgsetxrep(state, ae_false, _state);
77145 0 : mincgsetdrep(state, ae_false, _state);
77146 0 : mincgsetstpmax(state, (double)(0), _state);
77147 0 : mincgsetcgtype(state, -1, _state);
77148 0 : mincgsetprecdefault(state, _state);
77149 0 : ae_vector_set_length(&state->xk, n, _state);
77150 0 : ae_vector_set_length(&state->dk, n, _state);
77151 0 : ae_vector_set_length(&state->xn, n, _state);
77152 0 : ae_vector_set_length(&state->dn, n, _state);
77153 0 : ae_vector_set_length(&state->x, n, _state);
77154 0 : ae_vector_set_length(&state->d, n, _state);
77155 0 : ae_vector_set_length(&state->g, n, _state);
77156 0 : ae_vector_set_length(&state->work0, n, _state);
77157 0 : ae_vector_set_length(&state->work1, n, _state);
77158 0 : ae_vector_set_length(&state->yk, n, _state);
77159 0 : ae_vector_set_length(&state->s, n, _state);
77160 0 : ae_vector_set_length(&state->invs, n, _state);
77161 0 : ae_vector_set_length(&state->lastscaleused, n, _state);
77162 0 : rvectorsetlengthatleast(&state->xbase, n, _state);
77163 0 : for(i=0; i<=n-1; i++)
77164 : {
77165 0 : state->s.ptr.p_double[i] = 1.0;
77166 0 : state->invs.ptr.p_double[i] = 1.0;
77167 0 : state->lastscaleused.ptr.p_double[i] = 1.0;
77168 : }
77169 0 : }
77170 :
77171 :
77172 0 : void _mincgstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
77173 : {
77174 0 : mincgstate *p = (mincgstate*)_p;
77175 0 : ae_touch_ptr((void*)p);
77176 0 : ae_vector_init(&p->diagh, 0, DT_REAL, _state, make_automatic);
77177 0 : ae_vector_init(&p->diaghl2, 0, DT_REAL, _state, make_automatic);
77178 0 : ae_matrix_init(&p->vcorr, 0, 0, DT_REAL, _state, make_automatic);
77179 0 : ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic);
77180 0 : ae_vector_init(&p->xk, 0, DT_REAL, _state, make_automatic);
77181 0 : ae_vector_init(&p->dk, 0, DT_REAL, _state, make_automatic);
77182 0 : ae_vector_init(&p->xn, 0, DT_REAL, _state, make_automatic);
77183 0 : ae_vector_init(&p->dn, 0, DT_REAL, _state, make_automatic);
77184 0 : ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic);
77185 0 : ae_vector_init(&p->yk, 0, DT_REAL, _state, make_automatic);
77186 0 : ae_vector_init(&p->xbase, 0, DT_REAL, _state, make_automatic);
77187 0 : ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
77188 0 : ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic);
77189 0 : _rcommstate_init(&p->rstate, _state, make_automatic);
77190 0 : _linminstate_init(&p->lstate, _state, make_automatic);
77191 0 : ae_vector_init(&p->work0, 0, DT_REAL, _state, make_automatic);
77192 0 : ae_vector_init(&p->work1, 0, DT_REAL, _state, make_automatic);
77193 0 : ae_vector_init(&p->invs, 0, DT_REAL, _state, make_automatic);
77194 0 : _smoothnessmonitor_init(&p->smonitor, _state, make_automatic);
77195 0 : ae_vector_init(&p->lastscaleused, 0, DT_REAL, _state, make_automatic);
77196 0 : }
77197 :
77198 :
77199 0 : void _mincgstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
77200 : {
77201 0 : mincgstate *dst = (mincgstate*)_dst;
77202 0 : mincgstate *src = (mincgstate*)_src;
77203 0 : dst->n = src->n;
77204 0 : dst->epsg = src->epsg;
77205 0 : dst->epsf = src->epsf;
77206 0 : dst->epsx = src->epsx;
77207 0 : dst->maxits = src->maxits;
77208 0 : dst->stpmax = src->stpmax;
77209 0 : dst->suggestedstep = src->suggestedstep;
77210 0 : dst->xrep = src->xrep;
77211 0 : dst->drep = src->drep;
77212 0 : dst->cgtype = src->cgtype;
77213 0 : dst->prectype = src->prectype;
77214 0 : ae_vector_init_copy(&dst->diagh, &src->diagh, _state, make_automatic);
77215 0 : ae_vector_init_copy(&dst->diaghl2, &src->diaghl2, _state, make_automatic);
77216 0 : ae_matrix_init_copy(&dst->vcorr, &src->vcorr, _state, make_automatic);
77217 0 : dst->vcnt = src->vcnt;
77218 0 : ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic);
77219 0 : dst->diffstep = src->diffstep;
77220 0 : dst->nfev = src->nfev;
77221 0 : dst->mcstage = src->mcstage;
77222 0 : dst->k = src->k;
77223 0 : ae_vector_init_copy(&dst->xk, &src->xk, _state, make_automatic);
77224 0 : ae_vector_init_copy(&dst->dk, &src->dk, _state, make_automatic);
77225 0 : ae_vector_init_copy(&dst->xn, &src->xn, _state, make_automatic);
77226 0 : ae_vector_init_copy(&dst->dn, &src->dn, _state, make_automatic);
77227 0 : ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic);
77228 0 : dst->fold = src->fold;
77229 0 : dst->stp = src->stp;
77230 0 : dst->curstpmax = src->curstpmax;
77231 0 : ae_vector_init_copy(&dst->yk, &src->yk, _state, make_automatic);
77232 0 : dst->lastgoodstep = src->lastgoodstep;
77233 0 : dst->lastscaledstep = src->lastscaledstep;
77234 0 : dst->mcinfo = src->mcinfo;
77235 0 : dst->innerresetneeded = src->innerresetneeded;
77236 0 : dst->terminationneeded = src->terminationneeded;
77237 0 : dst->trimthreshold = src->trimthreshold;
77238 0 : ae_vector_init_copy(&dst->xbase, &src->xbase, _state, make_automatic);
77239 0 : dst->rstimer = src->rstimer;
77240 0 : ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
77241 0 : dst->f = src->f;
77242 0 : ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic);
77243 0 : dst->needf = src->needf;
77244 0 : dst->needfg = src->needfg;
77245 0 : dst->xupdated = src->xupdated;
77246 0 : dst->algpowerup = src->algpowerup;
77247 0 : dst->lsstart = src->lsstart;
77248 0 : dst->lsend = src->lsend;
77249 0 : dst->userterminationneeded = src->userterminationneeded;
77250 0 : _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic);
77251 0 : dst->repiterationscount = src->repiterationscount;
77252 0 : dst->repnfev = src->repnfev;
77253 0 : dst->repterminationtype = src->repterminationtype;
77254 0 : dst->debugrestartscount = src->debugrestartscount;
77255 0 : _linminstate_init_copy(&dst->lstate, &src->lstate, _state, make_automatic);
77256 0 : dst->fbase = src->fbase;
77257 0 : dst->fm2 = src->fm2;
77258 0 : dst->fm1 = src->fm1;
77259 0 : dst->fp1 = src->fp1;
77260 0 : dst->fp2 = src->fp2;
77261 0 : dst->betahs = src->betahs;
77262 0 : dst->betady = src->betady;
77263 0 : ae_vector_init_copy(&dst->work0, &src->work0, _state, make_automatic);
77264 0 : ae_vector_init_copy(&dst->work1, &src->work1, _state, make_automatic);
77265 0 : ae_vector_init_copy(&dst->invs, &src->invs, _state, make_automatic);
77266 0 : dst->teststep = src->teststep;
77267 0 : dst->smoothnessguardlevel = src->smoothnessguardlevel;
77268 0 : _smoothnessmonitor_init_copy(&dst->smonitor, &src->smonitor, _state, make_automatic);
77269 0 : ae_vector_init_copy(&dst->lastscaleused, &src->lastscaleused, _state, make_automatic);
77270 0 : }
77271 :
77272 :
77273 0 : void _mincgstate_clear(void* _p)
77274 : {
77275 0 : mincgstate *p = (mincgstate*)_p;
77276 0 : ae_touch_ptr((void*)p);
77277 0 : ae_vector_clear(&p->diagh);
77278 0 : ae_vector_clear(&p->diaghl2);
77279 0 : ae_matrix_clear(&p->vcorr);
77280 0 : ae_vector_clear(&p->s);
77281 0 : ae_vector_clear(&p->xk);
77282 0 : ae_vector_clear(&p->dk);
77283 0 : ae_vector_clear(&p->xn);
77284 0 : ae_vector_clear(&p->dn);
77285 0 : ae_vector_clear(&p->d);
77286 0 : ae_vector_clear(&p->yk);
77287 0 : ae_vector_clear(&p->xbase);
77288 0 : ae_vector_clear(&p->x);
77289 0 : ae_vector_clear(&p->g);
77290 0 : _rcommstate_clear(&p->rstate);
77291 0 : _linminstate_clear(&p->lstate);
77292 0 : ae_vector_clear(&p->work0);
77293 0 : ae_vector_clear(&p->work1);
77294 0 : ae_vector_clear(&p->invs);
77295 0 : _smoothnessmonitor_clear(&p->smonitor);
77296 0 : ae_vector_clear(&p->lastscaleused);
77297 0 : }
77298 :
77299 :
77300 0 : void _mincgstate_destroy(void* _p)
77301 : {
77302 0 : mincgstate *p = (mincgstate*)_p;
77303 0 : ae_touch_ptr((void*)p);
77304 0 : ae_vector_destroy(&p->diagh);
77305 0 : ae_vector_destroy(&p->diaghl2);
77306 0 : ae_matrix_destroy(&p->vcorr);
77307 0 : ae_vector_destroy(&p->s);
77308 0 : ae_vector_destroy(&p->xk);
77309 0 : ae_vector_destroy(&p->dk);
77310 0 : ae_vector_destroy(&p->xn);
77311 0 : ae_vector_destroy(&p->dn);
77312 0 : ae_vector_destroy(&p->d);
77313 0 : ae_vector_destroy(&p->yk);
77314 0 : ae_vector_destroy(&p->xbase);
77315 0 : ae_vector_destroy(&p->x);
77316 0 : ae_vector_destroy(&p->g);
77317 0 : _rcommstate_destroy(&p->rstate);
77318 0 : _linminstate_destroy(&p->lstate);
77319 0 : ae_vector_destroy(&p->work0);
77320 0 : ae_vector_destroy(&p->work1);
77321 0 : ae_vector_destroy(&p->invs);
77322 0 : _smoothnessmonitor_destroy(&p->smonitor);
77323 0 : ae_vector_destroy(&p->lastscaleused);
77324 0 : }
77325 :
77326 :
77327 0 : void _mincgreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
77328 : {
77329 0 : mincgreport *p = (mincgreport*)_p;
77330 0 : ae_touch_ptr((void*)p);
77331 0 : }
77332 :
77333 :
77334 0 : void _mincgreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
77335 : {
77336 0 : mincgreport *dst = (mincgreport*)_dst;
77337 0 : mincgreport *src = (mincgreport*)_src;
77338 0 : dst->iterationscount = src->iterationscount;
77339 0 : dst->nfev = src->nfev;
77340 0 : dst->terminationtype = src->terminationtype;
77341 0 : }
77342 :
77343 :
77344 0 : void _mincgreport_clear(void* _p)
77345 : {
77346 0 : mincgreport *p = (mincgreport*)_p;
77347 0 : ae_touch_ptr((void*)p);
77348 0 : }
77349 :
77350 :
77351 0 : void _mincgreport_destroy(void* _p)
77352 : {
77353 0 : mincgreport *p = (mincgreport*)_p;
77354 0 : ae_touch_ptr((void*)p);
77355 0 : }
77356 :
77357 :
77358 : #endif
77359 : #if defined(AE_COMPILE_MINLM) || !defined(AE_PARTIAL_BUILD)
77360 :
77361 :
77362 : /*************************************************************************
77363 : IMPROVED LEVENBERG-MARQUARDT METHOD FOR
77364 : NON-LINEAR LEAST SQUARES OPTIMIZATION
77365 :
77366 : DESCRIPTION:
77367 : This function is used to find minimum of function which is represented as
77368 : sum of squares:
77369 : F(x) = f[0]^2(x[0],...,x[n-1]) + ... + f[m-1]^2(x[0],...,x[n-1])
77370 : using value of function vector f[] and Jacobian of f[].
77371 :
77372 :
77373 : REQUIREMENTS:
77374 : This algorithm will request following information during its operation:
77375 :
77376 : * function vector f[] at given point X
77377 : * function vector f[] and Jacobian of f[] (simultaneously) at given point
77378 :
77379 : There are several overloaded versions of MinLMOptimize() function which
77380 : correspond to different LM-like optimization algorithms provided by this
77381 : unit. You should choose version which accepts fvec() and jac() callbacks.
77382 : First one is used to calculate f[] at given point, second one calculates
77383 : f[] and Jacobian df[i]/dx[j].
77384 :
77385 : You can try to initialize MinLMState structure with VJ function and then
77386 : use incorrect version of MinLMOptimize() (for example, version which
77387 : works with general form function and does not provide Jacobian), but it
77388 : will lead to exception being thrown after first attempt to calculate
77389 : Jacobian.
77390 :
77391 :
77392 : USAGE:
77393 : 1. User initializes algorithm state with MinLMCreateVJ() call
77394 : 2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and
77395 : other functions
77396 : 3. User calls MinLMOptimize() function which takes algorithm state and
77397 : callback functions.
77398 : 4. User calls MinLMResults() to get solution
77399 : 5. Optionally, user may call MinLMRestartFrom() to solve another problem
77400 : with same N/M but another starting point and/or another function.
77401 : MinLMRestartFrom() allows to reuse already initialized structure.
77402 :
77403 :
77404 : INPUT PARAMETERS:
77405 : N - dimension, N>1
77406 : * if given, only leading N elements of X are used
77407 : * if not given, automatically determined from size of X
77408 : M - number of functions f[i]
77409 : X - initial solution, array[0..N-1]
77410 :
77411 : OUTPUT PARAMETERS:
77412 : State - structure which stores algorithm state
77413 :
77414 : NOTES:
77415 : 1. you may tune stopping conditions with MinLMSetCond() function
77416 : 2. if target function contains exp() or other fast growing functions, and
77417 : optimization algorithm makes too large steps which leads to overflow,
77418 : use MinLMSetStpMax() function to bound algorithm's steps.
77419 :
77420 : -- ALGLIB --
77421 : Copyright 30.03.2009 by Bochkanov Sergey
77422 : *************************************************************************/
77423 0 : void minlmcreatevj(ae_int_t n,
77424 : ae_int_t m,
77425 : /* Real */ ae_vector* x,
77426 : minlmstate* state,
77427 : ae_state *_state)
77428 : {
77429 :
77430 0 : _minlmstate_clear(state);
77431 :
77432 0 : ae_assert(n>=1, "MinLMCreateVJ: N<1!", _state);
77433 0 : ae_assert(m>=1, "MinLMCreateVJ: M<1!", _state);
77434 0 : ae_assert(x->cnt>=n, "MinLMCreateVJ: Length(X)<N!", _state);
77435 0 : ae_assert(isfinitevector(x, n, _state), "MinLMCreateVJ: X contains infinite or NaN values!", _state);
77436 :
77437 : /*
77438 : * initialize, check parameters
77439 : */
77440 0 : state->teststep = (double)(0);
77441 0 : state->n = n;
77442 0 : state->m = m;
77443 0 : state->algomode = 1;
77444 0 : state->hasf = ae_false;
77445 0 : state->hasfi = ae_true;
77446 0 : state->hasg = ae_false;
77447 :
77448 : /*
77449 : * second stage of initialization
77450 : */
77451 0 : minlm_lmprepare(n, m, ae_false, state, _state);
77452 0 : minlmsetacctype(state, 0, _state);
77453 0 : minlmsetcond(state, (double)(0), 0, _state);
77454 0 : minlmsetxrep(state, ae_false, _state);
77455 0 : minlmsetstpmax(state, (double)(0), _state);
77456 0 : minlmrestartfrom(state, x, _state);
77457 0 : }
77458 :
77459 :
77460 : /*************************************************************************
77461 : IMPROVED LEVENBERG-MARQUARDT METHOD FOR
77462 : NON-LINEAR LEAST SQUARES OPTIMIZATION
77463 :
77464 : DESCRIPTION:
77465 : This function is used to find minimum of function which is represented as
77466 : sum of squares:
77467 : F(x) = f[0]^2(x[0],...,x[n-1]) + ... + f[m-1]^2(x[0],...,x[n-1])
77468 : using value of function vector f[] only. Finite differences are used to
77469 : calculate Jacobian.
77470 :
77471 :
77472 : REQUIREMENTS:
77473 : This algorithm will request following information during its operation:
77474 : * function vector f[] at given point X
77475 :
77476 : There are several overloaded versions of MinLMOptimize() function which
77477 : correspond to different LM-like optimization algorithms provided by this
77478 : unit. You should choose version which accepts fvec() callback.
77479 :
77480 : You can try to initialize MinLMState structure with VJ function and then
77481 : use incorrect version of MinLMOptimize() (for example, version which
77482 : works with general form function and does not accept function vector), but
77483 : it will lead to exception being thrown after first attempt to calculate
77484 : Jacobian.
77485 :
77486 :
77487 : USAGE:
77488 : 1. User initializes algorithm state with MinLMCreateV() call
77489 : 2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and
77490 : other functions
77491 : 3. User calls MinLMOptimize() function which takes algorithm state and
77492 : callback functions.
77493 : 4. User calls MinLMResults() to get solution
77494 : 5. Optionally, user may call MinLMRestartFrom() to solve another problem
77495 : with same N/M but another starting point and/or another function.
77496 : MinLMRestartFrom() allows to reuse already initialized structure.
77497 :
77498 :
77499 : INPUT PARAMETERS:
77500 : N - dimension, N>1
77501 : * if given, only leading N elements of X are used
77502 : * if not given, automatically determined from size of X
77503 : M - number of functions f[i]
77504 : X - initial solution, array[0..N-1]
77505 : DiffStep- differentiation step, >0
77506 :
77507 : OUTPUT PARAMETERS:
77508 : State - structure which stores algorithm state
77509 :
77510 : See also MinLMIteration, MinLMResults.
77511 :
77512 : NOTES:
77513 : 1. you may tune stopping conditions with MinLMSetCond() function
77514 : 2. if target function contains exp() or other fast growing functions, and
77515 : optimization algorithm makes too large steps which leads to overflow,
77516 : use MinLMSetStpMax() function to bound algorithm's steps.
77517 :
77518 : -- ALGLIB --
77519 : Copyright 30.03.2009 by Bochkanov Sergey
77520 : *************************************************************************/
77521 0 : void minlmcreatev(ae_int_t n,
77522 : ae_int_t m,
77523 : /* Real */ ae_vector* x,
77524 : double diffstep,
77525 : minlmstate* state,
77526 : ae_state *_state)
77527 : {
77528 :
77529 0 : _minlmstate_clear(state);
77530 :
77531 0 : ae_assert(ae_isfinite(diffstep, _state), "MinLMCreateV: DiffStep is not finite!", _state);
77532 0 : ae_assert(ae_fp_greater(diffstep,(double)(0)), "MinLMCreateV: DiffStep<=0!", _state);
77533 0 : ae_assert(n>=1, "MinLMCreateV: N<1!", _state);
77534 0 : ae_assert(m>=1, "MinLMCreateV: M<1!", _state);
77535 0 : ae_assert(x->cnt>=n, "MinLMCreateV: Length(X)<N!", _state);
77536 0 : ae_assert(isfinitevector(x, n, _state), "MinLMCreateV: X contains infinite or NaN values!", _state);
77537 :
77538 : /*
77539 : * Initialize
77540 : */
77541 0 : state->teststep = (double)(0);
77542 0 : state->n = n;
77543 0 : state->m = m;
77544 0 : state->algomode = 0;
77545 0 : state->hasf = ae_false;
77546 0 : state->hasfi = ae_true;
77547 0 : state->hasg = ae_false;
77548 0 : state->diffstep = diffstep;
77549 :
77550 : /*
77551 : * Second stage of initialization
77552 : */
77553 0 : minlm_lmprepare(n, m, ae_false, state, _state);
77554 0 : minlmsetacctype(state, 1, _state);
77555 0 : minlmsetcond(state, (double)(0), 0, _state);
77556 0 : minlmsetxrep(state, ae_false, _state);
77557 0 : minlmsetstpmax(state, (double)(0), _state);
77558 0 : minlmrestartfrom(state, x, _state);
77559 0 : }
77560 :
77561 :
77562 : /*************************************************************************
77563 : LEVENBERG-MARQUARDT-LIKE METHOD FOR NON-LINEAR OPTIMIZATION
77564 :
77565 : DESCRIPTION:
77566 : This function is used to find minimum of general form (not "sum-of-
77567 : -squares") function
77568 : F = F(x[0], ..., x[n-1])
77569 : using its gradient and Hessian. Levenberg-Marquardt modification with
77570 : L-BFGS pre-optimization and internal pre-conditioned L-BFGS optimization
77571 : after each Levenberg-Marquardt step is used.
77572 :
77573 :
77574 : REQUIREMENTS:
77575 : This algorithm will request following information during its operation:
77576 :
77577 : * function value F at given point X
77578 : * F and gradient G (simultaneously) at given point X
77579 : * F, G and Hessian H (simultaneously) at given point X
77580 :
77581 : There are several overloaded versions of MinLMOptimize() function which
77582 : correspond to different LM-like optimization algorithms provided by this
77583 : unit. You should choose version which accepts func(), grad() and hess()
77584 : function pointers. First pointer is used to calculate F at given point,
77585 : second one calculates F(x) and grad F(x), third one calculates F(x),
77586 : grad F(x), hess F(x).
77587 :
77588 : You can try to initialize MinLMState structure with FGH-function and then
77589 : use incorrect version of MinLMOptimize() (for example, version which does
77590 : not provide Hessian matrix), but it will lead to exception being thrown
77591 : after first attempt to calculate Hessian.
77592 :
77593 :
77594 : USAGE:
77595 : 1. User initializes algorithm state with MinLMCreateFGH() call
77596 : 2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and
77597 : other functions
77598 : 3. User calls MinLMOptimize() function which takes algorithm state and
77599 : pointers (delegates, etc.) to callback functions.
77600 : 4. User calls MinLMResults() to get solution
77601 : 5. Optionally, user may call MinLMRestartFrom() to solve another problem
77602 : with same N but another starting point and/or another function.
77603 : MinLMRestartFrom() allows to reuse already initialized structure.
77604 :
77605 :
77606 : INPUT PARAMETERS:
77607 : N - dimension, N>1
77608 : * if given, only leading N elements of X are used
77609 : * if not given, automatically determined from size of X
77610 : X - initial solution, array[0..N-1]
77611 :
77612 : OUTPUT PARAMETERS:
77613 : State - structure which stores algorithm state
77614 :
77615 : NOTES:
77616 : 1. you may tune stopping conditions with MinLMSetCond() function
77617 : 2. if target function contains exp() or other fast growing functions, and
77618 : optimization algorithm makes too large steps which leads to overflow,
77619 : use MinLMSetStpMax() function to bound algorithm's steps.
77620 :
77621 : -- ALGLIB --
77622 : Copyright 30.03.2009 by Bochkanov Sergey
77623 : *************************************************************************/
77624 0 : void minlmcreatefgh(ae_int_t n,
77625 : /* Real */ ae_vector* x,
77626 : minlmstate* state,
77627 : ae_state *_state)
77628 : {
77629 :
77630 0 : _minlmstate_clear(state);
77631 :
77632 0 : ae_assert(n>=1, "MinLMCreateFGH: N<1!", _state);
77633 0 : ae_assert(x->cnt>=n, "MinLMCreateFGH: Length(X)<N!", _state);
77634 0 : ae_assert(isfinitevector(x, n, _state), "MinLMCreateFGH: X contains infinite or NaN values!", _state);
77635 :
77636 : /*
77637 : * initialize
77638 : */
77639 0 : state->teststep = (double)(0);
77640 0 : state->n = n;
77641 0 : state->m = 0;
77642 0 : state->algomode = 2;
77643 0 : state->hasf = ae_true;
77644 0 : state->hasfi = ae_false;
77645 0 : state->hasg = ae_true;
77646 :
77647 : /*
77648 : * init2
77649 : */
77650 0 : minlm_lmprepare(n, 0, ae_true, state, _state);
77651 0 : minlmsetacctype(state, 2, _state);
77652 0 : minlmsetcond(state, (double)(0), 0, _state);
77653 0 : minlmsetxrep(state, ae_false, _state);
77654 0 : minlmsetstpmax(state, (double)(0), _state);
77655 0 : minlmrestartfrom(state, x, _state);
77656 0 : }
77657 :
77658 :
77659 : /*************************************************************************
77660 : This function sets stopping conditions for Levenberg-Marquardt optimization
77661 : algorithm.
77662 :
77663 : INPUT PARAMETERS:
77664 : State - structure which stores algorithm state
77665 : EpsX - >=0
77666 : The subroutine finishes its work if on k+1-th iteration
77667 : the condition |v|<=EpsX is fulfilled, where:
77668 : * |.| means Euclidian norm
77669 : * v - scaled step vector, v[i]=dx[i]/s[i]
77670 : * dx - ste pvector, dx=X(k+1)-X(k)
77671 : * s - scaling coefficients set by MinLMSetScale()
77672 : Recommended values: 1E-9 ... 1E-12.
77673 : MaxIts - maximum number of iterations. If MaxIts=0, the number of
77674 : iterations is unlimited. Only Levenberg-Marquardt
77675 : iterations are counted (L-BFGS/CG iterations are NOT
77676 : counted because their cost is very low compared to that of
77677 : LM).
77678 :
77679 : Passing EpsX=0 and MaxIts=0 (simultaneously) will lead to automatic
77680 : stopping criterion selection (small EpsX).
77681 :
77682 : NOTE: it is not recommended to set large EpsX (say, 0.001). Because LM is
77683 : a second-order method, it performs very precise steps anyway.
77684 :
77685 : -- ALGLIB --
77686 : Copyright 02.04.2010 by Bochkanov Sergey
77687 : *************************************************************************/
77688 0 : void minlmsetcond(minlmstate* state,
77689 : double epsx,
77690 : ae_int_t maxits,
77691 : ae_state *_state)
77692 : {
77693 :
77694 :
77695 0 : ae_assert(ae_isfinite(epsx, _state), "MinLMSetCond: EpsX is not finite number!", _state);
77696 0 : ae_assert(ae_fp_greater_eq(epsx,(double)(0)), "MinLMSetCond: negative EpsX!", _state);
77697 0 : ae_assert(maxits>=0, "MinLMSetCond: negative MaxIts!", _state);
77698 0 : if( ae_fp_eq(epsx,(double)(0))&&maxits==0 )
77699 : {
77700 0 : epsx = 1.0E-9;
77701 : }
77702 0 : state->epsx = epsx;
77703 0 : state->maxits = maxits;
77704 0 : }
77705 :
77706 :
77707 : /*************************************************************************
77708 : This function turns on/off reporting.
77709 :
77710 : INPUT PARAMETERS:
77711 : State - structure which stores algorithm state
77712 : NeedXRep- whether iteration reports are needed or not
77713 :
77714 : If NeedXRep is True, algorithm will call rep() callback function if it is
77715 : provided to MinLMOptimize(). Both Levenberg-Marquardt and internal L-BFGS
77716 : iterations are reported.
77717 :
77718 : -- ALGLIB --
77719 : Copyright 02.04.2010 by Bochkanov Sergey
77720 : *************************************************************************/
77721 0 : void minlmsetxrep(minlmstate* state, ae_bool needxrep, ae_state *_state)
77722 : {
77723 :
77724 :
77725 0 : state->xrep = needxrep;
77726 0 : }
77727 :
77728 :
77729 : /*************************************************************************
77730 : This function sets maximum step length
77731 :
77732 : INPUT PARAMETERS:
77733 : State - structure which stores algorithm state
77734 : StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't
77735 : want to limit step length.
77736 :
77737 : Use this subroutine when you optimize target function which contains exp()
77738 : or other fast growing functions, and optimization algorithm makes too
77739 : large steps which leads to overflow. This function allows us to reject
77740 : steps that are too large (and therefore expose us to the possible
77741 : overflow) without actually calculating function value at the x+stp*d.
77742 :
77743 : NOTE: non-zero StpMax leads to moderate performance degradation because
77744 : intermediate step of preconditioned L-BFGS optimization is incompatible
77745 : with limits on step size.
77746 :
77747 : -- ALGLIB --
77748 : Copyright 02.04.2010 by Bochkanov Sergey
77749 : *************************************************************************/
77750 0 : void minlmsetstpmax(minlmstate* state, double stpmax, ae_state *_state)
77751 : {
77752 :
77753 :
77754 0 : ae_assert(ae_isfinite(stpmax, _state), "MinLMSetStpMax: StpMax is not finite!", _state);
77755 0 : ae_assert(ae_fp_greater_eq(stpmax,(double)(0)), "MinLMSetStpMax: StpMax<0!", _state);
77756 0 : state->stpmax = stpmax;
77757 0 : }
77758 :
77759 :
77760 : /*************************************************************************
77761 : This function sets scaling coefficients for LM optimizer.
77762 :
77763 : ALGLIB optimizers use scaling matrices to test stopping conditions (step
77764 : size and gradient are scaled before comparison with tolerances). Scale of
77765 : the I-th variable is a translation invariant measure of:
77766 : a) "how large" the variable is
77767 : b) how large the step should be to make significant changes in the function
77768 :
77769 : Generally, scale is NOT considered to be a form of preconditioner. But LM
77770 : optimizer is unique in that it uses scaling matrix both in the stopping
77771 : condition tests and as Marquardt damping factor.
77772 :
77773 : Proper scaling is very important for the algorithm performance. It is less
77774 : important for the quality of results, but still has some influence (it is
77775 : easier to converge when variables are properly scaled, so premature
77776 : stopping is possible when very badly scalled variables are combined with
77777 : relaxed stopping conditions).
77778 :
77779 : INPUT PARAMETERS:
77780 : State - structure stores algorithm state
77781 : S - array[N], non-zero scaling coefficients
77782 : S[i] may be negative, sign doesn't matter.
77783 :
77784 : -- ALGLIB --
77785 : Copyright 14.01.2011 by Bochkanov Sergey
77786 : *************************************************************************/
77787 0 : void minlmsetscale(minlmstate* state,
77788 : /* Real */ ae_vector* s,
77789 : ae_state *_state)
77790 : {
77791 : ae_int_t i;
77792 :
77793 :
77794 0 : ae_assert(s->cnt>=state->n, "MinLMSetScale: Length(S)<N", _state);
77795 0 : for(i=0; i<=state->n-1; i++)
77796 : {
77797 0 : ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "MinLMSetScale: S contains infinite or NAN elements", _state);
77798 0 : ae_assert(ae_fp_neq(s->ptr.p_double[i],(double)(0)), "MinLMSetScale: S contains zero elements", _state);
77799 0 : state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state);
77800 : }
77801 0 : }
77802 :
77803 :
77804 : /*************************************************************************
77805 : This function sets boundary constraints for LM optimizer
77806 :
77807 : Boundary constraints are inactive by default (after initial creation).
77808 : They are preserved until explicitly turned off with another SetBC() call.
77809 :
77810 : INPUT PARAMETERS:
77811 : State - structure stores algorithm state
77812 : BndL - lower bounds, array[N].
77813 : If some (all) variables are unbounded, you may specify
77814 : very small number or -INF (latter is recommended because
77815 : it will allow solver to use better algorithm).
77816 : BndU - upper bounds, array[N].
77817 : If some (all) variables are unbounded, you may specify
77818 : very large number or +INF (latter is recommended because
77819 : it will allow solver to use better algorithm).
77820 :
77821 : NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th
77822 : variable will be "frozen" at X[i]=BndL[i]=BndU[i].
77823 :
77824 : NOTE 2: this solver has following useful properties:
77825 : * bound constraints are always satisfied exactly
77826 : * function is evaluated only INSIDE area specified by bound constraints
77827 : or at its boundary
77828 :
77829 : -- ALGLIB --
77830 : Copyright 14.01.2011 by Bochkanov Sergey
77831 : *************************************************************************/
77832 0 : void minlmsetbc(minlmstate* state,
77833 : /* Real */ ae_vector* bndl,
77834 : /* Real */ ae_vector* bndu,
77835 : ae_state *_state)
77836 : {
77837 : ae_int_t i;
77838 : ae_int_t n;
77839 :
77840 :
77841 0 : n = state->n;
77842 0 : ae_assert(bndl->cnt>=n, "MinLMSetBC: Length(BndL)<N", _state);
77843 0 : ae_assert(bndu->cnt>=n, "MinLMSetBC: Length(BndU)<N", _state);
77844 0 : for(i=0; i<=n-1; i++)
77845 : {
77846 0 : 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);
77847 0 : 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);
77848 0 : state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i];
77849 0 : state->havebndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state);
77850 0 : state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i];
77851 0 : state->havebndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state);
77852 : }
77853 0 : }
77854 :
77855 :
77856 : /*************************************************************************
77857 : This function sets general linear constraints for LM optimizer
77858 :
77859 : Linear constraints are inactive by default (after initial creation). They
77860 : are preserved until explicitly turned off with another minlmsetlc() call.
77861 :
77862 : INPUT PARAMETERS:
77863 : State - structure stores algorithm state
77864 : C - linear constraints, array[K,N+1].
77865 : Each row of C represents one constraint, either equality
77866 : or inequality (see below):
77867 : * first N elements correspond to coefficients,
77868 : * last element corresponds to the right part.
77869 : All elements of C (including right part) must be finite.
77870 : CT - type of constraints, array[K]:
77871 : * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
77872 : * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
77873 : * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
77874 : K - number of equality/inequality constraints, K>=0:
77875 : * if given, only leading K elements of C/CT are used
77876 : * if not given, automatically determined from sizes of C/CT
77877 :
77878 : IMPORTANT: if you have linear constraints, it is strongly recommended to
77879 : set scale of variables with minlmsetscale(). QP solver which is
77880 : used to calculate linearly constrained steps heavily relies on
77881 : good scaling of input problems.
77882 :
77883 : IMPORTANT: solvers created with minlmcreatefgh() do not support linear
77884 : constraints.
77885 :
77886 : NOTE: linear (non-bound) constraints are satisfied only approximately -
77887 : there always exists some violation due to numerical errors and
77888 : algorithmic limitations.
77889 :
77890 : NOTE: general linear constraints add significant overhead to solution
77891 : process. Although solver performs roughly same amount of iterations
77892 : (when compared with similar box-only constrained problem), each
77893 : iteration now involves solution of linearly constrained QP
77894 : subproblem, which requires ~3-5 times more Cholesky decompositions.
77895 : Thus, if you can reformulate your problem in such way this it has
77896 : only box constraints, it may be beneficial to do so.
77897 :
77898 : -- ALGLIB --
77899 : Copyright 14.01.2011 by Bochkanov Sergey
77900 : *************************************************************************/
77901 0 : void minlmsetlc(minlmstate* state,
77902 : /* Real */ ae_matrix* c,
77903 : /* Integer */ ae_vector* ct,
77904 : ae_int_t k,
77905 : ae_state *_state)
77906 : {
77907 : ae_int_t i;
77908 : ae_int_t n;
77909 :
77910 :
77911 0 : n = state->n;
77912 :
77913 : /*
77914 : * First, check for errors in the inputs
77915 : */
77916 0 : ae_assert(k>=0, "MinLMSetLC: K<0", _state);
77917 0 : ae_assert(c->cols>=n+1||k==0, "MinLMSetLC: Cols(C)<N+1", _state);
77918 0 : ae_assert(c->rows>=k, "MinLMSetLC: Rows(C)<K", _state);
77919 0 : ae_assert(ct->cnt>=k, "MinLMSetLC: Length(CT)<K", _state);
77920 0 : ae_assert(apservisfinitematrix(c, k, n+1, _state), "MinLMSetLC: C contains infinite or NaN values!", _state);
77921 :
77922 : /*
77923 : * Handle zero K
77924 : */
77925 0 : if( k==0 )
77926 : {
77927 0 : state->nec = 0;
77928 0 : state->nic = 0;
77929 0 : return;
77930 : }
77931 :
77932 : /*
77933 : * Equality constraints are stored first, in the upper
77934 : * NEC rows of State.CLEIC matrix. Inequality constraints
77935 : * are stored in the next NIC rows.
77936 : *
77937 : * NOTE: we convert inequality constraints to the form
77938 : * A*x<=b before copying them.
77939 : */
77940 0 : rmatrixsetlengthatleast(&state->cleic, k, n+1, _state);
77941 0 : state->nec = 0;
77942 0 : state->nic = 0;
77943 0 : for(i=0; i<=k-1; i++)
77944 : {
77945 0 : if( ct->ptr.p_int[i]==0 )
77946 : {
77947 0 : ae_v_move(&state->cleic.ptr.pp_double[state->nec][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n));
77948 0 : state->nec = state->nec+1;
77949 : }
77950 : }
77951 0 : for(i=0; i<=k-1; i++)
77952 : {
77953 0 : if( ct->ptr.p_int[i]!=0 )
77954 : {
77955 0 : if( ct->ptr.p_int[i]>0 )
77956 : {
77957 0 : 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));
77958 : }
77959 : else
77960 : {
77961 0 : 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));
77962 : }
77963 0 : state->nic = state->nic+1;
77964 : }
77965 : }
77966 : }
77967 :
77968 :
77969 : /*************************************************************************
77970 : This function is used to change acceleration settings
77971 :
77972 : You can choose between three acceleration strategies:
77973 : * AccType=0, no acceleration.
77974 : * AccType=1, secant updates are used to update quadratic model after each
77975 : iteration. After fixed number of iterations (or after model breakdown)
77976 : we recalculate quadratic model using analytic Jacobian or finite
77977 : differences. Number of secant-based iterations depends on optimization
77978 : settings: about 3 iterations - when we have analytic Jacobian, up to 2*N
77979 : iterations - when we use finite differences to calculate Jacobian.
77980 :
77981 : AccType=1 is recommended when Jacobian calculation cost is prohibitively
77982 : high (several Mx1 function vector calculations followed by several NxN
77983 : Cholesky factorizations are faster than calculation of one M*N Jacobian).
77984 : It should also be used when we have no Jacobian, because finite difference
77985 : approximation takes too much time to compute.
77986 :
77987 : Table below list optimization protocols (XYZ protocol corresponds to
77988 : MinLMCreateXYZ) and acceleration types they support (and use by default).
77989 :
77990 : ACCELERATION TYPES SUPPORTED BY OPTIMIZATION PROTOCOLS:
77991 :
77992 : protocol 0 1 comment
77993 : V + +
77994 : VJ + +
77995 : FGH +
77996 :
77997 : DEFAULT VALUES:
77998 :
77999 : protocol 0 1 comment
78000 : V x without acceleration it is so slooooooooow
78001 : VJ x
78002 : FGH x
78003 :
78004 : NOTE: this function should be called before optimization. Attempt to call
78005 : it during algorithm iterations may result in unexpected behavior.
78006 :
78007 : NOTE: attempt to call this function with unsupported protocol/acceleration
78008 : combination will result in exception being thrown.
78009 :
78010 : -- ALGLIB --
78011 : Copyright 14.10.2010 by Bochkanov Sergey
78012 : *************************************************************************/
78013 0 : void minlmsetacctype(minlmstate* state,
78014 : ae_int_t acctype,
78015 : ae_state *_state)
78016 : {
78017 :
78018 :
78019 0 : ae_assert((acctype==0||acctype==1)||acctype==2, "MinLMSetAccType: incorrect AccType!", _state);
78020 0 : if( acctype==2 )
78021 : {
78022 0 : acctype = 0;
78023 : }
78024 0 : if( acctype==0 )
78025 : {
78026 0 : state->maxmodelage = 0;
78027 0 : state->makeadditers = ae_false;
78028 0 : return;
78029 : }
78030 0 : if( acctype==1 )
78031 : {
78032 0 : ae_assert(state->hasfi, "MinLMSetAccType: AccType=1 is incompatible with current protocol!", _state);
78033 0 : if( state->algomode==0 )
78034 : {
78035 0 : state->maxmodelage = 2*state->n;
78036 : }
78037 : else
78038 : {
78039 0 : state->maxmodelage = minlm_smallmodelage;
78040 : }
78041 0 : state->makeadditers = ae_false;
78042 0 : return;
78043 : }
78044 : }
78045 :
78046 :
78047 : /*************************************************************************
78048 : NOTES:
78049 :
78050 : 1. Depending on function used to create state structure, this algorithm
78051 : may accept Jacobian and/or Hessian and/or gradient. According to the
78052 : said above, there ase several versions of this function, which accept
78053 : different sets of callbacks.
78054 :
78055 : This flexibility opens way to subtle errors - you may create state with
78056 : MinLMCreateFGH() (optimization using Hessian), but call function which
78057 : does not accept Hessian. So when algorithm will request Hessian, there
78058 : will be no callback to call. In this case exception will be thrown.
78059 :
78060 : Be careful to avoid such errors because there is no way to find them at
78061 : compile time - you can see them at runtime only.
78062 :
78063 : -- ALGLIB --
78064 : Copyright 10.03.2009 by Bochkanov Sergey
78065 : *************************************************************************/
78066 0 : ae_bool minlmiteration(minlmstate* state, ae_state *_state)
78067 : {
78068 : ae_int_t n;
78069 : ae_int_t m;
78070 : ae_bool bflag;
78071 : ae_int_t iflag;
78072 : double v;
78073 : double s;
78074 : double t;
78075 : double fnew;
78076 : ae_int_t i;
78077 : ae_int_t k;
78078 : ae_bool result;
78079 :
78080 :
78081 :
78082 : /*
78083 : * Reverse communication preparations
78084 : * I know it looks ugly, but it works the same way
78085 : * anywhere from C++ to Python.
78086 : *
78087 : * This code initializes locals by:
78088 : * * random values determined during code
78089 : * generation - on first subroutine call
78090 : * * values from previous call - on subsequent calls
78091 : */
78092 0 : if( state->rstate.stage>=0 )
78093 : {
78094 0 : n = state->rstate.ia.ptr.p_int[0];
78095 0 : m = state->rstate.ia.ptr.p_int[1];
78096 0 : iflag = state->rstate.ia.ptr.p_int[2];
78097 0 : i = state->rstate.ia.ptr.p_int[3];
78098 0 : k = state->rstate.ia.ptr.p_int[4];
78099 0 : bflag = state->rstate.ba.ptr.p_bool[0];
78100 0 : v = state->rstate.ra.ptr.p_double[0];
78101 0 : s = state->rstate.ra.ptr.p_double[1];
78102 0 : t = state->rstate.ra.ptr.p_double[2];
78103 0 : fnew = state->rstate.ra.ptr.p_double[3];
78104 : }
78105 : else
78106 : {
78107 0 : n = 359;
78108 0 : m = -58;
78109 0 : iflag = -919;
78110 0 : i = -909;
78111 0 : k = 81;
78112 0 : bflag = ae_true;
78113 0 : v = 74;
78114 0 : s = -788;
78115 0 : t = 809;
78116 0 : fnew = 205;
78117 : }
78118 0 : if( state->rstate.stage==0 )
78119 : {
78120 0 : goto lbl_0;
78121 : }
78122 0 : if( state->rstate.stage==1 )
78123 : {
78124 0 : goto lbl_1;
78125 : }
78126 0 : if( state->rstate.stage==2 )
78127 : {
78128 0 : goto lbl_2;
78129 : }
78130 0 : if( state->rstate.stage==3 )
78131 : {
78132 0 : goto lbl_3;
78133 : }
78134 0 : if( state->rstate.stage==4 )
78135 : {
78136 0 : goto lbl_4;
78137 : }
78138 0 : if( state->rstate.stage==5 )
78139 : {
78140 0 : goto lbl_5;
78141 : }
78142 0 : if( state->rstate.stage==6 )
78143 : {
78144 0 : goto lbl_6;
78145 : }
78146 0 : if( state->rstate.stage==7 )
78147 : {
78148 0 : goto lbl_7;
78149 : }
78150 0 : if( state->rstate.stage==8 )
78151 : {
78152 0 : goto lbl_8;
78153 : }
78154 0 : if( state->rstate.stage==9 )
78155 : {
78156 0 : goto lbl_9;
78157 : }
78158 0 : if( state->rstate.stage==10 )
78159 : {
78160 0 : goto lbl_10;
78161 : }
78162 0 : if( state->rstate.stage==11 )
78163 : {
78164 0 : goto lbl_11;
78165 : }
78166 0 : if( state->rstate.stage==12 )
78167 : {
78168 0 : goto lbl_12;
78169 : }
78170 0 : if( state->rstate.stage==13 )
78171 : {
78172 0 : goto lbl_13;
78173 : }
78174 0 : if( state->rstate.stage==14 )
78175 : {
78176 0 : goto lbl_14;
78177 : }
78178 0 : if( state->rstate.stage==15 )
78179 : {
78180 0 : goto lbl_15;
78181 : }
78182 0 : if( state->rstate.stage==16 )
78183 : {
78184 0 : goto lbl_16;
78185 : }
78186 0 : if( state->rstate.stage==17 )
78187 : {
78188 0 : goto lbl_17;
78189 : }
78190 0 : if( state->rstate.stage==18 )
78191 : {
78192 0 : goto lbl_18;
78193 : }
78194 0 : if( state->rstate.stage==19 )
78195 : {
78196 0 : goto lbl_19;
78197 : }
78198 0 : if( state->rstate.stage==20 )
78199 : {
78200 0 : goto lbl_20;
78201 : }
78202 0 : if( state->rstate.stage==21 )
78203 : {
78204 0 : goto lbl_21;
78205 : }
78206 0 : if( state->rstate.stage==22 )
78207 : {
78208 0 : goto lbl_22;
78209 : }
78210 0 : if( state->rstate.stage==23 )
78211 : {
78212 0 : goto lbl_23;
78213 : }
78214 0 : if( state->rstate.stage==24 )
78215 : {
78216 0 : goto lbl_24;
78217 : }
78218 0 : if( state->rstate.stage==25 )
78219 : {
78220 0 : goto lbl_25;
78221 : }
78222 0 : if( state->rstate.stage==26 )
78223 : {
78224 0 : goto lbl_26;
78225 : }
78226 0 : if( state->rstate.stage==27 )
78227 : {
78228 0 : goto lbl_27;
78229 : }
78230 :
78231 : /*
78232 : * Routine body
78233 : */
78234 :
78235 : /*
78236 : * prepare
78237 : */
78238 0 : n = state->n;
78239 0 : m = state->m;
78240 0 : state->repiterationscount = 0;
78241 0 : state->repterminationtype = 0;
78242 0 : state->repnfunc = 0;
78243 0 : state->repnjac = 0;
78244 0 : state->repngrad = 0;
78245 0 : state->repnhess = 0;
78246 0 : state->repncholesky = 0;
78247 0 : state->userterminationneeded = ae_false;
78248 0 : if( m>0 )
78249 : {
78250 0 : smoothnessmonitorinit(&state->smonitor, &state->s, n, m, ae_false, _state);
78251 : }
78252 0 : for(i=0; i<=n-1; i++)
78253 : {
78254 0 : state->lastscaleused.ptr.p_double[i] = state->s.ptr.p_double[i];
78255 : }
78256 :
78257 : /*
78258 : * Prepare LM step finder and enforce/check feasibility of constraints
78259 : */
78260 0 : if( !minlm_minlmstepfinderinit(&state->finderstate, n, m, state->maxmodelage, state->hasfi, &state->xbase, &state->bndl, &state->bndu, &state->cleic, state->nec, state->nic, &state->s, state->stpmax, state->epsx, _state) )
78261 : {
78262 0 : state->repterminationtype = -3;
78263 0 : result = ae_false;
78264 0 : return result;
78265 : }
78266 :
78267 : /*
78268 : * set constraints for obsolete QP solver
78269 : */
78270 0 : minqpsetbc(&state->qpstate, &state->bndl, &state->bndu, _state);
78271 :
78272 : /*
78273 : * Check correctness of the analytic Jacobian
78274 : */
78275 0 : minlm_clearrequestfields(state, _state);
78276 0 : if( !(state->algomode==1&&ae_fp_greater(state->teststep,(double)(0))) )
78277 : {
78278 0 : goto lbl_28;
78279 : }
78280 0 : ae_assert(m>0, "MinLM: integrity check failed", _state);
78281 0 : lbl_30:
78282 0 : if( !smoothnessmonitorcheckgradientatx0(&state->smonitor, &state->xbase, &state->s, &state->bndl, &state->bndu, ae_true, state->teststep, _state) )
78283 : {
78284 0 : goto lbl_31;
78285 : }
78286 0 : for(i=0; i<=n-1; i++)
78287 : {
78288 0 : state->x.ptr.p_double[i] = state->smonitor.x.ptr.p_double[i];
78289 : }
78290 0 : state->needfij = ae_true;
78291 0 : state->rstate.stage = 0;
78292 0 : goto lbl_rcomm;
78293 0 : lbl_0:
78294 0 : state->needfij = ae_false;
78295 0 : for(i=0; i<=m-1; i++)
78296 : {
78297 0 : state->smonitor.fi.ptr.p_double[i] = state->fi.ptr.p_double[i];
78298 0 : for(k=0; k<=n-1; k++)
78299 : {
78300 0 : state->smonitor.j.ptr.pp_double[i][k] = state->j.ptr.pp_double[i][k];
78301 : }
78302 : }
78303 0 : goto lbl_30;
78304 0 : lbl_31:
78305 0 : lbl_28:
78306 :
78307 : /*
78308 : * Initial report of current point
78309 : *
78310 : * Note 1: we rewrite State.X twice because
78311 : * user may accidentally change it after first call.
78312 : *
78313 : * Note 2: we set NeedF or NeedFI depending on what
78314 : * information about function we have.
78315 : */
78316 0 : if( !state->xrep )
78317 : {
78318 0 : goto lbl_32;
78319 : }
78320 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
78321 0 : minlm_clearrequestfields(state, _state);
78322 0 : if( !state->hasf )
78323 : {
78324 0 : goto lbl_34;
78325 : }
78326 0 : state->needf = ae_true;
78327 0 : state->rstate.stage = 1;
78328 0 : goto lbl_rcomm;
78329 0 : lbl_1:
78330 0 : state->needf = ae_false;
78331 0 : goto lbl_35;
78332 0 : lbl_34:
78333 0 : ae_assert(state->hasfi, "MinLM: internal error 2!", _state);
78334 0 : state->needfi = ae_true;
78335 0 : state->rstate.stage = 2;
78336 0 : goto lbl_rcomm;
78337 0 : lbl_2:
78338 0 : state->needfi = ae_false;
78339 0 : v = ae_v_dotproduct(&state->fi.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
78340 0 : state->f = v;
78341 0 : lbl_35:
78342 0 : state->repnfunc = state->repnfunc+1;
78343 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
78344 0 : minlm_clearrequestfields(state, _state);
78345 0 : state->xupdated = ae_true;
78346 0 : state->rstate.stage = 3;
78347 0 : goto lbl_rcomm;
78348 0 : lbl_3:
78349 0 : state->xupdated = ae_false;
78350 0 : lbl_32:
78351 0 : if( state->userterminationneeded )
78352 : {
78353 :
78354 : /*
78355 : * User requested termination
78356 : */
78357 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
78358 0 : state->repterminationtype = 8;
78359 0 : result = ae_false;
78360 0 : return result;
78361 : }
78362 :
78363 : /*
78364 : * Prepare control variables
78365 : */
78366 0 : state->nu = (double)(1);
78367 0 : state->lambdav = -ae_maxrealnumber;
78368 0 : state->modelage = state->maxmodelage+1;
78369 0 : state->deltaxready = ae_false;
78370 0 : state->deltafready = ae_false;
78371 0 : if( state->algomode==2 )
78372 : {
78373 0 : goto lbl_36;
78374 : }
78375 :
78376 : /*
78377 : * Jacobian-based optimization mode
78378 : *
78379 : * Main cycle.
78380 : *
78381 : * We move through it until either:
78382 : * * one of the stopping conditions is met
78383 : * * we decide that stopping conditions are too stringent
78384 : * and break from cycle
78385 : */
78386 0 : lbl_38:
78387 : if( ae_false )
78388 : {
78389 : goto lbl_39;
78390 : }
78391 :
78392 : /*
78393 : * First, we have to prepare quadratic model for our function.
78394 : * We use BFlag to ensure that model is prepared;
78395 : * if it is false at the end of this block, something went wrong.
78396 : *
78397 : * We may either calculate brand new model or update old one.
78398 : *
78399 : * Before this block we have:
78400 : * * State.XBase - current position.
78401 : * * State.DeltaX - if DeltaXReady is True
78402 : * * State.DeltaF - if DeltaFReady is True
78403 : *
78404 : * After this block is over, we will have:
78405 : * * State.XBase - base point (unchanged)
78406 : * * State.FBase - F(XBase)
78407 : * * State.GBase - linear term
78408 : * * State.QuadraticModel - quadratic term
78409 : * * State.LambdaV - current estimate for lambda
78410 : *
78411 : * We also clear DeltaXReady/DeltaFReady flags
78412 : * after initialization is done.
78413 : */
78414 0 : ae_assert(state->algomode==0||state->algomode==1, "MinLM: integrity check failed", _state);
78415 0 : if( !(state->modelage>state->maxmodelage||!(state->deltaxready&&state->deltafready)) )
78416 : {
78417 0 : goto lbl_40;
78418 : }
78419 :
78420 : /*
78421 : * Refresh model (using either finite differences or analytic Jacobian)
78422 : */
78423 0 : if( state->algomode!=0 )
78424 : {
78425 0 : goto lbl_42;
78426 : }
78427 :
78428 : /*
78429 : * Optimization using F values only.
78430 : * Use finite differences to estimate Jacobian.
78431 : */
78432 0 : ae_assert(state->hasfi, "MinLMIteration: internal error when estimating Jacobian (no f[])", _state);
78433 0 : k = 0;
78434 0 : lbl_44:
78435 0 : if( k>n-1 )
78436 : {
78437 0 : goto lbl_46;
78438 : }
78439 :
78440 : /*
78441 : * We guard X[k] from leaving [BndL,BndU].
78442 : * In case BndL=BndU, we assume that derivative in this direction is zero.
78443 : */
78444 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
78445 0 : state->x.ptr.p_double[k] = state->x.ptr.p_double[k]-state->s.ptr.p_double[k]*state->diffstep;
78446 0 : if( state->havebndl.ptr.p_bool[k] )
78447 : {
78448 0 : state->x.ptr.p_double[k] = ae_maxreal(state->x.ptr.p_double[k], state->bndl.ptr.p_double[k], _state);
78449 : }
78450 0 : if( state->havebndu.ptr.p_bool[k] )
78451 : {
78452 0 : state->x.ptr.p_double[k] = ae_minreal(state->x.ptr.p_double[k], state->bndu.ptr.p_double[k], _state);
78453 : }
78454 0 : state->xm1 = state->x.ptr.p_double[k];
78455 0 : minlm_clearrequestfields(state, _state);
78456 0 : state->needfi = ae_true;
78457 0 : state->rstate.stage = 4;
78458 0 : goto lbl_rcomm;
78459 0 : lbl_4:
78460 0 : state->repnfunc = state->repnfunc+1;
78461 0 : ae_v_move(&state->fm1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
78462 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
78463 0 : state->x.ptr.p_double[k] = state->x.ptr.p_double[k]+state->s.ptr.p_double[k]*state->diffstep;
78464 0 : if( state->havebndl.ptr.p_bool[k] )
78465 : {
78466 0 : state->x.ptr.p_double[k] = ae_maxreal(state->x.ptr.p_double[k], state->bndl.ptr.p_double[k], _state);
78467 : }
78468 0 : if( state->havebndu.ptr.p_bool[k] )
78469 : {
78470 0 : state->x.ptr.p_double[k] = ae_minreal(state->x.ptr.p_double[k], state->bndu.ptr.p_double[k], _state);
78471 : }
78472 0 : state->xp1 = state->x.ptr.p_double[k];
78473 0 : minlm_clearrequestfields(state, _state);
78474 0 : state->needfi = ae_true;
78475 0 : state->rstate.stage = 5;
78476 0 : goto lbl_rcomm;
78477 0 : lbl_5:
78478 0 : state->repnfunc = state->repnfunc+1;
78479 0 : ae_v_move(&state->fp1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
78480 0 : v = state->xp1-state->xm1;
78481 0 : if( ae_fp_neq(v,(double)(0)) )
78482 : {
78483 0 : v = 1/v;
78484 0 : 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);
78485 0 : 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);
78486 : }
78487 : else
78488 : {
78489 0 : for(i=0; i<=m-1; i++)
78490 : {
78491 0 : state->j.ptr.pp_double[i][k] = (double)(0);
78492 : }
78493 : }
78494 0 : k = k+1;
78495 0 : goto lbl_44;
78496 0 : lbl_46:
78497 :
78498 : /*
78499 : * Calculate F(XBase)
78500 : */
78501 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
78502 0 : minlm_clearrequestfields(state, _state);
78503 0 : state->needfi = ae_true;
78504 0 : state->rstate.stage = 6;
78505 0 : goto lbl_rcomm;
78506 0 : lbl_6:
78507 0 : state->needfi = ae_false;
78508 0 : state->repnfunc = state->repnfunc+1;
78509 0 : state->repnjac = state->repnjac+1;
78510 :
78511 : /*
78512 : * New model
78513 : */
78514 0 : state->modelage = 0;
78515 0 : goto lbl_43;
78516 0 : lbl_42:
78517 :
78518 : /*
78519 : * Obtain f[] and Jacobian
78520 : */
78521 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
78522 0 : minlm_clearrequestfields(state, _state);
78523 0 : state->needfij = ae_true;
78524 0 : state->rstate.stage = 7;
78525 0 : goto lbl_rcomm;
78526 0 : lbl_7:
78527 0 : state->needfij = ae_false;
78528 0 : state->repnfunc = state->repnfunc+1;
78529 0 : state->repnjac = state->repnjac+1;
78530 :
78531 : /*
78532 : * New model
78533 : */
78534 0 : state->modelage = 0;
78535 0 : lbl_43:
78536 0 : goto lbl_41;
78537 0 : lbl_40:
78538 :
78539 : /*
78540 : * State.J contains Jacobian or its current approximation;
78541 : * refresh it using secant updates:
78542 : *
78543 : * f(x0+dx) = f(x0) + J*dx,
78544 : * J_new = J_old + u*h'
78545 : * h = x_new-x_old
78546 : * u = (f_new - f_old - J_old*h)/(h'h)
78547 : *
78548 : * We can explicitly generate h and u, but it is
78549 : * preferential to do in-place calculations. Only
78550 : * I-th row of J_old is needed to calculate u[I],
78551 : * so we can update J row by row in one pass.
78552 : *
78553 : * NOTE: we expect that State.XBase contains new point,
78554 : * State.FBase contains old point, State.DeltaX and
78555 : * State.DeltaY contain updates from last step.
78556 : */
78557 0 : ae_assert(state->deltaxready&&state->deltafready, "MinLMIteration: uninitialized DeltaX/DeltaF", _state);
78558 0 : t = ae_v_dotproduct(&state->deltax.ptr.p_double[0], 1, &state->deltax.ptr.p_double[0], 1, ae_v_len(0,n-1));
78559 0 : ae_assert(ae_fp_neq(t,(double)(0)), "MinLM: internal error (T=0)", _state);
78560 0 : for(i=0; i<=m-1; i++)
78561 : {
78562 0 : 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));
78563 0 : v = (state->deltaf.ptr.p_double[i]-v)/t;
78564 0 : 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);
78565 : }
78566 0 : ae_v_move(&state->fi.ptr.p_double[0], 1, &state->fibase.ptr.p_double[0], 1, ae_v_len(0,m-1));
78567 0 : ae_v_add(&state->fi.ptr.p_double[0], 1, &state->deltaf.ptr.p_double[0], 1, ae_v_len(0,m-1));
78568 :
78569 : /*
78570 : * Increase model age
78571 : */
78572 0 : state->modelage = state->modelage+1;
78573 0 : lbl_41:
78574 0 : rmatrixgemm(n, n, m, 2.0, &state->j, 0, 0, 1, &state->j, 0, 0, 0, 0.0, &state->quadraticmodel, 0, 0, _state);
78575 0 : rmatrixmv(n, m, &state->j, 0, 0, 1, &state->fi, 0, &state->gbase, 0, _state);
78576 0 : ae_v_muld(&state->gbase.ptr.p_double[0], 1, ae_v_len(0,n-1), 2);
78577 0 : v = ae_v_dotproduct(&state->fi.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
78578 0 : state->fbase = v;
78579 0 : ae_v_move(&state->fibase.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
78580 0 : state->deltaxready = ae_false;
78581 0 : state->deltafready = ae_false;
78582 :
78583 : /*
78584 : * Perform integrity check (presense of NAN/INF)
78585 : */
78586 0 : v = state->fbase;
78587 0 : for(i=0; i<=n-1; i++)
78588 : {
78589 0 : v = 0.1*v+state->gbase.ptr.p_double[i];
78590 : }
78591 0 : if( !ae_isfinite(v, _state) )
78592 : {
78593 :
78594 : /*
78595 : * Break!
78596 : */
78597 0 : state->repterminationtype = -8;
78598 0 : result = ae_false;
78599 0 : return result;
78600 : }
78601 :
78602 : /*
78603 : * If Lambda is not initialized, initialize it using quadratic model
78604 : */
78605 0 : if( ae_fp_less(state->lambdav,(double)(0)) )
78606 : {
78607 0 : state->lambdav = (double)(0);
78608 0 : for(i=0; i<=n-1; i++)
78609 : {
78610 0 : 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);
78611 : }
78612 0 : state->lambdav = 0.001*state->lambdav;
78613 0 : if( ae_fp_eq(state->lambdav,(double)(0)) )
78614 : {
78615 0 : state->lambdav = (double)(1);
78616 : }
78617 : }
78618 :
78619 : /*
78620 : * Find value of Levenberg-Marquardt damping parameter which:
78621 : * * leads to positive definite damped model
78622 : * * within bounds specified by StpMax
78623 : * * generates step which decreases function value
78624 : *
78625 : * After this block IFlag is set to:
78626 : * * -8, if internal integrity control detected NAN/INF in function values
78627 : * * -3, if constraints are infeasible
78628 : * * -2, if model update is needed (either Lambda growth is too large
78629 : * or step is too short, but we can't rely on model and stop iterations)
78630 : * * -1, if model is fresh, Lambda have grown too large, termination is needed
78631 : * * 0, if everything is OK, continue iterations
78632 : * * >0, successful termination, step is less than EpsX
78633 : *
78634 : * State.Nu can have any value on enter, but after exit it is set to 1.0
78635 : */
78636 0 : iflag = -99;
78637 0 : minlm_minlmstepfinderstart(&state->finderstate, &state->quadraticmodel, &state->gbase, state->fbase, &state->xbase, &state->fibase, state->modelage, _state);
78638 0 : lbl_47:
78639 0 : if( !minlm_minlmstepfinderiteration(&state->finderstate, &state->lambdav, &state->nu, &state->xnew, &state->deltax, &state->deltaxready, &state->deltaf, &state->deltafready, &iflag, &fnew, &state->repncholesky, _state) )
78640 : {
78641 0 : goto lbl_48;
78642 : }
78643 0 : ae_assert(state->hasfi||state->hasf, "MinLM: internal error 2!", _state);
78644 0 : state->repnfunc = state->repnfunc+1;
78645 0 : minlm_clearrequestfields(state, _state);
78646 0 : if( !state->finderstate.needfi )
78647 : {
78648 0 : goto lbl_49;
78649 : }
78650 0 : ae_assert(state->hasfi, "MinLM: internal error 2!", _state);
78651 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->finderstate.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
78652 0 : state->needfi = ae_true;
78653 0 : state->rstate.stage = 8;
78654 0 : goto lbl_rcomm;
78655 0 : lbl_8:
78656 0 : state->needfi = ae_false;
78657 0 : ae_v_move(&state->finderstate.fi.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
78658 0 : goto lbl_47;
78659 0 : lbl_49:
78660 0 : if( !state->finderstate.needf )
78661 : {
78662 0 : goto lbl_51;
78663 : }
78664 0 : ae_assert(state->hasf, "MinLM: internal error 2!", _state);
78665 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->finderstate.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
78666 0 : state->needf = ae_true;
78667 0 : state->rstate.stage = 9;
78668 0 : goto lbl_rcomm;
78669 0 : lbl_9:
78670 0 : state->needf = ae_false;
78671 0 : state->finderstate.f = state->f;
78672 0 : goto lbl_47;
78673 0 : lbl_51:
78674 0 : ae_assert(ae_false, "MinLM: internal error 2!", _state);
78675 0 : goto lbl_47;
78676 0 : lbl_48:
78677 0 : if( state->userterminationneeded )
78678 : {
78679 :
78680 : /*
78681 : * User requested termination
78682 : */
78683 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
78684 0 : state->repterminationtype = 8;
78685 0 : result = ae_false;
78686 0 : return result;
78687 : }
78688 0 : state->nu = (double)(1);
78689 0 : ae_assert(((iflag>=-3&&iflag<=0)||iflag==-8)||iflag>0, "MinLM: internal integrity check failed!", _state);
78690 0 : if( iflag==-3 )
78691 : {
78692 0 : state->repterminationtype = -3;
78693 0 : result = ae_false;
78694 0 : return result;
78695 : }
78696 0 : if( iflag==-2 )
78697 : {
78698 0 : state->modelage = state->maxmodelage+1;
78699 0 : goto lbl_38;
78700 : }
78701 0 : if( iflag!=-1 )
78702 : {
78703 0 : goto lbl_53;
78704 : }
78705 :
78706 : /*
78707 : * Stopping conditions are too stringent
78708 : */
78709 0 : state->repterminationtype = 7;
78710 0 : if( !state->xrep )
78711 : {
78712 0 : goto lbl_55;
78713 : }
78714 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
78715 0 : state->f = state->fbase;
78716 0 : minlm_clearrequestfields(state, _state);
78717 0 : state->xupdated = ae_true;
78718 0 : state->rstate.stage = 10;
78719 0 : goto lbl_rcomm;
78720 0 : lbl_10:
78721 0 : state->xupdated = ae_false;
78722 0 : lbl_55:
78723 0 : result = ae_false;
78724 0 : return result;
78725 0 : lbl_53:
78726 0 : if( !(iflag==-8||iflag>0) )
78727 : {
78728 0 : goto lbl_57;
78729 : }
78730 :
78731 : /*
78732 : * Either:
78733 : * * Integrity check failed - infinities or NANs
78734 : * * successful termination (step size is small enough)
78735 : */
78736 0 : state->repterminationtype = iflag;
78737 0 : if( !state->xrep )
78738 : {
78739 0 : goto lbl_59;
78740 : }
78741 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
78742 0 : state->f = state->fbase;
78743 0 : minlm_clearrequestfields(state, _state);
78744 0 : state->xupdated = ae_true;
78745 0 : state->rstate.stage = 11;
78746 0 : goto lbl_rcomm;
78747 0 : lbl_11:
78748 0 : state->xupdated = ae_false;
78749 0 : lbl_59:
78750 0 : result = ae_false;
78751 0 : return result;
78752 0 : lbl_57:
78753 0 : state->f = fnew;
78754 :
78755 : /*
78756 : * Levenberg-Marquardt step is ready.
78757 : * Compare predicted vs. actual decrease and decide what to do with lambda.
78758 : *
78759 : * NOTE: we expect that State.DeltaX contains direction of step,
78760 : * State.F contains function value at new point.
78761 : */
78762 0 : ae_assert(state->deltaxready, "MinLM: deltaX is not ready", _state);
78763 0 : iflag = minlm_checkdecrease(&state->quadraticmodel, &state->gbase, state->fbase, n, &state->deltax, state->f, &state->lambdav, &state->nu, _state);
78764 0 : if( iflag==0 )
78765 : {
78766 0 : goto lbl_61;
78767 : }
78768 0 : state->repterminationtype = iflag;
78769 0 : if( !state->xrep )
78770 : {
78771 0 : goto lbl_63;
78772 : }
78773 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
78774 0 : state->f = state->fbase;
78775 0 : minlm_clearrequestfields(state, _state);
78776 0 : state->xupdated = ae_true;
78777 0 : state->rstate.stage = 12;
78778 0 : goto lbl_rcomm;
78779 0 : lbl_12:
78780 0 : state->xupdated = ae_false;
78781 0 : lbl_63:
78782 0 : result = ae_false;
78783 0 : return result;
78784 0 : lbl_61:
78785 :
78786 : /*
78787 : * Accept step, report it and
78788 : * test stopping conditions on iterations count and function decrease.
78789 : *
78790 : * NOTE: we expect that State.DeltaX contains direction of step,
78791 : * State.F contains function value at new point.
78792 : *
78793 : * NOTE2: we should update XBase ONLY. In the beginning of the next
78794 : * iteration we expect that State.FIBase is NOT updated and
78795 : * contains old value of a function vector.
78796 : */
78797 0 : ae_v_move(&state->xbase.ptr.p_double[0], 1, &state->xnew.ptr.p_double[0], 1, ae_v_len(0,n-1));
78798 0 : if( !state->xrep )
78799 : {
78800 0 : goto lbl_65;
78801 : }
78802 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
78803 0 : minlm_clearrequestfields(state, _state);
78804 0 : state->xupdated = ae_true;
78805 0 : state->rstate.stage = 13;
78806 0 : goto lbl_rcomm;
78807 0 : lbl_13:
78808 0 : state->xupdated = ae_false;
78809 0 : lbl_65:
78810 0 : state->repiterationscount = state->repiterationscount+1;
78811 0 : if( state->repiterationscount>=state->maxits&&state->maxits>0 )
78812 : {
78813 0 : state->repterminationtype = 5;
78814 : }
78815 0 : if( state->repterminationtype<=0 )
78816 : {
78817 0 : goto lbl_67;
78818 : }
78819 0 : if( !state->xrep )
78820 : {
78821 0 : goto lbl_69;
78822 : }
78823 :
78824 : /*
78825 : * Report: XBase contains new point, F contains function value at new point
78826 : */
78827 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
78828 0 : minlm_clearrequestfields(state, _state);
78829 0 : state->xupdated = ae_true;
78830 0 : state->rstate.stage = 14;
78831 0 : goto lbl_rcomm;
78832 0 : lbl_14:
78833 0 : state->xupdated = ae_false;
78834 0 : lbl_69:
78835 0 : result = ae_false;
78836 0 : return result;
78837 0 : lbl_67:
78838 0 : state->modelage = state->modelage+1;
78839 0 : goto lbl_38;
78840 : lbl_39:
78841 :
78842 : /*
78843 : * Lambda is too large, we have to break iterations.
78844 : */
78845 : state->repterminationtype = 7;
78846 : if( !state->xrep )
78847 : {
78848 : goto lbl_71;
78849 : }
78850 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
78851 : state->f = state->fbase;
78852 : minlm_clearrequestfields(state, _state);
78853 : state->xupdated = ae_true;
78854 : state->rstate.stage = 15;
78855 : goto lbl_rcomm;
78856 0 : lbl_15:
78857 0 : state->xupdated = ae_false;
78858 0 : lbl_71:
78859 0 : goto lbl_37;
78860 0 : lbl_36:
78861 :
78862 : /*
78863 : * Legacy Hessian-based mode
78864 : *
78865 : * Main cycle.
78866 : *
78867 : * We move through it until either:
78868 : * * one of the stopping conditions is met
78869 : * * we decide that stopping conditions are too stringent
78870 : * and break from cycle
78871 : *
78872 : */
78873 0 : if( state->nec+state->nic>0 )
78874 : {
78875 :
78876 : /*
78877 : * FGH solver does not support general linear constraints
78878 : */
78879 0 : state->repterminationtype = -5;
78880 0 : result = ae_false;
78881 0 : return result;
78882 : }
78883 0 : lbl_73:
78884 : if( ae_false )
78885 : {
78886 : goto lbl_74;
78887 : }
78888 :
78889 : /*
78890 : * First, we have to prepare quadratic model for our function.
78891 : * We use BFlag to ensure that model is prepared;
78892 : * if it is false at the end of this block, something went wrong.
78893 : *
78894 : * We may either calculate brand new model or update old one.
78895 : *
78896 : * Before this block we have:
78897 : * * State.XBase - current position.
78898 : * * State.DeltaX - if DeltaXReady is True
78899 : * * State.DeltaF - if DeltaFReady is True
78900 : *
78901 : * After this block is over, we will have:
78902 : * * State.XBase - base point (unchanged)
78903 : * * State.FBase - F(XBase)
78904 : * * State.GBase - linear term
78905 : * * State.QuadraticModel - quadratic term
78906 : * * State.LambdaV - current estimate for lambda
78907 : *
78908 : * We also clear DeltaXReady/DeltaFReady flags
78909 : * after initialization is done.
78910 : */
78911 0 : bflag = ae_false;
78912 0 : if( !(state->algomode==0||state->algomode==1) )
78913 : {
78914 0 : goto lbl_75;
78915 : }
78916 :
78917 : /*
78918 : * Calculate f[] and Jacobian
78919 : */
78920 0 : if( !(state->modelage>state->maxmodelage||!(state->deltaxready&&state->deltafready)) )
78921 : {
78922 0 : goto lbl_77;
78923 : }
78924 :
78925 : /*
78926 : * Refresh model (using either finite differences or analytic Jacobian)
78927 : */
78928 0 : if( state->algomode!=0 )
78929 : {
78930 0 : goto lbl_79;
78931 : }
78932 :
78933 : /*
78934 : * Optimization using F values only.
78935 : * Use finite differences to estimate Jacobian.
78936 : */
78937 0 : ae_assert(state->hasfi, "MinLMIteration: internal error when estimating Jacobian (no f[])", _state);
78938 0 : k = 0;
78939 0 : lbl_81:
78940 0 : if( k>n-1 )
78941 : {
78942 0 : goto lbl_83;
78943 : }
78944 :
78945 : /*
78946 : * We guard X[k] from leaving [BndL,BndU].
78947 : * In case BndL=BndU, we assume that derivative in this direction is zero.
78948 : */
78949 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
78950 0 : state->x.ptr.p_double[k] = state->x.ptr.p_double[k]-state->s.ptr.p_double[k]*state->diffstep;
78951 0 : if( state->havebndl.ptr.p_bool[k] )
78952 : {
78953 0 : state->x.ptr.p_double[k] = ae_maxreal(state->x.ptr.p_double[k], state->bndl.ptr.p_double[k], _state);
78954 : }
78955 0 : if( state->havebndu.ptr.p_bool[k] )
78956 : {
78957 0 : state->x.ptr.p_double[k] = ae_minreal(state->x.ptr.p_double[k], state->bndu.ptr.p_double[k], _state);
78958 : }
78959 0 : state->xm1 = state->x.ptr.p_double[k];
78960 0 : minlm_clearrequestfields(state, _state);
78961 0 : state->needfi = ae_true;
78962 0 : state->rstate.stage = 16;
78963 0 : goto lbl_rcomm;
78964 0 : lbl_16:
78965 0 : state->repnfunc = state->repnfunc+1;
78966 0 : ae_v_move(&state->fm1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
78967 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
78968 0 : state->x.ptr.p_double[k] = state->x.ptr.p_double[k]+state->s.ptr.p_double[k]*state->diffstep;
78969 0 : if( state->havebndl.ptr.p_bool[k] )
78970 : {
78971 0 : state->x.ptr.p_double[k] = ae_maxreal(state->x.ptr.p_double[k], state->bndl.ptr.p_double[k], _state);
78972 : }
78973 0 : if( state->havebndu.ptr.p_bool[k] )
78974 : {
78975 0 : state->x.ptr.p_double[k] = ae_minreal(state->x.ptr.p_double[k], state->bndu.ptr.p_double[k], _state);
78976 : }
78977 0 : state->xp1 = state->x.ptr.p_double[k];
78978 0 : minlm_clearrequestfields(state, _state);
78979 0 : state->needfi = ae_true;
78980 0 : state->rstate.stage = 17;
78981 0 : goto lbl_rcomm;
78982 0 : lbl_17:
78983 0 : state->repnfunc = state->repnfunc+1;
78984 0 : ae_v_move(&state->fp1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
78985 0 : v = state->xp1-state->xm1;
78986 0 : if( ae_fp_neq(v,(double)(0)) )
78987 : {
78988 0 : v = 1/v;
78989 0 : 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);
78990 0 : 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);
78991 : }
78992 : else
78993 : {
78994 0 : for(i=0; i<=m-1; i++)
78995 : {
78996 0 : state->j.ptr.pp_double[i][k] = (double)(0);
78997 : }
78998 : }
78999 0 : k = k+1;
79000 0 : goto lbl_81;
79001 0 : lbl_83:
79002 :
79003 : /*
79004 : * Calculate F(XBase)
79005 : */
79006 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
79007 0 : minlm_clearrequestfields(state, _state);
79008 0 : state->needfi = ae_true;
79009 0 : state->rstate.stage = 18;
79010 0 : goto lbl_rcomm;
79011 0 : lbl_18:
79012 0 : state->needfi = ae_false;
79013 0 : state->repnfunc = state->repnfunc+1;
79014 0 : state->repnjac = state->repnjac+1;
79015 :
79016 : /*
79017 : * New model
79018 : */
79019 0 : state->modelage = 0;
79020 0 : goto lbl_80;
79021 0 : lbl_79:
79022 :
79023 : /*
79024 : * Obtain f[] and Jacobian
79025 : */
79026 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
79027 0 : minlm_clearrequestfields(state, _state);
79028 0 : state->needfij = ae_true;
79029 0 : state->rstate.stage = 19;
79030 0 : goto lbl_rcomm;
79031 0 : lbl_19:
79032 0 : state->needfij = ae_false;
79033 0 : state->repnfunc = state->repnfunc+1;
79034 0 : state->repnjac = state->repnjac+1;
79035 :
79036 : /*
79037 : * New model
79038 : */
79039 0 : state->modelage = 0;
79040 0 : lbl_80:
79041 0 : goto lbl_78;
79042 0 : lbl_77:
79043 :
79044 : /*
79045 : * State.J contains Jacobian or its current approximation;
79046 : * refresh it using secant updates:
79047 : *
79048 : * f(x0+dx) = f(x0) + J*dx,
79049 : * J_new = J_old + u*h'
79050 : * h = x_new-x_old
79051 : * u = (f_new - f_old - J_old*h)/(h'h)
79052 : *
79053 : * We can explicitly generate h and u, but it is
79054 : * preferential to do in-place calculations. Only
79055 : * I-th row of J_old is needed to calculate u[I],
79056 : * so we can update J row by row in one pass.
79057 : *
79058 : * NOTE: we expect that State.XBase contains new point,
79059 : * State.FBase contains old point, State.DeltaX and
79060 : * State.DeltaY contain updates from last step.
79061 : */
79062 0 : ae_assert(state->deltaxready&&state->deltafready, "MinLMIteration: uninitialized DeltaX/DeltaF", _state);
79063 0 : t = ae_v_dotproduct(&state->deltax.ptr.p_double[0], 1, &state->deltax.ptr.p_double[0], 1, ae_v_len(0,n-1));
79064 0 : ae_assert(ae_fp_neq(t,(double)(0)), "MinLM: internal error (T=0)", _state);
79065 0 : for(i=0; i<=m-1; i++)
79066 : {
79067 0 : 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));
79068 0 : v = (state->deltaf.ptr.p_double[i]-v)/t;
79069 0 : 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);
79070 : }
79071 0 : ae_v_move(&state->fi.ptr.p_double[0], 1, &state->fibase.ptr.p_double[0], 1, ae_v_len(0,m-1));
79072 0 : ae_v_add(&state->fi.ptr.p_double[0], 1, &state->deltaf.ptr.p_double[0], 1, ae_v_len(0,m-1));
79073 :
79074 : /*
79075 : * Increase model age
79076 : */
79077 0 : state->modelage = state->modelage+1;
79078 0 : lbl_78:
79079 :
79080 : /*
79081 : * Generate quadratic model:
79082 : * f(xbase+dx) =
79083 : * = (f0 + J*dx)'(f0 + J*dx)
79084 : * = f0^2 + dx'J'f0 + f0*J*dx + dx'J'J*dx
79085 : * = f0^2 + 2*f0*J*dx + dx'J'J*dx
79086 : *
79087 : * Note that we calculate 2*(J'J) instead of J'J because
79088 : * our quadratic model is based on Tailor decomposition,
79089 : * i.e. it has 0.5 before quadratic term.
79090 : */
79091 0 : rmatrixgemm(n, n, m, 2.0, &state->j, 0, 0, 1, &state->j, 0, 0, 0, 0.0, &state->quadraticmodel, 0, 0, _state);
79092 0 : rmatrixmv(n, m, &state->j, 0, 0, 1, &state->fi, 0, &state->gbase, 0, _state);
79093 0 : ae_v_muld(&state->gbase.ptr.p_double[0], 1, ae_v_len(0,n-1), 2);
79094 0 : v = ae_v_dotproduct(&state->fi.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
79095 0 : state->fbase = v;
79096 0 : ae_v_move(&state->fibase.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
79097 :
79098 : /*
79099 : * set control variables
79100 : */
79101 0 : bflag = ae_true;
79102 0 : lbl_75:
79103 0 : if( state->algomode!=2 )
79104 : {
79105 0 : goto lbl_84;
79106 : }
79107 0 : ae_assert(!state->hasfi, "MinLMIteration: internal error (HasFI is True in Hessian-based mode)", _state);
79108 :
79109 : /*
79110 : * Obtain F, G, H
79111 : */
79112 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
79113 0 : minlm_clearrequestfields(state, _state);
79114 0 : state->needfgh = ae_true;
79115 0 : state->rstate.stage = 20;
79116 0 : goto lbl_rcomm;
79117 0 : lbl_20:
79118 0 : state->needfgh = ae_false;
79119 0 : state->repnfunc = state->repnfunc+1;
79120 0 : state->repngrad = state->repngrad+1;
79121 0 : state->repnhess = state->repnhess+1;
79122 0 : rmatrixcopy(n, n, &state->h, 0, 0, &state->quadraticmodel, 0, 0, _state);
79123 0 : ae_v_move(&state->gbase.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
79124 0 : state->fbase = state->f;
79125 :
79126 : /*
79127 : * set control variables
79128 : */
79129 0 : bflag = ae_true;
79130 0 : state->modelage = 0;
79131 0 : lbl_84:
79132 0 : ae_assert(bflag, "MinLM: internal integrity check failed!", _state);
79133 0 : state->deltaxready = ae_false;
79134 0 : state->deltafready = ae_false;
79135 :
79136 : /*
79137 : * Perform integrity check (presense of NAN/INF)
79138 : */
79139 0 : v = state->fbase;
79140 0 : for(i=0; i<=n-1; i++)
79141 : {
79142 0 : v = 0.1*v+state->gbase.ptr.p_double[i];
79143 : }
79144 0 : if( !ae_isfinite(v, _state) )
79145 : {
79146 :
79147 : /*
79148 : * Break!
79149 : */
79150 0 : state->repterminationtype = -8;
79151 0 : result = ae_false;
79152 0 : return result;
79153 : }
79154 :
79155 : /*
79156 : * If Lambda is not initialized, initialize it using quadratic model
79157 : */
79158 0 : if( ae_fp_less(state->lambdav,(double)(0)) )
79159 : {
79160 0 : state->lambdav = (double)(0);
79161 0 : for(i=0; i<=n-1; i++)
79162 : {
79163 0 : 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);
79164 : }
79165 0 : state->lambdav = 0.001*state->lambdav;
79166 0 : if( ae_fp_eq(state->lambdav,(double)(0)) )
79167 : {
79168 0 : state->lambdav = (double)(1);
79169 : }
79170 : }
79171 :
79172 : /*
79173 : * Find value of Levenberg-Marquardt damping parameter which:
79174 : * * leads to positive definite damped model
79175 : * * within bounds specified by StpMax
79176 : * * generates step which decreases function value
79177 : *
79178 : * After this block IFlag is set to:
79179 : * * -3, if constraints are infeasible
79180 : * * -2, if model update is needed (either Lambda growth is too large
79181 : * or step is too short, but we can't rely on model and stop iterations)
79182 : * * -1, if model is fresh, Lambda have grown too large, termination is needed
79183 : * * 0, if everything is OK, continue iterations
79184 : *
79185 : * State.Nu can have any value on enter, but after exit it is set to 1.0
79186 : */
79187 0 : iflag = -99;
79188 0 : lbl_86:
79189 : if( ae_false )
79190 : {
79191 : goto lbl_87;
79192 : }
79193 :
79194 : /*
79195 : * Do we need model update?
79196 : */
79197 0 : if( state->modelage>0&&ae_fp_greater_eq(state->nu,minlm_suspiciousnu) )
79198 : {
79199 0 : iflag = -2;
79200 0 : goto lbl_87;
79201 : }
79202 :
79203 : /*
79204 : * Setup quadratic solver and solve quadratic programming problem.
79205 : * After problem is solved we'll try to bound step by StpMax
79206 : * (Lambda will be increased if step size is too large).
79207 : *
79208 : * We use BFlag variable to indicate that we have to increase Lambda.
79209 : * If it is False, we will try to increase Lambda and move to new iteration.
79210 : */
79211 0 : bflag = ae_true;
79212 0 : minqpsetstartingpointfast(&state->qpstate, &state->xbase, _state);
79213 0 : minqpsetoriginfast(&state->qpstate, &state->xbase, _state);
79214 0 : minqpsetlineartermfast(&state->qpstate, &state->gbase, _state);
79215 0 : minqpsetquadratictermfast(&state->qpstate, &state->quadraticmodel, ae_true, 0.0, _state);
79216 0 : for(i=0; i<=n-1; i++)
79217 : {
79218 0 : state->tmp0.ptr.p_double[i] = state->quadraticmodel.ptr.pp_double[i][i]+state->lambdav/ae_sqr(state->s.ptr.p_double[i], _state);
79219 : }
79220 0 : minqprewritediagonal(&state->qpstate, &state->tmp0, _state);
79221 0 : minqpoptimize(&state->qpstate, _state);
79222 0 : minqpresultsbuf(&state->qpstate, &state->xdir, &state->qprep, _state);
79223 0 : if( state->qprep.terminationtype>0 )
79224 : {
79225 :
79226 : /*
79227 : * successful solution of QP problem
79228 : */
79229 0 : ae_v_sub(&state->xdir.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
79230 0 : v = ae_v_dotproduct(&state->xdir.ptr.p_double[0], 1, &state->xdir.ptr.p_double[0], 1, ae_v_len(0,n-1));
79231 0 : if( ae_isfinite(v, _state) )
79232 : {
79233 0 : v = ae_sqrt(v, _state);
79234 0 : if( ae_fp_greater(state->stpmax,(double)(0))&&ae_fp_greater(v,state->stpmax) )
79235 : {
79236 0 : bflag = ae_false;
79237 : }
79238 : }
79239 : else
79240 : {
79241 0 : bflag = ae_false;
79242 : }
79243 : }
79244 : else
79245 : {
79246 :
79247 : /*
79248 : * Either problem is non-convex (increase LambdaV) or constraints are inconsistent
79249 : */
79250 0 : ae_assert((state->qprep.terminationtype==-3||state->qprep.terminationtype==-4)||state->qprep.terminationtype==-5, "MinLM: unexpected completion code from QP solver", _state);
79251 0 : if( state->qprep.terminationtype==-3 )
79252 : {
79253 0 : iflag = -3;
79254 0 : goto lbl_87;
79255 : }
79256 0 : bflag = ae_false;
79257 : }
79258 0 : if( !bflag )
79259 : {
79260 :
79261 : /*
79262 : * Solution failed:
79263 : * try to increase lambda to make matrix positive definite and continue.
79264 : */
79265 0 : if( !minlm_increaselambda(&state->lambdav, &state->nu, _state) )
79266 : {
79267 0 : iflag = -1;
79268 0 : goto lbl_87;
79269 : }
79270 0 : goto lbl_86;
79271 : }
79272 :
79273 : /*
79274 : * Step in State.XDir and it is bounded by StpMax.
79275 : *
79276 : * We should check stopping conditions on step size here.
79277 : * DeltaX, which is used for secant updates, is initialized here.
79278 : *
79279 : * This code is a bit tricky because sometimes XDir<>0, but
79280 : * it is so small that XDir+XBase==XBase (in finite precision
79281 : * arithmetics). So we set DeltaX to XBase, then
79282 : * add XDir, and then subtract XBase to get exact value of
79283 : * DeltaX.
79284 : *
79285 : * Step length is estimated using DeltaX.
79286 : *
79287 : * NOTE: stopping conditions are tested
79288 : * for fresh models only (ModelAge=0)
79289 : */
79290 0 : ae_v_move(&state->deltax.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
79291 0 : ae_v_add(&state->deltax.ptr.p_double[0], 1, &state->xdir.ptr.p_double[0], 1, ae_v_len(0,n-1));
79292 0 : ae_v_sub(&state->deltax.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
79293 0 : state->deltaxready = ae_true;
79294 0 : v = 0.0;
79295 0 : for(i=0; i<=n-1; i++)
79296 : {
79297 0 : v = v+ae_sqr(state->deltax.ptr.p_double[i]/state->s.ptr.p_double[i], _state);
79298 : }
79299 0 : v = ae_sqrt(v, _state);
79300 0 : if( ae_fp_greater(v,state->epsx) )
79301 : {
79302 0 : goto lbl_88;
79303 : }
79304 0 : if( state->modelage!=0 )
79305 : {
79306 0 : goto lbl_90;
79307 : }
79308 :
79309 : /*
79310 : * Step is too short, model is fresh and we can rely on it.
79311 : * Terminating.
79312 : */
79313 0 : state->repterminationtype = 2;
79314 0 : if( !state->xrep )
79315 : {
79316 0 : goto lbl_92;
79317 : }
79318 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
79319 0 : state->f = state->fbase;
79320 0 : minlm_clearrequestfields(state, _state);
79321 0 : state->xupdated = ae_true;
79322 0 : state->rstate.stage = 21;
79323 0 : goto lbl_rcomm;
79324 0 : lbl_21:
79325 0 : state->xupdated = ae_false;
79326 0 : lbl_92:
79327 0 : result = ae_false;
79328 0 : return result;
79329 : goto lbl_91;
79330 0 : lbl_90:
79331 :
79332 : /*
79333 : * Step is suspiciously short, but model is not fresh
79334 : * and we can't rely on it.
79335 : */
79336 0 : iflag = -2;
79337 0 : goto lbl_87;
79338 0 : lbl_91:
79339 0 : lbl_88:
79340 :
79341 : /*
79342 : * Let's evaluate new step:
79343 : * a) if we have Fi vector, we evaluate it using rcomm, and
79344 : * then we manually calculate State.F as sum of squares of Fi[]
79345 : * b) if we have F value, we just evaluate it through rcomm interface
79346 : *
79347 : * We prefer (a) because we may need Fi vector for additional
79348 : * iterations
79349 : */
79350 0 : ae_assert(state->hasfi||state->hasf, "MinLM: internal error 2!", _state);
79351 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
79352 0 : ae_v_add(&state->x.ptr.p_double[0], 1, &state->xdir.ptr.p_double[0], 1, ae_v_len(0,n-1));
79353 0 : minlm_clearrequestfields(state, _state);
79354 0 : if( !state->hasfi )
79355 : {
79356 0 : goto lbl_94;
79357 : }
79358 0 : state->needfi = ae_true;
79359 0 : state->rstate.stage = 22;
79360 0 : goto lbl_rcomm;
79361 0 : lbl_22:
79362 0 : state->needfi = ae_false;
79363 0 : v = ae_v_dotproduct(&state->fi.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
79364 0 : state->f = v;
79365 0 : ae_v_move(&state->deltaf.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
79366 0 : ae_v_sub(&state->deltaf.ptr.p_double[0], 1, &state->fibase.ptr.p_double[0], 1, ae_v_len(0,m-1));
79367 0 : state->deltafready = ae_true;
79368 0 : goto lbl_95;
79369 0 : lbl_94:
79370 0 : state->needf = ae_true;
79371 0 : state->rstate.stage = 23;
79372 0 : goto lbl_rcomm;
79373 0 : lbl_23:
79374 0 : state->needf = ae_false;
79375 0 : lbl_95:
79376 0 : state->repnfunc = state->repnfunc+1;
79377 0 : if( !ae_isfinite(state->f, _state) )
79378 : {
79379 :
79380 : /*
79381 : * Integrity check failed, break!
79382 : */
79383 0 : state->repterminationtype = -8;
79384 0 : result = ae_false;
79385 0 : return result;
79386 : }
79387 0 : if( ae_fp_greater_eq(state->f,state->fbase) )
79388 : {
79389 :
79390 : /*
79391 : * Increase lambda and continue
79392 : */
79393 0 : if( !minlm_increaselambda(&state->lambdav, &state->nu, _state) )
79394 : {
79395 0 : iflag = -1;
79396 0 : goto lbl_87;
79397 : }
79398 0 : goto lbl_86;
79399 : }
79400 :
79401 : /*
79402 : * We've found our step!
79403 : */
79404 0 : iflag = 0;
79405 0 : goto lbl_87;
79406 : goto lbl_86;
79407 0 : lbl_87:
79408 0 : if( state->userterminationneeded )
79409 : {
79410 :
79411 : /*
79412 : * User requested termination
79413 : */
79414 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
79415 0 : state->repterminationtype = 8;
79416 0 : result = ae_false;
79417 0 : return result;
79418 : }
79419 0 : state->nu = (double)(1);
79420 0 : ae_assert(iflag>=-3&&iflag<=0, "MinLM: internal integrity check failed!", _state);
79421 0 : if( iflag==-3 )
79422 : {
79423 0 : state->repterminationtype = -3;
79424 0 : result = ae_false;
79425 0 : return result;
79426 : }
79427 0 : if( iflag==-2 )
79428 : {
79429 0 : state->modelage = state->maxmodelage+1;
79430 0 : goto lbl_73;
79431 : }
79432 0 : if( iflag==-1 )
79433 : {
79434 0 : goto lbl_74;
79435 : }
79436 :
79437 : /*
79438 : * Levenberg-Marquardt step is ready.
79439 : * Compare predicted vs. actual decrease and decide what to do with lambda.
79440 : *
79441 : * NOTE: we expect that State.DeltaX contains direction of step,
79442 : * State.F contains function value at new point.
79443 : */
79444 0 : ae_assert(state->deltaxready, "MinLM: deltaX is not ready", _state);
79445 0 : t = (double)(0);
79446 0 : for(i=0; i<=n-1; i++)
79447 : {
79448 0 : 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));
79449 0 : t = t+state->deltax.ptr.p_double[i]*state->gbase.ptr.p_double[i]+0.5*state->deltax.ptr.p_double[i]*v;
79450 : }
79451 0 : state->predicteddecrease = -t;
79452 0 : state->actualdecrease = -(state->f-state->fbase);
79453 0 : if( ae_fp_less_eq(state->predicteddecrease,(double)(0)) )
79454 : {
79455 0 : goto lbl_74;
79456 : }
79457 0 : v = state->actualdecrease/state->predicteddecrease;
79458 0 : if( ae_fp_greater_eq(v,0.1) )
79459 : {
79460 0 : goto lbl_96;
79461 : }
79462 0 : if( minlm_increaselambda(&state->lambdav, &state->nu, _state) )
79463 : {
79464 0 : goto lbl_98;
79465 : }
79466 :
79467 : /*
79468 : * Lambda is too large, we have to break iterations.
79469 : */
79470 0 : state->repterminationtype = 7;
79471 0 : if( !state->xrep )
79472 : {
79473 0 : goto lbl_100;
79474 : }
79475 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
79476 0 : state->f = state->fbase;
79477 0 : minlm_clearrequestfields(state, _state);
79478 0 : state->xupdated = ae_true;
79479 0 : state->rstate.stage = 24;
79480 0 : goto lbl_rcomm;
79481 0 : lbl_24:
79482 0 : state->xupdated = ae_false;
79483 0 : lbl_100:
79484 0 : result = ae_false;
79485 0 : return result;
79486 0 : lbl_98:
79487 0 : lbl_96:
79488 0 : if( ae_fp_greater(v,0.5) )
79489 : {
79490 0 : minlm_decreaselambda(&state->lambdav, &state->nu, _state);
79491 : }
79492 :
79493 : /*
79494 : * Accept step, report it and
79495 : * test stopping conditions on iterations count and function decrease.
79496 : *
79497 : * NOTE: we expect that State.DeltaX contains direction of step,
79498 : * State.F contains function value at new point.
79499 : *
79500 : * NOTE2: we should update XBase ONLY. In the beginning of the next
79501 : * iteration we expect that State.FIBase is NOT updated and
79502 : * contains old value of a function vector.
79503 : */
79504 0 : ae_v_add(&state->xbase.ptr.p_double[0], 1, &state->deltax.ptr.p_double[0], 1, ae_v_len(0,n-1));
79505 0 : if( !state->xrep )
79506 : {
79507 0 : goto lbl_102;
79508 : }
79509 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
79510 0 : minlm_clearrequestfields(state, _state);
79511 0 : state->xupdated = ae_true;
79512 0 : state->rstate.stage = 25;
79513 0 : goto lbl_rcomm;
79514 0 : lbl_25:
79515 0 : state->xupdated = ae_false;
79516 0 : lbl_102:
79517 0 : state->repiterationscount = state->repiterationscount+1;
79518 0 : if( state->repiterationscount>=state->maxits&&state->maxits>0 )
79519 : {
79520 0 : state->repterminationtype = 5;
79521 : }
79522 0 : if( state->repterminationtype<=0 )
79523 : {
79524 0 : goto lbl_104;
79525 : }
79526 0 : if( !state->xrep )
79527 : {
79528 0 : goto lbl_106;
79529 : }
79530 :
79531 : /*
79532 : * Report: XBase contains new point, F contains function value at new point
79533 : */
79534 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
79535 0 : minlm_clearrequestfields(state, _state);
79536 0 : state->xupdated = ae_true;
79537 0 : state->rstate.stage = 26;
79538 0 : goto lbl_rcomm;
79539 0 : lbl_26:
79540 0 : state->xupdated = ae_false;
79541 0 : lbl_106:
79542 0 : result = ae_false;
79543 0 : return result;
79544 0 : lbl_104:
79545 0 : state->modelage = state->modelage+1;
79546 0 : goto lbl_73;
79547 0 : lbl_74:
79548 :
79549 : /*
79550 : * Lambda is too large, we have to break iterations.
79551 : */
79552 0 : state->repterminationtype = 7;
79553 0 : if( !state->xrep )
79554 : {
79555 0 : goto lbl_108;
79556 : }
79557 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
79558 0 : state->f = state->fbase;
79559 0 : minlm_clearrequestfields(state, _state);
79560 0 : state->xupdated = ae_true;
79561 0 : state->rstate.stage = 27;
79562 0 : goto lbl_rcomm;
79563 0 : lbl_27:
79564 0 : state->xupdated = ae_false;
79565 0 : lbl_108:
79566 0 : lbl_37:
79567 0 : result = ae_false;
79568 0 : return result;
79569 :
79570 : /*
79571 : * Saving state
79572 : */
79573 0 : lbl_rcomm:
79574 0 : result = ae_true;
79575 0 : state->rstate.ia.ptr.p_int[0] = n;
79576 0 : state->rstate.ia.ptr.p_int[1] = m;
79577 0 : state->rstate.ia.ptr.p_int[2] = iflag;
79578 0 : state->rstate.ia.ptr.p_int[3] = i;
79579 0 : state->rstate.ia.ptr.p_int[4] = k;
79580 0 : state->rstate.ba.ptr.p_bool[0] = bflag;
79581 0 : state->rstate.ra.ptr.p_double[0] = v;
79582 0 : state->rstate.ra.ptr.p_double[1] = s;
79583 0 : state->rstate.ra.ptr.p_double[2] = t;
79584 0 : state->rstate.ra.ptr.p_double[3] = fnew;
79585 0 : return result;
79586 : }
79587 :
79588 :
79589 : /*************************************************************************
79590 : This function activates/deactivates verification of the user-supplied
79591 : analytic Jacobian.
79592 :
79593 : Upon activation of this option OptGuard integrity checker performs
79594 : numerical differentiation of your target function vector at the initial
79595 : point (note: future versions may also perform check at the final point)
79596 : and compares numerical Jacobian with analytic one provided by you.
79597 :
79598 : If difference is too large, an error flag is set and optimization session
79599 : continues. After optimization session is over, you can retrieve the report
79600 : which stores both Jacobians, and specific components highlighted as
79601 : suspicious by the OptGuard.
79602 :
79603 : The OptGuard report can be retrieved with minlmoptguardresults().
79604 :
79605 : IMPORTANT: gradient check is a high-overhead option which will cost you
79606 : about 3*N additional function evaluations. In many cases it may
79607 : cost as much as the rest of the optimization session.
79608 :
79609 : YOU SHOULD NOT USE IT IN THE PRODUCTION CODE UNLESS YOU WANT TO
79610 : CHECK DERIVATIVES PROVIDED BY SOME THIRD PARTY.
79611 :
79612 : NOTE: unlike previous incarnation of the gradient checking code, OptGuard
79613 : does NOT interrupt optimization even if it discovers bad gradient.
79614 :
79615 : INPUT PARAMETERS:
79616 : State - structure used to store algorithm state
79617 : TestStep - verification step used for numerical differentiation:
79618 : * TestStep=0 turns verification off
79619 : * TestStep>0 activates verification
79620 : You should carefully choose TestStep. Value which is
79621 : too large (so large that function behavior is non-
79622 : cubic at this scale) will lead to false alarms. Too
79623 : short step will result in rounding errors dominating
79624 : numerical derivative.
79625 :
79626 : You may use different step for different parameters by
79627 : means of setting scale with minlmsetscale().
79628 :
79629 : === EXPLANATION ==========================================================
79630 :
79631 : In order to verify gradient algorithm performs following steps:
79632 : * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i],
79633 : where X[i] is i-th component of the initial point and S[i] is a scale
79634 : of i-th parameter
79635 : * F(X) is evaluated at these trial points
79636 : * we perform one more evaluation in the middle point of the interval
79637 : * we build cubic model using function values and derivatives at trial
79638 : points and we compare its prediction with actual value in the middle
79639 : point
79640 :
79641 : -- ALGLIB --
79642 : Copyright 15.06.2014 by Bochkanov Sergey
79643 : *************************************************************************/
79644 0 : void minlmoptguardgradient(minlmstate* state,
79645 : double teststep,
79646 : ae_state *_state)
79647 : {
79648 :
79649 :
79650 0 : ae_assert(ae_isfinite(teststep, _state), "MinLMOptGuardGradient: TestStep contains NaN or INF", _state);
79651 0 : ae_assert(ae_fp_greater_eq(teststep,(double)(0)), "MinLMOptGuardGradient: invalid argument TestStep(TestStep<0)", _state);
79652 0 : state->teststep = teststep;
79653 0 : }
79654 :
79655 :
79656 : /*************************************************************************
79657 : Results of OptGuard integrity check, should be called after optimization
79658 : session is over.
79659 :
79660 : OptGuard checks analytic Jacobian against reference value obtained by
79661 : numerical differentiation with user-specified step.
79662 :
79663 : NOTE: other optimizers perform additional OptGuard checks for things like
79664 : C0/C1-continuity violations. However, LM optimizer can check only
79665 : for incorrect Jacobian.
79666 :
79667 : The reason is that unlike line search methods LM optimizer does not
79668 : perform extensive evaluations along the line. Thus, we simply do not
79669 : have enough data to catch C0/C1-violations.
79670 :
79671 : This check is activated with minlmoptguardgradient() function.
79672 :
79673 : Following flags are set when these errors are suspected:
79674 : * rep.badgradsuspected, and additionally:
79675 : * rep.badgradfidx for specific function (Jacobian row) suspected
79676 : * rep.badgradvidx for specific variable (Jacobian column) suspected
79677 : * rep.badgradxbase, a point where gradient/Jacobian is tested
79678 : * rep.badgraduser, user-provided gradient/Jacobian
79679 : * rep.badgradnum, reference gradient/Jacobian obtained via numerical
79680 : differentiation
79681 :
79682 : INPUT PARAMETERS:
79683 : state - algorithm state
79684 :
79685 : OUTPUT PARAMETERS:
79686 : rep - OptGuard report
79687 :
79688 : -- ALGLIB --
79689 : Copyright 21.11.2018 by Bochkanov Sergey
79690 : *************************************************************************/
79691 0 : void minlmoptguardresults(minlmstate* state,
79692 : optguardreport* rep,
79693 : ae_state *_state)
79694 : {
79695 :
79696 0 : _optguardreport_clear(rep);
79697 :
79698 0 : smoothnessmonitorexportreport(&state->smonitor, rep, _state);
79699 0 : }
79700 :
79701 :
79702 : /*************************************************************************
79703 : Levenberg-Marquardt algorithm results
79704 :
79705 : NOTE: if you activated OptGuard integrity checking functionality and want
79706 : to get OptGuard report, it can be retrieved with the help of
79707 : minlmoptguardresults() function.
79708 :
79709 : INPUT PARAMETERS:
79710 : State - algorithm state
79711 :
79712 : OUTPUT PARAMETERS:
79713 : X - array[0..N-1], solution
79714 : Rep - optimization report; includes termination codes and
79715 : additional information. Termination codes are listed below,
79716 : see comments for this structure for more info.
79717 : Termination code is stored in rep.terminationtype field:
79718 : * -8 optimizer detected NAN/INF values either in the
79719 : function itself, or in its Jacobian
79720 : * -3 constraints are inconsistent
79721 : * 2 relative step is no more than EpsX.
79722 : * 5 MaxIts steps was taken
79723 : * 7 stopping conditions are too stringent,
79724 : further improvement is impossible
79725 : * 8 terminated by user who called minlmrequesttermination().
79726 : X contains point which was "current accepted" when
79727 : termination request was submitted.
79728 :
79729 : -- ALGLIB --
79730 : Copyright 10.03.2009 by Bochkanov Sergey
79731 : *************************************************************************/
79732 0 : void minlmresults(minlmstate* state,
79733 : /* Real */ ae_vector* x,
79734 : minlmreport* rep,
79735 : ae_state *_state)
79736 : {
79737 :
79738 0 : ae_vector_clear(x);
79739 0 : _minlmreport_clear(rep);
79740 :
79741 0 : minlmresultsbuf(state, x, rep, _state);
79742 0 : }
79743 :
79744 :
79745 : /*************************************************************************
79746 : Levenberg-Marquardt algorithm results
79747 :
79748 : Buffered implementation of MinLMResults(), which uses pre-allocated buffer
79749 : to store X[]. If buffer size is too small, it resizes buffer. It is
79750 : intended to be used in the inner cycles of performance critical algorithms
79751 : where array reallocation penalty is too large to be ignored.
79752 :
79753 : -- ALGLIB --
79754 : Copyright 10.03.2009 by Bochkanov Sergey
79755 : *************************************************************************/
79756 0 : void minlmresultsbuf(minlmstate* state,
79757 : /* Real */ ae_vector* x,
79758 : minlmreport* rep,
79759 : ae_state *_state)
79760 : {
79761 :
79762 :
79763 0 : if( x->cnt<state->n )
79764 : {
79765 0 : ae_vector_set_length(x, state->n, _state);
79766 : }
79767 0 : ae_v_move(&x->ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,state->n-1));
79768 0 : rep->iterationscount = state->repiterationscount;
79769 0 : rep->terminationtype = state->repterminationtype;
79770 0 : rep->nfunc = state->repnfunc;
79771 0 : rep->njac = state->repnjac;
79772 0 : rep->ngrad = state->repngrad;
79773 0 : rep->nhess = state->repnhess;
79774 0 : rep->ncholesky = state->repncholesky;
79775 0 : }
79776 :
79777 :
79778 : /*************************************************************************
79779 : This subroutine restarts LM algorithm from new point. All optimization
79780 : parameters are left unchanged.
79781 :
79782 : This function allows to solve multiple optimization problems (which
79783 : must have same number of dimensions) without object reallocation penalty.
79784 :
79785 : INPUT PARAMETERS:
79786 : State - structure used for reverse communication previously
79787 : allocated with MinLMCreateXXX call.
79788 : X - new starting point.
79789 :
79790 : -- ALGLIB --
79791 : Copyright 30.07.2010 by Bochkanov Sergey
79792 : *************************************************************************/
79793 0 : void minlmrestartfrom(minlmstate* state,
79794 : /* Real */ ae_vector* x,
79795 : ae_state *_state)
79796 : {
79797 :
79798 :
79799 0 : ae_assert(x->cnt>=state->n, "MinLMRestartFrom: Length(X)<N!", _state);
79800 0 : ae_assert(isfinitevector(x, state->n, _state), "MinLMRestartFrom: X contains infinite or NaN values!", _state);
79801 0 : ae_v_move(&state->xbase.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,state->n-1));
79802 0 : ae_vector_set_length(&state->rstate.ia, 4+1, _state);
79803 0 : ae_vector_set_length(&state->rstate.ba, 0+1, _state);
79804 0 : ae_vector_set_length(&state->rstate.ra, 3+1, _state);
79805 0 : state->rstate.stage = -1;
79806 0 : minlm_clearrequestfields(state, _state);
79807 0 : }
79808 :
79809 :
79810 : /*************************************************************************
79811 : This subroutine submits request for termination of running optimizer. It
79812 : should be called from user-supplied callback when user decides that it is
79813 : time to "smoothly" terminate optimization process. As result, optimizer
79814 : stops at point which was "current accepted" when termination request was
79815 : submitted and returns error code 8 (successful termination).
79816 :
79817 : INPUT PARAMETERS:
79818 : State - optimizer structure
79819 :
79820 : NOTE: after request for termination optimizer may perform several
79821 : additional calls to user-supplied callbacks. It does NOT guarantee
79822 : to stop immediately - it just guarantees that these additional calls
79823 : will be discarded later.
79824 :
79825 : NOTE: calling this function on optimizer which is NOT running will have no
79826 : effect.
79827 :
79828 : NOTE: multiple calls to this function are possible. First call is counted,
79829 : subsequent calls are silently ignored.
79830 :
79831 : -- ALGLIB --
79832 : Copyright 08.10.2014 by Bochkanov Sergey
79833 : *************************************************************************/
79834 0 : void minlmrequesttermination(minlmstate* state, ae_state *_state)
79835 : {
79836 :
79837 :
79838 0 : state->userterminationneeded = ae_true;
79839 0 : }
79840 :
79841 :
79842 : /*************************************************************************
79843 : This is obsolete function.
79844 :
79845 : Since ALGLIB 3.3 it is equivalent to MinLMCreateVJ().
79846 :
79847 : -- ALGLIB --
79848 : Copyright 30.03.2009 by Bochkanov Sergey
79849 : *************************************************************************/
79850 0 : void minlmcreatevgj(ae_int_t n,
79851 : ae_int_t m,
79852 : /* Real */ ae_vector* x,
79853 : minlmstate* state,
79854 : ae_state *_state)
79855 : {
79856 :
79857 0 : _minlmstate_clear(state);
79858 :
79859 0 : minlmcreatevj(n, m, x, state, _state);
79860 0 : }
79861 :
79862 :
79863 : /*************************************************************************
79864 : This is obsolete function.
79865 :
79866 : Since ALGLIB 3.3 it is equivalent to MinLMCreateFJ().
79867 :
79868 : -- ALGLIB --
79869 : Copyright 30.03.2009 by Bochkanov Sergey
79870 : *************************************************************************/
79871 0 : void minlmcreatefgj(ae_int_t n,
79872 : ae_int_t m,
79873 : /* Real */ ae_vector* x,
79874 : minlmstate* state,
79875 : ae_state *_state)
79876 : {
79877 :
79878 0 : _minlmstate_clear(state);
79879 :
79880 0 : minlmcreatefj(n, m, x, state, _state);
79881 0 : }
79882 :
79883 :
79884 : /*************************************************************************
79885 : This function is considered obsolete since ALGLIB 3.1.0 and is present for
79886 : backward compatibility only. We recommend to use MinLMCreateVJ, which
79887 : provides similar, but more consistent and feature-rich interface.
79888 :
79889 : -- ALGLIB --
79890 : Copyright 30.03.2009 by Bochkanov Sergey
79891 : *************************************************************************/
79892 0 : void minlmcreatefj(ae_int_t n,
79893 : ae_int_t m,
79894 : /* Real */ ae_vector* x,
79895 : minlmstate* state,
79896 : ae_state *_state)
79897 : {
79898 :
79899 0 : _minlmstate_clear(state);
79900 :
79901 0 : ae_assert(n>=1, "MinLMCreateFJ: N<1!", _state);
79902 0 : ae_assert(m>=1, "MinLMCreateFJ: M<1!", _state);
79903 0 : ae_assert(x->cnt>=n, "MinLMCreateFJ: Length(X)<N!", _state);
79904 0 : ae_assert(isfinitevector(x, n, _state), "MinLMCreateFJ: X contains infinite or NaN values!", _state);
79905 :
79906 : /*
79907 : * initialize
79908 : */
79909 0 : state->teststep = (double)(0);
79910 0 : state->n = n;
79911 0 : state->m = m;
79912 0 : state->algomode = 1;
79913 0 : state->hasf = ae_true;
79914 0 : state->hasfi = ae_false;
79915 0 : state->hasg = ae_false;
79916 :
79917 : /*
79918 : * init 2
79919 : */
79920 0 : minlm_lmprepare(n, m, ae_true, state, _state);
79921 0 : minlmsetacctype(state, 0, _state);
79922 0 : minlmsetcond(state, (double)(0), 0, _state);
79923 0 : minlmsetxrep(state, ae_false, _state);
79924 0 : minlmsetstpmax(state, (double)(0), _state);
79925 0 : minlmrestartfrom(state, x, _state);
79926 0 : }
79927 :
79928 :
79929 : /*************************************************************************
79930 : Prepare internal structures (except for RComm).
79931 :
79932 : Note: M must be zero for FGH mode, non-zero for V/VJ/FJ/FGJ mode.
79933 : *************************************************************************/
79934 0 : static void minlm_lmprepare(ae_int_t n,
79935 : ae_int_t m,
79936 : ae_bool havegrad,
79937 : minlmstate* state,
79938 : ae_state *_state)
79939 : {
79940 : ae_int_t i;
79941 :
79942 :
79943 0 : smoothnessmonitorinit(&state->smonitor, &state->s, 0, 0, ae_false, _state);
79944 0 : if( n<=0||m<0 )
79945 : {
79946 0 : return;
79947 : }
79948 0 : if( havegrad )
79949 : {
79950 0 : ae_vector_set_length(&state->g, n, _state);
79951 : }
79952 0 : if( m!=0 )
79953 : {
79954 0 : ae_matrix_set_length(&state->j, m, n, _state);
79955 0 : ae_vector_set_length(&state->fi, m, _state);
79956 0 : ae_vector_set_length(&state->fibase, m, _state);
79957 0 : ae_vector_set_length(&state->deltaf, m, _state);
79958 0 : ae_vector_set_length(&state->fm1, m, _state);
79959 0 : ae_vector_set_length(&state->fp1, m, _state);
79960 0 : ae_vector_set_length(&state->fc1, m, _state);
79961 0 : ae_vector_set_length(&state->gm1, m, _state);
79962 0 : ae_vector_set_length(&state->gp1, m, _state);
79963 0 : ae_vector_set_length(&state->gc1, m, _state);
79964 : }
79965 : else
79966 : {
79967 0 : ae_matrix_set_length(&state->h, n, n, _state);
79968 : }
79969 0 : ae_vector_set_length(&state->x, n, _state);
79970 0 : ae_vector_set_length(&state->deltax, n, _state);
79971 0 : ae_matrix_set_length(&state->quadraticmodel, n, n, _state);
79972 0 : ae_vector_set_length(&state->xbase, n, _state);
79973 0 : ae_vector_set_length(&state->gbase, n, _state);
79974 0 : ae_vector_set_length(&state->xdir, n, _state);
79975 0 : ae_vector_set_length(&state->tmp0, n, _state);
79976 :
79977 : /*
79978 : * prepare internal L-BFGS
79979 : */
79980 0 : for(i=0; i<=n-1; i++)
79981 : {
79982 0 : state->x.ptr.p_double[i] = (double)(0);
79983 : }
79984 0 : minlbfgscreate(n, ae_minint(minlm_additers, n, _state), &state->x, &state->internalstate, _state);
79985 0 : minlbfgssetcond(&state->internalstate, 0.0, 0.0, 0.0, ae_minint(minlm_additers, n, _state), _state);
79986 :
79987 : /*
79988 : * Prepare internal QP solver
79989 : */
79990 0 : minqpcreate(n, &state->qpstate, _state);
79991 0 : minqpsetalgoquickqp(&state->qpstate, 0.0, 0.0, coalesce(0.01*state->epsx, 1.0E-12, _state), 10, ae_true, _state);
79992 :
79993 : /*
79994 : * Prepare boundary constraints
79995 : */
79996 0 : ae_vector_set_length(&state->bndl, n, _state);
79997 0 : ae_vector_set_length(&state->bndu, n, _state);
79998 0 : ae_vector_set_length(&state->havebndl, n, _state);
79999 0 : ae_vector_set_length(&state->havebndu, n, _state);
80000 0 : for(i=0; i<=n-1; i++)
80001 : {
80002 0 : state->bndl.ptr.p_double[i] = _state->v_neginf;
80003 0 : state->havebndl.ptr.p_bool[i] = ae_false;
80004 0 : state->bndu.ptr.p_double[i] = _state->v_posinf;
80005 0 : state->havebndu.ptr.p_bool[i] = ae_false;
80006 : }
80007 :
80008 : /*
80009 : * Prepare scaling matrix
80010 : */
80011 0 : ae_vector_set_length(&state->s, n, _state);
80012 0 : ae_vector_set_length(&state->lastscaleused, n, _state);
80013 0 : for(i=0; i<=n-1; i++)
80014 : {
80015 0 : state->s.ptr.p_double[i] = 1.0;
80016 0 : state->lastscaleused.ptr.p_double[i] = 1.0;
80017 : }
80018 :
80019 : /*
80020 : * Prepare linear constraints
80021 : */
80022 0 : state->nec = 0;
80023 0 : state->nic = 0;
80024 : }
80025 :
80026 :
80027 : /*************************************************************************
80028 : Clears request fileds (to be sure that we don't forgot to clear something)
80029 : *************************************************************************/
80030 0 : static void minlm_clearrequestfields(minlmstate* state, ae_state *_state)
80031 : {
80032 :
80033 :
80034 0 : state->needf = ae_false;
80035 0 : state->needfg = ae_false;
80036 0 : state->needfgh = ae_false;
80037 0 : state->needfij = ae_false;
80038 0 : state->needfi = ae_false;
80039 0 : state->xupdated = ae_false;
80040 0 : }
80041 :
80042 :
80043 : /*************************************************************************
80044 : Increases lambda, returns False when there is a danger of overflow
80045 : *************************************************************************/
80046 0 : static ae_bool minlm_increaselambda(double* lambdav,
80047 : double* nu,
80048 : ae_state *_state)
80049 : {
80050 : double lnlambda;
80051 : double lnnu;
80052 : double lnlambdaup;
80053 : double lnmax;
80054 : ae_bool result;
80055 :
80056 :
80057 0 : result = ae_false;
80058 0 : lnlambda = ae_log(*lambdav, _state);
80059 0 : lnlambdaup = ae_log(minlm_lambdaup, _state);
80060 0 : lnnu = ae_log(*nu, _state);
80061 0 : lnmax = ae_log(ae_maxrealnumber, _state);
80062 0 : if( ae_fp_greater(lnlambda+lnlambdaup+lnnu,0.25*lnmax) )
80063 : {
80064 0 : return result;
80065 : }
80066 0 : if( ae_fp_greater(lnnu+ae_log((double)(2), _state),lnmax) )
80067 : {
80068 0 : return result;
80069 : }
80070 0 : *lambdav = *lambdav*minlm_lambdaup*(*nu);
80071 0 : *nu = *nu*2;
80072 0 : result = ae_true;
80073 0 : return result;
80074 : }
80075 :
80076 :
80077 : /*************************************************************************
80078 : Decreases lambda, but leaves it unchanged when there is danger of underflow.
80079 : *************************************************************************/
80080 0 : static void minlm_decreaselambda(double* lambdav,
80081 : double* nu,
80082 : ae_state *_state)
80083 : {
80084 :
80085 :
80086 0 : *nu = (double)(1);
80087 0 : if( ae_fp_less(ae_log(*lambdav, _state)+ae_log(minlm_lambdadown, _state),ae_log(ae_minrealnumber, _state)) )
80088 : {
80089 0 : *lambdav = ae_minrealnumber;
80090 : }
80091 : else
80092 : {
80093 0 : *lambdav = *lambdav*minlm_lambdadown;
80094 : }
80095 0 : }
80096 :
80097 :
80098 : /*************************************************************************
80099 : This function compares actual decrease vs predicted decrease and updates
80100 : LambdaV/Nu accordingly.
80101 :
80102 : INPUT PARAMETERS:
80103 : QuadraticModel - array[N,N], full Hessian matrix of quadratic
80104 : model at deltaX=0
80105 : GBase - array[N], gradient at deltaX=0
80106 : FBase - F(deltaX=0)
80107 : N - size
80108 : DeltaX - step vector
80109 : FNew - new function value
80110 : LambdaV - lambda-value, updated on exit
80111 : Nu - Nu-multiplier, updated on exit
80112 :
80113 : On exit it returns:
80114 : * Result=0 - if we have to continue iterations
80115 : * Result<>0 - if termination with completion code Result is requested
80116 :
80117 : -- ALGLIB --
80118 : Copyright 17.02.2017 by Bochkanov Sergey
80119 : *************************************************************************/
80120 0 : static ae_int_t minlm_checkdecrease(/* Real */ ae_matrix* quadraticmodel,
80121 : /* Real */ ae_vector* gbase,
80122 : double fbase,
80123 : ae_int_t n,
80124 : /* Real */ ae_vector* deltax,
80125 : double fnew,
80126 : double* lambdav,
80127 : double* nu,
80128 : ae_state *_state)
80129 : {
80130 : ae_int_t i;
80131 : double v;
80132 : double t;
80133 : double predicteddecrease;
80134 : double actualdecrease;
80135 : ae_int_t result;
80136 :
80137 :
80138 0 : result = 0;
80139 0 : t = (double)(0);
80140 0 : for(i=0; i<=n-1; i++)
80141 : {
80142 0 : v = ae_v_dotproduct(&quadraticmodel->ptr.pp_double[i][0], 1, &deltax->ptr.p_double[0], 1, ae_v_len(0,n-1));
80143 0 : t = t+deltax->ptr.p_double[i]*gbase->ptr.p_double[i]+0.5*deltax->ptr.p_double[i]*v;
80144 : }
80145 0 : predicteddecrease = -t;
80146 0 : actualdecrease = -(fnew-fbase);
80147 0 : if( ae_fp_less_eq(predicteddecrease,(double)(0)) )
80148 : {
80149 0 : result = 7;
80150 0 : return result;
80151 : }
80152 0 : v = actualdecrease/predicteddecrease;
80153 0 : if( ae_fp_less(v,0.1) )
80154 : {
80155 0 : if( !minlm_increaselambda(lambdav, nu, _state) )
80156 : {
80157 :
80158 : /*
80159 : * Lambda is too large, we have to break iterations.
80160 : */
80161 0 : result = 7;
80162 0 : return result;
80163 : }
80164 : }
80165 0 : if( ae_fp_greater(v,0.5) )
80166 : {
80167 0 : minlm_decreaselambda(lambdav, nu, _state);
80168 : }
80169 0 : return result;
80170 : }
80171 :
80172 :
80173 : /*************************************************************************
80174 : This function initializes step finder object with problem statement;
80175 : model parameters specified during this call should not (and can not)
80176 : change during object lifetime (although it is possible to re-initialize
80177 : object with different settings).
80178 :
80179 : This function reuses internally allocated objects as much as possible.
80180 :
80181 : In addition to initializing step finder, this function enforces feasibility
80182 : in initial point X passed to this function. It is important that LM iteration
80183 : starts from feasible point and performs feasible steps;
80184 :
80185 : RETURN VALUE:
80186 : True for successful initialization
80187 : False for inconsistent constraints; you should not use step finder if
80188 : it returned False.
80189 : *************************************************************************/
80190 0 : static ae_bool minlm_minlmstepfinderinit(minlmstepfinder* state,
80191 : ae_int_t n,
80192 : ae_int_t m,
80193 : ae_int_t maxmodelage,
80194 : ae_bool hasfi,
80195 : /* Real */ ae_vector* xbase,
80196 : /* Real */ ae_vector* bndl,
80197 : /* Real */ ae_vector* bndu,
80198 : /* Real */ ae_matrix* cleic,
80199 : ae_int_t nec,
80200 : ae_int_t nic,
80201 : /* Real */ ae_vector* s,
80202 : double stpmax,
80203 : double epsx,
80204 : ae_state *_state)
80205 : {
80206 : ae_int_t i;
80207 : ae_bool result;
80208 :
80209 :
80210 0 : state->n = n;
80211 0 : state->m = m;
80212 0 : state->maxmodelage = maxmodelage;
80213 0 : state->hasfi = hasfi;
80214 0 : state->stpmax = stpmax;
80215 0 : state->epsx = epsx;
80216 :
80217 : /*
80218 : * Allocate temporaries, create QP solver, select QP algorithm
80219 : */
80220 0 : rvectorsetlengthatleast(&state->bndl, n, _state);
80221 0 : rvectorsetlengthatleast(&state->bndu, n, _state);
80222 0 : rvectorsetlengthatleast(&state->s, n, _state);
80223 0 : bvectorsetlengthatleast(&state->havebndl, n, _state);
80224 0 : bvectorsetlengthatleast(&state->havebndu, n, _state);
80225 0 : rvectorsetlengthatleast(&state->x, n, _state);
80226 0 : rvectorsetlengthatleast(&state->xbase, n, _state);
80227 0 : rvectorsetlengthatleast(&state->tmp0, n, _state);
80228 0 : rvectorsetlengthatleast(&state->modeldiag, n, _state);
80229 0 : ivectorsetlengthatleast(&state->tmpct, nec+nic, _state);
80230 0 : rvectorsetlengthatleast(&state->xdir, n, _state);
80231 0 : if( hasfi )
80232 : {
80233 0 : rvectorsetlengthatleast(&state->fi, m, _state);
80234 0 : rvectorsetlengthatleast(&state->fibase, m, _state);
80235 : }
80236 0 : for(i=0; i<=n-1; i++)
80237 : {
80238 0 : ae_assert(ae_isfinite(bndl->ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "MinLM: integrity check failed", _state);
80239 0 : ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "MinLM: integrity check failed", _state);
80240 0 : state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i];
80241 0 : state->havebndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state);
80242 0 : state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i];
80243 0 : state->havebndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state);
80244 0 : state->s.ptr.p_double[i] = s->ptr.p_double[i];
80245 : }
80246 0 : for(i=0; i<=nec-1; i++)
80247 : {
80248 0 : state->tmpct.ptr.p_int[i] = 0;
80249 : }
80250 0 : for(i=0; i<=nic-1; i++)
80251 : {
80252 0 : state->tmpct.ptr.p_int[nec+i] = -1;
80253 : }
80254 0 : minqpcreate(n, &state->qpstate, _state);
80255 0 : if( nec+nic==0 )
80256 : {
80257 0 : minqpsetalgoquickqp(&state->qpstate, 0.0, 0.0, coalesce(0.01*epsx, 1.0E-12, _state), 10, ae_true, _state);
80258 : }
80259 : else
80260 : {
80261 0 : minqpsetalgodenseaul(&state->qpstate, coalesce(0.01*epsx, 1.0E-12, _state), (double)(100), 10, _state);
80262 : }
80263 0 : minqpsetbc(&state->qpstate, bndl, bndu, _state);
80264 0 : minqpsetlc(&state->qpstate, cleic, &state->tmpct, nec+nic, _state);
80265 0 : minqpsetscale(&state->qpstate, s, _state);
80266 :
80267 : /*
80268 : * Check feasibility of constraints:
80269 : * * check/enforce box constraints (straightforward)
80270 : * * prepare QP subproblem which return us a feasible point
80271 : */
80272 0 : result = ae_true;
80273 0 : for(i=0; i<=n-1; i++)
80274 : {
80275 0 : if( (state->havebndl.ptr.p_bool[i]&&state->havebndu.ptr.p_bool[i])&&ae_fp_greater(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
80276 : {
80277 0 : result = ae_false;
80278 0 : return result;
80279 : }
80280 0 : if( state->havebndl.ptr.p_bool[i]&&ae_fp_less(xbase->ptr.p_double[i],state->bndl.ptr.p_double[i]) )
80281 : {
80282 0 : xbase->ptr.p_double[i] = state->bndl.ptr.p_double[i];
80283 : }
80284 0 : if( state->havebndu.ptr.p_bool[i]&&ae_fp_greater(xbase->ptr.p_double[i],state->bndu.ptr.p_double[i]) )
80285 : {
80286 0 : xbase->ptr.p_double[i] = state->bndu.ptr.p_double[i];
80287 : }
80288 : }
80289 0 : if( nec+nic>0 )
80290 : {
80291 :
80292 : /*
80293 : * Well, we have linear constraints... let's use heavy machinery.
80294 : *
80295 : * We will modify QP solver state below, but everything will be
80296 : * restored in MinLMStepFinderStart().
80297 : */
80298 0 : sparsecreate(n, n, n, &state->tmpsp, _state);
80299 0 : for(i=0; i<=n-1; i++)
80300 : {
80301 0 : sparseset(&state->tmpsp, i, i, 0.5, _state);
80302 0 : state->tmp0.ptr.p_double[i] = (double)(0);
80303 : }
80304 0 : minqpsetstartingpointfast(&state->qpstate, xbase, _state);
80305 0 : minqpsetoriginfast(&state->qpstate, xbase, _state);
80306 0 : minqpsetlineartermfast(&state->qpstate, &state->tmp0, _state);
80307 0 : minqpsetquadratictermsparse(&state->qpstate, &state->tmpsp, ae_true, _state);
80308 0 : minqpoptimize(&state->qpstate, _state);
80309 0 : minqpresultsbuf(&state->qpstate, xbase, &state->qprep, _state);
80310 : }
80311 0 : return result;
80312 : }
80313 :
80314 :
80315 : /*************************************************************************
80316 : This function prepares LM step search session.
80317 : *************************************************************************/
80318 0 : static void minlm_minlmstepfinderstart(minlmstepfinder* state,
80319 : /* Real */ ae_matrix* quadraticmodel,
80320 : /* Real */ ae_vector* gbase,
80321 : double fbase,
80322 : /* Real */ ae_vector* xbase,
80323 : /* Real */ ae_vector* fibase,
80324 : ae_int_t modelage,
80325 : ae_state *_state)
80326 : {
80327 : ae_int_t i;
80328 : ae_int_t n;
80329 :
80330 :
80331 0 : n = state->n;
80332 0 : ae_vector_set_length(&state->rstate.ia, 2+1, _state);
80333 0 : ae_vector_set_length(&state->rstate.ba, 0+1, _state);
80334 0 : ae_vector_set_length(&state->rstate.ra, 0+1, _state);
80335 0 : state->rstate.stage = -1;
80336 0 : state->modelage = modelage;
80337 0 : state->fbase = fbase;
80338 0 : if( state->hasfi )
80339 : {
80340 0 : for(i=0; i<=state->m-1; i++)
80341 : {
80342 0 : state->fibase.ptr.p_double[i] = fibase->ptr.p_double[i];
80343 : }
80344 : }
80345 0 : for(i=0; i<=n-1; i++)
80346 : {
80347 0 : state->xbase.ptr.p_double[i] = xbase->ptr.p_double[i];
80348 0 : state->modeldiag.ptr.p_double[i] = quadraticmodel->ptr.pp_double[i][i];
80349 : }
80350 0 : minqpsetstartingpointfast(&state->qpstate, xbase, _state);
80351 0 : minqpsetoriginfast(&state->qpstate, xbase, _state);
80352 0 : minqpsetlineartermfast(&state->qpstate, gbase, _state);
80353 0 : minqpsetquadratictermfast(&state->qpstate, quadraticmodel, ae_true, 0.0, _state);
80354 0 : }
80355 :
80356 :
80357 : /*************************************************************************
80358 : This function runs LM step search session.
80359 : //
80360 : // Find value of Levenberg-Marquardt damping parameter which:
80361 : // * leads to positive definite damped model
80362 : // * within bounds specified by StpMax
80363 : // * generates step which decreases function value
80364 : //
80365 : // After this block IFlag is set to:
80366 : // * -8, if infinities/NANs were detected in function values/gradient
80367 : // * -3, if constraints are infeasible
80368 : // * -2, if model update is needed (either Lambda growth is too large
80369 : // or step is too short, but we can't rely on model and stop iterations)
80370 : // * -1, if model is fresh, Lambda have grown too large, termination is needed
80371 : // * 0, if everything is OK, continue iterations
80372 : // * >0 - successful completion (step size is small enough)
80373 : //
80374 : // State.Nu can have any value on enter, but after exit it is set to 1.0
80375 : //
80376 : *************************************************************************/
80377 0 : static ae_bool minlm_minlmstepfinderiteration(minlmstepfinder* state,
80378 : double* lambdav,
80379 : double* nu,
80380 : /* Real */ ae_vector* xnew,
80381 : /* Real */ ae_vector* deltax,
80382 : ae_bool* deltaxready,
80383 : /* Real */ ae_vector* deltaf,
80384 : ae_bool* deltafready,
80385 : ae_int_t* iflag,
80386 : double* fnew,
80387 : ae_int_t* ncholesky,
80388 : ae_state *_state)
80389 : {
80390 : ae_int_t i;
80391 : ae_bool bflag;
80392 : double v;
80393 : ae_int_t n;
80394 : ae_int_t m;
80395 : ae_bool result;
80396 :
80397 :
80398 :
80399 : /*
80400 : * Reverse communication preparations
80401 : * I know it looks ugly, but it works the same way
80402 : * anywhere from C++ to Python.
80403 : *
80404 : * This code initializes locals by:
80405 : * * random values determined during code
80406 : * generation - on first subroutine call
80407 : * * values from previous call - on subsequent calls
80408 : */
80409 0 : if( state->rstate.stage>=0 )
80410 : {
80411 0 : i = state->rstate.ia.ptr.p_int[0];
80412 0 : n = state->rstate.ia.ptr.p_int[1];
80413 0 : m = state->rstate.ia.ptr.p_int[2];
80414 0 : bflag = state->rstate.ba.ptr.p_bool[0];
80415 0 : v = state->rstate.ra.ptr.p_double[0];
80416 : }
80417 : else
80418 : {
80419 0 : i = -838;
80420 0 : n = 939;
80421 0 : m = -526;
80422 0 : bflag = ae_true;
80423 0 : v = -541;
80424 : }
80425 0 : if( state->rstate.stage==0 )
80426 : {
80427 0 : goto lbl_0;
80428 : }
80429 0 : if( state->rstate.stage==1 )
80430 : {
80431 0 : goto lbl_1;
80432 : }
80433 :
80434 : /*
80435 : * Routine body
80436 : */
80437 0 : *iflag = -99;
80438 0 : n = state->n;
80439 0 : m = state->m;
80440 0 : lbl_2:
80441 : if( ae_false )
80442 : {
80443 : goto lbl_3;
80444 : }
80445 0 : *deltaxready = ae_false;
80446 0 : *deltafready = ae_false;
80447 :
80448 : /*
80449 : * Do we need model update?
80450 : */
80451 0 : if( state->modelage>0&&ae_fp_greater_eq(*nu,minlm_suspiciousnu) )
80452 : {
80453 0 : *iflag = -2;
80454 0 : goto lbl_3;
80455 : }
80456 :
80457 : /*
80458 : * Setup quadratic solver and solve quadratic programming problem.
80459 : * After problem is solved we'll try to bound step by StpMax
80460 : * (Lambda will be increased if step size is too large).
80461 : *
80462 : * We use BFlag variable to indicate that we have to increase Lambda.
80463 : * If it is False, we will try to increase Lambda and move to new iteration.
80464 : */
80465 0 : bflag = ae_true;
80466 0 : for(i=0; i<=n-1; i++)
80467 : {
80468 0 : state->tmp0.ptr.p_double[i] = state->modeldiag.ptr.p_double[i]+*lambdav/ae_sqr(state->s.ptr.p_double[i], _state);
80469 : }
80470 0 : minqprewritediagonal(&state->qpstate, &state->tmp0, _state);
80471 0 : minqpoptimize(&state->qpstate, _state);
80472 0 : minqpresultsbuf(&state->qpstate, xnew, &state->qprep, _state);
80473 0 : *ncholesky = *ncholesky+state->qprep.ncholesky;
80474 0 : if( state->qprep.terminationtype==-3 )
80475 : {
80476 :
80477 : /*
80478 : * Infeasible constraints
80479 : */
80480 0 : *iflag = -3;
80481 0 : goto lbl_3;
80482 : }
80483 0 : if( state->qprep.terminationtype==-4||state->qprep.terminationtype==-5 )
80484 : {
80485 :
80486 : /*
80487 : * Unconstrained direction of negative curvature was detected
80488 : */
80489 0 : if( !minlm_increaselambda(lambdav, nu, _state) )
80490 : {
80491 0 : *iflag = -1;
80492 0 : goto lbl_3;
80493 : }
80494 0 : goto lbl_2;
80495 : }
80496 0 : ae_assert(state->qprep.terminationtype>0, "MinLM: unexpected completion code from QP solver", _state);
80497 0 : ae_v_move(&state->xdir.ptr.p_double[0], 1, &xnew->ptr.p_double[0], 1, ae_v_len(0,n-1));
80498 0 : ae_v_sub(&state->xdir.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
80499 0 : v = 0.0;
80500 0 : for(i=0; i<=n-1; i++)
80501 : {
80502 0 : v = v+ae_sqr(state->xdir.ptr.p_double[i]/state->s.ptr.p_double[i], _state);
80503 : }
80504 0 : if( ae_isfinite(v, _state) )
80505 : {
80506 0 : v = ae_sqrt(v, _state);
80507 0 : if( ae_fp_greater(state->stpmax,(double)(0))&&ae_fp_greater(v,state->stpmax) )
80508 : {
80509 0 : bflag = ae_false;
80510 : }
80511 : }
80512 : else
80513 : {
80514 0 : bflag = ae_false;
80515 : }
80516 0 : if( !bflag )
80517 : {
80518 :
80519 : /*
80520 : * Solution failed:
80521 : * try to increase lambda to make matrix positive definite and continue.
80522 : */
80523 0 : if( !minlm_increaselambda(lambdav, nu, _state) )
80524 : {
80525 0 : *iflag = -1;
80526 0 : goto lbl_3;
80527 : }
80528 0 : goto lbl_2;
80529 : }
80530 :
80531 : /*
80532 : * Step in State.XDir and it is bounded by StpMax.
80533 : *
80534 : * We should check stopping conditions on step size here.
80535 : * DeltaX, which is used for secant updates, is initialized here.
80536 : *
80537 : * This code is a bit tricky because sometimes XDir<>0, but
80538 : * it is so small that XDir+XBase==XBase (in finite precision
80539 : * arithmetics). So we set DeltaX to XBase, then
80540 : * add XDir, and then subtract XBase to get exact value of
80541 : * DeltaX.
80542 : *
80543 : * Step length is estimated using DeltaX.
80544 : *
80545 : * NOTE: stopping conditions are tested
80546 : * for fresh models only (ModelAge=0)
80547 : */
80548 0 : ae_v_move(&deltax->ptr.p_double[0], 1, &xnew->ptr.p_double[0], 1, ae_v_len(0,n-1));
80549 0 : ae_v_sub(&deltax->ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
80550 0 : *deltaxready = ae_true;
80551 0 : v = 0.0;
80552 0 : for(i=0; i<=n-1; i++)
80553 : {
80554 0 : v = v+ae_sqr(deltax->ptr.p_double[i]/state->s.ptr.p_double[i], _state);
80555 : }
80556 0 : v = ae_sqrt(v, _state);
80557 0 : if( ae_fp_less_eq(v,state->epsx) )
80558 : {
80559 0 : if( state->modelage==0 )
80560 : {
80561 :
80562 : /*
80563 : * Step is too short, model is fresh and we can rely on it.
80564 : * Terminating.
80565 : */
80566 0 : *iflag = 2;
80567 0 : goto lbl_3;
80568 : }
80569 : else
80570 : {
80571 :
80572 : /*
80573 : * Step is suspiciously short, but model is not fresh
80574 : * and we can't rely on it.
80575 : */
80576 0 : *iflag = -2;
80577 0 : goto lbl_3;
80578 : }
80579 : }
80580 :
80581 : /*
80582 : * Let's evaluate new step:
80583 : * a) if we have Fi vector, we evaluate it using rcomm, and
80584 : * then we manually calculate State.F as sum of squares of Fi[]
80585 : * b) if we have F value, we just evaluate it through rcomm interface
80586 : *
80587 : * We prefer (a) because we may need Fi vector for additional
80588 : * iterations
80589 : */
80590 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &xnew->ptr.p_double[0], 1, ae_v_len(0,n-1));
80591 0 : state->needf = ae_false;
80592 0 : state->needfi = ae_false;
80593 0 : if( !state->hasfi )
80594 : {
80595 0 : goto lbl_4;
80596 : }
80597 0 : state->needfi = ae_true;
80598 0 : state->rstate.stage = 0;
80599 0 : goto lbl_rcomm;
80600 0 : lbl_0:
80601 0 : state->needfi = ae_false;
80602 0 : v = ae_v_dotproduct(&state->fi.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
80603 0 : *fnew = v;
80604 0 : ae_v_move(&deltaf->ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
80605 0 : ae_v_sub(&deltaf->ptr.p_double[0], 1, &state->fibase.ptr.p_double[0], 1, ae_v_len(0,m-1));
80606 0 : *deltafready = ae_true;
80607 0 : goto lbl_5;
80608 0 : lbl_4:
80609 0 : state->needf = ae_true;
80610 0 : state->rstate.stage = 1;
80611 0 : goto lbl_rcomm;
80612 0 : lbl_1:
80613 0 : state->needf = ae_false;
80614 0 : *fnew = state->f;
80615 0 : lbl_5:
80616 0 : if( !ae_isfinite(*fnew, _state) )
80617 : {
80618 :
80619 : /*
80620 : * Integrity check failed, break!
80621 : */
80622 0 : *iflag = -8;
80623 0 : goto lbl_3;
80624 : }
80625 0 : if( ae_fp_greater_eq(*fnew,state->fbase) )
80626 : {
80627 :
80628 : /*
80629 : * Increase lambda and continue
80630 : */
80631 0 : if( !minlm_increaselambda(lambdav, nu, _state) )
80632 : {
80633 0 : *iflag = -1;
80634 0 : goto lbl_3;
80635 : }
80636 0 : goto lbl_2;
80637 : }
80638 :
80639 : /*
80640 : * We've found our step!
80641 : */
80642 0 : *iflag = 0;
80643 0 : goto lbl_3;
80644 : goto lbl_2;
80645 0 : lbl_3:
80646 0 : *nu = (double)(1);
80647 0 : ae_assert(((*iflag>=-3&&*iflag<=0)||*iflag==-8)||*iflag>0, "MinLM: internal integrity check failed!", _state);
80648 0 : result = ae_false;
80649 0 : return result;
80650 :
80651 : /*
80652 : * Saving state
80653 : */
80654 0 : lbl_rcomm:
80655 0 : result = ae_true;
80656 0 : state->rstate.ia.ptr.p_int[0] = i;
80657 0 : state->rstate.ia.ptr.p_int[1] = n;
80658 0 : state->rstate.ia.ptr.p_int[2] = m;
80659 0 : state->rstate.ba.ptr.p_bool[0] = bflag;
80660 0 : state->rstate.ra.ptr.p_double[0] = v;
80661 0 : return result;
80662 : }
80663 :
80664 :
80665 0 : void _minlmstepfinder_init(void* _p, ae_state *_state, ae_bool make_automatic)
80666 : {
80667 0 : minlmstepfinder *p = (minlmstepfinder*)_p;
80668 0 : ae_touch_ptr((void*)p);
80669 0 : ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
80670 0 : ae_vector_init(&p->fi, 0, DT_REAL, _state, make_automatic);
80671 0 : ae_vector_init(&p->modeldiag, 0, DT_REAL, _state, make_automatic);
80672 0 : ae_vector_init(&p->xbase, 0, DT_REAL, _state, make_automatic);
80673 0 : ae_vector_init(&p->fibase, 0, DT_REAL, _state, make_automatic);
80674 0 : ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic);
80675 0 : ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic);
80676 0 : ae_vector_init(&p->havebndl, 0, DT_BOOL, _state, make_automatic);
80677 0 : ae_vector_init(&p->havebndu, 0, DT_BOOL, _state, make_automatic);
80678 0 : ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic);
80679 0 : _rcommstate_init(&p->rstate, _state, make_automatic);
80680 0 : ae_vector_init(&p->xdir, 0, DT_REAL, _state, make_automatic);
80681 0 : ae_vector_init(&p->choleskybuf, 0, DT_REAL, _state, make_automatic);
80682 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
80683 0 : ae_vector_init(&p->tmpct, 0, DT_INT, _state, make_automatic);
80684 0 : _minqpstate_init(&p->qpstate, _state, make_automatic);
80685 0 : _minqpreport_init(&p->qprep, _state, make_automatic);
80686 0 : _sparsematrix_init(&p->tmpsp, _state, make_automatic);
80687 0 : }
80688 :
80689 :
80690 0 : void _minlmstepfinder_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
80691 : {
80692 0 : minlmstepfinder *dst = (minlmstepfinder*)_dst;
80693 0 : minlmstepfinder *src = (minlmstepfinder*)_src;
80694 0 : dst->n = src->n;
80695 0 : dst->m = src->m;
80696 0 : dst->stpmax = src->stpmax;
80697 0 : dst->modelage = src->modelage;
80698 0 : dst->maxmodelage = src->maxmodelage;
80699 0 : dst->hasfi = src->hasfi;
80700 0 : dst->epsx = src->epsx;
80701 0 : ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
80702 0 : dst->f = src->f;
80703 0 : ae_vector_init_copy(&dst->fi, &src->fi, _state, make_automatic);
80704 0 : dst->needf = src->needf;
80705 0 : dst->needfi = src->needfi;
80706 0 : dst->fbase = src->fbase;
80707 0 : ae_vector_init_copy(&dst->modeldiag, &src->modeldiag, _state, make_automatic);
80708 0 : ae_vector_init_copy(&dst->xbase, &src->xbase, _state, make_automatic);
80709 0 : ae_vector_init_copy(&dst->fibase, &src->fibase, _state, make_automatic);
80710 0 : ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic);
80711 0 : ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic);
80712 0 : ae_vector_init_copy(&dst->havebndl, &src->havebndl, _state, make_automatic);
80713 0 : ae_vector_init_copy(&dst->havebndu, &src->havebndu, _state, make_automatic);
80714 0 : ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic);
80715 0 : _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic);
80716 0 : ae_vector_init_copy(&dst->xdir, &src->xdir, _state, make_automatic);
80717 0 : ae_vector_init_copy(&dst->choleskybuf, &src->choleskybuf, _state, make_automatic);
80718 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
80719 0 : ae_vector_init_copy(&dst->tmpct, &src->tmpct, _state, make_automatic);
80720 0 : dst->actualdecrease = src->actualdecrease;
80721 0 : dst->predicteddecrease = src->predicteddecrease;
80722 0 : _minqpstate_init_copy(&dst->qpstate, &src->qpstate, _state, make_automatic);
80723 0 : _minqpreport_init_copy(&dst->qprep, &src->qprep, _state, make_automatic);
80724 0 : _sparsematrix_init_copy(&dst->tmpsp, &src->tmpsp, _state, make_automatic);
80725 0 : }
80726 :
80727 :
80728 0 : void _minlmstepfinder_clear(void* _p)
80729 : {
80730 0 : minlmstepfinder *p = (minlmstepfinder*)_p;
80731 0 : ae_touch_ptr((void*)p);
80732 0 : ae_vector_clear(&p->x);
80733 0 : ae_vector_clear(&p->fi);
80734 0 : ae_vector_clear(&p->modeldiag);
80735 0 : ae_vector_clear(&p->xbase);
80736 0 : ae_vector_clear(&p->fibase);
80737 0 : ae_vector_clear(&p->bndl);
80738 0 : ae_vector_clear(&p->bndu);
80739 0 : ae_vector_clear(&p->havebndl);
80740 0 : ae_vector_clear(&p->havebndu);
80741 0 : ae_vector_clear(&p->s);
80742 0 : _rcommstate_clear(&p->rstate);
80743 0 : ae_vector_clear(&p->xdir);
80744 0 : ae_vector_clear(&p->choleskybuf);
80745 0 : ae_vector_clear(&p->tmp0);
80746 0 : ae_vector_clear(&p->tmpct);
80747 0 : _minqpstate_clear(&p->qpstate);
80748 0 : _minqpreport_clear(&p->qprep);
80749 0 : _sparsematrix_clear(&p->tmpsp);
80750 0 : }
80751 :
80752 :
80753 0 : void _minlmstepfinder_destroy(void* _p)
80754 : {
80755 0 : minlmstepfinder *p = (minlmstepfinder*)_p;
80756 0 : ae_touch_ptr((void*)p);
80757 0 : ae_vector_destroy(&p->x);
80758 0 : ae_vector_destroy(&p->fi);
80759 0 : ae_vector_destroy(&p->modeldiag);
80760 0 : ae_vector_destroy(&p->xbase);
80761 0 : ae_vector_destroy(&p->fibase);
80762 0 : ae_vector_destroy(&p->bndl);
80763 0 : ae_vector_destroy(&p->bndu);
80764 0 : ae_vector_destroy(&p->havebndl);
80765 0 : ae_vector_destroy(&p->havebndu);
80766 0 : ae_vector_destroy(&p->s);
80767 0 : _rcommstate_destroy(&p->rstate);
80768 0 : ae_vector_destroy(&p->xdir);
80769 0 : ae_vector_destroy(&p->choleskybuf);
80770 0 : ae_vector_destroy(&p->tmp0);
80771 0 : ae_vector_destroy(&p->tmpct);
80772 0 : _minqpstate_destroy(&p->qpstate);
80773 0 : _minqpreport_destroy(&p->qprep);
80774 0 : _sparsematrix_destroy(&p->tmpsp);
80775 0 : }
80776 :
80777 :
80778 0 : void _minlmstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
80779 : {
80780 0 : minlmstate *p = (minlmstate*)_p;
80781 0 : ae_touch_ptr((void*)p);
80782 0 : ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
80783 0 : ae_vector_init(&p->fi, 0, DT_REAL, _state, make_automatic);
80784 0 : ae_matrix_init(&p->j, 0, 0, DT_REAL, _state, make_automatic);
80785 0 : ae_matrix_init(&p->h, 0, 0, DT_REAL, _state, make_automatic);
80786 0 : ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic);
80787 0 : ae_vector_init(&p->xbase, 0, DT_REAL, _state, make_automatic);
80788 0 : ae_vector_init(&p->fibase, 0, DT_REAL, _state, make_automatic);
80789 0 : ae_vector_init(&p->gbase, 0, DT_REAL, _state, make_automatic);
80790 0 : ae_matrix_init(&p->quadraticmodel, 0, 0, DT_REAL, _state, make_automatic);
80791 0 : ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic);
80792 0 : ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic);
80793 0 : ae_vector_init(&p->havebndl, 0, DT_BOOL, _state, make_automatic);
80794 0 : ae_vector_init(&p->havebndu, 0, DT_BOOL, _state, make_automatic);
80795 0 : ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic);
80796 0 : ae_matrix_init(&p->cleic, 0, 0, DT_REAL, _state, make_automatic);
80797 0 : ae_vector_init(&p->xnew, 0, DT_REAL, _state, make_automatic);
80798 0 : ae_vector_init(&p->xdir, 0, DT_REAL, _state, make_automatic);
80799 0 : ae_vector_init(&p->deltax, 0, DT_REAL, _state, make_automatic);
80800 0 : ae_vector_init(&p->deltaf, 0, DT_REAL, _state, make_automatic);
80801 0 : _smoothnessmonitor_init(&p->smonitor, _state, make_automatic);
80802 0 : ae_vector_init(&p->lastscaleused, 0, DT_REAL, _state, make_automatic);
80803 0 : _rcommstate_init(&p->rstate, _state, make_automatic);
80804 0 : ae_vector_init(&p->choleskybuf, 0, DT_REAL, _state, make_automatic);
80805 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
80806 0 : ae_vector_init(&p->fm1, 0, DT_REAL, _state, make_automatic);
80807 0 : ae_vector_init(&p->fp1, 0, DT_REAL, _state, make_automatic);
80808 0 : ae_vector_init(&p->fc1, 0, DT_REAL, _state, make_automatic);
80809 0 : ae_vector_init(&p->gm1, 0, DT_REAL, _state, make_automatic);
80810 0 : ae_vector_init(&p->gp1, 0, DT_REAL, _state, make_automatic);
80811 0 : ae_vector_init(&p->gc1, 0, DT_REAL, _state, make_automatic);
80812 0 : _minlbfgsstate_init(&p->internalstate, _state, make_automatic);
80813 0 : _minlbfgsreport_init(&p->internalrep, _state, make_automatic);
80814 0 : _minqpstate_init(&p->qpstate, _state, make_automatic);
80815 0 : _minqpreport_init(&p->qprep, _state, make_automatic);
80816 0 : _minlmstepfinder_init(&p->finderstate, _state, make_automatic);
80817 0 : }
80818 :
80819 :
80820 0 : void _minlmstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
80821 : {
80822 0 : minlmstate *dst = (minlmstate*)_dst;
80823 0 : minlmstate *src = (minlmstate*)_src;
80824 0 : dst->n = src->n;
80825 0 : dst->m = src->m;
80826 0 : dst->diffstep = src->diffstep;
80827 0 : dst->epsx = src->epsx;
80828 0 : dst->maxits = src->maxits;
80829 0 : dst->xrep = src->xrep;
80830 0 : dst->stpmax = src->stpmax;
80831 0 : dst->maxmodelage = src->maxmodelage;
80832 0 : dst->makeadditers = src->makeadditers;
80833 0 : ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
80834 0 : dst->f = src->f;
80835 0 : ae_vector_init_copy(&dst->fi, &src->fi, _state, make_automatic);
80836 0 : ae_matrix_init_copy(&dst->j, &src->j, _state, make_automatic);
80837 0 : ae_matrix_init_copy(&dst->h, &src->h, _state, make_automatic);
80838 0 : ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic);
80839 0 : dst->needf = src->needf;
80840 0 : dst->needfg = src->needfg;
80841 0 : dst->needfgh = src->needfgh;
80842 0 : dst->needfij = src->needfij;
80843 0 : dst->needfi = src->needfi;
80844 0 : dst->xupdated = src->xupdated;
80845 0 : dst->userterminationneeded = src->userterminationneeded;
80846 0 : dst->algomode = src->algomode;
80847 0 : dst->hasf = src->hasf;
80848 0 : dst->hasfi = src->hasfi;
80849 0 : dst->hasg = src->hasg;
80850 0 : ae_vector_init_copy(&dst->xbase, &src->xbase, _state, make_automatic);
80851 0 : dst->fbase = src->fbase;
80852 0 : ae_vector_init_copy(&dst->fibase, &src->fibase, _state, make_automatic);
80853 0 : ae_vector_init_copy(&dst->gbase, &src->gbase, _state, make_automatic);
80854 0 : ae_matrix_init_copy(&dst->quadraticmodel, &src->quadraticmodel, _state, make_automatic);
80855 0 : ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic);
80856 0 : ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic);
80857 0 : ae_vector_init_copy(&dst->havebndl, &src->havebndl, _state, make_automatic);
80858 0 : ae_vector_init_copy(&dst->havebndu, &src->havebndu, _state, make_automatic);
80859 0 : ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic);
80860 0 : ae_matrix_init_copy(&dst->cleic, &src->cleic, _state, make_automatic);
80861 0 : dst->nec = src->nec;
80862 0 : dst->nic = src->nic;
80863 0 : dst->lambdav = src->lambdav;
80864 0 : dst->nu = src->nu;
80865 0 : dst->modelage = src->modelage;
80866 0 : ae_vector_init_copy(&dst->xnew, &src->xnew, _state, make_automatic);
80867 0 : ae_vector_init_copy(&dst->xdir, &src->xdir, _state, make_automatic);
80868 0 : ae_vector_init_copy(&dst->deltax, &src->deltax, _state, make_automatic);
80869 0 : ae_vector_init_copy(&dst->deltaf, &src->deltaf, _state, make_automatic);
80870 0 : dst->deltaxready = src->deltaxready;
80871 0 : dst->deltafready = src->deltafready;
80872 0 : _smoothnessmonitor_init_copy(&dst->smonitor, &src->smonitor, _state, make_automatic);
80873 0 : dst->teststep = src->teststep;
80874 0 : ae_vector_init_copy(&dst->lastscaleused, &src->lastscaleused, _state, make_automatic);
80875 0 : dst->repiterationscount = src->repiterationscount;
80876 0 : dst->repterminationtype = src->repterminationtype;
80877 0 : dst->repnfunc = src->repnfunc;
80878 0 : dst->repnjac = src->repnjac;
80879 0 : dst->repngrad = src->repngrad;
80880 0 : dst->repnhess = src->repnhess;
80881 0 : dst->repncholesky = src->repncholesky;
80882 0 : _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic);
80883 0 : ae_vector_init_copy(&dst->choleskybuf, &src->choleskybuf, _state, make_automatic);
80884 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
80885 0 : dst->actualdecrease = src->actualdecrease;
80886 0 : dst->predicteddecrease = src->predicteddecrease;
80887 0 : dst->xm1 = src->xm1;
80888 0 : dst->xp1 = src->xp1;
80889 0 : ae_vector_init_copy(&dst->fm1, &src->fm1, _state, make_automatic);
80890 0 : ae_vector_init_copy(&dst->fp1, &src->fp1, _state, make_automatic);
80891 0 : ae_vector_init_copy(&dst->fc1, &src->fc1, _state, make_automatic);
80892 0 : ae_vector_init_copy(&dst->gm1, &src->gm1, _state, make_automatic);
80893 0 : ae_vector_init_copy(&dst->gp1, &src->gp1, _state, make_automatic);
80894 0 : ae_vector_init_copy(&dst->gc1, &src->gc1, _state, make_automatic);
80895 0 : _minlbfgsstate_init_copy(&dst->internalstate, &src->internalstate, _state, make_automatic);
80896 0 : _minlbfgsreport_init_copy(&dst->internalrep, &src->internalrep, _state, make_automatic);
80897 0 : _minqpstate_init_copy(&dst->qpstate, &src->qpstate, _state, make_automatic);
80898 0 : _minqpreport_init_copy(&dst->qprep, &src->qprep, _state, make_automatic);
80899 0 : _minlmstepfinder_init_copy(&dst->finderstate, &src->finderstate, _state, make_automatic);
80900 0 : }
80901 :
80902 :
80903 0 : void _minlmstate_clear(void* _p)
80904 : {
80905 0 : minlmstate *p = (minlmstate*)_p;
80906 0 : ae_touch_ptr((void*)p);
80907 0 : ae_vector_clear(&p->x);
80908 0 : ae_vector_clear(&p->fi);
80909 0 : ae_matrix_clear(&p->j);
80910 0 : ae_matrix_clear(&p->h);
80911 0 : ae_vector_clear(&p->g);
80912 0 : ae_vector_clear(&p->xbase);
80913 0 : ae_vector_clear(&p->fibase);
80914 0 : ae_vector_clear(&p->gbase);
80915 0 : ae_matrix_clear(&p->quadraticmodel);
80916 0 : ae_vector_clear(&p->bndl);
80917 0 : ae_vector_clear(&p->bndu);
80918 0 : ae_vector_clear(&p->havebndl);
80919 0 : ae_vector_clear(&p->havebndu);
80920 0 : ae_vector_clear(&p->s);
80921 0 : ae_matrix_clear(&p->cleic);
80922 0 : ae_vector_clear(&p->xnew);
80923 0 : ae_vector_clear(&p->xdir);
80924 0 : ae_vector_clear(&p->deltax);
80925 0 : ae_vector_clear(&p->deltaf);
80926 0 : _smoothnessmonitor_clear(&p->smonitor);
80927 0 : ae_vector_clear(&p->lastscaleused);
80928 0 : _rcommstate_clear(&p->rstate);
80929 0 : ae_vector_clear(&p->choleskybuf);
80930 0 : ae_vector_clear(&p->tmp0);
80931 0 : ae_vector_clear(&p->fm1);
80932 0 : ae_vector_clear(&p->fp1);
80933 0 : ae_vector_clear(&p->fc1);
80934 0 : ae_vector_clear(&p->gm1);
80935 0 : ae_vector_clear(&p->gp1);
80936 0 : ae_vector_clear(&p->gc1);
80937 0 : _minlbfgsstate_clear(&p->internalstate);
80938 0 : _minlbfgsreport_clear(&p->internalrep);
80939 0 : _minqpstate_clear(&p->qpstate);
80940 0 : _minqpreport_clear(&p->qprep);
80941 0 : _minlmstepfinder_clear(&p->finderstate);
80942 0 : }
80943 :
80944 :
80945 0 : void _minlmstate_destroy(void* _p)
80946 : {
80947 0 : minlmstate *p = (minlmstate*)_p;
80948 0 : ae_touch_ptr((void*)p);
80949 0 : ae_vector_destroy(&p->x);
80950 0 : ae_vector_destroy(&p->fi);
80951 0 : ae_matrix_destroy(&p->j);
80952 0 : ae_matrix_destroy(&p->h);
80953 0 : ae_vector_destroy(&p->g);
80954 0 : ae_vector_destroy(&p->xbase);
80955 0 : ae_vector_destroy(&p->fibase);
80956 0 : ae_vector_destroy(&p->gbase);
80957 0 : ae_matrix_destroy(&p->quadraticmodel);
80958 0 : ae_vector_destroy(&p->bndl);
80959 0 : ae_vector_destroy(&p->bndu);
80960 0 : ae_vector_destroy(&p->havebndl);
80961 0 : ae_vector_destroy(&p->havebndu);
80962 0 : ae_vector_destroy(&p->s);
80963 0 : ae_matrix_destroy(&p->cleic);
80964 0 : ae_vector_destroy(&p->xnew);
80965 0 : ae_vector_destroy(&p->xdir);
80966 0 : ae_vector_destroy(&p->deltax);
80967 0 : ae_vector_destroy(&p->deltaf);
80968 0 : _smoothnessmonitor_destroy(&p->smonitor);
80969 0 : ae_vector_destroy(&p->lastscaleused);
80970 0 : _rcommstate_destroy(&p->rstate);
80971 0 : ae_vector_destroy(&p->choleskybuf);
80972 0 : ae_vector_destroy(&p->tmp0);
80973 0 : ae_vector_destroy(&p->fm1);
80974 0 : ae_vector_destroy(&p->fp1);
80975 0 : ae_vector_destroy(&p->fc1);
80976 0 : ae_vector_destroy(&p->gm1);
80977 0 : ae_vector_destroy(&p->gp1);
80978 0 : ae_vector_destroy(&p->gc1);
80979 0 : _minlbfgsstate_destroy(&p->internalstate);
80980 0 : _minlbfgsreport_destroy(&p->internalrep);
80981 0 : _minqpstate_destroy(&p->qpstate);
80982 0 : _minqpreport_destroy(&p->qprep);
80983 0 : _minlmstepfinder_destroy(&p->finderstate);
80984 0 : }
80985 :
80986 :
80987 0 : void _minlmreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
80988 : {
80989 0 : minlmreport *p = (minlmreport*)_p;
80990 0 : ae_touch_ptr((void*)p);
80991 0 : }
80992 :
80993 :
80994 0 : void _minlmreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
80995 : {
80996 0 : minlmreport *dst = (minlmreport*)_dst;
80997 0 : minlmreport *src = (minlmreport*)_src;
80998 0 : dst->iterationscount = src->iterationscount;
80999 0 : dst->terminationtype = src->terminationtype;
81000 0 : dst->nfunc = src->nfunc;
81001 0 : dst->njac = src->njac;
81002 0 : dst->ngrad = src->ngrad;
81003 0 : dst->nhess = src->nhess;
81004 0 : dst->ncholesky = src->ncholesky;
81005 0 : }
81006 :
81007 :
81008 0 : void _minlmreport_clear(void* _p)
81009 : {
81010 0 : minlmreport *p = (minlmreport*)_p;
81011 0 : ae_touch_ptr((void*)p);
81012 0 : }
81013 :
81014 :
81015 0 : void _minlmreport_destroy(void* _p)
81016 : {
81017 0 : minlmreport *p = (minlmreport*)_p;
81018 0 : ae_touch_ptr((void*)p);
81019 0 : }
81020 :
81021 :
81022 : #endif
81023 :
81024 : }
81025 :
|