LCOV - code coverage report
Current view: top level - synthesis/MeasurementEquations/lbfgs - optimization.cc (source / functions) Hit Total Coverage
Test: casa_coverage.info Lines: 845 28869 2.9 %
Date: 2023-10-25 08:47:59 Functions: 61 1293 4.7 %

          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             : 

Generated by: LCOV version 1.16