Xmipp  v3.23.11-Nereus
dataanalysis.cpp
Go to the documentation of this file.
1 /*************************************************************************
2 Copyright (c) Sergey Bochkanov (ALGLIB project).
3 
4 >>> SOURCE LICENSE >>>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation (www.fsf.org); either version 2 of the
8 License, or (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 A copy of the GNU General Public License is available at
16 http://www.fsf.org/licensing/licenses
17 >>> END OF LICENSE >>>
18 *************************************************************************/
19 #include "stdafx.h"
20 #include "dataanalysis.h"
21 
22 // disable some irrelevant warnings
23 #if (AE_COMPILER==AE_MSVC)
24 #pragma warning(disable:4100)
25 #pragma warning(disable:4127)
26 #pragma warning(disable:4702)
27 #pragma warning(disable:4996)
28 #endif
29 using namespace std;
30 
32 //
33 // THIS SECTION CONTAINS IMPLEMENTATION OF C++ INTERFACE
34 //
36 namespace alglib
37 {
38 
39 
40 /*************************************************************************
41 Optimal binary classification
42 
43 Algorithms finds optimal (=with minimal cross-entropy) binary partition.
44 Internal subroutine.
45 
46 INPUT PARAMETERS:
47  A - array[0..N-1], variable
48  C - array[0..N-1], class numbers (0 or 1).
49  N - array size
50 
51 OUTPUT PARAMETERS:
52  Info - completion code:
53  * -3, all values of A[] are same (partition is impossible)
54  * -2, one of C[] is incorrect (<0, >1)
55  * -1, incorrect pararemets were passed (N<=0).
56  * 1, OK
57  Threshold- partiton boundary. Left part contains values which are
58  strictly less than Threshold. Right part contains values
59  which are greater than or equal to Threshold.
60  PAL, PBL- probabilities P(0|v<Threshold) and P(1|v<Threshold)
61  PAR, PBR- probabilities P(0|v>=Threshold) and P(1|v>=Threshold)
62  CVE - cross-validation estimate of cross-entropy
63 
64  -- ALGLIB --
65  Copyright 22.05.2008 by Bochkanov Sergey
66 *************************************************************************/
67 void dsoptimalsplit2(const real_1d_array &a, const integer_1d_array &c, const ae_int_t n, ae_int_t &info, double &threshold, double &pal, double &pbl, double &par, double &pbr, double &cve)
68 {
69  alglib_impl::ae_state _alglib_env_state;
70  alglib_impl::ae_state_init(&_alglib_env_state);
71  try
72  {
73  alglib_impl::dsoptimalsplit2(const_cast<alglib_impl::ae_vector*>(a.c_ptr()), const_cast<alglib_impl::ae_vector*>(c.c_ptr()), n, &info, &threshold, &pal, &pbl, &par, &pbr, &cve, &_alglib_env_state);
74  alglib_impl::ae_state_clear(&_alglib_env_state);
75  return;
76  }
78  {
79  throw ap_error(_alglib_env_state.error_msg);
80  }
81 }
82 
83 /*************************************************************************
84 Optimal partition, internal subroutine. Fast version.
85 
86 Accepts:
87  A array[0..N-1] array of attributes array[0..N-1]
88  C array[0..N-1] array of class labels
89  TiesBuf array[0..N] temporaries (ties)
90  CntBuf array[0..2*NC-1] temporaries (counts)
91  Alpha centering factor (0<=alpha<=1, recommended value - 0.05)
92  BufR array[0..N-1] temporaries
93  BufI array[0..N-1] temporaries
94 
95 Output:
96  Info error code (">0"=OK, "<0"=bad)
97  RMS training set RMS error
98  CVRMS leave-one-out RMS error
99 
100 Note:
101  content of all arrays is changed by subroutine;
102  it doesn't allocate temporaries.
103 
104  -- ALGLIB --
105  Copyright 11.12.2008 by Bochkanov Sergey
106 *************************************************************************/
107 void dsoptimalsplit2fast(real_1d_array &a, integer_1d_array &c, integer_1d_array &tiesbuf, integer_1d_array &cntbuf, real_1d_array &bufr, integer_1d_array &bufi, const ae_int_t n, const ae_int_t nc, const double alpha, ae_int_t &info, double &threshold, double &rms, double &cvrms)
108 {
109  alglib_impl::ae_state _alglib_env_state;
110  alglib_impl::ae_state_init(&_alglib_env_state);
111  try
112  {
113  alglib_impl::dsoptimalsplit2fast(const_cast<alglib_impl::ae_vector*>(a.c_ptr()), const_cast<alglib_impl::ae_vector*>(c.c_ptr()), const_cast<alglib_impl::ae_vector*>(tiesbuf.c_ptr()), const_cast<alglib_impl::ae_vector*>(cntbuf.c_ptr()), const_cast<alglib_impl::ae_vector*>(bufr.c_ptr()), const_cast<alglib_impl::ae_vector*>(bufi.c_ptr()), n, nc, alpha, &info, &threshold, &rms, &cvrms, &_alglib_env_state);
114  alglib_impl::ae_state_clear(&_alglib_env_state);
115  return;
116  }
118  {
119  throw ap_error(_alglib_env_state.error_msg);
120  }
121 }
122 
123 /*************************************************************************
124 This structure is a clusterization engine.
125 
126 You should not try to access its fields directly.
127 Use ALGLIB functions in order to work with this object.
128 
129  -- ALGLIB --
130  Copyright 10.07.2012 by Bochkanov Sergey
131 *************************************************************************/
132 _clusterizerstate_owner::_clusterizerstate_owner()
133 {
135  if( p_struct==NULL )
136  throw ap_error("ALGLIB: malloc error");
137  if( !alglib_impl::_clusterizerstate_init(p_struct, NULL, ae_false) )
138  throw ap_error("ALGLIB: malloc error");
139 }
140 
141 _clusterizerstate_owner::_clusterizerstate_owner(const _clusterizerstate_owner &rhs)
142 {
144  if( p_struct==NULL )
145  throw ap_error("ALGLIB: malloc error");
146  if( !alglib_impl::_clusterizerstate_init_copy(p_struct, const_cast<alglib_impl::clusterizerstate*>(rhs.p_struct), NULL, ae_false) )
147  throw ap_error("ALGLIB: malloc error");
148 }
149 
150 _clusterizerstate_owner& _clusterizerstate_owner::operator=(const _clusterizerstate_owner &rhs)
151 {
152  if( this==&rhs )
153  return *this;
155  if( !alglib_impl::_clusterizerstate_init_copy(p_struct, const_cast<alglib_impl::clusterizerstate*>(rhs.p_struct), NULL, ae_false) )
156  throw ap_error("ALGLIB: malloc error");
157  return *this;
158 }
159 
160 _clusterizerstate_owner::~_clusterizerstate_owner()
161 {
163  ae_free(p_struct);
164 }
165 
166 alglib_impl::clusterizerstate* _clusterizerstate_owner::c_ptr()
167 {
168  return p_struct;
169 }
170 
171 alglib_impl::clusterizerstate* _clusterizerstate_owner::c_ptr() const
172 {
173  return const_cast<alglib_impl::clusterizerstate*>(p_struct);
174 }
175 clusterizerstate::clusterizerstate() : _clusterizerstate_owner()
176 {
177 }
178 
180 {
181 }
182 
184 {
185  if( this==&rhs )
186  return *this;
188  return *this;
189 }
190 
192 {
193 }
194 
195 
196 /*************************************************************************
197 This structure is used to store results of the agglomerative hierarchical
198 clustering (AHC).
199 
200 Following information is returned:
201 
202 * NPoints contains number of points in the original dataset
203 
204 * Z contains information about merges performed (see below). Z contains
205  indexes from the original (unsorted) dataset and it can be used when you
206  need to know what points were merged. However, it is not convenient when
207  you want to build a dendrograd (see below).
208 
209 * if you want to build dendrogram, you can use Z, but it is not good
210  option, because Z contains indexes from unsorted dataset. Dendrogram
211  built from such dataset is likely to have intersections. So, you have to
212  reorder you points before building dendrogram.
213  Permutation which reorders point is returned in P. Another representation
214  of merges, which is more convenient for dendorgram construction, is
215  returned in PM.
216 
217 * more information on format of Z, P and PM can be found below and in the
218  examples from ALGLIB Reference Manual.
219 
220 FORMAL DESCRIPTION OF FIELDS:
221  NPoints number of points
222  Z array[NPoints-1,2], contains indexes of clusters
223  linked in pairs to form clustering tree. I-th row
224  corresponds to I-th merge:
225  * Z[I,0] - index of the first cluster to merge
226  * Z[I,1] - index of the second cluster to merge
227  * Z[I,0]<Z[I,1]
228  * clusters are numbered from 0 to 2*NPoints-2, with
229  indexes from 0 to NPoints-1 corresponding to points
230  of the original dataset, and indexes from NPoints to
231  2*NPoints-2 correspond to clusters generated by
232  subsequent merges (I-th row of Z creates cluster
233  with index NPoints+I).
234 
235  IMPORTANT: indexes in Z[] are indexes in the ORIGINAL,
236  unsorted dataset. In addition to Z algorithm outputs
237  permutation which rearranges points in such way that
238  subsequent merges are performed on adjacent points
239  (such order is needed if you want to build dendrogram).
240  However, indexes in Z are related to original,
241  unrearranged sequence of points.
242 
243  P array[NPoints], permutation which reorders points for
244  dendrogram construction. P[i] contains index of the
245  position where we should move I-th point of the
246  original dataset in order to apply merges PZ/PM.
247 
248  PZ same as Z, but for permutation of points given by P.
249  The only thing which changed are indexes of the
250  original points; indexes of clusters remained same.
251 
252  MergeDist array[NPoints-1], contains distances between clusters
253  being merged (MergeDist[i] correspond to merge stored
254  in Z[i,...]).
255 
256  PM array[NPoints-1,6], another representation of merges,
257  which is suited for dendrogram construction. It deals
258  with rearranged points (permutation P is applied) and
259  represents merges in a form which different from one
260  used by Z.
261  For each I from 0 to NPoints-2, I-th row of PM represents
262  merge performed on two clusters C0 and C1. Here:
263  * C0 contains points with indexes PM[I,0]...PM[I,1]
264  * C1 contains points with indexes PM[I,2]...PM[I,3]
265  * indexes stored in PM are given for dataset sorted
266  according to permutation P
267  * PM[I,1]=PM[I,2]-1 (only adjacent clusters are merged)
268  * PM[I,0]<=PM[I,1], PM[I,2]<=PM[I,3], i.e. both
269  clusters contain at least one point
270  * heights of "subdendrograms" corresponding to C0/C1
271  are stored in PM[I,4] and PM[I,5]. Subdendrograms
272  corresponding to single-point clusters have
273  height=0. Dendrogram of the merge result has height
274  H=max(H0,H1)+1.
275 
276 NOTE: there is one-to-one correspondence between merges described by Z and
277  PM. I-th row of Z describes same merge of clusters as I-th row of PM,
278  with "left" cluster from Z corresponding to the "left" one from PM.
279 
280  -- ALGLIB --
281  Copyright 10.07.2012 by Bochkanov Sergey
282 *************************************************************************/
284 {
286  if( p_struct==NULL )
287  throw ap_error("ALGLIB: malloc error");
289  throw ap_error("ALGLIB: malloc error");
290 }
291 
293 {
295  if( p_struct==NULL )
296  throw ap_error("ALGLIB: malloc error");
297  if( !alglib_impl::_ahcreport_init_copy(p_struct, const_cast<alglib_impl::ahcreport*>(rhs.p_struct), NULL, ae_false) )
298  throw ap_error("ALGLIB: malloc error");
299 }
300 
302 {
303  if( this==&rhs )
304  return *this;
306  if( !alglib_impl::_ahcreport_init_copy(p_struct, const_cast<alglib_impl::ahcreport*>(rhs.p_struct), NULL, ae_false) )
307  throw ap_error("ALGLIB: malloc error");
308  return *this;
309 }
310 
312 {
314  ae_free(p_struct);
315 }
316 
318 {
319  return p_struct;
320 }
321 
323 {
324  return const_cast<alglib_impl::ahcreport*>(p_struct);
325 }
326 ahcreport::ahcreport() : _ahcreport_owner() ,npoints(p_struct->npoints),p(&p_struct->p),z(&p_struct->z),pz(&p_struct->pz),pm(&p_struct->pm),mergedist(&p_struct->mergedist)
327 {
328 }
329 
331 {
332 }
333 
335 {
336  if( this==&rhs )
337  return *this;
339  return *this;
340 }
341 
343 {
344 }
345 
346 
347 /*************************************************************************
348 This structure is used to store results of the k-means++ clustering
349 algorithm.
350 
351 Following information is always returned:
352 * NPoints contains number of points in the original dataset
353 * TerminationType contains completion code, negative on failure, positive
354  on success
355 * K contains number of clusters
356 
357 For positive TerminationType we return:
358 * NFeatures contains number of variables in the original dataset
359 * C, which contains centers found by algorithm
360 * CIdx, which maps points of the original dataset to clusters
361 
362 FORMAL DESCRIPTION OF FIELDS:
363  NPoints number of points, >=0
364  NFeatures number of variables, >=1
365  TerminationType completion code:
366  * -5 if distance type is anything different from
367  Euclidean metric
368  * -3 for degenerate dataset: a) less than K distinct
369  points, b) K=0 for non-empty dataset.
370  * +1 for successful completion
371  K number of clusters
372  C array[K,NFeatures], rows of the array store centers
373  CIdx array[NPoints], which contains cluster indexes
374 
375  -- ALGLIB --
376  Copyright 27.11.2012 by Bochkanov Sergey
377 *************************************************************************/
379 {
381  if( p_struct==NULL )
382  throw ap_error("ALGLIB: malloc error");
384  throw ap_error("ALGLIB: malloc error");
385 }
386 
388 {
390  if( p_struct==NULL )
391  throw ap_error("ALGLIB: malloc error");
392  if( !alglib_impl::_kmeansreport_init_copy(p_struct, const_cast<alglib_impl::kmeansreport*>(rhs.p_struct), NULL, ae_false) )
393  throw ap_error("ALGLIB: malloc error");
394 }
395 
397 {
398  if( this==&rhs )
399  return *this;
401  if( !alglib_impl::_kmeansreport_init_copy(p_struct, const_cast<alglib_impl::kmeansreport*>(rhs.p_struct), NULL, ae_false) )
402  throw ap_error("ALGLIB: malloc error");
403  return *this;
404 }
405 
407 {
409  ae_free(p_struct);
410 }
411 
413 {
414  return p_struct;
415 }
416 
418 {
419  return const_cast<alglib_impl::kmeansreport*>(p_struct);
420 }
421 kmeansreport::kmeansreport() : _kmeansreport_owner() ,npoints(p_struct->npoints),nfeatures(p_struct->nfeatures),terminationtype(p_struct->terminationtype),k(p_struct->k),c(&p_struct->c),cidx(&p_struct->cidx)
422 {
423 }
424 
426 {
427 }
428 
430 {
431  if( this==&rhs )
432  return *this;
434  return *this;
435 }
436 
438 {
439 }
440 
441 /*************************************************************************
442 This function initializes clusterizer object. Newly initialized object is
443 empty, i.e. it does not contain dataset. You should use it as follows:
444 1. creation
445 2. dataset is added with ClusterizerSetPoints()
446 3. additional parameters are set
447 3. clusterization is performed with one of the clustering functions
448 
449  -- ALGLIB --
450  Copyright 10.07.2012 by Bochkanov Sergey
451 *************************************************************************/
453 {
454  alglib_impl::ae_state _alglib_env_state;
455  alglib_impl::ae_state_init(&_alglib_env_state);
456  try
457  {
458  alglib_impl::clusterizercreate(const_cast<alglib_impl::clusterizerstate*>(s.c_ptr()), &_alglib_env_state);
459  alglib_impl::ae_state_clear(&_alglib_env_state);
460  return;
461  }
463  {
464  throw ap_error(_alglib_env_state.error_msg);
465  }
466 }
467 
468 /*************************************************************************
469 This function adds dataset to the clusterizer structure.
470 
471 This function overrides all previous calls of ClusterizerSetPoints() or
472 ClusterizerSetDistances().
473 
474 INPUT PARAMETERS:
475  S - clusterizer state, initialized by ClusterizerCreate()
476  XY - array[NPoints,NFeatures], dataset
477  NPoints - number of points, >=0
478  NFeatures- number of features, >=1
479  DistType- distance function:
480  * 0 Chebyshev distance (L-inf norm)
481  * 1 city block distance (L1 norm)
482  * 2 Euclidean distance (L2 norm)
483  * 10 Pearson correlation:
484  dist(a,b) = 1-corr(a,b)
485  * 11 Absolute Pearson correlation:
486  dist(a,b) = 1-|corr(a,b)|
487  * 12 Uncentered Pearson correlation (cosine of the angle):
488  dist(a,b) = a'*b/(|a|*|b|)
489  * 13 Absolute uncentered Pearson correlation
490  dist(a,b) = |a'*b|/(|a|*|b|)
491  * 20 Spearman rank correlation:
492  dist(a,b) = 1-rankcorr(a,b)
493  * 21 Absolute Spearman rank correlation
494  dist(a,b) = 1-|rankcorr(a,b)|
495 
496 NOTE 1: different distance functions have different performance penalty:
497  * Euclidean or Pearson correlation distances are the fastest ones
498  * Spearman correlation distance function is a bit slower
499  * city block and Chebyshev distances are order of magnitude slower
500 
501  The reason behing difference in performance is that correlation-based
502  distance functions are computed using optimized linear algebra kernels,
503  while Chebyshev and city block distance functions are computed using
504  simple nested loops with two branches at each iteration.
505 
506 NOTE 2: different clustering algorithms have different limitations:
507  * agglomerative hierarchical clustering algorithms may be used with
508  any kind of distance metric
509  * k-means++ clustering algorithm may be used only with Euclidean
510  distance function
511  Thus, list of specific clustering algorithms you may use depends
512  on distance function you specify when you set your dataset.
513 
514  -- ALGLIB --
515  Copyright 10.07.2012 by Bochkanov Sergey
516 *************************************************************************/
517 void clusterizersetpoints(const clusterizerstate &s, const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nfeatures, const ae_int_t disttype)
518 {
519  alglib_impl::ae_state _alglib_env_state;
520  alglib_impl::ae_state_init(&_alglib_env_state);
521  try
522  {
523  alglib_impl::clusterizersetpoints(const_cast<alglib_impl::clusterizerstate*>(s.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, nfeatures, disttype, &_alglib_env_state);
524  alglib_impl::ae_state_clear(&_alglib_env_state);
525  return;
526  }
528  {
529  throw ap_error(_alglib_env_state.error_msg);
530  }
531 }
532 
533 /*************************************************************************
534 This function adds dataset to the clusterizer structure.
535 
536 This function overrides all previous calls of ClusterizerSetPoints() or
537 ClusterizerSetDistances().
538 
539 INPUT PARAMETERS:
540  S - clusterizer state, initialized by ClusterizerCreate()
541  XY - array[NPoints,NFeatures], dataset
542  NPoints - number of points, >=0
543  NFeatures- number of features, >=1
544  DistType- distance function:
545  * 0 Chebyshev distance (L-inf norm)
546  * 1 city block distance (L1 norm)
547  * 2 Euclidean distance (L2 norm)
548  * 10 Pearson correlation:
549  dist(a,b) = 1-corr(a,b)
550  * 11 Absolute Pearson correlation:
551  dist(a,b) = 1-|corr(a,b)|
552  * 12 Uncentered Pearson correlation (cosine of the angle):
553  dist(a,b) = a'*b/(|a|*|b|)
554  * 13 Absolute uncentered Pearson correlation
555  dist(a,b) = |a'*b|/(|a|*|b|)
556  * 20 Spearman rank correlation:
557  dist(a,b) = 1-rankcorr(a,b)
558  * 21 Absolute Spearman rank correlation
559  dist(a,b) = 1-|rankcorr(a,b)|
560 
561 NOTE 1: different distance functions have different performance penalty:
562  * Euclidean or Pearson correlation distances are the fastest ones
563  * Spearman correlation distance function is a bit slower
564  * city block and Chebyshev distances are order of magnitude slower
565 
566  The reason behing difference in performance is that correlation-based
567  distance functions are computed using optimized linear algebra kernels,
568  while Chebyshev and city block distance functions are computed using
569  simple nested loops with two branches at each iteration.
570 
571 NOTE 2: different clustering algorithms have different limitations:
572  * agglomerative hierarchical clustering algorithms may be used with
573  any kind of distance metric
574  * k-means++ clustering algorithm may be used only with Euclidean
575  distance function
576  Thus, list of specific clustering algorithms you may use depends
577  on distance function you specify when you set your dataset.
578 
579  -- ALGLIB --
580  Copyright 10.07.2012 by Bochkanov Sergey
581 *************************************************************************/
582 void clusterizersetpoints(const clusterizerstate &s, const real_2d_array &xy, const ae_int_t disttype)
583 {
584  alglib_impl::ae_state _alglib_env_state;
587 
588  npoints = xy.rows();
589  nfeatures = xy.cols();
590  alglib_impl::ae_state_init(&_alglib_env_state);
591  try
592  {
593  alglib_impl::clusterizersetpoints(const_cast<alglib_impl::clusterizerstate*>(s.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, nfeatures, disttype, &_alglib_env_state);
594 
595  alglib_impl::ae_state_clear(&_alglib_env_state);
596  return;
597  }
599  {
600  throw ap_error(_alglib_env_state.error_msg);
601  }
602 }
603 
604 /*************************************************************************
605 This function adds dataset given by distance matrix to the clusterizer
606 structure. It is important that dataset is not given explicitly - only
607 distance matrix is given.
608 
609 This function overrides all previous calls of ClusterizerSetPoints() or
610 ClusterizerSetDistances().
611 
612 INPUT PARAMETERS:
613  S - clusterizer state, initialized by ClusterizerCreate()
614  D - array[NPoints,NPoints], distance matrix given by its upper
615  or lower triangle (main diagonal is ignored because its
616  entries are expected to be zero).
617  NPoints - number of points
618  IsUpper - whether upper or lower triangle of D is given.
619 
620 NOTE 1: different clustering algorithms have different limitations:
621  * agglomerative hierarchical clustering algorithms may be used with
622  any kind of distance metric, including one which is given by
623  distance matrix
624  * k-means++ clustering algorithm may be used only with Euclidean
625  distance function and explicitly given points - it can not be
626  used with dataset given by distance matrix
627  Thus, if you call this function, you will be unable to use k-means
628  clustering algorithm to process your problem.
629 
630  -- ALGLIB --
631  Copyright 10.07.2012 by Bochkanov Sergey
632 *************************************************************************/
633 void clusterizersetdistances(const clusterizerstate &s, const real_2d_array &d, const ae_int_t npoints, const bool isupper)
634 {
635  alglib_impl::ae_state _alglib_env_state;
636  alglib_impl::ae_state_init(&_alglib_env_state);
637  try
638  {
639  alglib_impl::clusterizersetdistances(const_cast<alglib_impl::clusterizerstate*>(s.c_ptr()), const_cast<alglib_impl::ae_matrix*>(d.c_ptr()), npoints, isupper, &_alglib_env_state);
640  alglib_impl::ae_state_clear(&_alglib_env_state);
641  return;
642  }
644  {
645  throw ap_error(_alglib_env_state.error_msg);
646  }
647 }
648 
649 /*************************************************************************
650 This function adds dataset given by distance matrix to the clusterizer
651 structure. It is important that dataset is not given explicitly - only
652 distance matrix is given.
653 
654 This function overrides all previous calls of ClusterizerSetPoints() or
655 ClusterizerSetDistances().
656 
657 INPUT PARAMETERS:
658  S - clusterizer state, initialized by ClusterizerCreate()
659  D - array[NPoints,NPoints], distance matrix given by its upper
660  or lower triangle (main diagonal is ignored because its
661  entries are expected to be zero).
662  NPoints - number of points
663  IsUpper - whether upper or lower triangle of D is given.
664 
665 NOTE 1: different clustering algorithms have different limitations:
666  * agglomerative hierarchical clustering algorithms may be used with
667  any kind of distance metric, including one which is given by
668  distance matrix
669  * k-means++ clustering algorithm may be used only with Euclidean
670  distance function and explicitly given points - it can not be
671  used with dataset given by distance matrix
672  Thus, if you call this function, you will be unable to use k-means
673  clustering algorithm to process your problem.
674 
675  -- ALGLIB --
676  Copyright 10.07.2012 by Bochkanov Sergey
677 *************************************************************************/
678 void clusterizersetdistances(const clusterizerstate &s, const real_2d_array &d, const bool isupper)
679 {
680  alglib_impl::ae_state _alglib_env_state;
682  if( (d.rows()!=d.cols()))
683  throw ap_error("Error while calling 'clusterizersetdistances': looks like one of arguments has wrong size");
684  npoints = d.rows();
685  alglib_impl::ae_state_init(&_alglib_env_state);
686  try
687  {
688  alglib_impl::clusterizersetdistances(const_cast<alglib_impl::clusterizerstate*>(s.c_ptr()), const_cast<alglib_impl::ae_matrix*>(d.c_ptr()), npoints, isupper, &_alglib_env_state);
689 
690  alglib_impl::ae_state_clear(&_alglib_env_state);
691  return;
692  }
694  {
695  throw ap_error(_alglib_env_state.error_msg);
696  }
697 }
698 
699 /*************************************************************************
700 This function sets agglomerative hierarchical clustering algorithm
701 
702 INPUT PARAMETERS:
703  S - clusterizer state, initialized by ClusterizerCreate()
704  Algo - algorithm type:
705  * 0 complete linkage (default algorithm)
706  * 1 single linkage
707  * 2 unweighted average linkage
708  * 3 weighted average linkage
709 
710  -- ALGLIB --
711  Copyright 10.07.2012 by Bochkanov Sergey
712 *************************************************************************/
714 {
715  alglib_impl::ae_state _alglib_env_state;
716  alglib_impl::ae_state_init(&_alglib_env_state);
717  try
718  {
719  alglib_impl::clusterizersetahcalgo(const_cast<alglib_impl::clusterizerstate*>(s.c_ptr()), algo, &_alglib_env_state);
720  alglib_impl::ae_state_clear(&_alglib_env_state);
721  return;
722  }
724  {
725  throw ap_error(_alglib_env_state.error_msg);
726  }
727 }
728 
729 /*************************************************************************
730 This function sets k-means++ properties : number of restarts and maximum
731 number of iterations per one run.
732 
733 INPUT PARAMETERS:
734  S - clusterizer state, initialized by ClusterizerCreate()
735  Restarts- restarts count, >=1.
736  k-means++ algorithm performs several restarts and chooses
737  best set of centers (one with minimum squared distance).
738  MaxIts - maximum number of k-means iterations performed during one
739  run. >=0, zero value means that algorithm performs unlimited
740  number of iterations.
741 
742  -- ALGLIB --
743  Copyright 10.07.2012 by Bochkanov Sergey
744 *************************************************************************/
745 void clusterizersetkmeanslimits(const clusterizerstate &s, const ae_int_t restarts, const ae_int_t maxits)
746 {
747  alglib_impl::ae_state _alglib_env_state;
748  alglib_impl::ae_state_init(&_alglib_env_state);
749  try
750  {
751  alglib_impl::clusterizersetkmeanslimits(const_cast<alglib_impl::clusterizerstate*>(s.c_ptr()), restarts, maxits, &_alglib_env_state);
752  alglib_impl::ae_state_clear(&_alglib_env_state);
753  return;
754  }
756  {
757  throw ap_error(_alglib_env_state.error_msg);
758  }
759 }
760 
761 /*************************************************************************
762 This function performs agglomerative hierarchical clustering
763 
764 FOR USERS OF SMP EDITION:
765 
766  ! This function can utilize multicore capabilities of your system. In
767  ! order to do this you have to call version with "smp_" prefix, which
768  ! indicates that multicore code will be used.
769  !
770  ! This note is given for users of SMP edition; if you use GPL edition,
771  ! or commercial edition of ALGLIB without SMP support, you still will
772  ! be able to call smp-version of this function, but all computations
773  ! will be done serially.
774  !
775  ! We recommend you to carefully read ALGLIB Reference Manual, section
776  ! called 'SMP support', before using parallel version of this function.
777  !
778  ! You should remember that starting/stopping worker thread always have
779  ! non-zero cost. Multicore version is pretty efficient on large
780  ! problems which need more than 1.000.000 operations to be solved,
781  ! gives moderate speed-up in mid-range (from 100.000 to 1.000.000 CPU
782  ! cycles), but gives no speed-up for small problems (less than 100.000
783  ! operations).
784 
785 INPUT PARAMETERS:
786  S - clusterizer state, initialized by ClusterizerCreate()
787 
788 OUTPUT PARAMETERS:
789  Rep - clustering results; see description of AHCReport
790  structure for more information.
791 
792 NOTE 1: hierarchical clustering algorithms require large amounts of memory.
793  In particular, this implementation needs sizeof(double)*NPoints^2
794  bytes, which are used to store distance matrix. In case we work
795  with user-supplied matrix, this amount is multiplied by 2 (we have
796  to store original matrix and to work with its copy).
797 
798  For example, problem with 10000 points would require 800M of RAM,
799  even when working in a 1-dimensional space.
800 
801  -- ALGLIB --
802  Copyright 10.07.2012 by Bochkanov Sergey
803 *************************************************************************/
805 {
806  alglib_impl::ae_state _alglib_env_state;
807  alglib_impl::ae_state_init(&_alglib_env_state);
808  try
809  {
810  alglib_impl::clusterizerrunahc(const_cast<alglib_impl::clusterizerstate*>(s.c_ptr()), const_cast<alglib_impl::ahcreport*>(rep.c_ptr()), &_alglib_env_state);
811  alglib_impl::ae_state_clear(&_alglib_env_state);
812  return;
813  }
815  {
816  throw ap_error(_alglib_env_state.error_msg);
817  }
818 }
819 
820 
822 {
823  alglib_impl::ae_state _alglib_env_state;
824  alglib_impl::ae_state_init(&_alglib_env_state);
825  try
826  {
827  alglib_impl::_pexec_clusterizerrunahc(const_cast<alglib_impl::clusterizerstate*>(s.c_ptr()), const_cast<alglib_impl::ahcreport*>(rep.c_ptr()), &_alglib_env_state);
828  alglib_impl::ae_state_clear(&_alglib_env_state);
829  return;
830  }
832  {
833  throw ap_error(_alglib_env_state.error_msg);
834  }
835 }
836 
837 /*************************************************************************
838 This function performs clustering by k-means++ algorithm.
839 
840 You may change algorithm properties like number of restarts or iterations
841 limit by calling ClusterizerSetKMeansLimits() functions.
842 
843 INPUT PARAMETERS:
844  S - clusterizer state, initialized by ClusterizerCreate()
845  K - number of clusters, K>=0.
846  K can be zero only when algorithm is called for empty
847  dataset, in this case completion code is set to
848  success (+1).
849  If K=0 and dataset size is non-zero, we can not
850  meaningfully assign points to some center (there are no
851  centers because K=0) and return -3 as completion code
852  (failure).
853 
854 OUTPUT PARAMETERS:
855  Rep - clustering results; see description of KMeansReport
856  structure for more information.
857 
858 NOTE 1: k-means clustering can be performed only for datasets with
859  Euclidean distance function. Algorithm will return negative
860  completion code in Rep.TerminationType in case dataset was added
861  to clusterizer with DistType other than Euclidean (or dataset was
862  specified by distance matrix instead of explicitly given points).
863 
864  -- ALGLIB --
865  Copyright 10.07.2012 by Bochkanov Sergey
866 *************************************************************************/
868 {
869  alglib_impl::ae_state _alglib_env_state;
870  alglib_impl::ae_state_init(&_alglib_env_state);
871  try
872  {
873  alglib_impl::clusterizerrunkmeans(const_cast<alglib_impl::clusterizerstate*>(s.c_ptr()), k, const_cast<alglib_impl::kmeansreport*>(rep.c_ptr()), &_alglib_env_state);
874  alglib_impl::ae_state_clear(&_alglib_env_state);
875  return;
876  }
878  {
879  throw ap_error(_alglib_env_state.error_msg);
880  }
881 }
882 
883 /*************************************************************************
884 This function returns distance matrix for dataset
885 
886 FOR USERS OF SMP EDITION:
887 
888  ! This function can utilize multicore capabilities of your system. In
889  ! order to do this you have to call version with "smp_" prefix, which
890  ! indicates that multicore code will be used.
891  !
892  ! This note is given for users of SMP edition; if you use GPL edition,
893  ! or commercial edition of ALGLIB without SMP support, you still will
894  ! be able to call smp-version of this function, but all computations
895  ! will be done serially.
896  !
897  ! We recommend you to carefully read ALGLIB Reference Manual, section
898  ! called 'SMP support', before using parallel version of this function.
899  !
900  ! You should remember that starting/stopping worker thread always have
901  ! non-zero cost. Multicore version is pretty efficient on large
902  ! problems which need more than 1.000.000 operations to be solved,
903  ! gives moderate speed-up in mid-range (from 100.000 to 1.000.000 CPU
904  ! cycles), but gives no speed-up for small problems (less than 100.000
905  ! operations).
906 
907 INPUT PARAMETERS:
908  XY - array[NPoints,NFeatures], dataset
909  NPoints - number of points, >=0
910  NFeatures- number of features, >=1
911  DistType- distance function:
912  * 0 Chebyshev distance (L-inf norm)
913  * 1 city block distance (L1 norm)
914  * 2 Euclidean distance (L2 norm)
915  * 10 Pearson correlation:
916  dist(a,b) = 1-corr(a,b)
917  * 11 Absolute Pearson correlation:
918  dist(a,b) = 1-|corr(a,b)|
919  * 12 Uncentered Pearson correlation (cosine of the angle):
920  dist(a,b) = a'*b/(|a|*|b|)
921  * 13 Absolute uncentered Pearson correlation
922  dist(a,b) = |a'*b|/(|a|*|b|)
923  * 20 Spearman rank correlation:
924  dist(a,b) = 1-rankcorr(a,b)
925  * 21 Absolute Spearman rank correlation
926  dist(a,b) = 1-|rankcorr(a,b)|
927 
928 OUTPUT PARAMETERS:
929  D - array[NPoints,NPoints], distance matrix
930  (full matrix is returned, with lower and upper triangles)
931 
932 NOTES: different distance functions have different performance penalty:
933  * Euclidean or Pearson correlation distances are the fastest ones
934  * Spearman correlation distance function is a bit slower
935  * city block and Chebyshev distances are order of magnitude slower
936 
937  The reason behing difference in performance is that correlation-based
938  distance functions are computed using optimized linear algebra kernels,
939  while Chebyshev and city block distance functions are computed using
940  simple nested loops with two branches at each iteration.
941 
942  -- ALGLIB --
943  Copyright 10.07.2012 by Bochkanov Sergey
944 *************************************************************************/
946 {
947  alglib_impl::ae_state _alglib_env_state;
948  alglib_impl::ae_state_init(&_alglib_env_state);
949  try
950  {
951  alglib_impl::clusterizergetdistances(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, nfeatures, disttype, const_cast<alglib_impl::ae_matrix*>(d.c_ptr()), &_alglib_env_state);
952  alglib_impl::ae_state_clear(&_alglib_env_state);
953  return;
954  }
956  {
957  throw ap_error(_alglib_env_state.error_msg);
958  }
959 }
960 
961 
963 {
964  alglib_impl::ae_state _alglib_env_state;
965  alglib_impl::ae_state_init(&_alglib_env_state);
966  try
967  {
968  alglib_impl::_pexec_clusterizergetdistances(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, nfeatures, disttype, const_cast<alglib_impl::ae_matrix*>(d.c_ptr()), &_alglib_env_state);
969  alglib_impl::ae_state_clear(&_alglib_env_state);
970  return;
971  }
973  {
974  throw ap_error(_alglib_env_state.error_msg);
975  }
976 }
977 
978 /*************************************************************************
979 This function takes as input clusterization report Rep, desired clusters
980 count K, and builds top K clusters from hierarchical clusterization tree.
981 It returns assignment of points to clusters (array of cluster indexes).
982 
983 INPUT PARAMETERS:
984  Rep - report from ClusterizerRunAHC() performed on XY
985  K - desired number of clusters, 1<=K<=NPoints.
986  K can be zero only when NPoints=0.
987 
988 OUTPUT PARAMETERS:
989  CIdx - array[NPoints], I-th element contains cluster index (from
990  0 to K-1) for I-th point of the dataset.
991  CZ - array[K]. This array allows to convert cluster indexes
992  returned by this function to indexes used by Rep.Z. J-th
993  cluster returned by this function corresponds to CZ[J]-th
994  cluster stored in Rep.Z/PZ/PM.
995  It is guaranteed that CZ[I]<CZ[I+1].
996 
997 NOTE: K clusters built by this subroutine are assumed to have no hierarchy.
998  Although they were obtained by manipulation with top K nodes of
999  dendrogram (i.e. hierarchical decomposition of dataset), this
1000  function does not return information about hierarchy. Each of the
1001  clusters stand on its own.
1002 
1003 NOTE: Cluster indexes returned by this function does not correspond to
1004  indexes returned in Rep.Z/PZ/PM. Either you work with hierarchical
1005  representation of the dataset (dendrogram), or you work with "flat"
1006  representation returned by this function. Each of representations
1007  has its own clusters indexing system (former uses [0, 2*NPoints-2]),
1008  while latter uses [0..K-1]), although it is possible to perform
1009  conversion from one system to another by means of CZ array, returned
1010  by this function, which allows you to convert indexes stored in CIdx
1011  to the numeration system used by Rep.Z.
1012 
1013 NOTE: this subroutine is optimized for moderate values of K. Say, for K=5
1014  it will perform many times faster than for K=100. Its worst-case
1015  performance is O(N*K), although in average case it perform better
1016  (up to O(N*log(K))).
1017 
1018  -- ALGLIB --
1019  Copyright 10.07.2012 by Bochkanov Sergey
1020 *************************************************************************/
1022 {
1023  alglib_impl::ae_state _alglib_env_state;
1024  alglib_impl::ae_state_init(&_alglib_env_state);
1025  try
1026  {
1027  alglib_impl::clusterizergetkclusters(const_cast<alglib_impl::ahcreport*>(rep.c_ptr()), k, const_cast<alglib_impl::ae_vector*>(cidx.c_ptr()), const_cast<alglib_impl::ae_vector*>(cz.c_ptr()), &_alglib_env_state);
1028  alglib_impl::ae_state_clear(&_alglib_env_state);
1029  return;
1030  }
1032  {
1033  throw ap_error(_alglib_env_state.error_msg);
1034  }
1035 }
1036 
1037 /*************************************************************************
1038 This function accepts AHC report Rep, desired minimum intercluster
1039 distance and returns top clusters from hierarchical clusterization tree
1040 which are separated by distance R or HIGHER.
1041 
1042 It returns assignment of points to clusters (array of cluster indexes).
1043 
1044 There is one more function with similar name - ClusterizerSeparatedByCorr,
1045 which returns clusters with intercluster correlation equal to R or LOWER
1046 (note: higher for distance, lower for correlation).
1047 
1048 INPUT PARAMETERS:
1049  Rep - report from ClusterizerRunAHC() performed on XY
1050  R - desired minimum intercluster distance, R>=0
1051 
1052 OUTPUT PARAMETERS:
1053  K - number of clusters, 1<=K<=NPoints
1054  CIdx - array[NPoints], I-th element contains cluster index (from
1055  0 to K-1) for I-th point of the dataset.
1056  CZ - array[K]. This array allows to convert cluster indexes
1057  returned by this function to indexes used by Rep.Z. J-th
1058  cluster returned by this function corresponds to CZ[J]-th
1059  cluster stored in Rep.Z/PZ/PM.
1060  It is guaranteed that CZ[I]<CZ[I+1].
1061 
1062 NOTE: K clusters built by this subroutine are assumed to have no hierarchy.
1063  Although they were obtained by manipulation with top K nodes of
1064  dendrogram (i.e. hierarchical decomposition of dataset), this
1065  function does not return information about hierarchy. Each of the
1066  clusters stand on its own.
1067 
1068 NOTE: Cluster indexes returned by this function does not correspond to
1069  indexes returned in Rep.Z/PZ/PM. Either you work with hierarchical
1070  representation of the dataset (dendrogram), or you work with "flat"
1071  representation returned by this function. Each of representations
1072  has its own clusters indexing system (former uses [0, 2*NPoints-2]),
1073  while latter uses [0..K-1]), although it is possible to perform
1074  conversion from one system to another by means of CZ array, returned
1075  by this function, which allows you to convert indexes stored in CIdx
1076  to the numeration system used by Rep.Z.
1077 
1078 NOTE: this subroutine is optimized for moderate values of K. Say, for K=5
1079  it will perform many times faster than for K=100. Its worst-case
1080  performance is O(N*K), although in average case it perform better
1081  (up to O(N*log(K))).
1082 
1083  -- ALGLIB --
1084  Copyright 10.07.2012 by Bochkanov Sergey
1085 *************************************************************************/
1087 {
1088  alglib_impl::ae_state _alglib_env_state;
1089  alglib_impl::ae_state_init(&_alglib_env_state);
1090  try
1091  {
1092  alglib_impl::clusterizerseparatedbydist(const_cast<alglib_impl::ahcreport*>(rep.c_ptr()), r, &k, const_cast<alglib_impl::ae_vector*>(cidx.c_ptr()), const_cast<alglib_impl::ae_vector*>(cz.c_ptr()), &_alglib_env_state);
1093  alglib_impl::ae_state_clear(&_alglib_env_state);
1094  return;
1095  }
1097  {
1098  throw ap_error(_alglib_env_state.error_msg);
1099  }
1100 }
1101 
1102 /*************************************************************************
1103 This function accepts AHC report Rep, desired maximum intercluster
1104 correlation and returns top clusters from hierarchical clusterization tree
1105 which are separated by correlation R or LOWER.
1106 
1107 It returns assignment of points to clusters (array of cluster indexes).
1108 
1109 There is one more function with similar name - ClusterizerSeparatedByDist,
1110 which returns clusters with intercluster distance equal to R or HIGHER
1111 (note: higher for distance, lower for correlation).
1112 
1113 INPUT PARAMETERS:
1114  Rep - report from ClusterizerRunAHC() performed on XY
1115  R - desired maximum intercluster correlation, -1<=R<=+1
1116 
1117 OUTPUT PARAMETERS:
1118  K - number of clusters, 1<=K<=NPoints
1119  CIdx - array[NPoints], I-th element contains cluster index (from
1120  0 to K-1) for I-th point of the dataset.
1121  CZ - array[K]. This array allows to convert cluster indexes
1122  returned by this function to indexes used by Rep.Z. J-th
1123  cluster returned by this function corresponds to CZ[J]-th
1124  cluster stored in Rep.Z/PZ/PM.
1125  It is guaranteed that CZ[I]<CZ[I+1].
1126 
1127 NOTE: K clusters built by this subroutine are assumed to have no hierarchy.
1128  Although they were obtained by manipulation with top K nodes of
1129  dendrogram (i.e. hierarchical decomposition of dataset), this
1130  function does not return information about hierarchy. Each of the
1131  clusters stand on its own.
1132 
1133 NOTE: Cluster indexes returned by this function does not correspond to
1134  indexes returned in Rep.Z/PZ/PM. Either you work with hierarchical
1135  representation of the dataset (dendrogram), or you work with "flat"
1136  representation returned by this function. Each of representations
1137  has its own clusters indexing system (former uses [0, 2*NPoints-2]),
1138  while latter uses [0..K-1]), although it is possible to perform
1139  conversion from one system to another by means of CZ array, returned
1140  by this function, which allows you to convert indexes stored in CIdx
1141  to the numeration system used by Rep.Z.
1142 
1143 NOTE: this subroutine is optimized for moderate values of K. Say, for K=5
1144  it will perform many times faster than for K=100. Its worst-case
1145  performance is O(N*K), although in average case it perform better
1146  (up to O(N*log(K))).
1147 
1148  -- ALGLIB --
1149  Copyright 10.07.2012 by Bochkanov Sergey
1150 *************************************************************************/
1152 {
1153  alglib_impl::ae_state _alglib_env_state;
1154  alglib_impl::ae_state_init(&_alglib_env_state);
1155  try
1156  {
1157  alglib_impl::clusterizerseparatedbycorr(const_cast<alglib_impl::ahcreport*>(rep.c_ptr()), r, &k, const_cast<alglib_impl::ae_vector*>(cidx.c_ptr()), const_cast<alglib_impl::ae_vector*>(cz.c_ptr()), &_alglib_env_state);
1158  alglib_impl::ae_state_clear(&_alglib_env_state);
1159  return;
1160  }
1162  {
1163  throw ap_error(_alglib_env_state.error_msg);
1164  }
1165 }
1166 
1167 /*************************************************************************
1168 k-means++ clusterization.
1169 Backward compatibility function, we recommend to use CLUSTERING subpackage
1170 as better replacement.
1171 
1172  -- ALGLIB --
1173  Copyright 21.03.2009 by Bochkanov Sergey
1174 *************************************************************************/
1175 void kmeansgenerate(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t k, const ae_int_t restarts, ae_int_t &info, real_2d_array &c, integer_1d_array &xyc)
1176 {
1177  alglib_impl::ae_state _alglib_env_state;
1178  alglib_impl::ae_state_init(&_alglib_env_state);
1179  try
1180  {
1181  alglib_impl::kmeansgenerate(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, nvars, k, restarts, &info, const_cast<alglib_impl::ae_matrix*>(c.c_ptr()), const_cast<alglib_impl::ae_vector*>(xyc.c_ptr()), &_alglib_env_state);
1182  alglib_impl::ae_state_clear(&_alglib_env_state);
1183  return;
1184  }
1186  {
1187  throw ap_error(_alglib_env_state.error_msg);
1188  }
1189 }
1190 
1191 /*************************************************************************
1192 
1193 *************************************************************************/
1195 {
1197  if( p_struct==NULL )
1198  throw ap_error("ALGLIB: malloc error");
1200  throw ap_error("ALGLIB: malloc error");
1201 }
1202 
1204 {
1206  if( p_struct==NULL )
1207  throw ap_error("ALGLIB: malloc error");
1208  if( !alglib_impl::_decisionforest_init_copy(p_struct, const_cast<alglib_impl::decisionforest*>(rhs.p_struct), NULL, ae_false) )
1209  throw ap_error("ALGLIB: malloc error");
1210 }
1211 
1213 {
1214  if( this==&rhs )
1215  return *this;
1217  if( !alglib_impl::_decisionforest_init_copy(p_struct, const_cast<alglib_impl::decisionforest*>(rhs.p_struct), NULL, ae_false) )
1218  throw ap_error("ALGLIB: malloc error");
1219  return *this;
1220 }
1221 
1223 {
1225  ae_free(p_struct);
1226 }
1227 
1229 {
1230  return p_struct;
1231 }
1232 
1234 {
1235  return const_cast<alglib_impl::decisionforest*>(p_struct);
1236 }
1238 {
1239 }
1240 
1242 {
1243 }
1244 
1246 {
1247  if( this==&rhs )
1248  return *this;
1250  return *this;
1251 }
1252 
1254 {
1255 }
1256 
1257 
1258 /*************************************************************************
1259 
1260 *************************************************************************/
1262 {
1264  if( p_struct==NULL )
1265  throw ap_error("ALGLIB: malloc error");
1267  throw ap_error("ALGLIB: malloc error");
1268 }
1269 
1271 {
1273  if( p_struct==NULL )
1274  throw ap_error("ALGLIB: malloc error");
1275  if( !alglib_impl::_dfreport_init_copy(p_struct, const_cast<alglib_impl::dfreport*>(rhs.p_struct), NULL, ae_false) )
1276  throw ap_error("ALGLIB: malloc error");
1277 }
1278 
1280 {
1281  if( this==&rhs )
1282  return *this;
1284  if( !alglib_impl::_dfreport_init_copy(p_struct, const_cast<alglib_impl::dfreport*>(rhs.p_struct), NULL, ae_false) )
1285  throw ap_error("ALGLIB: malloc error");
1286  return *this;
1287 }
1288 
1290 {
1292  ae_free(p_struct);
1293 }
1294 
1296 {
1297  return p_struct;
1298 }
1299 
1301 {
1302  return const_cast<alglib_impl::dfreport*>(p_struct);
1303 }
1304 dfreport::dfreport() : _dfreport_owner() ,relclserror(p_struct->relclserror),avgce(p_struct->avgce),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),oobrelclserror(p_struct->oobrelclserror),oobavgce(p_struct->oobavgce),oobrmserror(p_struct->oobrmserror),oobavgerror(p_struct->oobavgerror),oobavgrelerror(p_struct->oobavgrelerror)
1305 {
1306 }
1307 
1309 {
1310 }
1311 
1313 {
1314  if( this==&rhs )
1315  return *this;
1317  return *this;
1318 }
1319 
1321 {
1322 }
1323 
1324 
1325 /*************************************************************************
1326 This function serializes data structure to string.
1327 
1328 Important properties of s_out:
1329 * it contains alphanumeric characters, dots, underscores, minus signs
1330 * these symbols are grouped into words, which are separated by spaces
1331  and Windows-style (CR+LF) newlines
1332 * although serializer uses spaces and CR+LF as separators, you can
1333  replace any separator character by arbitrary combination of spaces,
1334  tabs, Windows or Unix newlines. It allows flexible reformatting of
1335  the string in case you want to include it into text or XML file.
1336  But you should not insert separators into the middle of the "words"
1337  nor you should change case of letters.
1338 * s_out can be freely moved between 32-bit and 64-bit systems, little
1339  and big endian machines, and so on. You can serialize structure on
1340  32-bit machine and unserialize it on 64-bit one (or vice versa), or
1341  serialize it on SPARC and unserialize on x86. You can also
1342  serialize it in C++ version of ALGLIB and unserialize in C# one,
1343  and vice versa.
1344 *************************************************************************/
1345 void dfserialize(decisionforest &obj, std::string &s_out)
1346 {
1347  alglib_impl::ae_state state;
1348  alglib_impl::ae_serializer serializer;
1349  alglib_impl::ae_int_t ssize;
1350 
1352  try
1353  {
1354  alglib_impl::ae_serializer_init(&serializer);
1356  alglib_impl::dfalloc(&serializer, obj.c_ptr(), &state);
1357  ssize = alglib_impl::ae_serializer_get_alloc_size(&serializer);
1358  s_out.clear();
1359  s_out.reserve((size_t)(ssize+1));
1360  alglib_impl::ae_serializer_sstart_str(&serializer, &s_out);
1361  alglib_impl::dfserialize(&serializer, obj.c_ptr(), &state);
1362  alglib_impl::ae_serializer_stop(&serializer);
1363  if( s_out.length()>(size_t)ssize )
1364  throw ap_error("ALGLIB: serialization integrity error");
1365  alglib_impl::ae_serializer_clear(&serializer);
1367  }
1369  {
1370  throw ap_error(state.error_msg);
1371  }
1372 }
1373 /*************************************************************************
1374 This function unserializes data structure from string.
1375 *************************************************************************/
1376 void dfunserialize(std::string &s_in, decisionforest &obj)
1377 {
1378  alglib_impl::ae_state state;
1379  alglib_impl::ae_serializer serializer;
1380 
1382  try
1383  {
1384  alglib_impl::ae_serializer_init(&serializer);
1385  alglib_impl::ae_serializer_ustart_str(&serializer, &s_in);
1386  alglib_impl::dfunserialize(&serializer, obj.c_ptr(), &state);
1387  alglib_impl::ae_serializer_stop(&serializer);
1388  alglib_impl::ae_serializer_clear(&serializer);
1390  }
1392  {
1393  throw ap_error(state.error_msg);
1394  }
1395 }
1396 
1397 /*************************************************************************
1398 This subroutine builds random decision forest.
1399 
1400 INPUT PARAMETERS:
1401  XY - training set
1402  NPoints - training set size, NPoints>=1
1403  NVars - number of independent variables, NVars>=1
1404  NClasses - task type:
1405  * NClasses=1 - regression task with one
1406  dependent variable
1407  * NClasses>1 - classification task with
1408  NClasses classes.
1409  NTrees - number of trees in a forest, NTrees>=1.
1410  recommended values: 50-100.
1411  R - percent of a training set used to build
1412  individual trees. 0<R<=1.
1413  recommended values: 0.1 <= R <= 0.66.
1414 
1415 OUTPUT PARAMETERS:
1416  Info - return code:
1417  * -2, if there is a point with class number
1418  outside of [0..NClasses-1].
1419  * -1, if incorrect parameters was passed
1420  (NPoints<1, NVars<1, NClasses<1, NTrees<1, R<=0
1421  or R>1).
1422  * 1, if task has been solved
1423  DF - model built
1424  Rep - training report, contains error on a training set
1425  and out-of-bag estimates of generalization error.
1426 
1427  -- ALGLIB --
1428  Copyright 19.02.2009 by Bochkanov Sergey
1429 *************************************************************************/
1430 void dfbuildrandomdecisionforest(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nclasses, const ae_int_t ntrees, const double r, ae_int_t &info, decisionforest &df, dfreport &rep)
1431 {
1432  alglib_impl::ae_state _alglib_env_state;
1433  alglib_impl::ae_state_init(&_alglib_env_state);
1434  try
1435  {
1436  alglib_impl::dfbuildrandomdecisionforest(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, nvars, nclasses, ntrees, r, &info, const_cast<alglib_impl::decisionforest*>(df.c_ptr()), const_cast<alglib_impl::dfreport*>(rep.c_ptr()), &_alglib_env_state);
1437  alglib_impl::ae_state_clear(&_alglib_env_state);
1438  return;
1439  }
1441  {
1442  throw ap_error(_alglib_env_state.error_msg);
1443  }
1444 }
1445 
1446 /*************************************************************************
1447 This subroutine builds random decision forest.
1448 This function gives ability to tune number of variables used when choosing
1449 best split.
1450 
1451 INPUT PARAMETERS:
1452  XY - training set
1453  NPoints - training set size, NPoints>=1
1454  NVars - number of independent variables, NVars>=1
1455  NClasses - task type:
1456  * NClasses=1 - regression task with one
1457  dependent variable
1458  * NClasses>1 - classification task with
1459  NClasses classes.
1460  NTrees - number of trees in a forest, NTrees>=1.
1461  recommended values: 50-100.
1462  NRndVars - number of variables used when choosing best split
1463  R - percent of a training set used to build
1464  individual trees. 0<R<=1.
1465  recommended values: 0.1 <= R <= 0.66.
1466 
1467 OUTPUT PARAMETERS:
1468  Info - return code:
1469  * -2, if there is a point with class number
1470  outside of [0..NClasses-1].
1471  * -1, if incorrect parameters was passed
1472  (NPoints<1, NVars<1, NClasses<1, NTrees<1, R<=0
1473  or R>1).
1474  * 1, if task has been solved
1475  DF - model built
1476  Rep - training report, contains error on a training set
1477  and out-of-bag estimates of generalization error.
1478 
1479  -- ALGLIB --
1480  Copyright 19.02.2009 by Bochkanov Sergey
1481 *************************************************************************/
1482 void dfbuildrandomdecisionforestx1(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nclasses, const ae_int_t ntrees, const ae_int_t nrndvars, const double r, ae_int_t &info, decisionforest &df, dfreport &rep)
1483 {
1484  alglib_impl::ae_state _alglib_env_state;
1485  alglib_impl::ae_state_init(&_alglib_env_state);
1486  try
1487  {
1488  alglib_impl::dfbuildrandomdecisionforestx1(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, nvars, nclasses, ntrees, nrndvars, r, &info, const_cast<alglib_impl::decisionforest*>(df.c_ptr()), const_cast<alglib_impl::dfreport*>(rep.c_ptr()), &_alglib_env_state);
1489  alglib_impl::ae_state_clear(&_alglib_env_state);
1490  return;
1491  }
1493  {
1494  throw ap_error(_alglib_env_state.error_msg);
1495  }
1496 }
1497 
1498 /*************************************************************************
1499 Procesing
1500 
1501 INPUT PARAMETERS:
1502  DF - decision forest model
1503  X - input vector, array[0..NVars-1].
1504 
1505 OUTPUT PARAMETERS:
1506  Y - result. Regression estimate when solving regression task,
1507  vector of posterior probabilities for classification task.
1508 
1509 See also DFProcessI.
1510 
1511  -- ALGLIB --
1512  Copyright 16.02.2009 by Bochkanov Sergey
1513 *************************************************************************/
1515 {
1516  alglib_impl::ae_state _alglib_env_state;
1517  alglib_impl::ae_state_init(&_alglib_env_state);
1518  try
1519  {
1520  alglib_impl::dfprocess(const_cast<alglib_impl::decisionforest*>(df.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), &_alglib_env_state);
1521  alglib_impl::ae_state_clear(&_alglib_env_state);
1522  return;
1523  }
1525  {
1526  throw ap_error(_alglib_env_state.error_msg);
1527  }
1528 }
1529 
1530 /*************************************************************************
1531 'interactive' variant of DFProcess for languages like Python which support
1532 constructs like "Y = DFProcessI(DF,X)" and interactive mode of interpreter
1533 
1534 This function allocates new array on each call, so it is significantly
1535 slower than its 'non-interactive' counterpart, but it is more convenient
1536 when you call it from command line.
1537 
1538  -- ALGLIB --
1539  Copyright 28.02.2010 by Bochkanov Sergey
1540 *************************************************************************/
1542 {
1543  alglib_impl::ae_state _alglib_env_state;
1544  alglib_impl::ae_state_init(&_alglib_env_state);
1545  try
1546  {
1547  alglib_impl::dfprocessi(const_cast<alglib_impl::decisionforest*>(df.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), &_alglib_env_state);
1548  alglib_impl::ae_state_clear(&_alglib_env_state);
1549  return;
1550  }
1552  {
1553  throw ap_error(_alglib_env_state.error_msg);
1554  }
1555 }
1556 
1557 /*************************************************************************
1558 Relative classification error on the test set
1559 
1560 INPUT PARAMETERS:
1561  DF - decision forest model
1562  XY - test set
1563  NPoints - test set size
1564 
1565 RESULT:
1566  percent of incorrectly classified cases.
1567  Zero if model solves regression task.
1568 
1569  -- ALGLIB --
1570  Copyright 16.02.2009 by Bochkanov Sergey
1571 *************************************************************************/
1572 double dfrelclserror(const decisionforest &df, const real_2d_array &xy, const ae_int_t npoints)
1573 {
1574  alglib_impl::ae_state _alglib_env_state;
1575  alglib_impl::ae_state_init(&_alglib_env_state);
1576  try
1577  {
1578  double result = alglib_impl::dfrelclserror(const_cast<alglib_impl::decisionforest*>(df.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
1579  alglib_impl::ae_state_clear(&_alglib_env_state);
1580  return *(reinterpret_cast<double*>(&result));
1581  }
1583  {
1584  throw ap_error(_alglib_env_state.error_msg);
1585  }
1586 }
1587 
1588 /*************************************************************************
1589 Average cross-entropy (in bits per element) on the test set
1590 
1591 INPUT PARAMETERS:
1592  DF - decision forest model
1593  XY - test set
1594  NPoints - test set size
1595 
1596 RESULT:
1597  CrossEntropy/(NPoints*LN(2)).
1598  Zero if model solves regression task.
1599 
1600  -- ALGLIB --
1601  Copyright 16.02.2009 by Bochkanov Sergey
1602 *************************************************************************/
1603 double dfavgce(const decisionforest &df, const real_2d_array &xy, const ae_int_t npoints)
1604 {
1605  alglib_impl::ae_state _alglib_env_state;
1606  alglib_impl::ae_state_init(&_alglib_env_state);
1607  try
1608  {
1609  double result = alglib_impl::dfavgce(const_cast<alglib_impl::decisionforest*>(df.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
1610  alglib_impl::ae_state_clear(&_alglib_env_state);
1611  return *(reinterpret_cast<double*>(&result));
1612  }
1614  {
1615  throw ap_error(_alglib_env_state.error_msg);
1616  }
1617 }
1618 
1619 /*************************************************************************
1620 RMS error on the test set
1621 
1622 INPUT PARAMETERS:
1623  DF - decision forest model
1624  XY - test set
1625  NPoints - test set size
1626 
1627 RESULT:
1628  root mean square error.
1629  Its meaning for regression task is obvious. As for
1630  classification task, RMS error means error when estimating posterior
1631  probabilities.
1632 
1633  -- ALGLIB --
1634  Copyright 16.02.2009 by Bochkanov Sergey
1635 *************************************************************************/
1636 double dfrmserror(const decisionforest &df, const real_2d_array &xy, const ae_int_t npoints)
1637 {
1638  alglib_impl::ae_state _alglib_env_state;
1639  alglib_impl::ae_state_init(&_alglib_env_state);
1640  try
1641  {
1642  double result = alglib_impl::dfrmserror(const_cast<alglib_impl::decisionforest*>(df.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
1643  alglib_impl::ae_state_clear(&_alglib_env_state);
1644  return *(reinterpret_cast<double*>(&result));
1645  }
1647  {
1648  throw ap_error(_alglib_env_state.error_msg);
1649  }
1650 }
1651 
1652 /*************************************************************************
1653 Average error on the test set
1654 
1655 INPUT PARAMETERS:
1656  DF - decision forest model
1657  XY - test set
1658  NPoints - test set size
1659 
1660 RESULT:
1661  Its meaning for regression task is obvious. As for
1662  classification task, it means average error when estimating posterior
1663  probabilities.
1664 
1665  -- ALGLIB --
1666  Copyright 16.02.2009 by Bochkanov Sergey
1667 *************************************************************************/
1668 double dfavgerror(const decisionforest &df, const real_2d_array &xy, const ae_int_t npoints)
1669 {
1670  alglib_impl::ae_state _alglib_env_state;
1671  alglib_impl::ae_state_init(&_alglib_env_state);
1672  try
1673  {
1674  double result = alglib_impl::dfavgerror(const_cast<alglib_impl::decisionforest*>(df.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
1675  alglib_impl::ae_state_clear(&_alglib_env_state);
1676  return *(reinterpret_cast<double*>(&result));
1677  }
1679  {
1680  throw ap_error(_alglib_env_state.error_msg);
1681  }
1682 }
1683 
1684 /*************************************************************************
1685 Average relative error on the test set
1686 
1687 INPUT PARAMETERS:
1688  DF - decision forest model
1689  XY - test set
1690  NPoints - test set size
1691 
1692 RESULT:
1693  Its meaning for regression task is obvious. As for
1694  classification task, it means average relative error when estimating
1695  posterior probability of belonging to the correct class.
1696 
1697  -- ALGLIB --
1698  Copyright 16.02.2009 by Bochkanov Sergey
1699 *************************************************************************/
1700 double dfavgrelerror(const decisionforest &df, const real_2d_array &xy, const ae_int_t npoints)
1701 {
1702  alglib_impl::ae_state _alglib_env_state;
1703  alglib_impl::ae_state_init(&_alglib_env_state);
1704  try
1705  {
1706  double result = alglib_impl::dfavgrelerror(const_cast<alglib_impl::decisionforest*>(df.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
1707  alglib_impl::ae_state_clear(&_alglib_env_state);
1708  return *(reinterpret_cast<double*>(&result));
1709  }
1711  {
1712  throw ap_error(_alglib_env_state.error_msg);
1713  }
1714 }
1715 
1716 /*************************************************************************
1717 
1718 *************************************************************************/
1720 {
1722  if( p_struct==NULL )
1723  throw ap_error("ALGLIB: malloc error");
1725  throw ap_error("ALGLIB: malloc error");
1726 }
1727 
1729 {
1731  if( p_struct==NULL )
1732  throw ap_error("ALGLIB: malloc error");
1733  if( !alglib_impl::_linearmodel_init_copy(p_struct, const_cast<alglib_impl::linearmodel*>(rhs.p_struct), NULL, ae_false) )
1734  throw ap_error("ALGLIB: malloc error");
1735 }
1736 
1738 {
1739  if( this==&rhs )
1740  return *this;
1742  if( !alglib_impl::_linearmodel_init_copy(p_struct, const_cast<alglib_impl::linearmodel*>(rhs.p_struct), NULL, ae_false) )
1743  throw ap_error("ALGLIB: malloc error");
1744  return *this;
1745 }
1746 
1748 {
1750  ae_free(p_struct);
1751 }
1752 
1754 {
1755  return p_struct;
1756 }
1757 
1759 {
1760  return const_cast<alglib_impl::linearmodel*>(p_struct);
1761 }
1763 {
1764 }
1765 
1767 {
1768 }
1769 
1771 {
1772  if( this==&rhs )
1773  return *this;
1775  return *this;
1776 }
1777 
1779 {
1780 }
1781 
1782 
1783 /*************************************************************************
1784 LRReport structure contains additional information about linear model:
1785 * C - covariation matrix, array[0..NVars,0..NVars].
1786  C[i,j] = Cov(A[i],A[j])
1787 * RMSError - root mean square error on a training set
1788 * AvgError - average error on a training set
1789 * AvgRelError - average relative error on a training set (excluding
1790  observations with zero function value).
1791 * CVRMSError - leave-one-out cross-validation estimate of
1792  generalization error. Calculated using fast algorithm
1793  with O(NVars*NPoints) complexity.
1794 * CVAvgError - cross-validation estimate of average error
1795 * CVAvgRelError - cross-validation estimate of average relative error
1796 
1797 All other fields of the structure are intended for internal use and should
1798 not be used outside ALGLIB.
1799 *************************************************************************/
1801 {
1803  if( p_struct==NULL )
1804  throw ap_error("ALGLIB: malloc error");
1806  throw ap_error("ALGLIB: malloc error");
1807 }
1808 
1810 {
1812  if( p_struct==NULL )
1813  throw ap_error("ALGLIB: malloc error");
1814  if( !alglib_impl::_lrreport_init_copy(p_struct, const_cast<alglib_impl::lrreport*>(rhs.p_struct), NULL, ae_false) )
1815  throw ap_error("ALGLIB: malloc error");
1816 }
1817 
1819 {
1820  if( this==&rhs )
1821  return *this;
1823  if( !alglib_impl::_lrreport_init_copy(p_struct, const_cast<alglib_impl::lrreport*>(rhs.p_struct), NULL, ae_false) )
1824  throw ap_error("ALGLIB: malloc error");
1825  return *this;
1826 }
1827 
1829 {
1831  ae_free(p_struct);
1832 }
1833 
1835 {
1836  return p_struct;
1837 }
1838 
1840 {
1841  return const_cast<alglib_impl::lrreport*>(p_struct);
1842 }
1843 lrreport::lrreport() : _lrreport_owner() ,c(&p_struct->c),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),cvrmserror(p_struct->cvrmserror),cvavgerror(p_struct->cvavgerror),cvavgrelerror(p_struct->cvavgrelerror),ncvdefects(p_struct->ncvdefects),cvdefects(&p_struct->cvdefects)
1844 {
1845 }
1846 
1848 {
1849 }
1850 
1852 {
1853  if( this==&rhs )
1854  return *this;
1856  return *this;
1857 }
1858 
1860 {
1861 }
1862 
1863 /*************************************************************************
1864 Linear regression
1865 
1866 Subroutine builds model:
1867 
1868  Y = A(0)*X[0] + ... + A(N-1)*X[N-1] + A(N)
1869 
1870 and model found in ALGLIB format, covariation matrix, training set errors
1871 (rms, average, average relative) and leave-one-out cross-validation
1872 estimate of the generalization error. CV estimate calculated using fast
1873 algorithm with O(NPoints*NVars) complexity.
1874 
1875 When covariation matrix is calculated standard deviations of function
1876 values are assumed to be equal to RMS error on the training set.
1877 
1878 INPUT PARAMETERS:
1879  XY - training set, array [0..NPoints-1,0..NVars]:
1880  * NVars columns - independent variables
1881  * last column - dependent variable
1882  NPoints - training set size, NPoints>NVars+1
1883  NVars - number of independent variables
1884 
1885 OUTPUT PARAMETERS:
1886  Info - return code:
1887  * -255, in case of unknown internal error
1888  * -4, if internal SVD subroutine haven't converged
1889  * -1, if incorrect parameters was passed (NPoints<NVars+2, NVars<1).
1890  * 1, if subroutine successfully finished
1891  LM - linear model in the ALGLIB format. Use subroutines of
1892  this unit to work with the model.
1893  AR - additional results
1894 
1895 
1896  -- ALGLIB --
1897  Copyright 02.08.2008 by Bochkanov Sergey
1898 *************************************************************************/
1899 void lrbuild(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, ae_int_t &info, linearmodel &lm, lrreport &ar)
1900 {
1901  alglib_impl::ae_state _alglib_env_state;
1902  alglib_impl::ae_state_init(&_alglib_env_state);
1903  try
1904  {
1905  alglib_impl::lrbuild(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, nvars, &info, const_cast<alglib_impl::linearmodel*>(lm.c_ptr()), const_cast<alglib_impl::lrreport*>(ar.c_ptr()), &_alglib_env_state);
1906  alglib_impl::ae_state_clear(&_alglib_env_state);
1907  return;
1908  }
1910  {
1911  throw ap_error(_alglib_env_state.error_msg);
1912  }
1913 }
1914 
1915 /*************************************************************************
1916 Linear regression
1917 
1918 Variant of LRBuild which uses vector of standatd deviations (errors in
1919 function values).
1920 
1921 INPUT PARAMETERS:
1922  XY - training set, array [0..NPoints-1,0..NVars]:
1923  * NVars columns - independent variables
1924  * last column - dependent variable
1925  S - standard deviations (errors in function values)
1926  array[0..NPoints-1], S[i]>0.
1927  NPoints - training set size, NPoints>NVars+1
1928  NVars - number of independent variables
1929 
1930 OUTPUT PARAMETERS:
1931  Info - return code:
1932  * -255, in case of unknown internal error
1933  * -4, if internal SVD subroutine haven't converged
1934  * -1, if incorrect parameters was passed (NPoints<NVars+2, NVars<1).
1935  * -2, if S[I]<=0
1936  * 1, if subroutine successfully finished
1937  LM - linear model in the ALGLIB format. Use subroutines of
1938  this unit to work with the model.
1939  AR - additional results
1940 
1941 
1942  -- ALGLIB --
1943  Copyright 02.08.2008 by Bochkanov Sergey
1944 *************************************************************************/
1945 void lrbuilds(const real_2d_array &xy, const real_1d_array &s, const ae_int_t npoints, const ae_int_t nvars, ae_int_t &info, linearmodel &lm, lrreport &ar)
1946 {
1947  alglib_impl::ae_state _alglib_env_state;
1948  alglib_impl::ae_state_init(&_alglib_env_state);
1949  try
1950  {
1951  alglib_impl::lrbuilds(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), const_cast<alglib_impl::ae_vector*>(s.c_ptr()), npoints, nvars, &info, const_cast<alglib_impl::linearmodel*>(lm.c_ptr()), const_cast<alglib_impl::lrreport*>(ar.c_ptr()), &_alglib_env_state);
1952  alglib_impl::ae_state_clear(&_alglib_env_state);
1953  return;
1954  }
1956  {
1957  throw ap_error(_alglib_env_state.error_msg);
1958  }
1959 }
1960 
1961 /*************************************************************************
1962 Like LRBuildS, but builds model
1963 
1964  Y = A(0)*X[0] + ... + A(N-1)*X[N-1]
1965 
1966 i.e. with zero constant term.
1967 
1968  -- ALGLIB --
1969  Copyright 30.10.2008 by Bochkanov Sergey
1970 *************************************************************************/
1971 void lrbuildzs(const real_2d_array &xy, const real_1d_array &s, const ae_int_t npoints, const ae_int_t nvars, ae_int_t &info, linearmodel &lm, lrreport &ar)
1972 {
1973  alglib_impl::ae_state _alglib_env_state;
1974  alglib_impl::ae_state_init(&_alglib_env_state);
1975  try
1976  {
1977  alglib_impl::lrbuildzs(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), const_cast<alglib_impl::ae_vector*>(s.c_ptr()), npoints, nvars, &info, const_cast<alglib_impl::linearmodel*>(lm.c_ptr()), const_cast<alglib_impl::lrreport*>(ar.c_ptr()), &_alglib_env_state);
1978  alglib_impl::ae_state_clear(&_alglib_env_state);
1979  return;
1980  }
1982  {
1983  throw ap_error(_alglib_env_state.error_msg);
1984  }
1985 }
1986 
1987 /*************************************************************************
1988 Like LRBuild but builds model
1989 
1990  Y = A(0)*X[0] + ... + A(N-1)*X[N-1]
1991 
1992 i.e. with zero constant term.
1993 
1994  -- ALGLIB --
1995  Copyright 30.10.2008 by Bochkanov Sergey
1996 *************************************************************************/
1997 void lrbuildz(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, ae_int_t &info, linearmodel &lm, lrreport &ar)
1998 {
1999  alglib_impl::ae_state _alglib_env_state;
2000  alglib_impl::ae_state_init(&_alglib_env_state);
2001  try
2002  {
2003  alglib_impl::lrbuildz(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, nvars, &info, const_cast<alglib_impl::linearmodel*>(lm.c_ptr()), const_cast<alglib_impl::lrreport*>(ar.c_ptr()), &_alglib_env_state);
2004  alglib_impl::ae_state_clear(&_alglib_env_state);
2005  return;
2006  }
2008  {
2009  throw ap_error(_alglib_env_state.error_msg);
2010  }
2011 }
2012 
2013 /*************************************************************************
2014 Unpacks coefficients of linear model.
2015 
2016 INPUT PARAMETERS:
2017  LM - linear model in ALGLIB format
2018 
2019 OUTPUT PARAMETERS:
2020  V - coefficients, array[0..NVars]
2021  constant term (intercept) is stored in the V[NVars].
2022  NVars - number of independent variables (one less than number
2023  of coefficients)
2024 
2025  -- ALGLIB --
2026  Copyright 30.08.2008 by Bochkanov Sergey
2027 *************************************************************************/
2028 void lrunpack(const linearmodel &lm, real_1d_array &v, ae_int_t &nvars)
2029 {
2030  alglib_impl::ae_state _alglib_env_state;
2031  alglib_impl::ae_state_init(&_alglib_env_state);
2032  try
2033  {
2034  alglib_impl::lrunpack(const_cast<alglib_impl::linearmodel*>(lm.c_ptr()), const_cast<alglib_impl::ae_vector*>(v.c_ptr()), &nvars, &_alglib_env_state);
2035  alglib_impl::ae_state_clear(&_alglib_env_state);
2036  return;
2037  }
2039  {
2040  throw ap_error(_alglib_env_state.error_msg);
2041  }
2042 }
2043 
2044 /*************************************************************************
2045 "Packs" coefficients and creates linear model in ALGLIB format (LRUnpack
2046 reversed).
2047 
2048 INPUT PARAMETERS:
2049  V - coefficients, array[0..NVars]
2050  NVars - number of independent variables
2051 
2052 OUTPUT PAREMETERS:
2053  LM - linear model.
2054 
2055  -- ALGLIB --
2056  Copyright 30.08.2008 by Bochkanov Sergey
2057 *************************************************************************/
2058 void lrpack(const real_1d_array &v, const ae_int_t nvars, linearmodel &lm)
2059 {
2060  alglib_impl::ae_state _alglib_env_state;
2061  alglib_impl::ae_state_init(&_alglib_env_state);
2062  try
2063  {
2064  alglib_impl::lrpack(const_cast<alglib_impl::ae_vector*>(v.c_ptr()), nvars, const_cast<alglib_impl::linearmodel*>(lm.c_ptr()), &_alglib_env_state);
2065  alglib_impl::ae_state_clear(&_alglib_env_state);
2066  return;
2067  }
2069  {
2070  throw ap_error(_alglib_env_state.error_msg);
2071  }
2072 }
2073 
2074 /*************************************************************************
2075 Procesing
2076 
2077 INPUT PARAMETERS:
2078  LM - linear model
2079  X - input vector, array[0..NVars-1].
2080 
2081 Result:
2082  value of linear model regression estimate
2083 
2084  -- ALGLIB --
2085  Copyright 03.09.2008 by Bochkanov Sergey
2086 *************************************************************************/
2087 double lrprocess(const linearmodel &lm, const real_1d_array &x)
2088 {
2089  alglib_impl::ae_state _alglib_env_state;
2090  alglib_impl::ae_state_init(&_alglib_env_state);
2091  try
2092  {
2093  double result = alglib_impl::lrprocess(const_cast<alglib_impl::linearmodel*>(lm.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
2094  alglib_impl::ae_state_clear(&_alglib_env_state);
2095  return *(reinterpret_cast<double*>(&result));
2096  }
2098  {
2099  throw ap_error(_alglib_env_state.error_msg);
2100  }
2101 }
2102 
2103 /*************************************************************************
2104 RMS error on the test set
2105 
2106 INPUT PARAMETERS:
2107  LM - linear model
2108  XY - test set
2109  NPoints - test set size
2110 
2111 RESULT:
2112  root mean square error.
2113 
2114  -- ALGLIB --
2115  Copyright 30.08.2008 by Bochkanov Sergey
2116 *************************************************************************/
2117 double lrrmserror(const linearmodel &lm, const real_2d_array &xy, const ae_int_t npoints)
2118 {
2119  alglib_impl::ae_state _alglib_env_state;
2120  alglib_impl::ae_state_init(&_alglib_env_state);
2121  try
2122  {
2123  double result = alglib_impl::lrrmserror(const_cast<alglib_impl::linearmodel*>(lm.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
2124  alglib_impl::ae_state_clear(&_alglib_env_state);
2125  return *(reinterpret_cast<double*>(&result));
2126  }
2128  {
2129  throw ap_error(_alglib_env_state.error_msg);
2130  }
2131 }
2132 
2133 /*************************************************************************
2134 Average error on the test set
2135 
2136 INPUT PARAMETERS:
2137  LM - linear model
2138  XY - test set
2139  NPoints - test set size
2140 
2141 RESULT:
2142  average error.
2143 
2144  -- ALGLIB --
2145  Copyright 30.08.2008 by Bochkanov Sergey
2146 *************************************************************************/
2147 double lravgerror(const linearmodel &lm, const real_2d_array &xy, const ae_int_t npoints)
2148 {
2149  alglib_impl::ae_state _alglib_env_state;
2150  alglib_impl::ae_state_init(&_alglib_env_state);
2151  try
2152  {
2153  double result = alglib_impl::lravgerror(const_cast<alglib_impl::linearmodel*>(lm.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
2154  alglib_impl::ae_state_clear(&_alglib_env_state);
2155  return *(reinterpret_cast<double*>(&result));
2156  }
2158  {
2159  throw ap_error(_alglib_env_state.error_msg);
2160  }
2161 }
2162 
2163 /*************************************************************************
2164 RMS error on the test set
2165 
2166 INPUT PARAMETERS:
2167  LM - linear model
2168  XY - test set
2169  NPoints - test set size
2170 
2171 RESULT:
2172  average relative error.
2173 
2174  -- ALGLIB --
2175  Copyright 30.08.2008 by Bochkanov Sergey
2176 *************************************************************************/
2177 double lravgrelerror(const linearmodel &lm, const real_2d_array &xy, const ae_int_t npoints)
2178 {
2179  alglib_impl::ae_state _alglib_env_state;
2180  alglib_impl::ae_state_init(&_alglib_env_state);
2181  try
2182  {
2183  double result = alglib_impl::lravgrelerror(const_cast<alglib_impl::linearmodel*>(lm.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
2184  alglib_impl::ae_state_clear(&_alglib_env_state);
2185  return *(reinterpret_cast<double*>(&result));
2186  }
2188  {
2189  throw ap_error(_alglib_env_state.error_msg);
2190  }
2191 }
2192 
2193 /*************************************************************************
2194 Filters: simple moving averages (unsymmetric).
2195 
2196 This filter replaces array by results of SMA(K) filter. SMA(K) is defined
2197 as filter which averages at most K previous points (previous - not points
2198 AROUND central point) - or less, in case of the first K-1 points.
2199 
2200 INPUT PARAMETERS:
2201  X - array[N], array to process. It can be larger than N,
2202  in this case only first N points are processed.
2203  N - points count, N>=0
2204  K - K>=1 (K can be larger than N , such cases will be
2205  correctly handled). Window width. K=1 corresponds to
2206  identity transformation (nothing changes).
2207 
2208 OUTPUT PARAMETERS:
2209  X - array, whose first N elements were processed with SMA(K)
2210 
2211 NOTE 1: this function uses efficient in-place algorithm which does not
2212  allocate temporary arrays.
2213 
2214 NOTE 2: this algorithm makes only one pass through array and uses running
2215  sum to speed-up calculation of the averages. Additional measures
2216  are taken to ensure that running sum on a long sequence of zero
2217  elements will be correctly reset to zero even in the presence of
2218  round-off error.
2219 
2220 NOTE 3: this is unsymmetric version of the algorithm, which does NOT
2221  averages points after the current one. Only X[i], X[i-1], ... are
2222  used when calculating new value of X[i]. We should also note that
2223  this algorithm uses BOTH previous points and current one, i.e.
2224  new value of X[i] depends on BOTH previous point and X[i] itself.
2225 
2226  -- ALGLIB --
2227  Copyright 25.10.2011 by Bochkanov Sergey
2228 *************************************************************************/
2230 {
2231  alglib_impl::ae_state _alglib_env_state;
2232  alglib_impl::ae_state_init(&_alglib_env_state);
2233  try
2234  {
2235  alglib_impl::filtersma(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), n, k, &_alglib_env_state);
2236  alglib_impl::ae_state_clear(&_alglib_env_state);
2237  return;
2238  }
2240  {
2241  throw ap_error(_alglib_env_state.error_msg);
2242  }
2243 }
2244 
2245 /*************************************************************************
2246 Filters: simple moving averages (unsymmetric).
2247 
2248 This filter replaces array by results of SMA(K) filter. SMA(K) is defined
2249 as filter which averages at most K previous points (previous - not points
2250 AROUND central point) - or less, in case of the first K-1 points.
2251 
2252 INPUT PARAMETERS:
2253  X - array[N], array to process. It can be larger than N,
2254  in this case only first N points are processed.
2255  N - points count, N>=0
2256  K - K>=1 (K can be larger than N , such cases will be
2257  correctly handled). Window width. K=1 corresponds to
2258  identity transformation (nothing changes).
2259 
2260 OUTPUT PARAMETERS:
2261  X - array, whose first N elements were processed with SMA(K)
2262 
2263 NOTE 1: this function uses efficient in-place algorithm which does not
2264  allocate temporary arrays.
2265 
2266 NOTE 2: this algorithm makes only one pass through array and uses running
2267  sum to speed-up calculation of the averages. Additional measures
2268  are taken to ensure that running sum on a long sequence of zero
2269  elements will be correctly reset to zero even in the presence of
2270  round-off error.
2271 
2272 NOTE 3: this is unsymmetric version of the algorithm, which does NOT
2273  averages points after the current one. Only X[i], X[i-1], ... are
2274  used when calculating new value of X[i]. We should also note that
2275  this algorithm uses BOTH previous points and current one, i.e.
2276  new value of X[i] depends on BOTH previous point and X[i] itself.
2277 
2278  -- ALGLIB --
2279  Copyright 25.10.2011 by Bochkanov Sergey
2280 *************************************************************************/
2282 {
2283  alglib_impl::ae_state _alglib_env_state;
2284  ae_int_t n;
2285 
2286  n = x.length();
2287  alglib_impl::ae_state_init(&_alglib_env_state);
2288  try
2289  {
2290  alglib_impl::filtersma(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), n, k, &_alglib_env_state);
2291 
2292  alglib_impl::ae_state_clear(&_alglib_env_state);
2293  return;
2294  }
2296  {
2297  throw ap_error(_alglib_env_state.error_msg);
2298  }
2299 }
2300 
2301 /*************************************************************************
2302 Filters: exponential moving averages.
2303 
2304 This filter replaces array by results of EMA(alpha) filter. EMA(alpha) is
2305 defined as filter which replaces X[] by S[]:
2306  S[0] = X[0]
2307  S[t] = alpha*X[t] + (1-alpha)*S[t-1]
2308 
2309 INPUT PARAMETERS:
2310  X - array[N], array to process. It can be larger than N,
2311  in this case only first N points are processed.
2312  N - points count, N>=0
2313  alpha - 0<alpha<=1, smoothing parameter.
2314 
2315 OUTPUT PARAMETERS:
2316  X - array, whose first N elements were processed
2317  with EMA(alpha)
2318 
2319 NOTE 1: this function uses efficient in-place algorithm which does not
2320  allocate temporary arrays.
2321 
2322 NOTE 2: this algorithm uses BOTH previous points and current one, i.e.
2323  new value of X[i] depends on BOTH previous point and X[i] itself.
2324 
2325 NOTE 3: technical analytis users quite often work with EMA coefficient
2326  expressed in DAYS instead of fractions. If you want to calculate
2327  EMA(N), where N is a number of days, you can use alpha=2/(N+1).
2328 
2329  -- ALGLIB --
2330  Copyright 25.10.2011 by Bochkanov Sergey
2331 *************************************************************************/
2332 void filterema(real_1d_array &x, const ae_int_t n, const double alpha)
2333 {
2334  alglib_impl::ae_state _alglib_env_state;
2335  alglib_impl::ae_state_init(&_alglib_env_state);
2336  try
2337  {
2338  alglib_impl::filterema(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), n, alpha, &_alglib_env_state);
2339  alglib_impl::ae_state_clear(&_alglib_env_state);
2340  return;
2341  }
2343  {
2344  throw ap_error(_alglib_env_state.error_msg);
2345  }
2346 }
2347 
2348 /*************************************************************************
2349 Filters: exponential moving averages.
2350 
2351 This filter replaces array by results of EMA(alpha) filter. EMA(alpha) is
2352 defined as filter which replaces X[] by S[]:
2353  S[0] = X[0]
2354  S[t] = alpha*X[t] + (1-alpha)*S[t-1]
2355 
2356 INPUT PARAMETERS:
2357  X - array[N], array to process. It can be larger than N,
2358  in this case only first N points are processed.
2359  N - points count, N>=0
2360  alpha - 0<alpha<=1, smoothing parameter.
2361 
2362 OUTPUT PARAMETERS:
2363  X - array, whose first N elements were processed
2364  with EMA(alpha)
2365 
2366 NOTE 1: this function uses efficient in-place algorithm which does not
2367  allocate temporary arrays.
2368 
2369 NOTE 2: this algorithm uses BOTH previous points and current one, i.e.
2370  new value of X[i] depends on BOTH previous point and X[i] itself.
2371 
2372 NOTE 3: technical analytis users quite often work with EMA coefficient
2373  expressed in DAYS instead of fractions. If you want to calculate
2374  EMA(N), where N is a number of days, you can use alpha=2/(N+1).
2375 
2376  -- ALGLIB --
2377  Copyright 25.10.2011 by Bochkanov Sergey
2378 *************************************************************************/
2379 void filterema(real_1d_array &x, const double alpha)
2380 {
2381  alglib_impl::ae_state _alglib_env_state;
2382  ae_int_t n;
2383 
2384  n = x.length();
2385  alglib_impl::ae_state_init(&_alglib_env_state);
2386  try
2387  {
2388  alglib_impl::filterema(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), n, alpha, &_alglib_env_state);
2389 
2390  alglib_impl::ae_state_clear(&_alglib_env_state);
2391  return;
2392  }
2394  {
2395  throw ap_error(_alglib_env_state.error_msg);
2396  }
2397 }
2398 
2399 /*************************************************************************
2400 Filters: linear regression moving averages.
2401 
2402 This filter replaces array by results of LRMA(K) filter.
2403 
2404 LRMA(K) is defined as filter which, for each data point, builds linear
2405 regression model using K prevous points (point itself is included in
2406 these K points) and calculates value of this linear model at the point in
2407 question.
2408 
2409 INPUT PARAMETERS:
2410  X - array[N], array to process. It can be larger than N,
2411  in this case only first N points are processed.
2412  N - points count, N>=0
2413  K - K>=1 (K can be larger than N , such cases will be
2414  correctly handled). Window width. K=1 corresponds to
2415  identity transformation (nothing changes).
2416 
2417 OUTPUT PARAMETERS:
2418  X - array, whose first N elements were processed with SMA(K)
2419 
2420 NOTE 1: this function uses efficient in-place algorithm which does not
2421  allocate temporary arrays.
2422 
2423 NOTE 2: this algorithm makes only one pass through array and uses running
2424  sum to speed-up calculation of the averages. Additional measures
2425  are taken to ensure that running sum on a long sequence of zero
2426  elements will be correctly reset to zero even in the presence of
2427  round-off error.
2428 
2429 NOTE 3: this is unsymmetric version of the algorithm, which does NOT
2430  averages points after the current one. Only X[i], X[i-1], ... are
2431  used when calculating new value of X[i]. We should also note that
2432  this algorithm uses BOTH previous points and current one, i.e.
2433  new value of X[i] depends on BOTH previous point and X[i] itself.
2434 
2435  -- ALGLIB --
2436  Copyright 25.10.2011 by Bochkanov Sergey
2437 *************************************************************************/
2439 {
2440  alglib_impl::ae_state _alglib_env_state;
2441  alglib_impl::ae_state_init(&_alglib_env_state);
2442  try
2443  {
2444  alglib_impl::filterlrma(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), n, k, &_alglib_env_state);
2445  alglib_impl::ae_state_clear(&_alglib_env_state);
2446  return;
2447  }
2449  {
2450  throw ap_error(_alglib_env_state.error_msg);
2451  }
2452 }
2453 
2454 /*************************************************************************
2455 Filters: linear regression moving averages.
2456 
2457 This filter replaces array by results of LRMA(K) filter.
2458 
2459 LRMA(K) is defined as filter which, for each data point, builds linear
2460 regression model using K prevous points (point itself is included in
2461 these K points) and calculates value of this linear model at the point in
2462 question.
2463 
2464 INPUT PARAMETERS:
2465  X - array[N], array to process. It can be larger than N,
2466  in this case only first N points are processed.
2467  N - points count, N>=0
2468  K - K>=1 (K can be larger than N , such cases will be
2469  correctly handled). Window width. K=1 corresponds to
2470  identity transformation (nothing changes).
2471 
2472 OUTPUT PARAMETERS:
2473  X - array, whose first N elements were processed with SMA(K)
2474 
2475 NOTE 1: this function uses efficient in-place algorithm which does not
2476  allocate temporary arrays.
2477 
2478 NOTE 2: this algorithm makes only one pass through array and uses running
2479  sum to speed-up calculation of the averages. Additional measures
2480  are taken to ensure that running sum on a long sequence of zero
2481  elements will be correctly reset to zero even in the presence of
2482  round-off error.
2483 
2484 NOTE 3: this is unsymmetric version of the algorithm, which does NOT
2485  averages points after the current one. Only X[i], X[i-1], ... are
2486  used when calculating new value of X[i]. We should also note that
2487  this algorithm uses BOTH previous points and current one, i.e.
2488  new value of X[i] depends on BOTH previous point and X[i] itself.
2489 
2490  -- ALGLIB --
2491  Copyright 25.10.2011 by Bochkanov Sergey
2492 *************************************************************************/
2494 {
2495  alglib_impl::ae_state _alglib_env_state;
2496  ae_int_t n;
2497 
2498  n = x.length();
2499  alglib_impl::ae_state_init(&_alglib_env_state);
2500  try
2501  {
2502  alglib_impl::filterlrma(const_cast<alglib_impl::ae_vector*>(x.c_ptr()), n, k, &_alglib_env_state);
2503 
2504  alglib_impl::ae_state_clear(&_alglib_env_state);
2505  return;
2506  }
2508  {
2509  throw ap_error(_alglib_env_state.error_msg);
2510  }
2511 }
2512 
2513 /*************************************************************************
2514 Multiclass Fisher LDA
2515 
2516 Subroutine finds coefficients of linear combination which optimally separates
2517 training set on classes.
2518 
2519 INPUT PARAMETERS:
2520  XY - training set, array[0..NPoints-1,0..NVars].
2521  First NVars columns store values of independent
2522  variables, next column stores number of class (from 0
2523  to NClasses-1) which dataset element belongs to. Fractional
2524  values are rounded to nearest integer.
2525  NPoints - training set size, NPoints>=0
2526  NVars - number of independent variables, NVars>=1
2527  NClasses - number of classes, NClasses>=2
2528 
2529 
2530 OUTPUT PARAMETERS:
2531  Info - return code:
2532  * -4, if internal EVD subroutine hasn't converged
2533  * -2, if there is a point with class number
2534  outside of [0..NClasses-1].
2535  * -1, if incorrect parameters was passed (NPoints<0,
2536  NVars<1, NClasses<2)
2537  * 1, if task has been solved
2538  * 2, if there was a multicollinearity in training set,
2539  but task has been solved.
2540  W - linear combination coefficients, array[0..NVars-1]
2541 
2542  -- ALGLIB --
2543  Copyright 31.05.2008 by Bochkanov Sergey
2544 *************************************************************************/
2545 void fisherlda(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nclasses, ae_int_t &info, real_1d_array &w)
2546 {
2547  alglib_impl::ae_state _alglib_env_state;
2548  alglib_impl::ae_state_init(&_alglib_env_state);
2549  try
2550  {
2551  alglib_impl::fisherlda(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, nvars, nclasses, &info, const_cast<alglib_impl::ae_vector*>(w.c_ptr()), &_alglib_env_state);
2552  alglib_impl::ae_state_clear(&_alglib_env_state);
2553  return;
2554  }
2556  {
2557  throw ap_error(_alglib_env_state.error_msg);
2558  }
2559 }
2560 
2561 /*************************************************************************
2562 N-dimensional multiclass Fisher LDA
2563 
2564 Subroutine finds coefficients of linear combinations which optimally separates
2565 training set on classes. It returns N-dimensional basis whose vector are sorted
2566 by quality of training set separation (in descending order).
2567 
2568 INPUT PARAMETERS:
2569  XY - training set, array[0..NPoints-1,0..NVars].
2570  First NVars columns store values of independent
2571  variables, next column stores number of class (from 0
2572  to NClasses-1) which dataset element belongs to. Fractional
2573  values are rounded to nearest integer.
2574  NPoints - training set size, NPoints>=0
2575  NVars - number of independent variables, NVars>=1
2576  NClasses - number of classes, NClasses>=2
2577 
2578 
2579 OUTPUT PARAMETERS:
2580  Info - return code:
2581  * -4, if internal EVD subroutine hasn't converged
2582  * -2, if there is a point with class number
2583  outside of [0..NClasses-1].
2584  * -1, if incorrect parameters was passed (NPoints<0,
2585  NVars<1, NClasses<2)
2586  * 1, if task has been solved
2587  * 2, if there was a multicollinearity in training set,
2588  but task has been solved.
2589  W - basis, array[0..NVars-1,0..NVars-1]
2590  columns of matrix stores basis vectors, sorted by
2591  quality of training set separation (in descending order)
2592 
2593  -- ALGLIB --
2594  Copyright 31.05.2008 by Bochkanov Sergey
2595 *************************************************************************/
2596 void fisherldan(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nclasses, ae_int_t &info, real_2d_array &w)
2597 {
2598  alglib_impl::ae_state _alglib_env_state;
2599  alglib_impl::ae_state_init(&_alglib_env_state);
2600  try
2601  {
2602  alglib_impl::fisherldan(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, nvars, nclasses, &info, const_cast<alglib_impl::ae_matrix*>(w.c_ptr()), &_alglib_env_state);
2603  alglib_impl::ae_state_clear(&_alglib_env_state);
2604  return;
2605  }
2607  {
2608  throw ap_error(_alglib_env_state.error_msg);
2609  }
2610 }
2611 
2612 /*************************************************************************
2613 Model's errors:
2614  * RelCLSError - fraction of misclassified cases.
2615  * AvgCE - acerage cross-entropy
2616  * RMSError - root-mean-square error
2617  * AvgError - average error
2618  * AvgRelError - average relative error
2619 
2620 NOTE 1: RelCLSError/AvgCE are zero on regression problems.
2621 
2622 NOTE 2: on classification problems RMSError/AvgError/AvgRelError contain
2623  errors in prediction of posterior probabilities
2624 *************************************************************************/
2626 {
2628  if( p_struct==NULL )
2629  throw ap_error("ALGLIB: malloc error");
2631  throw ap_error("ALGLIB: malloc error");
2632 }
2633 
2635 {
2637  if( p_struct==NULL )
2638  throw ap_error("ALGLIB: malloc error");
2639  if( !alglib_impl::_modelerrors_init_copy(p_struct, const_cast<alglib_impl::modelerrors*>(rhs.p_struct), NULL, ae_false) )
2640  throw ap_error("ALGLIB: malloc error");
2641 }
2642 
2644 {
2645  if( this==&rhs )
2646  return *this;
2648  if( !alglib_impl::_modelerrors_init_copy(p_struct, const_cast<alglib_impl::modelerrors*>(rhs.p_struct), NULL, ae_false) )
2649  throw ap_error("ALGLIB: malloc error");
2650  return *this;
2651 }
2652 
2654 {
2656  ae_free(p_struct);
2657 }
2658 
2660 {
2661  return p_struct;
2662 }
2663 
2665 {
2666  return const_cast<alglib_impl::modelerrors*>(p_struct);
2667 }
2669 {
2670 }
2671 
2673 {
2674 }
2675 
2677 {
2678  if( this==&rhs )
2679  return *this;
2681  return *this;
2682 }
2683 
2685 {
2686 }
2687 
2688 
2689 /*************************************************************************
2690 
2691 *************************************************************************/
2693 {
2695  if( p_struct==NULL )
2696  throw ap_error("ALGLIB: malloc error");
2698  throw ap_error("ALGLIB: malloc error");
2699 }
2700 
2702 {
2704  if( p_struct==NULL )
2705  throw ap_error("ALGLIB: malloc error");
2706  if( !alglib_impl::_multilayerperceptron_init_copy(p_struct, const_cast<alglib_impl::multilayerperceptron*>(rhs.p_struct), NULL, ae_false) )
2707  throw ap_error("ALGLIB: malloc error");
2708 }
2709 
2711 {
2712  if( this==&rhs )
2713  return *this;
2715  if( !alglib_impl::_multilayerperceptron_init_copy(p_struct, const_cast<alglib_impl::multilayerperceptron*>(rhs.p_struct), NULL, ae_false) )
2716  throw ap_error("ALGLIB: malloc error");
2717  return *this;
2718 }
2719 
2721 {
2723  ae_free(p_struct);
2724 }
2725 
2727 {
2728  return p_struct;
2729 }
2730 
2732 {
2733  return const_cast<alglib_impl::multilayerperceptron*>(p_struct);
2734 }
2736 {
2737 }
2738 
2740 {
2741 }
2742 
2744 {
2745  if( this==&rhs )
2746  return *this;
2748  return *this;
2749 }
2750 
2752 {
2753 }
2754 
2755 
2756 /*************************************************************************
2757 This function serializes data structure to string.
2758 
2759 Important properties of s_out:
2760 * it contains alphanumeric characters, dots, underscores, minus signs
2761 * these symbols are grouped into words, which are separated by spaces
2762  and Windows-style (CR+LF) newlines
2763 * although serializer uses spaces and CR+LF as separators, you can
2764  replace any separator character by arbitrary combination of spaces,
2765  tabs, Windows or Unix newlines. It allows flexible reformatting of
2766  the string in case you want to include it into text or XML file.
2767  But you should not insert separators into the middle of the "words"
2768  nor you should change case of letters.
2769 * s_out can be freely moved between 32-bit and 64-bit systems, little
2770  and big endian machines, and so on. You can serialize structure on
2771  32-bit machine and unserialize it on 64-bit one (or vice versa), or
2772  serialize it on SPARC and unserialize on x86. You can also
2773  serialize it in C++ version of ALGLIB and unserialize in C# one,
2774  and vice versa.
2775 *************************************************************************/
2776 void mlpserialize(multilayerperceptron &obj, std::string &s_out)
2777 {
2778  alglib_impl::ae_state state;
2779  alglib_impl::ae_serializer serializer;
2780  alglib_impl::ae_int_t ssize;
2781 
2783  try
2784  {
2785  alglib_impl::ae_serializer_init(&serializer);
2787  alglib_impl::mlpalloc(&serializer, obj.c_ptr(), &state);
2788  ssize = alglib_impl::ae_serializer_get_alloc_size(&serializer);
2789  s_out.clear();
2790  s_out.reserve((size_t)(ssize+1));
2791  alglib_impl::ae_serializer_sstart_str(&serializer, &s_out);
2792  alglib_impl::mlpserialize(&serializer, obj.c_ptr(), &state);
2793  alglib_impl::ae_serializer_stop(&serializer);
2794  if( s_out.length()>(size_t)ssize )
2795  throw ap_error("ALGLIB: serialization integrity error");
2796  alglib_impl::ae_serializer_clear(&serializer);
2798  }
2800  {
2801  throw ap_error(state.error_msg);
2802  }
2803 }
2804 /*************************************************************************
2805 This function unserializes data structure from string.
2806 *************************************************************************/
2807 void mlpunserialize(std::string &s_in, multilayerperceptron &obj)
2808 {
2809  alglib_impl::ae_state state;
2810  alglib_impl::ae_serializer serializer;
2811 
2813  try
2814  {
2815  alglib_impl::ae_serializer_init(&serializer);
2816  alglib_impl::ae_serializer_ustart_str(&serializer, &s_in);
2817  alglib_impl::mlpunserialize(&serializer, obj.c_ptr(), &state);
2818  alglib_impl::ae_serializer_stop(&serializer);
2819  alglib_impl::ae_serializer_clear(&serializer);
2821  }
2823  {
2824  throw ap_error(state.error_msg);
2825  }
2826 }
2827 
2828 /*************************************************************************
2829 Creates neural network with NIn inputs, NOut outputs, without hidden
2830 layers, with linear output layer. Network weights are filled with small
2831 random values.
2832 
2833  -- ALGLIB --
2834  Copyright 04.11.2007 by Bochkanov Sergey
2835 *************************************************************************/
2836 void mlpcreate0(const ae_int_t nin, const ae_int_t nout, multilayerperceptron &network)
2837 {
2838  alglib_impl::ae_state _alglib_env_state;
2839  alglib_impl::ae_state_init(&_alglib_env_state);
2840  try
2841  {
2842  alglib_impl::mlpcreate0(nin, nout, const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), &_alglib_env_state);
2843  alglib_impl::ae_state_clear(&_alglib_env_state);
2844  return;
2845  }
2847  {
2848  throw ap_error(_alglib_env_state.error_msg);
2849  }
2850 }
2851 
2852 /*************************************************************************
2853 Same as MLPCreate0, but with one hidden layer (NHid neurons) with
2854 non-linear activation function. Output layer is linear.
2855 
2856  -- ALGLIB --
2857  Copyright 04.11.2007 by Bochkanov Sergey
2858 *************************************************************************/
2859 void mlpcreate1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, multilayerperceptron &network)
2860 {
2861  alglib_impl::ae_state _alglib_env_state;
2862  alglib_impl::ae_state_init(&_alglib_env_state);
2863  try
2864  {
2865  alglib_impl::mlpcreate1(nin, nhid, nout, const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), &_alglib_env_state);
2866  alglib_impl::ae_state_clear(&_alglib_env_state);
2867  return;
2868  }
2870  {
2871  throw ap_error(_alglib_env_state.error_msg);
2872  }
2873 }
2874 
2875 /*************************************************************************
2876 Same as MLPCreate0, but with two hidden layers (NHid1 and NHid2 neurons)
2877 with non-linear activation function. Output layer is linear.
2878  $ALL
2879 
2880  -- ALGLIB --
2881  Copyright 04.11.2007 by Bochkanov Sergey
2882 *************************************************************************/
2883 void mlpcreate2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, multilayerperceptron &network)
2884 {
2885  alglib_impl::ae_state _alglib_env_state;
2886  alglib_impl::ae_state_init(&_alglib_env_state);
2887  try
2888  {
2889  alglib_impl::mlpcreate2(nin, nhid1, nhid2, nout, const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), &_alglib_env_state);
2890  alglib_impl::ae_state_clear(&_alglib_env_state);
2891  return;
2892  }
2894  {
2895  throw ap_error(_alglib_env_state.error_msg);
2896  }
2897 }
2898 
2899 /*************************************************************************
2900 Creates neural network with NIn inputs, NOut outputs, without hidden
2901 layers with non-linear output layer. Network weights are filled with small
2902 random values.
2903 
2904 Activation function of the output layer takes values:
2905 
2906  (B, +INF), if D>=0
2907 
2908 or
2909 
2910  (-INF, B), if D<0.
2911 
2912 
2913  -- ALGLIB --
2914  Copyright 30.03.2008 by Bochkanov Sergey
2915 *************************************************************************/
2916 void mlpcreateb0(const ae_int_t nin, const ae_int_t nout, const double b, const double d, multilayerperceptron &network)
2917 {
2918  alglib_impl::ae_state _alglib_env_state;
2919  alglib_impl::ae_state_init(&_alglib_env_state);
2920  try
2921  {
2922  alglib_impl::mlpcreateb0(nin, nout, b, d, const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), &_alglib_env_state);
2923  alglib_impl::ae_state_clear(&_alglib_env_state);
2924  return;
2925  }
2927  {
2928  throw ap_error(_alglib_env_state.error_msg);
2929  }
2930 }
2931 
2932 /*************************************************************************
2933 Same as MLPCreateB0 but with non-linear hidden layer.
2934 
2935  -- ALGLIB --
2936  Copyright 30.03.2008 by Bochkanov Sergey
2937 *************************************************************************/
2938 void mlpcreateb1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const double b, const double d, multilayerperceptron &network)
2939 {
2940  alglib_impl::ae_state _alglib_env_state;
2941  alglib_impl::ae_state_init(&_alglib_env_state);
2942  try
2943  {
2944  alglib_impl::mlpcreateb1(nin, nhid, nout, b, d, const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), &_alglib_env_state);
2945  alglib_impl::ae_state_clear(&_alglib_env_state);
2946  return;
2947  }
2949  {
2950  throw ap_error(_alglib_env_state.error_msg);
2951  }
2952 }
2953 
2954 /*************************************************************************
2955 Same as MLPCreateB0 but with two non-linear hidden layers.
2956 
2957  -- ALGLIB --
2958  Copyright 30.03.2008 by Bochkanov Sergey
2959 *************************************************************************/
2960 void mlpcreateb2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const double b, const double d, multilayerperceptron &network)
2961 {
2962  alglib_impl::ae_state _alglib_env_state;
2963  alglib_impl::ae_state_init(&_alglib_env_state);
2964  try
2965  {
2966  alglib_impl::mlpcreateb2(nin, nhid1, nhid2, nout, b, d, const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), &_alglib_env_state);
2967  alglib_impl::ae_state_clear(&_alglib_env_state);
2968  return;
2969  }
2971  {
2972  throw ap_error(_alglib_env_state.error_msg);
2973  }
2974 }
2975 
2976 /*************************************************************************
2977 Creates neural network with NIn inputs, NOut outputs, without hidden
2978 layers with non-linear output layer. Network weights are filled with small
2979 random values. Activation function of the output layer takes values [A,B].
2980 
2981  -- ALGLIB --
2982  Copyright 30.03.2008 by Bochkanov Sergey
2983 *************************************************************************/
2984 void mlpcreater0(const ae_int_t nin, const ae_int_t nout, const double a, const double b, multilayerperceptron &network)
2985 {
2986  alglib_impl::ae_state _alglib_env_state;
2987  alglib_impl::ae_state_init(&_alglib_env_state);
2988  try
2989  {
2990  alglib_impl::mlpcreater0(nin, nout, a, b, const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), &_alglib_env_state);
2991  alglib_impl::ae_state_clear(&_alglib_env_state);
2992  return;
2993  }
2995  {
2996  throw ap_error(_alglib_env_state.error_msg);
2997  }
2998 }
2999 
3000 /*************************************************************************
3001 Same as MLPCreateR0, but with non-linear hidden layer.
3002 
3003  -- ALGLIB --
3004  Copyright 30.03.2008 by Bochkanov Sergey
3005 *************************************************************************/
3006 void mlpcreater1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const double a, const double b, multilayerperceptron &network)
3007 {
3008  alglib_impl::ae_state _alglib_env_state;
3009  alglib_impl::ae_state_init(&_alglib_env_state);
3010  try
3011  {
3012  alglib_impl::mlpcreater1(nin, nhid, nout, a, b, const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), &_alglib_env_state);
3013  alglib_impl::ae_state_clear(&_alglib_env_state);
3014  return;
3015  }
3017  {
3018  throw ap_error(_alglib_env_state.error_msg);
3019  }
3020 }
3021 
3022 /*************************************************************************
3023 Same as MLPCreateR0, but with two non-linear hidden layers.
3024 
3025  -- ALGLIB --
3026  Copyright 30.03.2008 by Bochkanov Sergey
3027 *************************************************************************/
3028 void mlpcreater2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const double a, const double b, multilayerperceptron &network)
3029 {
3030  alglib_impl::ae_state _alglib_env_state;
3031  alglib_impl::ae_state_init(&_alglib_env_state);
3032  try
3033  {
3034  alglib_impl::mlpcreater2(nin, nhid1, nhid2, nout, a, b, const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), &_alglib_env_state);
3035  alglib_impl::ae_state_clear(&_alglib_env_state);
3036  return;
3037  }
3039  {
3040  throw ap_error(_alglib_env_state.error_msg);
3041  }
3042 }
3043 
3044 /*************************************************************************
3045 Creates classifier network with NIn inputs and NOut possible classes.
3046 Network contains no hidden layers and linear output layer with SOFTMAX-
3047 normalization (so outputs sums up to 1.0 and converge to posterior
3048 probabilities).
3049 
3050  -- ALGLIB --
3051  Copyright 04.11.2007 by Bochkanov Sergey
3052 *************************************************************************/
3053 void mlpcreatec0(const ae_int_t nin, const ae_int_t nout, multilayerperceptron &network)
3054 {
3055  alglib_impl::ae_state _alglib_env_state;
3056  alglib_impl::ae_state_init(&_alglib_env_state);
3057  try
3058  {
3059  alglib_impl::mlpcreatec0(nin, nout, const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), &_alglib_env_state);
3060  alglib_impl::ae_state_clear(&_alglib_env_state);
3061  return;
3062  }
3064  {
3065  throw ap_error(_alglib_env_state.error_msg);
3066  }
3067 }
3068 
3069 /*************************************************************************
3070 Same as MLPCreateC0, but with one non-linear hidden layer.
3071 
3072  -- ALGLIB --
3073  Copyright 04.11.2007 by Bochkanov Sergey
3074 *************************************************************************/
3075 void mlpcreatec1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, multilayerperceptron &network)
3076 {
3077  alglib_impl::ae_state _alglib_env_state;
3078  alglib_impl::ae_state_init(&_alglib_env_state);
3079  try
3080  {
3081  alglib_impl::mlpcreatec1(nin, nhid, nout, const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), &_alglib_env_state);
3082  alglib_impl::ae_state_clear(&_alglib_env_state);
3083  return;
3084  }
3086  {
3087  throw ap_error(_alglib_env_state.error_msg);
3088  }
3089 }
3090 
3091 /*************************************************************************
3092 Same as MLPCreateC0, but with two non-linear hidden layers.
3093 
3094  -- ALGLIB --
3095  Copyright 04.11.2007 by Bochkanov Sergey
3096 *************************************************************************/
3097 void mlpcreatec2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, multilayerperceptron &network)
3098 {
3099  alglib_impl::ae_state _alglib_env_state;
3100  alglib_impl::ae_state_init(&_alglib_env_state);
3101  try
3102  {
3103  alglib_impl::mlpcreatec2(nin, nhid1, nhid2, nout, const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), &_alglib_env_state);
3104  alglib_impl::ae_state_clear(&_alglib_env_state);
3105  return;
3106  }
3108  {
3109  throw ap_error(_alglib_env_state.error_msg);
3110  }
3111 }
3112 
3113 /*************************************************************************
3114 Randomization of neural network weights
3115 
3116  -- ALGLIB --
3117  Copyright 06.11.2007 by Bochkanov Sergey
3118 *************************************************************************/
3120 {
3121  alglib_impl::ae_state _alglib_env_state;
3122  alglib_impl::ae_state_init(&_alglib_env_state);
3123  try
3124  {
3125  alglib_impl::mlprandomize(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), &_alglib_env_state);
3126  alglib_impl::ae_state_clear(&_alglib_env_state);
3127  return;
3128  }
3130  {
3131  throw ap_error(_alglib_env_state.error_msg);
3132  }
3133 }
3134 
3135 /*************************************************************************
3136 Randomization of neural network weights and standartisator
3137 
3138  -- ALGLIB --
3139  Copyright 10.03.2008 by Bochkanov Sergey
3140 *************************************************************************/
3142 {
3143  alglib_impl::ae_state _alglib_env_state;
3144  alglib_impl::ae_state_init(&_alglib_env_state);
3145  try
3146  {
3147  alglib_impl::mlprandomizefull(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), &_alglib_env_state);
3148  alglib_impl::ae_state_clear(&_alglib_env_state);
3149  return;
3150  }
3152  {
3153  throw ap_error(_alglib_env_state.error_msg);
3154  }
3155 }
3156 
3157 /*************************************************************************
3158 Returns information about initialized network: number of inputs, outputs,
3159 weights.
3160 
3161  -- ALGLIB --
3162  Copyright 04.11.2007 by Bochkanov Sergey
3163 *************************************************************************/
3164 void mlpproperties(const multilayerperceptron &network, ae_int_t &nin, ae_int_t &nout, ae_int_t &wcount)
3165 {
3166  alglib_impl::ae_state _alglib_env_state;
3167  alglib_impl::ae_state_init(&_alglib_env_state);
3168  try
3169  {
3170  alglib_impl::mlpproperties(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), &nin, &nout, &wcount, &_alglib_env_state);
3171  alglib_impl::ae_state_clear(&_alglib_env_state);
3172  return;
3173  }
3175  {
3176  throw ap_error(_alglib_env_state.error_msg);
3177  }
3178 }
3179 
3180 /*************************************************************************
3181 Returns number of inputs.
3182 
3183  -- ALGLIB --
3184  Copyright 19.10.2011 by Bochkanov Sergey
3185 *************************************************************************/
3187 {
3188  alglib_impl::ae_state _alglib_env_state;
3189  alglib_impl::ae_state_init(&_alglib_env_state);
3190  try
3191  {
3192  alglib_impl::ae_int_t result = alglib_impl::mlpgetinputscount(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), &_alglib_env_state);
3193  alglib_impl::ae_state_clear(&_alglib_env_state);
3194  return *(reinterpret_cast<ae_int_t*>(&result));
3195  }
3197  {
3198  throw ap_error(_alglib_env_state.error_msg);
3199  }
3200 }
3201 
3202 /*************************************************************************
3203 Returns number of outputs.
3204 
3205  -- ALGLIB --
3206  Copyright 19.10.2011 by Bochkanov Sergey
3207 *************************************************************************/
3209 {
3210  alglib_impl::ae_state _alglib_env_state;
3211  alglib_impl::ae_state_init(&_alglib_env_state);
3212  try
3213  {
3214  alglib_impl::ae_int_t result = alglib_impl::mlpgetoutputscount(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), &_alglib_env_state);
3215  alglib_impl::ae_state_clear(&_alglib_env_state);
3216  return *(reinterpret_cast<ae_int_t*>(&result));
3217  }
3219  {
3220  throw ap_error(_alglib_env_state.error_msg);
3221  }
3222 }
3223 
3224 /*************************************************************************
3225 Returns number of weights.
3226 
3227  -- ALGLIB --
3228  Copyright 19.10.2011 by Bochkanov Sergey
3229 *************************************************************************/
3231 {
3232  alglib_impl::ae_state _alglib_env_state;
3233  alglib_impl::ae_state_init(&_alglib_env_state);
3234  try
3235  {
3236  alglib_impl::ae_int_t result = alglib_impl::mlpgetweightscount(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), &_alglib_env_state);
3237  alglib_impl::ae_state_clear(&_alglib_env_state);
3238  return *(reinterpret_cast<ae_int_t*>(&result));
3239  }
3241  {
3242  throw ap_error(_alglib_env_state.error_msg);
3243  }
3244 }
3245 
3246 /*************************************************************************
3247 Tells whether network is SOFTMAX-normalized (i.e. classifier) or not.
3248 
3249  -- ALGLIB --
3250  Copyright 04.11.2007 by Bochkanov Sergey
3251 *************************************************************************/
3253 {
3254  alglib_impl::ae_state _alglib_env_state;
3255  alglib_impl::ae_state_init(&_alglib_env_state);
3256  try
3257  {
3258  ae_bool result = alglib_impl::mlpissoftmax(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), &_alglib_env_state);
3259  alglib_impl::ae_state_clear(&_alglib_env_state);
3260  return *(reinterpret_cast<bool*>(&result));
3261  }
3263  {
3264  throw ap_error(_alglib_env_state.error_msg);
3265  }
3266 }
3267 
3268 /*************************************************************************
3269 This function returns total number of layers (including input, hidden and
3270 output layers).
3271 
3272  -- ALGLIB --
3273  Copyright 25.03.2011 by Bochkanov Sergey
3274 *************************************************************************/
3276 {
3277  alglib_impl::ae_state _alglib_env_state;
3278  alglib_impl::ae_state_init(&_alglib_env_state);
3279  try
3280  {
3281  alglib_impl::ae_int_t result = alglib_impl::mlpgetlayerscount(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), &_alglib_env_state);
3282  alglib_impl::ae_state_clear(&_alglib_env_state);
3283  return *(reinterpret_cast<ae_int_t*>(&result));
3284  }
3286  {
3287  throw ap_error(_alglib_env_state.error_msg);
3288  }
3289 }
3290 
3291 /*************************************************************************
3292 This function returns size of K-th layer.
3293 
3294 K=0 corresponds to input layer, K=CNT-1 corresponds to output layer.
3295 
3296 Size of the output layer is always equal to the number of outputs, although
3297 when we have softmax-normalized network, last neuron doesn't have any
3298 connections - it is just zero.
3299 
3300  -- ALGLIB --
3301  Copyright 25.03.2011 by Bochkanov Sergey
3302 *************************************************************************/
3304 {
3305  alglib_impl::ae_state _alglib_env_state;
3306  alglib_impl::ae_state_init(&_alglib_env_state);
3307  try
3308  {
3309  alglib_impl::ae_int_t result = alglib_impl::mlpgetlayersize(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), k, &_alglib_env_state);
3310  alglib_impl::ae_state_clear(&_alglib_env_state);
3311  return *(reinterpret_cast<ae_int_t*>(&result));
3312  }
3314  {
3315  throw ap_error(_alglib_env_state.error_msg);
3316  }
3317 }
3318 
3319 /*************************************************************************
3320 This function returns offset/scaling coefficients for I-th input of the
3321 network.
3322 
3323 INPUT PARAMETERS:
3324  Network - network
3325  I - input index
3326 
3327 OUTPUT PARAMETERS:
3328  Mean - mean term
3329  Sigma - sigma term, guaranteed to be nonzero.
3330 
3331 I-th input is passed through linear transformation
3332  IN[i] = (IN[i]-Mean)/Sigma
3333 before feeding to the network
3334 
3335  -- ALGLIB --
3336  Copyright 25.03.2011 by Bochkanov Sergey
3337 *************************************************************************/
3338 void mlpgetinputscaling(const multilayerperceptron &network, const ae_int_t i, double &mean, double &sigma)
3339 {
3340  alglib_impl::ae_state _alglib_env_state;
3341  alglib_impl::ae_state_init(&_alglib_env_state);
3342  try
3343  {
3344  alglib_impl::mlpgetinputscaling(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), i, &mean, &sigma, &_alglib_env_state);
3345  alglib_impl::ae_state_clear(&_alglib_env_state);
3346  return;
3347  }
3349  {
3350  throw ap_error(_alglib_env_state.error_msg);
3351  }
3352 }
3353 
3354 /*************************************************************************
3355 This function returns offset/scaling coefficients for I-th output of the
3356 network.
3357 
3358 INPUT PARAMETERS:
3359  Network - network
3360  I - input index
3361 
3362 OUTPUT PARAMETERS:
3363  Mean - mean term
3364  Sigma - sigma term, guaranteed to be nonzero.
3365 
3366 I-th output is passed through linear transformation
3367  OUT[i] = OUT[i]*Sigma+Mean
3368 before returning it to user. In case we have SOFTMAX-normalized network,
3369 we return (Mean,Sigma)=(0.0,1.0).
3370 
3371  -- ALGLIB --
3372  Copyright 25.03.2011 by Bochkanov Sergey
3373 *************************************************************************/
3374 void mlpgetoutputscaling(const multilayerperceptron &network, const ae_int_t i, double &mean, double &sigma)
3375 {
3376  alglib_impl::ae_state _alglib_env_state;
3377  alglib_impl::ae_state_init(&_alglib_env_state);
3378  try
3379  {
3380  alglib_impl::mlpgetoutputscaling(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), i, &mean, &sigma, &_alglib_env_state);
3381  alglib_impl::ae_state_clear(&_alglib_env_state);
3382  return;
3383  }
3385  {
3386  throw ap_error(_alglib_env_state.error_msg);
3387  }
3388 }
3389 
3390 /*************************************************************************
3391 This function returns information about Ith neuron of Kth layer
3392 
3393 INPUT PARAMETERS:
3394  Network - network
3395  K - layer index
3396  I - neuron index (within layer)
3397 
3398 OUTPUT PARAMETERS:
3399  FKind - activation function type (used by MLPActivationFunction())
3400  this value is zero for input or linear neurons
3401  Threshold - also called offset, bias
3402  zero for input neurons
3403 
3404 NOTE: this function throws exception if layer or neuron with given index
3405 do not exists.
3406 
3407  -- ALGLIB --
3408  Copyright 25.03.2011 by Bochkanov Sergey
3409 *************************************************************************/
3410 void mlpgetneuroninfo(const multilayerperceptron &network, const ae_int_t k, const ae_int_t i, ae_int_t &fkind, double &threshold)
3411 {
3412  alglib_impl::ae_state _alglib_env_state;
3413  alglib_impl::ae_state_init(&_alglib_env_state);
3414  try
3415  {
3416  alglib_impl::mlpgetneuroninfo(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), k, i, &fkind, &threshold, &_alglib_env_state);
3417  alglib_impl::ae_state_clear(&_alglib_env_state);
3418  return;
3419  }
3421  {
3422  throw ap_error(_alglib_env_state.error_msg);
3423  }
3424 }
3425 
3426 /*************************************************************************
3427 This function returns information about connection from I0-th neuron of
3428 K0-th layer to I1-th neuron of K1-th layer.
3429 
3430 INPUT PARAMETERS:
3431  Network - network
3432  K0 - layer index
3433  I0 - neuron index (within layer)
3434  K1 - layer index
3435  I1 - neuron index (within layer)
3436 
3437 RESULT:
3438  connection weight (zero for non-existent connections)
3439 
3440 This function:
3441 1. throws exception if layer or neuron with given index do not exists.
3442 2. returns zero if neurons exist, but there is no connection between them
3443 
3444  -- ALGLIB --
3445  Copyright 25.03.2011 by Bochkanov Sergey
3446 *************************************************************************/
3447 double mlpgetweight(const multilayerperceptron &network, const ae_int_t k0, const ae_int_t i0, const ae_int_t k1, const ae_int_t i1)
3448 {
3449  alglib_impl::ae_state _alglib_env_state;
3450  alglib_impl::ae_state_init(&_alglib_env_state);
3451  try
3452  {
3453  double result = alglib_impl::mlpgetweight(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), k0, i0, k1, i1, &_alglib_env_state);
3454  alglib_impl::ae_state_clear(&_alglib_env_state);
3455  return *(reinterpret_cast<double*>(&result));
3456  }
3458  {
3459  throw ap_error(_alglib_env_state.error_msg);
3460  }
3461 }
3462 
3463 /*************************************************************************
3464 This function sets offset/scaling coefficients for I-th input of the
3465 network.
3466 
3467 INPUT PARAMETERS:
3468  Network - network
3469  I - input index
3470  Mean - mean term
3471  Sigma - sigma term (if zero, will be replaced by 1.0)
3472 
3473 NTE: I-th input is passed through linear transformation
3474  IN[i] = (IN[i]-Mean)/Sigma
3475 before feeding to the network. This function sets Mean and Sigma.
3476 
3477  -- ALGLIB --
3478  Copyright 25.03.2011 by Bochkanov Sergey
3479 *************************************************************************/
3480 void mlpsetinputscaling(const multilayerperceptron &network, const ae_int_t i, const double mean, const double sigma)
3481 {
3482  alglib_impl::ae_state _alglib_env_state;
3483  alglib_impl::ae_state_init(&_alglib_env_state);
3484  try
3485  {
3486  alglib_impl::mlpsetinputscaling(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), i, mean, sigma, &_alglib_env_state);
3487  alglib_impl::ae_state_clear(&_alglib_env_state);
3488  return;
3489  }
3491  {
3492  throw ap_error(_alglib_env_state.error_msg);
3493  }
3494 }
3495 
3496 /*************************************************************************
3497 This function sets offset/scaling coefficients for I-th output of the
3498 network.
3499 
3500 INPUT PARAMETERS:
3501  Network - network
3502  I - input index
3503  Mean - mean term
3504  Sigma - sigma term (if zero, will be replaced by 1.0)
3505 
3506 OUTPUT PARAMETERS:
3507 
3508 NOTE: I-th output is passed through linear transformation
3509  OUT[i] = OUT[i]*Sigma+Mean
3510 before returning it to user. This function sets Sigma/Mean. In case we
3511 have SOFTMAX-normalized network, you can not set (Sigma,Mean) to anything
3512 other than(0.0,1.0) - this function will throw exception.
3513 
3514  -- ALGLIB --
3515  Copyright 25.03.2011 by Bochkanov Sergey
3516 *************************************************************************/
3517 void mlpsetoutputscaling(const multilayerperceptron &network, const ae_int_t i, const double mean, const double sigma)
3518 {
3519  alglib_impl::ae_state _alglib_env_state;
3520  alglib_impl::ae_state_init(&_alglib_env_state);
3521  try
3522  {
3523  alglib_impl::mlpsetoutputscaling(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), i, mean, sigma, &_alglib_env_state);
3524  alglib_impl::ae_state_clear(&_alglib_env_state);
3525  return;
3526  }
3528  {
3529  throw ap_error(_alglib_env_state.error_msg);
3530  }
3531 }
3532 
3533 /*************************************************************************
3534 This function modifies information about Ith neuron of Kth layer
3535 
3536 INPUT PARAMETERS:
3537  Network - network
3538  K - layer index
3539  I - neuron index (within layer)
3540  FKind - activation function type (used by MLPActivationFunction())
3541  this value must be zero for input neurons
3542  (you can not set activation function for input neurons)
3543  Threshold - also called offset, bias
3544  this value must be zero for input neurons
3545  (you can not set threshold for input neurons)
3546 
3547 NOTES:
3548 1. this function throws exception if layer or neuron with given index do
3549  not exists.
3550 2. this function also throws exception when you try to set non-linear
3551  activation function for input neurons (any kind of network) or for output
3552  neurons of classifier network.
3553 3. this function throws exception when you try to set non-zero threshold for
3554  input neurons (any kind of network).
3555 
3556  -- ALGLIB --
3557  Copyright 25.03.2011 by Bochkanov Sergey
3558 *************************************************************************/
3559 void mlpsetneuroninfo(const multilayerperceptron &network, const ae_int_t k, const ae_int_t i, const ae_int_t fkind, const double threshold)
3560 {
3561  alglib_impl::ae_state _alglib_env_state;
3562  alglib_impl::ae_state_init(&_alglib_env_state);
3563  try
3564  {
3565  alglib_impl::mlpsetneuroninfo(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), k, i, fkind, threshold, &_alglib_env_state);
3566  alglib_impl::ae_state_clear(&_alglib_env_state);
3567  return;
3568  }
3570  {
3571  throw ap_error(_alglib_env_state.error_msg);
3572  }
3573 }
3574 
3575 /*************************************************************************
3576 This function modifies information about connection from I0-th neuron of
3577 K0-th layer to I1-th neuron of K1-th layer.
3578 
3579 INPUT PARAMETERS:
3580  Network - network
3581  K0 - layer index
3582  I0 - neuron index (within layer)
3583  K1 - layer index
3584  I1 - neuron index (within layer)
3585  W - connection weight (must be zero for non-existent
3586  connections)
3587 
3588 This function:
3589 1. throws exception if layer or neuron with given index do not exists.
3590 2. throws exception if you try to set non-zero weight for non-existent
3591  connection
3592 
3593  -- ALGLIB --
3594  Copyright 25.03.2011 by Bochkanov Sergey
3595 *************************************************************************/
3596 void mlpsetweight(const multilayerperceptron &network, const ae_int_t k0, const ae_int_t i0, const ae_int_t k1, const ae_int_t i1, const double w)
3597 {
3598  alglib_impl::ae_state _alglib_env_state;
3599  alglib_impl::ae_state_init(&_alglib_env_state);
3600  try
3601  {
3602  alglib_impl::mlpsetweight(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), k0, i0, k1, i1, w, &_alglib_env_state);
3603  alglib_impl::ae_state_clear(&_alglib_env_state);
3604  return;
3605  }
3607  {
3608  throw ap_error(_alglib_env_state.error_msg);
3609  }
3610 }
3611 
3612 /*************************************************************************
3613 Neural network activation function
3614 
3615 INPUT PARAMETERS:
3616  NET - neuron input
3617  K - function index (zero for linear function)
3618 
3619 OUTPUT PARAMETERS:
3620  F - function
3621  DF - its derivative
3622  D2F - its second derivative
3623 
3624  -- ALGLIB --
3625  Copyright 04.11.2007 by Bochkanov Sergey
3626 *************************************************************************/
3627 void mlpactivationfunction(const double net, const ae_int_t k, double &f, double &df, double &d2f)
3628 {
3629  alglib_impl::ae_state _alglib_env_state;
3630  alglib_impl::ae_state_init(&_alglib_env_state);
3631  try
3632  {
3633  alglib_impl::mlpactivationfunction(net, k, &f, &df, &d2f, &_alglib_env_state);
3634  alglib_impl::ae_state_clear(&_alglib_env_state);
3635  return;
3636  }
3638  {
3639  throw ap_error(_alglib_env_state.error_msg);
3640  }
3641 }
3642 
3643 /*************************************************************************
3644 Procesing
3645 
3646 INPUT PARAMETERS:
3647  Network - neural network
3648  X - input vector, array[0..NIn-1].
3649 
3650 OUTPUT PARAMETERS:
3651  Y - result. Regression estimate when solving regression task,
3652  vector of posterior probabilities for classification task.
3653 
3654 See also MLPProcessI
3655 
3656  -- ALGLIB --
3657  Copyright 04.11.2007 by Bochkanov Sergey
3658 *************************************************************************/
3660 {
3661  alglib_impl::ae_state _alglib_env_state;
3662  alglib_impl::ae_state_init(&_alglib_env_state);
3663  try
3664  {
3665  alglib_impl::mlpprocess(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), &_alglib_env_state);
3666  alglib_impl::ae_state_clear(&_alglib_env_state);
3667  return;
3668  }
3670  {
3671  throw ap_error(_alglib_env_state.error_msg);
3672  }
3673 }
3674 
3675 /*************************************************************************
3676 'interactive' variant of MLPProcess for languages like Python which
3677 support constructs like "Y = MLPProcess(NN,X)" and interactive mode of the
3678 interpreter
3679 
3680 This function allocates new array on each call, so it is significantly
3681 slower than its 'non-interactive' counterpart, but it is more convenient
3682 when you call it from command line.
3683 
3684  -- ALGLIB --
3685  Copyright 21.09.2010 by Bochkanov Sergey
3686 *************************************************************************/
3688 {
3689  alglib_impl::ae_state _alglib_env_state;
3690  alglib_impl::ae_state_init(&_alglib_env_state);
3691  try
3692  {
3693  alglib_impl::mlpprocessi(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), &_alglib_env_state);
3694  alglib_impl::ae_state_clear(&_alglib_env_state);
3695  return;
3696  }
3698  {
3699  throw ap_error(_alglib_env_state.error_msg);
3700  }
3701 }
3702 
3703 /*************************************************************************
3704 Error of the neural network on dataset.
3705 
3706 
3707 FOR USERS OF COMMERCIAL EDITION:
3708 
3709  ! Commercial version of ALGLIB includes two important improvements of
3710  ! this function:
3711  ! * multicore support (C++ and C# computational cores)
3712  ! * SSE support
3713  !
3714  ! First improvement gives close-to-linear speedup on multicore systems.
3715  ! Second improvement gives constant speedup (2-3x, depending on your CPU)
3716  !
3717  ! In order to use multicore features you have to:
3718  ! * use commercial version of ALGLIB
3719  ! * call this function with "smp_" prefix, which indicates that
3720  ! multicore code will be used (for multicore support)
3721  !
3722  ! In order to use SSE features you have to:
3723  ! * use commercial version of ALGLIB on Intel processors
3724  ! * use C++ computational core
3725  !
3726  ! This note is given for users of commercial edition; if you use GPL
3727  ! edition, you still will be able to call smp-version of this function,
3728  ! but all computations will be done serially.
3729  !
3730  ! We recommend you to carefully read ALGLIB Reference Manual, section
3731  ! called 'SMP support', before using parallel version of this function.
3732 
3733 
3734 INPUT PARAMETERS:
3735  Network - neural network;
3736  XY - training set, see below for information on the
3737  training set format;
3738  NPoints - points count.
3739 
3740 RESULT:
3741  sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2)
3742 
3743 DATASET FORMAT:
3744 
3745 This function uses two different dataset formats - one for regression
3746 networks, another one for classification networks.
3747 
3748 For regression networks with NIn inputs and NOut outputs following dataset
3749 format is used:
3750 * dataset is given by NPoints*(NIn+NOut) matrix
3751 * each row corresponds to one example
3752 * first NIn columns are inputs, next NOut columns are outputs
3753 
3754 For classification networks with NIn inputs and NClasses clases following
3755 dataset format is used:
3756 * dataset is given by NPoints*(NIn+1) matrix
3757 * each row corresponds to one example
3758 * first NIn columns are inputs, last column stores class number (from 0 to
3759  NClasses-1).
3760 
3761  -- ALGLIB --
3762  Copyright 04.11.2007 by Bochkanov Sergey
3763 *************************************************************************/
3764 double mlperror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
3765 {
3766  alglib_impl::ae_state _alglib_env_state;
3767  alglib_impl::ae_state_init(&_alglib_env_state);
3768  try
3769  {
3770  double result = alglib_impl::mlperror(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
3771  alglib_impl::ae_state_clear(&_alglib_env_state);
3772  return *(reinterpret_cast<double*>(&result));
3773  }
3775  {
3776  throw ap_error(_alglib_env_state.error_msg);
3777  }
3778 }
3779 
3780 
3781 double smp_mlperror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
3782 {
3783  alglib_impl::ae_state _alglib_env_state;
3784  alglib_impl::ae_state_init(&_alglib_env_state);
3785  try
3786  {
3787  double result = alglib_impl::_pexec_mlperror(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
3788  alglib_impl::ae_state_clear(&_alglib_env_state);
3789  return *(reinterpret_cast<double*>(&result));
3790  }
3792  {
3793  throw ap_error(_alglib_env_state.error_msg);
3794  }
3795 }
3796 
3797 /*************************************************************************
3798 Error of the neural network on dataset given by sparse matrix.
3799 
3800 
3801 FOR USERS OF COMMERCIAL EDITION:
3802 
3803  ! Commercial version of ALGLIB includes two important improvements of
3804  ! this function:
3805  ! * multicore support (C++ and C# computational cores)
3806  ! * SSE support
3807  !
3808  ! First improvement gives close-to-linear speedup on multicore systems.
3809  ! Second improvement gives constant speedup (2-3x, depending on your CPU)
3810  !
3811  ! In order to use multicore features you have to:
3812  ! * use commercial version of ALGLIB
3813  ! * call this function with "smp_" prefix, which indicates that
3814  ! multicore code will be used (for multicore support)
3815  !
3816  ! In order to use SSE features you have to:
3817  ! * use commercial version of ALGLIB on Intel processors
3818  ! * use C++ computational core
3819  !
3820  ! This note is given for users of commercial edition; if you use GPL
3821  ! edition, you still will be able to call smp-version of this function,
3822  ! but all computations will be done serially.
3823  !
3824  ! We recommend you to carefully read ALGLIB Reference Manual, section
3825  ! called 'SMP support', before using parallel version of this function.
3826 
3827 
3828 INPUT PARAMETERS:
3829  Network - neural network
3830  XY - training set, see below for information on the
3831  training set format. This function checks correctness
3832  of the dataset (no NANs/INFs, class numbers are
3833  correct) and throws exception when incorrect dataset
3834  is passed. Sparse matrix must use CRS format for
3835  storage.
3836  NPoints - points count, >=0
3837 
3838 RESULT:
3839  sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2)
3840 
3841 DATASET FORMAT:
3842 
3843 This function uses two different dataset formats - one for regression
3844 networks, another one for classification networks.
3845 
3846 For regression networks with NIn inputs and NOut outputs following dataset
3847 format is used:
3848 * dataset is given by NPoints*(NIn+NOut) matrix
3849 * each row corresponds to one example
3850 * first NIn columns are inputs, next NOut columns are outputs
3851 
3852 For classification networks with NIn inputs and NClasses clases following
3853 dataset format is used:
3854 * dataset is given by NPoints*(NIn+1) matrix
3855 * each row corresponds to one example
3856 * first NIn columns are inputs, last column stores class number (from 0 to
3857  NClasses-1).
3858 
3859  -- ALGLIB --
3860  Copyright 23.07.2012 by Bochkanov Sergey
3861 *************************************************************************/
3862 double mlperrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
3863 {
3864  alglib_impl::ae_state _alglib_env_state;
3865  alglib_impl::ae_state_init(&_alglib_env_state);
3866  try
3867  {
3868  double result = alglib_impl::mlperrorsparse(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::sparsematrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
3869  alglib_impl::ae_state_clear(&_alglib_env_state);
3870  return *(reinterpret_cast<double*>(&result));
3871  }
3873  {
3874  throw ap_error(_alglib_env_state.error_msg);
3875  }
3876 }
3877 
3878 
3879 double smp_mlperrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
3880 {
3881  alglib_impl::ae_state _alglib_env_state;
3882  alglib_impl::ae_state_init(&_alglib_env_state);
3883  try
3884  {
3885  double result = alglib_impl::_pexec_mlperrorsparse(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::sparsematrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
3886  alglib_impl::ae_state_clear(&_alglib_env_state);
3887  return *(reinterpret_cast<double*>(&result));
3888  }
3890  {
3891  throw ap_error(_alglib_env_state.error_msg);
3892  }
3893 }
3894 
3895 /*************************************************************************
3896 Natural error function for neural network, internal subroutine.
3897 
3898 NOTE: this function is single-threaded. Unlike other error function, it
3899 receives no speed-up from being executed in SMP mode.
3900 
3901  -- ALGLIB --
3902  Copyright 04.11.2007 by Bochkanov Sergey
3903 *************************************************************************/
3904 double mlperrorn(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize)
3905 {
3906  alglib_impl::ae_state _alglib_env_state;
3907  alglib_impl::ae_state_init(&_alglib_env_state);
3908  try
3909  {
3910  double result = alglib_impl::mlperrorn(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), ssize, &_alglib_env_state);
3911  alglib_impl::ae_state_clear(&_alglib_env_state);
3912  return *(reinterpret_cast<double*>(&result));
3913  }
3915  {
3916  throw ap_error(_alglib_env_state.error_msg);
3917  }
3918 }
3919 
3920 /*************************************************************************
3921 Classification error of the neural network on dataset.
3922 
3923 
3924 FOR USERS OF COMMERCIAL EDITION:
3925 
3926  ! Commercial version of ALGLIB includes two important improvements of
3927  ! this function:
3928  ! * multicore support (C++ and C# computational cores)
3929  ! * SSE support
3930  !
3931  ! First improvement gives close-to-linear speedup on multicore systems.
3932  ! Second improvement gives constant speedup (2-3x depending on your CPU)
3933  !
3934  ! In order to use multicore features you have to:
3935  ! * use commercial version of ALGLIB
3936  ! * call this function with "smp_" prefix, which indicates that
3937  ! multicore code will be used (for multicore support)
3938  !
3939  ! In order to use SSE features you have to:
3940  ! * use commercial version of ALGLIB on Intel processors
3941  ! * use C++ computational core
3942  !
3943  ! This note is given for users of commercial edition; if you use GPL
3944  ! edition, you still will be able to call smp-version of this function,
3945  ! but all computations will be done serially.
3946  !
3947  ! We recommend you to carefully read ALGLIB Reference Manual, section
3948  ! called 'SMP support', before using parallel version of this function.
3949 
3950 
3951 INPUT PARAMETERS:
3952  Network - neural network;
3953  XY - training set, see below for information on the
3954  training set format;
3955  NPoints - points count.
3956 
3957 RESULT:
3958  classification error (number of misclassified cases)
3959 
3960 DATASET FORMAT:
3961 
3962 This function uses two different dataset formats - one for regression
3963 networks, another one for classification networks.
3964 
3965 For regression networks with NIn inputs and NOut outputs following dataset
3966 format is used:
3967 * dataset is given by NPoints*(NIn+NOut) matrix
3968 * each row corresponds to one example
3969 * first NIn columns are inputs, next NOut columns are outputs
3970 
3971 For classification networks with NIn inputs and NClasses clases following
3972 dataset format is used:
3973 * dataset is given by NPoints*(NIn+1) matrix
3974 * each row corresponds to one example
3975 * first NIn columns are inputs, last column stores class number (from 0 to
3976  NClasses-1).
3977 
3978  -- ALGLIB --
3979  Copyright 04.11.2007 by Bochkanov Sergey
3980 *************************************************************************/
3981 ae_int_t mlpclserror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
3982 {
3983  alglib_impl::ae_state _alglib_env_state;
3984  alglib_impl::ae_state_init(&_alglib_env_state);
3985  try
3986  {
3987  alglib_impl::ae_int_t result = alglib_impl::mlpclserror(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
3988  alglib_impl::ae_state_clear(&_alglib_env_state);
3989  return *(reinterpret_cast<ae_int_t*>(&result));
3990  }
3992  {
3993  throw ap_error(_alglib_env_state.error_msg);
3994  }
3995 }
3996 
3997 
3998 ae_int_t smp_mlpclserror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
3999 {
4000  alglib_impl::ae_state _alglib_env_state;
4001  alglib_impl::ae_state_init(&_alglib_env_state);
4002  try
4003  {
4004  alglib_impl::ae_int_t result = alglib_impl::_pexec_mlpclserror(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
4005  alglib_impl::ae_state_clear(&_alglib_env_state);
4006  return *(reinterpret_cast<ae_int_t*>(&result));
4007  }
4009  {
4010  throw ap_error(_alglib_env_state.error_msg);
4011  }
4012 }
4013 
4014 /*************************************************************************
4015 Relative classification error on the test set.
4016 
4017 
4018 FOR USERS OF COMMERCIAL EDITION:
4019 
4020  ! Commercial version of ALGLIB includes two important improvements of
4021  ! this function:
4022  ! * multicore support (C++ and C# computational cores)
4023  ! * SSE support
4024  !
4025  ! First improvement gives close-to-linear speedup on multicore systems.
4026  ! Second improvement gives constant speedup (2-3x depending on your CPU)
4027  !
4028  ! In order to use multicore features you have to:
4029  ! * use commercial version of ALGLIB
4030  ! * call this function with "smp_" prefix, which indicates that
4031  ! multicore code will be used (for multicore support)
4032  !
4033  ! In order to use SSE features you have to:
4034  ! * use commercial version of ALGLIB on Intel processors
4035  ! * use C++ computational core
4036  !
4037  ! This note is given for users of commercial edition; if you use GPL
4038  ! edition, you still will be able to call smp-version of this function,
4039  ! but all computations will be done serially.
4040  !
4041  ! We recommend you to carefully read ALGLIB Reference Manual, section
4042  ! called 'SMP support', before using parallel version of this function.
4043 
4044 
4045 INPUT PARAMETERS:
4046  Network - neural network;
4047  XY - training set, see below for information on the
4048  training set format;
4049  NPoints - points count.
4050 
4051 RESULT:
4052 Percent of incorrectly classified cases. Works both for classifier
4053 networks and general purpose networks used as classifiers.
4054 
4055 DATASET FORMAT:
4056 
4057 This function uses two different dataset formats - one for regression
4058 networks, another one for classification networks.
4059 
4060 For regression networks with NIn inputs and NOut outputs following dataset
4061 format is used:
4062 * dataset is given by NPoints*(NIn+NOut) matrix
4063 * each row corresponds to one example
4064 * first NIn columns are inputs, next NOut columns are outputs
4065 
4066 For classification networks with NIn inputs and NClasses clases following
4067 dataset format is used:
4068 * dataset is given by NPoints*(NIn+1) matrix
4069 * each row corresponds to one example
4070 * first NIn columns are inputs, last column stores class number (from 0 to
4071  NClasses-1).
4072 
4073  -- ALGLIB --
4074  Copyright 25.12.2008 by Bochkanov Sergey
4075 *************************************************************************/
4076 double mlprelclserror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
4077 {
4078  alglib_impl::ae_state _alglib_env_state;
4079  alglib_impl::ae_state_init(&_alglib_env_state);
4080  try
4081  {
4082  double result = alglib_impl::mlprelclserror(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
4083  alglib_impl::ae_state_clear(&_alglib_env_state);
4084  return *(reinterpret_cast<double*>(&result));
4085  }
4087  {
4088  throw ap_error(_alglib_env_state.error_msg);
4089  }
4090 }
4091 
4092 
4093 double smp_mlprelclserror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
4094 {
4095  alglib_impl::ae_state _alglib_env_state;
4096  alglib_impl::ae_state_init(&_alglib_env_state);
4097  try
4098  {
4099  double result = alglib_impl::_pexec_mlprelclserror(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
4100  alglib_impl::ae_state_clear(&_alglib_env_state);
4101  return *(reinterpret_cast<double*>(&result));
4102  }
4104  {
4105  throw ap_error(_alglib_env_state.error_msg);
4106  }
4107 }
4108 
4109 /*************************************************************************
4110 Relative classification error on the test set given by sparse matrix.
4111 
4112 
4113 FOR USERS OF COMMERCIAL EDITION:
4114 
4115  ! Commercial version of ALGLIB includes two important improvements of
4116  ! this function:
4117  ! * multicore support (C++ and C# computational cores)
4118  ! * SSE support
4119  !
4120  ! First improvement gives close-to-linear speedup on multicore systems.
4121  ! Second improvement gives constant speedup (2-3x depending on your CPU)
4122  !
4123  ! In order to use multicore features you have to:
4124  ! * use commercial version of ALGLIB
4125  ! * call this function with "smp_" prefix, which indicates that
4126  ! multicore code will be used (for multicore support)
4127  !
4128  ! In order to use SSE features you have to:
4129  ! * use commercial version of ALGLIB on Intel processors
4130  ! * use C++ computational core
4131  !
4132  ! This note is given for users of commercial edition; if you use GPL
4133  ! edition, you still will be able to call smp-version of this function,
4134  ! but all computations will be done serially.
4135  !
4136  ! We recommend you to carefully read ALGLIB Reference Manual, section
4137  ! called 'SMP support', before using parallel version of this function.
4138 
4139 
4140 INPUT PARAMETERS:
4141  Network - neural network;
4142  XY - training set, see below for information on the
4143  training set format. Sparse matrix must use CRS format
4144  for storage.
4145  NPoints - points count, >=0.
4146 
4147 RESULT:
4148 Percent of incorrectly classified cases. Works both for classifier
4149 networks and general purpose networks used as classifiers.
4150 
4151 DATASET FORMAT:
4152 
4153 This function uses two different dataset formats - one for regression
4154 networks, another one for classification networks.
4155 
4156 For regression networks with NIn inputs and NOut outputs following dataset
4157 format is used:
4158 * dataset is given by NPoints*(NIn+NOut) matrix
4159 * each row corresponds to one example
4160 * first NIn columns are inputs, next NOut columns are outputs
4161 
4162 For classification networks with NIn inputs and NClasses clases following
4163 dataset format is used:
4164 * dataset is given by NPoints*(NIn+1) matrix
4165 * each row corresponds to one example
4166 * first NIn columns are inputs, last column stores class number (from 0 to
4167  NClasses-1).
4168 
4169  -- ALGLIB --
4170  Copyright 09.08.2012 by Bochkanov Sergey
4171 *************************************************************************/
4172 double mlprelclserrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
4173 {
4174  alglib_impl::ae_state _alglib_env_state;
4175  alglib_impl::ae_state_init(&_alglib_env_state);
4176  try
4177  {
4178  double result = alglib_impl::mlprelclserrorsparse(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::sparsematrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
4179  alglib_impl::ae_state_clear(&_alglib_env_state);
4180  return *(reinterpret_cast<double*>(&result));
4181  }
4183  {
4184  throw ap_error(_alglib_env_state.error_msg);
4185  }
4186 }
4187 
4188 
4189 double smp_mlprelclserrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
4190 {
4191  alglib_impl::ae_state _alglib_env_state;
4192  alglib_impl::ae_state_init(&_alglib_env_state);
4193  try
4194  {
4195  double result = alglib_impl::_pexec_mlprelclserrorsparse(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::sparsematrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
4196  alglib_impl::ae_state_clear(&_alglib_env_state);
4197  return *(reinterpret_cast<double*>(&result));
4198  }
4200  {
4201  throw ap_error(_alglib_env_state.error_msg);
4202  }
4203 }
4204 
4205 /*************************************************************************
4206 Average cross-entropy (in bits per element) on the test set.
4207 
4208 
4209 FOR USERS OF COMMERCIAL EDITION:
4210 
4211  ! Commercial version of ALGLIB includes two important improvements of
4212  ! this function:
4213  ! * multicore support (C++ and C# computational cores)
4214  ! * SSE support
4215  !
4216  ! First improvement gives close-to-linear speedup on multicore systems.
4217  ! Second improvement gives constant speedup (2-3x depending on your CPU)
4218  !
4219  ! In order to use multicore features you have to:
4220  ! * use commercial version of ALGLIB
4221  ! * call this function with "smp_" prefix, which indicates that
4222  ! multicore code will be used (for multicore support)
4223  !
4224  ! In order to use SSE features you have to:
4225  ! * use commercial version of ALGLIB on Intel processors
4226  ! * use C++ computational core
4227  !
4228  ! This note is given for users of commercial edition; if you use GPL
4229  ! edition, you still will be able to call smp-version of this function,
4230  ! but all computations will be done serially.
4231  !
4232  ! We recommend you to carefully read ALGLIB Reference Manual, section
4233  ! called 'SMP support', before using parallel version of this function.
4234 
4235 
4236 INPUT PARAMETERS:
4237  Network - neural network;
4238  XY - training set, see below for information on the
4239  training set format;
4240  NPoints - points count.
4241 
4242 RESULT:
4243 CrossEntropy/(NPoints*LN(2)).
4244 Zero if network solves regression task.
4245 
4246 DATASET FORMAT:
4247 
4248 This function uses two different dataset formats - one for regression
4249 networks, another one for classification networks.
4250 
4251 For regression networks with NIn inputs and NOut outputs following dataset
4252 format is used:
4253 * dataset is given by NPoints*(NIn+NOut) matrix
4254 * each row corresponds to one example
4255 * first NIn columns are inputs, next NOut columns are outputs
4256 
4257 For classification networks with NIn inputs and NClasses clases following
4258 dataset format is used:
4259 * dataset is given by NPoints*(NIn+1) matrix
4260 * each row corresponds to one example
4261 * first NIn columns are inputs, last column stores class number (from 0 to
4262  NClasses-1).
4263 
4264  -- ALGLIB --
4265  Copyright 08.01.2009 by Bochkanov Sergey
4266 *************************************************************************/
4267 double mlpavgce(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
4268 {
4269  alglib_impl::ae_state _alglib_env_state;
4270  alglib_impl::ae_state_init(&_alglib_env_state);
4271  try
4272  {
4273  double result = alglib_impl::mlpavgce(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
4274  alglib_impl::ae_state_clear(&_alglib_env_state);
4275  return *(reinterpret_cast<double*>(&result));
4276  }
4278  {
4279  throw ap_error(_alglib_env_state.error_msg);
4280  }
4281 }
4282 
4283 
4284 double smp_mlpavgce(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
4285 {
4286  alglib_impl::ae_state _alglib_env_state;
4287  alglib_impl::ae_state_init(&_alglib_env_state);
4288  try
4289  {
4290  double result = alglib_impl::_pexec_mlpavgce(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
4291  alglib_impl::ae_state_clear(&_alglib_env_state);
4292  return *(reinterpret_cast<double*>(&result));
4293  }
4295  {
4296  throw ap_error(_alglib_env_state.error_msg);
4297  }
4298 }
4299 
4300 /*************************************************************************
4301 Average cross-entropy (in bits per element) on the test set given by
4302 sparse matrix.
4303 
4304 
4305 FOR USERS OF COMMERCIAL EDITION:
4306 
4307  ! Commercial version of ALGLIB includes two important improvements of
4308  ! this function:
4309  ! * multicore support (C++ and C# computational cores)
4310  ! * SSE support
4311  !
4312  ! First improvement gives close-to-linear speedup on multicore systems.
4313  ! Second improvement gives constant speedup (2-3x depending on your CPU)
4314  !
4315  ! In order to use multicore features you have to:
4316  ! * use commercial version of ALGLIB
4317  ! * call this function with "smp_" prefix, which indicates that
4318  ! multicore code will be used (for multicore support)
4319  !
4320  ! In order to use SSE features you have to:
4321  ! * use commercial version of ALGLIB on Intel processors
4322  ! * use C++ computational core
4323  !
4324  ! This note is given for users of commercial edition; if you use GPL
4325  ! edition, you still will be able to call smp-version of this function,
4326  ! but all computations will be done serially.
4327  !
4328  ! We recommend you to carefully read ALGLIB Reference Manual, section
4329  ! called 'SMP support', before using parallel version of this function.
4330 
4331 
4332 INPUT PARAMETERS:
4333  Network - neural network;
4334  XY - training set, see below for information on the
4335  training set format. This function checks correctness
4336  of the dataset (no NANs/INFs, class numbers are
4337  correct) and throws exception when incorrect dataset
4338  is passed. Sparse matrix must use CRS format for
4339  storage.
4340  NPoints - points count, >=0.
4341 
4342 RESULT:
4343 CrossEntropy/(NPoints*LN(2)).
4344 Zero if network solves regression task.
4345 
4346 DATASET FORMAT:
4347 
4348 This function uses two different dataset formats - one for regression
4349 networks, another one for classification networks.
4350 
4351 For regression networks with NIn inputs and NOut outputs following dataset
4352 format is used:
4353 * dataset is given by NPoints*(NIn+NOut) matrix
4354 * each row corresponds to one example
4355 * first NIn columns are inputs, next NOut columns are outputs
4356 
4357 For classification networks with NIn inputs and NClasses clases following
4358 dataset format is used:
4359 * dataset is given by NPoints*(NIn+1) matrix
4360 * each row corresponds to one example
4361 * first NIn columns are inputs, last column stores class number (from 0 to
4362  NClasses-1).
4363 
4364  -- ALGLIB --
4365  Copyright 9.08.2012 by Bochkanov Sergey
4366 *************************************************************************/
4367 double mlpavgcesparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
4368 {
4369  alglib_impl::ae_state _alglib_env_state;
4370  alglib_impl::ae_state_init(&_alglib_env_state);
4371  try
4372  {
4373  double result = alglib_impl::mlpavgcesparse(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::sparsematrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
4374  alglib_impl::ae_state_clear(&_alglib_env_state);
4375  return *(reinterpret_cast<double*>(&result));
4376  }
4378  {
4379  throw ap_error(_alglib_env_state.error_msg);
4380  }
4381 }
4382 
4383 
4384 double smp_mlpavgcesparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
4385 {
4386  alglib_impl::ae_state _alglib_env_state;
4387  alglib_impl::ae_state_init(&_alglib_env_state);
4388  try
4389  {
4390  double result = alglib_impl::_pexec_mlpavgcesparse(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::sparsematrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
4391  alglib_impl::ae_state_clear(&_alglib_env_state);
4392  return *(reinterpret_cast<double*>(&result));
4393  }
4395  {
4396  throw ap_error(_alglib_env_state.error_msg);
4397  }
4398 }
4399 
4400 /*************************************************************************
4401 RMS error on the test set given.
4402 
4403 
4404 FOR USERS OF COMMERCIAL EDITION:
4405 
4406  ! Commercial version of ALGLIB includes two important improvements of
4407  ! this function:
4408  ! * multicore support (C++ and C# computational cores)
4409  ! * SSE support
4410  !
4411  ! First improvement gives close-to-linear speedup on multicore systems.
4412  ! Second improvement gives constant speedup (2-3x depending on your CPU)
4413  !
4414  ! In order to use multicore features you have to:
4415  ! * use commercial version of ALGLIB
4416  ! * call this function with "smp_" prefix, which indicates that
4417  ! multicore code will be used (for multicore support)
4418  !
4419  ! In order to use SSE features you have to:
4420  ! * use commercial version of ALGLIB on Intel processors
4421  ! * use C++ computational core
4422  !
4423  ! This note is given for users of commercial edition; if you use GPL
4424  ! edition, you still will be able to call smp-version of this function,
4425  ! but all computations will be done serially.
4426  !
4427  ! We recommend you to carefully read ALGLIB Reference Manual, section
4428  ! called 'SMP support', before using parallel version of this function.
4429 
4430 
4431 INPUT PARAMETERS:
4432  Network - neural network;
4433  XY - training set, see below for information on the
4434  training set format;
4435  NPoints - points count.
4436 
4437 RESULT:
4438 Root mean square error. Its meaning for regression task is obvious. As for
4439 classification task, RMS error means error when estimating posterior
4440 probabilities.
4441 
4442 DATASET FORMAT:
4443 
4444 This function uses two different dataset formats - one for regression
4445 networks, another one for classification networks.
4446 
4447 For regression networks with NIn inputs and NOut outputs following dataset
4448 format is used:
4449 * dataset is given by NPoints*(NIn+NOut) matrix
4450 * each row corresponds to one example
4451 * first NIn columns are inputs, next NOut columns are outputs
4452 
4453 For classification networks with NIn inputs and NClasses clases following
4454 dataset format is used:
4455 * dataset is given by NPoints*(NIn+1) matrix
4456 * each row corresponds to one example
4457 * first NIn columns are inputs, last column stores class number (from 0 to
4458  NClasses-1).
4459 
4460  -- ALGLIB --
4461  Copyright 04.11.2007 by Bochkanov Sergey
4462 *************************************************************************/
4463 double mlprmserror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
4464 {
4465  alglib_impl::ae_state _alglib_env_state;
4466  alglib_impl::ae_state_init(&_alglib_env_state);
4467  try
4468  {
4469  double result = alglib_impl::mlprmserror(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
4470  alglib_impl::ae_state_clear(&_alglib_env_state);
4471  return *(reinterpret_cast<double*>(&result));
4472  }
4474  {
4475  throw ap_error(_alglib_env_state.error_msg);
4476  }
4477 }
4478 
4479 
4480 double smp_mlprmserror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
4481 {
4482  alglib_impl::ae_state _alglib_env_state;
4483  alglib_impl::ae_state_init(&_alglib_env_state);
4484  try
4485  {
4486  double result = alglib_impl::_pexec_mlprmserror(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
4487  alglib_impl::ae_state_clear(&_alglib_env_state);
4488  return *(reinterpret_cast<double*>(&result));
4489  }
4491  {
4492  throw ap_error(_alglib_env_state.error_msg);
4493  }
4494 }
4495 
4496 /*************************************************************************
4497 RMS error on the test set given by sparse matrix.
4498 
4499 
4500 FOR USERS OF COMMERCIAL EDITION:
4501 
4502  ! Commercial version of ALGLIB includes two important improvements of
4503  ! this function:
4504  ! * multicore support (C++ and C# computational cores)
4505  ! * SSE support
4506  !
4507  ! First improvement gives close-to-linear speedup on multicore systems.
4508  ! Second improvement gives constant speedup (2-3x depending on your CPU)
4509  !
4510  ! In order to use multicore features you have to:
4511  ! * use commercial version of ALGLIB
4512  ! * call this function with "smp_" prefix, which indicates that
4513  ! multicore code will be used (for multicore support)
4514  !
4515  ! In order to use SSE features you have to:
4516  ! * use commercial version of ALGLIB on Intel processors
4517  ! * use C++ computational core
4518  !
4519  ! This note is given for users of commercial edition; if you use GPL
4520  ! edition, you still will be able to call smp-version of this function,
4521  ! but all computations will be done serially.
4522  !
4523  ! We recommend you to carefully read ALGLIB Reference Manual, section
4524  ! called 'SMP support', before using parallel version of this function.
4525 
4526 
4527 INPUT PARAMETERS:
4528  Network - neural network;
4529  XY - training set, see below for information on the
4530  training set format. This function checks correctness
4531  of the dataset (no NANs/INFs, class numbers are
4532  correct) and throws exception when incorrect dataset
4533  is passed. Sparse matrix must use CRS format for
4534  storage.
4535  NPoints - points count, >=0.
4536 
4537 RESULT:
4538 Root mean square error. Its meaning for regression task is obvious. As for
4539 classification task, RMS error means error when estimating posterior
4540 probabilities.
4541 
4542 DATASET FORMAT:
4543 
4544 This function uses two different dataset formats - one for regression
4545 networks, another one for classification networks.
4546 
4547 For regression networks with NIn inputs and NOut outputs following dataset
4548 format is used:
4549 * dataset is given by NPoints*(NIn+NOut) matrix
4550 * each row corresponds to one example
4551 * first NIn columns are inputs, next NOut columns are outputs
4552 
4553 For classification networks with NIn inputs and NClasses clases following
4554 dataset format is used:
4555 * dataset is given by NPoints*(NIn+1) matrix
4556 * each row corresponds to one example
4557 * first NIn columns are inputs, last column stores class number (from 0 to
4558  NClasses-1).
4559 
4560  -- ALGLIB --
4561  Copyright 09.08.2012 by Bochkanov Sergey
4562 *************************************************************************/
4563 double mlprmserrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
4564 {
4565  alglib_impl::ae_state _alglib_env_state;
4566  alglib_impl::ae_state_init(&_alglib_env_state);
4567  try
4568  {
4569  double result = alglib_impl::mlprmserrorsparse(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::sparsematrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
4570  alglib_impl::ae_state_clear(&_alglib_env_state);
4571  return *(reinterpret_cast<double*>(&result));
4572  }
4574  {
4575  throw ap_error(_alglib_env_state.error_msg);
4576  }
4577 }
4578 
4579 
4580 double smp_mlprmserrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
4581 {
4582  alglib_impl::ae_state _alglib_env_state;
4583  alglib_impl::ae_state_init(&_alglib_env_state);
4584  try
4585  {
4586  double result = alglib_impl::_pexec_mlprmserrorsparse(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::sparsematrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
4587  alglib_impl::ae_state_clear(&_alglib_env_state);
4588  return *(reinterpret_cast<double*>(&result));
4589  }
4591  {
4592  throw ap_error(_alglib_env_state.error_msg);
4593  }
4594 }
4595 
4596 /*************************************************************************
4597 Average absolute error on the test set.
4598 
4599 
4600 FOR USERS OF COMMERCIAL EDITION:
4601 
4602  ! Commercial version of ALGLIB includes two important improvements of
4603  ! this function:
4604  ! * multicore support (C++ and C# computational cores)
4605  ! * SSE support
4606  !
4607  ! First improvement gives close-to-linear speedup on multicore systems.
4608  ! Second improvement gives constant speedup (2-3x depending on your CPU)
4609  !
4610  ! In order to use multicore features you have to:
4611  ! * use commercial version of ALGLIB
4612  ! * call this function with "smp_" prefix, which indicates that
4613  ! multicore code will be used (for multicore support)
4614  !
4615  ! In order to use SSE features you have to:
4616  ! * use commercial version of ALGLIB on Intel processors
4617  ! * use C++ computational core
4618  !
4619  ! This note is given for users of commercial edition; if you use GPL
4620  ! edition, you still will be able to call smp-version of this function,
4621  ! but all computations will be done serially.
4622  !
4623  ! We recommend you to carefully read ALGLIB Reference Manual, section
4624  ! called 'SMP support', before using parallel version of this function.
4625 
4626 
4627 INPUT PARAMETERS:
4628  Network - neural network;
4629  XY - training set, see below for information on the
4630  training set format;
4631  NPoints - points count.
4632 
4633 RESULT:
4634 Its meaning for regression task is obvious. As for classification task, it
4635 means average error when estimating posterior probabilities.
4636 
4637 DATASET FORMAT:
4638 
4639 This function uses two different dataset formats - one for regression
4640 networks, another one for classification networks.
4641 
4642 For regression networks with NIn inputs and NOut outputs following dataset
4643 format is used:
4644 * dataset is given by NPoints*(NIn+NOut) matrix
4645 * each row corresponds to one example
4646 * first NIn columns are inputs, next NOut columns are outputs
4647 
4648 For classification networks with NIn inputs and NClasses clases following
4649 dataset format is used:
4650 * dataset is given by NPoints*(NIn+1) matrix
4651 * each row corresponds to one example
4652 * first NIn columns are inputs, last column stores class number (from 0 to
4653  NClasses-1).
4654 
4655  -- ALGLIB --
4656  Copyright 11.03.2008 by Bochkanov Sergey
4657 *************************************************************************/
4658 double mlpavgerror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
4659 {
4660  alglib_impl::ae_state _alglib_env_state;
4661  alglib_impl::ae_state_init(&_alglib_env_state);
4662  try
4663  {
4664  double result = alglib_impl::mlpavgerror(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
4665  alglib_impl::ae_state_clear(&_alglib_env_state);
4666  return *(reinterpret_cast<double*>(&result));
4667  }
4669  {
4670  throw ap_error(_alglib_env_state.error_msg);
4671  }
4672 }
4673 
4674 
4675 double smp_mlpavgerror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
4676 {
4677  alglib_impl::ae_state _alglib_env_state;
4678  alglib_impl::ae_state_init(&_alglib_env_state);
4679  try
4680  {
4681  double result = alglib_impl::_pexec_mlpavgerror(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
4682  alglib_impl::ae_state_clear(&_alglib_env_state);
4683  return *(reinterpret_cast<double*>(&result));
4684  }
4686  {
4687  throw ap_error(_alglib_env_state.error_msg);
4688  }
4689 }
4690 
4691 /*************************************************************************
4692 Average absolute error on the test set given by sparse matrix.
4693 
4694 
4695 FOR USERS OF COMMERCIAL EDITION:
4696 
4697  ! Commercial version of ALGLIB includes two important improvements of
4698  ! this function:
4699  ! * multicore support (C++ and C# computational cores)
4700  ! * SSE support
4701  !
4702  ! First improvement gives close-to-linear speedup on multicore systems.
4703  ! Second improvement gives constant speedup (2-3x depending on your CPU)
4704  !
4705  ! In order to use multicore features you have to:
4706  ! * use commercial version of ALGLIB
4707  ! * call this function with "smp_" prefix, which indicates that
4708  ! multicore code will be used (for multicore support)
4709  !
4710  ! In order to use SSE features you have to:
4711  ! * use commercial version of ALGLIB on Intel processors
4712  ! * use C++ computational core
4713  !
4714  ! This note is given for users of commercial edition; if you use GPL
4715  ! edition, you still will be able to call smp-version of this function,
4716  ! but all computations will be done serially.
4717  !
4718  ! We recommend you to carefully read ALGLIB Reference Manual, section
4719  ! called 'SMP support', before using parallel version of this function.
4720 
4721 
4722 INPUT PARAMETERS:
4723  Network - neural network;
4724  XY - training set, see below for information on the
4725  training set format. This function checks correctness
4726  of the dataset (no NANs/INFs, class numbers are
4727  correct) and throws exception when incorrect dataset
4728  is passed. Sparse matrix must use CRS format for
4729  storage.
4730  NPoints - points count, >=0.
4731 
4732 RESULT:
4733 Its meaning for regression task is obvious. As for classification task, it
4734 means average error when estimating posterior probabilities.
4735 
4736 DATASET FORMAT:
4737 
4738 This function uses two different dataset formats - one for regression
4739 networks, another one for classification networks.
4740 
4741 For regression networks with NIn inputs and NOut outputs following dataset
4742 format is used:
4743 * dataset is given by NPoints*(NIn+NOut) matrix
4744 * each row corresponds to one example
4745 * first NIn columns are inputs, next NOut columns are outputs
4746 
4747 For classification networks with NIn inputs and NClasses clases following
4748 dataset format is used:
4749 * dataset is given by NPoints*(NIn+1) matrix
4750 * each row corresponds to one example
4751 * first NIn columns are inputs, last column stores class number (from 0 to
4752  NClasses-1).
4753 
4754  -- ALGLIB --
4755  Copyright 09.08.2012 by Bochkanov Sergey
4756 *************************************************************************/
4757 double mlpavgerrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
4758 {
4759  alglib_impl::ae_state _alglib_env_state;
4760  alglib_impl::ae_state_init(&_alglib_env_state);
4761  try
4762  {
4763  double result = alglib_impl::mlpavgerrorsparse(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::sparsematrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
4764  alglib_impl::ae_state_clear(&_alglib_env_state);
4765  return *(reinterpret_cast<double*>(&result));
4766  }
4768  {
4769  throw ap_error(_alglib_env_state.error_msg);
4770  }
4771 }
4772 
4773 
4774 double smp_mlpavgerrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
4775 {
4776  alglib_impl::ae_state _alglib_env_state;
4777  alglib_impl::ae_state_init(&_alglib_env_state);
4778  try
4779  {
4780  double result = alglib_impl::_pexec_mlpavgerrorsparse(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::sparsematrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
4781  alglib_impl::ae_state_clear(&_alglib_env_state);
4782  return *(reinterpret_cast<double*>(&result));
4783  }
4785  {
4786  throw ap_error(_alglib_env_state.error_msg);
4787  }
4788 }
4789 
4790 /*************************************************************************
4791 Average relative error on the test set.
4792 
4793 
4794 FOR USERS OF COMMERCIAL EDITION:
4795 
4796  ! Commercial version of ALGLIB includes two important improvements of
4797  ! this function:
4798  ! * multicore support (C++ and C# computational cores)
4799  ! * SSE support
4800  !
4801  ! First improvement gives close-to-linear speedup on multicore systems.
4802  ! Second improvement gives constant speedup (2-3x depending on your CPU)
4803  !
4804  ! In order to use multicore features you have to:
4805  ! * use commercial version of ALGLIB
4806  ! * call this function with "smp_" prefix, which indicates that
4807  ! multicore code will be used (for multicore support)
4808  !
4809  ! In order to use SSE features you have to:
4810  ! * use commercial version of ALGLIB on Intel processors
4811  ! * use C++ computational core
4812  !
4813  ! This note is given for users of commercial edition; if you use GPL
4814  ! edition, you still will be able to call smp-version of this function,
4815  ! but all computations will be done serially.
4816  !
4817  ! We recommend you to carefully read ALGLIB Reference Manual, section
4818  ! called 'SMP support', before using parallel version of this function.
4819 
4820 
4821 INPUT PARAMETERS:
4822  Network - neural network;
4823  XY - training set, see below for information on the
4824  training set format;
4825  NPoints - points count.
4826 
4827 RESULT:
4828 Its meaning for regression task is obvious. As for classification task, it
4829 means average relative error when estimating posterior probability of
4830 belonging to the correct class.
4831 
4832 DATASET FORMAT:
4833 
4834 This function uses two different dataset formats - one for regression
4835 networks, another one for classification networks.
4836 
4837 For regression networks with NIn inputs and NOut outputs following dataset
4838 format is used:
4839 * dataset is given by NPoints*(NIn+NOut) matrix
4840 * each row corresponds to one example
4841 * first NIn columns are inputs, next NOut columns are outputs
4842 
4843 For classification networks with NIn inputs and NClasses clases following
4844 dataset format is used:
4845 * dataset is given by NPoints*(NIn+1) matrix
4846 * each row corresponds to one example
4847 * first NIn columns are inputs, last column stores class number (from 0 to
4848  NClasses-1).
4849 
4850  -- ALGLIB --
4851  Copyright 11.03.2008 by Bochkanov Sergey
4852 *************************************************************************/
4853 double mlpavgrelerror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
4854 {
4855  alglib_impl::ae_state _alglib_env_state;
4856  alglib_impl::ae_state_init(&_alglib_env_state);
4857  try
4858  {
4859  double result = alglib_impl::mlpavgrelerror(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
4860  alglib_impl::ae_state_clear(&_alglib_env_state);
4861  return *(reinterpret_cast<double*>(&result));
4862  }
4864  {
4865  throw ap_error(_alglib_env_state.error_msg);
4866  }
4867 }
4868 
4869 
4870 double smp_mlpavgrelerror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
4871 {
4872  alglib_impl::ae_state _alglib_env_state;
4873  alglib_impl::ae_state_init(&_alglib_env_state);
4874  try
4875  {
4876  double result = alglib_impl::_pexec_mlpavgrelerror(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
4877  alglib_impl::ae_state_clear(&_alglib_env_state);
4878  return *(reinterpret_cast<double*>(&result));
4879  }
4881  {
4882  throw ap_error(_alglib_env_state.error_msg);
4883  }
4884 }
4885 
4886 /*************************************************************************
4887 Average relative error on the test set given by sparse matrix.
4888 
4889 
4890 FOR USERS OF COMMERCIAL EDITION:
4891 
4892  ! Commercial version of ALGLIB includes two important improvements of
4893  ! this function:
4894  ! * multicore support (C++ and C# computational cores)
4895  ! * SSE support
4896  !
4897  ! First improvement gives close-to-linear speedup on multicore systems.
4898  ! Second improvement gives constant speedup (2-3x depending on your CPU)
4899  !
4900  ! In order to use multicore features you have to:
4901  ! * use commercial version of ALGLIB
4902  ! * call this function with "smp_" prefix, which indicates that
4903  ! multicore code will be used (for multicore support)
4904  !
4905  ! In order to use SSE features you have to:
4906  ! * use commercial version of ALGLIB on Intel processors
4907  ! * use C++ computational core
4908  !
4909  ! This note is given for users of commercial edition; if you use GPL
4910  ! edition, you still will be able to call smp-version of this function,
4911  ! but all computations will be done serially.
4912  !
4913  ! We recommend you to carefully read ALGLIB Reference Manual, section
4914  ! called 'SMP support', before using parallel version of this function.
4915 
4916 
4917 INPUT PARAMETERS:
4918  Network - neural network;
4919  XY - training set, see below for information on the
4920  training set format. This function checks correctness
4921  of the dataset (no NANs/INFs, class numbers are
4922  correct) and throws exception when incorrect dataset
4923  is passed. Sparse matrix must use CRS format for
4924  storage.
4925  NPoints - points count, >=0.
4926 
4927 RESULT:
4928 Its meaning for regression task is obvious. As for classification task, it
4929 means average relative error when estimating posterior probability of
4930 belonging to the correct class.
4931 
4932 DATASET FORMAT:
4933 
4934 This function uses two different dataset formats - one for regression
4935 networks, another one for classification networks.
4936 
4937 For regression networks with NIn inputs and NOut outputs following dataset
4938 format is used:
4939 * dataset is given by NPoints*(NIn+NOut) matrix
4940 * each row corresponds to one example
4941 * first NIn columns are inputs, next NOut columns are outputs
4942 
4943 For classification networks with NIn inputs and NClasses clases following
4944 dataset format is used:
4945 * dataset is given by NPoints*(NIn+1) matrix
4946 * each row corresponds to one example
4947 * first NIn columns are inputs, last column stores class number (from 0 to
4948  NClasses-1).
4949 
4950  -- ALGLIB --
4951  Copyright 09.08.2012 by Bochkanov Sergey
4952 *************************************************************************/
4953 double mlpavgrelerrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
4954 {
4955  alglib_impl::ae_state _alglib_env_state;
4956  alglib_impl::ae_state_init(&_alglib_env_state);
4957  try
4958  {
4959  double result = alglib_impl::mlpavgrelerrorsparse(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::sparsematrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
4960  alglib_impl::ae_state_clear(&_alglib_env_state);
4961  return *(reinterpret_cast<double*>(&result));
4962  }
4964  {
4965  throw ap_error(_alglib_env_state.error_msg);
4966  }
4967 }
4968 
4969 
4970 double smp_mlpavgrelerrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
4971 {
4972  alglib_impl::ae_state _alglib_env_state;
4973  alglib_impl::ae_state_init(&_alglib_env_state);
4974  try
4975  {
4976  double result = alglib_impl::_pexec_mlpavgrelerrorsparse(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::sparsematrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
4977  alglib_impl::ae_state_clear(&_alglib_env_state);
4978  return *(reinterpret_cast<double*>(&result));
4979  }
4981  {
4982  throw ap_error(_alglib_env_state.error_msg);
4983  }
4984 }
4985 
4986 /*************************************************************************
4987 Gradient calculation
4988 
4989 INPUT PARAMETERS:
4990  Network - network initialized with one of the network creation funcs
4991  X - input vector, length of array must be at least NIn
4992  DesiredY- desired outputs, length of array must be at least NOut
4993  Grad - possibly preallocated array. If size of array is smaller
4994  than WCount, it will be reallocated. It is recommended to
4995  reuse previously allocated array to reduce allocation
4996  overhead.
4997 
4998 OUTPUT PARAMETERS:
4999  E - error function, SUM(sqr(y[i]-desiredy[i])/2,i)
5000  Grad - gradient of E with respect to weights of network, array[WCount]
5001 
5002  -- ALGLIB --
5003  Copyright 04.11.2007 by Bochkanov Sergey
5004 *************************************************************************/
5005 void mlpgrad(const multilayerperceptron &network, const real_1d_array &x, const real_1d_array &desiredy, double &e, real_1d_array &grad)
5006 {
5007  alglib_impl::ae_state _alglib_env_state;
5008  alglib_impl::ae_state_init(&_alglib_env_state);
5009  try
5010  {
5011  alglib_impl::mlpgrad(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(desiredy.c_ptr()), &e, const_cast<alglib_impl::ae_vector*>(grad.c_ptr()), &_alglib_env_state);
5012  alglib_impl::ae_state_clear(&_alglib_env_state);
5013  return;
5014  }
5016  {
5017  throw ap_error(_alglib_env_state.error_msg);
5018  }
5019 }
5020 
5021 /*************************************************************************
5022 Gradient calculation (natural error function is used)
5023 
5024 INPUT PARAMETERS:
5025  Network - network initialized with one of the network creation funcs
5026  X - input vector, length of array must be at least NIn
5027  DesiredY- desired outputs, length of array must be at least NOut
5028  Grad - possibly preallocated array. If size of array is smaller
5029  than WCount, it will be reallocated. It is recommended to
5030  reuse previously allocated array to reduce allocation
5031  overhead.
5032 
5033 OUTPUT PARAMETERS:
5034  E - error function, sum-of-squares for regression networks,
5035  cross-entropy for classification networks.
5036  Grad - gradient of E with respect to weights of network, array[WCount]
5037 
5038  -- ALGLIB --
5039  Copyright 04.11.2007 by Bochkanov Sergey
5040 *************************************************************************/
5041 void mlpgradn(const multilayerperceptron &network, const real_1d_array &x, const real_1d_array &desiredy, double &e, real_1d_array &grad)
5042 {
5043  alglib_impl::ae_state _alglib_env_state;
5044  alglib_impl::ae_state_init(&_alglib_env_state);
5045  try
5046  {
5047  alglib_impl::mlpgradn(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(desiredy.c_ptr()), &e, const_cast<alglib_impl::ae_vector*>(grad.c_ptr()), &_alglib_env_state);
5048  alglib_impl::ae_state_clear(&_alglib_env_state);
5049  return;
5050  }
5052  {
5053  throw ap_error(_alglib_env_state.error_msg);
5054  }
5055 }
5056 
5057 /*************************************************************************
5058 Batch gradient calculation for a set of inputs/outputs
5059 
5060 
5061 FOR USERS OF COMMERCIAL EDITION:
5062 
5063  ! Commercial version of ALGLIB includes two important improvements of
5064  ! this function:
5065  ! * multicore support (C++ and C# computational cores)
5066  ! * SSE support
5067  !
5068  ! First improvement gives close-to-linear speedup on multicore systems.
5069  ! Second improvement gives constant speedup (2-3x depending on your CPU)
5070  !
5071  ! In order to use multicore features you have to:
5072  ! * use commercial version of ALGLIB
5073  ! * call this function with "smp_" prefix, which indicates that
5074  ! multicore code will be used (for multicore support)
5075  !
5076  ! In order to use SSE features you have to:
5077  ! * use commercial version of ALGLIB on Intel processors
5078  ! * use C++ computational core
5079  !
5080  ! This note is given for users of commercial edition; if you use GPL
5081  ! edition, you still will be able to call smp-version of this function,
5082  ! but all computations will be done serially.
5083  !
5084  ! We recommend you to carefully read ALGLIB Reference Manual, section
5085  ! called 'SMP support', before using parallel version of this function.
5086 
5087 
5088 INPUT PARAMETERS:
5089  Network - network initialized with one of the network creation funcs
5090  XY - original dataset in dense format; one sample = one row:
5091  * first NIn columns contain inputs,
5092  * for regression problem, next NOut columns store
5093  desired outputs.
5094  * for classification problem, next column (just one!)
5095  stores class number.
5096  SSize - number of elements in XY
5097  Grad - possibly preallocated array. If size of array is smaller
5098  than WCount, it will be reallocated. It is recommended to
5099  reuse previously allocated array to reduce allocation
5100  overhead.
5101 
5102 OUTPUT PARAMETERS:
5103  E - error function, SUM(sqr(y[i]-desiredy[i])/2,i)
5104  Grad - gradient of E with respect to weights of network, array[WCount]
5105 
5106  -- ALGLIB --
5107  Copyright 04.11.2007 by Bochkanov Sergey
5108 *************************************************************************/
5109 void mlpgradbatch(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize, double &e, real_1d_array &grad)
5110 {
5111  alglib_impl::ae_state _alglib_env_state;
5112  alglib_impl::ae_state_init(&_alglib_env_state);
5113  try
5114  {
5115  alglib_impl::mlpgradbatch(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), ssize, &e, const_cast<alglib_impl::ae_vector*>(grad.c_ptr()), &_alglib_env_state);
5116  alglib_impl::ae_state_clear(&_alglib_env_state);
5117  return;
5118  }
5120  {
5121  throw ap_error(_alglib_env_state.error_msg);
5122  }
5123 }
5124 
5125 
5126 void smp_mlpgradbatch(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize, double &e, real_1d_array &grad)
5127 {
5128  alglib_impl::ae_state _alglib_env_state;
5129  alglib_impl::ae_state_init(&_alglib_env_state);
5130  try
5131  {
5132  alglib_impl::_pexec_mlpgradbatch(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), ssize, &e, const_cast<alglib_impl::ae_vector*>(grad.c_ptr()), &_alglib_env_state);
5133  alglib_impl::ae_state_clear(&_alglib_env_state);
5134  return;
5135  }
5137  {
5138  throw ap_error(_alglib_env_state.error_msg);
5139  }
5140 }
5141 
5142 /*************************************************************************
5143 Batch gradient calculation for a set of inputs/outputs given by sparse
5144 matrices
5145 
5146 
5147 FOR USERS OF COMMERCIAL EDITION:
5148 
5149  ! Commercial version of ALGLIB includes two important improvements of
5150  ! this function:
5151  ! * multicore support (C++ and C# computational cores)
5152  ! * SSE support
5153  !
5154  ! First improvement gives close-to-linear speedup on multicore systems.
5155  ! Second improvement gives constant speedup (2-3x depending on your CPU)
5156  !
5157  ! In order to use multicore features you have to:
5158  ! * use commercial version of ALGLIB
5159  ! * call this function with "smp_" prefix, which indicates that
5160  ! multicore code will be used (for multicore support)
5161  !
5162  ! In order to use SSE features you have to:
5163  ! * use commercial version of ALGLIB on Intel processors
5164  ! * use C++ computational core
5165  !
5166  ! This note is given for users of commercial edition; if you use GPL
5167  ! edition, you still will be able to call smp-version of this function,
5168  ! but all computations will be done serially.
5169  !
5170  ! We recommend you to carefully read ALGLIB Reference Manual, section
5171  ! called 'SMP support', before using parallel version of this function.
5172 
5173 
5174 INPUT PARAMETERS:
5175  Network - network initialized with one of the network creation funcs
5176  XY - original dataset in sparse format; one sample = one row:
5177  * MATRIX MUST BE STORED IN CRS FORMAT
5178  * first NIn columns contain inputs.
5179  * for regression problem, next NOut columns store
5180  desired outputs.
5181  * for classification problem, next column (just one!)
5182  stores class number.
5183  SSize - number of elements in XY
5184  Grad - possibly preallocated array. If size of array is smaller
5185  than WCount, it will be reallocated. It is recommended to
5186  reuse previously allocated array to reduce allocation
5187  overhead.
5188 
5189 OUTPUT PARAMETERS:
5190  E - error function, SUM(sqr(y[i]-desiredy[i])/2,i)
5191  Grad - gradient of E with respect to weights of network, array[WCount]
5192 
5193  -- ALGLIB --
5194  Copyright 26.07.2012 by Bochkanov Sergey
5195 *************************************************************************/
5196 void mlpgradbatchsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t ssize, double &e, real_1d_array &grad)
5197 {
5198  alglib_impl::ae_state _alglib_env_state;
5199  alglib_impl::ae_state_init(&_alglib_env_state);
5200  try
5201  {
5202  alglib_impl::mlpgradbatchsparse(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::sparsematrix*>(xy.c_ptr()), ssize, &e, const_cast<alglib_impl::ae_vector*>(grad.c_ptr()), &_alglib_env_state);
5203  alglib_impl::ae_state_clear(&_alglib_env_state);
5204  return;
5205  }
5207  {
5208  throw ap_error(_alglib_env_state.error_msg);
5209  }
5210 }
5211 
5212 
5213 void smp_mlpgradbatchsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t ssize, double &e, real_1d_array &grad)
5214 {
5215  alglib_impl::ae_state _alglib_env_state;
5216  alglib_impl::ae_state_init(&_alglib_env_state);
5217  try
5218  {
5219  alglib_impl::_pexec_mlpgradbatchsparse(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::sparsematrix*>(xy.c_ptr()), ssize, &e, const_cast<alglib_impl::ae_vector*>(grad.c_ptr()), &_alglib_env_state);
5220  alglib_impl::ae_state_clear(&_alglib_env_state);
5221  return;
5222  }
5224  {
5225  throw ap_error(_alglib_env_state.error_msg);
5226  }
5227 }
5228 
5229 /*************************************************************************
5230 Batch gradient calculation for a subset of dataset
5231 
5232 
5233 FOR USERS OF COMMERCIAL EDITION:
5234 
5235  ! Commercial version of ALGLIB includes two important improvements of
5236  ! this function:
5237  ! * multicore support (C++ and C# computational cores)
5238  ! * SSE support
5239  !
5240  ! First improvement gives close-to-linear speedup on multicore systems.
5241  ! Second improvement gives constant speedup (2-3x depending on your CPU)
5242  !
5243  ! In order to use multicore features you have to:
5244  ! * use commercial version of ALGLIB
5245  ! * call this function with "smp_" prefix, which indicates that
5246  ! multicore code will be used (for multicore support)
5247  !
5248  ! In order to use SSE features you have to:
5249  ! * use commercial version of ALGLIB on Intel processors
5250  ! * use C++ computational core
5251  !
5252  ! This note is given for users of commercial edition; if you use GPL
5253  ! edition, you still will be able to call smp-version of this function,
5254  ! but all computations will be done serially.
5255  !
5256  ! We recommend you to carefully read ALGLIB Reference Manual, section
5257  ! called 'SMP support', before using parallel version of this function.
5258 
5259 
5260 INPUT PARAMETERS:
5261  Network - network initialized with one of the network creation funcs
5262  XY - original dataset in dense format; one sample = one row:
5263  * first NIn columns contain inputs,
5264  * for regression problem, next NOut columns store
5265  desired outputs.
5266  * for classification problem, next column (just one!)
5267  stores class number.
5268  SetSize - real size of XY, SetSize>=0;
5269  Idx - subset of SubsetSize elements, array[SubsetSize]:
5270  * Idx[I] stores row index in the original dataset which is
5271  given by XY. Gradient is calculated with respect to rows
5272  whose indexes are stored in Idx[].
5273  * Idx[] must store correct indexes; this function throws
5274  an exception in case incorrect index (less than 0 or
5275  larger than rows(XY)) is given
5276  * Idx[] may store indexes in any order and even with
5277  repetitions.
5278  SubsetSize- number of elements in Idx[] array:
5279  * positive value means that subset given by Idx[] is processed
5280  * zero value results in zero gradient
5281  * negative value means that full dataset is processed
5282  Grad - possibly preallocated array. If size of array is smaller
5283  than WCount, it will be reallocated. It is recommended to
5284  reuse previously allocated array to reduce allocation
5285  overhead.
5286 
5287 OUTPUT PARAMETERS:
5288  E - error function, SUM(sqr(y[i]-desiredy[i])/2,i)
5289  Grad - gradient of E with respect to weights of network,
5290  array[WCount]
5291 
5292  -- ALGLIB --
5293  Copyright 26.07.2012 by Bochkanov Sergey
5294 *************************************************************************/
5295 void mlpgradbatchsubset(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t setsize, const integer_1d_array &idx, const ae_int_t subsetsize, double &e, real_1d_array &grad)
5296 {
5297  alglib_impl::ae_state _alglib_env_state;
5298  alglib_impl::ae_state_init(&_alglib_env_state);
5299  try
5300  {
5301  alglib_impl::mlpgradbatchsubset(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), setsize, const_cast<alglib_impl::ae_vector*>(idx.c_ptr()), subsetsize, &e, const_cast<alglib_impl::ae_vector*>(grad.c_ptr()), &_alglib_env_state);
5302  alglib_impl::ae_state_clear(&_alglib_env_state);
5303  return;
5304  }
5306  {
5307  throw ap_error(_alglib_env_state.error_msg);
5308  }
5309 }
5310 
5311 
5312 void smp_mlpgradbatchsubset(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t setsize, const integer_1d_array &idx, const ae_int_t subsetsize, double &e, real_1d_array &grad)
5313 {
5314  alglib_impl::ae_state _alglib_env_state;
5315  alglib_impl::ae_state_init(&_alglib_env_state);
5316  try
5317  {
5318  alglib_impl::_pexec_mlpgradbatchsubset(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), setsize, const_cast<alglib_impl::ae_vector*>(idx.c_ptr()), subsetsize, &e, const_cast<alglib_impl::ae_vector*>(grad.c_ptr()), &_alglib_env_state);
5319  alglib_impl::ae_state_clear(&_alglib_env_state);
5320  return;
5321  }
5323  {
5324  throw ap_error(_alglib_env_state.error_msg);
5325  }
5326 }
5327 
5328 /*************************************************************************
5329 Batch gradient calculation for a set of inputs/outputs for a subset of
5330 dataset given by set of indexes.
5331 
5332 
5333 FOR USERS OF COMMERCIAL EDITION:
5334 
5335  ! Commercial version of ALGLIB includes two important improvements of
5336  ! this function:
5337  ! * multicore support (C++ and C# computational cores)
5338  ! * SSE support
5339  !
5340  ! First improvement gives close-to-linear speedup on multicore systems.
5341  ! Second improvement gives constant speedup (2-3x depending on your CPU)
5342  !
5343  ! In order to use multicore features you have to:
5344  ! * use commercial version of ALGLIB
5345  ! * call this function with "smp_" prefix, which indicates that
5346  ! multicore code will be used (for multicore support)
5347  !
5348  ! In order to use SSE features you have to:
5349  ! * use commercial version of ALGLIB on Intel processors
5350  ! * use C++ computational core
5351  !
5352  ! This note is given for users of commercial edition; if you use GPL
5353  ! edition, you still will be able to call smp-version of this function,
5354  ! but all computations will be done serially.
5355  !
5356  ! We recommend you to carefully read ALGLIB Reference Manual, section
5357  ! called 'SMP support', before using parallel version of this function.
5358 
5359 
5360 INPUT PARAMETERS:
5361  Network - network initialized with one of the network creation funcs
5362  XY - original dataset in sparse format; one sample = one row:
5363  * MATRIX MUST BE STORED IN CRS FORMAT
5364  * first NIn columns contain inputs,
5365  * for regression problem, next NOut columns store
5366  desired outputs.
5367  * for classification problem, next column (just one!)
5368  stores class number.
5369  SetSize - real size of XY, SetSize>=0;
5370  Idx - subset of SubsetSize elements, array[SubsetSize]:
5371  * Idx[I] stores row index in the original dataset which is
5372  given by XY. Gradient is calculated with respect to rows
5373  whose indexes are stored in Idx[].
5374  * Idx[] must store correct indexes; this function throws
5375  an exception in case incorrect index (less than 0 or
5376  larger than rows(XY)) is given
5377  * Idx[] may store indexes in any order and even with
5378  repetitions.
5379  SubsetSize- number of elements in Idx[] array:
5380  * positive value means that subset given by Idx[] is processed
5381  * zero value results in zero gradient
5382  * negative value means that full dataset is processed
5383  Grad - possibly preallocated array. If size of array is smaller
5384  than WCount, it will be reallocated. It is recommended to
5385  reuse previously allocated array to reduce allocation
5386  overhead.
5387 
5388 OUTPUT PARAMETERS:
5389  E - error function, SUM(sqr(y[i]-desiredy[i])/2,i)
5390  Grad - gradient of E with respect to weights of network,
5391  array[WCount]
5392 
5393 NOTE: when SubsetSize<0 is used full dataset by call MLPGradBatchSparse
5394  function.
5395 
5396  -- ALGLIB --
5397  Copyright 26.07.2012 by Bochkanov Sergey
5398 *************************************************************************/
5399 void mlpgradbatchsparsesubset(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t setsize, const integer_1d_array &idx, const ae_int_t subsetsize, double &e, real_1d_array &grad)
5400 {
5401  alglib_impl::ae_state _alglib_env_state;
5402  alglib_impl::ae_state_init(&_alglib_env_state);
5403  try
5404  {
5405  alglib_impl::mlpgradbatchsparsesubset(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::sparsematrix*>(xy.c_ptr()), setsize, const_cast<alglib_impl::ae_vector*>(idx.c_ptr()), subsetsize, &e, const_cast<alglib_impl::ae_vector*>(grad.c_ptr()), &_alglib_env_state);
5406  alglib_impl::ae_state_clear(&_alglib_env_state);
5407  return;
5408  }
5410  {
5411  throw ap_error(_alglib_env_state.error_msg);
5412  }
5413 }
5414 
5415 
5416 void smp_mlpgradbatchsparsesubset(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t setsize, const integer_1d_array &idx, const ae_int_t subsetsize, double &e, real_1d_array &grad)
5417 {
5418  alglib_impl::ae_state _alglib_env_state;
5419  alglib_impl::ae_state_init(&_alglib_env_state);
5420  try
5421  {
5422  alglib_impl::_pexec_mlpgradbatchsparsesubset(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::sparsematrix*>(xy.c_ptr()), setsize, const_cast<alglib_impl::ae_vector*>(idx.c_ptr()), subsetsize, &e, const_cast<alglib_impl::ae_vector*>(grad.c_ptr()), &_alglib_env_state);
5423  alglib_impl::ae_state_clear(&_alglib_env_state);
5424  return;
5425  }
5427  {
5428  throw ap_error(_alglib_env_state.error_msg);
5429  }
5430 }
5431 
5432 /*************************************************************************
5433 Batch gradient calculation for a set of inputs/outputs
5434 (natural error function is used)
5435 
5436 INPUT PARAMETERS:
5437  Network - network initialized with one of the network creation funcs
5438  XY - set of inputs/outputs; one sample = one row;
5439  first NIn columns contain inputs,
5440  next NOut columns - desired outputs.
5441  SSize - number of elements in XY
5442  Grad - possibly preallocated array. If size of array is smaller
5443  than WCount, it will be reallocated. It is recommended to
5444  reuse previously allocated array to reduce allocation
5445  overhead.
5446 
5447 OUTPUT PARAMETERS:
5448  E - error function, sum-of-squares for regression networks,
5449  cross-entropy for classification networks.
5450  Grad - gradient of E with respect to weights of network, array[WCount]
5451 
5452  -- ALGLIB --
5453  Copyright 04.11.2007 by Bochkanov Sergey
5454 *************************************************************************/
5455 void mlpgradnbatch(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize, double &e, real_1d_array &grad)
5456 {
5457  alglib_impl::ae_state _alglib_env_state;
5458  alglib_impl::ae_state_init(&_alglib_env_state);
5459  try
5460  {
5461  alglib_impl::mlpgradnbatch(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), ssize, &e, const_cast<alglib_impl::ae_vector*>(grad.c_ptr()), &_alglib_env_state);
5462  alglib_impl::ae_state_clear(&_alglib_env_state);
5463  return;
5464  }
5466  {
5467  throw ap_error(_alglib_env_state.error_msg);
5468  }
5469 }
5470 
5471 /*************************************************************************
5472 Batch Hessian calculation (natural error function) using R-algorithm.
5473 Internal subroutine.
5474 
5475  -- ALGLIB --
5476  Copyright 26.01.2008 by Bochkanov Sergey.
5477 
5478  Hessian calculation based on R-algorithm described in
5479  "Fast Exact Multiplication by the Hessian",
5480  B. A. Pearlmutter,
5481  Neural Computation, 1994.
5482 *************************************************************************/
5483 void mlphessiannbatch(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize, double &e, real_1d_array &grad, real_2d_array &h)
5484 {
5485  alglib_impl::ae_state _alglib_env_state;
5486  alglib_impl::ae_state_init(&_alglib_env_state);
5487  try
5488  {
5489  alglib_impl::mlphessiannbatch(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), ssize, &e, const_cast<alglib_impl::ae_vector*>(grad.c_ptr()), const_cast<alglib_impl::ae_matrix*>(h.c_ptr()), &_alglib_env_state);
5490  alglib_impl::ae_state_clear(&_alglib_env_state);
5491  return;
5492  }
5494  {
5495  throw ap_error(_alglib_env_state.error_msg);
5496  }
5497 }
5498 
5499 /*************************************************************************
5500 Batch Hessian calculation using R-algorithm.
5501 Internal subroutine.
5502 
5503  -- ALGLIB --
5504  Copyright 26.01.2008 by Bochkanov Sergey.
5505 
5506  Hessian calculation based on R-algorithm described in
5507  "Fast Exact Multiplication by the Hessian",
5508  B. A. Pearlmutter,
5509  Neural Computation, 1994.
5510 *************************************************************************/
5511 void mlphessianbatch(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize, double &e, real_1d_array &grad, real_2d_array &h)
5512 {
5513  alglib_impl::ae_state _alglib_env_state;
5514  alglib_impl::ae_state_init(&_alglib_env_state);
5515  try
5516  {
5517  alglib_impl::mlphessianbatch(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), ssize, &e, const_cast<alglib_impl::ae_vector*>(grad.c_ptr()), const_cast<alglib_impl::ae_matrix*>(h.c_ptr()), &_alglib_env_state);
5518  alglib_impl::ae_state_clear(&_alglib_env_state);
5519  return;
5520  }
5522  {
5523  throw ap_error(_alglib_env_state.error_msg);
5524  }
5525 }
5526 
5527 /*************************************************************************
5528 Calculation of all types of errors.
5529 
5530 
5531 FOR USERS OF COMMERCIAL EDITION:
5532 
5533  ! Commercial version of ALGLIB includes two important improvements of
5534  ! this function:
5535  ! * multicore support (C++ and C# computational cores)
5536  ! * SSE support
5537  !
5538  ! First improvement gives close-to-linear speedup on multicore systems.
5539  ! Second improvement gives constant speedup (2-3x depending on your CPU)
5540  !
5541  ! In order to use multicore features you have to:
5542  ! * use commercial version of ALGLIB
5543  ! * call this function with "smp_" prefix, which indicates that
5544  ! multicore code will be used (for multicore support)
5545  !
5546  ! In order to use SSE features you have to:
5547  ! * use commercial version of ALGLIB on Intel processors
5548  ! * use C++ computational core
5549  !
5550  ! This note is given for users of commercial edition; if you use GPL
5551  ! edition, you still will be able to call smp-version of this function,
5552  ! but all computations will be done serially.
5553  !
5554  ! We recommend you to carefully read ALGLIB Reference Manual, section
5555  ! called 'SMP support', before using parallel version of this function.
5556 
5557 
5558 INPUT PARAMETERS:
5559  Network - network initialized with one of the network creation funcs
5560  XY - original dataset; one sample = one row;
5561  first NIn columns contain inputs,
5562  next NOut columns - desired outputs.
5563  SetSize - real size of XY, SetSize>=0;
5564  Subset - subset of SubsetSize elements, array[SubsetSize];
5565  SubsetSize- number of elements in Subset[] array.
5566 
5567 OUTPUT PARAMETERS:
5568  Rep - it contains all type of errors.
5569 
5570 NOTE: when SubsetSize<0 is used full dataset by call MLPGradBatch function.
5571 
5572  -- ALGLIB --
5573  Copyright 04.09.2012 by Bochkanov Sergey
5574 *************************************************************************/
5575 void mlpallerrorssubset(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize, modelerrors &rep)
5576 {
5577  alglib_impl::ae_state _alglib_env_state;
5578  alglib_impl::ae_state_init(&_alglib_env_state);
5579  try
5580  {
5581  alglib_impl::mlpallerrorssubset(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), setsize, const_cast<alglib_impl::ae_vector*>(subset.c_ptr()), subsetsize, const_cast<alglib_impl::modelerrors*>(rep.c_ptr()), &_alglib_env_state);
5582  alglib_impl::ae_state_clear(&_alglib_env_state);
5583  return;
5584  }
5586  {
5587  throw ap_error(_alglib_env_state.error_msg);
5588  }
5589 }
5590 
5591 
5592 void smp_mlpallerrorssubset(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize, modelerrors &rep)
5593 {
5594  alglib_impl::ae_state _alglib_env_state;
5595  alglib_impl::ae_state_init(&_alglib_env_state);
5596  try
5597  {
5598  alglib_impl::_pexec_mlpallerrorssubset(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), setsize, const_cast<alglib_impl::ae_vector*>(subset.c_ptr()), subsetsize, const_cast<alglib_impl::modelerrors*>(rep.c_ptr()), &_alglib_env_state);
5599  alglib_impl::ae_state_clear(&_alglib_env_state);
5600  return;
5601  }
5603  {
5604  throw ap_error(_alglib_env_state.error_msg);
5605  }
5606 }
5607 
5608 /*************************************************************************
5609 Calculation of all types of errors on sparse dataset.
5610 
5611 
5612 FOR USERS OF COMMERCIAL EDITION:
5613 
5614  ! Commercial version of ALGLIB includes two important improvements of
5615  ! this function:
5616  ! * multicore support (C++ and C# computational cores)
5617  ! * SSE support
5618  !
5619  ! First improvement gives close-to-linear speedup on multicore systems.
5620  ! Second improvement gives constant speedup (2-3x depending on your CPU)
5621  !
5622  ! In order to use multicore features you have to:
5623  ! * use commercial version of ALGLIB
5624  ! * call this function with "smp_" prefix, which indicates that
5625  ! multicore code will be used (for multicore support)
5626  !
5627  ! In order to use SSE features you have to:
5628  ! * use commercial version of ALGLIB on Intel processors
5629  ! * use C++ computational core
5630  !
5631  ! This note is given for users of commercial edition; if you use GPL
5632  ! edition, you still will be able to call smp-version of this function,
5633  ! but all computations will be done serially.
5634  !
5635  ! We recommend you to carefully read ALGLIB Reference Manual, section
5636  ! called 'SMP support', before using parallel version of this function.
5637 
5638 
5639 INPUT PARAMETERS:
5640  Network - network initialized with one of the network creation funcs
5641  XY - original dataset given by sparse matrix;
5642  one sample = one row;
5643  first NIn columns contain inputs,
5644  next NOut columns - desired outputs.
5645  SetSize - real size of XY, SetSize>=0;
5646  Subset - subset of SubsetSize elements, array[SubsetSize];
5647  SubsetSize- number of elements in Subset[] array.
5648 
5649 OUTPUT PARAMETERS:
5650  Rep - it contains all type of errors.
5651 
5652 NOTE: when SubsetSize<0 is used full dataset by call MLPGradBatch function.
5653 
5654  -- ALGLIB --
5655  Copyright 04.09.2012 by Bochkanov Sergey
5656 *************************************************************************/
5657 void mlpallerrorssparsesubset(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize, modelerrors &rep)
5658 {
5659  alglib_impl::ae_state _alglib_env_state;
5660  alglib_impl::ae_state_init(&_alglib_env_state);
5661  try
5662  {
5663  alglib_impl::mlpallerrorssparsesubset(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::sparsematrix*>(xy.c_ptr()), setsize, const_cast<alglib_impl::ae_vector*>(subset.c_ptr()), subsetsize, const_cast<alglib_impl::modelerrors*>(rep.c_ptr()), &_alglib_env_state);
5664  alglib_impl::ae_state_clear(&_alglib_env_state);
5665  return;
5666  }
5668  {
5669  throw ap_error(_alglib_env_state.error_msg);
5670  }
5671 }
5672 
5673 
5674 void smp_mlpallerrorssparsesubset(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize, modelerrors &rep)
5675 {
5676  alglib_impl::ae_state _alglib_env_state;
5677  alglib_impl::ae_state_init(&_alglib_env_state);
5678  try
5679  {
5680  alglib_impl::_pexec_mlpallerrorssparsesubset(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::sparsematrix*>(xy.c_ptr()), setsize, const_cast<alglib_impl::ae_vector*>(subset.c_ptr()), subsetsize, const_cast<alglib_impl::modelerrors*>(rep.c_ptr()), &_alglib_env_state);
5681  alglib_impl::ae_state_clear(&_alglib_env_state);
5682  return;
5683  }
5685  {
5686  throw ap_error(_alglib_env_state.error_msg);
5687  }
5688 }
5689 
5690 /*************************************************************************
5691 Error of the neural network on dataset.
5692 
5693 
5694 FOR USERS OF COMMERCIAL EDITION:
5695 
5696  ! Commercial version of ALGLIB includes two important improvements of
5697  ! this function:
5698  ! * multicore support (C++ and C# computational cores)
5699  ! * SSE support
5700  !
5701  ! First improvement gives close-to-linear speedup on multicore systems.
5702  ! Second improvement gives constant speedup (2-3x depending on your CPU)
5703  !
5704  ! In order to use multicore features you have to:
5705  ! * use commercial version of ALGLIB
5706  ! * call this function with "smp_" prefix, which indicates that
5707  ! multicore code will be used (for multicore support)
5708  !
5709  ! In order to use SSE features you have to:
5710  ! * use commercial version of ALGLIB on Intel processors
5711  ! * use C++ computational core
5712  !
5713  ! This note is given for users of commercial edition; if you use GPL
5714  ! edition, you still will be able to call smp-version of this function,
5715  ! but all computations will be done serially.
5716  !
5717  ! We recommend you to carefully read ALGLIB Reference Manual, section
5718  ! called 'SMP support', before using parallel version of this function.
5719 
5720 
5721 INPUT PARAMETERS:
5722  Network - neural network;
5723  XY - training set, see below for information on the
5724  training set format;
5725  SetSize - real size of XY, SetSize>=0;
5726  Subset - subset of SubsetSize elements, array[SubsetSize];
5727  SubsetSize- number of elements in Subset[] array.
5728 
5729 RESULT:
5730  sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2)
5731 
5732 DATASET FORMAT:
5733 
5734 This function uses two different dataset formats - one for regression
5735 networks, another one for classification networks.
5736 
5737 For regression networks with NIn inputs and NOut outputs following dataset
5738 format is used:
5739 * dataset is given by NPoints*(NIn+NOut) matrix
5740 * each row corresponds to one example
5741 * first NIn columns are inputs, next NOut columns are outputs
5742 
5743 For classification networks with NIn inputs and NClasses clases following
5744 dataset format is used:
5745 * dataset is given by NPoints*(NIn+1) matrix
5746 * each row corresponds to one example
5747 * first NIn columns are inputs, last column stores class number (from 0 to
5748  NClasses-1).
5749 
5750  -- ALGLIB --
5751  Copyright 04.09.2012 by Bochkanov Sergey
5752 *************************************************************************/
5753 double mlperrorsubset(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize)
5754 {
5755  alglib_impl::ae_state _alglib_env_state;
5756  alglib_impl::ae_state_init(&_alglib_env_state);
5757  try
5758  {
5759  double result = alglib_impl::mlperrorsubset(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), setsize, const_cast<alglib_impl::ae_vector*>(subset.c_ptr()), subsetsize, &_alglib_env_state);
5760  alglib_impl::ae_state_clear(&_alglib_env_state);
5761  return *(reinterpret_cast<double*>(&result));
5762  }
5764  {
5765  throw ap_error(_alglib_env_state.error_msg);
5766  }
5767 }
5768 
5769 
5770 double smp_mlperrorsubset(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize)
5771 {
5772  alglib_impl::ae_state _alglib_env_state;
5773  alglib_impl::ae_state_init(&_alglib_env_state);
5774  try
5775  {
5776  double result = alglib_impl::_pexec_mlperrorsubset(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), setsize, const_cast<alglib_impl::ae_vector*>(subset.c_ptr()), subsetsize, &_alglib_env_state);
5777  alglib_impl::ae_state_clear(&_alglib_env_state);
5778  return *(reinterpret_cast<double*>(&result));
5779  }
5781  {
5782  throw ap_error(_alglib_env_state.error_msg);
5783  }
5784 }
5785 
5786 /*************************************************************************
5787 Error of the neural network on sparse dataset.
5788 
5789 
5790 FOR USERS OF COMMERCIAL EDITION:
5791 
5792  ! Commercial version of ALGLIB includes two important improvements of
5793  ! this function:
5794  ! * multicore support (C++ and C# computational cores)
5795  ! * SSE support
5796  !
5797  ! First improvement gives close-to-linear speedup on multicore systems.
5798  ! Second improvement gives constant speedup (2-3x depending on your CPU)
5799  !
5800  ! In order to use multicore features you have to:
5801  ! * use commercial version of ALGLIB
5802  ! * call this function with "smp_" prefix, which indicates that
5803  ! multicore code will be used (for multicore support)
5804  !
5805  ! In order to use SSE features you have to:
5806  ! * use commercial version of ALGLIB on Intel processors
5807  ! * use C++ computational core
5808  !
5809  ! This note is given for users of commercial edition; if you use GPL
5810  ! edition, you still will be able to call smp-version of this function,
5811  ! but all computations will be done serially.
5812  !
5813  ! We recommend you to carefully read ALGLIB Reference Manual, section
5814  ! called 'SMP support', before using parallel version of this function.
5815 
5816 
5817 INPUT PARAMETERS:
5818  Network - neural network;
5819  XY - training set, see below for information on the
5820  training set format. This function checks correctness
5821  of the dataset (no NANs/INFs, class numbers are
5822  correct) and throws exception when incorrect dataset
5823  is passed. Sparse matrix must use CRS format for
5824  storage.
5825  SetSize - real size of XY, SetSize>=0;
5826  it is used when SubsetSize<0;
5827  Subset - subset of SubsetSize elements, array[SubsetSize];
5828  SubsetSize- number of elements in Subset[] array.
5829 
5830 RESULT:
5831  sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2)
5832 
5833 DATASET FORMAT:
5834 
5835 This function uses two different dataset formats - one for regression
5836 networks, another one for classification networks.
5837 
5838 For regression networks with NIn inputs and NOut outputs following dataset
5839 format is used:
5840 * dataset is given by NPoints*(NIn+NOut) matrix
5841 * each row corresponds to one example
5842 * first NIn columns are inputs, next NOut columns are outputs
5843 
5844 For classification networks with NIn inputs and NClasses clases following
5845 dataset format is used:
5846 * dataset is given by NPoints*(NIn+1) matrix
5847 * each row corresponds to one example
5848 * first NIn columns are inputs, last column stores class number (from 0 to
5849  NClasses-1).
5850 
5851  -- ALGLIB --
5852  Copyright 04.09.2012 by Bochkanov Sergey
5853 *************************************************************************/
5854 double mlperrorsparsesubset(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize)
5855 {
5856  alglib_impl::ae_state _alglib_env_state;
5857  alglib_impl::ae_state_init(&_alglib_env_state);
5858  try
5859  {
5860  double result = alglib_impl::mlperrorsparsesubset(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::sparsematrix*>(xy.c_ptr()), setsize, const_cast<alglib_impl::ae_vector*>(subset.c_ptr()), subsetsize, &_alglib_env_state);
5861  alglib_impl::ae_state_clear(&_alglib_env_state);
5862  return *(reinterpret_cast<double*>(&result));
5863  }
5865  {
5866  throw ap_error(_alglib_env_state.error_msg);
5867  }
5868 }
5869 
5870 
5871 double smp_mlperrorsparsesubset(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize)
5872 {
5873  alglib_impl::ae_state _alglib_env_state;
5874  alglib_impl::ae_state_init(&_alglib_env_state);
5875  try
5876  {
5877  double result = alglib_impl::_pexec_mlperrorsparsesubset(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::sparsematrix*>(xy.c_ptr()), setsize, const_cast<alglib_impl::ae_vector*>(subset.c_ptr()), subsetsize, &_alglib_env_state);
5878  alglib_impl::ae_state_clear(&_alglib_env_state);
5879  return *(reinterpret_cast<double*>(&result));
5880  }
5882  {
5883  throw ap_error(_alglib_env_state.error_msg);
5884  }
5885 }
5886 
5887 /*************************************************************************
5888 
5889 *************************************************************************/
5891 {
5893  if( p_struct==NULL )
5894  throw ap_error("ALGLIB: malloc error");
5896  throw ap_error("ALGLIB: malloc error");
5897 }
5898 
5900 {
5902  if( p_struct==NULL )
5903  throw ap_error("ALGLIB: malloc error");
5904  if( !alglib_impl::_logitmodel_init_copy(p_struct, const_cast<alglib_impl::logitmodel*>(rhs.p_struct), NULL, ae_false) )
5905  throw ap_error("ALGLIB: malloc error");
5906 }
5907 
5909 {
5910  if( this==&rhs )
5911  return *this;
5913  if( !alglib_impl::_logitmodel_init_copy(p_struct, const_cast<alglib_impl::logitmodel*>(rhs.p_struct), NULL, ae_false) )
5914  throw ap_error("ALGLIB: malloc error");
5915  return *this;
5916 }
5917 
5919 {
5921  ae_free(p_struct);
5922 }
5923 
5925 {
5926  return p_struct;
5927 }
5928 
5930 {
5931  return const_cast<alglib_impl::logitmodel*>(p_struct);
5932 }
5934 {
5935 }
5936 
5938 {
5939 }
5940 
5942 {
5943  if( this==&rhs )
5944  return *this;
5946  return *this;
5947 }
5948 
5950 {
5951 }
5952 
5953 
5954 /*************************************************************************
5955 MNLReport structure contains information about training process:
5956 * NGrad - number of gradient calculations
5957 * NHess - number of Hessian calculations
5958 *************************************************************************/
5960 {
5962  if( p_struct==NULL )
5963  throw ap_error("ALGLIB: malloc error");
5965  throw ap_error("ALGLIB: malloc error");
5966 }
5967 
5969 {
5971  if( p_struct==NULL )
5972  throw ap_error("ALGLIB: malloc error");
5973  if( !alglib_impl::_mnlreport_init_copy(p_struct, const_cast<alglib_impl::mnlreport*>(rhs.p_struct), NULL, ae_false) )
5974  throw ap_error("ALGLIB: malloc error");
5975 }
5976 
5978 {
5979  if( this==&rhs )
5980  return *this;
5982  if( !alglib_impl::_mnlreport_init_copy(p_struct, const_cast<alglib_impl::mnlreport*>(rhs.p_struct), NULL, ae_false) )
5983  throw ap_error("ALGLIB: malloc error");
5984  return *this;
5985 }
5986 
5988 {
5990  ae_free(p_struct);
5991 }
5992 
5994 {
5995  return p_struct;
5996 }
5997 
5999 {
6000  return const_cast<alglib_impl::mnlreport*>(p_struct);
6001 }
6002 mnlreport::mnlreport() : _mnlreport_owner() ,ngrad(p_struct->ngrad),nhess(p_struct->nhess)
6003 {
6004 }
6005 
6007 {
6008 }
6009 
6011 {
6012  if( this==&rhs )
6013  return *this;
6015  return *this;
6016 }
6017 
6019 {
6020 }
6021 
6022 /*************************************************************************
6023 This subroutine trains logit model.
6024 
6025 INPUT PARAMETERS:
6026  XY - training set, array[0..NPoints-1,0..NVars]
6027  First NVars columns store values of independent
6028  variables, next column stores number of class (from 0
6029  to NClasses-1) which dataset element belongs to. Fractional
6030  values are rounded to nearest integer.
6031  NPoints - training set size, NPoints>=1
6032  NVars - number of independent variables, NVars>=1
6033  NClasses - number of classes, NClasses>=2
6034 
6035 OUTPUT PARAMETERS:
6036  Info - return code:
6037  * -2, if there is a point with class number
6038  outside of [0..NClasses-1].
6039  * -1, if incorrect parameters was passed
6040  (NPoints<NVars+2, NVars<1, NClasses<2).
6041  * 1, if task has been solved
6042  LM - model built
6043  Rep - training report
6044 
6045  -- ALGLIB --
6046  Copyright 10.09.2008 by Bochkanov Sergey
6047 *************************************************************************/
6048 void mnltrainh(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nclasses, ae_int_t &info, logitmodel &lm, mnlreport &rep)
6049 {
6050  alglib_impl::ae_state _alglib_env_state;
6051  alglib_impl::ae_state_init(&_alglib_env_state);
6052  try
6053  {
6054  alglib_impl::mnltrainh(const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, nvars, nclasses, &info, const_cast<alglib_impl::logitmodel*>(lm.c_ptr()), const_cast<alglib_impl::mnlreport*>(rep.c_ptr()), &_alglib_env_state);
6055  alglib_impl::ae_state_clear(&_alglib_env_state);
6056  return;
6057  }
6059  {
6060  throw ap_error(_alglib_env_state.error_msg);
6061  }
6062 }
6063 
6064 /*************************************************************************
6065 Procesing
6066 
6067 INPUT PARAMETERS:
6068  LM - logit model, passed by non-constant reference
6069  (some fields of structure are used as temporaries
6070  when calculating model output).
6071  X - input vector, array[0..NVars-1].
6072  Y - (possibly) preallocated buffer; if size of Y is less than
6073  NClasses, it will be reallocated.If it is large enough, it
6074  is NOT reallocated, so we can save some time on reallocation.
6075 
6076 OUTPUT PARAMETERS:
6077  Y - result, array[0..NClasses-1]
6078  Vector of posterior probabilities for classification task.
6079 
6080  -- ALGLIB --
6081  Copyright 10.09.2008 by Bochkanov Sergey
6082 *************************************************************************/
6084 {
6085  alglib_impl::ae_state _alglib_env_state;
6086  alglib_impl::ae_state_init(&_alglib_env_state);
6087  try
6088  {
6089  alglib_impl::mnlprocess(const_cast<alglib_impl::logitmodel*>(lm.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), &_alglib_env_state);
6090  alglib_impl::ae_state_clear(&_alglib_env_state);
6091  return;
6092  }
6094  {
6095  throw ap_error(_alglib_env_state.error_msg);
6096  }
6097 }
6098 
6099 /*************************************************************************
6100 'interactive' variant of MNLProcess for languages like Python which
6101 support constructs like "Y = MNLProcess(LM,X)" and interactive mode of the
6102 interpreter
6103 
6104 This function allocates new array on each call, so it is significantly
6105 slower than its 'non-interactive' counterpart, but it is more convenient
6106 when you call it from command line.
6107 
6108  -- ALGLIB --
6109  Copyright 10.09.2008 by Bochkanov Sergey
6110 *************************************************************************/
6112 {
6113  alglib_impl::ae_state _alglib_env_state;
6114  alglib_impl::ae_state_init(&_alglib_env_state);
6115  try
6116  {
6117  alglib_impl::mnlprocessi(const_cast<alglib_impl::logitmodel*>(lm.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), &_alglib_env_state);
6118  alglib_impl::ae_state_clear(&_alglib_env_state);
6119  return;
6120  }
6122  {
6123  throw ap_error(_alglib_env_state.error_msg);
6124  }
6125 }
6126 
6127 /*************************************************************************
6128 Unpacks coefficients of logit model. Logit model have form:
6129 
6130  P(class=i) = S(i) / (S(0) + S(1) + ... +S(M-1))
6131  S(i) = Exp(A[i,0]*X[0] + ... + A[i,N-1]*X[N-1] + A[i,N]), when i<M-1
6132  S(M-1) = 1
6133 
6134 INPUT PARAMETERS:
6135  LM - logit model in ALGLIB format
6136 
6137 OUTPUT PARAMETERS:
6138  V - coefficients, array[0..NClasses-2,0..NVars]
6139  NVars - number of independent variables
6140  NClasses - number of classes
6141 
6142  -- ALGLIB --
6143  Copyright 10.09.2008 by Bochkanov Sergey
6144 *************************************************************************/
6145 void mnlunpack(const logitmodel &lm, real_2d_array &a, ae_int_t &nvars, ae_int_t &nclasses)
6146 {
6147  alglib_impl::ae_state _alglib_env_state;
6148  alglib_impl::ae_state_init(&_alglib_env_state);
6149  try
6150  {
6151  alglib_impl::mnlunpack(const_cast<alglib_impl::logitmodel*>(lm.c_ptr()), const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), &nvars, &nclasses, &_alglib_env_state);
6152  alglib_impl::ae_state_clear(&_alglib_env_state);
6153  return;
6154  }
6156  {
6157  throw ap_error(_alglib_env_state.error_msg);
6158  }
6159 }
6160 
6161 /*************************************************************************
6162 "Packs" coefficients and creates logit model in ALGLIB format (MNLUnpack
6163 reversed).
6164 
6165 INPUT PARAMETERS:
6166  A - model (see MNLUnpack)
6167  NVars - number of independent variables
6168  NClasses - number of classes
6169 
6170 OUTPUT PARAMETERS:
6171  LM - logit model.
6172 
6173  -- ALGLIB --
6174  Copyright 10.09.2008 by Bochkanov Sergey
6175 *************************************************************************/
6176 void mnlpack(const real_2d_array &a, const ae_int_t nvars, const ae_int_t nclasses, logitmodel &lm)
6177 {
6178  alglib_impl::ae_state _alglib_env_state;
6179  alglib_impl::ae_state_init(&_alglib_env_state);
6180  try
6181  {
6182  alglib_impl::mnlpack(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), nvars, nclasses, const_cast<alglib_impl::logitmodel*>(lm.c_ptr()), &_alglib_env_state);
6183  alglib_impl::ae_state_clear(&_alglib_env_state);
6184  return;
6185  }
6187  {
6188  throw ap_error(_alglib_env_state.error_msg);
6189  }
6190 }
6191 
6192 /*************************************************************************
6193 Average cross-entropy (in bits per element) on the test set
6194 
6195 INPUT PARAMETERS:
6196  LM - logit model
6197  XY - test set
6198  NPoints - test set size
6199 
6200 RESULT:
6201  CrossEntropy/(NPoints*ln(2)).
6202 
6203  -- ALGLIB --
6204  Copyright 10.09.2008 by Bochkanov Sergey
6205 *************************************************************************/
6206 double mnlavgce(const logitmodel &lm, const real_2d_array &xy, const ae_int_t npoints)
6207 {
6208  alglib_impl::ae_state _alglib_env_state;
6209  alglib_impl::ae_state_init(&_alglib_env_state);
6210  try
6211  {
6212  double result = alglib_impl::mnlavgce(const_cast<alglib_impl::logitmodel*>(lm.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
6213  alglib_impl::ae_state_clear(&_alglib_env_state);
6214  return *(reinterpret_cast<double*>(&result));
6215  }
6217  {
6218  throw ap_error(_alglib_env_state.error_msg);
6219  }
6220 }
6221 
6222 /*************************************************************************
6223 Relative classification error on the test set
6224 
6225 INPUT PARAMETERS:
6226  LM - logit model
6227  XY - test set
6228  NPoints - test set size
6229 
6230 RESULT:
6231  percent of incorrectly classified cases.
6232 
6233  -- ALGLIB --
6234  Copyright 10.09.2008 by Bochkanov Sergey
6235 *************************************************************************/
6236 double mnlrelclserror(const logitmodel &lm, const real_2d_array &xy, const ae_int_t npoints)
6237 {
6238  alglib_impl::ae_state _alglib_env_state;
6239  alglib_impl::ae_state_init(&_alglib_env_state);
6240  try
6241  {
6242  double result = alglib_impl::mnlrelclserror(const_cast<alglib_impl::logitmodel*>(lm.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
6243  alglib_impl::ae_state_clear(&_alglib_env_state);
6244  return *(reinterpret_cast<double*>(&result));
6245  }
6247  {
6248  throw ap_error(_alglib_env_state.error_msg);
6249  }
6250 }
6251 
6252 /*************************************************************************
6253 RMS error on the test set
6254 
6255 INPUT PARAMETERS:
6256  LM - logit model
6257  XY - test set
6258  NPoints - test set size
6259 
6260 RESULT:
6261  root mean square error (error when estimating posterior probabilities).
6262 
6263  -- ALGLIB --
6264  Copyright 30.08.2008 by Bochkanov Sergey
6265 *************************************************************************/
6266 double mnlrmserror(const logitmodel &lm, const real_2d_array &xy, const ae_int_t npoints)
6267 {
6268  alglib_impl::ae_state _alglib_env_state;
6269  alglib_impl::ae_state_init(&_alglib_env_state);
6270  try
6271  {
6272  double result = alglib_impl::mnlrmserror(const_cast<alglib_impl::logitmodel*>(lm.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
6273  alglib_impl::ae_state_clear(&_alglib_env_state);
6274  return *(reinterpret_cast<double*>(&result));
6275  }
6277  {
6278  throw ap_error(_alglib_env_state.error_msg);
6279  }
6280 }
6281 
6282 /*************************************************************************
6283 Average error on the test set
6284 
6285 INPUT PARAMETERS:
6286  LM - logit model
6287  XY - test set
6288  NPoints - test set size
6289 
6290 RESULT:
6291  average error (error when estimating posterior probabilities).
6292 
6293  -- ALGLIB --
6294  Copyright 30.08.2008 by Bochkanov Sergey
6295 *************************************************************************/
6296 double mnlavgerror(const logitmodel &lm, const real_2d_array &xy, const ae_int_t npoints)
6297 {
6298  alglib_impl::ae_state _alglib_env_state;
6299  alglib_impl::ae_state_init(&_alglib_env_state);
6300  try
6301  {
6302  double result = alglib_impl::mnlavgerror(const_cast<alglib_impl::logitmodel*>(lm.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
6303  alglib_impl::ae_state_clear(&_alglib_env_state);
6304  return *(reinterpret_cast<double*>(&result));
6305  }
6307  {
6308  throw ap_error(_alglib_env_state.error_msg);
6309  }
6310 }
6311 
6312 /*************************************************************************
6313 Average relative error on the test set
6314 
6315 INPUT PARAMETERS:
6316  LM - logit model
6317  XY - test set
6318  NPoints - test set size
6319 
6320 RESULT:
6321  average relative error (error when estimating posterior probabilities).
6322 
6323  -- ALGLIB --
6324  Copyright 30.08.2008 by Bochkanov Sergey
6325 *************************************************************************/
6326 double mnlavgrelerror(const logitmodel &lm, const real_2d_array &xy, const ae_int_t ssize)
6327 {
6328  alglib_impl::ae_state _alglib_env_state;
6329  alglib_impl::ae_state_init(&_alglib_env_state);
6330  try
6331  {
6332  double result = alglib_impl::mnlavgrelerror(const_cast<alglib_impl::logitmodel*>(lm.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), ssize, &_alglib_env_state);
6333  alglib_impl::ae_state_clear(&_alglib_env_state);
6334  return *(reinterpret_cast<double*>(&result));
6335  }
6337  {
6338  throw ap_error(_alglib_env_state.error_msg);
6339  }
6340 }
6341 
6342 /*************************************************************************
6343 Classification error on test set = MNLRelClsError*NPoints
6344 
6345  -- ALGLIB --
6346  Copyright 10.09.2008 by Bochkanov Sergey
6347 *************************************************************************/
6348 ae_int_t mnlclserror(const logitmodel &lm, const real_2d_array &xy, const ae_int_t npoints)
6349 {
6350  alglib_impl::ae_state _alglib_env_state;
6351  alglib_impl::ae_state_init(&_alglib_env_state);
6352  try
6353  {
6354  alglib_impl::ae_int_t result = alglib_impl::mnlclserror(const_cast<alglib_impl::logitmodel*>(lm.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
6355  alglib_impl::ae_state_clear(&_alglib_env_state);
6356  return *(reinterpret_cast<ae_int_t*>(&result));
6357  }
6359  {
6360  throw ap_error(_alglib_env_state.error_msg);
6361  }
6362 }
6363 
6364 /*************************************************************************
6365 This structure is a MCPD (Markov Chains for Population Data) solver.
6366 
6367 You should use ALGLIB functions in order to work with this object.
6368 
6369  -- ALGLIB --
6370  Copyright 23.05.2010 by Bochkanov Sergey
6371 *************************************************************************/
6373 {
6375  if( p_struct==NULL )
6376  throw ap_error("ALGLIB: malloc error");
6378  throw ap_error("ALGLIB: malloc error");
6379 }
6380 
6382 {
6384  if( p_struct==NULL )
6385  throw ap_error("ALGLIB: malloc error");
6386  if( !alglib_impl::_mcpdstate_init_copy(p_struct, const_cast<alglib_impl::mcpdstate*>(rhs.p_struct), NULL, ae_false) )
6387  throw ap_error("ALGLIB: malloc error");
6388 }
6389 
6391 {
6392  if( this==&rhs )
6393  return *this;
6395  if( !alglib_impl::_mcpdstate_init_copy(p_struct, const_cast<alglib_impl::mcpdstate*>(rhs.p_struct), NULL, ae_false) )
6396  throw ap_error("ALGLIB: malloc error");
6397  return *this;
6398 }
6399 
6401 {
6403  ae_free(p_struct);
6404 }
6405 
6407 {
6408  return p_struct;
6409 }
6410 
6412 {
6413  return const_cast<alglib_impl::mcpdstate*>(p_struct);
6414 }
6416 {
6417 }
6418 
6420 {
6421 }
6422 
6424 {
6425  if( this==&rhs )
6426  return *this;
6428  return *this;
6429 }
6430 
6432 {
6433 }
6434 
6435 
6436 /*************************************************************************
6437 This structure is a MCPD training report:
6438  InnerIterationsCount - number of inner iterations of the
6439  underlying optimization algorithm
6440  OuterIterationsCount - number of outer iterations of the
6441  underlying optimization algorithm
6442  NFEV - number of merit function evaluations
6443  TerminationType - termination type
6444  (same as for MinBLEIC optimizer, positive
6445  values denote success, negative ones -
6446  failure)
6447 
6448  -- ALGLIB --
6449  Copyright 23.05.2010 by Bochkanov Sergey
6450 *************************************************************************/
6452 {
6454  if( p_struct==NULL )
6455  throw ap_error("ALGLIB: malloc error");
6457  throw ap_error("ALGLIB: malloc error");
6458 }
6459 
6461 {
6463  if( p_struct==NULL )
6464  throw ap_error("ALGLIB: malloc error");
6465  if( !alglib_impl::_mcpdreport_init_copy(p_struct, const_cast<alglib_impl::mcpdreport*>(rhs.p_struct), NULL, ae_false) )
6466  throw ap_error("ALGLIB: malloc error");
6467 }
6468 
6470 {
6471  if( this==&rhs )
6472  return *this;
6474  if( !alglib_impl::_mcpdreport_init_copy(p_struct, const_cast<alglib_impl::mcpdreport*>(rhs.p_struct), NULL, ae_false) )
6475  throw ap_error("ALGLIB: malloc error");
6476  return *this;
6477 }
6478 
6480 {
6482  ae_free(p_struct);
6483 }
6484 
6486 {
6487  return p_struct;
6488 }
6489 
6491 {
6492  return const_cast<alglib_impl::mcpdreport*>(p_struct);
6493 }
6494 mcpdreport::mcpdreport() : _mcpdreport_owner() ,inneriterationscount(p_struct->inneriterationscount),outeriterationscount(p_struct->outeriterationscount),nfev(p_struct->nfev),terminationtype(p_struct->terminationtype)
6495 {
6496 }
6497 
6499 {
6500 }
6501 
6503 {
6504  if( this==&rhs )
6505  return *this;
6507  return *this;
6508 }
6509 
6511 {
6512 }
6513 
6514 /*************************************************************************
6515 DESCRIPTION:
6516 
6517 This function creates MCPD (Markov Chains for Population Data) solver.
6518 
6519 This solver can be used to find transition matrix P for N-dimensional
6520 prediction problem where transition from X[i] to X[i+1] is modelled as
6521  X[i+1] = P*X[i]
6522 where X[i] and X[i+1] are N-dimensional population vectors (components of
6523 each X are non-negative), and P is a N*N transition matrix (elements of P
6524 are non-negative, each column sums to 1.0).
6525 
6526 Such models arise when when:
6527 * there is some population of individuals
6528 * individuals can have different states
6529 * individuals can transit from one state to another
6530 * population size is constant, i.e. there is no new individuals and no one
6531  leaves population
6532 * you want to model transitions of individuals from one state into another
6533 
6534 USAGE:
6535 
6536 Here we give very brief outline of the MCPD. We strongly recommend you to
6537 read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide
6538 on data analysis which is available at http://www.alglib.net/dataanalysis/
6539 
6540 1. User initializes algorithm state with MCPDCreate() call
6541 
6542 2. User adds one or more tracks - sequences of states which describe
6543  evolution of a system being modelled from different starting conditions
6544 
6545 3. User may add optional boundary, equality and/or linear constraints on
6546  the coefficients of P by calling one of the following functions:
6547  * MCPDSetEC() to set equality constraints
6548  * MCPDSetBC() to set bound constraints
6549  * MCPDSetLC() to set linear constraints
6550 
6551 4. Optionally, user may set custom weights for prediction errors (by
6552  default, algorithm assigns non-equal, automatically chosen weights for
6553  errors in the prediction of different components of X). It can be done
6554  with a call of MCPDSetPredictionWeights() function.
6555 
6556 5. User calls MCPDSolve() function which takes algorithm state and
6557  pointer (delegate, etc.) to callback function which calculates F/G.
6558 
6559 6. User calls MCPDResults() to get solution
6560 
6561 INPUT PARAMETERS:
6562  N - problem dimension, N>=1
6563 
6564 OUTPUT PARAMETERS:
6565  State - structure stores algorithm state
6566 
6567  -- ALGLIB --
6568  Copyright 23.05.2010 by Bochkanov Sergey
6569 *************************************************************************/
6571 {
6572  alglib_impl::ae_state _alglib_env_state;
6573  alglib_impl::ae_state_init(&_alglib_env_state);
6574  try
6575  {
6576  alglib_impl::mcpdcreate(n, const_cast<alglib_impl::mcpdstate*>(s.c_ptr()), &_alglib_env_state);
6577  alglib_impl::ae_state_clear(&_alglib_env_state);
6578  return;
6579  }
6581  {
6582  throw ap_error(_alglib_env_state.error_msg);
6583  }
6584 }
6585 
6586 /*************************************************************************
6587 DESCRIPTION:
6588 
6589 This function is a specialized version of MCPDCreate() function, and we
6590 recommend you to read comments for this function for general information
6591 about MCPD solver.
6592 
6593 This function creates MCPD (Markov Chains for Population Data) solver
6594 for "Entry-state" model, i.e. model where transition from X[i] to X[i+1]
6595 is modelled as
6596  X[i+1] = P*X[i]
6597 where
6598  X[i] and X[i+1] are N-dimensional state vectors
6599  P is a N*N transition matrix
6600 and one selected component of X[] is called "entry" state and is treated
6601 in a special way:
6602  system state always transits from "entry" state to some another state
6603  system state can not transit from any state into "entry" state
6604 Such conditions basically mean that row of P which corresponds to "entry"
6605 state is zero.
6606 
6607 Such models arise when:
6608 * there is some population of individuals
6609 * individuals can have different states
6610 * individuals can transit from one state to another
6611 * population size is NOT constant - at every moment of time there is some
6612  (unpredictable) amount of "new" individuals, which can transit into one
6613  of the states at the next turn, but still no one leaves population
6614 * you want to model transitions of individuals from one state into another
6615 * but you do NOT want to predict amount of "new" individuals because it
6616  does not depends on individuals already present (hence system can not
6617  transit INTO entry state - it can only transit FROM it).
6618 
6619 This model is discussed in more details in the ALGLIB User Guide (see
6620 http://www.alglib.net/dataanalysis/ for more data).
6621 
6622 INPUT PARAMETERS:
6623  N - problem dimension, N>=2
6624  EntryState- index of entry state, in 0..N-1
6625 
6626 OUTPUT PARAMETERS:
6627  State - structure stores algorithm state
6628 
6629  -- ALGLIB --
6630  Copyright 23.05.2010 by Bochkanov Sergey
6631 *************************************************************************/
6632 void mcpdcreateentry(const ae_int_t n, const ae_int_t entrystate, mcpdstate &s)
6633 {
6634  alglib_impl::ae_state _alglib_env_state;
6635  alglib_impl::ae_state_init(&_alglib_env_state);
6636  try
6637  {
6638  alglib_impl::mcpdcreateentry(n, entrystate, const_cast<alglib_impl::mcpdstate*>(s.c_ptr()), &_alglib_env_state);
6639  alglib_impl::ae_state_clear(&_alglib_env_state);
6640  return;
6641  }
6643  {
6644  throw ap_error(_alglib_env_state.error_msg);
6645  }
6646 }
6647 
6648 /*************************************************************************
6649 DESCRIPTION:
6650 
6651 This function is a specialized version of MCPDCreate() function, and we
6652 recommend you to read comments for this function for general information
6653 about MCPD solver.
6654 
6655 This function creates MCPD (Markov Chains for Population Data) solver
6656 for "Exit-state" model, i.e. model where transition from X[i] to X[i+1]
6657 is modelled as
6658  X[i+1] = P*X[i]
6659 where
6660  X[i] and X[i+1] are N-dimensional state vectors
6661  P is a N*N transition matrix
6662 and one selected component of X[] is called "exit" state and is treated
6663 in a special way:
6664  system state can transit from any state into "exit" state
6665  system state can not transit from "exit" state into any other state
6666  transition operator discards "exit" state (makes it zero at each turn)
6667 Such conditions basically mean that column of P which corresponds to
6668 "exit" state is zero. Multiplication by such P may decrease sum of vector
6669 components.
6670 
6671 Such models arise when:
6672 * there is some population of individuals
6673 * individuals can have different states
6674 * individuals can transit from one state to another
6675 * population size is NOT constant - individuals can move into "exit" state
6676  and leave population at the next turn, but there are no new individuals
6677 * amount of individuals which leave population can be predicted
6678 * you want to model transitions of individuals from one state into another
6679  (including transitions into the "exit" state)
6680 
6681 This model is discussed in more details in the ALGLIB User Guide (see
6682 http://www.alglib.net/dataanalysis/ for more data).
6683 
6684 INPUT PARAMETERS:
6685  N - problem dimension, N>=2
6686  ExitState- index of exit state, in 0..N-1
6687 
6688 OUTPUT PARAMETERS:
6689  State - structure stores algorithm state
6690 
6691  -- ALGLIB --
6692  Copyright 23.05.2010 by Bochkanov Sergey
6693 *************************************************************************/
6694 void mcpdcreateexit(const ae_int_t n, const ae_int_t exitstate, mcpdstate &s)
6695 {
6696  alglib_impl::ae_state _alglib_env_state;
6697  alglib_impl::ae_state_init(&_alglib_env_state);
6698  try
6699  {
6700  alglib_impl::mcpdcreateexit(n, exitstate, const_cast<alglib_impl::mcpdstate*>(s.c_ptr()), &_alglib_env_state);
6701  alglib_impl::ae_state_clear(&_alglib_env_state);
6702  return;
6703  }
6705  {
6706  throw ap_error(_alglib_env_state.error_msg);
6707  }
6708 }
6709 
6710 /*************************************************************************
6711 DESCRIPTION:
6712 
6713 This function is a specialized version of MCPDCreate() function, and we
6714 recommend you to read comments for this function for general information
6715 about MCPD solver.
6716 
6717 This function creates MCPD (Markov Chains for Population Data) solver
6718 for "Entry-Exit-states" model, i.e. model where transition from X[i] to
6719 X[i+1] is modelled as
6720  X[i+1] = P*X[i]
6721 where
6722  X[i] and X[i+1] are N-dimensional state vectors
6723  P is a N*N transition matrix
6724 one selected component of X[] is called "entry" state and is treated in a
6725 special way:
6726  system state always transits from "entry" state to some another state
6727  system state can not transit from any state into "entry" state
6728 and another one component of X[] is called "exit" state and is treated in
6729 a special way too:
6730  system state can transit from any state into "exit" state
6731  system state can not transit from "exit" state into any other state
6732  transition operator discards "exit" state (makes it zero at each turn)
6733 Such conditions basically mean that:
6734  row of P which corresponds to "entry" state is zero
6735  column of P which corresponds to "exit" state is zero
6736 Multiplication by such P may decrease sum of vector components.
6737 
6738 Such models arise when:
6739 * there is some population of individuals
6740 * individuals can have different states
6741 * individuals can transit from one state to another
6742 * population size is NOT constant
6743 * at every moment of time there is some (unpredictable) amount of "new"
6744  individuals, which can transit into one of the states at the next turn
6745 * some individuals can move (predictably) into "exit" state and leave
6746  population at the next turn
6747 * you want to model transitions of individuals from one state into another,
6748  including transitions from the "entry" state and into the "exit" state.
6749 * but you do NOT want to predict amount of "new" individuals because it
6750  does not depends on individuals already present (hence system can not
6751  transit INTO entry state - it can only transit FROM it).
6752 
6753 This model is discussed in more details in the ALGLIB User Guide (see
6754 http://www.alglib.net/dataanalysis/ for more data).
6755 
6756 INPUT PARAMETERS:
6757  N - problem dimension, N>=2
6758  EntryState- index of entry state, in 0..N-1
6759  ExitState- index of exit state, in 0..N-1
6760 
6761 OUTPUT PARAMETERS:
6762  State - structure stores algorithm state
6763 
6764  -- ALGLIB --
6765  Copyright 23.05.2010 by Bochkanov Sergey
6766 *************************************************************************/
6767 void mcpdcreateentryexit(const ae_int_t n, const ae_int_t entrystate, const ae_int_t exitstate, mcpdstate &s)
6768 {
6769  alglib_impl::ae_state _alglib_env_state;
6770  alglib_impl::ae_state_init(&_alglib_env_state);
6771  try
6772  {
6773  alglib_impl::mcpdcreateentryexit(n, entrystate, exitstate, const_cast<alglib_impl::mcpdstate*>(s.c_ptr()), &_alglib_env_state);
6774  alglib_impl::ae_state_clear(&_alglib_env_state);
6775  return;
6776  }
6778  {
6779  throw ap_error(_alglib_env_state.error_msg);
6780  }
6781 }
6782 
6783 /*************************************************************************
6784 This function is used to add a track - sequence of system states at the
6785 different moments of its evolution.
6786 
6787 You may add one or several tracks to the MCPD solver. In case you have
6788 several tracks, they won't overwrite each other. For example, if you pass
6789 two tracks, A1-A2-A3 (system at t=A+1, t=A+2 and t=A+3) and B1-B2-B3, then
6790 solver will try to model transitions from t=A+1 to t=A+2, t=A+2 to t=A+3,
6791 t=B+1 to t=B+2, t=B+2 to t=B+3. But it WON'T mix these two tracks - i.e. it
6792 won't try to model transition from t=A+3 to t=B+1.
6793 
6794 INPUT PARAMETERS:
6795  S - solver
6796  XY - track, array[K,N]:
6797  * I-th row is a state at t=I
6798  * elements of XY must be non-negative (exception will be
6799  thrown on negative elements)
6800  K - number of points in a track
6801  * if given, only leading K rows of XY are used
6802  * if not given, automatically determined from size of XY
6803 
6804 NOTES:
6805 
6806 1. Track may contain either proportional or population data:
6807  * with proportional data all rows of XY must sum to 1.0, i.e. we have
6808  proportions instead of absolute population values
6809  * with population data rows of XY contain population counts and generally
6810  do not sum to 1.0 (although they still must be non-negative)
6811 
6812  -- ALGLIB --
6813  Copyright 23.05.2010 by Bochkanov Sergey
6814 *************************************************************************/
6815 void mcpdaddtrack(const mcpdstate &s, const real_2d_array &xy, const ae_int_t k)
6816 {
6817  alglib_impl::ae_state _alglib_env_state;
6818  alglib_impl::ae_state_init(&_alglib_env_state);
6819  try
6820  {
6821  alglib_impl::mcpdaddtrack(const_cast<alglib_impl::mcpdstate*>(s.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), k, &_alglib_env_state);
6822  alglib_impl::ae_state_clear(&_alglib_env_state);
6823  return;
6824  }
6826  {
6827  throw ap_error(_alglib_env_state.error_msg);
6828  }
6829 }
6830 
6831 /*************************************************************************
6832 This function is used to add a track - sequence of system states at the
6833 different moments of its evolution.
6834 
6835 You may add one or several tracks to the MCPD solver. In case you have
6836 several tracks, they won't overwrite each other. For example, if you pass
6837 two tracks, A1-A2-A3 (system at t=A+1, t=A+2 and t=A+3) and B1-B2-B3, then
6838 solver will try to model transitions from t=A+1 to t=A+2, t=A+2 to t=A+3,
6839 t=B+1 to t=B+2, t=B+2 to t=B+3. But it WON'T mix these two tracks - i.e. it
6840 won't try to model transition from t=A+3 to t=B+1.
6841 
6842 INPUT PARAMETERS:
6843  S - solver
6844  XY - track, array[K,N]:
6845  * I-th row is a state at t=I
6846  * elements of XY must be non-negative (exception will be
6847  thrown on negative elements)
6848  K - number of points in a track
6849  * if given, only leading K rows of XY are used
6850  * if not given, automatically determined from size of XY
6851 
6852 NOTES:
6853 
6854 1. Track may contain either proportional or population data:
6855  * with proportional data all rows of XY must sum to 1.0, i.e. we have
6856  proportions instead of absolute population values
6857  * with population data rows of XY contain population counts and generally
6858  do not sum to 1.0 (although they still must be non-negative)
6859 
6860  -- ALGLIB --
6861  Copyright 23.05.2010 by Bochkanov Sergey
6862 *************************************************************************/
6863 void mcpdaddtrack(const mcpdstate &s, const real_2d_array &xy)
6864 {
6865  alglib_impl::ae_state _alglib_env_state;
6866  ae_int_t k;
6867 
6868  k = xy.rows();
6869  alglib_impl::ae_state_init(&_alglib_env_state);
6870  try
6871  {
6872  alglib_impl::mcpdaddtrack(const_cast<alglib_impl::mcpdstate*>(s.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), k, &_alglib_env_state);
6873 
6874  alglib_impl::ae_state_clear(&_alglib_env_state);
6875  return;
6876  }
6878  {
6879  throw ap_error(_alglib_env_state.error_msg);
6880  }
6881 }
6882 
6883 /*************************************************************************
6884 This function is used to add equality constraints on the elements of the
6885 transition matrix P.
6886 
6887 MCPD solver has four types of constraints which can be placed on P:
6888 * user-specified equality constraints (optional)
6889 * user-specified bound constraints (optional)
6890 * user-specified general linear constraints (optional)
6891 * basic constraints (always present):
6892  * non-negativity: P[i,j]>=0
6893  * consistency: every column of P sums to 1.0
6894 
6895 Final constraints which are passed to the underlying optimizer are
6896 calculated as intersection of all present constraints. For example, you
6897 may specify boundary constraint on P[0,0] and equality one:
6898  0.1<=P[0,0]<=0.9
6899  P[0,0]=0.5
6900 Such combination of constraints will be silently reduced to their
6901 intersection, which is P[0,0]=0.5.
6902 
6903 This function can be used to place equality constraints on arbitrary
6904 subset of elements of P. Set of constraints is specified by EC, which may
6905 contain either NAN's or finite numbers from [0,1]. NAN denotes absence of
6906 constraint, finite number denotes equality constraint on specific element
6907 of P.
6908 
6909 You can also use MCPDAddEC() function which allows to ADD equality
6910 constraint for one element of P without changing constraints for other
6911 elements.
6912 
6913 These functions (MCPDSetEC and MCPDAddEC) interact as follows:
6914 * there is internal matrix of equality constraints which is stored in the
6915  MCPD solver
6916 * MCPDSetEC() replaces this matrix by another one (SET)
6917 * MCPDAddEC() modifies one element of this matrix and leaves other ones
6918  unchanged (ADD)
6919 * thus MCPDAddEC() call preserves all modifications done by previous
6920  calls, while MCPDSetEC() completely discards all changes done to the
6921  equality constraints.
6922 
6923 INPUT PARAMETERS:
6924  S - solver
6925  EC - equality constraints, array[N,N]. Elements of EC can be
6926  either NAN's or finite numbers from [0,1]. NAN denotes
6927  absence of constraints, while finite value denotes
6928  equality constraint on the corresponding element of P.
6929 
6930 NOTES:
6931 
6932 1. infinite values of EC will lead to exception being thrown. Values less
6933 than 0.0 or greater than 1.0 will lead to error code being returned after
6934 call to MCPDSolve().
6935 
6936  -- ALGLIB --
6937  Copyright 23.05.2010 by Bochkanov Sergey
6938 *************************************************************************/
6939 void mcpdsetec(const mcpdstate &s, const real_2d_array &ec)
6940 {
6941  alglib_impl::ae_state _alglib_env_state;
6942  alglib_impl::ae_state_init(&_alglib_env_state);
6943  try
6944  {
6945  alglib_impl::mcpdsetec(const_cast<alglib_impl::mcpdstate*>(s.c_ptr()), const_cast<alglib_impl::ae_matrix*>(ec.c_ptr()), &_alglib_env_state);
6946  alglib_impl::ae_state_clear(&_alglib_env_state);
6947  return;
6948  }
6950  {
6951  throw ap_error(_alglib_env_state.error_msg);
6952  }
6953 }
6954 
6955 /*************************************************************************
6956 This function is used to add equality constraints on the elements of the
6957 transition matrix P.
6958 
6959 MCPD solver has four types of constraints which can be placed on P:
6960 * user-specified equality constraints (optional)
6961 * user-specified bound constraints (optional)
6962 * user-specified general linear constraints (optional)
6963 * basic constraints (always present):
6964  * non-negativity: P[i,j]>=0
6965  * consistency: every column of P sums to 1.0
6966 
6967 Final constraints which are passed to the underlying optimizer are
6968 calculated as intersection of all present constraints. For example, you
6969 may specify boundary constraint on P[0,0] and equality one:
6970  0.1<=P[0,0]<=0.9
6971  P[0,0]=0.5
6972 Such combination of constraints will be silently reduced to their
6973 intersection, which is P[0,0]=0.5.
6974 
6975 This function can be used to ADD equality constraint for one element of P
6976 without changing constraints for other elements.
6977 
6978 You can also use MCPDSetEC() function which allows you to specify
6979 arbitrary set of equality constraints in one call.
6980 
6981 These functions (MCPDSetEC and MCPDAddEC) interact as follows:
6982 * there is internal matrix of equality constraints which is stored in the
6983  MCPD solver
6984 * MCPDSetEC() replaces this matrix by another one (SET)
6985 * MCPDAddEC() modifies one element of this matrix and leaves other ones
6986  unchanged (ADD)
6987 * thus MCPDAddEC() call preserves all modifications done by previous
6988  calls, while MCPDSetEC() completely discards all changes done to the
6989  equality constraints.
6990 
6991 INPUT PARAMETERS:
6992  S - solver
6993  I - row index of element being constrained
6994  J - column index of element being constrained
6995  C - value (constraint for P[I,J]). Can be either NAN (no
6996  constraint) or finite value from [0,1].
6997 
6998 NOTES:
6999 
7000 1. infinite values of C will lead to exception being thrown. Values less
7001 than 0.0 or greater than 1.0 will lead to error code being returned after
7002 call to MCPDSolve().
7003 
7004  -- ALGLIB --
7005  Copyright 23.05.2010 by Bochkanov Sergey
7006 *************************************************************************/
7007 void mcpdaddec(const mcpdstate &s, const ae_int_t i, const ae_int_t j, const double c)
7008 {
7009  alglib_impl::ae_state _alglib_env_state;
7010  alglib_impl::ae_state_init(&_alglib_env_state);
7011  try
7012  {
7013  alglib_impl::mcpdaddec(const_cast<alglib_impl::mcpdstate*>(s.c_ptr()), i, j, c, &_alglib_env_state);
7014  alglib_impl::ae_state_clear(&_alglib_env_state);
7015  return;
7016  }
7018  {
7019  throw ap_error(_alglib_env_state.error_msg);
7020  }
7021 }
7022 
7023 /*************************************************************************
7024 This function is used to add bound constraints on the elements of the
7025 transition matrix P.
7026 
7027 MCPD solver has four types of constraints which can be placed on P:
7028 * user-specified equality constraints (optional)
7029 * user-specified bound constraints (optional)
7030 * user-specified general linear constraints (optional)
7031 * basic constraints (always present):
7032  * non-negativity: P[i,j]>=0
7033  * consistency: every column of P sums to 1.0
7034 
7035 Final constraints which are passed to the underlying optimizer are
7036 calculated as intersection of all present constraints. For example, you
7037 may specify boundary constraint on P[0,0] and equality one:
7038  0.1<=P[0,0]<=0.9
7039  P[0,0]=0.5
7040 Such combination of constraints will be silently reduced to their
7041 intersection, which is P[0,0]=0.5.
7042 
7043 This function can be used to place bound constraints on arbitrary
7044 subset of elements of P. Set of constraints is specified by BndL/BndU
7045 matrices, which may contain arbitrary combination of finite numbers or
7046 infinities (like -INF<x<=0.5 or 0.1<=x<+INF).
7047 
7048 You can also use MCPDAddBC() function which allows to ADD bound constraint
7049 for one element of P without changing constraints for other elements.
7050 
7051 These functions (MCPDSetBC and MCPDAddBC) interact as follows:
7052 * there is internal matrix of bound constraints which is stored in the
7053  MCPD solver
7054 * MCPDSetBC() replaces this matrix by another one (SET)
7055 * MCPDAddBC() modifies one element of this matrix and leaves other ones
7056  unchanged (ADD)
7057 * thus MCPDAddBC() call preserves all modifications done by previous
7058  calls, while MCPDSetBC() completely discards all changes done to the
7059  equality constraints.
7060 
7061 INPUT PARAMETERS:
7062  S - solver
7063  BndL - lower bounds constraints, array[N,N]. Elements of BndL can
7064  be finite numbers or -INF.
7065  BndU - upper bounds constraints, array[N,N]. Elements of BndU can
7066  be finite numbers or +INF.
7067 
7068  -- ALGLIB --
7069  Copyright 23.05.2010 by Bochkanov Sergey
7070 *************************************************************************/
7071 void mcpdsetbc(const mcpdstate &s, const real_2d_array &bndl, const real_2d_array &bndu)
7072 {
7073  alglib_impl::ae_state _alglib_env_state;
7074  alglib_impl::ae_state_init(&_alglib_env_state);
7075  try
7076  {
7077  alglib_impl::mcpdsetbc(const_cast<alglib_impl::mcpdstate*>(s.c_ptr()), const_cast<alglib_impl::ae_matrix*>(bndl.c_ptr()), const_cast<alglib_impl::ae_matrix*>(bndu.c_ptr()), &_alglib_env_state);
7078  alglib_impl::ae_state_clear(&_alglib_env_state);
7079  return;
7080  }
7082  {
7083  throw ap_error(_alglib_env_state.error_msg);
7084  }
7085 }
7086 
7087 /*************************************************************************
7088 This function is used to add bound constraints on the elements of the
7089 transition matrix P.
7090 
7091 MCPD solver has four types of constraints which can be placed on P:
7092 * user-specified equality constraints (optional)
7093 * user-specified bound constraints (optional)
7094 * user-specified general linear constraints (optional)
7095 * basic constraints (always present):
7096  * non-negativity: P[i,j]>=0
7097  * consistency: every column of P sums to 1.0
7098 
7099 Final constraints which are passed to the underlying optimizer are
7100 calculated as intersection of all present constraints. For example, you
7101 may specify boundary constraint on P[0,0] and equality one:
7102  0.1<=P[0,0]<=0.9
7103  P[0,0]=0.5
7104 Such combination of constraints will be silently reduced to their
7105 intersection, which is P[0,0]=0.5.
7106 
7107 This function can be used to ADD bound constraint for one element of P
7108 without changing constraints for other elements.
7109 
7110 You can also use MCPDSetBC() function which allows to place bound
7111 constraints on arbitrary subset of elements of P. Set of constraints is
7112 specified by BndL/BndU matrices, which may contain arbitrary combination
7113 of finite numbers or infinities (like -INF<x<=0.5 or 0.1<=x<+INF).
7114 
7115 These functions (MCPDSetBC and MCPDAddBC) interact as follows:
7116 * there is internal matrix of bound constraints which is stored in the
7117  MCPD solver
7118 * MCPDSetBC() replaces this matrix by another one (SET)
7119 * MCPDAddBC() modifies one element of this matrix and leaves other ones
7120  unchanged (ADD)
7121 * thus MCPDAddBC() call preserves all modifications done by previous
7122  calls, while MCPDSetBC() completely discards all changes done to the
7123  equality constraints.
7124 
7125 INPUT PARAMETERS:
7126  S - solver
7127  I - row index of element being constrained
7128  J - column index of element being constrained
7129  BndL - lower bound
7130  BndU - upper bound
7131 
7132  -- ALGLIB --
7133  Copyright 23.05.2010 by Bochkanov Sergey
7134 *************************************************************************/
7135 void mcpdaddbc(const mcpdstate &s, const ae_int_t i, const ae_int_t j, const double bndl, const double bndu)
7136 {
7137  alglib_impl::ae_state _alglib_env_state;
7138  alglib_impl::ae_state_init(&_alglib_env_state);
7139  try
7140  {
7141  alglib_impl::mcpdaddbc(const_cast<alglib_impl::mcpdstate*>(s.c_ptr()), i, j, bndl, bndu, &_alglib_env_state);
7142  alglib_impl::ae_state_clear(&_alglib_env_state);
7143  return;
7144  }
7146  {
7147  throw ap_error(_alglib_env_state.error_msg);
7148  }
7149 }
7150 
7151 /*************************************************************************
7152 This function is used to set linear equality/inequality constraints on the
7153 elements of the transition matrix P.
7154 
7155 This function can be used to set one or several general linear constraints
7156 on the elements of P. Two types of constraints are supported:
7157 * equality constraints
7158 * inequality constraints (both less-or-equal and greater-or-equal)
7159 
7160 Coefficients of constraints are specified by matrix C (one of the
7161 parameters). One row of C corresponds to one constraint. Because
7162 transition matrix P has N*N elements, we need N*N columns to store all
7163 coefficients (they are stored row by row), and one more column to store
7164 right part - hence C has N*N+1 columns. Constraint kind is stored in the
7165 CT array.
7166 
7167 Thus, I-th linear constraint is
7168  P[0,0]*C[I,0] + P[0,1]*C[I,1] + .. + P[0,N-1]*C[I,N-1] +
7169  + P[1,0]*C[I,N] + P[1,1]*C[I,N+1] + ... +
7170  + P[N-1,N-1]*C[I,N*N-1] ?=? C[I,N*N]
7171 where ?=? can be either "=" (CT[i]=0), "<=" (CT[i]<0) or ">=" (CT[i]>0).
7172 
7173 Your constraint may involve only some subset of P (less than N*N elements).
7174 For example it can be something like
7175  P[0,0] + P[0,1] = 0.5
7176 In this case you still should pass matrix with N*N+1 columns, but all its
7177 elements (except for C[0,0], C[0,1] and C[0,N*N-1]) will be zero.
7178 
7179 INPUT PARAMETERS:
7180  S - solver
7181  C - array[K,N*N+1] - coefficients of constraints
7182  (see above for complete description)
7183  CT - array[K] - constraint types
7184  (see above for complete description)
7185  K - number of equality/inequality constraints, K>=0:
7186  * if given, only leading K elements of C/CT are used
7187  * if not given, automatically determined from sizes of C/CT
7188 
7189  -- ALGLIB --
7190  Copyright 23.05.2010 by Bochkanov Sergey
7191 *************************************************************************/
7192 void mcpdsetlc(const mcpdstate &s, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k)
7193 {
7194  alglib_impl::ae_state _alglib_env_state;
7195  alglib_impl::ae_state_init(&_alglib_env_state);
7196  try
7197  {
7198  alglib_impl::mcpdsetlc(const_cast<alglib_impl::mcpdstate*>(s.c_ptr()), const_cast<alglib_impl::ae_matrix*>(c.c_ptr()), const_cast<alglib_impl::ae_vector*>(ct.c_ptr()), k, &_alglib_env_state);
7199  alglib_impl::ae_state_clear(&_alglib_env_state);
7200  return;
7201  }
7203  {
7204  throw ap_error(_alglib_env_state.error_msg);
7205  }
7206 }
7207 
7208 /*************************************************************************
7209 This function is used to set linear equality/inequality constraints on the
7210 elements of the transition matrix P.
7211 
7212 This function can be used to set one or several general linear constraints
7213 on the elements of P. Two types of constraints are supported:
7214 * equality constraints
7215 * inequality constraints (both less-or-equal and greater-or-equal)
7216 
7217 Coefficients of constraints are specified by matrix C (one of the
7218 parameters). One row of C corresponds to one constraint. Because
7219 transition matrix P has N*N elements, we need N*N columns to store all
7220 coefficients (they are stored row by row), and one more column to store
7221 right part - hence C has N*N+1 columns. Constraint kind is stored in the
7222 CT array.
7223 
7224 Thus, I-th linear constraint is
7225  P[0,0]*C[I,0] + P[0,1]*C[I,1] + .. + P[0,N-1]*C[I,N-1] +
7226  + P[1,0]*C[I,N] + P[1,1]*C[I,N+1] + ... +
7227  + P[N-1,N-1]*C[I,N*N-1] ?=? C[I,N*N]
7228 where ?=? can be either "=" (CT[i]=0), "<=" (CT[i]<0) or ">=" (CT[i]>0).
7229 
7230 Your constraint may involve only some subset of P (less than N*N elements).
7231 For example it can be something like
7232  P[0,0] + P[0,1] = 0.5
7233 In this case you still should pass matrix with N*N+1 columns, but all its
7234 elements (except for C[0,0], C[0,1] and C[0,N*N-1]) will be zero.
7235 
7236 INPUT PARAMETERS:
7237  S - solver
7238  C - array[K,N*N+1] - coefficients of constraints
7239  (see above for complete description)
7240  CT - array[K] - constraint types
7241  (see above for complete description)
7242  K - number of equality/inequality constraints, K>=0:
7243  * if given, only leading K elements of C/CT are used
7244  * if not given, automatically determined from sizes of C/CT
7245 
7246  -- ALGLIB --
7247  Copyright 23.05.2010 by Bochkanov Sergey
7248 *************************************************************************/
7249 void mcpdsetlc(const mcpdstate &s, const real_2d_array &c, const integer_1d_array &ct)
7250 {
7251  alglib_impl::ae_state _alglib_env_state;
7252  ae_int_t k;
7253  if( (c.rows()!=ct.length()))
7254  throw ap_error("Error while calling 'mcpdsetlc': looks like one of arguments has wrong size");
7255  k = c.rows();
7256  alglib_impl::ae_state_init(&_alglib_env_state);
7257  try
7258  {
7259  alglib_impl::mcpdsetlc(const_cast<alglib_impl::mcpdstate*>(s.c_ptr()), const_cast<alglib_impl::ae_matrix*>(c.c_ptr()), const_cast<alglib_impl::ae_vector*>(ct.c_ptr()), k, &_alglib_env_state);
7260 
7261  alglib_impl::ae_state_clear(&_alglib_env_state);
7262  return;
7263  }
7265  {
7266  throw ap_error(_alglib_env_state.error_msg);
7267  }
7268 }
7269 
7270 /*************************************************************************
7271 This function allows to tune amount of Tikhonov regularization being
7272 applied to your problem.
7273 
7274 By default, regularizing term is equal to r*||P-prior_P||^2, where r is a
7275 small non-zero value, P is transition matrix, prior_P is identity matrix,
7276 ||X||^2 is a sum of squared elements of X.
7277 
7278 This function allows you to change coefficient r. You can also change
7279 prior values with MCPDSetPrior() function.
7280 
7281 INPUT PARAMETERS:
7282  S - solver
7283  V - regularization coefficient, finite non-negative value. It
7284  is not recommended to specify zero value unless you are
7285  pretty sure that you want it.
7286 
7287  -- ALGLIB --
7288  Copyright 23.05.2010 by Bochkanov Sergey
7289 *************************************************************************/
7290 void mcpdsettikhonovregularizer(const mcpdstate &s, const double v)
7291 {
7292  alglib_impl::ae_state _alglib_env_state;
7293  alglib_impl::ae_state_init(&_alglib_env_state);
7294  try
7295  {
7296  alglib_impl::mcpdsettikhonovregularizer(const_cast<alglib_impl::mcpdstate*>(s.c_ptr()), v, &_alglib_env_state);
7297  alglib_impl::ae_state_clear(&_alglib_env_state);
7298  return;
7299  }
7301  {
7302  throw ap_error(_alglib_env_state.error_msg);
7303  }
7304 }
7305 
7306 /*************************************************************************
7307 This function allows to set prior values used for regularization of your
7308 problem.
7309 
7310 By default, regularizing term is equal to r*||P-prior_P||^2, where r is a
7311 small non-zero value, P is transition matrix, prior_P is identity matrix,
7312 ||X||^2 is a sum of squared elements of X.
7313 
7314 This function allows you to change prior values prior_P. You can also
7315 change r with MCPDSetTikhonovRegularizer() function.
7316 
7317 INPUT PARAMETERS:
7318  S - solver
7319  PP - array[N,N], matrix of prior values:
7320  1. elements must be real numbers from [0,1]
7321  2. columns must sum to 1.0.
7322  First property is checked (exception is thrown otherwise),
7323  while second one is not checked/enforced.
7324 
7325  -- ALGLIB --
7326  Copyright 23.05.2010 by Bochkanov Sergey
7327 *************************************************************************/
7328 void mcpdsetprior(const mcpdstate &s, const real_2d_array &pp)
7329 {
7330  alglib_impl::ae_state _alglib_env_state;
7331  alglib_impl::ae_state_init(&_alglib_env_state);
7332  try
7333  {
7334  alglib_impl::mcpdsetprior(const_cast<alglib_impl::mcpdstate*>(s.c_ptr()), const_cast<alglib_impl::ae_matrix*>(pp.c_ptr()), &_alglib_env_state);
7335  alglib_impl::ae_state_clear(&_alglib_env_state);
7336  return;
7337  }
7339  {
7340  throw ap_error(_alglib_env_state.error_msg);
7341  }
7342 }
7343 
7344 /*************************************************************************
7345 This function is used to change prediction weights
7346 
7347 MCPD solver scales prediction errors as follows
7348  Error(P) = ||W*(y-P*x)||^2
7349 where
7350  x is a system state at time t
7351  y is a system state at time t+1
7352  P is a transition matrix
7353  W is a diagonal scaling matrix
7354 
7355 By default, weights are chosen in order to minimize relative prediction
7356 error instead of absolute one. For example, if one component of state is
7357 about 0.5 in magnitude and another one is about 0.05, then algorithm will
7358 make corresponding weights equal to 2.0 and 20.0.
7359 
7360 INPUT PARAMETERS:
7361  S - solver
7362  PW - array[N], weights:
7363  * must be non-negative values (exception will be thrown otherwise)
7364  * zero values will be replaced by automatically chosen values
7365 
7366  -- ALGLIB --
7367  Copyright 23.05.2010 by Bochkanov Sergey
7368 *************************************************************************/
7370 {
7371  alglib_impl::ae_state _alglib_env_state;
7372  alglib_impl::ae_state_init(&_alglib_env_state);
7373  try
7374  {
7375  alglib_impl::mcpdsetpredictionweights(const_cast<alglib_impl::mcpdstate*>(s.c_ptr()), const_cast<alglib_impl::ae_vector*>(pw.c_ptr()), &_alglib_env_state);
7376  alglib_impl::ae_state_clear(&_alglib_env_state);
7377  return;
7378  }
7380  {
7381  throw ap_error(_alglib_env_state.error_msg);
7382  }
7383 }
7384 
7385 /*************************************************************************
7386 This function is used to start solution of the MCPD problem.
7387 
7388 After return from this function, you can use MCPDResults() to get solution
7389 and completion code.
7390 
7391  -- ALGLIB --
7392  Copyright 23.05.2010 by Bochkanov Sergey
7393 *************************************************************************/
7394 void mcpdsolve(const mcpdstate &s)
7395 {
7396  alglib_impl::ae_state _alglib_env_state;
7397  alglib_impl::ae_state_init(&_alglib_env_state);
7398  try
7399  {
7400  alglib_impl::mcpdsolve(const_cast<alglib_impl::mcpdstate*>(s.c_ptr()), &_alglib_env_state);
7401  alglib_impl::ae_state_clear(&_alglib_env_state);
7402  return;
7403  }
7405  {
7406  throw ap_error(_alglib_env_state.error_msg);
7407  }
7408 }
7409 
7410 /*************************************************************************
7411 MCPD results
7412 
7413 INPUT PARAMETERS:
7414  State - algorithm state
7415 
7416 OUTPUT PARAMETERS:
7417  P - array[N,N], transition matrix
7418  Rep - optimization report. You should check Rep.TerminationType
7419  in order to distinguish successful termination from
7420  unsuccessful one. Speaking short, positive values denote
7421  success, negative ones are failures.
7422  More information about fields of this structure can be
7423  found in the comments on MCPDReport datatype.
7424 
7425 
7426  -- ALGLIB --
7427  Copyright 23.05.2010 by Bochkanov Sergey
7428 *************************************************************************/
7430 {
7431  alglib_impl::ae_state _alglib_env_state;
7432  alglib_impl::ae_state_init(&_alglib_env_state);
7433  try
7434  {
7435  alglib_impl::mcpdresults(const_cast<alglib_impl::mcpdstate*>(s.c_ptr()), const_cast<alglib_impl::ae_matrix*>(p.c_ptr()), const_cast<alglib_impl::mcpdreport*>(rep.c_ptr()), &_alglib_env_state);
7436  alglib_impl::ae_state_clear(&_alglib_env_state);
7437  return;
7438  }
7440  {
7441  throw ap_error(_alglib_env_state.error_msg);
7442  }
7443 }
7444 
7445 /*************************************************************************
7446 Neural networks ensemble
7447 *************************************************************************/
7449 {
7451  if( p_struct==NULL )
7452  throw ap_error("ALGLIB: malloc error");
7454  throw ap_error("ALGLIB: malloc error");
7455 }
7456 
7458 {
7460  if( p_struct==NULL )
7461  throw ap_error("ALGLIB: malloc error");
7462  if( !alglib_impl::_mlpensemble_init_copy(p_struct, const_cast<alglib_impl::mlpensemble*>(rhs.p_struct), NULL, ae_false) )
7463  throw ap_error("ALGLIB: malloc error");
7464 }
7465 
7467 {
7468  if( this==&rhs )
7469  return *this;
7471  if( !alglib_impl::_mlpensemble_init_copy(p_struct, const_cast<alglib_impl::mlpensemble*>(rhs.p_struct), NULL, ae_false) )
7472  throw ap_error("ALGLIB: malloc error");
7473  return *this;
7474 }
7475 
7477 {
7479  ae_free(p_struct);
7480 }
7481 
7483 {
7484  return p_struct;
7485 }
7486 
7488 {
7489  return const_cast<alglib_impl::mlpensemble*>(p_struct);
7490 }
7492 {
7493 }
7494 
7496 {
7497 }
7498 
7500 {
7501  if( this==&rhs )
7502  return *this;
7504  return *this;
7505 }
7506 
7508 {
7509 }
7510 
7511 
7512 /*************************************************************************
7513 This function serializes data structure to string.
7514 
7515 Important properties of s_out:
7516 * it contains alphanumeric characters, dots, underscores, minus signs
7517 * these symbols are grouped into words, which are separated by spaces
7518  and Windows-style (CR+LF) newlines
7519 * although serializer uses spaces and CR+LF as separators, you can
7520  replace any separator character by arbitrary combination of spaces,
7521  tabs, Windows or Unix newlines. It allows flexible reformatting of
7522  the string in case you want to include it into text or XML file.
7523  But you should not insert separators into the middle of the "words"
7524  nor you should change case of letters.
7525 * s_out can be freely moved between 32-bit and 64-bit systems, little
7526  and big endian machines, and so on. You can serialize structure on
7527  32-bit machine and unserialize it on 64-bit one (or vice versa), or
7528  serialize it on SPARC and unserialize on x86. You can also
7529  serialize it in C++ version of ALGLIB and unserialize in C# one,
7530  and vice versa.
7531 *************************************************************************/
7532 void mlpeserialize(mlpensemble &obj, std::string &s_out)
7533 {
7534  alglib_impl::ae_state state;
7535  alglib_impl::ae_serializer serializer;
7536  alglib_impl::ae_int_t ssize;
7537 
7539  try
7540  {
7541  alglib_impl::ae_serializer_init(&serializer);
7543  alglib_impl::mlpealloc(&serializer, obj.c_ptr(), &state);
7544  ssize = alglib_impl::ae_serializer_get_alloc_size(&serializer);
7545  s_out.clear();
7546  s_out.reserve((size_t)(ssize+1));
7547  alglib_impl::ae_serializer_sstart_str(&serializer, &s_out);
7548  alglib_impl::mlpeserialize(&serializer, obj.c_ptr(), &state);
7549  alglib_impl::ae_serializer_stop(&serializer);
7550  if( s_out.length()>(size_t)ssize )
7551  throw ap_error("ALGLIB: serialization integrity error");
7552  alglib_impl::ae_serializer_clear(&serializer);
7554  }
7556  {
7557  throw ap_error(state.error_msg);
7558  }
7559 }
7560 /*************************************************************************
7561 This function unserializes data structure from string.
7562 *************************************************************************/
7563 void mlpeunserialize(std::string &s_in, mlpensemble &obj)
7564 {
7565  alglib_impl::ae_state state;
7566  alglib_impl::ae_serializer serializer;
7567 
7569  try
7570  {
7571  alglib_impl::ae_serializer_init(&serializer);
7572  alglib_impl::ae_serializer_ustart_str(&serializer, &s_in);
7573  alglib_impl::mlpeunserialize(&serializer, obj.c_ptr(), &state);
7574  alglib_impl::ae_serializer_stop(&serializer);
7575  alglib_impl::ae_serializer_clear(&serializer);
7577  }
7579  {
7580  throw ap_error(state.error_msg);
7581  }
7582 }
7583 
7584 /*************************************************************************
7585 Like MLPCreate0, but for ensembles.
7586 
7587  -- ALGLIB --
7588  Copyright 18.02.2009 by Bochkanov Sergey
7589 *************************************************************************/
7590 void mlpecreate0(const ae_int_t nin, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble)
7591 {
7592  alglib_impl::ae_state _alglib_env_state;
7593  alglib_impl::ae_state_init(&_alglib_env_state);
7594  try
7595  {
7596  alglib_impl::mlpecreate0(nin, nout, ensemblesize, const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), &_alglib_env_state);
7597  alglib_impl::ae_state_clear(&_alglib_env_state);
7598  return;
7599  }
7601  {
7602  throw ap_error(_alglib_env_state.error_msg);
7603  }
7604 }
7605 
7606 /*************************************************************************
7607 Like MLPCreate1, but for ensembles.
7608 
7609  -- ALGLIB --
7610  Copyright 18.02.2009 by Bochkanov Sergey
7611 *************************************************************************/
7612 void mlpecreate1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble)
7613 {
7614  alglib_impl::ae_state _alglib_env_state;
7615  alglib_impl::ae_state_init(&_alglib_env_state);
7616  try
7617  {
7618  alglib_impl::mlpecreate1(nin, nhid, nout, ensemblesize, const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), &_alglib_env_state);
7619  alglib_impl::ae_state_clear(&_alglib_env_state);
7620  return;
7621  }
7623  {
7624  throw ap_error(_alglib_env_state.error_msg);
7625  }
7626 }
7627 
7628 /*************************************************************************
7629 Like MLPCreate2, but for ensembles.
7630 
7631  -- ALGLIB --
7632  Copyright 18.02.2009 by Bochkanov Sergey
7633 *************************************************************************/
7634 void mlpecreate2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble)
7635 {
7636  alglib_impl::ae_state _alglib_env_state;
7637  alglib_impl::ae_state_init(&_alglib_env_state);
7638  try
7639  {
7640  alglib_impl::mlpecreate2(nin, nhid1, nhid2, nout, ensemblesize, const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), &_alglib_env_state);
7641  alglib_impl::ae_state_clear(&_alglib_env_state);
7642  return;
7643  }
7645  {
7646  throw ap_error(_alglib_env_state.error_msg);
7647  }
7648 }
7649 
7650 /*************************************************************************
7651 Like MLPCreateB0, but for ensembles.
7652 
7653  -- ALGLIB --
7654  Copyright 18.02.2009 by Bochkanov Sergey
7655 *************************************************************************/
7656 void mlpecreateb0(const ae_int_t nin, const ae_int_t nout, const double b, const double d, const ae_int_t ensemblesize, mlpensemble &ensemble)
7657 {
7658  alglib_impl::ae_state _alglib_env_state;
7659  alglib_impl::ae_state_init(&_alglib_env_state);
7660  try
7661  {
7662  alglib_impl::mlpecreateb0(nin, nout, b, d, ensemblesize, const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), &_alglib_env_state);
7663  alglib_impl::ae_state_clear(&_alglib_env_state);
7664  return;
7665  }
7667  {
7668  throw ap_error(_alglib_env_state.error_msg);
7669  }
7670 }
7671 
7672 /*************************************************************************
7673 Like MLPCreateB1, but for ensembles.
7674 
7675  -- ALGLIB --
7676  Copyright 18.02.2009 by Bochkanov Sergey
7677 *************************************************************************/
7678 void mlpecreateb1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const double b, const double d, const ae_int_t ensemblesize, mlpensemble &ensemble)
7679 {
7680  alglib_impl::ae_state _alglib_env_state;
7681  alglib_impl::ae_state_init(&_alglib_env_state);
7682  try
7683  {
7684  alglib_impl::mlpecreateb1(nin, nhid, nout, b, d, ensemblesize, const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), &_alglib_env_state);
7685  alglib_impl::ae_state_clear(&_alglib_env_state);
7686  return;
7687  }
7689  {
7690  throw ap_error(_alglib_env_state.error_msg);
7691  }
7692 }
7693 
7694 /*************************************************************************
7695 Like MLPCreateB2, but for ensembles.
7696 
7697  -- ALGLIB --
7698  Copyright 18.02.2009 by Bochkanov Sergey
7699 *************************************************************************/
7700 void mlpecreateb2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const double b, const double d, const ae_int_t ensemblesize, mlpensemble &ensemble)
7701 {
7702  alglib_impl::ae_state _alglib_env_state;
7703  alglib_impl::ae_state_init(&_alglib_env_state);
7704  try
7705  {
7706  alglib_impl::mlpecreateb2(nin, nhid1, nhid2, nout, b, d, ensemblesize, const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), &_alglib_env_state);
7707  alglib_impl::ae_state_clear(&_alglib_env_state);
7708  return;
7709  }
7711  {
7712  throw ap_error(_alglib_env_state.error_msg);
7713  }
7714 }
7715 
7716 /*************************************************************************
7717 Like MLPCreateR0, but for ensembles.
7718 
7719  -- ALGLIB --
7720  Copyright 18.02.2009 by Bochkanov Sergey
7721 *************************************************************************/
7722 void mlpecreater0(const ae_int_t nin, const ae_int_t nout, const double a, const double b, const ae_int_t ensemblesize, mlpensemble &ensemble)
7723 {
7724  alglib_impl::ae_state _alglib_env_state;
7725  alglib_impl::ae_state_init(&_alglib_env_state);
7726  try
7727  {
7728  alglib_impl::mlpecreater0(nin, nout, a, b, ensemblesize, const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), &_alglib_env_state);
7729  alglib_impl::ae_state_clear(&_alglib_env_state);
7730  return;
7731  }
7733  {
7734  throw ap_error(_alglib_env_state.error_msg);
7735  }
7736 }
7737 
7738 /*************************************************************************
7739 Like MLPCreateR1, but for ensembles.
7740 
7741  -- ALGLIB --
7742  Copyright 18.02.2009 by Bochkanov Sergey
7743 *************************************************************************/
7744 void mlpecreater1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const double a, const double b, const ae_int_t ensemblesize, mlpensemble &ensemble)
7745 {
7746  alglib_impl::ae_state _alglib_env_state;
7747  alglib_impl::ae_state_init(&_alglib_env_state);
7748  try
7749  {
7750  alglib_impl::mlpecreater1(nin, nhid, nout, a, b, ensemblesize, const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), &_alglib_env_state);
7751  alglib_impl::ae_state_clear(&_alglib_env_state);
7752  return;
7753  }
7755  {
7756  throw ap_error(_alglib_env_state.error_msg);
7757  }
7758 }
7759 
7760 /*************************************************************************
7761 Like MLPCreateR2, but for ensembles.
7762 
7763  -- ALGLIB --
7764  Copyright 18.02.2009 by Bochkanov Sergey
7765 *************************************************************************/
7766 void mlpecreater2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const double a, const double b, const ae_int_t ensemblesize, mlpensemble &ensemble)
7767 {
7768  alglib_impl::ae_state _alglib_env_state;
7769  alglib_impl::ae_state_init(&_alglib_env_state);
7770  try
7771  {
7772  alglib_impl::mlpecreater2(nin, nhid1, nhid2, nout, a, b, ensemblesize, const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), &_alglib_env_state);
7773  alglib_impl::ae_state_clear(&_alglib_env_state);
7774  return;
7775  }
7777  {
7778  throw ap_error(_alglib_env_state.error_msg);
7779  }
7780 }
7781 
7782 /*************************************************************************
7783 Like MLPCreateC0, but for ensembles.
7784 
7785  -- ALGLIB --
7786  Copyright 18.02.2009 by Bochkanov Sergey
7787 *************************************************************************/
7788 void mlpecreatec0(const ae_int_t nin, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble)
7789 {
7790  alglib_impl::ae_state _alglib_env_state;
7791  alglib_impl::ae_state_init(&_alglib_env_state);
7792  try
7793  {
7794  alglib_impl::mlpecreatec0(nin, nout, ensemblesize, const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), &_alglib_env_state);
7795  alglib_impl::ae_state_clear(&_alglib_env_state);
7796  return;
7797  }
7799  {
7800  throw ap_error(_alglib_env_state.error_msg);
7801  }
7802 }
7803 
7804 /*************************************************************************
7805 Like MLPCreateC1, but for ensembles.
7806 
7807  -- ALGLIB --
7808  Copyright 18.02.2009 by Bochkanov Sergey
7809 *************************************************************************/
7810 void mlpecreatec1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble)
7811 {
7812  alglib_impl::ae_state _alglib_env_state;
7813  alglib_impl::ae_state_init(&_alglib_env_state);
7814  try
7815  {
7816  alglib_impl::mlpecreatec1(nin, nhid, nout, ensemblesize, const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), &_alglib_env_state);
7817  alglib_impl::ae_state_clear(&_alglib_env_state);
7818  return;
7819  }
7821  {
7822  throw ap_error(_alglib_env_state.error_msg);
7823  }
7824 }
7825 
7826 /*************************************************************************
7827 Like MLPCreateC2, but for ensembles.
7828 
7829  -- ALGLIB --
7830  Copyright 18.02.2009 by Bochkanov Sergey
7831 *************************************************************************/
7832 void mlpecreatec2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble)
7833 {
7834  alglib_impl::ae_state _alglib_env_state;
7835  alglib_impl::ae_state_init(&_alglib_env_state);
7836  try
7837  {
7838  alglib_impl::mlpecreatec2(nin, nhid1, nhid2, nout, ensemblesize, const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), &_alglib_env_state);
7839  alglib_impl::ae_state_clear(&_alglib_env_state);
7840  return;
7841  }
7843  {
7844  throw ap_error(_alglib_env_state.error_msg);
7845  }
7846 }
7847 
7848 /*************************************************************************
7849 Creates ensemble from network. Only network geometry is copied.
7850 
7851  -- ALGLIB --
7852  Copyright 17.02.2009 by Bochkanov Sergey
7853 *************************************************************************/
7854 void mlpecreatefromnetwork(const multilayerperceptron &network, const ae_int_t ensemblesize, mlpensemble &ensemble)
7855 {
7856  alglib_impl::ae_state _alglib_env_state;
7857  alglib_impl::ae_state_init(&_alglib_env_state);
7858  try
7859  {
7860  alglib_impl::mlpecreatefromnetwork(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), ensemblesize, const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), &_alglib_env_state);
7861  alglib_impl::ae_state_clear(&_alglib_env_state);
7862  return;
7863  }
7865  {
7866  throw ap_error(_alglib_env_state.error_msg);
7867  }
7868 }
7869 
7870 /*************************************************************************
7871 Randomization of MLP ensemble
7872 
7873  -- ALGLIB --
7874  Copyright 17.02.2009 by Bochkanov Sergey
7875 *************************************************************************/
7876 void mlperandomize(const mlpensemble &ensemble)
7877 {
7878  alglib_impl::ae_state _alglib_env_state;
7879  alglib_impl::ae_state_init(&_alglib_env_state);
7880  try
7881  {
7882  alglib_impl::mlperandomize(const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), &_alglib_env_state);
7883  alglib_impl::ae_state_clear(&_alglib_env_state);
7884  return;
7885  }
7887  {
7888  throw ap_error(_alglib_env_state.error_msg);
7889  }
7890 }
7891 
7892 /*************************************************************************
7893 Return ensemble properties (number of inputs and outputs).
7894 
7895  -- ALGLIB --
7896  Copyright 17.02.2009 by Bochkanov Sergey
7897 *************************************************************************/
7898 void mlpeproperties(const mlpensemble &ensemble, ae_int_t &nin, ae_int_t &nout)
7899 {
7900  alglib_impl::ae_state _alglib_env_state;
7901  alglib_impl::ae_state_init(&_alglib_env_state);
7902  try
7903  {
7904  alglib_impl::mlpeproperties(const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), &nin, &nout, &_alglib_env_state);
7905  alglib_impl::ae_state_clear(&_alglib_env_state);
7906  return;
7907  }
7909  {
7910  throw ap_error(_alglib_env_state.error_msg);
7911  }
7912 }
7913 
7914 /*************************************************************************
7915 Return normalization type (whether ensemble is SOFTMAX-normalized or not).
7916 
7917  -- ALGLIB --
7918  Copyright 17.02.2009 by Bochkanov Sergey
7919 *************************************************************************/
7920 bool mlpeissoftmax(const mlpensemble &ensemble)
7921 {
7922  alglib_impl::ae_state _alglib_env_state;
7923  alglib_impl::ae_state_init(&_alglib_env_state);
7924  try
7925  {
7926  ae_bool result = alglib_impl::mlpeissoftmax(const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), &_alglib_env_state);
7927  alglib_impl::ae_state_clear(&_alglib_env_state);
7928  return *(reinterpret_cast<bool*>(&result));
7929  }
7931  {
7932  throw ap_error(_alglib_env_state.error_msg);
7933  }
7934 }
7935 
7936 /*************************************************************************
7937 Procesing
7938 
7939 INPUT PARAMETERS:
7940  Ensemble- neural networks ensemble
7941  X - input vector, array[0..NIn-1].
7942  Y - (possibly) preallocated buffer; if size of Y is less than
7943  NOut, it will be reallocated. If it is large enough, it
7944  is NOT reallocated, so we can save some time on reallocation.
7945 
7946 
7947 OUTPUT PARAMETERS:
7948  Y - result. Regression estimate when solving regression task,
7949  vector of posterior probabilities for classification task.
7950 
7951  -- ALGLIB --
7952  Copyright 17.02.2009 by Bochkanov Sergey
7953 *************************************************************************/
7954 void mlpeprocess(const mlpensemble &ensemble, const real_1d_array &x, real_1d_array &y)
7955 {
7956  alglib_impl::ae_state _alglib_env_state;
7957  alglib_impl::ae_state_init(&_alglib_env_state);
7958  try
7959  {
7960  alglib_impl::mlpeprocess(const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), &_alglib_env_state);
7961  alglib_impl::ae_state_clear(&_alglib_env_state);
7962  return;
7963  }
7965  {
7966  throw ap_error(_alglib_env_state.error_msg);
7967  }
7968 }
7969 
7970 /*************************************************************************
7971 'interactive' variant of MLPEProcess for languages like Python which
7972 support constructs like "Y = MLPEProcess(LM,X)" and interactive mode of the
7973 interpreter
7974 
7975 This function allocates new array on each call, so it is significantly
7976 slower than its 'non-interactive' counterpart, but it is more convenient
7977 when you call it from command line.
7978 
7979  -- ALGLIB --
7980  Copyright 17.02.2009 by Bochkanov Sergey
7981 *************************************************************************/
7982 void mlpeprocessi(const mlpensemble &ensemble, const real_1d_array &x, real_1d_array &y)
7983 {
7984  alglib_impl::ae_state _alglib_env_state;
7985  alglib_impl::ae_state_init(&_alglib_env_state);
7986  try
7987  {
7988  alglib_impl::mlpeprocessi(const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), &_alglib_env_state);
7989  alglib_impl::ae_state_clear(&_alglib_env_state);
7990  return;
7991  }
7993  {
7994  throw ap_error(_alglib_env_state.error_msg);
7995  }
7996 }
7997 
7998 /*************************************************************************
7999 Relative classification error on the test set
8000 
8001 INPUT PARAMETERS:
8002  Ensemble- ensemble
8003  XY - test set
8004  NPoints - test set size
8005 
8006 RESULT:
8007  percent of incorrectly classified cases.
8008  Works both for classifier betwork and for regression networks which
8009 are used as classifiers.
8010 
8011  -- ALGLIB --
8012  Copyright 17.02.2009 by Bochkanov Sergey
8013 *************************************************************************/
8014 double mlperelclserror(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints)
8015 {
8016  alglib_impl::ae_state _alglib_env_state;
8017  alglib_impl::ae_state_init(&_alglib_env_state);
8018  try
8019  {
8020  double result = alglib_impl::mlperelclserror(const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
8021  alglib_impl::ae_state_clear(&_alglib_env_state);
8022  return *(reinterpret_cast<double*>(&result));
8023  }
8025  {
8026  throw ap_error(_alglib_env_state.error_msg);
8027  }
8028 }
8029 
8030 /*************************************************************************
8031 Average cross-entropy (in bits per element) on the test set
8032 
8033 INPUT PARAMETERS:
8034  Ensemble- ensemble
8035  XY - test set
8036  NPoints - test set size
8037 
8038 RESULT:
8039  CrossEntropy/(NPoints*LN(2)).
8040  Zero if ensemble solves regression task.
8041 
8042  -- ALGLIB --
8043  Copyright 17.02.2009 by Bochkanov Sergey
8044 *************************************************************************/
8045 double mlpeavgce(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints)
8046 {
8047  alglib_impl::ae_state _alglib_env_state;
8048  alglib_impl::ae_state_init(&_alglib_env_state);
8049  try
8050  {
8051  double result = alglib_impl::mlpeavgce(const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
8052  alglib_impl::ae_state_clear(&_alglib_env_state);
8053  return *(reinterpret_cast<double*>(&result));
8054  }
8056  {
8057  throw ap_error(_alglib_env_state.error_msg);
8058  }
8059 }
8060 
8061 /*************************************************************************
8062 RMS error on the test set
8063 
8064 INPUT PARAMETERS:
8065  Ensemble- ensemble
8066  XY - test set
8067  NPoints - test set size
8068 
8069 RESULT:
8070  root mean square error.
8071  Its meaning for regression task is obvious. As for classification task
8072 RMS error means error when estimating posterior probabilities.
8073 
8074  -- ALGLIB --
8075  Copyright 17.02.2009 by Bochkanov Sergey
8076 *************************************************************************/
8077 double mlpermserror(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints)
8078 {
8079  alglib_impl::ae_state _alglib_env_state;
8080  alglib_impl::ae_state_init(&_alglib_env_state);
8081  try
8082  {
8083  double result = alglib_impl::mlpermserror(const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
8084  alglib_impl::ae_state_clear(&_alglib_env_state);
8085  return *(reinterpret_cast<double*>(&result));
8086  }
8088  {
8089  throw ap_error(_alglib_env_state.error_msg);
8090  }
8091 }
8092 
8093 /*************************************************************************
8094 Average error on the test set
8095 
8096 INPUT PARAMETERS:
8097  Ensemble- ensemble
8098  XY - test set
8099  NPoints - test set size
8100 
8101 RESULT:
8102  Its meaning for regression task is obvious. As for classification task
8103 it means average error when estimating posterior probabilities.
8104 
8105  -- ALGLIB --
8106  Copyright 17.02.2009 by Bochkanov Sergey
8107 *************************************************************************/
8108 double mlpeavgerror(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints)
8109 {
8110  alglib_impl::ae_state _alglib_env_state;
8111  alglib_impl::ae_state_init(&_alglib_env_state);
8112  try
8113  {
8114  double result = alglib_impl::mlpeavgerror(const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
8115  alglib_impl::ae_state_clear(&_alglib_env_state);
8116  return *(reinterpret_cast<double*>(&result));
8117  }
8119  {
8120  throw ap_error(_alglib_env_state.error_msg);
8121  }
8122 }
8123 
8124 /*************************************************************************
8125 Average relative error on the test set
8126 
8127 INPUT PARAMETERS:
8128  Ensemble- ensemble
8129  XY - test set
8130  NPoints - test set size
8131 
8132 RESULT:
8133  Its meaning for regression task is obvious. As for classification task
8134 it means average relative error when estimating posterior probabilities.
8135 
8136  -- ALGLIB --
8137  Copyright 17.02.2009 by Bochkanov Sergey
8138 *************************************************************************/
8139 double mlpeavgrelerror(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints)
8140 {
8141  alglib_impl::ae_state _alglib_env_state;
8142  alglib_impl::ae_state_init(&_alglib_env_state);
8143  try
8144  {
8145  double result = alglib_impl::mlpeavgrelerror(const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
8146  alglib_impl::ae_state_clear(&_alglib_env_state);
8147  return *(reinterpret_cast<double*>(&result));
8148  }
8150  {
8151  throw ap_error(_alglib_env_state.error_msg);
8152  }
8153 }
8154 
8155 /*************************************************************************
8156 Training report:
8157  * RelCLSError - fraction of misclassified cases.
8158  * AvgCE - acerage cross-entropy
8159  * RMSError - root-mean-square error
8160  * AvgError - average error
8161  * AvgRelError - average relative error
8162  * NGrad - number of gradient calculations
8163  * NHess - number of Hessian calculations
8164  * NCholesky - number of Cholesky decompositions
8165 
8166 NOTE 1: RelCLSError/AvgCE are zero on regression problems.
8167 
8168 NOTE 2: on classification problems RMSError/AvgError/AvgRelError contain
8169  errors in prediction of posterior probabilities
8170 *************************************************************************/
8172 {
8174  if( p_struct==NULL )
8175  throw ap_error("ALGLIB: malloc error");
8177  throw ap_error("ALGLIB: malloc error");
8178 }
8179 
8181 {
8183  if( p_struct==NULL )
8184  throw ap_error("ALGLIB: malloc error");
8185  if( !alglib_impl::_mlpreport_init_copy(p_struct, const_cast<alglib_impl::mlpreport*>(rhs.p_struct), NULL, ae_false) )
8186  throw ap_error("ALGLIB: malloc error");
8187 }
8188 
8190 {
8191  if( this==&rhs )
8192  return *this;
8194  if( !alglib_impl::_mlpreport_init_copy(p_struct, const_cast<alglib_impl::mlpreport*>(rhs.p_struct), NULL, ae_false) )
8195  throw ap_error("ALGLIB: malloc error");
8196  return *this;
8197 }
8198 
8200 {
8202  ae_free(p_struct);
8203 }
8204 
8206 {
8207  return p_struct;
8208 }
8209 
8211 {
8212  return const_cast<alglib_impl::mlpreport*>(p_struct);
8213 }
8214 mlpreport::mlpreport() : _mlpreport_owner() ,relclserror(p_struct->relclserror),avgce(p_struct->avgce),rmserror(p_struct->rmserror),avgerror(p_struct->avgerror),avgrelerror(p_struct->avgrelerror),ngrad(p_struct->ngrad),nhess(p_struct->nhess),ncholesky(p_struct->ncholesky)
8215 {
8216 }
8217 
8219 {
8220 }
8221 
8223 {
8224  if( this==&rhs )
8225  return *this;
8227  return *this;
8228 }
8229 
8231 {
8232 }
8233 
8234 
8235 /*************************************************************************
8236 Cross-validation estimates of generalization error
8237 *************************************************************************/
8239 {
8241  if( p_struct==NULL )
8242  throw ap_error("ALGLIB: malloc error");
8244  throw ap_error("ALGLIB: malloc error");
8245 }
8246 
8248 {
8250  if( p_struct==NULL )
8251  throw ap_error("ALGLIB: malloc error");
8252  if( !alglib_impl::_mlpcvreport_init_copy(p_struct, const_cast<alglib_impl::mlpcvreport*>(rhs.p_struct), NULL, ae_false) )
8253  throw ap_error("ALGLIB: malloc error");
8254 }
8255 
8257 {
8258  if( this==&rhs )
8259  return *this;
8261  if( !alglib_impl::_mlpcvreport_init_copy(p_struct, const_cast<alglib_impl::mlpcvreport*>(rhs.p_struct), NULL, ae_false) )
8262  throw ap_error("ALGLIB: malloc error");
8263  return *this;
8264 }
8265 
8267 {
8269  ae_free(p_struct);
8270 }
8271 
8273 {
8274  return p_struct;
8275 }
8276 
8278 {
8279  return const_cast<alglib_impl::mlpcvreport*>(p_struct);
8280 }
8282 {
8283 }
8284 
8286 {
8287 }
8288 
8290 {
8291  if( this==&rhs )
8292  return *this;
8294  return *this;
8295 }
8296 
8298 {
8299 }
8300 
8301 
8302 /*************************************************************************
8303 Trainer object for neural network.
8304 
8305 You should not try to access fields of this object directly - use ALGLIB
8306 functions to work with this object.
8307 *************************************************************************/
8309 {
8311  if( p_struct==NULL )
8312  throw ap_error("ALGLIB: malloc error");
8314  throw ap_error("ALGLIB: malloc error");
8315 }
8316 
8318 {
8320  if( p_struct==NULL )
8321  throw ap_error("ALGLIB: malloc error");
8322  if( !alglib_impl::_mlptrainer_init_copy(p_struct, const_cast<alglib_impl::mlptrainer*>(rhs.p_struct), NULL, ae_false) )
8323  throw ap_error("ALGLIB: malloc error");
8324 }
8325 
8327 {
8328  if( this==&rhs )
8329  return *this;
8331  if( !alglib_impl::_mlptrainer_init_copy(p_struct, const_cast<alglib_impl::mlptrainer*>(rhs.p_struct), NULL, ae_false) )
8332  throw ap_error("ALGLIB: malloc error");
8333  return *this;
8334 }
8335 
8337 {
8339  ae_free(p_struct);
8340 }
8341 
8343 {
8344  return p_struct;
8345 }
8346 
8348 {
8349  return const_cast<alglib_impl::mlptrainer*>(p_struct);
8350 }
8352 {
8353 }
8354 
8356 {
8357 }
8358 
8360 {
8361  if( this==&rhs )
8362  return *this;
8364  return *this;
8365 }
8366 
8368 {
8369 }
8370 
8371 /*************************************************************************
8372 Neural network training using modified Levenberg-Marquardt with exact
8373 Hessian calculation and regularization. Subroutine trains neural network
8374 with restarts from random positions. Algorithm is well suited for small
8375 and medium scale problems (hundreds of weights).
8376 
8377 INPUT PARAMETERS:
8378  Network - neural network with initialized geometry
8379  XY - training set
8380  NPoints - training set size
8381  Decay - weight decay constant, >=0.001
8382  Decay term 'Decay*||Weights||^2' is added to error
8383  function.
8384  If you don't know what Decay to choose, use 0.001.
8385  Restarts - number of restarts from random position, >0.
8386  If you don't know what Restarts to choose, use 2.
8387 
8388 OUTPUT PARAMETERS:
8389  Network - trained neural network.
8390  Info - return code:
8391  * -9, if internal matrix inverse subroutine failed
8392  * -2, if there is a point with class number
8393  outside of [0..NOut-1].
8394  * -1, if wrong parameters specified
8395  (NPoints<0, Restarts<1).
8396  * 2, if task has been solved.
8397  Rep - training report
8398 
8399  -- ALGLIB --
8400  Copyright 10.03.2009 by Bochkanov Sergey
8401 *************************************************************************/
8402 void mlptrainlm(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, ae_int_t &info, mlpreport &rep)
8403 {
8404  alglib_impl::ae_state _alglib_env_state;
8405  alglib_impl::ae_state_init(&_alglib_env_state);
8406  try
8407  {
8408  alglib_impl::mlptrainlm(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, decay, restarts, &info, const_cast<alglib_impl::mlpreport*>(rep.c_ptr()), &_alglib_env_state);
8409  alglib_impl::ae_state_clear(&_alglib_env_state);
8410  return;
8411  }
8413  {
8414  throw ap_error(_alglib_env_state.error_msg);
8415  }
8416 }
8417 
8418 /*************************************************************************
8419 Neural network training using L-BFGS algorithm with regularization.
8420 Subroutine trains neural network with restarts from random positions.
8421 Algorithm is well suited for problems of any dimensionality (memory
8422 requirements and step complexity are linear by weights number).
8423 
8424 INPUT PARAMETERS:
8425  Network - neural network with initialized geometry
8426  XY - training set
8427  NPoints - training set size
8428  Decay - weight decay constant, >=0.001
8429  Decay term 'Decay*||Weights||^2' is added to error
8430  function.
8431  If you don't know what Decay to choose, use 0.001.
8432  Restarts - number of restarts from random position, >0.
8433  If you don't know what Restarts to choose, use 2.
8434  WStep - stopping criterion. Algorithm stops if step size is
8435  less than WStep. Recommended value - 0.01. Zero step
8436  size means stopping after MaxIts iterations.
8437  MaxIts - stopping criterion. Algorithm stops after MaxIts
8438  iterations (NOT gradient calculations). Zero MaxIts
8439  means stopping when step is sufficiently small.
8440 
8441 OUTPUT PARAMETERS:
8442  Network - trained neural network.
8443  Info - return code:
8444  * -8, if both WStep=0 and MaxIts=0
8445  * -2, if there is a point with class number
8446  outside of [0..NOut-1].
8447  * -1, if wrong parameters specified
8448  (NPoints<0, Restarts<1).
8449  * 2, if task has been solved.
8450  Rep - training report
8451 
8452  -- ALGLIB --
8453  Copyright 09.12.2007 by Bochkanov Sergey
8454 *************************************************************************/
8455 void mlptrainlbfgs(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, const double wstep, const ae_int_t maxits, ae_int_t &info, mlpreport &rep)
8456 {
8457  alglib_impl::ae_state _alglib_env_state;
8458  alglib_impl::ae_state_init(&_alglib_env_state);
8459  try
8460  {
8461  alglib_impl::mlptrainlbfgs(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, decay, restarts, wstep, maxits, &info, const_cast<alglib_impl::mlpreport*>(rep.c_ptr()), &_alglib_env_state);
8462  alglib_impl::ae_state_clear(&_alglib_env_state);
8463  return;
8464  }
8466  {
8467  throw ap_error(_alglib_env_state.error_msg);
8468  }
8469 }
8470 
8471 /*************************************************************************
8472 Neural network training using early stopping (base algorithm - L-BFGS with
8473 regularization).
8474 
8475 INPUT PARAMETERS:
8476  Network - neural network with initialized geometry
8477  TrnXY - training set
8478  TrnSize - training set size, TrnSize>0
8479  ValXY - validation set
8480  ValSize - validation set size, ValSize>0
8481  Decay - weight decay constant, >=0.001
8482  Decay term 'Decay*||Weights||^2' is added to error
8483  function.
8484  If you don't know what Decay to choose, use 0.001.
8485  Restarts - number of restarts, either:
8486  * strictly positive number - algorithm make specified
8487  number of restarts from random position.
8488  * -1, in which case algorithm makes exactly one run
8489  from the initial state of the network (no randomization).
8490  If you don't know what Restarts to choose, choose one
8491  one the following:
8492  * -1 (deterministic start)
8493  * +1 (one random restart)
8494  * +5 (moderate amount of random restarts)
8495 
8496 OUTPUT PARAMETERS:
8497  Network - trained neural network.
8498  Info - return code:
8499  * -2, if there is a point with class number
8500  outside of [0..NOut-1].
8501  * -1, if wrong parameters specified
8502  (NPoints<0, Restarts<1, ...).
8503  * 2, task has been solved, stopping criterion met -
8504  sufficiently small step size. Not expected (we
8505  use EARLY stopping) but possible and not an
8506  error.
8507  * 6, task has been solved, stopping criterion met -
8508  increasing of validation set error.
8509  Rep - training report
8510 
8511 NOTE:
8512 
8513 Algorithm stops if validation set error increases for a long enough or
8514 step size is small enought (there are task where validation set may
8515 decrease for eternity). In any case solution returned corresponds to the
8516 minimum of validation set error.
8517 
8518  -- ALGLIB --
8519  Copyright 10.03.2009 by Bochkanov Sergey
8520 *************************************************************************/
8521 void mlptraines(const multilayerperceptron &network, const real_2d_array &trnxy, const ae_int_t trnsize, const real_2d_array &valxy, const ae_int_t valsize, const double decay, const ae_int_t restarts, ae_int_t &info, mlpreport &rep)
8522 {
8523  alglib_impl::ae_state _alglib_env_state;
8524  alglib_impl::ae_state_init(&_alglib_env_state);
8525  try
8526  {
8527  alglib_impl::mlptraines(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(trnxy.c_ptr()), trnsize, const_cast<alglib_impl::ae_matrix*>(valxy.c_ptr()), valsize, decay, restarts, &info, const_cast<alglib_impl::mlpreport*>(rep.c_ptr()), &_alglib_env_state);
8528  alglib_impl::ae_state_clear(&_alglib_env_state);
8529  return;
8530  }
8532  {
8533  throw ap_error(_alglib_env_state.error_msg);
8534  }
8535 }
8536 
8537 /*************************************************************************
8538 Cross-validation estimate of generalization error.
8539 
8540 Base algorithm - L-BFGS.
8541 
8542 INPUT PARAMETERS:
8543  Network - neural network with initialized geometry. Network is
8544  not changed during cross-validation - it is used only
8545  as a representative of its architecture.
8546  XY - training set.
8547  SSize - training set size
8548  Decay - weight decay, same as in MLPTrainLBFGS
8549  Restarts - number of restarts, >0.
8550  restarts are counted for each partition separately, so
8551  total number of restarts will be Restarts*FoldsCount.
8552  WStep - stopping criterion, same as in MLPTrainLBFGS
8553  MaxIts - stopping criterion, same as in MLPTrainLBFGS
8554  FoldsCount - number of folds in k-fold cross-validation,
8555  2<=FoldsCount<=SSize.
8556  recommended value: 10.
8557 
8558 OUTPUT PARAMETERS:
8559  Info - return code, same as in MLPTrainLBFGS
8560  Rep - report, same as in MLPTrainLM/MLPTrainLBFGS
8561  CVRep - generalization error estimates
8562 
8563  -- ALGLIB --
8564  Copyright 09.12.2007 by Bochkanov Sergey
8565 *************************************************************************/
8566 void mlpkfoldcvlbfgs(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, const double wstep, const ae_int_t maxits, const ae_int_t foldscount, ae_int_t &info, mlpreport &rep, mlpcvreport &cvrep)
8567 {
8568  alglib_impl::ae_state _alglib_env_state;
8569  alglib_impl::ae_state_init(&_alglib_env_state);
8570  try
8571  {
8572  alglib_impl::mlpkfoldcvlbfgs(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, decay, restarts, wstep, maxits, foldscount, &info, const_cast<alglib_impl::mlpreport*>(rep.c_ptr()), const_cast<alglib_impl::mlpcvreport*>(cvrep.c_ptr()), &_alglib_env_state);
8573  alglib_impl::ae_state_clear(&_alglib_env_state);
8574  return;
8575  }
8577  {
8578  throw ap_error(_alglib_env_state.error_msg);
8579  }
8580 }
8581 
8582 /*************************************************************************
8583 Cross-validation estimate of generalization error.
8584 
8585 Base algorithm - Levenberg-Marquardt.
8586 
8587 INPUT PARAMETERS:
8588  Network - neural network with initialized geometry. Network is
8589  not changed during cross-validation - it is used only
8590  as a representative of its architecture.
8591  XY - training set.
8592  SSize - training set size
8593  Decay - weight decay, same as in MLPTrainLBFGS
8594  Restarts - number of restarts, >0.
8595  restarts are counted for each partition separately, so
8596  total number of restarts will be Restarts*FoldsCount.
8597  FoldsCount - number of folds in k-fold cross-validation,
8598  2<=FoldsCount<=SSize.
8599  recommended value: 10.
8600 
8601 OUTPUT PARAMETERS:
8602  Info - return code, same as in MLPTrainLBFGS
8603  Rep - report, same as in MLPTrainLM/MLPTrainLBFGS
8604  CVRep - generalization error estimates
8605 
8606  -- ALGLIB --
8607  Copyright 09.12.2007 by Bochkanov Sergey
8608 *************************************************************************/
8609 void mlpkfoldcvlm(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, const ae_int_t foldscount, ae_int_t &info, mlpreport &rep, mlpcvreport &cvrep)
8610 {
8611  alglib_impl::ae_state _alglib_env_state;
8612  alglib_impl::ae_state_init(&_alglib_env_state);
8613  try
8614  {
8615  alglib_impl::mlpkfoldcvlm(const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, decay, restarts, foldscount, &info, const_cast<alglib_impl::mlpreport*>(rep.c_ptr()), const_cast<alglib_impl::mlpcvreport*>(cvrep.c_ptr()), &_alglib_env_state);
8616  alglib_impl::ae_state_clear(&_alglib_env_state);
8617  return;
8618  }
8620  {
8621  throw ap_error(_alglib_env_state.error_msg);
8622  }
8623 }
8624 
8625 /*************************************************************************
8626 This function estimates generalization error using cross-validation on the
8627 current dataset with current training settings.
8628 
8629 FOR USERS OF COMMERCIAL EDITION:
8630 
8631  ! Commercial version of ALGLIB includes two important improvements of
8632  ! this function:
8633  ! * multicore support (C++ and C# computational cores)
8634  ! * SSE support (C++ computational core)
8635  !
8636  ! Second improvement gives constant speedup (2-3X). First improvement
8637  ! gives close-to-linear speedup on multicore systems. Following
8638  ! operations can be executed in parallel:
8639  ! * FoldsCount cross-validation rounds (always)
8640  ! * NRestarts training sessions performed within each of
8641  ! cross-validation rounds (if NRestarts>1)
8642  ! * gradient calculation over large dataset (if dataset is large enough)
8643  !
8644  ! In order to use multicore features you have to:
8645  ! * use commercial version of ALGLIB
8646  ! * call this function with "smp_" prefix, which indicates that
8647  ! multicore code will be used (for multicore support)
8648  !
8649  ! In order to use SSE features you have to:
8650  ! * use commercial version of ALGLIB on Intel processors
8651  ! * use C++ computational core
8652  !
8653  ! This note is given for users of commercial edition; if you use GPL
8654  ! edition, you still will be able to call smp-version of this function,
8655  ! but all computations will be done serially.
8656  !
8657  ! We recommend you to carefully read ALGLIB Reference Manual, section
8658  ! called 'SMP support', before using parallel version of this function.
8659 
8660 INPUT PARAMETERS:
8661  S - trainer object
8662  Network - neural network. It must have same number of inputs and
8663  output/classes as was specified during creation of the
8664  trainer object. Network is not changed during cross-
8665  validation and is not trained - it is used only as
8666  representative of its architecture. I.e., we estimate
8667  generalization properties of ARCHITECTURE, not some
8668  specific network.
8669  NRestarts - number of restarts, >=0:
8670  * NRestarts>0 means that for each cross-validation
8671  round specified number of random restarts is
8672  performed, with best network being chosen after
8673  training.
8674  * NRestarts=0 is same as NRestarts=1
8675  FoldsCount - number of folds in k-fold cross-validation:
8676  * 2<=FoldsCount<=size of dataset
8677  * recommended value: 10.
8678  * values larger than dataset size will be silently
8679  truncated down to dataset size
8680 
8681 OUTPUT PARAMETERS:
8682  Rep - structure which contains cross-validation estimates:
8683  * Rep.RelCLSError - fraction of misclassified cases.
8684  * Rep.AvgCE - acerage cross-entropy
8685  * Rep.RMSError - root-mean-square error
8686  * Rep.AvgError - average error
8687  * Rep.AvgRelError - average relative error
8688 
8689 NOTE: when no dataset was specified with MLPSetDataset/SetSparseDataset(),
8690  or subset with only one point was given, zeros are returned as
8691  estimates.
8692 
8693 NOTE: this method performs FoldsCount cross-validation rounds, each one
8694  with NRestarts random starts. Thus, FoldsCount*NRestarts networks
8695  are trained in total.
8696 
8697 NOTE: Rep.RelCLSError/Rep.AvgCE are zero on regression problems.
8698 
8699 NOTE: on classification problems Rep.RMSError/Rep.AvgError/Rep.AvgRelError
8700  contain errors in prediction of posterior probabilities.
8701 
8702  -- ALGLIB --
8703  Copyright 23.07.2012 by Bochkanov Sergey
8704 *************************************************************************/
8705 void mlpkfoldcv(const mlptrainer &s, const multilayerperceptron &network, const ae_int_t nrestarts, const ae_int_t foldscount, mlpreport &rep)
8706 {
8707  alglib_impl::ae_state _alglib_env_state;
8708  alglib_impl::ae_state_init(&_alglib_env_state);
8709  try
8710  {
8711  alglib_impl::mlpkfoldcv(const_cast<alglib_impl::mlptrainer*>(s.c_ptr()), const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), nrestarts, foldscount, const_cast<alglib_impl::mlpreport*>(rep.c_ptr()), &_alglib_env_state);
8712  alglib_impl::ae_state_clear(&_alglib_env_state);
8713  return;
8714  }
8716  {
8717  throw ap_error(_alglib_env_state.error_msg);
8718  }
8719 }
8720 
8721 
8722 void smp_mlpkfoldcv(const mlptrainer &s, const multilayerperceptron &network, const ae_int_t nrestarts, const ae_int_t foldscount, mlpreport &rep)
8723 {
8724  alglib_impl::ae_state _alglib_env_state;
8725  alglib_impl::ae_state_init(&_alglib_env_state);
8726  try
8727  {
8728  alglib_impl::_pexec_mlpkfoldcv(const_cast<alglib_impl::mlptrainer*>(s.c_ptr()), const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), nrestarts, foldscount, const_cast<alglib_impl::mlpreport*>(rep.c_ptr()), &_alglib_env_state);
8729  alglib_impl::ae_state_clear(&_alglib_env_state);
8730  return;
8731  }
8733  {
8734  throw ap_error(_alglib_env_state.error_msg);
8735  }
8736 }
8737 
8738 /*************************************************************************
8739 Creation of the network trainer object for regression networks
8740 
8741 INPUT PARAMETERS:
8742  NIn - number of inputs, NIn>=1
8743  NOut - number of outputs, NOut>=1
8744 
8745 OUTPUT PARAMETERS:
8746  S - neural network trainer object.
8747  This structure can be used to train any regression
8748  network with NIn inputs and NOut outputs.
8749 
8750  -- ALGLIB --
8751  Copyright 23.07.2012 by Bochkanov Sergey
8752 *************************************************************************/
8753 void mlpcreatetrainer(const ae_int_t nin, const ae_int_t nout, mlptrainer &s)
8754 {
8755  alglib_impl::ae_state _alglib_env_state;
8756  alglib_impl::ae_state_init(&_alglib_env_state);
8757  try
8758  {
8759  alglib_impl::mlpcreatetrainer(nin, nout, const_cast<alglib_impl::mlptrainer*>(s.c_ptr()), &_alglib_env_state);
8760  alglib_impl::ae_state_clear(&_alglib_env_state);
8761  return;
8762  }
8764  {
8765  throw ap_error(_alglib_env_state.error_msg);
8766  }
8767 }
8768 
8769 /*************************************************************************
8770 Creation of the network trainer object for classification networks
8771 
8772 INPUT PARAMETERS:
8773  NIn - number of inputs, NIn>=1
8774  NClasses - number of classes, NClasses>=2
8775 
8776 OUTPUT PARAMETERS:
8777  S - neural network trainer object.
8778  This structure can be used to train any classification
8779  network with NIn inputs and NOut outputs.
8780 
8781  -- ALGLIB --
8782  Copyright 23.07.2012 by Bochkanov Sergey
8783 *************************************************************************/
8784 void mlpcreatetrainercls(const ae_int_t nin, const ae_int_t nclasses, mlptrainer &s)
8785 {
8786  alglib_impl::ae_state _alglib_env_state;
8787  alglib_impl::ae_state_init(&_alglib_env_state);
8788  try
8789  {
8790  alglib_impl::mlpcreatetrainercls(nin, nclasses, const_cast<alglib_impl::mlptrainer*>(s.c_ptr()), &_alglib_env_state);
8791  alglib_impl::ae_state_clear(&_alglib_env_state);
8792  return;
8793  }
8795  {
8796  throw ap_error(_alglib_env_state.error_msg);
8797  }
8798 }
8799 
8800 /*************************************************************************
8801 This function sets "current dataset" of the trainer object to one passed
8802 by user.
8803 
8804 INPUT PARAMETERS:
8805  S - trainer object
8806  XY - training set, see below for information on the
8807  training set format. This function checks correctness
8808  of the dataset (no NANs/INFs, class numbers are
8809  correct) and throws exception when incorrect dataset
8810  is passed.
8811  NPoints - points count, >=0.
8812 
8813 DATASET FORMAT:
8814 
8815 This function uses two different dataset formats - one for regression
8816 networks, another one for classification networks.
8817 
8818 For regression networks with NIn inputs and NOut outputs following dataset
8819 format is used:
8820 * dataset is given by NPoints*(NIn+NOut) matrix
8821 * each row corresponds to one example
8822 * first NIn columns are inputs, next NOut columns are outputs
8823 
8824 For classification networks with NIn inputs and NClasses clases following
8825 datasetformat is used:
8826 * dataset is given by NPoints*(NIn+1) matrix
8827 * each row corresponds to one example
8828 * first NIn columns are inputs, last column stores class number (from 0 to
8829  NClasses-1).
8830 
8831  -- ALGLIB --
8832  Copyright 23.07.2012 by Bochkanov Sergey
8833 *************************************************************************/
8834 void mlpsetdataset(const mlptrainer &s, const real_2d_array &xy, const ae_int_t npoints)
8835 {
8836  alglib_impl::ae_state _alglib_env_state;
8837  alglib_impl::ae_state_init(&_alglib_env_state);
8838  try
8839  {
8840  alglib_impl::mlpsetdataset(const_cast<alglib_impl::mlptrainer*>(s.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
8841  alglib_impl::ae_state_clear(&_alglib_env_state);
8842  return;
8843  }
8845  {
8846  throw ap_error(_alglib_env_state.error_msg);
8847  }
8848 }
8849 
8850 /*************************************************************************
8851 This function sets "current dataset" of the trainer object to one passed
8852 by user (sparse matrix is used to store dataset).
8853 
8854 INPUT PARAMETERS:
8855  S - trainer object
8856  XY - training set, see below for information on the
8857  training set format. This function checks correctness
8858  of the dataset (no NANs/INFs, class numbers are
8859  correct) and throws exception when incorrect dataset
8860  is passed. Any sparse storage format can be used:
8861  Hash-table, CRS...
8862  NPoints - points count, >=0
8863 
8864 DATASET FORMAT:
8865 
8866 This function uses two different dataset formats - one for regression
8867 networks, another one for classification networks.
8868 
8869 For regression networks with NIn inputs and NOut outputs following dataset
8870 format is used:
8871 * dataset is given by NPoints*(NIn+NOut) matrix
8872 * each row corresponds to one example
8873 * first NIn columns are inputs, next NOut columns are outputs
8874 
8875 For classification networks with NIn inputs and NClasses clases following
8876 datasetformat is used:
8877 * dataset is given by NPoints*(NIn+1) matrix
8878 * each row corresponds to one example
8879 * first NIn columns are inputs, last column stores class number (from 0 to
8880  NClasses-1).
8881 
8882  -- ALGLIB --
8883  Copyright 23.07.2012 by Bochkanov Sergey
8884 *************************************************************************/
8885 void mlpsetsparsedataset(const mlptrainer &s, const sparsematrix &xy, const ae_int_t npoints)
8886 {
8887  alglib_impl::ae_state _alglib_env_state;
8888  alglib_impl::ae_state_init(&_alglib_env_state);
8889  try
8890  {
8891  alglib_impl::mlpsetsparsedataset(const_cast<alglib_impl::mlptrainer*>(s.c_ptr()), const_cast<alglib_impl::sparsematrix*>(xy.c_ptr()), npoints, &_alglib_env_state);
8892  alglib_impl::ae_state_clear(&_alglib_env_state);
8893  return;
8894  }
8896  {
8897  throw ap_error(_alglib_env_state.error_msg);
8898  }
8899 }
8900 
8901 /*************************************************************************
8902 This function sets weight decay coefficient which is used for training.
8903 
8904 INPUT PARAMETERS:
8905  S - trainer object
8906  Decay - weight decay coefficient, >=0. Weight decay term
8907  'Decay*||Weights||^2' is added to error function. If
8908  you don't know what Decay to choose, use 1.0E-3.
8909  Weight decay can be set to zero, in this case network
8910  is trained without weight decay.
8911 
8912 NOTE: by default network uses some small nonzero value for weight decay.
8913 
8914  -- ALGLIB --
8915  Copyright 23.07.2012 by Bochkanov Sergey
8916 *************************************************************************/
8917 void mlpsetdecay(const mlptrainer &s, const double decay)
8918 {
8919  alglib_impl::ae_state _alglib_env_state;
8920  alglib_impl::ae_state_init(&_alglib_env_state);
8921  try
8922  {
8923  alglib_impl::mlpsetdecay(const_cast<alglib_impl::mlptrainer*>(s.c_ptr()), decay, &_alglib_env_state);
8924  alglib_impl::ae_state_clear(&_alglib_env_state);
8925  return;
8926  }
8928  {
8929  throw ap_error(_alglib_env_state.error_msg);
8930  }
8931 }
8932 
8933 /*************************************************************************
8934 This function sets stopping criteria for the optimizer.
8935 
8936 INPUT PARAMETERS:
8937  S - trainer object
8938  WStep - stopping criterion. Algorithm stops if step size is
8939  less than WStep. Recommended value - 0.01. Zero step
8940  size means stopping after MaxIts iterations.
8941  WStep>=0.
8942  MaxIts - stopping criterion. Algorithm stops after MaxIts
8943  epochs (full passes over entire dataset). Zero MaxIts
8944  means stopping when step is sufficiently small.
8945  MaxIts>=0.
8946 
8947 NOTE: by default, WStep=0.005 and MaxIts=0 are used. These values are also
8948  used when MLPSetCond() is called with WStep=0 and MaxIts=0.
8949 
8950 NOTE: these stopping criteria are used for all kinds of neural training -
8951  from "conventional" networks to early stopping ensembles. When used
8952  for "conventional" networks, they are used as the only stopping
8953  criteria. When combined with early stopping, they used as ADDITIONAL
8954  stopping criteria which can terminate early stopping algorithm.
8955 
8956  -- ALGLIB --
8957  Copyright 23.07.2012 by Bochkanov Sergey
8958 *************************************************************************/
8959 void mlpsetcond(const mlptrainer &s, const double wstep, const ae_int_t maxits)
8960 {
8961  alglib_impl::ae_state _alglib_env_state;
8962  alglib_impl::ae_state_init(&_alglib_env_state);
8963  try
8964  {
8965  alglib_impl::mlpsetcond(const_cast<alglib_impl::mlptrainer*>(s.c_ptr()), wstep, maxits, &_alglib_env_state);
8966  alglib_impl::ae_state_clear(&_alglib_env_state);
8967  return;
8968  }
8970  {
8971  throw ap_error(_alglib_env_state.error_msg);
8972  }
8973 }
8974 
8975 /*************************************************************************
8976 This function sets training algorithm: batch training using L-BFGS will be
8977 used.
8978 
8979 This algorithm:
8980 * the most robust for small-scale problems, but may be too slow for large
8981  scale ones.
8982 * perfoms full pass through the dataset before performing step
8983 * uses conditions specified by MLPSetCond() for stopping
8984 * is default one used by trainer object
8985 
8986 INPUT PARAMETERS:
8987  S - trainer object
8988 
8989  -- ALGLIB --
8990  Copyright 23.07.2012 by Bochkanov Sergey
8991 *************************************************************************/
8993 {
8994  alglib_impl::ae_state _alglib_env_state;
8995  alglib_impl::ae_state_init(&_alglib_env_state);
8996  try
8997  {
8998  alglib_impl::mlpsetalgobatch(const_cast<alglib_impl::mlptrainer*>(s.c_ptr()), &_alglib_env_state);
8999  alglib_impl::ae_state_clear(&_alglib_env_state);
9000  return;
9001  }
9003  {
9004  throw ap_error(_alglib_env_state.error_msg);
9005  }
9006 }
9007 
9008 /*************************************************************************
9009 This function trains neural network passed to this function, using current
9010 dataset (one which was passed to MLPSetDataset() or MLPSetSparseDataset())
9011 and current training settings. Training from NRestarts random starting
9012 positions is performed, best network is chosen.
9013 
9014 Training is performed using current training algorithm.
9015 
9016 FOR USERS OF COMMERCIAL EDITION:
9017 
9018  ! Commercial version of ALGLIB includes two important improvements of
9019  ! this function:
9020  ! * multicore support (C++ and C# computational cores)
9021  ! * SSE support (C++ computational core)
9022  !
9023  ! Second improvement gives constant speedup (2-3X). First improvement
9024  ! gives close-to-linear speedup on multicore systems. Following
9025  ! operations can be executed in parallel:
9026  ! * NRestarts training sessions performed within each of
9027  ! cross-validation rounds (if NRestarts>1)
9028  ! * gradient calculation over large dataset (if dataset is large enough)
9029  !
9030  ! In order to use multicore features you have to:
9031  ! * use commercial version of ALGLIB
9032  ! * call this function with "smp_" prefix, which indicates that
9033  ! multicore code will be used (for multicore support)
9034  !
9035  ! In order to use SSE features you have to:
9036  ! * use commercial version of ALGLIB on Intel processors
9037  ! * use C++ computational core
9038  !
9039  ! This note is given for users of commercial edition; if you use GPL
9040  ! edition, you still will be able to call smp-version of this function,
9041  ! but all computations will be done serially.
9042  !
9043  ! We recommend you to carefully read ALGLIB Reference Manual, section
9044  ! called 'SMP support', before using parallel version of this function.
9045 
9046 INPUT PARAMETERS:
9047  S - trainer object
9048  Network - neural network. It must have same number of inputs and
9049  output/classes as was specified during creation of the
9050  trainer object.
9051  NRestarts - number of restarts, >=0:
9052  * NRestarts>0 means that specified number of random
9053  restarts are performed, best network is chosen after
9054  training
9055  * NRestarts=0 means that current state of the network
9056  is used for training.
9057 
9058 OUTPUT PARAMETERS:
9059  Network - trained network
9060 
9061 NOTE: when no dataset was specified with MLPSetDataset/SetSparseDataset(),
9062  network is filled by zero values. Same behavior for functions
9063  MLPStartTraining and MLPContinueTraining.
9064 
9065 NOTE: this method uses sum-of-squares error function for training.
9066 
9067  -- ALGLIB --
9068  Copyright 23.07.2012 by Bochkanov Sergey
9069 *************************************************************************/
9070 void mlptrainnetwork(const mlptrainer &s, const multilayerperceptron &network, const ae_int_t nrestarts, mlpreport &rep)
9071 {
9072  alglib_impl::ae_state _alglib_env_state;
9073  alglib_impl::ae_state_init(&_alglib_env_state);
9074  try
9075  {
9076  alglib_impl::mlptrainnetwork(const_cast<alglib_impl::mlptrainer*>(s.c_ptr()), const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), nrestarts, const_cast<alglib_impl::mlpreport*>(rep.c_ptr()), &_alglib_env_state);
9077  alglib_impl::ae_state_clear(&_alglib_env_state);
9078  return;
9079  }
9081  {
9082  throw ap_error(_alglib_env_state.error_msg);
9083  }
9084 }
9085 
9086 
9087 void smp_mlptrainnetwork(const mlptrainer &s, const multilayerperceptron &network, const ae_int_t nrestarts, mlpreport &rep)
9088 {
9089  alglib_impl::ae_state _alglib_env_state;
9090  alglib_impl::ae_state_init(&_alglib_env_state);
9091  try
9092  {
9093  alglib_impl::_pexec_mlptrainnetwork(const_cast<alglib_impl::mlptrainer*>(s.c_ptr()), const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), nrestarts, const_cast<alglib_impl::mlpreport*>(rep.c_ptr()), &_alglib_env_state);
9094  alglib_impl::ae_state_clear(&_alglib_env_state);
9095  return;
9096  }
9098  {
9099  throw ap_error(_alglib_env_state.error_msg);
9100  }
9101 }
9102 
9103 /*************************************************************************
9104 IMPORTANT: this is an "expert" version of the MLPTrain() function. We do
9105  not recommend you to use it unless you are pretty sure that you
9106  need ability to monitor training progress.
9107 
9108 This function performs step-by-step training of the neural network. Here
9109 "step-by-step" means that training starts with MLPStartTraining() call,
9110 and then user subsequently calls MLPContinueTraining() to perform one more
9111 iteration of the training.
9112 
9113 After call to this function trainer object remembers network and is ready
9114 to train it. However, no training is performed until first call to
9115 MLPContinueTraining() function. Subsequent calls to MLPContinueTraining()
9116 will advance training progress one iteration further.
9117 
9118 EXAMPLE:
9119  >
9120  > ...initialize network and trainer object....
9121  >
9122  > MLPStartTraining(Trainer, Network, True)
9123  > while MLPContinueTraining(Trainer, Network) do
9124  > ...visualize training progress...
9125  >
9126 
9127 INPUT PARAMETERS:
9128  S - trainer object
9129  Network - neural network. It must have same number of inputs and
9130  output/classes as was specified during creation of the
9131  trainer object.
9132  RandomStart - randomize network before training or not:
9133  * True means that network is randomized and its
9134  initial state (one which was passed to the trainer
9135  object) is lost.
9136  * False means that training is started from the
9137  current state of the network
9138 
9139 OUTPUT PARAMETERS:
9140  Network - neural network which is ready to training (weights are
9141  initialized, preprocessor is initialized using current
9142  training set)
9143 
9144 NOTE: this method uses sum-of-squares error function for training.
9145 
9146 NOTE: it is expected that trainer object settings are NOT changed during
9147  step-by-step training, i.e. no one changes stopping criteria or
9148  training set during training. It is possible and there is no defense
9149  against such actions, but algorithm behavior in such cases is
9150  undefined and can be unpredictable.
9151 
9152  -- ALGLIB --
9153  Copyright 23.07.2012 by Bochkanov Sergey
9154 *************************************************************************/
9155 void mlpstarttraining(const mlptrainer &s, const multilayerperceptron &network, const bool randomstart)
9156 {
9157  alglib_impl::ae_state _alglib_env_state;
9158  alglib_impl::ae_state_init(&_alglib_env_state);
9159  try
9160  {
9161  alglib_impl::mlpstarttraining(const_cast<alglib_impl::mlptrainer*>(s.c_ptr()), const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), randomstart, &_alglib_env_state);
9162  alglib_impl::ae_state_clear(&_alglib_env_state);
9163  return;
9164  }
9166  {
9167  throw ap_error(_alglib_env_state.error_msg);
9168  }
9169 }
9170 
9171 /*************************************************************************
9172 IMPORTANT: this is an "expert" version of the MLPTrain() function. We do
9173  not recommend you to use it unless you are pretty sure that you
9174  need ability to monitor training progress.
9175 
9176 FOR USERS OF COMMERCIAL EDITION:
9177 
9178  ! Commercial version of ALGLIB includes two important improvements of
9179  ! this function:
9180  ! * multicore support (C++ and C# computational cores)
9181  ! * SSE support (C++ computational core)
9182  !
9183  ! Second improvement gives constant speedup (2-3X). First improvement
9184  ! gives close-to-linear speedup on multicore systems. Following
9185  ! operations can be executed in parallel:
9186  ! * gradient calculation over large dataset (if dataset is large enough)
9187  !
9188  ! In order to use multicore features you have to:
9189  ! * use commercial version of ALGLIB
9190  ! * call this function with "smp_" prefix, which indicates that
9191  ! multicore code will be used (for multicore support)
9192  !
9193  ! In order to use SSE features you have to:
9194  ! * use commercial version of ALGLIB on Intel processors
9195  ! * use C++ computational core
9196  !
9197  ! This note is given for users of commercial edition; if you use GPL
9198  ! edition, you still will be able to call smp-version of this function,
9199  ! but all computations will be done serially.
9200  !
9201  ! We recommend you to carefully read ALGLIB Reference Manual, section
9202  ! called 'SMP support', before using parallel version of this function.
9203 
9204 This function performs step-by-step training of the neural network. Here
9205 "step-by-step" means that training starts with MLPStartTraining() call,
9206 and then user subsequently calls MLPContinueTraining() to perform one more
9207 iteration of the training.
9208 
9209 This function performs one more iteration of the training and returns
9210 either True (training continues) or False (training stopped). In case True
9211 was returned, Network weights are updated according to the current state
9212 of the optimization progress. In case False was returned, no additional
9213 updates is performed (previous update of the network weights moved us to
9214 the final point, and no additional updates is needed).
9215 
9216 EXAMPLE:
9217  >
9218  > [initialize network and trainer object]
9219  >
9220  > MLPStartTraining(Trainer, Network, True)
9221  > while MLPContinueTraining(Trainer, Network) do
9222  > [visualize training progress]
9223  >
9224 
9225 INPUT PARAMETERS:
9226  S - trainer object
9227  Network - neural network structure, which is used to store
9228  current state of the training process.
9229 
9230 OUTPUT PARAMETERS:
9231  Network - weights of the neural network are rewritten by the
9232  current approximation.
9233 
9234 NOTE: this method uses sum-of-squares error function for training.
9235 
9236 NOTE: it is expected that trainer object settings are NOT changed during
9237  step-by-step training, i.e. no one changes stopping criteria or
9238  training set during training. It is possible and there is no defense
9239  against such actions, but algorithm behavior in such cases is
9240  undefined and can be unpredictable.
9241 
9242 NOTE: It is expected that Network is the same one which was passed to
9243  MLPStartTraining() function. However, THIS function checks only
9244  following:
9245  * that number of network inputs is consistent with trainer object
9246  settings
9247  * that number of network outputs/classes is consistent with trainer
9248  object settings
9249  * that number of network weights is the same as number of weights in
9250  the network passed to MLPStartTraining() function
9251  Exception is thrown when these conditions are violated.
9252 
9253  It is also expected that you do not change state of the network on
9254  your own - the only party who has right to change network during its
9255  training is a trainer object. Any attempt to interfere with trainer
9256  may lead to unpredictable results.
9257 
9258 
9259  -- ALGLIB --
9260  Copyright 23.07.2012 by Bochkanov Sergey
9261 *************************************************************************/
9263 {
9264  alglib_impl::ae_state _alglib_env_state;
9265  alglib_impl::ae_state_init(&_alglib_env_state);
9266  try
9267  {
9268  ae_bool result = alglib_impl::mlpcontinuetraining(const_cast<alglib_impl::mlptrainer*>(s.c_ptr()), const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), &_alglib_env_state);
9269  alglib_impl::ae_state_clear(&_alglib_env_state);
9270  return *(reinterpret_cast<bool*>(&result));
9271  }
9273  {
9274  throw ap_error(_alglib_env_state.error_msg);
9275  }
9276 }
9277 
9278 
9280 {
9281  alglib_impl::ae_state _alglib_env_state;
9282  alglib_impl::ae_state_init(&_alglib_env_state);
9283  try
9284  {
9285  ae_bool result = alglib_impl::_pexec_mlpcontinuetraining(const_cast<alglib_impl::mlptrainer*>(s.c_ptr()), const_cast<alglib_impl::multilayerperceptron*>(network.c_ptr()), &_alglib_env_state);
9286  alglib_impl::ae_state_clear(&_alglib_env_state);
9287  return *(reinterpret_cast<bool*>(&result));
9288  }
9290  {
9291  throw ap_error(_alglib_env_state.error_msg);
9292  }
9293 }
9294 
9295 /*************************************************************************
9296 Training neural networks ensemble using bootstrap aggregating (bagging).
9297 Modified Levenberg-Marquardt algorithm is used as base training method.
9298 
9299 INPUT PARAMETERS:
9300  Ensemble - model with initialized geometry
9301  XY - training set
9302  NPoints - training set size
9303  Decay - weight decay coefficient, >=0.001
9304  Restarts - restarts, >0.
9305 
9306 OUTPUT PARAMETERS:
9307  Ensemble - trained model
9308  Info - return code:
9309  * -2, if there is a point with class number
9310  outside of [0..NClasses-1].
9311  * -1, if incorrect parameters was passed
9312  (NPoints<0, Restarts<1).
9313  * 2, if task has been solved.
9314  Rep - training report.
9315  OOBErrors - out-of-bag generalization error estimate
9316 
9317  -- ALGLIB --
9318  Copyright 17.02.2009 by Bochkanov Sergey
9319 *************************************************************************/
9320 void mlpebagginglm(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, ae_int_t &info, mlpreport &rep, mlpcvreport &ooberrors)
9321 {
9322  alglib_impl::ae_state _alglib_env_state;
9323  alglib_impl::ae_state_init(&_alglib_env_state);
9324  try
9325  {
9326  alglib_impl::mlpebagginglm(const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, decay, restarts, &info, const_cast<alglib_impl::mlpreport*>(rep.c_ptr()), const_cast<alglib_impl::mlpcvreport*>(ooberrors.c_ptr()), &_alglib_env_state);
9327  alglib_impl::ae_state_clear(&_alglib_env_state);
9328  return;
9329  }
9331  {
9332  throw ap_error(_alglib_env_state.error_msg);
9333  }
9334 }
9335 
9336 /*************************************************************************
9337 Training neural networks ensemble using bootstrap aggregating (bagging).
9338 L-BFGS algorithm is used as base training method.
9339 
9340 INPUT PARAMETERS:
9341  Ensemble - model with initialized geometry
9342  XY - training set
9343  NPoints - training set size
9344  Decay - weight decay coefficient, >=0.001
9345  Restarts - restarts, >0.
9346  WStep - stopping criterion, same as in MLPTrainLBFGS
9347  MaxIts - stopping criterion, same as in MLPTrainLBFGS
9348 
9349 OUTPUT PARAMETERS:
9350  Ensemble - trained model
9351  Info - return code:
9352  * -8, if both WStep=0 and MaxIts=0
9353  * -2, if there is a point with class number
9354  outside of [0..NClasses-1].
9355  * -1, if incorrect parameters was passed
9356  (NPoints<0, Restarts<1).
9357  * 2, if task has been solved.
9358  Rep - training report.
9359  OOBErrors - out-of-bag generalization error estimate
9360 
9361  -- ALGLIB --
9362  Copyright 17.02.2009 by Bochkanov Sergey
9363 *************************************************************************/
9364 void mlpebagginglbfgs(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, const double wstep, const ae_int_t maxits, ae_int_t &info, mlpreport &rep, mlpcvreport &ooberrors)
9365 {
9366  alglib_impl::ae_state _alglib_env_state;
9367  alglib_impl::ae_state_init(&_alglib_env_state);
9368  try
9369  {
9370  alglib_impl::mlpebagginglbfgs(const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, decay, restarts, wstep, maxits, &info, const_cast<alglib_impl::mlpreport*>(rep.c_ptr()), const_cast<alglib_impl::mlpcvreport*>(ooberrors.c_ptr()), &_alglib_env_state);
9371  alglib_impl::ae_state_clear(&_alglib_env_state);
9372  return;
9373  }
9375  {
9376  throw ap_error(_alglib_env_state.error_msg);
9377  }
9378 }
9379 
9380 /*************************************************************************
9381 Training neural networks ensemble using early stopping.
9382 
9383 INPUT PARAMETERS:
9384  Ensemble - model with initialized geometry
9385  XY - training set
9386  NPoints - training set size
9387  Decay - weight decay coefficient, >=0.001
9388  Restarts - restarts, >0.
9389 
9390 OUTPUT PARAMETERS:
9391  Ensemble - trained model
9392  Info - return code:
9393  * -2, if there is a point with class number
9394  outside of [0..NClasses-1].
9395  * -1, if incorrect parameters was passed
9396  (NPoints<0, Restarts<1).
9397  * 6, if task has been solved.
9398  Rep - training report.
9399  OOBErrors - out-of-bag generalization error estimate
9400 
9401  -- ALGLIB --
9402  Copyright 10.03.2009 by Bochkanov Sergey
9403 *************************************************************************/
9404 void mlpetraines(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, ae_int_t &info, mlpreport &rep)
9405 {
9406  alglib_impl::ae_state _alglib_env_state;
9407  alglib_impl::ae_state_init(&_alglib_env_state);
9408  try
9409  {
9410  alglib_impl::mlpetraines(const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), const_cast<alglib_impl::ae_matrix*>(xy.c_ptr()), npoints, decay, restarts, &info, const_cast<alglib_impl::mlpreport*>(rep.c_ptr()), &_alglib_env_state);
9411  alglib_impl::ae_state_clear(&_alglib_env_state);
9412  return;
9413  }
9415  {
9416  throw ap_error(_alglib_env_state.error_msg);
9417  }
9418 }
9419 
9420 /*************************************************************************
9421 This function trains neural network ensemble passed to this function using
9422 current dataset and early stopping training algorithm. Each early stopping
9423 round performs NRestarts random restarts (thus, EnsembleSize*NRestarts
9424 training rounds is performed in total).
9425 
9426 FOR USERS OF COMMERCIAL EDITION:
9427 
9428  ! Commercial version of ALGLIB includes two important improvements of
9429  ! this function:
9430  ! * multicore support (C++ and C# computational cores)
9431  ! * SSE support (C++ computational core)
9432  !
9433  ! Second improvement gives constant speedup (2-3X). First improvement
9434  ! gives close-to-linear speedup on multicore systems. Following
9435  ! operations can be executed in parallel:
9436  ! * EnsembleSize training sessions performed for each of ensemble
9437  ! members (always parallelized)
9438  ! * NRestarts training sessions performed within each of training
9439  ! sessions (if NRestarts>1)
9440  ! * gradient calculation over large dataset (if dataset is large enough)
9441  !
9442  ! In order to use multicore features you have to:
9443  ! * use commercial version of ALGLIB
9444  ! * call this function with "smp_" prefix, which indicates that
9445  ! multicore code will be used (for multicore support)
9446  !
9447  ! In order to use SSE features you have to:
9448  ! * use commercial version of ALGLIB on Intel processors
9449  ! * use C++ computational core
9450  !
9451  ! This note is given for users of commercial edition; if you use GPL
9452  ! edition, you still will be able to call smp-version of this function,
9453  ! but all computations will be done serially.
9454  !
9455  ! We recommend you to carefully read ALGLIB Reference Manual, section
9456  ! called 'SMP support', before using parallel version of this function.
9457 
9458 INPUT PARAMETERS:
9459  S - trainer object;
9460  Ensemble - neural network ensemble. It must have same number of
9461  inputs and outputs/classes as was specified during
9462  creation of the trainer object.
9463  NRestarts - number of restarts, >=0:
9464  * NRestarts>0 means that specified number of random
9465  restarts are performed during each ES round;
9466  * NRestarts=0 is silently replaced by 1.
9467 
9468 OUTPUT PARAMETERS:
9469  Ensemble - trained ensemble;
9470  Rep - it contains all type of errors.
9471 
9472 NOTE: this training method uses BOTH early stopping and weight decay! So,
9473  you should select weight decay before starting training just as you
9474  select it before training "conventional" networks.
9475 
9476 NOTE: when no dataset was specified with MLPSetDataset/SetSparseDataset(),
9477  or single-point dataset was passed, ensemble is filled by zero
9478  values.
9479 
9480 NOTE: this method uses sum-of-squares error function for training.
9481 
9482  -- ALGLIB --
9483  Copyright 22.08.2012 by Bochkanov Sergey
9484 *************************************************************************/
9485 void mlptrainensemblees(const mlptrainer &s, const mlpensemble &ensemble, const ae_int_t nrestarts, mlpreport &rep)
9486 {
9487  alglib_impl::ae_state _alglib_env_state;
9488  alglib_impl::ae_state_init(&_alglib_env_state);
9489  try
9490  {
9491  alglib_impl::mlptrainensemblees(const_cast<alglib_impl::mlptrainer*>(s.c_ptr()), const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), nrestarts, const_cast<alglib_impl::mlpreport*>(rep.c_ptr()), &_alglib_env_state);
9492  alglib_impl::ae_state_clear(&_alglib_env_state);
9493  return;
9494  }
9496  {
9497  throw ap_error(_alglib_env_state.error_msg);
9498  }
9499 }
9500 
9501 
9502 void smp_mlptrainensemblees(const mlptrainer &s, const mlpensemble &ensemble, const ae_int_t nrestarts, mlpreport &rep)
9503 {
9504  alglib_impl::ae_state _alglib_env_state;
9505  alglib_impl::ae_state_init(&_alglib_env_state);
9506  try
9507  {
9508  alglib_impl::_pexec_mlptrainensemblees(const_cast<alglib_impl::mlptrainer*>(s.c_ptr()), const_cast<alglib_impl::mlpensemble*>(ensemble.c_ptr()), nrestarts, const_cast<alglib_impl::mlpreport*>(rep.c_ptr()), &_alglib_env_state);
9509  alglib_impl::ae_state_clear(&_alglib_env_state);
9510  return;
9511  }
9513  {
9514  throw ap_error(_alglib_env_state.error_msg);
9515  }
9516 }
9517 
9518 /*************************************************************************
9519 Principal components analysis
9520 
9521 Subroutine builds orthogonal basis where first axis corresponds to
9522 direction with maximum variance, second axis maximizes variance in subspace
9523 orthogonal to first axis and so on.
9524 
9525 It should be noted that, unlike LDA, PCA does not use class labels.
9526 
9527 INPUT PARAMETERS:
9528  X - dataset, array[0..NPoints-1,0..NVars-1].
9529  matrix contains ONLY INDEPENDENT VARIABLES.
9530  NPoints - dataset size, NPoints>=0
9531  NVars - number of independent variables, NVars>=1
9532 
9533 ÂÛÕÎÄÍÛÅ ÏÀÐÀÌÅÒÐÛ:
9534  Info - return code:
9535  * -4, if SVD subroutine haven't converged
9536  * -1, if wrong parameters has been passed (NPoints<0,
9537  NVars<1)
9538  * 1, if task is solved
9539  S2 - array[0..NVars-1]. variance values corresponding
9540  to basis vectors.
9541  V - array[0..NVars-1,0..NVars-1]
9542  matrix, whose columns store basis vectors.
9543 
9544  -- ALGLIB --
9545  Copyright 25.08.2008 by Bochkanov Sergey
9546 *************************************************************************/
9547 void pcabuildbasis(const real_2d_array &x, const ae_int_t npoints, const ae_int_t nvars, ae_int_t &info, real_1d_array &s2, real_2d_array &v)
9548 {
9549  alglib_impl::ae_state _alglib_env_state;
9550  alglib_impl::ae_state_init(&_alglib_env_state);
9551  try
9552  {
9553  alglib_impl::pcabuildbasis(const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), npoints, nvars, &info, const_cast<alglib_impl::ae_vector*>(s2.c_ptr()), const_cast<alglib_impl::ae_matrix*>(v.c_ptr()), &_alglib_env_state);
9554  alglib_impl::ae_state_clear(&_alglib_env_state);
9555  return;
9556  }
9558  {
9559  throw ap_error(_alglib_env_state.error_msg);
9560  }
9561 }
9562 }
9563 
9565 //
9566 // THIS SECTION CONTAINS IMPLEMENTATION OF COMPUTATIONAL CORE
9567 //
9569 namespace alglib_impl
9570 {
9571 static double bdss_xlny(double x, double y, ae_state *_state);
9572 static double bdss_getcv(/* Integer */ ae_vector* cnt,
9573  ae_int_t nc,
9574  ae_state *_state);
9575 static void bdss_tieaddc(/* Integer */ ae_vector* c,
9576  /* Integer */ ae_vector* ties,
9577  ae_int_t ntie,
9578  ae_int_t nc,
9579  /* Integer */ ae_vector* cnt,
9580  ae_state *_state);
9581 static void bdss_tiesubc(/* Integer */ ae_vector* c,
9582  /* Integer */ ae_vector* ties,
9583  ae_int_t ntie,
9584  ae_int_t nc,
9585  /* Integer */ ae_vector* cnt,
9586  ae_state *_state);
9587 
9588 
9589 static ae_int_t clustering_parallelcomplexity = 200000;
9590 static ae_bool clustering_selectcenterpp(/* Real */ ae_matrix* xy,
9591  ae_int_t npoints,
9592  ae_int_t nvars,
9593  /* Real */ ae_matrix* centers,
9594  /* Boolean */ ae_vector* busycenters,
9595  ae_int_t ccnt,
9596  /* Real */ ae_vector* d2,
9597  /* Real */ ae_vector* p,
9598  /* Real */ ae_vector* tmp,
9599  ae_state *_state);
9600 static void clustering_clusterizerrunahcinternal(clusterizerstate* s,
9601  /* Real */ ae_matrix* d,
9602  ahcreport* rep,
9603  ae_state *_state);
9604 static void clustering_evaluatedistancematrixrec(/* Real */ ae_matrix* xy,
9605  ae_int_t nfeatures,
9606  ae_int_t disttype,
9607  /* Real */ ae_matrix* d,
9608  ae_int_t i0,
9609  ae_int_t i1,
9610  ae_int_t j0,
9611  ae_int_t j1,
9612  ae_state *_state);
9613 
9614 
9615 
9616 
9617 static ae_int_t dforest_innernodewidth = 3;
9618 static ae_int_t dforest_leafnodewidth = 2;
9619 static ae_int_t dforest_dfusestrongsplits = 1;
9620 static ae_int_t dforest_dfuseevs = 2;
9621 static ae_int_t dforest_dffirstversion = 0;
9622 static ae_int_t dforest_dfclserror(decisionforest* df,
9623  /* Real */ ae_matrix* xy,
9624  ae_int_t npoints,
9625  ae_state *_state);
9626 static void dforest_dfprocessinternal(decisionforest* df,
9627  ae_int_t offs,
9628  /* Real */ ae_vector* x,
9629  /* Real */ ae_vector* y,
9630  ae_state *_state);
9631 static void dforest_dfbuildtree(/* Real */ ae_matrix* xy,
9632  ae_int_t npoints,
9633  ae_int_t nvars,
9634  ae_int_t nclasses,
9635  ae_int_t nfeatures,
9636  ae_int_t nvarsinpool,
9637  ae_int_t flags,
9638  dfinternalbuffers* bufs,
9639  hqrndstate* rs,
9640  ae_state *_state);
9641 static void dforest_dfbuildtreerec(/* Real */ ae_matrix* xy,
9642  ae_int_t npoints,
9643  ae_int_t nvars,
9644  ae_int_t nclasses,
9645  ae_int_t nfeatures,
9646  ae_int_t nvarsinpool,
9647  ae_int_t flags,
9648  ae_int_t* numprocessed,
9649  ae_int_t idx1,
9650  ae_int_t idx2,
9651  dfinternalbuffers* bufs,
9652  hqrndstate* rs,
9653  ae_state *_state);
9654 static void dforest_dfsplitc(/* Real */ ae_vector* x,
9655  /* Integer */ ae_vector* c,
9656  /* Integer */ ae_vector* cntbuf,
9657  ae_int_t n,
9658  ae_int_t nc,
9659  ae_int_t flags,
9660  ae_int_t* info,
9661  double* threshold,
9662  double* e,
9663  /* Real */ ae_vector* sortrbuf,
9664  /* Integer */ ae_vector* sortibuf,
9665  ae_state *_state);
9666 static void dforest_dfsplitr(/* Real */ ae_vector* x,
9667  /* Real */ ae_vector* y,
9668  ae_int_t n,
9669  ae_int_t flags,
9670  ae_int_t* info,
9671  double* threshold,
9672  double* e,
9673  /* Real */ ae_vector* sortrbuf,
9674  /* Real */ ae_vector* sortrbuf2,
9675  ae_state *_state);
9676 
9677 
9678 static ae_int_t linreg_lrvnum = 5;
9679 static void linreg_lrinternal(/* Real */ ae_matrix* xy,
9680  /* Real */ ae_vector* s,
9681  ae_int_t npoints,
9682  ae_int_t nvars,
9683  ae_int_t* info,
9684  linearmodel* lm,
9685  lrreport* ar,
9686  ae_state *_state);
9687 
9688 
9689 
9690 
9691 
9692 
9693 static ae_int_t mlpbase_mlpvnum = 7;
9694 static ae_int_t mlpbase_mlpfirstversion = 0;
9695 static ae_int_t mlpbase_nfieldwidth = 4;
9696 static ae_int_t mlpbase_hlconnfieldwidth = 5;
9697 static ae_int_t mlpbase_hlnfieldwidth = 4;
9698 static ae_int_t mlpbase_gradbasecasecost = 50000;
9699 static ae_int_t mlpbase_microbatchsize = 64;
9700 static void mlpbase_addinputlayer(ae_int_t ncount,
9701  /* Integer */ ae_vector* lsizes,
9702  /* Integer */ ae_vector* ltypes,
9703  /* Integer */ ae_vector* lconnfirst,
9704  /* Integer */ ae_vector* lconnlast,
9705  ae_int_t* lastproc,
9706  ae_state *_state);
9707 static void mlpbase_addbiasedsummatorlayer(ae_int_t ncount,
9708  /* Integer */ ae_vector* lsizes,
9709  /* Integer */ ae_vector* ltypes,
9710  /* Integer */ ae_vector* lconnfirst,
9711  /* Integer */ ae_vector* lconnlast,
9712  ae_int_t* lastproc,
9713  ae_state *_state);
9714 static void mlpbase_addactivationlayer(ae_int_t functype,
9715  /* Integer */ ae_vector* lsizes,
9716  /* Integer */ ae_vector* ltypes,
9717  /* Integer */ ae_vector* lconnfirst,
9718  /* Integer */ ae_vector* lconnlast,
9719  ae_int_t* lastproc,
9720  ae_state *_state);
9721 static void mlpbase_addzerolayer(/* Integer */ ae_vector* lsizes,
9722  /* Integer */ ae_vector* ltypes,
9723  /* Integer */ ae_vector* lconnfirst,
9724  /* Integer */ ae_vector* lconnlast,
9725  ae_int_t* lastproc,
9726  ae_state *_state);
9727 static void mlpbase_hladdinputlayer(multilayerperceptron* network,
9728  ae_int_t* connidx,
9729  ae_int_t* neuroidx,
9730  ae_int_t* structinfoidx,
9731  ae_int_t nin,
9732  ae_state *_state);
9733 static void mlpbase_hladdoutputlayer(multilayerperceptron* network,
9734  ae_int_t* connidx,
9735  ae_int_t* neuroidx,
9736  ae_int_t* structinfoidx,
9737  ae_int_t* weightsidx,
9738  ae_int_t k,
9739  ae_int_t nprev,
9740  ae_int_t nout,
9741  ae_bool iscls,
9742  ae_bool islinearout,
9743  ae_state *_state);
9744 static void mlpbase_hladdhiddenlayer(multilayerperceptron* network,
9745  ae_int_t* connidx,
9746  ae_int_t* neuroidx,
9747  ae_int_t* structinfoidx,
9748  ae_int_t* weightsidx,
9749  ae_int_t k,
9750  ae_int_t nprev,
9751  ae_int_t ncur,
9752  ae_state *_state);
9753 static void mlpbase_fillhighlevelinformation(multilayerperceptron* network,
9754  ae_int_t nin,
9755  ae_int_t nhid1,
9756  ae_int_t nhid2,
9757  ae_int_t nout,
9758  ae_bool iscls,
9759  ae_bool islinearout,
9760  ae_state *_state);
9761 static void mlpbase_mlpcreate(ae_int_t nin,
9762  ae_int_t nout,
9763  /* Integer */ ae_vector* lsizes,
9764  /* Integer */ ae_vector* ltypes,
9765  /* Integer */ ae_vector* lconnfirst,
9766  /* Integer */ ae_vector* lconnlast,
9767  ae_int_t layerscount,
9768  ae_bool isclsnet,
9769  multilayerperceptron* network,
9770  ae_state *_state);
9771 static void mlpbase_mlphessianbatchinternal(multilayerperceptron* network,
9772  /* Real */ ae_matrix* xy,
9773  ae_int_t ssize,
9774  ae_bool naturalerr,
9775  double* e,
9776  /* Real */ ae_vector* grad,
9777  /* Real */ ae_matrix* h,
9778  ae_state *_state);
9779 static void mlpbase_mlpinternalcalculategradient(multilayerperceptron* network,
9780  /* Real */ ae_vector* neurons,
9781  /* Real */ ae_vector* weights,
9782  /* Real */ ae_vector* derror,
9783  /* Real */ ae_vector* grad,
9784  ae_bool naturalerrorfunc,
9785  ae_state *_state);
9786 static void mlpbase_mlpchunkedgradient(multilayerperceptron* network,
9787  /* Real */ ae_matrix* xy,
9788  ae_int_t cstart,
9789  ae_int_t csize,
9790  /* Real */ ae_vector* batch4buf,
9791  /* Real */ ae_vector* hpcbuf,
9792  double* e,
9793  ae_bool naturalerrorfunc,
9794  ae_state *_state);
9795 static void mlpbase_mlpchunkedprocess(multilayerperceptron* network,
9796  /* Real */ ae_matrix* xy,
9797  ae_int_t cstart,
9798  ae_int_t csize,
9799  /* Real */ ae_vector* batch4buf,
9800  /* Real */ ae_vector* hpcbuf,
9801  ae_state *_state);
9802 static double mlpbase_safecrossentropy(double t,
9803  double z,
9804  ae_state *_state);
9805 static void mlpbase_randomizebackwardpass(multilayerperceptron* network,
9806  ae_int_t neuronidx,
9807  double v,
9808  ae_state *_state);
9809 
9810 
9811 static double logit_xtol = 100*ae_machineepsilon;
9812 static double logit_ftol = 0.0001;
9813 static double logit_gtol = 0.3;
9814 static ae_int_t logit_maxfev = 20;
9815 static double logit_stpmin = 1.0E-2;
9816 static double logit_stpmax = 1.0E5;
9817 static ae_int_t logit_logitvnum = 6;
9818 static void logit_mnliexp(/* Real */ ae_vector* w,
9819  /* Real */ ae_vector* x,
9820  ae_state *_state);
9821 static void logit_mnlallerrors(logitmodel* lm,
9822  /* Real */ ae_matrix* xy,
9823  ae_int_t npoints,
9824  double* relcls,
9825  double* avgce,
9826  double* rms,
9827  double* avg,
9828  double* avgrel,
9829  ae_state *_state);
9830 static void logit_mnlmcsrch(ae_int_t n,
9831  /* Real */ ae_vector* x,
9832  double* f,
9833  /* Real */ ae_vector* g,
9834  /* Real */ ae_vector* s,
9835  double* stp,
9836  ae_int_t* info,
9837  ae_int_t* nfev,
9838  /* Real */ ae_vector* wa,
9839  logitmcstate* state,
9840  ae_int_t* stage,
9841  ae_state *_state);
9842 static void logit_mnlmcstep(double* stx,
9843  double* fx,
9844  double* dx,
9845  double* sty,
9846  double* fy,
9847  double* dy,
9848  double* stp,
9849  double fp,
9850  double dp,
9851  ae_bool* brackt,
9852  double stmin,
9853  double stmax,
9854  ae_int_t* info,
9855  ae_state *_state);
9856 
9857 
9858 static double mcpd_xtol = 1.0E-8;
9859 static void mcpd_mcpdinit(ae_int_t n,
9860  ae_int_t entrystate,
9861  ae_int_t exitstate,
9862  mcpdstate* s,
9863  ae_state *_state);
9864 
9865 
9866 static ae_int_t mlpe_mlpefirstversion = 1;
9867 
9868 
9869 static double mlptrain_mindecay = 0.001;
9870 static ae_int_t mlptrain_defaultlbfgsfactor = 6;
9871 static void mlptrain_mlpkfoldcvgeneral(multilayerperceptron* n,
9872  /* Real */ ae_matrix* xy,
9873  ae_int_t npoints,
9874  double decay,
9875  ae_int_t restarts,
9876  ae_int_t foldscount,
9877  ae_bool lmalgorithm,
9878  double wstep,
9879  ae_int_t maxits,
9880  ae_int_t* info,
9881  mlpreport* rep,
9882  mlpcvreport* cvrep,
9883  ae_state *_state);
9884 static void mlptrain_mlpkfoldsplit(/* Real */ ae_matrix* xy,
9885  ae_int_t npoints,
9886  ae_int_t nclasses,
9887  ae_int_t foldscount,
9888  ae_bool stratifiedsplits,
9889  /* Integer */ ae_vector* folds,
9890  ae_state *_state);
9891 static void mlptrain_mthreadcv(mlptrainer* s,
9892  ae_int_t rowsize,
9893  ae_int_t nrestarts,
9894  /* Integer */ ae_vector* folds,
9895  ae_int_t fold,
9896  ae_int_t dfold,
9897  /* Real */ ae_matrix* cvy,
9898  ae_shared_pool* pooldatacv,
9899  ae_state *_state);
9900 static void mlptrain_mlptrainnetworkx(mlptrainer* s,
9901  ae_int_t nrestarts,
9902  ae_int_t algokind,
9903  /* Integer */ ae_vector* trnsubset,
9904  ae_int_t trnsubsetsize,
9905  /* Integer */ ae_vector* valsubset,
9906  ae_int_t valsubsetsize,
9907  multilayerperceptron* network,
9908  mlpreport* rep,
9909  ae_bool isrootcall,
9910  ae_shared_pool* sessions,
9911  ae_state *_state);
9912 static void mlptrain_mlptrainensemblex(mlptrainer* s,
9913  mlpensemble* ensemble,
9914  ae_int_t idx0,
9915  ae_int_t idx1,
9916  ae_int_t nrestarts,
9917  ae_int_t trainingmethod,
9918  sinteger* ngrad,
9919  ae_bool isrootcall,
9920  ae_shared_pool* esessions,
9921  ae_state *_state);
9922 static void mlptrain_mlpstarttrainingx(mlptrainer* s,
9923  ae_bool randomstart,
9924  ae_int_t algokind,
9925  /* Integer */ ae_vector* subset,
9926  ae_int_t subsetsize,
9927  smlptrnsession* session,
9928  ae_state *_state);
9929 static ae_bool mlptrain_mlpcontinuetrainingx(mlptrainer* s,
9930  /* Integer */ ae_vector* subset,
9931  ae_int_t subsetsize,
9932  ae_int_t* ngradbatch,
9933  smlptrnsession* session,
9934  ae_state *_state);
9935 static void mlptrain_mlpebagginginternal(mlpensemble* ensemble,
9936  /* Real */ ae_matrix* xy,
9937  ae_int_t npoints,
9938  double decay,
9939  ae_int_t restarts,
9940  double wstep,
9941  ae_int_t maxits,
9942  ae_bool lmalgorithm,
9943  ae_int_t* info,
9944  mlpreport* rep,
9945  mlpcvreport* ooberrors,
9946  ae_state *_state);
9947 static void mlptrain_initmlptrnsession(multilayerperceptron* networktrained,
9948  ae_bool randomizenetwork,
9949  mlptrainer* trainer,
9950  smlptrnsession* session,
9951  ae_state *_state);
9952 static void mlptrain_initmlptrnsessions(multilayerperceptron* networktrained,
9953  ae_bool randomizenetwork,
9954  mlptrainer* trainer,
9955  ae_shared_pool* sessions,
9956  ae_state *_state);
9957 static void mlptrain_initmlpetrnsession(multilayerperceptron* individualnetwork,
9958  mlptrainer* trainer,
9959  mlpetrnsession* session,
9960  ae_state *_state);
9961 static void mlptrain_initmlpetrnsessions(multilayerperceptron* individualnetwork,
9962  mlptrainer* trainer,
9963  ae_shared_pool* sessions,
9964  ae_state *_state);
9965 
9966 
9967 
9968 
9969 
9970 
9971 
9972 /*************************************************************************
9973 This set of routines (DSErrAllocate, DSErrAccumulate, DSErrFinish)
9974 calculates different error functions (classification error, cross-entropy,
9975 rms, avg, avg.rel errors).
9976 
9977 1. DSErrAllocate prepares buffer.
9978 2. DSErrAccumulate accumulates individual errors:
9979  * Y contains predicted output (posterior probabilities for classification)
9980  * DesiredY contains desired output (class number for classification)
9981 3. DSErrFinish outputs results:
9982  * Buf[0] contains relative classification error (zero for regression tasks)
9983  * Buf[1] contains avg. cross-entropy (zero for regression tasks)
9984  * Buf[2] contains rms error (regression, classification)
9985  * Buf[3] contains average error (regression, classification)
9986  * Buf[4] contains average relative error (regression, classification)
9987 
9988 NOTES(1):
9989  "NClasses>0" means that we have classification task.
9990  "NClasses<0" means regression task with -NClasses real outputs.
9991 
9992 NOTES(2):
9993  rms. avg, avg.rel errors for classification tasks are interpreted as
9994  errors in posterior probabilities with respect to probabilities given
9995  by training/test set.
9996 
9997  -- ALGLIB --
9998  Copyright 11.01.2009 by Bochkanov Sergey
9999 *************************************************************************/
10000 void dserrallocate(ae_int_t nclasses,
10001  /* Real */ ae_vector* buf,
10002  ae_state *_state)
10003 {
10004 
10005  ae_vector_clear(buf);
10006 
10007  ae_vector_set_length(buf, 7+1, _state);
10008  buf->ptr.p_double[0] = 0;
10009  buf->ptr.p_double[1] = 0;
10010  buf->ptr.p_double[2] = 0;
10011  buf->ptr.p_double[3] = 0;
10012  buf->ptr.p_double[4] = 0;
10013  buf->ptr.p_double[5] = nclasses;
10014  buf->ptr.p_double[6] = 0;
10015  buf->ptr.p_double[7] = 0;
10016 }
10017 
10018 
10019 /*************************************************************************
10020 See DSErrAllocate for comments on this routine.
10021 
10022  -- ALGLIB --
10023  Copyright 11.01.2009 by Bochkanov Sergey
10024 *************************************************************************/
10025 void dserraccumulate(/* Real */ ae_vector* buf,
10026  /* Real */ ae_vector* y,
10027  /* Real */ ae_vector* desiredy,
10028  ae_state *_state)
10029 {
10030  ae_int_t nclasses;
10031  ae_int_t nout;
10032  ae_int_t offs;
10033  ae_int_t mmax;
10034  ae_int_t rmax;
10035  ae_int_t j;
10036  double v;
10037  double ev;
10038 
10039 
10040  offs = 5;
10041  nclasses = ae_round(buf->ptr.p_double[offs], _state);
10042  if( nclasses>0 )
10043  {
10044 
10045  /*
10046  * Classification
10047  */
10048  rmax = ae_round(desiredy->ptr.p_double[0], _state);
10049  mmax = 0;
10050  for(j=1; j<=nclasses-1; j++)
10051  {
10052  if( ae_fp_greater(y->ptr.p_double[j],y->ptr.p_double[mmax]) )
10053  {
10054  mmax = j;
10055  }
10056  }
10057  if( mmax!=rmax )
10058  {
10059  buf->ptr.p_double[0] = buf->ptr.p_double[0]+1;
10060  }
10061  if( ae_fp_greater(y->ptr.p_double[rmax],0) )
10062  {
10063  buf->ptr.p_double[1] = buf->ptr.p_double[1]-ae_log(y->ptr.p_double[rmax], _state);
10064  }
10065  else
10066  {
10067  buf->ptr.p_double[1] = buf->ptr.p_double[1]+ae_log(ae_maxrealnumber, _state);
10068  }
10069  for(j=0; j<=nclasses-1; j++)
10070  {
10071  v = y->ptr.p_double[j];
10072  if( j==rmax )
10073  {
10074  ev = 1;
10075  }
10076  else
10077  {
10078  ev = 0;
10079  }
10080  buf->ptr.p_double[2] = buf->ptr.p_double[2]+ae_sqr(v-ev, _state);
10081  buf->ptr.p_double[3] = buf->ptr.p_double[3]+ae_fabs(v-ev, _state);
10082  if( ae_fp_neq(ev,0) )
10083  {
10084  buf->ptr.p_double[4] = buf->ptr.p_double[4]+ae_fabs((v-ev)/ev, _state);
10085  buf->ptr.p_double[offs+2] = buf->ptr.p_double[offs+2]+1;
10086  }
10087  }
10088  buf->ptr.p_double[offs+1] = buf->ptr.p_double[offs+1]+1;
10089  }
10090  else
10091  {
10092 
10093  /*
10094  * Regression
10095  */
10096  nout = -nclasses;
10097  rmax = 0;
10098  for(j=1; j<=nout-1; j++)
10099  {
10100  if( ae_fp_greater(desiredy->ptr.p_double[j],desiredy->ptr.p_double[rmax]) )
10101  {
10102  rmax = j;
10103  }
10104  }
10105  mmax = 0;
10106  for(j=1; j<=nout-1; j++)
10107  {
10108  if( ae_fp_greater(y->ptr.p_double[j],y->ptr.p_double[mmax]) )
10109  {
10110  mmax = j;
10111  }
10112  }
10113  if( mmax!=rmax )
10114  {
10115  buf->ptr.p_double[0] = buf->ptr.p_double[0]+1;
10116  }
10117  for(j=0; j<=nout-1; j++)
10118  {
10119  v = y->ptr.p_double[j];
10120  ev = desiredy->ptr.p_double[j];
10121  buf->ptr.p_double[2] = buf->ptr.p_double[2]+ae_sqr(v-ev, _state);
10122  buf->ptr.p_double[3] = buf->ptr.p_double[3]+ae_fabs(v-ev, _state);
10123  if( ae_fp_neq(ev,0) )
10124  {
10125  buf->ptr.p_double[4] = buf->ptr.p_double[4]+ae_fabs((v-ev)/ev, _state);
10126  buf->ptr.p_double[offs+2] = buf->ptr.p_double[offs+2]+1;
10127  }
10128  }
10129  buf->ptr.p_double[offs+1] = buf->ptr.p_double[offs+1]+1;
10130  }
10131 }
10132 
10133 
10134 /*************************************************************************
10135 See DSErrAllocate for comments on this routine.
10136 
10137  -- ALGLIB --
10138  Copyright 11.01.2009 by Bochkanov Sergey
10139 *************************************************************************/
10140 void dserrfinish(/* Real */ ae_vector* buf, ae_state *_state)
10141 {
10142  ae_int_t nout;
10143  ae_int_t offs;
10144 
10145 
10146  offs = 5;
10147  nout = ae_iabs(ae_round(buf->ptr.p_double[offs], _state), _state);
10148  if( ae_fp_neq(buf->ptr.p_double[offs+1],0) )
10149  {
10150  buf->ptr.p_double[0] = buf->ptr.p_double[0]/buf->ptr.p_double[offs+1];
10151  buf->ptr.p_double[1] = buf->ptr.p_double[1]/buf->ptr.p_double[offs+1];
10152  buf->ptr.p_double[2] = ae_sqrt(buf->ptr.p_double[2]/(nout*buf->ptr.p_double[offs+1]), _state);
10153  buf->ptr.p_double[3] = buf->ptr.p_double[3]/(nout*buf->ptr.p_double[offs+1]);
10154  }
10155  if( ae_fp_neq(buf->ptr.p_double[offs+2],0) )
10156  {
10157  buf->ptr.p_double[4] = buf->ptr.p_double[4]/buf->ptr.p_double[offs+2];
10158  }
10159 }
10160 
10161 
10162 /*************************************************************************
10163 
10164  -- ALGLIB --
10165  Copyright 19.05.2008 by Bochkanov Sergey
10166 *************************************************************************/
10167 void dsnormalize(/* Real */ ae_matrix* xy,
10168  ae_int_t npoints,
10169  ae_int_t nvars,
10170  ae_int_t* info,
10171  /* Real */ ae_vector* means,
10172  /* Real */ ae_vector* sigmas,
10173  ae_state *_state)
10174 {
10175  ae_frame _frame_block;
10176  ae_int_t i;
10177  ae_int_t j;
10178  ae_vector tmp;
10179  double mean;
10180  double variance;
10181  double skewness;
10182  double kurtosis;
10183 
10184  ae_frame_make(_state, &_frame_block);
10185  *info = 0;
10186  ae_vector_clear(means);
10187  ae_vector_clear(sigmas);
10188  ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
10189 
10190 
10191  /*
10192  * Test parameters
10193  */
10194  if( npoints<=0||nvars<1 )
10195  {
10196  *info = -1;
10197  ae_frame_leave(_state);
10198  return;
10199  }
10200  *info = 1;
10201 
10202  /*
10203  * Standartization
10204  */
10205  ae_vector_set_length(means, nvars-1+1, _state);
10206  ae_vector_set_length(sigmas, nvars-1+1, _state);
10207  ae_vector_set_length(&tmp, npoints-1+1, _state);
10208  for(j=0; j<=nvars-1; j++)
10209  {
10210  ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][j], xy->stride, ae_v_len(0,npoints-1));
10211  samplemoments(&tmp, npoints, &mean, &variance, &skewness, &kurtosis, _state);
10212  means->ptr.p_double[j] = mean;
10213  sigmas->ptr.p_double[j] = ae_sqrt(variance, _state);
10214  if( ae_fp_eq(sigmas->ptr.p_double[j],0) )
10215  {
10216  sigmas->ptr.p_double[j] = 1;
10217  }
10218  for(i=0; i<=npoints-1; i++)
10219  {
10220  xy->ptr.pp_double[i][j] = (xy->ptr.pp_double[i][j]-means->ptr.p_double[j])/sigmas->ptr.p_double[j];
10221  }
10222  }
10223  ae_frame_leave(_state);
10224 }
10225 
10226 
10227 /*************************************************************************
10228 
10229  -- ALGLIB --
10230  Copyright 19.05.2008 by Bochkanov Sergey
10231 *************************************************************************/
10232 void dsnormalizec(/* Real */ ae_matrix* xy,
10233  ae_int_t npoints,
10234  ae_int_t nvars,
10235  ae_int_t* info,
10236  /* Real */ ae_vector* means,
10237  /* Real */ ae_vector* sigmas,
10238  ae_state *_state)
10239 {
10240  ae_frame _frame_block;
10241  ae_int_t j;
10242  ae_vector tmp;
10243  double mean;
10244  double variance;
10245  double skewness;
10246  double kurtosis;
10247 
10248  ae_frame_make(_state, &_frame_block);
10249  *info = 0;
10250  ae_vector_clear(means);
10251  ae_vector_clear(sigmas);
10252  ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
10253 
10254 
10255  /*
10256  * Test parameters
10257  */
10258  if( npoints<=0||nvars<1 )
10259  {
10260  *info = -1;
10261  ae_frame_leave(_state);
10262  return;
10263  }
10264  *info = 1;
10265 
10266  /*
10267  * Standartization
10268  */
10269  ae_vector_set_length(means, nvars-1+1, _state);
10270  ae_vector_set_length(sigmas, nvars-1+1, _state);
10271  ae_vector_set_length(&tmp, npoints-1+1, _state);
10272  for(j=0; j<=nvars-1; j++)
10273  {
10274  ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[0][j], xy->stride, ae_v_len(0,npoints-1));
10275  samplemoments(&tmp, npoints, &mean, &variance, &skewness, &kurtosis, _state);
10276  means->ptr.p_double[j] = mean;
10277  sigmas->ptr.p_double[j] = ae_sqrt(variance, _state);
10278  if( ae_fp_eq(sigmas->ptr.p_double[j],0) )
10279  {
10280  sigmas->ptr.p_double[j] = 1;
10281  }
10282  }
10283  ae_frame_leave(_state);
10284 }
10285 
10286 
10287 /*************************************************************************
10288 
10289  -- ALGLIB --
10290  Copyright 19.05.2008 by Bochkanov Sergey
10291 *************************************************************************/
10292 double dsgetmeanmindistance(/* Real */ ae_matrix* xy,
10293  ae_int_t npoints,
10294  ae_int_t nvars,
10295  ae_state *_state)
10296 {
10297  ae_frame _frame_block;
10298  ae_int_t i;
10299  ae_int_t j;
10300  ae_vector tmp;
10301  ae_vector tmp2;
10302  double v;
10303  double result;
10304 
10305  ae_frame_make(_state, &_frame_block);
10306  ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
10307  ae_vector_init(&tmp2, 0, DT_REAL, _state, ae_true);
10308 
10309 
10310  /*
10311  * Test parameters
10312  */
10313  if( npoints<=0||nvars<1 )
10314  {
10315  result = 0;
10316  ae_frame_leave(_state);
10317  return result;
10318  }
10319 
10320  /*
10321  * Process
10322  */
10323  ae_vector_set_length(&tmp, npoints-1+1, _state);
10324  for(i=0; i<=npoints-1; i++)
10325  {
10326  tmp.ptr.p_double[i] = ae_maxrealnumber;
10327  }
10328  ae_vector_set_length(&tmp2, nvars-1+1, _state);
10329  for(i=0; i<=npoints-1; i++)
10330  {
10331  for(j=i+1; j<=npoints-1; j++)
10332  {
10333  ae_v_move(&tmp2.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
10334  ae_v_sub(&tmp2.ptr.p_double[0], 1, &xy->ptr.pp_double[j][0], 1, ae_v_len(0,nvars-1));
10335  v = ae_v_dotproduct(&tmp2.ptr.p_double[0], 1, &tmp2.ptr.p_double[0], 1, ae_v_len(0,nvars-1));
10336  v = ae_sqrt(v, _state);
10337  tmp.ptr.p_double[i] = ae_minreal(tmp.ptr.p_double[i], v, _state);
10338  tmp.ptr.p_double[j] = ae_minreal(tmp.ptr.p_double[j], v, _state);
10339  }
10340  }
10341  result = 0;
10342  for(i=0; i<=npoints-1; i++)
10343  {
10344  result = result+tmp.ptr.p_double[i]/npoints;
10345  }
10346  ae_frame_leave(_state);
10347  return result;
10348 }
10349 
10350 
10351 /*************************************************************************
10352 
10353  -- ALGLIB --
10354  Copyright 19.05.2008 by Bochkanov Sergey
10355 *************************************************************************/
10356 void dstie(/* Real */ ae_vector* a,
10357  ae_int_t n,
10358  /* Integer */ ae_vector* ties,
10359  ae_int_t* tiecount,
10360  /* Integer */ ae_vector* p1,
10361  /* Integer */ ae_vector* p2,
10362  ae_state *_state)
10363 {
10364  ae_frame _frame_block;
10365  ae_int_t i;
10366  ae_int_t k;
10367  ae_vector tmp;
10368 
10369  ae_frame_make(_state, &_frame_block);
10370  ae_vector_clear(ties);
10371  *tiecount = 0;
10372  ae_vector_clear(p1);
10373  ae_vector_clear(p2);
10374  ae_vector_init(&tmp, 0, DT_INT, _state, ae_true);
10375 
10376 
10377  /*
10378  * Special case
10379  */
10380  if( n<=0 )
10381  {
10382  *tiecount = 0;
10383  ae_frame_leave(_state);
10384  return;
10385  }
10386 
10387  /*
10388  * Sort A
10389  */
10390  tagsort(a, n, p1, p2, _state);
10391 
10392  /*
10393  * Process ties
10394  */
10395  *tiecount = 1;
10396  for(i=1; i<=n-1; i++)
10397  {
10398  if( ae_fp_neq(a->ptr.p_double[i],a->ptr.p_double[i-1]) )
10399  {
10400  *tiecount = *tiecount+1;
10401  }
10402  }
10403  ae_vector_set_length(ties, *tiecount+1, _state);
10404  ties->ptr.p_int[0] = 0;
10405  k = 1;
10406  for(i=1; i<=n-1; i++)
10407  {
10408  if( ae_fp_neq(a->ptr.p_double[i],a->ptr.p_double[i-1]) )
10409  {
10410  ties->ptr.p_int[k] = i;
10411  k = k+1;
10412  }
10413  }
10414  ties->ptr.p_int[*tiecount] = n;
10415  ae_frame_leave(_state);
10416 }
10417 
10418 
10419 /*************************************************************************
10420 
10421  -- ALGLIB --
10422  Copyright 11.12.2008 by Bochkanov Sergey
10423 *************************************************************************/
10424 void dstiefasti(/* Real */ ae_vector* a,
10425  /* Integer */ ae_vector* b,
10426  ae_int_t n,
10427  /* Integer */ ae_vector* ties,
10428  ae_int_t* tiecount,
10429  /* Real */ ae_vector* bufr,
10430  /* Integer */ ae_vector* bufi,
10431  ae_state *_state)
10432 {
10433  ae_frame _frame_block;
10434  ae_int_t i;
10435  ae_int_t k;
10436  ae_vector tmp;
10437 
10438  ae_frame_make(_state, &_frame_block);
10439  *tiecount = 0;
10440  ae_vector_init(&tmp, 0, DT_INT, _state, ae_true);
10441 
10442 
10443  /*
10444  * Special case
10445  */
10446  if( n<=0 )
10447  {
10448  *tiecount = 0;
10449  ae_frame_leave(_state);
10450  return;
10451  }
10452 
10453  /*
10454  * Sort A
10455  */
10456  tagsortfasti(a, b, bufr, bufi, n, _state);
10457 
10458  /*
10459  * Process ties
10460  */
10461  ties->ptr.p_int[0] = 0;
10462  k = 1;
10463  for(i=1; i<=n-1; i++)
10464  {
10465  if( ae_fp_neq(a->ptr.p_double[i],a->ptr.p_double[i-1]) )
10466  {
10467  ties->ptr.p_int[k] = i;
10468  k = k+1;
10469  }
10470  }
10471  ties->ptr.p_int[k] = n;
10472  *tiecount = k;
10473  ae_frame_leave(_state);
10474 }
10475 
10476 
10477 /*************************************************************************
10478 Optimal binary classification
10479 
10480 Algorithms finds optimal (=with minimal cross-entropy) binary partition.
10481 Internal subroutine.
10482 
10483 INPUT PARAMETERS:
10484  A - array[0..N-1], variable
10485  C - array[0..N-1], class numbers (0 or 1).
10486  N - array size
10487 
10488 OUTPUT PARAMETERS:
10489  Info - completion code:
10490  * -3, all values of A[] are same (partition is impossible)
10491  * -2, one of C[] is incorrect (<0, >1)
10492  * -1, incorrect pararemets were passed (N<=0).
10493  * 1, OK
10494  Threshold- partiton boundary. Left part contains values which are
10495  strictly less than Threshold. Right part contains values
10496  which are greater than or equal to Threshold.
10497  PAL, PBL- probabilities P(0|v<Threshold) and P(1|v<Threshold)
10498  PAR, PBR- probabilities P(0|v>=Threshold) and P(1|v>=Threshold)
10499  CVE - cross-validation estimate of cross-entropy
10500 
10501  -- ALGLIB --
10502  Copyright 22.05.2008 by Bochkanov Sergey
10503 *************************************************************************/
10504 void dsoptimalsplit2(/* Real */ ae_vector* a,
10505  /* Integer */ ae_vector* c,
10506  ae_int_t n,
10507  ae_int_t* info,
10508  double* threshold,
10509  double* pal,
10510  double* pbl,
10511  double* par,
10512  double* pbr,
10513  double* cve,
10514  ae_state *_state)
10515 {
10516  ae_frame _frame_block;
10517  ae_vector _a;
10518  ae_vector _c;
10519  ae_int_t i;
10520  ae_int_t t;
10521  double s;
10522  ae_vector ties;
10523  ae_int_t tiecount;
10524  ae_vector p1;
10525  ae_vector p2;
10526  ae_int_t k;
10527  ae_int_t koptimal;
10528  double pak;
10529  double pbk;
10530  double cvoptimal;
10531  double cv;
10532 
10533  ae_frame_make(_state, &_frame_block);
10534  ae_vector_init_copy(&_a, a, _state, ae_true);
10535  a = &_a;
10536  ae_vector_init_copy(&_c, c, _state, ae_true);
10537  c = &_c;
10538  *info = 0;
10539  *threshold = 0;
10540  *pal = 0;
10541  *pbl = 0;
10542  *par = 0;
10543  *pbr = 0;
10544  *cve = 0;
10545  ae_vector_init(&ties, 0, DT_INT, _state, ae_true);
10546  ae_vector_init(&p1, 0, DT_INT, _state, ae_true);
10547  ae_vector_init(&p2, 0, DT_INT, _state, ae_true);
10548 
10549 
10550  /*
10551  * Test for errors in inputs
10552  */
10553  if( n<=0 )
10554  {
10555  *info = -1;
10556  ae_frame_leave(_state);
10557  return;
10558  }
10559  for(i=0; i<=n-1; i++)
10560  {
10561  if( c->ptr.p_int[i]!=0&&c->ptr.p_int[i]!=1 )
10562  {
10563  *info = -2;
10564  ae_frame_leave(_state);
10565  return;
10566  }
10567  }
10568  *info = 1;
10569 
10570  /*
10571  * Tie
10572  */
10573  dstie(a, n, &ties, &tiecount, &p1, &p2, _state);
10574  for(i=0; i<=n-1; i++)
10575  {
10576  if( p2.ptr.p_int[i]!=i )
10577  {
10578  t = c->ptr.p_int[i];
10579  c->ptr.p_int[i] = c->ptr.p_int[p2.ptr.p_int[i]];
10580  c->ptr.p_int[p2.ptr.p_int[i]] = t;
10581  }
10582  }
10583 
10584  /*
10585  * Special case: number of ties is 1.
10586  *
10587  * NOTE: we assume that P[i,j] equals to 0 or 1,
10588  * intermediate values are not allowed.
10589  */
10590  if( tiecount==1 )
10591  {
10592  *info = -3;
10593  ae_frame_leave(_state);
10594  return;
10595  }
10596 
10597  /*
10598  * General case, number of ties > 1
10599  *
10600  * NOTE: we assume that P[i,j] equals to 0 or 1,
10601  * intermediate values are not allowed.
10602  */
10603  *pal = 0;
10604  *pbl = 0;
10605  *par = 0;
10606  *pbr = 0;
10607  for(i=0; i<=n-1; i++)
10608  {
10609  if( c->ptr.p_int[i]==0 )
10610  {
10611  *par = *par+1;
10612  }
10613  if( c->ptr.p_int[i]==1 )
10614  {
10615  *pbr = *pbr+1;
10616  }
10617  }
10618  koptimal = -1;
10619  cvoptimal = ae_maxrealnumber;
10620  for(k=0; k<=tiecount-2; k++)
10621  {
10622 
10623  /*
10624  * first, obtain information about K-th tie which is
10625  * moved from R-part to L-part
10626  */
10627  pak = 0;
10628  pbk = 0;
10629  for(i=ties.ptr.p_int[k]; i<=ties.ptr.p_int[k+1]-1; i++)
10630  {
10631  if( c->ptr.p_int[i]==0 )
10632  {
10633  pak = pak+1;
10634  }
10635  if( c->ptr.p_int[i]==1 )
10636  {
10637  pbk = pbk+1;
10638  }
10639  }
10640 
10641  /*
10642  * Calculate cross-validation CE
10643  */
10644  cv = 0;
10645  cv = cv-bdss_xlny(*pal+pak, (*pal+pak)/(*pal+pak+(*pbl)+pbk+1), _state);
10646  cv = cv-bdss_xlny(*pbl+pbk, (*pbl+pbk)/(*pal+pak+1+(*pbl)+pbk), _state);
10647  cv = cv-bdss_xlny(*par-pak, (*par-pak)/(*par-pak+(*pbr)-pbk+1), _state);
10648  cv = cv-bdss_xlny(*pbr-pbk, (*pbr-pbk)/(*par-pak+1+(*pbr)-pbk), _state);
10649 
10650  /*
10651  * Compare with best
10652  */
10653  if( ae_fp_less(cv,cvoptimal) )
10654  {
10655  cvoptimal = cv;
10656  koptimal = k;
10657  }
10658 
10659  /*
10660  * update
10661  */
10662  *pal = *pal+pak;
10663  *pbl = *pbl+pbk;
10664  *par = *par-pak;
10665  *pbr = *pbr-pbk;
10666  }
10667  *cve = cvoptimal;
10668  *threshold = 0.5*(a->ptr.p_double[ties.ptr.p_int[koptimal]]+a->ptr.p_double[ties.ptr.p_int[koptimal+1]]);
10669  *pal = 0;
10670  *pbl = 0;
10671  *par = 0;
10672  *pbr = 0;
10673  for(i=0; i<=n-1; i++)
10674  {
10675  if( ae_fp_less(a->ptr.p_double[i],*threshold) )
10676  {
10677  if( c->ptr.p_int[i]==0 )
10678  {
10679  *pal = *pal+1;
10680  }
10681  else
10682  {
10683  *pbl = *pbl+1;
10684  }
10685  }
10686  else
10687  {
10688  if( c->ptr.p_int[i]==0 )
10689  {
10690  *par = *par+1;
10691  }
10692  else
10693  {
10694  *pbr = *pbr+1;
10695  }
10696  }
10697  }
10698  s = *pal+(*pbl);
10699  *pal = *pal/s;
10700  *pbl = *pbl/s;
10701  s = *par+(*pbr);
10702  *par = *par/s;
10703  *pbr = *pbr/s;
10704  ae_frame_leave(_state);
10705 }
10706 
10707 
10708 /*************************************************************************
10709 Optimal partition, internal subroutine. Fast version.
10710 
10711 Accepts:
10712  A array[0..N-1] array of attributes array[0..N-1]
10713  C array[0..N-1] array of class labels
10714  TiesBuf array[0..N] temporaries (ties)
10715  CntBuf array[0..2*NC-1] temporaries (counts)
10716  Alpha centering factor (0<=alpha<=1, recommended value - 0.05)
10717  BufR array[0..N-1] temporaries
10718  BufI array[0..N-1] temporaries
10719 
10720 Output:
10721  Info error code (">0"=OK, "<0"=bad)
10722  RMS training set RMS error
10723  CVRMS leave-one-out RMS error
10724 
10725 Note:
10726  content of all arrays is changed by subroutine;
10727  it doesn't allocate temporaries.
10728 
10729  -- ALGLIB --
10730  Copyright 11.12.2008 by Bochkanov Sergey
10731 *************************************************************************/
10733  /* Integer */ ae_vector* c,
10734  /* Integer */ ae_vector* tiesbuf,
10735  /* Integer */ ae_vector* cntbuf,
10736  /* Real */ ae_vector* bufr,
10737  /* Integer */ ae_vector* bufi,
10738  ae_int_t n,
10739  ae_int_t nc,
10740  double alpha,
10741  ae_int_t* info,
10742  double* threshold,
10743  double* rms,
10744  double* cvrms,
10745  ae_state *_state)
10746 {
10747  ae_int_t i;
10748  ae_int_t k;
10749  ae_int_t cl;
10750  ae_int_t tiecount;
10751  double cbest;
10752  double cc;
10753  ae_int_t koptimal;
10754  ae_int_t sl;
10755  ae_int_t sr;
10756  double v;
10757  double w;
10758  double x;
10759 
10760  *info = 0;
10761  *threshold = 0;
10762  *rms = 0;
10763  *cvrms = 0;
10764 
10765 
10766  /*
10767  * Test for errors in inputs
10768  */
10769  if( n<=0||nc<2 )
10770  {
10771  *info = -1;
10772  return;
10773  }
10774  for(i=0; i<=n-1; i++)
10775  {
10776  if( c->ptr.p_int[i]<0||c->ptr.p_int[i]>=nc )
10777  {
10778  *info = -2;
10779  return;
10780  }
10781  }
10782  *info = 1;
10783 
10784  /*
10785  * Tie
10786  */
10787  dstiefasti(a, c, n, tiesbuf, &tiecount, bufr, bufi, _state);
10788 
10789  /*
10790  * Special case: number of ties is 1.
10791  */
10792  if( tiecount==1 )
10793  {
10794  *info = -3;
10795  return;
10796  }
10797 
10798  /*
10799  * General case, number of ties > 1
10800  */
10801  for(i=0; i<=2*nc-1; i++)
10802  {
10803  cntbuf->ptr.p_int[i] = 0;
10804  }
10805  for(i=0; i<=n-1; i++)
10806  {
10807  cntbuf->ptr.p_int[nc+c->ptr.p_int[i]] = cntbuf->ptr.p_int[nc+c->ptr.p_int[i]]+1;
10808  }
10809  koptimal = -1;
10810  *threshold = a->ptr.p_double[n-1];
10811  cbest = ae_maxrealnumber;
10812  sl = 0;
10813  sr = n;
10814  for(k=0; k<=tiecount-2; k++)
10815  {
10816 
10817  /*
10818  * first, move Kth tie from right to left
10819  */
10820  for(i=tiesbuf->ptr.p_int[k]; i<=tiesbuf->ptr.p_int[k+1]-1; i++)
10821  {
10822  cl = c->ptr.p_int[i];
10823  cntbuf->ptr.p_int[cl] = cntbuf->ptr.p_int[cl]+1;
10824  cntbuf->ptr.p_int[nc+cl] = cntbuf->ptr.p_int[nc+cl]-1;
10825  }
10826  sl = sl+(tiesbuf->ptr.p_int[k+1]-tiesbuf->ptr.p_int[k]);
10827  sr = sr-(tiesbuf->ptr.p_int[k+1]-tiesbuf->ptr.p_int[k]);
10828 
10829  /*
10830  * Calculate RMS error
10831  */
10832  v = 0;
10833  for(i=0; i<=nc-1; i++)
10834  {
10835  w = cntbuf->ptr.p_int[i];
10836  v = v+w*ae_sqr(w/sl-1, _state);
10837  v = v+(sl-w)*ae_sqr(w/sl, _state);
10838  w = cntbuf->ptr.p_int[nc+i];
10839  v = v+w*ae_sqr(w/sr-1, _state);
10840  v = v+(sr-w)*ae_sqr(w/sr, _state);
10841  }
10842  v = ae_sqrt(v/(nc*n), _state);
10843 
10844  /*
10845  * Compare with best
10846  */
10847  x = (double)(2*sl)/(double)(sl+sr)-1;
10848  cc = v*(1-alpha+alpha*ae_sqr(x, _state));
10849  if( ae_fp_less(cc,cbest) )
10850  {
10851 
10852  /*
10853  * store split
10854  */
10855  *rms = v;
10856  koptimal = k;
10857  cbest = cc;
10858 
10859  /*
10860  * calculate CVRMS error
10861  */
10862  *cvrms = 0;
10863  for(i=0; i<=nc-1; i++)
10864  {
10865  if( sl>1 )
10866  {
10867  w = cntbuf->ptr.p_int[i];
10868  *cvrms = *cvrms+w*ae_sqr((w-1)/(sl-1)-1, _state);
10869  *cvrms = *cvrms+(sl-w)*ae_sqr(w/(sl-1), _state);
10870  }
10871  else
10872  {
10873  w = cntbuf->ptr.p_int[i];
10874  *cvrms = *cvrms+w*ae_sqr((double)1/(double)nc-1, _state);
10875  *cvrms = *cvrms+(sl-w)*ae_sqr((double)1/(double)nc, _state);
10876  }
10877  if( sr>1 )
10878  {
10879  w = cntbuf->ptr.p_int[nc+i];
10880  *cvrms = *cvrms+w*ae_sqr((w-1)/(sr-1)-1, _state);
10881  *cvrms = *cvrms+(sr-w)*ae_sqr(w/(sr-1), _state);
10882  }
10883  else
10884  {
10885  w = cntbuf->ptr.p_int[nc+i];
10886  *cvrms = *cvrms+w*ae_sqr((double)1/(double)nc-1, _state);
10887  *cvrms = *cvrms+(sr-w)*ae_sqr((double)1/(double)nc, _state);
10888  }
10889  }
10890  *cvrms = ae_sqrt(*cvrms/(nc*n), _state);
10891  }
10892  }
10893 
10894  /*
10895  * Calculate threshold.
10896  * Code is a bit complicated because there can be such
10897  * numbers that 0.5(A+B) equals to A or B (if A-B=epsilon)
10898  */
10899  *threshold = 0.5*(a->ptr.p_double[tiesbuf->ptr.p_int[koptimal]]+a->ptr.p_double[tiesbuf->ptr.p_int[koptimal+1]]);
10900  if( ae_fp_less_eq(*threshold,a->ptr.p_double[tiesbuf->ptr.p_int[koptimal]]) )
10901  {
10902  *threshold = a->ptr.p_double[tiesbuf->ptr.p_int[koptimal+1]];
10903  }
10904 }
10905 
10906 
10907 /*************************************************************************
10908 Automatic non-optimal discretization, internal subroutine.
10909 
10910  -- ALGLIB --
10911  Copyright 22.05.2008 by Bochkanov Sergey
10912 *************************************************************************/
10913 void dssplitk(/* Real */ ae_vector* a,
10914  /* Integer */ ae_vector* c,
10915  ae_int_t n,
10916  ae_int_t nc,
10917  ae_int_t kmax,
10918  ae_int_t* info,
10919  /* Real */ ae_vector* thresholds,
10920  ae_int_t* ni,
10921  double* cve,
10922  ae_state *_state)
10923 {
10924  ae_frame _frame_block;
10925  ae_vector _a;
10926  ae_vector _c;
10927  ae_int_t i;
10928  ae_int_t j;
10929  ae_int_t j1;
10930  ae_int_t k;
10931  ae_vector ties;
10932  ae_int_t tiecount;
10933  ae_vector p1;
10934  ae_vector p2;
10935  ae_vector cnt;
10936  double v2;
10937  ae_int_t bestk;
10938  double bestcve;
10939  ae_vector bestsizes;
10940  double curcve;
10941  ae_vector cursizes;
10942 
10943  ae_frame_make(_state, &_frame_block);
10944  ae_vector_init_copy(&_a, a, _state, ae_true);
10945  a = &_a;
10946  ae_vector_init_copy(&_c, c, _state, ae_true);
10947  c = &_c;
10948  *info = 0;
10949  ae_vector_clear(thresholds);
10950  *ni = 0;
10951  *cve = 0;
10952  ae_vector_init(&ties, 0, DT_INT, _state, ae_true);
10953  ae_vector_init(&p1, 0, DT_INT, _state, ae_true);
10954  ae_vector_init(&p2, 0, DT_INT, _state, ae_true);
10955  ae_vector_init(&cnt, 0, DT_INT, _state, ae_true);
10956  ae_vector_init(&bestsizes, 0, DT_INT, _state, ae_true);
10957  ae_vector_init(&cursizes, 0, DT_INT, _state, ae_true);
10958 
10959 
10960  /*
10961  * Test for errors in inputs
10962  */
10963  if( (n<=0||nc<2)||kmax<2 )
10964  {
10965  *info = -1;
10966  ae_frame_leave(_state);
10967  return;
10968  }
10969  for(i=0; i<=n-1; i++)
10970  {
10971  if( c->ptr.p_int[i]<0||c->ptr.p_int[i]>=nc )
10972  {
10973  *info = -2;
10974  ae_frame_leave(_state);
10975  return;
10976  }
10977  }
10978  *info = 1;
10979 
10980  /*
10981  * Tie
10982  */
10983  dstie(a, n, &ties, &tiecount, &p1, &p2, _state);
10984  for(i=0; i<=n-1; i++)
10985  {
10986  if( p2.ptr.p_int[i]!=i )
10987  {
10988  k = c->ptr.p_int[i];
10989  c->ptr.p_int[i] = c->ptr.p_int[p2.ptr.p_int[i]];
10990  c->ptr.p_int[p2.ptr.p_int[i]] = k;
10991  }
10992  }
10993 
10994  /*
10995  * Special cases
10996  */
10997  if( tiecount==1 )
10998  {
10999  *info = -3;
11000  ae_frame_leave(_state);
11001  return;
11002  }
11003 
11004  /*
11005  * General case:
11006  * 0. allocate arrays
11007  */
11008  kmax = ae_minint(kmax, tiecount, _state);
11009  ae_vector_set_length(&bestsizes, kmax-1+1, _state);
11010  ae_vector_set_length(&cursizes, kmax-1+1, _state);
11011  ae_vector_set_length(&cnt, nc-1+1, _state);
11012 
11013  /*
11014  * General case:
11015  * 1. prepare "weak" solution (two subintervals, divided at median)
11016  */
11017  v2 = ae_maxrealnumber;
11018  j = -1;
11019  for(i=1; i<=tiecount-1; i++)
11020  {
11021  if( ae_fp_less(ae_fabs(ties.ptr.p_int[i]-0.5*(n-1), _state),v2) )
11022  {
11023  v2 = ae_fabs(ties.ptr.p_int[i]-0.5*n, _state);
11024  j = i;
11025  }
11026  }
11027  ae_assert(j>0, "DSSplitK: internal error #1!", _state);
11028  bestk = 2;
11029  bestsizes.ptr.p_int[0] = ties.ptr.p_int[j];
11030  bestsizes.ptr.p_int[1] = n-j;
11031  bestcve = 0;
11032  for(i=0; i<=nc-1; i++)
11033  {
11034  cnt.ptr.p_int[i] = 0;
11035  }
11036  for(i=0; i<=j-1; i++)
11037  {
11038  bdss_tieaddc(c, &ties, i, nc, &cnt, _state);
11039  }
11040  bestcve = bestcve+bdss_getcv(&cnt, nc, _state);
11041  for(i=0; i<=nc-1; i++)
11042  {
11043  cnt.ptr.p_int[i] = 0;
11044  }
11045  for(i=j; i<=tiecount-1; i++)
11046  {
11047  bdss_tieaddc(c, &ties, i, nc, &cnt, _state);
11048  }
11049  bestcve = bestcve+bdss_getcv(&cnt, nc, _state);
11050 
11051  /*
11052  * General case:
11053  * 2. Use greedy algorithm to find sub-optimal split in O(KMax*N) time
11054  */
11055  for(k=2; k<=kmax; k++)
11056  {
11057 
11058  /*
11059  * Prepare greedy K-interval split
11060  */
11061  for(i=0; i<=k-1; i++)
11062  {
11063  cursizes.ptr.p_int[i] = 0;
11064  }
11065  i = 0;
11066  j = 0;
11067  while(j<=tiecount-1&&i<=k-1)
11068  {
11069 
11070  /*
11071  * Rule: I-th bin is empty, fill it
11072  */
11073  if( cursizes.ptr.p_int[i]==0 )
11074  {
11075  cursizes.ptr.p_int[i] = ties.ptr.p_int[j+1]-ties.ptr.p_int[j];
11076  j = j+1;
11077  continue;
11078  }
11079 
11080  /*
11081  * Rule: (K-1-I) bins left, (K-1-I) ties left (1 tie per bin); next bin
11082  */
11083  if( tiecount-j==k-1-i )
11084  {
11085  i = i+1;
11086  continue;
11087  }
11088 
11089  /*
11090  * Rule: last bin, always place in current
11091  */
11092  if( i==k-1 )
11093  {
11094  cursizes.ptr.p_int[i] = cursizes.ptr.p_int[i]+ties.ptr.p_int[j+1]-ties.ptr.p_int[j];
11095  j = j+1;
11096  continue;
11097  }
11098 
11099  /*
11100  * Place J-th tie in I-th bin, or leave for I+1-th bin.
11101  */
11102  if( ae_fp_less(ae_fabs(cursizes.ptr.p_int[i]+ties.ptr.p_int[j+1]-ties.ptr.p_int[j]-(double)n/(double)k, _state),ae_fabs(cursizes.ptr.p_int[i]-(double)n/(double)k, _state)) )
11103  {
11104  cursizes.ptr.p_int[i] = cursizes.ptr.p_int[i]+ties.ptr.p_int[j+1]-ties.ptr.p_int[j];
11105  j = j+1;
11106  }
11107  else
11108  {
11109  i = i+1;
11110  }
11111  }
11112  ae_assert(cursizes.ptr.p_int[k-1]!=0&&j==tiecount, "DSSplitK: internal error #1", _state);
11113 
11114  /*
11115  * Calculate CVE
11116  */
11117  curcve = 0;
11118  j = 0;
11119  for(i=0; i<=k-1; i++)
11120  {
11121  for(j1=0; j1<=nc-1; j1++)
11122  {
11123  cnt.ptr.p_int[j1] = 0;
11124  }
11125  for(j1=j; j1<=j+cursizes.ptr.p_int[i]-1; j1++)
11126  {
11127  cnt.ptr.p_int[c->ptr.p_int[j1]] = cnt.ptr.p_int[c->ptr.p_int[j1]]+1;
11128  }
11129  curcve = curcve+bdss_getcv(&cnt, nc, _state);
11130  j = j+cursizes.ptr.p_int[i];
11131  }
11132 
11133  /*
11134  * Choose best variant
11135  */
11136  if( ae_fp_less(curcve,bestcve) )
11137  {
11138  for(i=0; i<=k-1; i++)
11139  {
11140  bestsizes.ptr.p_int[i] = cursizes.ptr.p_int[i];
11141  }
11142  bestcve = curcve;
11143  bestk = k;
11144  }
11145  }
11146 
11147  /*
11148  * Transform from sizes to thresholds
11149  */
11150  *cve = bestcve;
11151  *ni = bestk;
11152  ae_vector_set_length(thresholds, *ni-2+1, _state);
11153  j = bestsizes.ptr.p_int[0];
11154  for(i=1; i<=bestk-1; i++)
11155  {
11156  thresholds->ptr.p_double[i-1] = 0.5*(a->ptr.p_double[j-1]+a->ptr.p_double[j]);
11157  j = j+bestsizes.ptr.p_int[i];
11158  }
11159  ae_frame_leave(_state);
11160 }
11161 
11162 
11163 /*************************************************************************
11164 Automatic optimal discretization, internal subroutine.
11165 
11166  -- ALGLIB --
11167  Copyright 22.05.2008 by Bochkanov Sergey
11168 *************************************************************************/
11169 void dsoptimalsplitk(/* Real */ ae_vector* a,
11170  /* Integer */ ae_vector* c,
11171  ae_int_t n,
11172  ae_int_t nc,
11173  ae_int_t kmax,
11174  ae_int_t* info,
11175  /* Real */ ae_vector* thresholds,
11176  ae_int_t* ni,
11177  double* cve,
11178  ae_state *_state)
11179 {
11180  ae_frame _frame_block;
11181  ae_vector _a;
11182  ae_vector _c;
11183  ae_int_t i;
11184  ae_int_t j;
11185  ae_int_t s;
11186  ae_int_t jl;
11187  ae_int_t jr;
11188  double v2;
11189  ae_vector ties;
11190  ae_int_t tiecount;
11191  ae_vector p1;
11192  ae_vector p2;
11193  double cvtemp;
11194  ae_vector cnt;
11195  ae_vector cnt2;
11196  ae_matrix cv;
11197  ae_matrix splits;
11198  ae_int_t k;
11199  ae_int_t koptimal;
11200  double cvoptimal;
11201 
11202  ae_frame_make(_state, &_frame_block);
11203  ae_vector_init_copy(&_a, a, _state, ae_true);
11204  a = &_a;
11205  ae_vector_init_copy(&_c, c, _state, ae_true);
11206  c = &_c;
11207  *info = 0;
11208  ae_vector_clear(thresholds);
11209  *ni = 0;
11210  *cve = 0;
11211  ae_vector_init(&ties, 0, DT_INT, _state, ae_true);
11212  ae_vector_init(&p1, 0, DT_INT, _state, ae_true);
11213  ae_vector_init(&p2, 0, DT_INT, _state, ae_true);
11214  ae_vector_init(&cnt, 0, DT_INT, _state, ae_true);
11215  ae_vector_init(&cnt2, 0, DT_INT, _state, ae_true);
11216  ae_matrix_init(&cv, 0, 0, DT_REAL, _state, ae_true);
11217  ae_matrix_init(&splits, 0, 0, DT_INT, _state, ae_true);
11218 
11219 
11220  /*
11221  * Test for errors in inputs
11222  */
11223  if( (n<=0||nc<2)||kmax<2 )
11224  {
11225  *info = -1;
11226  ae_frame_leave(_state);
11227  return;
11228  }
11229  for(i=0; i<=n-1; i++)
11230  {
11231  if( c->ptr.p_int[i]<0||c->ptr.p_int[i]>=nc )
11232  {
11233  *info = -2;
11234  ae_frame_leave(_state);
11235  return;
11236  }
11237  }
11238  *info = 1;
11239 
11240  /*
11241  * Tie
11242  */
11243  dstie(a, n, &ties, &tiecount, &p1, &p2, _state);
11244  for(i=0; i<=n-1; i++)
11245  {
11246  if( p2.ptr.p_int[i]!=i )
11247  {
11248  k = c->ptr.p_int[i];
11249  c->ptr.p_int[i] = c->ptr.p_int[p2.ptr.p_int[i]];
11250  c->ptr.p_int[p2.ptr.p_int[i]] = k;
11251  }
11252  }
11253 
11254  /*
11255  * Special cases
11256  */
11257  if( tiecount==1 )
11258  {
11259  *info = -3;
11260  ae_frame_leave(_state);
11261  return;
11262  }
11263 
11264  /*
11265  * General case
11266  * Use dynamic programming to find best split in O(KMax*NC*TieCount^2) time
11267  */
11268  kmax = ae_minint(kmax, tiecount, _state);
11269  ae_matrix_set_length(&cv, kmax-1+1, tiecount-1+1, _state);
11270  ae_matrix_set_length(&splits, kmax-1+1, tiecount-1+1, _state);
11271  ae_vector_set_length(&cnt, nc-1+1, _state);
11272  ae_vector_set_length(&cnt2, nc-1+1, _state);
11273  for(j=0; j<=nc-1; j++)
11274  {
11275  cnt.ptr.p_int[j] = 0;
11276  }
11277  for(j=0; j<=tiecount-1; j++)
11278  {
11279  bdss_tieaddc(c, &ties, j, nc, &cnt, _state);
11280  splits.ptr.pp_int[0][j] = 0;
11281  cv.ptr.pp_double[0][j] = bdss_getcv(&cnt, nc, _state);
11282  }
11283  for(k=1; k<=kmax-1; k++)
11284  {
11285  for(j=0; j<=nc-1; j++)
11286  {
11287  cnt.ptr.p_int[j] = 0;
11288  }
11289 
11290  /*
11291  * Subtask size J in [K..TieCount-1]:
11292  * optimal K-splitting on ties from 0-th to J-th.
11293  */
11294  for(j=k; j<=tiecount-1; j++)
11295  {
11296 
11297  /*
11298  * Update Cnt - let it contain classes of ties from K-th to J-th
11299  */
11300  bdss_tieaddc(c, &ties, j, nc, &cnt, _state);
11301 
11302  /*
11303  * Search for optimal split point S in [K..J]
11304  */
11305  for(i=0; i<=nc-1; i++)
11306  {
11307  cnt2.ptr.p_int[i] = cnt.ptr.p_int[i];
11308  }
11309  cv.ptr.pp_double[k][j] = cv.ptr.pp_double[k-1][j-1]+bdss_getcv(&cnt2, nc, _state);
11310  splits.ptr.pp_int[k][j] = j;
11311  for(s=k+1; s<=j; s++)
11312  {
11313 
11314  /*
11315  * Update Cnt2 - let it contain classes of ties from S-th to J-th
11316  */
11317  bdss_tiesubc(c, &ties, s-1, nc, &cnt2, _state);
11318 
11319  /*
11320  * Calculate CVE
11321  */
11322  cvtemp = cv.ptr.pp_double[k-1][s-1]+bdss_getcv(&cnt2, nc, _state);
11323  if( ae_fp_less(cvtemp,cv.ptr.pp_double[k][j]) )
11324  {
11325  cv.ptr.pp_double[k][j] = cvtemp;
11326  splits.ptr.pp_int[k][j] = s;
11327  }
11328  }
11329  }
11330  }
11331 
11332  /*
11333  * Choose best partition, output result
11334  */
11335  koptimal = -1;
11336  cvoptimal = ae_maxrealnumber;
11337  for(k=0; k<=kmax-1; k++)
11338  {
11339  if( ae_fp_less(cv.ptr.pp_double[k][tiecount-1],cvoptimal) )
11340  {
11341  cvoptimal = cv.ptr.pp_double[k][tiecount-1];
11342  koptimal = k;
11343  }
11344  }
11345  ae_assert(koptimal>=0, "DSOptimalSplitK: internal error #1!", _state);
11346  if( koptimal==0 )
11347  {
11348 
11349  /*
11350  * Special case: best partition is one big interval.
11351  * Even 2-partition is not better.
11352  * This is possible when dealing with "weak" predictor variables.
11353  *
11354  * Make binary split as close to the median as possible.
11355  */
11356  v2 = ae_maxrealnumber;
11357  j = -1;
11358  for(i=1; i<=tiecount-1; i++)
11359  {
11360  if( ae_fp_less(ae_fabs(ties.ptr.p_int[i]-0.5*(n-1), _state),v2) )
11361  {
11362  v2 = ae_fabs(ties.ptr.p_int[i]-0.5*(n-1), _state);
11363  j = i;
11364  }
11365  }
11366  ae_assert(j>0, "DSOptimalSplitK: internal error #2!", _state);
11367  ae_vector_set_length(thresholds, 0+1, _state);
11368  thresholds->ptr.p_double[0] = 0.5*(a->ptr.p_double[ties.ptr.p_int[j-1]]+a->ptr.p_double[ties.ptr.p_int[j]]);
11369  *ni = 2;
11370  *cve = 0;
11371  for(i=0; i<=nc-1; i++)
11372  {
11373  cnt.ptr.p_int[i] = 0;
11374  }
11375  for(i=0; i<=j-1; i++)
11376  {
11377  bdss_tieaddc(c, &ties, i, nc, &cnt, _state);
11378  }
11379  *cve = *cve+bdss_getcv(&cnt, nc, _state);
11380  for(i=0; i<=nc-1; i++)
11381  {
11382  cnt.ptr.p_int[i] = 0;
11383  }
11384  for(i=j; i<=tiecount-1; i++)
11385  {
11386  bdss_tieaddc(c, &ties, i, nc, &cnt, _state);
11387  }
11388  *cve = *cve+bdss_getcv(&cnt, nc, _state);
11389  }
11390  else
11391  {
11392 
11393  /*
11394  * General case: 2 or more intervals
11395  *
11396  * NOTE: we initialize both JL and JR (left and right bounds),
11397  * although algorithm needs only JL.
11398  */
11399  ae_vector_set_length(thresholds, koptimal-1+1, _state);
11400  *ni = koptimal+1;
11401  *cve = cv.ptr.pp_double[koptimal][tiecount-1];
11402  jl = splits.ptr.pp_int[koptimal][tiecount-1];
11403  jr = tiecount-1;
11404  for(k=koptimal; k>=1; k--)
11405  {
11406  thresholds->ptr.p_double[k-1] = 0.5*(a->ptr.p_double[ties.ptr.p_int[jl-1]]+a->ptr.p_double[ties.ptr.p_int[jl]]);
11407  jr = jl-1;
11408  jl = splits.ptr.pp_int[k-1][jl-1];
11409  }
11410  touchint(&jr, _state);
11411  }
11412  ae_frame_leave(_state);
11413 }
11414 
11415 
11416 /*************************************************************************
11417 Internal function
11418 *************************************************************************/
11419 static double bdss_xlny(double x, double y, ae_state *_state)
11420 {
11421  double result;
11422 
11423 
11424  if( ae_fp_eq(x,0) )
11425  {
11426  result = 0;
11427  }
11428  else
11429  {
11430  result = x*ae_log(y, _state);
11431  }
11432  return result;
11433 }
11434 
11435 
11436 /*************************************************************************
11437 Internal function,
11438 returns number of samples of class I in Cnt[I]
11439 *************************************************************************/
11440 static double bdss_getcv(/* Integer */ ae_vector* cnt,
11441  ae_int_t nc,
11442  ae_state *_state)
11443 {
11444  ae_int_t i;
11445  double s;
11446  double result;
11447 
11448 
11449  s = 0;
11450  for(i=0; i<=nc-1; i++)
11451  {
11452  s = s+cnt->ptr.p_int[i];
11453  }
11454  result = 0;
11455  for(i=0; i<=nc-1; i++)
11456  {
11457  result = result-bdss_xlny(cnt->ptr.p_int[i], cnt->ptr.p_int[i]/(s+nc-1), _state);
11458  }
11459  return result;
11460 }
11461 
11462 
11463 /*************************************************************************
11464 Internal function, adds number of samples of class I in tie NTie to Cnt[I]
11465 *************************************************************************/
11466 static void bdss_tieaddc(/* Integer */ ae_vector* c,
11467  /* Integer */ ae_vector* ties,
11468  ae_int_t ntie,
11469  ae_int_t nc,
11470  /* Integer */ ae_vector* cnt,
11471  ae_state *_state)
11472 {
11473  ae_int_t i;
11474 
11475 
11476  for(i=ties->ptr.p_int[ntie]; i<=ties->ptr.p_int[ntie+1]-1; i++)
11477  {
11478  cnt->ptr.p_int[c->ptr.p_int[i]] = cnt->ptr.p_int[c->ptr.p_int[i]]+1;
11479  }
11480 }
11481 
11482 
11483 /*************************************************************************
11484 Internal function, subtracts number of samples of class I in tie NTie to Cnt[I]
11485 *************************************************************************/
11486 static void bdss_tiesubc(/* Integer */ ae_vector* c,
11487  /* Integer */ ae_vector* ties,
11488  ae_int_t ntie,
11489  ae_int_t nc,
11490  /* Integer */ ae_vector* cnt,
11491  ae_state *_state)
11492 {
11493  ae_int_t i;
11494 
11495 
11496  for(i=ties->ptr.p_int[ntie]; i<=ties->ptr.p_int[ntie+1]-1; i++)
11497  {
11498  cnt->ptr.p_int[c->ptr.p_int[i]] = cnt->ptr.p_int[c->ptr.p_int[i]]-1;
11499  }
11500 }
11501 
11502 
11503 ae_bool _cvreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
11504 {
11505  cvreport *p = (cvreport*)_p;
11506  ae_touch_ptr((void*)p);
11507  return ae_true;
11508 }
11509 
11510 
11511 ae_bool _cvreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
11512 {
11513  cvreport *dst = (cvreport*)_dst;
11514  cvreport *src = (cvreport*)_src;
11515  dst->relclserror = src->relclserror;
11516  dst->avgce = src->avgce;
11517  dst->rmserror = src->rmserror;
11518  dst->avgerror = src->avgerror;
11519  dst->avgrelerror = src->avgrelerror;
11520  return ae_true;
11521 }
11522 
11523 
11524 void _cvreport_clear(void* _p)
11525 {
11526  cvreport *p = (cvreport*)_p;
11527  ae_touch_ptr((void*)p);
11528 }
11529 
11530 
11531 void _cvreport_destroy(void* _p)
11532 {
11533  cvreport *p = (cvreport*)_p;
11534  ae_touch_ptr((void*)p);
11535 }
11536 
11537 
11538 
11539 
11540 /*************************************************************************
11541 This function initializes clusterizer object. Newly initialized object is
11542 empty, i.e. it does not contain dataset. You should use it as follows:
11543 1. creation
11544 2. dataset is added with ClusterizerSetPoints()
11545 3. additional parameters are set
11546 3. clusterization is performed with one of the clustering functions
11547 
11548  -- ALGLIB --
11549  Copyright 10.07.2012 by Bochkanov Sergey
11550 *************************************************************************/
11552 {
11553 
11555 
11556  s->npoints = 0;
11557  s->nfeatures = 0;
11558  s->disttype = 2;
11559  s->ahcalgo = 0;
11560  s->kmeansrestarts = 1;
11561  s->kmeansmaxits = 0;
11562 }
11563 
11564 
11565 /*************************************************************************
11566 This function adds dataset to the clusterizer structure.
11567 
11568 This function overrides all previous calls of ClusterizerSetPoints() or
11569 ClusterizerSetDistances().
11570 
11571 INPUT PARAMETERS:
11572  S - clusterizer state, initialized by ClusterizerCreate()
11573  XY - array[NPoints,NFeatures], dataset
11574  NPoints - number of points, >=0
11575  NFeatures- number of features, >=1
11576  DistType- distance function:
11577  * 0 Chebyshev distance (L-inf norm)
11578  * 1 city block distance (L1 norm)
11579  * 2 Euclidean distance (L2 norm)
11580  * 10 Pearson correlation:
11581  dist(a,b) = 1-corr(a,b)
11582  * 11 Absolute Pearson correlation:
11583  dist(a,b) = 1-|corr(a,b)|
11584  * 12 Uncentered Pearson correlation (cosine of the angle):
11585  dist(a,b) = a'*b/(|a|*|b|)
11586  * 13 Absolute uncentered Pearson correlation
11587  dist(a,b) = |a'*b|/(|a|*|b|)
11588  * 20 Spearman rank correlation:
11589  dist(a,b) = 1-rankcorr(a,b)
11590  * 21 Absolute Spearman rank correlation
11591  dist(a,b) = 1-|rankcorr(a,b)|
11592 
11593 NOTE 1: different distance functions have different performance penalty:
11594  * Euclidean or Pearson correlation distances are the fastest ones
11595  * Spearman correlation distance function is a bit slower
11596  * city block and Chebyshev distances are order of magnitude slower
11597 
11598  The reason behing difference in performance is that correlation-based
11599  distance functions are computed using optimized linear algebra kernels,
11600  while Chebyshev and city block distance functions are computed using
11601  simple nested loops with two branches at each iteration.
11602 
11603 NOTE 2: different clustering algorithms have different limitations:
11604  * agglomerative hierarchical clustering algorithms may be used with
11605  any kind of distance metric
11606  * k-means++ clustering algorithm may be used only with Euclidean
11607  distance function
11608  Thus, list of specific clustering algorithms you may use depends
11609  on distance function you specify when you set your dataset.
11610 
11611  -- ALGLIB --
11612  Copyright 10.07.2012 by Bochkanov Sergey
11613 *************************************************************************/
11615  /* Real */ ae_matrix* xy,
11616  ae_int_t npoints,
11617  ae_int_t nfeatures,
11618  ae_int_t disttype,
11619  ae_state *_state)
11620 {
11621  ae_int_t i;
11622 
11623 
11624  ae_assert((((((((disttype==0||disttype==1)||disttype==2)||disttype==10)||disttype==11)||disttype==12)||disttype==13)||disttype==20)||disttype==21, "ClusterizerSetPoints: incorrect DistType", _state);
11625  ae_assert(npoints>=0, "ClusterizerSetPoints: NPoints<0", _state);
11626  ae_assert(nfeatures>=1, "ClusterizerSetPoints: NFeatures<1", _state);
11627  ae_assert(xy->rows>=npoints, "ClusterizerSetPoints: Rows(XY)<NPoints", _state);
11628  ae_assert(xy->cols>=nfeatures, "ClusterizerSetPoints: Cols(XY)<NFeatures", _state);
11629  ae_assert(apservisfinitematrix(xy, npoints, nfeatures, _state), "ClusterizerSetPoints: XY contains NAN/INF", _state);
11630  s->npoints = npoints;
11631  s->nfeatures = nfeatures;
11632  s->disttype = disttype;
11633  rmatrixsetlengthatleast(&s->xy, npoints, nfeatures, _state);
11634  for(i=0; i<=npoints-1; i++)
11635  {
11636  ae_v_move(&s->xy.ptr.pp_double[i][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nfeatures-1));
11637  }
11638 }
11639 
11640 
11641 /*************************************************************************
11642 This function adds dataset given by distance matrix to the clusterizer
11643 structure. It is important that dataset is not given explicitly - only
11644 distance matrix is given.
11645 
11646 This function overrides all previous calls of ClusterizerSetPoints() or
11647 ClusterizerSetDistances().
11648 
11649 INPUT PARAMETERS:
11650  S - clusterizer state, initialized by ClusterizerCreate()
11651  D - array[NPoints,NPoints], distance matrix given by its upper
11652  or lower triangle (main diagonal is ignored because its
11653  entries are expected to be zero).
11654  NPoints - number of points
11655  IsUpper - whether upper or lower triangle of D is given.
11656 
11657 NOTE 1: different clustering algorithms have different limitations:
11658  * agglomerative hierarchical clustering algorithms may be used with
11659  any kind of distance metric, including one which is given by
11660  distance matrix
11661  * k-means++ clustering algorithm may be used only with Euclidean
11662  distance function and explicitly given points - it can not be
11663  used with dataset given by distance matrix
11664  Thus, if you call this function, you will be unable to use k-means
11665  clustering algorithm to process your problem.
11666 
11667  -- ALGLIB --
11668  Copyright 10.07.2012 by Bochkanov Sergey
11669 *************************************************************************/
11671  /* Real */ ae_matrix* d,
11672  ae_int_t npoints,
11673  ae_bool isupper,
11674  ae_state *_state)
11675 {
11676  ae_int_t i;
11677  ae_int_t j;
11678  ae_int_t j0;
11679  ae_int_t j1;
11680 
11681 
11682  ae_assert(npoints>=0, "ClusterizerSetDistances: NPoints<0", _state);
11683  ae_assert(d->rows>=npoints, "ClusterizerSetDistances: Rows(D)<NPoints", _state);
11684  ae_assert(d->cols>=npoints, "ClusterizerSetDistances: Cols(D)<NPoints", _state);
11685  s->npoints = npoints;
11686  s->nfeatures = 0;
11687  s->disttype = -1;
11688  rmatrixsetlengthatleast(&s->d, npoints, npoints, _state);
11689  for(i=0; i<=npoints-1; i++)
11690  {
11691  if( isupper )
11692  {
11693  j0 = i+1;
11694  j1 = npoints-1;
11695  }
11696  else
11697  {
11698  j0 = 0;
11699  j1 = i-1;
11700  }
11701  for(j=j0; j<=j1; j++)
11702  {
11703  ae_assert(ae_isfinite(d->ptr.pp_double[i][j], _state)&&ae_fp_greater_eq(d->ptr.pp_double[i][j],0), "ClusterizerSetDistances: D contains infinite, NAN or negative elements", _state);
11704  s->d.ptr.pp_double[i][j] = d->ptr.pp_double[i][j];
11705  s->d.ptr.pp_double[j][i] = d->ptr.pp_double[i][j];
11706  }
11707  s->d.ptr.pp_double[i][i] = 0;
11708  }
11709 }
11710 
11711 
11712 /*************************************************************************
11713 This function sets agglomerative hierarchical clustering algorithm
11714 
11715 INPUT PARAMETERS:
11716  S - clusterizer state, initialized by ClusterizerCreate()
11717  Algo - algorithm type:
11718  * 0 complete linkage (default algorithm)
11719  * 1 single linkage
11720  * 2 unweighted average linkage
11721  * 3 weighted average linkage
11722 
11723  -- ALGLIB --
11724  Copyright 10.07.2012 by Bochkanov Sergey
11725 *************************************************************************/
11727  ae_int_t algo,
11728  ae_state *_state)
11729 {
11730 
11731 
11732  ae_assert(((algo==0||algo==1)||algo==2)||algo==3, "ClusterizerSetHCAlgo: incorrect algorithm type", _state);
11733  s->ahcalgo = algo;
11734 }
11735 
11736 
11737 /*************************************************************************
11738 This function sets k-means++ properties : number of restarts and maximum
11739 number of iterations per one run.
11740 
11741 INPUT PARAMETERS:
11742  S - clusterizer state, initialized by ClusterizerCreate()
11743  Restarts- restarts count, >=1.
11744  k-means++ algorithm performs several restarts and chooses
11745  best set of centers (one with minimum squared distance).
11746  MaxIts - maximum number of k-means iterations performed during one
11747  run. >=0, zero value means that algorithm performs unlimited
11748  number of iterations.
11749 
11750  -- ALGLIB --
11751  Copyright 10.07.2012 by Bochkanov Sergey
11752 *************************************************************************/
11754  ae_int_t restarts,
11755  ae_int_t maxits,
11756  ae_state *_state)
11757 {
11758 
11759 
11760  ae_assert(restarts>=1, "ClusterizerSetKMeansLimits: Restarts<=0", _state);
11761  ae_assert(maxits>=0, "ClusterizerSetKMeansLimits: MaxIts<0", _state);
11762  s->kmeansrestarts = restarts;
11763  s->kmeansmaxits = maxits;
11764 }
11765 
11766 
11767 /*************************************************************************
11768 This function performs agglomerative hierarchical clustering
11769 
11770 FOR USERS OF SMP EDITION:
11771 
11772  ! This function can utilize multicore capabilities of your system. In
11773  ! order to do this you have to call version with "smp_" prefix, which
11774  ! indicates that multicore code will be used.
11775  !
11776  ! This note is given for users of SMP edition; if you use GPL edition,
11777  ! or commercial edition of ALGLIB without SMP support, you still will
11778  ! be able to call smp-version of this function, but all computations
11779  ! will be done serially.
11780  !
11781  ! We recommend you to carefully read ALGLIB Reference Manual, section
11782  ! called 'SMP support', before using parallel version of this function.
11783  !
11784  ! You should remember that starting/stopping worker thread always have
11785  ! non-zero cost. Multicore version is pretty efficient on large
11786  ! problems which need more than 1.000.000 operations to be solved,
11787  ! gives moderate speed-up in mid-range (from 100.000 to 1.000.000 CPU
11788  ! cycles), but gives no speed-up for small problems (less than 100.000
11789  ! operations).
11790 
11791 INPUT PARAMETERS:
11792  S - clusterizer state, initialized by ClusterizerCreate()
11793 
11794 OUTPUT PARAMETERS:
11795  Rep - clustering results; see description of AHCReport
11796  structure for more information.
11797 
11798 NOTE 1: hierarchical clustering algorithms require large amounts of memory.
11799  In particular, this implementation needs sizeof(double)*NPoints^2
11800  bytes, which are used to store distance matrix. In case we work
11801  with user-supplied matrix, this amount is multiplied by 2 (we have
11802  to store original matrix and to work with its copy).
11803 
11804  For example, problem with 10000 points would require 800M of RAM,
11805  even when working in a 1-dimensional space.
11806 
11807  -- ALGLIB --
11808  Copyright 10.07.2012 by Bochkanov Sergey
11809 *************************************************************************/
11811  ahcreport* rep,
11812  ae_state *_state)
11813 {
11814  ae_frame _frame_block;
11815  ae_int_t npoints;
11816  ae_int_t nfeatures;
11817  ae_matrix d;
11818 
11819  ae_frame_make(_state, &_frame_block);
11820  _ahcreport_clear(rep);
11821  ae_matrix_init(&d, 0, 0, DT_REAL, _state, ae_true);
11822 
11823  npoints = s->npoints;
11824  nfeatures = s->nfeatures;
11825 
11826  /*
11827  * Fill Rep.NPoints, quick exit when NPoints<=1
11828  */
11829  rep->npoints = npoints;
11830  if( npoints==0 )
11831  {
11832  ae_vector_set_length(&rep->p, 0, _state);
11833  ae_matrix_set_length(&rep->z, 0, 0, _state);
11834  ae_matrix_set_length(&rep->pz, 0, 0, _state);
11835  ae_matrix_set_length(&rep->pm, 0, 0, _state);
11836  ae_vector_set_length(&rep->mergedist, 0, _state);
11837  ae_frame_leave(_state);
11838  return;
11839  }
11840  if( npoints==1 )
11841  {
11842  ae_vector_set_length(&rep->p, 1, _state);
11843  ae_matrix_set_length(&rep->z, 0, 0, _state);
11844  ae_matrix_set_length(&rep->pz, 0, 0, _state);
11845  ae_matrix_set_length(&rep->pm, 0, 0, _state);
11846  ae_vector_set_length(&rep->mergedist, 0, _state);
11847  rep->p.ptr.p_int[0] = 0;
11848  ae_frame_leave(_state);
11849  return;
11850  }
11851 
11852  /*
11853  * More than one point
11854  */
11855  if( s->disttype==-1 )
11856  {
11857 
11858  /*
11859  * Run clusterizer with user-supplied distance matrix
11860  */
11861  clustering_clusterizerrunahcinternal(s, &s->d, rep, _state);
11862  ae_frame_leave(_state);
11863  return;
11864  }
11865  else
11866  {
11867 
11868  /*
11869  * Build distance matrix D.
11870  */
11871  clusterizergetdistances(&s->xy, npoints, nfeatures, s->disttype, &d, _state);
11872 
11873  /*
11874  * Run clusterizer
11875  */
11876  clustering_clusterizerrunahcinternal(s, &d, rep, _state);
11877  ae_frame_leave(_state);
11878  return;
11879  }
11880  ae_frame_leave(_state);
11881 }
11882 
11883 
11884 /*************************************************************************
11885 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
11886 *************************************************************************/
11888  ahcreport* rep, ae_state *_state)
11889 {
11890  clusterizerrunahc(s,rep, _state);
11891 }
11892 
11893 
11894 /*************************************************************************
11895 This function performs clustering by k-means++ algorithm.
11896 
11897 You may change algorithm properties like number of restarts or iterations
11898 limit by calling ClusterizerSetKMeansLimits() functions.
11899 
11900 INPUT PARAMETERS:
11901  S - clusterizer state, initialized by ClusterizerCreate()
11902  K - number of clusters, K>=0.
11903  K can be zero only when algorithm is called for empty
11904  dataset, in this case completion code is set to
11905  success (+1).
11906  If K=0 and dataset size is non-zero, we can not
11907  meaningfully assign points to some center (there are no
11908  centers because K=0) and return -3 as completion code
11909  (failure).
11910 
11911 OUTPUT PARAMETERS:
11912  Rep - clustering results; see description of KMeansReport
11913  structure for more information.
11914 
11915 NOTE 1: k-means clustering can be performed only for datasets with
11916  Euclidean distance function. Algorithm will return negative
11917  completion code in Rep.TerminationType in case dataset was added
11918  to clusterizer with DistType other than Euclidean (or dataset was
11919  specified by distance matrix instead of explicitly given points).
11920 
11921  -- ALGLIB --
11922  Copyright 10.07.2012 by Bochkanov Sergey
11923 *************************************************************************/
11925  ae_int_t k,
11926  kmeansreport* rep,
11927  ae_state *_state)
11928 {
11929  ae_frame _frame_block;
11930  ae_matrix dummy;
11931 
11932  ae_frame_make(_state, &_frame_block);
11933  _kmeansreport_clear(rep);
11934  ae_matrix_init(&dummy, 0, 0, DT_REAL, _state, ae_true);
11935 
11936  ae_assert(k>=0, "ClusterizerRunKMeans: K<0", _state);
11937 
11938  /*
11939  * Incorrect distance type
11940  */
11941  if( s->disttype!=2 )
11942  {
11943  rep->npoints = s->npoints;
11944  rep->terminationtype = -5;
11945  rep->k = k;
11946  ae_frame_leave(_state);
11947  return;
11948  }
11949 
11950  /*
11951  * K>NPoints or (K=0 and NPoints>0)
11952  */
11953  if( k>s->npoints||(k==0&&s->npoints>0) )
11954  {
11955  rep->npoints = s->npoints;
11956  rep->terminationtype = -3;
11957  rep->k = k;
11958  ae_frame_leave(_state);
11959  return;
11960  }
11961 
11962  /*
11963  * No points
11964  */
11965  if( s->npoints==0 )
11966  {
11967  rep->npoints = 0;
11968  rep->terminationtype = 1;
11969  rep->k = k;
11970  ae_frame_leave(_state);
11971  return;
11972  }
11973 
11974  /*
11975  * Normal case:
11976  * 1<=K<=NPoints, Euclidean distance
11977  */
11978  rep->npoints = s->npoints;
11979  rep->nfeatures = s->nfeatures;
11980  rep->k = k;
11981  rep->npoints = s->npoints;
11982  rep->nfeatures = s->nfeatures;
11983  kmeansgenerateinternal(&s->xy, s->npoints, s->nfeatures, k, s->kmeansmaxits, s->kmeansrestarts, &rep->terminationtype, &dummy, ae_false, &rep->c, ae_true, &rep->cidx, _state);
11984  ae_frame_leave(_state);
11985 }
11986 
11987 
11988 /*************************************************************************
11989 This function returns distance matrix for dataset
11990 
11991 FOR USERS OF SMP EDITION:
11992 
11993  ! This function can utilize multicore capabilities of your system. In
11994  ! order to do this you have to call version with "smp_" prefix, which
11995  ! indicates that multicore code will be used.
11996  !
11997  ! This note is given for users of SMP edition; if you use GPL edition,
11998  ! or commercial edition of ALGLIB without SMP support, you still will
11999  ! be able to call smp-version of this function, but all computations
12000  ! will be done serially.
12001  !
12002  ! We recommend you to carefully read ALGLIB Reference Manual, section
12003  ! called 'SMP support', before using parallel version of this function.
12004  !
12005  ! You should remember that starting/stopping worker thread always have
12006  ! non-zero cost. Multicore version is pretty efficient on large
12007  ! problems which need more than 1.000.000 operations to be solved,
12008  ! gives moderate speed-up in mid-range (from 100.000 to 1.000.000 CPU
12009  ! cycles), but gives no speed-up for small problems (less than 100.000
12010  ! operations).
12011 
12012 INPUT PARAMETERS:
12013  XY - array[NPoints,NFeatures], dataset
12014  NPoints - number of points, >=0
12015  NFeatures- number of features, >=1
12016  DistType- distance function:
12017  * 0 Chebyshev distance (L-inf norm)
12018  * 1 city block distance (L1 norm)
12019  * 2 Euclidean distance (L2 norm)
12020  * 10 Pearson correlation:
12021  dist(a,b) = 1-corr(a,b)
12022  * 11 Absolute Pearson correlation:
12023  dist(a,b) = 1-|corr(a,b)|
12024  * 12 Uncentered Pearson correlation (cosine of the angle):
12025  dist(a,b) = a'*b/(|a|*|b|)
12026  * 13 Absolute uncentered Pearson correlation
12027  dist(a,b) = |a'*b|/(|a|*|b|)
12028  * 20 Spearman rank correlation:
12029  dist(a,b) = 1-rankcorr(a,b)
12030  * 21 Absolute Spearman rank correlation
12031  dist(a,b) = 1-|rankcorr(a,b)|
12032 
12033 OUTPUT PARAMETERS:
12034  D - array[NPoints,NPoints], distance matrix
12035  (full matrix is returned, with lower and upper triangles)
12036 
12037 NOTES: different distance functions have different performance penalty:
12038  * Euclidean or Pearson correlation distances are the fastest ones
12039  * Spearman correlation distance function is a bit slower
12040  * city block and Chebyshev distances are order of magnitude slower
12041 
12042  The reason behing difference in performance is that correlation-based
12043  distance functions are computed using optimized linear algebra kernels,
12044  while Chebyshev and city block distance functions are computed using
12045  simple nested loops with two branches at each iteration.
12046 
12047  -- ALGLIB --
12048  Copyright 10.07.2012 by Bochkanov Sergey
12049 *************************************************************************/
12051  ae_int_t npoints,
12052  ae_int_t nfeatures,
12053  ae_int_t disttype,
12054  /* Real */ ae_matrix* d,
12055  ae_state *_state)
12056 {
12057  ae_frame _frame_block;
12058  ae_int_t i;
12059  ae_int_t j;
12060  double v;
12061  double vv;
12062  double vr;
12063  ae_matrix tmpxy;
12064  ae_vector tmpx;
12065  ae_vector tmpy;
12066  ae_vector diagbuf;
12067  apbuffers buf;
12068 
12069  ae_frame_make(_state, &_frame_block);
12070  ae_matrix_clear(d);
12071  ae_matrix_init(&tmpxy, 0, 0, DT_REAL, _state, ae_true);
12072  ae_vector_init(&tmpx, 0, DT_REAL, _state, ae_true);
12073  ae_vector_init(&tmpy, 0, DT_REAL, _state, ae_true);
12074  ae_vector_init(&diagbuf, 0, DT_REAL, _state, ae_true);
12075  _apbuffers_init(&buf, _state, ae_true);
12076 
12077  ae_assert(nfeatures>=1, "ClusterizerGetDistances: NFeatures<1", _state);
12078  ae_assert(npoints>=0, "ClusterizerGetDistances: NPoints<1", _state);
12079  ae_assert((((((((disttype==0||disttype==1)||disttype==2)||disttype==10)||disttype==11)||disttype==12)||disttype==13)||disttype==20)||disttype==21, "ClusterizerGetDistances: incorrect DistType", _state);
12080  ae_assert(xy->rows>=npoints, "ClusterizerGetDistances: Rows(XY)<NPoints", _state);
12081  ae_assert(xy->cols>=nfeatures, "ClusterizerGetDistances: Cols(XY)<NFeatures", _state);
12082  ae_assert(apservisfinitematrix(xy, npoints, nfeatures, _state), "ClusterizerGetDistances: XY contains NAN/INF", _state);
12083 
12084  /*
12085  * Quick exit
12086  */
12087  if( npoints==0 )
12088  {
12089  ae_frame_leave(_state);
12090  return;
12091  }
12092  if( npoints==1 )
12093  {
12094  ae_matrix_set_length(d, 1, 1, _state);
12095  d->ptr.pp_double[0][0] = 0;
12096  ae_frame_leave(_state);
12097  return;
12098  }
12099 
12100  /*
12101  * Build distance matrix D.
12102  */
12103  if( disttype==0||disttype==1 )
12104  {
12105 
12106  /*
12107  * Chebyshev or city-block distances:
12108  * * recursively calculate upper triangle (with main diagonal)
12109  * * copy it to the bottom part of the matrix
12110  */
12111  ae_matrix_set_length(d, npoints, npoints, _state);
12112  clustering_evaluatedistancematrixrec(xy, nfeatures, disttype, d, 0, npoints, 0, npoints, _state);
12113  rmatrixenforcesymmetricity(d, npoints, ae_true, _state);
12114  ae_frame_leave(_state);
12115  return;
12116  }
12117  if( disttype==2 )
12118  {
12119 
12120  /*
12121  * Euclidean distance
12122  *
12123  * NOTE: parallelization is done within RMatrixSYRK
12124  */
12125  ae_matrix_set_length(d, npoints, npoints, _state);
12126  ae_matrix_set_length(&tmpxy, npoints, nfeatures, _state);
12127  ae_vector_set_length(&tmpx, nfeatures, _state);
12128  ae_vector_set_length(&diagbuf, npoints, _state);
12129  for(j=0; j<=nfeatures-1; j++)
12130  {
12131  tmpx.ptr.p_double[j] = 0.0;
12132  }
12133  v = (double)1/(double)npoints;
12134  for(i=0; i<=npoints-1; i++)
12135  {
12136  ae_v_addd(&tmpx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nfeatures-1), v);
12137  }
12138  for(i=0; i<=npoints-1; i++)
12139  {
12140  ae_v_move(&tmpxy.ptr.pp_double[i][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nfeatures-1));
12141  ae_v_sub(&tmpxy.ptr.pp_double[i][0], 1, &tmpx.ptr.p_double[0], 1, ae_v_len(0,nfeatures-1));
12142  }
12143  rmatrixsyrk(npoints, nfeatures, 1.0, &tmpxy, 0, 0, 0, 0.0, d, 0, 0, ae_true, _state);
12144  for(i=0; i<=npoints-1; i++)
12145  {
12146  diagbuf.ptr.p_double[i] = d->ptr.pp_double[i][i];
12147  }
12148  for(i=0; i<=npoints-1; i++)
12149  {
12150  d->ptr.pp_double[i][i] = 0.0;
12151  for(j=i+1; j<=npoints-1; j++)
12152  {
12153  v = ae_sqrt(ae_maxreal(diagbuf.ptr.p_double[i]+diagbuf.ptr.p_double[j]-2*d->ptr.pp_double[i][j], 0.0, _state), _state);
12154  d->ptr.pp_double[i][j] = v;
12155  }
12156  }
12157  rmatrixenforcesymmetricity(d, npoints, ae_true, _state);
12158  ae_frame_leave(_state);
12159  return;
12160  }
12161  if( disttype==10||disttype==11 )
12162  {
12163 
12164  /*
12165  * Absolute/nonabsolute Pearson correlation distance
12166  *
12167  * NOTE: parallelization is done within PearsonCorrM, which calls RMatrixSYRK internally
12168  */
12169  ae_matrix_set_length(d, npoints, npoints, _state);
12170  ae_vector_set_length(&diagbuf, npoints, _state);
12171  ae_matrix_set_length(&tmpxy, npoints, nfeatures, _state);
12172  for(i=0; i<=npoints-1; i++)
12173  {
12174  v = 0.0;
12175  for(j=0; j<=nfeatures-1; j++)
12176  {
12177  v = v+xy->ptr.pp_double[i][j];
12178  }
12179  v = v/nfeatures;
12180  for(j=0; j<=nfeatures-1; j++)
12181  {
12182  tmpxy.ptr.pp_double[i][j] = xy->ptr.pp_double[i][j]-v;
12183  }
12184  }
12185  rmatrixsyrk(npoints, nfeatures, 1.0, &tmpxy, 0, 0, 0, 0.0, d, 0, 0, ae_true, _state);
12186  for(i=0; i<=npoints-1; i++)
12187  {
12188  diagbuf.ptr.p_double[i] = d->ptr.pp_double[i][i];
12189  }
12190  for(i=0; i<=npoints-1; i++)
12191  {
12192  d->ptr.pp_double[i][i] = 0.0;
12193  for(j=i+1; j<=npoints-1; j++)
12194  {
12195  v = d->ptr.pp_double[i][j]/ae_sqrt(diagbuf.ptr.p_double[i]*diagbuf.ptr.p_double[j], _state);
12196  if( disttype==10 )
12197  {
12198  v = 1-v;
12199  }
12200  else
12201  {
12202  v = 1-ae_fabs(v, _state);
12203  }
12204  v = ae_maxreal(v, 0.0, _state);
12205  d->ptr.pp_double[i][j] = v;
12206  }
12207  }
12208  rmatrixenforcesymmetricity(d, npoints, ae_true, _state);
12209  ae_frame_leave(_state);
12210  return;
12211  }
12212  if( disttype==12||disttype==13 )
12213  {
12214 
12215  /*
12216  * Absolute/nonabsolute uncentered Pearson correlation distance
12217  *
12218  * NOTE: parallelization is done within RMatrixSYRK
12219  */
12220  ae_matrix_set_length(d, npoints, npoints, _state);
12221  ae_vector_set_length(&diagbuf, npoints, _state);
12222  rmatrixsyrk(npoints, nfeatures, 1.0, xy, 0, 0, 0, 0.0, d, 0, 0, ae_true, _state);
12223  for(i=0; i<=npoints-1; i++)
12224  {
12225  diagbuf.ptr.p_double[i] = d->ptr.pp_double[i][i];
12226  }
12227  for(i=0; i<=npoints-1; i++)
12228  {
12229  d->ptr.pp_double[i][i] = 0.0;
12230  for(j=i+1; j<=npoints-1; j++)
12231  {
12232  v = d->ptr.pp_double[i][j]/ae_sqrt(diagbuf.ptr.p_double[i]*diagbuf.ptr.p_double[j], _state);
12233  if( disttype==13 )
12234  {
12235  v = ae_fabs(v, _state);
12236  }
12237  v = ae_minreal(v, 1.0, _state);
12238  d->ptr.pp_double[i][j] = 1-v;
12239  }
12240  }
12241  rmatrixenforcesymmetricity(d, npoints, ae_true, _state);
12242  ae_frame_leave(_state);
12243  return;
12244  }
12245  if( disttype==20||disttype==21 )
12246  {
12247 
12248  /*
12249  * Spearman rank correlation
12250  *
12251  * NOTE: parallelization of correlation matrix is done within
12252  * PearsonCorrM, which calls RMatrixSYRK internally
12253  */
12254  ae_matrix_set_length(d, npoints, npoints, _state);
12255  ae_vector_set_length(&diagbuf, npoints, _state);
12256  ae_matrix_set_length(&tmpxy, npoints, nfeatures, _state);
12257  rmatrixcopy(npoints, nfeatures, xy, 0, 0, &tmpxy, 0, 0, _state);
12258  rankdatacentered(&tmpxy, npoints, nfeatures, _state);
12259  rmatrixsyrk(npoints, nfeatures, 1.0, &tmpxy, 0, 0, 0, 0.0, d, 0, 0, ae_true, _state);
12260  for(i=0; i<=npoints-1; i++)
12261  {
12262  if( ae_fp_greater(d->ptr.pp_double[i][i],0) )
12263  {
12264  diagbuf.ptr.p_double[i] = 1/ae_sqrt(d->ptr.pp_double[i][i], _state);
12265  }
12266  else
12267  {
12268  diagbuf.ptr.p_double[i] = 0.0;
12269  }
12270  }
12271  for(i=0; i<=npoints-1; i++)
12272  {
12273  v = diagbuf.ptr.p_double[i];
12274  d->ptr.pp_double[i][i] = 0.0;
12275  for(j=i+1; j<=npoints-1; j++)
12276  {
12277  vv = d->ptr.pp_double[i][j]*v*diagbuf.ptr.p_double[j];
12278  if( disttype==20 )
12279  {
12280  vr = 1-vv;
12281  }
12282  else
12283  {
12284  vr = 1-ae_fabs(vv, _state);
12285  }
12286  if( ae_fp_less(vr,0) )
12287  {
12288  vr = 0.0;
12289  }
12290  d->ptr.pp_double[i][j] = vr;
12291  }
12292  }
12293  rmatrixenforcesymmetricity(d, npoints, ae_true, _state);
12294  ae_frame_leave(_state);
12295  return;
12296  }
12297  ae_assert(ae_false, "Assertion failed", _state);
12298  ae_frame_leave(_state);
12299 }
12300 
12301 
12302 /*************************************************************************
12303 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
12304 *************************************************************************/
12306  ae_int_t npoints,
12307  ae_int_t nfeatures,
12308  ae_int_t disttype,
12309  /* Real */ ae_matrix* d, ae_state *_state)
12310 {
12311  clusterizergetdistances(xy,npoints,nfeatures,disttype,d, _state);
12312 }
12313 
12314 
12315 /*************************************************************************
12316 This function takes as input clusterization report Rep, desired clusters
12317 count K, and builds top K clusters from hierarchical clusterization tree.
12318 It returns assignment of points to clusters (array of cluster indexes).
12319 
12320 INPUT PARAMETERS:
12321  Rep - report from ClusterizerRunAHC() performed on XY
12322  K - desired number of clusters, 1<=K<=NPoints.
12323  K can be zero only when NPoints=0.
12324 
12325 OUTPUT PARAMETERS:
12326  CIdx - array[NPoints], I-th element contains cluster index (from
12327  0 to K-1) for I-th point of the dataset.
12328  CZ - array[K]. This array allows to convert cluster indexes
12329  returned by this function to indexes used by Rep.Z. J-th
12330  cluster returned by this function corresponds to CZ[J]-th
12331  cluster stored in Rep.Z/PZ/PM.
12332  It is guaranteed that CZ[I]<CZ[I+1].
12333 
12334 NOTE: K clusters built by this subroutine are assumed to have no hierarchy.
12335  Although they were obtained by manipulation with top K nodes of
12336  dendrogram (i.e. hierarchical decomposition of dataset), this
12337  function does not return information about hierarchy. Each of the
12338  clusters stand on its own.
12339 
12340 NOTE: Cluster indexes returned by this function does not correspond to
12341  indexes returned in Rep.Z/PZ/PM. Either you work with hierarchical
12342  representation of the dataset (dendrogram), or you work with "flat"
12343  representation returned by this function. Each of representations
12344  has its own clusters indexing system (former uses [0, 2*NPoints-2]),
12345  while latter uses [0..K-1]), although it is possible to perform
12346  conversion from one system to another by means of CZ array, returned
12347  by this function, which allows you to convert indexes stored in CIdx
12348  to the numeration system used by Rep.Z.
12349 
12350 NOTE: this subroutine is optimized for moderate values of K. Say, for K=5
12351  it will perform many times faster than for K=100. Its worst-case
12352  performance is O(N*K), although in average case it perform better
12353  (up to O(N*log(K))).
12354 
12355  -- ALGLIB --
12356  Copyright 10.07.2012 by Bochkanov Sergey
12357 *************************************************************************/
12359  ae_int_t k,
12360  /* Integer */ ae_vector* cidx,
12361  /* Integer */ ae_vector* cz,
12362  ae_state *_state)
12363 {
12364  ae_frame _frame_block;
12365  ae_int_t i;
12366  ae_int_t mergeidx;
12367  ae_int_t i0;
12368  ae_int_t i1;
12369  ae_int_t t;
12370  ae_vector presentclusters;
12371  ae_vector clusterindexes;
12372  ae_vector clustersizes;
12373  ae_vector tmpidx;
12374  ae_int_t npoints;
12375 
12376  ae_frame_make(_state, &_frame_block);
12377  ae_vector_clear(cidx);
12378  ae_vector_clear(cz);
12379  ae_vector_init(&presentclusters, 0, DT_BOOL, _state, ae_true);
12380  ae_vector_init(&clusterindexes, 0, DT_INT, _state, ae_true);
12381  ae_vector_init(&clustersizes, 0, DT_INT, _state, ae_true);
12382  ae_vector_init(&tmpidx, 0, DT_INT, _state, ae_true);
12383 
12384  npoints = rep->npoints;
12385  ae_assert(npoints>=0, "ClusterizerGetKClusters: internal error in Rep integrity", _state);
12386  ae_assert(k>=0, "ClusterizerGetKClusters: K<=0", _state);
12387  ae_assert(k<=npoints, "ClusterizerGetKClusters: K>NPoints", _state);
12388  ae_assert(k>0||npoints==0, "ClusterizerGetKClusters: K<=0", _state);
12389  ae_assert(npoints==rep->npoints, "ClusterizerGetKClusters: NPoints<>Rep.NPoints", _state);
12390 
12391  /*
12392  * Quick exit
12393  */
12394  if( npoints==0 )
12395  {
12396  ae_frame_leave(_state);
12397  return;
12398  }
12399  if( npoints==1 )
12400  {
12401  ae_vector_set_length(cz, 1, _state);
12402  ae_vector_set_length(cidx, 1, _state);
12403  cz->ptr.p_int[0] = 0;
12404  cidx->ptr.p_int[0] = 0;
12405  ae_frame_leave(_state);
12406  return;
12407  }
12408 
12409  /*
12410  * Replay merges, from top to bottom,
12411  * keep track of clusters being present at the moment
12412  */
12413  ae_vector_set_length(&presentclusters, 2*npoints-1, _state);
12414  ae_vector_set_length(&tmpidx, npoints, _state);
12415  for(i=0; i<=2*npoints-3; i++)
12416  {
12417  presentclusters.ptr.p_bool[i] = ae_false;
12418  }
12419  presentclusters.ptr.p_bool[2*npoints-2] = ae_true;
12420  for(i=0; i<=npoints-1; i++)
12421  {
12422  tmpidx.ptr.p_int[i] = 2*npoints-2;
12423  }
12424  for(mergeidx=npoints-2; mergeidx>=npoints-k; mergeidx--)
12425  {
12426 
12427  /*
12428  * Update information about clusters being present at the moment
12429  */
12430  presentclusters.ptr.p_bool[npoints+mergeidx] = ae_false;
12431  presentclusters.ptr.p_bool[rep->z.ptr.pp_int[mergeidx][0]] = ae_true;
12432  presentclusters.ptr.p_bool[rep->z.ptr.pp_int[mergeidx][1]] = ae_true;
12433 
12434  /*
12435  * Update TmpIdx according to the current state of the dataset
12436  *
12437  * NOTE: TmpIdx contains cluster indexes from [0..2*NPoints-2];
12438  * we will convert them to [0..K-1] later.
12439  */
12440  i0 = rep->pm.ptr.pp_int[mergeidx][0];
12441  i1 = rep->pm.ptr.pp_int[mergeidx][1];
12442  t = rep->z.ptr.pp_int[mergeidx][0];
12443  for(i=i0; i<=i1; i++)
12444  {
12445  tmpidx.ptr.p_int[i] = t;
12446  }
12447  i0 = rep->pm.ptr.pp_int[mergeidx][2];
12448  i1 = rep->pm.ptr.pp_int[mergeidx][3];
12449  t = rep->z.ptr.pp_int[mergeidx][1];
12450  for(i=i0; i<=i1; i++)
12451  {
12452  tmpidx.ptr.p_int[i] = t;
12453  }
12454  }
12455 
12456  /*
12457  * Fill CZ - array which allows us to convert cluster indexes
12458  * from one system to another.
12459  */
12460  ae_vector_set_length(cz, k, _state);
12461  ae_vector_set_length(&clusterindexes, 2*npoints-1, _state);
12462  t = 0;
12463  for(i=0; i<=2*npoints-2; i++)
12464  {
12465  if( presentclusters.ptr.p_bool[i] )
12466  {
12467  cz->ptr.p_int[t] = i;
12468  clusterindexes.ptr.p_int[i] = t;
12469  t = t+1;
12470  }
12471  }
12472  ae_assert(t==k, "ClusterizerGetKClusters: internal error", _state);
12473 
12474  /*
12475  * Convert indexes stored in CIdx
12476  */
12477  ae_vector_set_length(cidx, npoints, _state);
12478  for(i=0; i<=npoints-1; i++)
12479  {
12480  cidx->ptr.p_int[i] = clusterindexes.ptr.p_int[tmpidx.ptr.p_int[rep->p.ptr.p_int[i]]];
12481  }
12482  ae_frame_leave(_state);
12483 }
12484 
12485 
12486 /*************************************************************************
12487 This function accepts AHC report Rep, desired minimum intercluster
12488 distance and returns top clusters from hierarchical clusterization tree
12489 which are separated by distance R or HIGHER.
12490 
12491 It returns assignment of points to clusters (array of cluster indexes).
12492 
12493 There is one more function with similar name - ClusterizerSeparatedByCorr,
12494 which returns clusters with intercluster correlation equal to R or LOWER
12495 (note: higher for distance, lower for correlation).
12496 
12497 INPUT PARAMETERS:
12498  Rep - report from ClusterizerRunAHC() performed on XY
12499  R - desired minimum intercluster distance, R>=0
12500 
12501 OUTPUT PARAMETERS:
12502  K - number of clusters, 1<=K<=NPoints
12503  CIdx - array[NPoints], I-th element contains cluster index (from
12504  0 to K-1) for I-th point of the dataset.
12505  CZ - array[K]. This array allows to convert cluster indexes
12506  returned by this function to indexes used by Rep.Z. J-th
12507  cluster returned by this function corresponds to CZ[J]-th
12508  cluster stored in Rep.Z/PZ/PM.
12509  It is guaranteed that CZ[I]<CZ[I+1].
12510 
12511 NOTE: K clusters built by this subroutine are assumed to have no hierarchy.
12512  Although they were obtained by manipulation with top K nodes of
12513  dendrogram (i.e. hierarchical decomposition of dataset), this
12514  function does not return information about hierarchy. Each of the
12515  clusters stand on its own.
12516 
12517 NOTE: Cluster indexes returned by this function does not correspond to
12518  indexes returned in Rep.Z/PZ/PM. Either you work with hierarchical
12519  representation of the dataset (dendrogram), or you work with "flat"
12520  representation returned by this function. Each of representations
12521  has its own clusters indexing system (former uses [0, 2*NPoints-2]),
12522  while latter uses [0..K-1]), although it is possible to perform
12523  conversion from one system to another by means of CZ array, returned
12524  by this function, which allows you to convert indexes stored in CIdx
12525  to the numeration system used by Rep.Z.
12526 
12527 NOTE: this subroutine is optimized for moderate values of K. Say, for K=5
12528  it will perform many times faster than for K=100. Its worst-case
12529  performance is O(N*K), although in average case it perform better
12530  (up to O(N*log(K))).
12531 
12532  -- ALGLIB --
12533  Copyright 10.07.2012 by Bochkanov Sergey
12534 *************************************************************************/
12535 void clusterizerseparatedbydist(ahcreport* rep,
12536  double r,
12537  ae_int_t* k,
12538  /* Integer */ ae_vector* cidx,
12539  /* Integer */ ae_vector* cz,
12540  ae_state *_state)
12541 {
12542 
12543  *k = 0;
12544  ae_vector_clear(cidx);
12545  ae_vector_clear(cz);
12546 
12547  ae_assert(ae_isfinite(r, _state)&&ae_fp_greater_eq(r,0), "ClusterizerSeparatedByDist: R is infinite or less than 0", _state);
12548  *k = 1;
12549  while(*k<rep->npoints&&ae_fp_greater_eq(rep->mergedist.ptr.p_double[rep->npoints-1-(*k)],r))
12550  {
12551  *k = *k+1;
12552  }
12553  clusterizergetkclusters(rep, *k, cidx, cz, _state);
12554 }
12555 
12556 
12557 /*************************************************************************
12558 This function accepts AHC report Rep, desired maximum intercluster
12559 correlation and returns top clusters from hierarchical clusterization tree
12560 which are separated by correlation R or LOWER.
12561 
12562 It returns assignment of points to clusters (array of cluster indexes).
12563 
12564 There is one more function with similar name - ClusterizerSeparatedByDist,
12565 which returns clusters with intercluster distance equal to R or HIGHER
12566 (note: higher for distance, lower for correlation).
12567 
12568 INPUT PARAMETERS:
12569  Rep - report from ClusterizerRunAHC() performed on XY
12570  R - desired maximum intercluster correlation, -1<=R<=+1
12571 
12572 OUTPUT PARAMETERS:
12573  K - number of clusters, 1<=K<=NPoints
12574  CIdx - array[NPoints], I-th element contains cluster index (from
12575  0 to K-1) for I-th point of the dataset.
12576  CZ - array[K]. This array allows to convert cluster indexes
12577  returned by this function to indexes used by Rep.Z. J-th
12578  cluster returned by this function corresponds to CZ[J]-th
12579  cluster stored in Rep.Z/PZ/PM.
12580  It is guaranteed that CZ[I]<CZ[I+1].
12581 
12582 NOTE: K clusters built by this subroutine are assumed to have no hierarchy.
12583  Although they were obtained by manipulation with top K nodes of
12584  dendrogram (i.e. hierarchical decomposition of dataset), this
12585  function does not return information about hierarchy. Each of the
12586  clusters stand on its own.
12587 
12588 NOTE: Cluster indexes returned by this function does not correspond to
12589  indexes returned in Rep.Z/PZ/PM. Either you work with hierarchical
12590  representation of the dataset (dendrogram), or you work with "flat"
12591  representation returned by this function. Each of representations
12592  has its own clusters indexing system (former uses [0, 2*NPoints-2]),
12593  while latter uses [0..K-1]), although it is possible to perform
12594  conversion from one system to another by means of CZ array, returned
12595  by this function, which allows you to convert indexes stored in CIdx
12596  to the numeration system used by Rep.Z.
12597 
12598 NOTE: this subroutine is optimized for moderate values of K. Say, for K=5
12599  it will perform many times faster than for K=100. Its worst-case
12600  performance is O(N*K), although in average case it perform better
12601  (up to O(N*log(K))).
12602 
12603  -- ALGLIB --
12604  Copyright 10.07.2012 by Bochkanov Sergey
12605 *************************************************************************/
12606 void clusterizerseparatedbycorr(ahcreport* rep,
12607  double r,
12608  ae_int_t* k,
12609  /* Integer */ ae_vector* cidx,
12610  /* Integer */ ae_vector* cz,
12611  ae_state *_state)
12612 {
12613 
12614  *k = 0;
12615  ae_vector_clear(cidx);
12616  ae_vector_clear(cz);
12617 
12618  ae_assert((ae_isfinite(r, _state)&&ae_fp_greater_eq(r,-1))&&ae_fp_less_eq(r,1), "ClusterizerSeparatedByCorr: R is infinite or less than 0", _state);
12619  *k = 1;
12620  while(*k<rep->npoints&&ae_fp_greater_eq(rep->mergedist.ptr.p_double[rep->npoints-1-(*k)],1-r))
12621  {
12622  *k = *k+1;
12623  }
12624  clusterizergetkclusters(rep, *k, cidx, cz, _state);
12625 }
12626 
12627 
12628 /*************************************************************************
12629 K-means++ clusterization
12630 
12631 INPUT PARAMETERS:
12632  XY - dataset, array [0..NPoints-1,0..NVars-1].
12633  NPoints - dataset size, NPoints>=K
12634  NVars - number of variables, NVars>=1
12635  K - desired number of clusters, K>=1
12636  Restarts - number of restarts, Restarts>=1
12637 
12638 OUTPUT PARAMETERS:
12639  Info - return code:
12640  * -3, if task is degenerate (number of distinct points is
12641  less than K)
12642  * -1, if incorrect NPoints/NFeatures/K/Restarts was passed
12643  * 1, if subroutine finished successfully
12644  CCol - array[0..NVars-1,0..K-1].matrix whose columns store
12645  cluster's centers
12646  NeedCCol - True in case caller requires to store result in CCol
12647  CRow - array[0..K-1,0..NVars-1], same as CCol, but centers are
12648  stored in rows
12649  NeedCRow - True in case caller requires to store result in CCol
12650  XYC - array[NPoints], which contains cluster indexes
12651 
12652  -- ALGLIB --
12653  Copyright 21.03.2009 by Bochkanov Sergey
12654 *************************************************************************/
12655 void kmeansgenerateinternal(/* Real */ ae_matrix* xy,
12656  ae_int_t npoints,
12657  ae_int_t nvars,
12658  ae_int_t k,
12659  ae_int_t maxits,
12660  ae_int_t restarts,
12661  ae_int_t* info,
12662  /* Real */ ae_matrix* ccol,
12663  ae_bool needccol,
12664  /* Real */ ae_matrix* crow,
12665  ae_bool needcrow,
12666  /* Integer */ ae_vector* xyc,
12667  ae_state *_state)
12668 {
12669  ae_frame _frame_block;
12670  ae_int_t i;
12671  ae_int_t j;
12672  ae_matrix ct;
12673  ae_matrix ctbest;
12674  ae_vector xycbest;
12675  double e;
12676  double eprev;
12677  double ebest;
12678  ae_vector x;
12679  ae_vector tmp;
12680  ae_vector d2;
12681  ae_vector p;
12682  ae_vector csizes;
12683  ae_vector cbusy;
12684  double v;
12685  ae_int_t cclosest;
12686  double dclosest;
12687  ae_vector work;
12688  ae_bool waschanges;
12689  ae_bool zerosizeclusters;
12690  ae_int_t pass;
12691  ae_int_t itcnt;
12692  hqrndstate rs;
12693 
12694  ae_frame_make(_state, &_frame_block);
12695  *info = 0;
12696  ae_matrix_clear(ccol);
12697  ae_matrix_clear(crow);
12698  ae_vector_clear(xyc);
12699  ae_matrix_init(&ct, 0, 0, DT_REAL, _state, ae_true);
12700  ae_matrix_init(&ctbest, 0, 0, DT_REAL, _state, ae_true);
12701  ae_vector_init(&xycbest, 0, DT_INT, _state, ae_true);
12702  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
12703  ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
12704  ae_vector_init(&d2, 0, DT_REAL, _state, ae_true);
12705  ae_vector_init(&p, 0, DT_REAL, _state, ae_true);
12706  ae_vector_init(&csizes, 0, DT_INT, _state, ae_true);
12707  ae_vector_init(&cbusy, 0, DT_BOOL, _state, ae_true);
12708  ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
12709  _hqrndstate_init(&rs, _state, ae_true);
12710 
12711 
12712  /*
12713  * Test parameters
12714  */
12715  if( ((npoints<k||nvars<1)||k<1)||restarts<1 )
12716  {
12717  *info = -1;
12718  ae_frame_leave(_state);
12719  return;
12720  }
12721 
12722  /*
12723  * TODO: special case K=1
12724  * TODO: special case K=NPoints
12725  */
12726  *info = 1;
12727 
12728  /*
12729  * Multiple passes of k-means++ algorithm
12730  */
12731  ae_matrix_set_length(&ct, k, nvars, _state);
12732  ae_matrix_set_length(&ctbest, k, nvars, _state);
12733  ae_vector_set_length(xyc, npoints, _state);
12734  ae_vector_set_length(&xycbest, npoints, _state);
12735  ae_vector_set_length(&d2, npoints, _state);
12736  ae_vector_set_length(&p, npoints, _state);
12737  ae_vector_set_length(&tmp, nvars, _state);
12738  ae_vector_set_length(&csizes, k, _state);
12739  ae_vector_set_length(&cbusy, k, _state);
12740  ebest = ae_maxrealnumber;
12741  hqrndrandomize(&rs, _state);
12742  for(pass=1; pass<=restarts; pass++)
12743  {
12744 
12745  /*
12746  * Select initial centers using k-means++ algorithm
12747  * 1. Choose first center at random
12748  * 2. Choose next centers using their distance from centers already chosen
12749  *
12750  * Note that for performance reasons centers are stored in ROWS of CT, not
12751  * in columns. We'll transpose CT in the end and store it in the C.
12752  */
12753  i = hqrnduniformi(&rs, npoints, _state);
12754  ae_v_move(&ct.ptr.pp_double[0][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
12755  cbusy.ptr.p_bool[0] = ae_true;
12756  for(i=1; i<=k-1; i++)
12757  {
12758  cbusy.ptr.p_bool[i] = ae_false;
12759  }
12760  if( !clustering_selectcenterpp(xy, npoints, nvars, &ct, &cbusy, k, &d2, &p, &tmp, _state) )
12761  {
12762  *info = -3;
12763  ae_frame_leave(_state);
12764  return;
12765  }
12766 
12767  /*
12768  * Update centers:
12769  * 2. update center positions
12770  */
12771  for(i=0; i<=npoints-1; i++)
12772  {
12773  xyc->ptr.p_int[i] = -1;
12774  }
12775  eprev = ae_maxrealnumber;
12776  itcnt = 0;
12777  e = 0;
12778  while(maxits==0||itcnt<maxits)
12779  {
12780 
12781  /*
12782  * Update iteration counter
12783  */
12784  itcnt = itcnt+1;
12785 
12786  /*
12787  * fill XYC with center numbers
12788  */
12789  waschanges = ae_false;
12790  for(i=0; i<=npoints-1; i++)
12791  {
12792  cclosest = -1;
12793  dclosest = ae_maxrealnumber;
12794  for(j=0; j<=k-1; j++)
12795  {
12796  ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
12797  ae_v_sub(&tmp.ptr.p_double[0], 1, &ct.ptr.pp_double[j][0], 1, ae_v_len(0,nvars-1));
12798  v = ae_v_dotproduct(&tmp.ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,nvars-1));
12799  if( ae_fp_less(v,dclosest) )
12800  {
12801  cclosest = j;
12802  dclosest = v;
12803  }
12804  }
12805  if( xyc->ptr.p_int[i]!=cclosest )
12806  {
12807  waschanges = ae_true;
12808  }
12809  xyc->ptr.p_int[i] = cclosest;
12810  }
12811 
12812  /*
12813  * Update centers
12814  */
12815  for(j=0; j<=k-1; j++)
12816  {
12817  csizes.ptr.p_int[j] = 0;
12818  }
12819  for(i=0; i<=k-1; i++)
12820  {
12821  for(j=0; j<=nvars-1; j++)
12822  {
12823  ct.ptr.pp_double[i][j] = 0;
12824  }
12825  }
12826  for(i=0; i<=npoints-1; i++)
12827  {
12828  csizes.ptr.p_int[xyc->ptr.p_int[i]] = csizes.ptr.p_int[xyc->ptr.p_int[i]]+1;
12829  ae_v_add(&ct.ptr.pp_double[xyc->ptr.p_int[i]][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
12830  }
12831  zerosizeclusters = ae_false;
12832  for(j=0; j<=k-1; j++)
12833  {
12834  if( csizes.ptr.p_int[j]!=0 )
12835  {
12836  v = (double)1/(double)csizes.ptr.p_int[j];
12837  ae_v_muld(&ct.ptr.pp_double[j][0], 1, ae_v_len(0,nvars-1), v);
12838  }
12839  cbusy.ptr.p_bool[j] = csizes.ptr.p_int[j]!=0;
12840  zerosizeclusters = zerosizeclusters||csizes.ptr.p_int[j]==0;
12841  }
12842  if( zerosizeclusters )
12843  {
12844 
12845  /*
12846  * Some clusters have zero size - rare, but possible.
12847  * We'll choose new centers for such clusters using k-means++ rule
12848  * and restart algorithm
12849  */
12850  if( !clustering_selectcenterpp(xy, npoints, nvars, &ct, &cbusy, k, &d2, &p, &tmp, _state) )
12851  {
12852  *info = -3;
12853  ae_frame_leave(_state);
12854  return;
12855  }
12856  continue;
12857  }
12858 
12859  /*
12860  * Stop if one of two conditions is met:
12861  * 1. nothing has changed during iteration
12862  * 2. energy function increased
12863  */
12864  e = 0;
12865  for(i=0; i<=npoints-1; i++)
12866  {
12867  ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
12868  ae_v_sub(&tmp.ptr.p_double[0], 1, &ct.ptr.pp_double[xyc->ptr.p_int[i]][0], 1, ae_v_len(0,nvars-1));
12869  v = ae_v_dotproduct(&tmp.ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,nvars-1));
12870  e = e+v;
12871  }
12872  if( !waschanges||ae_fp_greater_eq(e,eprev) )
12873  {
12874  break;
12875  }
12876 
12877  /*
12878  * Update EPrev
12879  */
12880  eprev = e;
12881  }
12882 
12883  /*
12884  * 3. Calculate E, compare with best centers found so far
12885  */
12886  if( ae_fp_less(e,ebest) )
12887  {
12888 
12889  /*
12890  * store partition.
12891  */
12892  ebest = e;
12893  copymatrix(&ct, 0, k-1, 0, nvars-1, &ctbest, 0, k-1, 0, nvars-1, _state);
12894  for(i=0; i<=npoints-1; i++)
12895  {
12896  xycbest.ptr.p_int[i] = xyc->ptr.p_int[i];
12897  }
12898  }
12899  }
12900 
12901  /*
12902  * Copy and transpose
12903  */
12904  if( needccol )
12905  {
12906  ae_matrix_set_length(ccol, nvars, k, _state);
12907  copyandtranspose(&ctbest, 0, k-1, 0, nvars-1, ccol, 0, nvars-1, 0, k-1, _state);
12908  }
12909  if( needcrow )
12910  {
12911  ae_matrix_set_length(crow, k, nvars, _state);
12912  rmatrixcopy(k, nvars, &ctbest, 0, 0, crow, 0, 0, _state);
12913  }
12914  for(i=0; i<=npoints-1; i++)
12915  {
12916  xyc->ptr.p_int[i] = xycbest.ptr.p_int[i];
12917  }
12918  ae_frame_leave(_state);
12919 }
12920 
12921 
12922 /*************************************************************************
12923 Select center for a new cluster using k-means++ rule
12924 *************************************************************************/
12925 static ae_bool clustering_selectcenterpp(/* Real */ ae_matrix* xy,
12926  ae_int_t npoints,
12927  ae_int_t nvars,
12928  /* Real */ ae_matrix* centers,
12929  /* Boolean */ ae_vector* busycenters,
12930  ae_int_t ccnt,
12931  /* Real */ ae_vector* d2,
12932  /* Real */ ae_vector* p,
12933  /* Real */ ae_vector* tmp,
12934  ae_state *_state)
12935 {
12936  ae_int_t i;
12937  ae_int_t j;
12938  ae_int_t cc;
12939  double v;
12940  double s;
12941  ae_bool result;
12942 
12943 
12944  result = ae_true;
12945  for(cc=0; cc<=ccnt-1; cc++)
12946  {
12947  if( !busycenters->ptr.p_bool[cc] )
12948  {
12949 
12950  /*
12951  * fill D2
12952  */
12953  for(i=0; i<=npoints-1; i++)
12954  {
12955  d2->ptr.p_double[i] = ae_maxrealnumber;
12956  for(j=0; j<=ccnt-1; j++)
12957  {
12958  if( busycenters->ptr.p_bool[j] )
12959  {
12960  ae_v_move(&tmp->ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
12961  ae_v_sub(&tmp->ptr.p_double[0], 1, &centers->ptr.pp_double[j][0], 1, ae_v_len(0,nvars-1));
12962  v = ae_v_dotproduct(&tmp->ptr.p_double[0], 1, &tmp->ptr.p_double[0], 1, ae_v_len(0,nvars-1));
12963  if( ae_fp_less(v,d2->ptr.p_double[i]) )
12964  {
12965  d2->ptr.p_double[i] = v;
12966  }
12967  }
12968  }
12969  }
12970 
12971  /*
12972  * calculate P (non-cumulative)
12973  */
12974  s = 0;
12975  for(i=0; i<=npoints-1; i++)
12976  {
12977  s = s+d2->ptr.p_double[i];
12978  }
12979  if( ae_fp_eq(s,0) )
12980  {
12981  result = ae_false;
12982  return result;
12983  }
12984  s = 1/s;
12985  ae_v_moved(&p->ptr.p_double[0], 1, &d2->ptr.p_double[0], 1, ae_v_len(0,npoints-1), s);
12986 
12987  /*
12988  * choose one of points with probability P
12989  * random number within (0,1) is generated and
12990  * inverse empirical CDF is used to randomly choose a point.
12991  */
12992  s = 0;
12993  v = ae_randomreal(_state);
12994  for(i=0; i<=npoints-1; i++)
12995  {
12996  s = s+p->ptr.p_double[i];
12997  if( ae_fp_less_eq(v,s)||i==npoints-1 )
12998  {
12999  ae_v_move(&centers->ptr.pp_double[cc][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
13000  busycenters->ptr.p_bool[cc] = ae_true;
13001  break;
13002  }
13003  }
13004  }
13005  }
13006  return result;
13007 }
13008 
13009 
13010 /*************************************************************************
13011 This function performs agglomerative hierarchical clustering using
13012 precomputed distance matrix. Internal function, should not be called
13013 directly.
13014 
13015 INPUT PARAMETERS:
13016  S - clusterizer state, initialized by ClusterizerCreate()
13017  D - distance matrix, array[S.NFeatures,S.NFeatures]
13018  Contents of the matrix is destroyed during
13019  algorithm operation.
13020 
13021 OUTPUT PARAMETERS:
13022  Rep - clustering results; see description of AHCReport
13023  structure for more information.
13024 
13025  -- ALGLIB --
13026  Copyright 10.07.2012 by Bochkanov Sergey
13027 *************************************************************************/
13028 static void clustering_clusterizerrunahcinternal(clusterizerstate* s,
13029  /* Real */ ae_matrix* d,
13030  ahcreport* rep,
13031  ae_state *_state)
13032 {
13033  ae_frame _frame_block;
13034  ae_int_t i;
13035  ae_int_t j;
13036  ae_int_t k;
13037  double v;
13038  ae_int_t mergeidx;
13039  ae_int_t c0;
13040  ae_int_t c1;
13041  ae_int_t s0;
13042  ae_int_t s1;
13043  ae_int_t ar;
13044  ae_int_t br;
13045  ae_int_t npoints;
13046  ae_vector cidx;
13047  ae_vector csizes;
13048  ae_vector nnidx;
13049  ae_matrix cinfo;
13050 
13051  ae_frame_make(_state, &_frame_block);
13052  ae_vector_init(&cidx, 0, DT_INT, _state, ae_true);
13053  ae_vector_init(&csizes, 0, DT_INT, _state, ae_true);
13054  ae_vector_init(&nnidx, 0, DT_INT, _state, ae_true);
13055  ae_matrix_init(&cinfo, 0, 0, DT_INT, _state, ae_true);
13056 
13057  npoints = s->npoints;
13058 
13059  /*
13060  * Fill Rep.NPoints, quick exit when NPoints<=1
13061  */
13062  rep->npoints = npoints;
13063  if( npoints==0 )
13064  {
13065  ae_vector_set_length(&rep->p, 0, _state);
13066  ae_matrix_set_length(&rep->z, 0, 0, _state);
13067  ae_matrix_set_length(&rep->pz, 0, 0, _state);
13068  ae_matrix_set_length(&rep->pm, 0, 0, _state);
13069  ae_vector_set_length(&rep->mergedist, 0, _state);
13070  ae_frame_leave(_state);
13071  return;
13072  }
13073  if( npoints==1 )
13074  {
13075  ae_vector_set_length(&rep->p, 1, _state);
13076  ae_matrix_set_length(&rep->z, 0, 0, _state);
13077  ae_matrix_set_length(&rep->pz, 0, 0, _state);
13078  ae_matrix_set_length(&rep->pm, 0, 0, _state);
13079  ae_vector_set_length(&rep->mergedist, 0, _state);
13080  rep->p.ptr.p_int[0] = 0;
13081  ae_frame_leave(_state);
13082  return;
13083  }
13084  ae_matrix_set_length(&rep->z, npoints-1, 2, _state);
13085  ae_vector_set_length(&rep->mergedist, npoints-1, _state);
13086 
13087  /*
13088  * Build list of nearest neighbors
13089  */
13090  ae_vector_set_length(&nnidx, npoints, _state);
13091  for(i=0; i<=npoints-1; i++)
13092  {
13093 
13094  /*
13095  * Calculate index of the nearest neighbor
13096  */
13097  k = -1;
13098  v = ae_maxrealnumber;
13099  for(j=0; j<=npoints-1; j++)
13100  {
13101  if( j!=i&&ae_fp_less(d->ptr.pp_double[i][j],v) )
13102  {
13103  k = j;
13104  v = d->ptr.pp_double[i][j];
13105  }
13106  }
13107  ae_assert(ae_fp_less(v,ae_maxrealnumber), "ClusterizerRunAHC: internal error", _state);
13108  nnidx.ptr.p_int[i] = k;
13109  }
13110 
13111  /*
13112  * Distance matrix is built, perform merges.
13113  *
13114  * NOTE 1: CIdx is array[NPoints] which maps rows/columns of the
13115  * distance matrix D to indexes of clusters. Values of CIdx
13116  * from [0,NPoints) denote single-point clusters, and values
13117  * from [NPoints,2*NPoints-1) denote ones obtained by merging
13118  * smaller clusters. Negative calues correspond to absent clusters.
13119  *
13120  * Initially it contains [0...NPoints-1], after each merge
13121  * one element of CIdx (one with index C0) is replaced by
13122  * NPoints+MergeIdx, and another one with index C1 is
13123  * rewritten by -1.
13124  *
13125  * NOTE 2: CSizes is array[NPoints] which stores sizes of clusters.
13126  *
13127  */
13128  ae_vector_set_length(&cidx, npoints, _state);
13129  ae_vector_set_length(&csizes, npoints, _state);
13130  for(i=0; i<=npoints-1; i++)
13131  {
13132  cidx.ptr.p_int[i] = i;
13133  csizes.ptr.p_int[i] = 1;
13134  }
13135  for(mergeidx=0; mergeidx<=npoints-2; mergeidx++)
13136  {
13137 
13138  /*
13139  * Select pair of clusters (C0,C1) with CIdx[C0]<CIdx[C1] to merge.
13140  */
13141  c0 = -1;
13142  c1 = -1;
13143  v = ae_maxrealnumber;
13144  for(i=0; i<=npoints-1; i++)
13145  {
13146  if( cidx.ptr.p_int[i]>=0 )
13147  {
13148  if( ae_fp_less(d->ptr.pp_double[i][nnidx.ptr.p_int[i]],v) )
13149  {
13150  c0 = i;
13151  c1 = nnidx.ptr.p_int[i];
13152  v = d->ptr.pp_double[i][nnidx.ptr.p_int[i]];
13153  }
13154  }
13155  }
13156  ae_assert(ae_fp_less(v,ae_maxrealnumber), "ClusterizerRunAHC: internal error", _state);
13157  if( cidx.ptr.p_int[c0]>cidx.ptr.p_int[c1] )
13158  {
13159  i = c1;
13160  c1 = c0;
13161  c0 = i;
13162  }
13163 
13164  /*
13165  * Fill one row of Rep.Z and one element of Rep.MergeDist
13166  */
13167  rep->z.ptr.pp_int[mergeidx][0] = cidx.ptr.p_int[c0];
13168  rep->z.ptr.pp_int[mergeidx][1] = cidx.ptr.p_int[c1];
13169  rep->mergedist.ptr.p_double[mergeidx] = v;
13170 
13171  /*
13172  * Update distance matrix:
13173  * * row/column C0 are updated by distances to the new cluster
13174  * * row/column C1 are considered empty (we can fill them by zeros,
13175  * but do not want to spend time - we just ignore them)
13176  *
13177  * NOTE: it is important to update distance matrix BEFORE CIdx/CSizes
13178  * are updated.
13179  */
13180  ae_assert(((s->ahcalgo==0||s->ahcalgo==1)||s->ahcalgo==2)||s->ahcalgo==3, "ClusterizerRunAHC: internal error", _state);
13181  for(i=0; i<=npoints-1; i++)
13182  {
13183  if( i!=c0&&i!=c1 )
13184  {
13185  if( s->ahcalgo==0 )
13186  {
13187  d->ptr.pp_double[i][c0] = ae_maxreal(d->ptr.pp_double[i][c0], d->ptr.pp_double[i][c1], _state);
13188  }
13189  if( s->ahcalgo==1 )
13190  {
13191  d->ptr.pp_double[i][c0] = ae_minreal(d->ptr.pp_double[i][c0], d->ptr.pp_double[i][c1], _state);
13192  }
13193  if( s->ahcalgo==2 )
13194  {
13195  d->ptr.pp_double[i][c0] = (csizes.ptr.p_int[c0]*d->ptr.pp_double[i][c0]+csizes.ptr.p_int[c1]*d->ptr.pp_double[i][c1])/(csizes.ptr.p_int[c0]+csizes.ptr.p_int[c1]);
13196  }
13197  if( s->ahcalgo==3 )
13198  {
13199  d->ptr.pp_double[i][c0] = (d->ptr.pp_double[i][c0]+d->ptr.pp_double[i][c1])/2;
13200  }
13201  d->ptr.pp_double[c0][i] = d->ptr.pp_double[i][c0];
13202  }
13203  }
13204 
13205  /*
13206  * Update CIdx and CSizes
13207  */
13208  cidx.ptr.p_int[c0] = npoints+mergeidx;
13209  cidx.ptr.p_int[c1] = -1;
13210  csizes.ptr.p_int[c0] = csizes.ptr.p_int[c0]+csizes.ptr.p_int[c1];
13211  csizes.ptr.p_int[c1] = 0;
13212 
13213  /*
13214  * Update nearest neighbors array:
13215  * * update nearest neighbors of everything except for C0/C1
13216  * * update neighbors of C0/C1
13217  */
13218  for(i=0; i<=npoints-1; i++)
13219  {
13220  if( (cidx.ptr.p_int[i]>=0&&i!=c0)&&(nnidx.ptr.p_int[i]==c0||nnidx.ptr.p_int[i]==c1) )
13221  {
13222 
13223  /*
13224  * I-th cluster which is distinct from C0/C1 has former C0/C1 cluster as its nearest
13225  * neighbor. We handle this issue depending on specific AHC algorithm being used.
13226  */
13227  if( s->ahcalgo==1 )
13228  {
13229 
13230  /*
13231  * Single linkage. Merging of two clusters together
13232  * does NOT change distances between new cluster and
13233  * other clusters.
13234  *
13235  * The only thing we have to do is to update nearest neighbor index
13236  */
13237  nnidx.ptr.p_int[i] = c0;
13238  }
13239  else
13240  {
13241 
13242  /*
13243  * Something other than single linkage. We have to re-examine
13244  * all the row to find nearest neighbor.
13245  */
13246  k = -1;
13247  v = ae_maxrealnumber;
13248  for(j=0; j<=npoints-1; j++)
13249  {
13250  if( (cidx.ptr.p_int[j]>=0&&j!=i)&&ae_fp_less(d->ptr.pp_double[i][j],v) )
13251  {
13252  k = j;
13253  v = d->ptr.pp_double[i][j];
13254  }
13255  }
13256  ae_assert(ae_fp_less(v,ae_maxrealnumber)||mergeidx==npoints-2, "ClusterizerRunAHC: internal error", _state);
13257  nnidx.ptr.p_int[i] = k;
13258  }
13259  }
13260  }
13261  k = -1;
13262  v = ae_maxrealnumber;
13263  for(j=0; j<=npoints-1; j++)
13264  {
13265  if( (cidx.ptr.p_int[j]>=0&&j!=c0)&&ae_fp_less(d->ptr.pp_double[c0][j],v) )
13266  {
13267  k = j;
13268  v = d->ptr.pp_double[c0][j];
13269  }
13270  }
13271  ae_assert(ae_fp_less(v,ae_maxrealnumber)||mergeidx==npoints-2, "ClusterizerRunAHC: internal error", _state);
13272  nnidx.ptr.p_int[c0] = k;
13273  }
13274 
13275  /*
13276  * Calculate Rep.P and Rep.PM.
13277  *
13278  * In order to do that, we fill CInfo matrix - (2*NPoints-1)*3 matrix,
13279  * with I-th row containing:
13280  * * CInfo[I,0] - size of I-th cluster
13281  * * CInfo[I,1] - beginning of I-th cluster
13282  * * CInfo[I,2] - end of I-th cluster
13283  * * CInfo[I,3] - height of I-th cluster
13284  *
13285  * We perform it as follows:
13286  * * first NPoints clusters have unit size (CInfo[I,0]=1) and zero
13287  * height (CInfo[I,3]=0)
13288  * * we replay NPoints-1 merges from first to last and fill sizes of
13289  * corresponding clusters (new size is a sum of sizes of clusters
13290  * being merged) and height (new height is max(heights)+1).
13291  * * now we ready to determine locations of clusters. Last cluster
13292  * spans entire dataset, we know it. We replay merges from last to
13293  * first, during each merge we already know location of the merge
13294  * result, and we can position first cluster to the left part of
13295  * the result, and second cluster to the right part.
13296  */
13297  ae_vector_set_length(&rep->p, npoints, _state);
13298  ae_matrix_set_length(&rep->pm, npoints-1, 6, _state);
13299  ae_matrix_set_length(&cinfo, 2*npoints-1, 4, _state);
13300  for(i=0; i<=npoints-1; i++)
13301  {
13302  cinfo.ptr.pp_int[i][0] = 1;
13303  cinfo.ptr.pp_int[i][3] = 0;
13304  }
13305  for(i=0; i<=npoints-2; i++)
13306  {
13307  cinfo.ptr.pp_int[npoints+i][0] = cinfo.ptr.pp_int[rep->z.ptr.pp_int[i][0]][0]+cinfo.ptr.pp_int[rep->z.ptr.pp_int[i][1]][0];
13308  cinfo.ptr.pp_int[npoints+i][3] = ae_maxint(cinfo.ptr.pp_int[rep->z.ptr.pp_int[i][0]][3], cinfo.ptr.pp_int[rep->z.ptr.pp_int[i][1]][3], _state)+1;
13309  }
13310  cinfo.ptr.pp_int[2*npoints-2][1] = 0;
13311  cinfo.ptr.pp_int[2*npoints-2][2] = npoints-1;
13312  for(i=npoints-2; i>=0; i--)
13313  {
13314 
13315  /*
13316  * We merge C0 which spans [A0,B0] and C1 (spans [A1,B1]),
13317  * with unknown A0, B0, A1, B1. However, we know that result
13318  * is CR, which spans [AR,BR] with known AR/BR, and we know
13319  * sizes of C0, C1, CR (denotes as S0, S1, SR).
13320  */
13321  c0 = rep->z.ptr.pp_int[i][0];
13322  c1 = rep->z.ptr.pp_int[i][1];
13323  s0 = cinfo.ptr.pp_int[c0][0];
13324  s1 = cinfo.ptr.pp_int[c1][0];
13325  ar = cinfo.ptr.pp_int[npoints+i][1];
13326  br = cinfo.ptr.pp_int[npoints+i][2];
13327  cinfo.ptr.pp_int[c0][1] = ar;
13328  cinfo.ptr.pp_int[c0][2] = ar+s0-1;
13329  cinfo.ptr.pp_int[c1][1] = br-(s1-1);
13330  cinfo.ptr.pp_int[c1][2] = br;
13331  rep->pm.ptr.pp_int[i][0] = cinfo.ptr.pp_int[c0][1];
13332  rep->pm.ptr.pp_int[i][1] = cinfo.ptr.pp_int[c0][2];
13333  rep->pm.ptr.pp_int[i][2] = cinfo.ptr.pp_int[c1][1];
13334  rep->pm.ptr.pp_int[i][3] = cinfo.ptr.pp_int[c1][2];
13335  rep->pm.ptr.pp_int[i][4] = cinfo.ptr.pp_int[c0][3];
13336  rep->pm.ptr.pp_int[i][5] = cinfo.ptr.pp_int[c1][3];
13337  }
13338  for(i=0; i<=npoints-1; i++)
13339  {
13340  ae_assert(cinfo.ptr.pp_int[i][1]==cinfo.ptr.pp_int[i][2], "Assertion failed", _state);
13341  rep->p.ptr.p_int[i] = cinfo.ptr.pp_int[i][1];
13342  }
13343 
13344  /*
13345  * Calculate Rep.PZ
13346  */
13347  ae_matrix_set_length(&rep->pz, npoints-1, 2, _state);
13348  for(i=0; i<=npoints-2; i++)
13349  {
13350  rep->pz.ptr.pp_int[i][0] = rep->z.ptr.pp_int[i][0];
13351  rep->pz.ptr.pp_int[i][1] = rep->z.ptr.pp_int[i][1];
13352  if( rep->pz.ptr.pp_int[i][0]<npoints )
13353  {
13354  rep->pz.ptr.pp_int[i][0] = rep->p.ptr.p_int[rep->pz.ptr.pp_int[i][0]];
13355  }
13356  if( rep->pz.ptr.pp_int[i][1]<npoints )
13357  {
13358  rep->pz.ptr.pp_int[i][1] = rep->p.ptr.p_int[rep->pz.ptr.pp_int[i][1]];
13359  }
13360  }
13361  ae_frame_leave(_state);
13362 }
13363 
13364 
13365 static void clustering_evaluatedistancematrixrec(/* Real */ ae_matrix* xy,
13366  ae_int_t nfeatures,
13367  ae_int_t disttype,
13368  /* Real */ ae_matrix* d,
13369  ae_int_t i0,
13370  ae_int_t i1,
13371  ae_int_t j0,
13372  ae_int_t j1,
13373  ae_state *_state)
13374 {
13375  double rcomplexity;
13376  ae_int_t len0;
13377  ae_int_t len1;
13378  ae_int_t i;
13379  ae_int_t j;
13380  ae_int_t k;
13381  double v;
13382  double vv;
13383 
13384 
13385  ae_assert(disttype==0||disttype==1, "EvaluateDistanceMatrixRec: incorrect DistType", _state);
13386 
13387  /*
13388  * Normalize J0/J1:
13389  * * J0:=max(J0,I0) - we ignore lower triangle
13390  * * J1:=max(J1,J0) - normalize J1
13391  */
13392  j0 = ae_maxint(j0, i0, _state);
13393  j1 = ae_maxint(j1, j0, _state);
13394  if( j1<=j0||i1<=i0 )
13395  {
13396  return;
13397  }
13398 
13399  /*
13400  * Try to process in parallel. Two condtions must hold in order to
13401  * activate parallel processing:
13402  * 1. I1-I0>2 or J1-J0>2
13403  * 2. (I1-I0)*(J1-J0)*NFeatures>=ParallelComplexity
13404  *
13405  * NOTE: all quantities are converted to reals in order to avoid
13406  * integer overflow during multiplication
13407  *
13408  * NOTE: strict inequality in (1) is necessary to reduce task to 2x2
13409  * basecases. In future versions we will be able to handle such
13410  * basecases more efficiently than 1x1 cases.
13411  */
13412  rcomplexity = i1-i0;
13413  rcomplexity = rcomplexity*(j1-j0);
13414  rcomplexity = rcomplexity*nfeatures;
13415  if( ae_fp_greater_eq(rcomplexity,clustering_parallelcomplexity)&&(i1-i0>2||j1-j0>2) )
13416  {
13417 
13418  /*
13419  * Recursive division along largest of dimensions
13420  */
13421  if( i1-i0>j1-j0 )
13422  {
13423  splitlengtheven(i1-i0, &len0, &len1, _state);
13424  clustering_evaluatedistancematrixrec(xy, nfeatures, disttype, d, i0, i0+len0, j0, j1, _state);
13425  clustering_evaluatedistancematrixrec(xy, nfeatures, disttype, d, i0+len0, i1, j0, j1, _state);
13426  }
13427  else
13428  {
13429  splitlengtheven(j1-j0, &len0, &len1, _state);
13430  clustering_evaluatedistancematrixrec(xy, nfeatures, disttype, d, i0, i1, j0, j0+len0, _state);
13431  clustering_evaluatedistancematrixrec(xy, nfeatures, disttype, d, i0, i1, j0+len0, j1, _state);
13432  }
13433  return;
13434  }
13435 
13436  /*
13437  * Sequential processing
13438  */
13439  for(i=i0; i<=i1-1; i++)
13440  {
13441  for(j=j0; j<=j1-1; j++)
13442  {
13443  if( j>=i )
13444  {
13445  v = 0.0;
13446  if( disttype==0 )
13447  {
13448  for(k=0; k<=nfeatures-1; k++)
13449  {
13450  vv = xy->ptr.pp_double[i][k]-xy->ptr.pp_double[j][k];
13451  if( ae_fp_less(vv,0) )
13452  {
13453  vv = -vv;
13454  }
13455  if( ae_fp_greater(vv,v) )
13456  {
13457  v = vv;
13458  }
13459  }
13460  }
13461  if( disttype==1 )
13462  {
13463  for(k=0; k<=nfeatures-1; k++)
13464  {
13465  vv = xy->ptr.pp_double[i][k]-xy->ptr.pp_double[j][k];
13466  if( ae_fp_less(vv,0) )
13467  {
13468  vv = -vv;
13469  }
13470  v = v+vv;
13471  }
13472  }
13473  d->ptr.pp_double[i][j] = v;
13474  }
13475  }
13476  }
13477 }
13478 
13479 
13480 ae_bool _clusterizerstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
13481 {
13482  clusterizerstate *p = (clusterizerstate*)_p;
13483  ae_touch_ptr((void*)p);
13484  if( !ae_matrix_init(&p->xy, 0, 0, DT_REAL, _state, make_automatic) )
13485  return ae_false;
13486  if( !ae_matrix_init(&p->d, 0, 0, DT_REAL, _state, make_automatic) )
13487  return ae_false;
13488  return ae_true;
13489 }
13490 
13491 
13492 ae_bool _clusterizerstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
13493 {
13494  clusterizerstate *dst = (clusterizerstate*)_dst;
13495  clusterizerstate *src = (clusterizerstate*)_src;
13496  dst->npoints = src->npoints;
13497  dst->nfeatures = src->nfeatures;
13498  dst->disttype = src->disttype;
13499  if( !ae_matrix_init_copy(&dst->xy, &src->xy, _state, make_automatic) )
13500  return ae_false;
13501  if( !ae_matrix_init_copy(&dst->d, &src->d, _state, make_automatic) )
13502  return ae_false;
13503  dst->ahcalgo = src->ahcalgo;
13504  dst->kmeansrestarts = src->kmeansrestarts;
13505  dst->kmeansmaxits = src->kmeansmaxits;
13506  return ae_true;
13507 }
13508 
13509 
13510 void _clusterizerstate_clear(void* _p)
13511 {
13512  clusterizerstate *p = (clusterizerstate*)_p;
13513  ae_touch_ptr((void*)p);
13514  ae_matrix_clear(&p->xy);
13515  ae_matrix_clear(&p->d);
13516 }
13517 
13518 
13519 void _clusterizerstate_destroy(void* _p)
13520 {
13521  clusterizerstate *p = (clusterizerstate*)_p;
13522  ae_touch_ptr((void*)p);
13523  ae_matrix_destroy(&p->xy);
13524  ae_matrix_destroy(&p->d);
13525 }
13526 
13527 
13528 ae_bool _ahcreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
13529 {
13530  ahcreport *p = (ahcreport*)_p;
13531  ae_touch_ptr((void*)p);
13532  if( !ae_vector_init(&p->p, 0, DT_INT, _state, make_automatic) )
13533  return ae_false;
13534  if( !ae_matrix_init(&p->z, 0, 0, DT_INT, _state, make_automatic) )
13535  return ae_false;
13536  if( !ae_matrix_init(&p->pz, 0, 0, DT_INT, _state, make_automatic) )
13537  return ae_false;
13538  if( !ae_matrix_init(&p->pm, 0, 0, DT_INT, _state, make_automatic) )
13539  return ae_false;
13540  if( !ae_vector_init(&p->mergedist, 0, DT_REAL, _state, make_automatic) )
13541  return ae_false;
13542  return ae_true;
13543 }
13544 
13545 
13546 ae_bool _ahcreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
13547 {
13548  ahcreport *dst = (ahcreport*)_dst;
13549  ahcreport *src = (ahcreport*)_src;
13550  dst->npoints = src->npoints;
13551  if( !ae_vector_init_copy(&dst->p, &src->p, _state, make_automatic) )
13552  return ae_false;
13553  if( !ae_matrix_init_copy(&dst->z, &src->z, _state, make_automatic) )
13554  return ae_false;
13555  if( !ae_matrix_init_copy(&dst->pz, &src->pz, _state, make_automatic) )
13556  return ae_false;
13557  if( !ae_matrix_init_copy(&dst->pm, &src->pm, _state, make_automatic) )
13558  return ae_false;
13559  if( !ae_vector_init_copy(&dst->mergedist, &src->mergedist, _state, make_automatic) )
13560  return ae_false;
13561  return ae_true;
13562 }
13563 
13564 
13565 void _ahcreport_clear(void* _p)
13566 {
13567  ahcreport *p = (ahcreport*)_p;
13568  ae_touch_ptr((void*)p);
13569  ae_vector_clear(&p->p);
13570  ae_matrix_clear(&p->z);
13571  ae_matrix_clear(&p->pz);
13572  ae_matrix_clear(&p->pm);
13573  ae_vector_clear(&p->mergedist);
13574 }
13575 
13576 
13577 void _ahcreport_destroy(void* _p)
13578 {
13579  ahcreport *p = (ahcreport*)_p;
13580  ae_touch_ptr((void*)p);
13581  ae_vector_destroy(&p->p);
13582  ae_matrix_destroy(&p->z);
13583  ae_matrix_destroy(&p->pz);
13584  ae_matrix_destroy(&p->pm);
13585  ae_vector_destroy(&p->mergedist);
13586 }
13587 
13588 
13589 ae_bool _kmeansreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
13590 {
13591  kmeansreport *p = (kmeansreport*)_p;
13592  ae_touch_ptr((void*)p);
13593  if( !ae_matrix_init(&p->c, 0, 0, DT_REAL, _state, make_automatic) )
13594  return ae_false;
13595  if( !ae_vector_init(&p->cidx, 0, DT_INT, _state, make_automatic) )
13596  return ae_false;
13597  return ae_true;
13598 }
13599 
13600 
13601 ae_bool _kmeansreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
13602 {
13603  kmeansreport *dst = (kmeansreport*)_dst;
13604  kmeansreport *src = (kmeansreport*)_src;
13605  dst->npoints = src->npoints;
13606  dst->nfeatures = src->nfeatures;
13607  dst->terminationtype = src->terminationtype;
13608  dst->k = src->k;
13609  if( !ae_matrix_init_copy(&dst->c, &src->c, _state, make_automatic) )
13610  return ae_false;
13611  if( !ae_vector_init_copy(&dst->cidx, &src->cidx, _state, make_automatic) )
13612  return ae_false;
13613  return ae_true;
13614 }
13615 
13616 
13617 void _kmeansreport_clear(void* _p)
13618 {
13619  kmeansreport *p = (kmeansreport*)_p;
13620  ae_touch_ptr((void*)p);
13621  ae_matrix_clear(&p->c);
13622  ae_vector_clear(&p->cidx);
13623 }
13624 
13625 
13626 void _kmeansreport_destroy(void* _p)
13627 {
13628  kmeansreport *p = (kmeansreport*)_p;
13629  ae_touch_ptr((void*)p);
13630  ae_matrix_destroy(&p->c);
13631  ae_vector_destroy(&p->cidx);
13632 }
13633 
13634 
13635 
13636 
13637 /*************************************************************************
13638 k-means++ clusterization.
13639 Backward compatibility function, we recommend to use CLUSTERING subpackage
13640 as better replacement.
13641 
13642  -- ALGLIB --
13643  Copyright 21.03.2009 by Bochkanov Sergey
13644 *************************************************************************/
13645 void kmeansgenerate(/* Real */ ae_matrix* xy,
13646  ae_int_t npoints,
13647  ae_int_t nvars,
13648  ae_int_t k,
13649  ae_int_t restarts,
13650  ae_int_t* info,
13651  /* Real */ ae_matrix* c,
13652  /* Integer */ ae_vector* xyc,
13653  ae_state *_state)
13654 {
13655  ae_frame _frame_block;
13656  ae_matrix dummy;
13657 
13658  ae_frame_make(_state, &_frame_block);
13659  *info = 0;
13660  ae_matrix_clear(c);
13661  ae_vector_clear(xyc);
13662  ae_matrix_init(&dummy, 0, 0, DT_REAL, _state, ae_true);
13663 
13664  kmeansgenerateinternal(xy, npoints, nvars, k, 0, restarts, info, c, ae_true, &dummy, ae_false, xyc, _state);
13665  ae_frame_leave(_state);
13666 }
13667 
13668 
13669 
13670 
13671 /*************************************************************************
13672 This subroutine builds random decision forest.
13673 
13674 INPUT PARAMETERS:
13675  XY - training set
13676  NPoints - training set size, NPoints>=1
13677  NVars - number of independent variables, NVars>=1
13678  NClasses - task type:
13679  * NClasses=1 - regression task with one
13680  dependent variable
13681  * NClasses>1 - classification task with
13682  NClasses classes.
13683  NTrees - number of trees in a forest, NTrees>=1.
13684  recommended values: 50-100.
13685  R - percent of a training set used to build
13686  individual trees. 0<R<=1.
13687  recommended values: 0.1 <= R <= 0.66.
13688 
13689 OUTPUT PARAMETERS:
13690  Info - return code:
13691  * -2, if there is a point with class number
13692  outside of [0..NClasses-1].
13693  * -1, if incorrect parameters was passed
13694  (NPoints<1, NVars<1, NClasses<1, NTrees<1, R<=0
13695  or R>1).
13696  * 1, if task has been solved
13697  DF - model built
13698  Rep - training report, contains error on a training set
13699  and out-of-bag estimates of generalization error.
13700 
13701  -- ALGLIB --
13702  Copyright 19.02.2009 by Bochkanov Sergey
13703 *************************************************************************/
13704 void dfbuildrandomdecisionforest(/* Real */ ae_matrix* xy,
13705  ae_int_t npoints,
13706  ae_int_t nvars,
13707  ae_int_t nclasses,
13708  ae_int_t ntrees,
13709  double r,
13710  ae_int_t* info,
13711  decisionforest* df,
13712  dfreport* rep,
13713  ae_state *_state)
13714 {
13715  ae_int_t samplesize;
13716 
13717  *info = 0;
13718  _decisionforest_clear(df);
13719  _dfreport_clear(rep);
13720 
13721  if( ae_fp_less_eq(r,0)||ae_fp_greater(r,1) )
13722  {
13723  *info = -1;
13724  return;
13725  }
13726  samplesize = ae_maxint(ae_round(r*npoints, _state), 1, _state);
13727  dfbuildinternal(xy, npoints, nvars, nclasses, ntrees, samplesize, ae_maxint(nvars/2, 1, _state), dforest_dfusestrongsplits+dforest_dfuseevs, info, df, rep, _state);
13728 }
13729 
13730 
13731 /*************************************************************************
13732 This subroutine builds random decision forest.
13733 This function gives ability to tune number of variables used when choosing
13734 best split.
13735 
13736 INPUT PARAMETERS:
13737  XY - training set
13738  NPoints - training set size, NPoints>=1
13739  NVars - number of independent variables, NVars>=1
13740  NClasses - task type:
13741  * NClasses=1 - regression task with one
13742  dependent variable
13743  * NClasses>1 - classification task with
13744  NClasses classes.
13745  NTrees - number of trees in a forest, NTrees>=1.
13746  recommended values: 50-100.
13747  NRndVars - number of variables used when choosing best split
13748  R - percent of a training set used to build
13749  individual trees. 0<R<=1.
13750  recommended values: 0.1 <= R <= 0.66.
13751 
13752 OUTPUT PARAMETERS:
13753  Info - return code:
13754  * -2, if there is a point with class number
13755  outside of [0..NClasses-1].
13756  * -1, if incorrect parameters was passed
13757  (NPoints<1, NVars<1, NClasses<1, NTrees<1, R<=0
13758  or R>1).
13759  * 1, if task has been solved
13760  DF - model built
13761  Rep - training report, contains error on a training set
13762  and out-of-bag estimates of generalization error.
13763 
13764  -- ALGLIB --
13765  Copyright 19.02.2009 by Bochkanov Sergey
13766 *************************************************************************/
13767 void dfbuildrandomdecisionforestx1(/* Real */ ae_matrix* xy,
13768  ae_int_t npoints,
13769  ae_int_t nvars,
13770  ae_int_t nclasses,
13771  ae_int_t ntrees,
13772  ae_int_t nrndvars,
13773  double r,
13774  ae_int_t* info,
13775  decisionforest* df,
13776  dfreport* rep,
13777  ae_state *_state)
13778 {
13779  ae_int_t samplesize;
13780 
13781  *info = 0;
13782  _decisionforest_clear(df);
13783  _dfreport_clear(rep);
13784 
13785  if( ae_fp_less_eq(r,0)||ae_fp_greater(r,1) )
13786  {
13787  *info = -1;
13788  return;
13789  }
13790  if( nrndvars<=0||nrndvars>nvars )
13791  {
13792  *info = -1;
13793  return;
13794  }
13795  samplesize = ae_maxint(ae_round(r*npoints, _state), 1, _state);
13796  dfbuildinternal(xy, npoints, nvars, nclasses, ntrees, samplesize, nrndvars, dforest_dfusestrongsplits+dforest_dfuseevs, info, df, rep, _state);
13797 }
13798 
13799 
13800 void dfbuildinternal(/* Real */ ae_matrix* xy,
13801  ae_int_t npoints,
13802  ae_int_t nvars,
13803  ae_int_t nclasses,
13804  ae_int_t ntrees,
13805  ae_int_t samplesize,
13806  ae_int_t nfeatures,
13807  ae_int_t flags,
13808  ae_int_t* info,
13809  decisionforest* df,
13810  dfreport* rep,
13811  ae_state *_state)
13812 {
13813  ae_frame _frame_block;
13814  ae_int_t i;
13815  ae_int_t j;
13816  ae_int_t k;
13817  ae_int_t tmpi;
13818  ae_int_t lasttreeoffs;
13819  ae_int_t offs;
13820  ae_int_t ooboffs;
13821  ae_int_t treesize;
13822  ae_int_t nvarsinpool;
13823  ae_bool useevs;
13824  dfinternalbuffers bufs;
13825  ae_vector permbuf;
13826  ae_vector oobbuf;
13827  ae_vector oobcntbuf;
13828  ae_matrix xys;
13829  ae_vector x;
13830  ae_vector y;
13831  ae_int_t oobcnt;
13832  ae_int_t oobrelcnt;
13833  double v;
13834  double vmin;
13835  double vmax;
13836  ae_bool bflag;
13837  hqrndstate rs;
13838 
13839  ae_frame_make(_state, &_frame_block);
13840  *info = 0;
13841  _decisionforest_clear(df);
13842  _dfreport_clear(rep);
13843  _dfinternalbuffers_init(&bufs, _state, ae_true);
13844  ae_vector_init(&permbuf, 0, DT_INT, _state, ae_true);
13845  ae_vector_init(&oobbuf, 0, DT_REAL, _state, ae_true);
13846  ae_vector_init(&oobcntbuf, 0, DT_INT, _state, ae_true);
13847  ae_matrix_init(&xys, 0, 0, DT_REAL, _state, ae_true);
13848  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
13849  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
13850  _hqrndstate_init(&rs, _state, ae_true);
13851 
13852 
13853  /*
13854  * Test for inputs
13855  */
13856  if( (((((npoints<1||samplesize<1)||samplesize>npoints)||nvars<1)||nclasses<1)||ntrees<1)||nfeatures<1 )
13857  {
13858  *info = -1;
13859  ae_frame_leave(_state);
13860  return;
13861  }
13862  if( nclasses>1 )
13863  {
13864  for(i=0; i<=npoints-1; i++)
13865  {
13866  if( ae_round(xy->ptr.pp_double[i][nvars], _state)<0||ae_round(xy->ptr.pp_double[i][nvars], _state)>=nclasses )
13867  {
13868  *info = -2;
13869  ae_frame_leave(_state);
13870  return;
13871  }
13872  }
13873  }
13874  *info = 1;
13875 
13876  /*
13877  * Flags
13878  */
13879  useevs = flags/dforest_dfuseevs%2!=0;
13880 
13881  /*
13882  * Allocate data, prepare header
13883  */
13884  treesize = 1+dforest_innernodewidth*(samplesize-1)+dforest_leafnodewidth*samplesize;
13885  ae_vector_set_length(&permbuf, npoints-1+1, _state);
13886  ae_vector_set_length(&bufs.treebuf, treesize-1+1, _state);
13887  ae_vector_set_length(&bufs.idxbuf, npoints-1+1, _state);
13888  ae_vector_set_length(&bufs.tmpbufr, npoints-1+1, _state);
13889  ae_vector_set_length(&bufs.tmpbufr2, npoints-1+1, _state);
13890  ae_vector_set_length(&bufs.tmpbufi, npoints-1+1, _state);
13891  ae_vector_set_length(&bufs.sortrbuf, npoints, _state);
13892  ae_vector_set_length(&bufs.sortrbuf2, npoints, _state);
13893  ae_vector_set_length(&bufs.sortibuf, npoints, _state);
13894  ae_vector_set_length(&bufs.varpool, nvars-1+1, _state);
13895  ae_vector_set_length(&bufs.evsbin, nvars-1+1, _state);
13896  ae_vector_set_length(&bufs.evssplits, nvars-1+1, _state);
13897  ae_vector_set_length(&bufs.classibuf, 2*nclasses-1+1, _state);
13898  ae_vector_set_length(&oobbuf, nclasses*npoints-1+1, _state);
13899  ae_vector_set_length(&oobcntbuf, npoints-1+1, _state);
13900  ae_vector_set_length(&df->trees, ntrees*treesize-1+1, _state);
13901  ae_matrix_set_length(&xys, samplesize-1+1, nvars+1, _state);
13902  ae_vector_set_length(&x, nvars-1+1, _state);
13903  ae_vector_set_length(&y, nclasses-1+1, _state);
13904  for(i=0; i<=npoints-1; i++)
13905  {
13906  permbuf.ptr.p_int[i] = i;
13907  }
13908  for(i=0; i<=npoints*nclasses-1; i++)
13909  {
13910  oobbuf.ptr.p_double[i] = 0;
13911  }
13912  for(i=0; i<=npoints-1; i++)
13913  {
13914  oobcntbuf.ptr.p_int[i] = 0;
13915  }
13916 
13917  /*
13918  * Prepare variable pool and EVS (extended variable selection/splitting) buffers
13919  * (whether EVS is turned on or not):
13920  * 1. detect binary variables and pre-calculate splits for them
13921  * 2. detect variables with non-distinct values and exclude them from pool
13922  */
13923  for(i=0; i<=nvars-1; i++)
13924  {
13925  bufs.varpool.ptr.p_int[i] = i;
13926  }
13927  nvarsinpool = nvars;
13928  if( useevs )
13929  {
13930  for(j=0; j<=nvars-1; j++)
13931  {
13932  vmin = xy->ptr.pp_double[0][j];
13933  vmax = vmin;
13934  for(i=0; i<=npoints-1; i++)
13935  {
13936  v = xy->ptr.pp_double[i][j];
13937  vmin = ae_minreal(vmin, v, _state);
13938  vmax = ae_maxreal(vmax, v, _state);
13939  }
13940  if( ae_fp_eq(vmin,vmax) )
13941  {
13942 
13943  /*
13944  * exclude variable from pool
13945  */
13946  bufs.varpool.ptr.p_int[j] = bufs.varpool.ptr.p_int[nvarsinpool-1];
13947  bufs.varpool.ptr.p_int[nvarsinpool-1] = -1;
13948  nvarsinpool = nvarsinpool-1;
13949  continue;
13950  }
13951  bflag = ae_false;
13952  for(i=0; i<=npoints-1; i++)
13953  {
13954  v = xy->ptr.pp_double[i][j];
13955  if( ae_fp_neq(v,vmin)&&ae_fp_neq(v,vmax) )
13956  {
13957  bflag = ae_true;
13958  break;
13959  }
13960  }
13961  if( bflag )
13962  {
13963 
13964  /*
13965  * non-binary variable
13966  */
13967  bufs.evsbin.ptr.p_bool[j] = ae_false;
13968  }
13969  else
13970  {
13971 
13972  /*
13973  * Prepare
13974  */
13975  bufs.evsbin.ptr.p_bool[j] = ae_true;
13976  bufs.evssplits.ptr.p_double[j] = 0.5*(vmin+vmax);
13977  if( ae_fp_less_eq(bufs.evssplits.ptr.p_double[j],vmin) )
13978  {
13979  bufs.evssplits.ptr.p_double[j] = vmax;
13980  }
13981  }
13982  }
13983  }
13984 
13985  /*
13986  * RANDOM FOREST FORMAT
13987  * W[0] - size of array
13988  * W[1] - version number
13989  * W[2] - NVars
13990  * W[3] - NClasses (1 for regression)
13991  * W[4] - NTrees
13992  * W[5] - trees offset
13993  *
13994  *
13995  * TREE FORMAT
13996  * W[Offs] - size of sub-array
13997  * node info:
13998  * W[K+0] - variable number (-1 for leaf mode)
13999  * W[K+1] - threshold (class/value for leaf node)
14000  * W[K+2] - ">=" branch index (absent for leaf node)
14001  *
14002  */
14003  df->nvars = nvars;
14004  df->nclasses = nclasses;
14005  df->ntrees = ntrees;
14006 
14007  /*
14008  * Build forest
14009  */
14010  hqrndrandomize(&rs, _state);
14011  offs = 0;
14012  for(i=0; i<=ntrees-1; i++)
14013  {
14014 
14015  /*
14016  * Prepare sample
14017  */
14018  for(k=0; k<=samplesize-1; k++)
14019  {
14020  j = k+hqrnduniformi(&rs, npoints-k, _state);
14021  tmpi = permbuf.ptr.p_int[k];
14022  permbuf.ptr.p_int[k] = permbuf.ptr.p_int[j];
14023  permbuf.ptr.p_int[j] = tmpi;
14024  j = permbuf.ptr.p_int[k];
14025  ae_v_move(&xys.ptr.pp_double[k][0], 1, &xy->ptr.pp_double[j][0], 1, ae_v_len(0,nvars));
14026  }
14027 
14028  /*
14029  * build tree, copy
14030  */
14031  dforest_dfbuildtree(&xys, samplesize, nvars, nclasses, nfeatures, nvarsinpool, flags, &bufs, &rs, _state);
14032  j = ae_round(bufs.treebuf.ptr.p_double[0], _state);
14033  ae_v_move(&df->trees.ptr.p_double[offs], 1, &bufs.treebuf.ptr.p_double[0], 1, ae_v_len(offs,offs+j-1));
14034  lasttreeoffs = offs;
14035  offs = offs+j;
14036 
14037  /*
14038  * OOB estimates
14039  */
14040  for(k=samplesize; k<=npoints-1; k++)
14041  {
14042  for(j=0; j<=nclasses-1; j++)
14043  {
14044  y.ptr.p_double[j] = 0;
14045  }
14046  j = permbuf.ptr.p_int[k];
14047  ae_v_move(&x.ptr.p_double[0], 1, &xy->ptr.pp_double[j][0], 1, ae_v_len(0,nvars-1));
14048  dforest_dfprocessinternal(df, lasttreeoffs, &x, &y, _state);
14049  ae_v_add(&oobbuf.ptr.p_double[j*nclasses], 1, &y.ptr.p_double[0], 1, ae_v_len(j*nclasses,(j+1)*nclasses-1));
14050  oobcntbuf.ptr.p_int[j] = oobcntbuf.ptr.p_int[j]+1;
14051  }
14052  }
14053  df->bufsize = offs;
14054 
14055  /*
14056  * Normalize OOB results
14057  */
14058  for(i=0; i<=npoints-1; i++)
14059  {
14060  if( oobcntbuf.ptr.p_int[i]!=0 )
14061  {
14062  v = (double)1/(double)oobcntbuf.ptr.p_int[i];
14063  ae_v_muld(&oobbuf.ptr.p_double[i*nclasses], 1, ae_v_len(i*nclasses,i*nclasses+nclasses-1), v);
14064  }
14065  }
14066 
14067  /*
14068  * Calculate training set estimates
14069  */
14070  rep->relclserror = dfrelclserror(df, xy, npoints, _state);
14071  rep->avgce = dfavgce(df, xy, npoints, _state);
14072  rep->rmserror = dfrmserror(df, xy, npoints, _state);
14073  rep->avgerror = dfavgerror(df, xy, npoints, _state);
14074  rep->avgrelerror = dfavgrelerror(df, xy, npoints, _state);
14075 
14076  /*
14077  * Calculate OOB estimates.
14078  */
14079  rep->oobrelclserror = 0;
14080  rep->oobavgce = 0;
14081  rep->oobrmserror = 0;
14082  rep->oobavgerror = 0;
14083  rep->oobavgrelerror = 0;
14084  oobcnt = 0;
14085  oobrelcnt = 0;
14086  for(i=0; i<=npoints-1; i++)
14087  {
14088  if( oobcntbuf.ptr.p_int[i]!=0 )
14089  {
14090  ooboffs = i*nclasses;
14091  if( nclasses>1 )
14092  {
14093 
14094  /*
14095  * classification-specific code
14096  */
14097  k = ae_round(xy->ptr.pp_double[i][nvars], _state);
14098  tmpi = 0;
14099  for(j=1; j<=nclasses-1; j++)
14100  {
14101  if( ae_fp_greater(oobbuf.ptr.p_double[ooboffs+j],oobbuf.ptr.p_double[ooboffs+tmpi]) )
14102  {
14103  tmpi = j;
14104  }
14105  }
14106  if( tmpi!=k )
14107  {
14108  rep->oobrelclserror = rep->oobrelclserror+1;
14109  }
14110  if( ae_fp_neq(oobbuf.ptr.p_double[ooboffs+k],0) )
14111  {
14112  rep->oobavgce = rep->oobavgce-ae_log(oobbuf.ptr.p_double[ooboffs+k], _state);
14113  }
14114  else
14115  {
14116  rep->oobavgce = rep->oobavgce-ae_log(ae_minrealnumber, _state);
14117  }
14118  for(j=0; j<=nclasses-1; j++)
14119  {
14120  if( j==k )
14121  {
14122  rep->oobrmserror = rep->oobrmserror+ae_sqr(oobbuf.ptr.p_double[ooboffs+j]-1, _state);
14123  rep->oobavgerror = rep->oobavgerror+ae_fabs(oobbuf.ptr.p_double[ooboffs+j]-1, _state);
14124  rep->oobavgrelerror = rep->oobavgrelerror+ae_fabs(oobbuf.ptr.p_double[ooboffs+j]-1, _state);
14125  oobrelcnt = oobrelcnt+1;
14126  }
14127  else
14128  {
14129  rep->oobrmserror = rep->oobrmserror+ae_sqr(oobbuf.ptr.p_double[ooboffs+j], _state);
14130  rep->oobavgerror = rep->oobavgerror+ae_fabs(oobbuf.ptr.p_double[ooboffs+j], _state);
14131  }
14132  }
14133  }
14134  else
14135  {
14136 
14137  /*
14138  * regression-specific code
14139  */
14140  rep->oobrmserror = rep->oobrmserror+ae_sqr(oobbuf.ptr.p_double[ooboffs]-xy->ptr.pp_double[i][nvars], _state);
14141  rep->oobavgerror = rep->oobavgerror+ae_fabs(oobbuf.ptr.p_double[ooboffs]-xy->ptr.pp_double[i][nvars], _state);
14142  if( ae_fp_neq(xy->ptr.pp_double[i][nvars],0) )
14143  {
14144  rep->oobavgrelerror = rep->oobavgrelerror+ae_fabs((oobbuf.ptr.p_double[ooboffs]-xy->ptr.pp_double[i][nvars])/xy->ptr.pp_double[i][nvars], _state);
14145  oobrelcnt = oobrelcnt+1;
14146  }
14147  }
14148 
14149  /*
14150  * update OOB estimates count.
14151  */
14152  oobcnt = oobcnt+1;
14153  }
14154  }
14155  if( oobcnt>0 )
14156  {
14157  rep->oobrelclserror = rep->oobrelclserror/oobcnt;
14158  rep->oobavgce = rep->oobavgce/oobcnt;
14159  rep->oobrmserror = ae_sqrt(rep->oobrmserror/(oobcnt*nclasses), _state);
14160  rep->oobavgerror = rep->oobavgerror/(oobcnt*nclasses);
14161  if( oobrelcnt>0 )
14162  {
14163  rep->oobavgrelerror = rep->oobavgrelerror/oobrelcnt;
14164  }
14165  }
14166  ae_frame_leave(_state);
14167 }
14168 
14169 
14170 /*************************************************************************
14171 Procesing
14172 
14173 INPUT PARAMETERS:
14174  DF - decision forest model
14175  X - input vector, array[0..NVars-1].
14176 
14177 OUTPUT PARAMETERS:
14178  Y - result. Regression estimate when solving regression task,
14179  vector of posterior probabilities for classification task.
14180 
14181 See also DFProcessI.
14182 
14183  -- ALGLIB --
14184  Copyright 16.02.2009 by Bochkanov Sergey
14185 *************************************************************************/
14186 void dfprocess(decisionforest* df,
14187  /* Real */ ae_vector* x,
14188  /* Real */ ae_vector* y,
14189  ae_state *_state)
14190 {
14191  ae_int_t offs;
14192  ae_int_t i;
14193  double v;
14194 
14195 
14196 
14197  /*
14198  * Proceed
14199  */
14200  if( y->cnt<df->nclasses )
14201  {
14202  ae_vector_set_length(y, df->nclasses, _state);
14203  }
14204  offs = 0;
14205  for(i=0; i<=df->nclasses-1; i++)
14206  {
14207  y->ptr.p_double[i] = 0;
14208  }
14209  for(i=0; i<=df->ntrees-1; i++)
14210  {
14211 
14212  /*
14213  * Process basic tree
14214  */
14215  dforest_dfprocessinternal(df, offs, x, y, _state);
14216 
14217  /*
14218  * Next tree
14219  */
14220  offs = offs+ae_round(df->trees.ptr.p_double[offs], _state);
14221  }
14222  v = (double)1/(double)df->ntrees;
14223  ae_v_muld(&y->ptr.p_double[0], 1, ae_v_len(0,df->nclasses-1), v);
14224 }
14225 
14226 
14227 /*************************************************************************
14228 'interactive' variant of DFProcess for languages like Python which support
14229 constructs like "Y = DFProcessI(DF,X)" and interactive mode of interpreter
14230 
14231 This function allocates new array on each call, so it is significantly
14232 slower than its 'non-interactive' counterpart, but it is more convenient
14233 when you call it from command line.
14234 
14235  -- ALGLIB --
14236  Copyright 28.02.2010 by Bochkanov Sergey
14237 *************************************************************************/
14238 void dfprocessi(decisionforest* df,
14239  /* Real */ ae_vector* x,
14240  /* Real */ ae_vector* y,
14241  ae_state *_state)
14242 {
14243 
14244  ae_vector_clear(y);
14245 
14246  dfprocess(df, x, y, _state);
14247 }
14248 
14249 
14250 /*************************************************************************
14251 Relative classification error on the test set
14252 
14253 INPUT PARAMETERS:
14254  DF - decision forest model
14255  XY - test set
14256  NPoints - test set size
14257 
14258 RESULT:
14259  percent of incorrectly classified cases.
14260  Zero if model solves regression task.
14261 
14262  -- ALGLIB --
14263  Copyright 16.02.2009 by Bochkanov Sergey
14264 *************************************************************************/
14265 double dfrelclserror(decisionforest* df,
14266  /* Real */ ae_matrix* xy,
14267  ae_int_t npoints,
14268  ae_state *_state)
14269 {
14270  double result;
14271 
14272 
14273  result = (double)dforest_dfclserror(df, xy, npoints, _state)/(double)npoints;
14274  return result;
14275 }
14276 
14277 
14278 /*************************************************************************
14279 Average cross-entropy (in bits per element) on the test set
14280 
14281 INPUT PARAMETERS:
14282  DF - decision forest model
14283  XY - test set
14284  NPoints - test set size
14285 
14286 RESULT:
14287  CrossEntropy/(NPoints*LN(2)).
14288  Zero if model solves regression task.
14289 
14290  -- ALGLIB --
14291  Copyright 16.02.2009 by Bochkanov Sergey
14292 *************************************************************************/
14293 double dfavgce(decisionforest* df,
14294  /* Real */ ae_matrix* xy,
14295  ae_int_t npoints,
14296  ae_state *_state)
14297 {
14298  ae_frame _frame_block;
14299  ae_vector x;
14300  ae_vector y;
14301  ae_int_t i;
14302  ae_int_t j;
14303  ae_int_t k;
14304  ae_int_t tmpi;
14305  double result;
14306 
14307  ae_frame_make(_state, &_frame_block);
14308  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
14309  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
14310 
14311  ae_vector_set_length(&x, df->nvars-1+1, _state);
14312  ae_vector_set_length(&y, df->nclasses-1+1, _state);
14313  result = 0;
14314  for(i=0; i<=npoints-1; i++)
14315  {
14316  ae_v_move(&x.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,df->nvars-1));
14317  dfprocess(df, &x, &y, _state);
14318  if( df->nclasses>1 )
14319  {
14320 
14321  /*
14322  * classification-specific code
14323  */
14324  k = ae_round(xy->ptr.pp_double[i][df->nvars], _state);
14325  tmpi = 0;
14326  for(j=1; j<=df->nclasses-1; j++)
14327  {
14328  if( ae_fp_greater(y.ptr.p_double[j],y.ptr.p_double[tmpi]) )
14329  {
14330  tmpi = j;
14331  }
14332  }
14333  if( ae_fp_neq(y.ptr.p_double[k],0) )
14334  {
14335  result = result-ae_log(y.ptr.p_double[k], _state);
14336  }
14337  else
14338  {
14339  result = result-ae_log(ae_minrealnumber, _state);
14340  }
14341  }
14342  }
14343  result = result/npoints;
14344  ae_frame_leave(_state);
14345  return result;
14346 }
14347 
14348 
14349 /*************************************************************************
14350 RMS error on the test set
14351 
14352 INPUT PARAMETERS:
14353  DF - decision forest model
14354  XY - test set
14355  NPoints - test set size
14356 
14357 RESULT:
14358  root mean square error.
14359  Its meaning for regression task is obvious. As for
14360  classification task, RMS error means error when estimating posterior
14361  probabilities.
14362 
14363  -- ALGLIB --
14364  Copyright 16.02.2009 by Bochkanov Sergey
14365 *************************************************************************/
14366 double dfrmserror(decisionforest* df,
14367  /* Real */ ae_matrix* xy,
14368  ae_int_t npoints,
14369  ae_state *_state)
14370 {
14371  ae_frame _frame_block;
14372  ae_vector x;
14373  ae_vector y;
14374  ae_int_t i;
14375  ae_int_t j;
14376  ae_int_t k;
14377  ae_int_t tmpi;
14378  double result;
14379 
14380  ae_frame_make(_state, &_frame_block);
14381  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
14382  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
14383 
14384  ae_vector_set_length(&x, df->nvars-1+1, _state);
14385  ae_vector_set_length(&y, df->nclasses-1+1, _state);
14386  result = 0;
14387  for(i=0; i<=npoints-1; i++)
14388  {
14389  ae_v_move(&x.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,df->nvars-1));
14390  dfprocess(df, &x, &y, _state);
14391  if( df->nclasses>1 )
14392  {
14393 
14394  /*
14395  * classification-specific code
14396  */
14397  k = ae_round(xy->ptr.pp_double[i][df->nvars], _state);
14398  tmpi = 0;
14399  for(j=1; j<=df->nclasses-1; j++)
14400  {
14401  if( ae_fp_greater(y.ptr.p_double[j],y.ptr.p_double[tmpi]) )
14402  {
14403  tmpi = j;
14404  }
14405  }
14406  for(j=0; j<=df->nclasses-1; j++)
14407  {
14408  if( j==k )
14409  {
14410  result = result+ae_sqr(y.ptr.p_double[j]-1, _state);
14411  }
14412  else
14413  {
14414  result = result+ae_sqr(y.ptr.p_double[j], _state);
14415  }
14416  }
14417  }
14418  else
14419  {
14420 
14421  /*
14422  * regression-specific code
14423  */
14424  result = result+ae_sqr(y.ptr.p_double[0]-xy->ptr.pp_double[i][df->nvars], _state);
14425  }
14426  }
14427  result = ae_sqrt(result/(npoints*df->nclasses), _state);
14428  ae_frame_leave(_state);
14429  return result;
14430 }
14431 
14432 
14433 /*************************************************************************
14434 Average error on the test set
14435 
14436 INPUT PARAMETERS:
14437  DF - decision forest model
14438  XY - test set
14439  NPoints - test set size
14440 
14441 RESULT:
14442  Its meaning for regression task is obvious. As for
14443  classification task, it means average error when estimating posterior
14444  probabilities.
14445 
14446  -- ALGLIB --
14447  Copyright 16.02.2009 by Bochkanov Sergey
14448 *************************************************************************/
14449 double dfavgerror(decisionforest* df,
14450  /* Real */ ae_matrix* xy,
14451  ae_int_t npoints,
14452  ae_state *_state)
14453 {
14454  ae_frame _frame_block;
14455  ae_vector x;
14456  ae_vector y;
14457  ae_int_t i;
14458  ae_int_t j;
14459  ae_int_t k;
14460  double result;
14461 
14462  ae_frame_make(_state, &_frame_block);
14463  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
14464  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
14465 
14466  ae_vector_set_length(&x, df->nvars-1+1, _state);
14467  ae_vector_set_length(&y, df->nclasses-1+1, _state);
14468  result = 0;
14469  for(i=0; i<=npoints-1; i++)
14470  {
14471  ae_v_move(&x.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,df->nvars-1));
14472  dfprocess(df, &x, &y, _state);
14473  if( df->nclasses>1 )
14474  {
14475 
14476  /*
14477  * classification-specific code
14478  */
14479  k = ae_round(xy->ptr.pp_double[i][df->nvars], _state);
14480  for(j=0; j<=df->nclasses-1; j++)
14481  {
14482  if( j==k )
14483  {
14484  result = result+ae_fabs(y.ptr.p_double[j]-1, _state);
14485  }
14486  else
14487  {
14488  result = result+ae_fabs(y.ptr.p_double[j], _state);
14489  }
14490  }
14491  }
14492  else
14493  {
14494 
14495  /*
14496  * regression-specific code
14497  */
14498  result = result+ae_fabs(y.ptr.p_double[0]-xy->ptr.pp_double[i][df->nvars], _state);
14499  }
14500  }
14501  result = result/(npoints*df->nclasses);
14502  ae_frame_leave(_state);
14503  return result;
14504 }
14505 
14506 
14507 /*************************************************************************
14508 Average relative error on the test set
14509 
14510 INPUT PARAMETERS:
14511  DF - decision forest model
14512  XY - test set
14513  NPoints - test set size
14514 
14515 RESULT:
14516  Its meaning for regression task is obvious. As for
14517  classification task, it means average relative error when estimating
14518  posterior probability of belonging to the correct class.
14519 
14520  -- ALGLIB --
14521  Copyright 16.02.2009 by Bochkanov Sergey
14522 *************************************************************************/
14523 double dfavgrelerror(decisionforest* df,
14524  /* Real */ ae_matrix* xy,
14525  ae_int_t npoints,
14526  ae_state *_state)
14527 {
14528  ae_frame _frame_block;
14529  ae_vector x;
14530  ae_vector y;
14531  ae_int_t relcnt;
14532  ae_int_t i;
14533  ae_int_t j;
14534  ae_int_t k;
14535  double result;
14536 
14537  ae_frame_make(_state, &_frame_block);
14538  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
14539  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
14540 
14541  ae_vector_set_length(&x, df->nvars-1+1, _state);
14542  ae_vector_set_length(&y, df->nclasses-1+1, _state);
14543  result = 0;
14544  relcnt = 0;
14545  for(i=0; i<=npoints-1; i++)
14546  {
14547  ae_v_move(&x.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,df->nvars-1));
14548  dfprocess(df, &x, &y, _state);
14549  if( df->nclasses>1 )
14550  {
14551 
14552  /*
14553  * classification-specific code
14554  */
14555  k = ae_round(xy->ptr.pp_double[i][df->nvars], _state);
14556  for(j=0; j<=df->nclasses-1; j++)
14557  {
14558  if( j==k )
14559  {
14560  result = result+ae_fabs(y.ptr.p_double[j]-1, _state);
14561  relcnt = relcnt+1;
14562  }
14563  }
14564  }
14565  else
14566  {
14567 
14568  /*
14569  * regression-specific code
14570  */
14571  if( ae_fp_neq(xy->ptr.pp_double[i][df->nvars],0) )
14572  {
14573  result = result+ae_fabs((y.ptr.p_double[0]-xy->ptr.pp_double[i][df->nvars])/xy->ptr.pp_double[i][df->nvars], _state);
14574  relcnt = relcnt+1;
14575  }
14576  }
14577  }
14578  if( relcnt>0 )
14579  {
14580  result = result/relcnt;
14581  }
14582  ae_frame_leave(_state);
14583  return result;
14584 }
14585 
14586 
14587 /*************************************************************************
14588 Copying of DecisionForest strucure
14589 
14590 INPUT PARAMETERS:
14591  DF1 - original
14592 
14593 OUTPUT PARAMETERS:
14594  DF2 - copy
14595 
14596  -- ALGLIB --
14597  Copyright 13.02.2009 by Bochkanov Sergey
14598 *************************************************************************/
14599 void dfcopy(decisionforest* df1, decisionforest* df2, ae_state *_state)
14600 {
14601 
14602  _decisionforest_clear(df2);
14603 
14604  df2->nvars = df1->nvars;
14605  df2->nclasses = df1->nclasses;
14606  df2->ntrees = df1->ntrees;
14607  df2->bufsize = df1->bufsize;
14608  ae_vector_set_length(&df2->trees, df1->bufsize-1+1, _state);
14609  ae_v_move(&df2->trees.ptr.p_double[0], 1, &df1->trees.ptr.p_double[0], 1, ae_v_len(0,df1->bufsize-1));
14610 }
14611 
14612 
14613 /*************************************************************************
14614 Serializer: allocation
14615 
14616  -- ALGLIB --
14617  Copyright 14.03.2011 by Bochkanov Sergey
14618 *************************************************************************/
14619 void dfalloc(ae_serializer* s, decisionforest* forest, ae_state *_state)
14620 {
14621 
14622 
14623  ae_serializer_alloc_entry(s);
14624  ae_serializer_alloc_entry(s);
14625  ae_serializer_alloc_entry(s);
14626  ae_serializer_alloc_entry(s);
14627  ae_serializer_alloc_entry(s);
14628  ae_serializer_alloc_entry(s);
14629  allocrealarray(s, &forest->trees, forest->bufsize, _state);
14630 }
14631 
14632 
14633 /*************************************************************************
14634 Serializer: serialization
14635 
14636  -- ALGLIB --
14637  Copyright 14.03.2011 by Bochkanov Sergey
14638 *************************************************************************/
14639 void dfserialize(ae_serializer* s,
14640  decisionforest* forest,
14641  ae_state *_state)
14642 {
14643 
14644 
14645  ae_serializer_serialize_int(s, getrdfserializationcode(_state), _state);
14646  ae_serializer_serialize_int(s, dforest_dffirstversion, _state);
14647  ae_serializer_serialize_int(s, forest->nvars, _state);
14648  ae_serializer_serialize_int(s, forest->nclasses, _state);
14649  ae_serializer_serialize_int(s, forest->ntrees, _state);
14650  ae_serializer_serialize_int(s, forest->bufsize, _state);
14651  serializerealarray(s, &forest->trees, forest->bufsize, _state);
14652 }
14653 
14654 
14655 /*************************************************************************
14656 Serializer: unserialization
14657 
14658  -- ALGLIB --
14659  Copyright 14.03.2011 by Bochkanov Sergey
14660 *************************************************************************/
14661 void dfunserialize(ae_serializer* s,
14662  decisionforest* forest,
14663  ae_state *_state)
14664 {
14665  ae_int_t i0;
14666  ae_int_t i1;
14667 
14668  _decisionforest_clear(forest);
14669 
14670 
14671  /*
14672  * check correctness of header
14673  */
14674  ae_serializer_unserialize_int(s, &i0, _state);
14675  ae_assert(i0==getrdfserializationcode(_state), "DFUnserialize: stream header corrupted", _state);
14676  ae_serializer_unserialize_int(s, &i1, _state);
14677  ae_assert(i1==dforest_dffirstversion, "DFUnserialize: stream header corrupted", _state);
14678 
14679  /*
14680  * Unserialize data
14681  */
14682  ae_serializer_unserialize_int(s, &forest->nvars, _state);
14683  ae_serializer_unserialize_int(s, &forest->nclasses, _state);
14684  ae_serializer_unserialize_int(s, &forest->ntrees, _state);
14685  ae_serializer_unserialize_int(s, &forest->bufsize, _state);
14686  unserializerealarray(s, &forest->trees, _state);
14687 }
14688 
14689 
14690 /*************************************************************************
14691 Classification error
14692 *************************************************************************/
14693 static ae_int_t dforest_dfclserror(decisionforest* df,
14694  /* Real */ ae_matrix* xy,
14695  ae_int_t npoints,
14696  ae_state *_state)
14697 {
14698  ae_frame _frame_block;
14699  ae_vector x;
14700  ae_vector y;
14701  ae_int_t i;
14702  ae_int_t j;
14703  ae_int_t k;
14704  ae_int_t tmpi;
14705  ae_int_t result;
14706 
14707  ae_frame_make(_state, &_frame_block);
14708  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
14709  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
14710 
14711  if( df->nclasses<=1 )
14712  {
14713  result = 0;
14714  ae_frame_leave(_state);
14715  return result;
14716  }
14717  ae_vector_set_length(&x, df->nvars-1+1, _state);
14718  ae_vector_set_length(&y, df->nclasses-1+1, _state);
14719  result = 0;
14720  for(i=0; i<=npoints-1; i++)
14721  {
14722  ae_v_move(&x.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,df->nvars-1));
14723  dfprocess(df, &x, &y, _state);
14724  k = ae_round(xy->ptr.pp_double[i][df->nvars], _state);
14725  tmpi = 0;
14726  for(j=1; j<=df->nclasses-1; j++)
14727  {
14728  if( ae_fp_greater(y.ptr.p_double[j],y.ptr.p_double[tmpi]) )
14729  {
14730  tmpi = j;
14731  }
14732  }
14733  if( tmpi!=k )
14734  {
14735  result = result+1;
14736  }
14737  }
14738  ae_frame_leave(_state);
14739  return result;
14740 }
14741 
14742 
14743 /*************************************************************************
14744 Internal subroutine for processing one decision tree starting at Offs
14745 *************************************************************************/
14746 static void dforest_dfprocessinternal(decisionforest* df,
14747  ae_int_t offs,
14748  /* Real */ ae_vector* x,
14749  /* Real */ ae_vector* y,
14750  ae_state *_state)
14751 {
14752  ae_int_t k;
14753  ae_int_t idx;
14754 
14755 
14756 
14757  /*
14758  * Set pointer to the root
14759  */
14760  k = offs+1;
14761 
14762  /*
14763  * Navigate through the tree
14764  */
14765  for(;;)
14766  {
14767  if( ae_fp_eq(df->trees.ptr.p_double[k],-1) )
14768  {
14769  if( df->nclasses==1 )
14770  {
14771  y->ptr.p_double[0] = y->ptr.p_double[0]+df->trees.ptr.p_double[k+1];
14772  }
14773  else
14774  {
14775  idx = ae_round(df->trees.ptr.p_double[k+1], _state);
14776  y->ptr.p_double[idx] = y->ptr.p_double[idx]+1;
14777  }
14778  break;
14779  }
14780  if( ae_fp_less(x->ptr.p_double[ae_round(df->trees.ptr.p_double[k], _state)],df->trees.ptr.p_double[k+1]) )
14781  {
14782  k = k+dforest_innernodewidth;
14783  }
14784  else
14785  {
14786  k = offs+ae_round(df->trees.ptr.p_double[k+2], _state);
14787  }
14788  }
14789 }
14790 
14791 
14792 /*************************************************************************
14793 Builds one decision tree. Just a wrapper for the DFBuildTreeRec.
14794 *************************************************************************/
14795 static void dforest_dfbuildtree(/* Real */ ae_matrix* xy,
14796  ae_int_t npoints,
14797  ae_int_t nvars,
14798  ae_int_t nclasses,
14799  ae_int_t nfeatures,
14800  ae_int_t nvarsinpool,
14801  ae_int_t flags,
14802  dfinternalbuffers* bufs,
14803  hqrndstate* rs,
14804  ae_state *_state)
14805 {
14806  ae_int_t numprocessed;
14807  ae_int_t i;
14808 
14809 
14810  ae_assert(npoints>0, "Assertion failed", _state);
14811 
14812  /*
14813  * Prepare IdxBuf. It stores indices of the training set elements.
14814  * When training set is being split, contents of IdxBuf is
14815  * correspondingly reordered so we can know which elements belong
14816  * to which branch of decision tree.
14817  */
14818  for(i=0; i<=npoints-1; i++)
14819  {
14820  bufs->idxbuf.ptr.p_int[i] = i;
14821  }
14822 
14823  /*
14824  * Recursive procedure
14825  */
14826  numprocessed = 1;
14827  dforest_dfbuildtreerec(xy, npoints, nvars, nclasses, nfeatures, nvarsinpool, flags, &numprocessed, 0, npoints-1, bufs, rs, _state);
14828  bufs->treebuf.ptr.p_double[0] = numprocessed;
14829 }
14830 
14831 
14832 /*************************************************************************
14833 Builds one decision tree (internal recursive subroutine)
14834 
14835 Parameters:
14836  TreeBuf - large enough array, at least TreeSize
14837  IdxBuf - at least NPoints elements
14838  TmpBufR - at least NPoints
14839  TmpBufR2 - at least NPoints
14840  TmpBufI - at least NPoints
14841  TmpBufI2 - at least NPoints+1
14842 *************************************************************************/
14843 static void dforest_dfbuildtreerec(/* Real */ ae_matrix* xy,
14844  ae_int_t npoints,
14845  ae_int_t nvars,
14846  ae_int_t nclasses,
14847  ae_int_t nfeatures,
14848  ae_int_t nvarsinpool,
14849  ae_int_t flags,
14850  ae_int_t* numprocessed,
14851  ae_int_t idx1,
14852  ae_int_t idx2,
14853  dfinternalbuffers* bufs,
14854  hqrndstate* rs,
14855  ae_state *_state)
14856 {
14857  ae_int_t i;
14858  ae_int_t j;
14859  ae_int_t k;
14860  ae_bool bflag;
14861  ae_int_t i1;
14862  ae_int_t i2;
14863  ae_int_t info;
14864  double sl;
14865  double sr;
14866  double w;
14867  ae_int_t idxbest;
14868  double ebest;
14869  double tbest;
14870  ae_int_t varcur;
14871  double s;
14872  double v;
14873  double v1;
14874  double v2;
14875  double threshold;
14876  ae_int_t oldnp;
14877  double currms;
14878  ae_bool useevs;
14879 
14880 
14881 
14882  /*
14883  * these initializers are not really necessary,
14884  * but without them compiler complains about uninitialized locals
14885  */
14886  tbest = 0;
14887 
14888  /*
14889  * Prepare
14890  */
14891  ae_assert(npoints>0, "Assertion failed", _state);
14892  ae_assert(idx2>=idx1, "Assertion failed", _state);
14893  useevs = flags/dforest_dfuseevs%2!=0;
14894 
14895  /*
14896  * Leaf node
14897  */
14898  if( idx2==idx1 )
14899  {
14900  bufs->treebuf.ptr.p_double[*numprocessed] = -1;
14901  bufs->treebuf.ptr.p_double[*numprocessed+1] = xy->ptr.pp_double[bufs->idxbuf.ptr.p_int[idx1]][nvars];
14902  *numprocessed = *numprocessed+dforest_leafnodewidth;
14903  return;
14904  }
14905 
14906  /*
14907  * Non-leaf node.
14908  * Select random variable, prepare split:
14909  * 1. prepare default solution - no splitting, class at random
14910  * 2. investigate possible splits, compare with default/best
14911  */
14912  idxbest = -1;
14913  if( nclasses>1 )
14914  {
14915 
14916  /*
14917  * default solution for classification
14918  */
14919  for(i=0; i<=nclasses-1; i++)
14920  {
14921  bufs->classibuf.ptr.p_int[i] = 0;
14922  }
14923  s = idx2-idx1+1;
14924  for(i=idx1; i<=idx2; i++)
14925  {
14926  j = ae_round(xy->ptr.pp_double[bufs->idxbuf.ptr.p_int[i]][nvars], _state);
14927  bufs->classibuf.ptr.p_int[j] = bufs->classibuf.ptr.p_int[j]+1;
14928  }
14929  ebest = 0;
14930  for(i=0; i<=nclasses-1; i++)
14931  {
14932  ebest = ebest+bufs->classibuf.ptr.p_int[i]*ae_sqr(1-bufs->classibuf.ptr.p_int[i]/s, _state)+(s-bufs->classibuf.ptr.p_int[i])*ae_sqr(bufs->classibuf.ptr.p_int[i]/s, _state);
14933  }
14934  ebest = ae_sqrt(ebest/(nclasses*(idx2-idx1+1)), _state);
14935  }
14936  else
14937  {
14938 
14939  /*
14940  * default solution for regression
14941  */
14942  v = 0;
14943  for(i=idx1; i<=idx2; i++)
14944  {
14945  v = v+xy->ptr.pp_double[bufs->idxbuf.ptr.p_int[i]][nvars];
14946  }
14947  v = v/(idx2-idx1+1);
14948  ebest = 0;
14949  for(i=idx1; i<=idx2; i++)
14950  {
14951  ebest = ebest+ae_sqr(xy->ptr.pp_double[bufs->idxbuf.ptr.p_int[i]][nvars]-v, _state);
14952  }
14953  ebest = ae_sqrt(ebest/(idx2-idx1+1), _state);
14954  }
14955  i = 0;
14956  while(i<=ae_minint(nfeatures, nvarsinpool, _state)-1)
14957  {
14958 
14959  /*
14960  * select variables from pool
14961  */
14962  j = i+hqrnduniformi(rs, nvarsinpool-i, _state);
14963  k = bufs->varpool.ptr.p_int[i];
14964  bufs->varpool.ptr.p_int[i] = bufs->varpool.ptr.p_int[j];
14965  bufs->varpool.ptr.p_int[j] = k;
14966  varcur = bufs->varpool.ptr.p_int[i];
14967 
14968  /*
14969  * load variable values to working array
14970  *
14971  * apply EVS preprocessing: if all variable values are same,
14972  * variable is excluded from pool.
14973  *
14974  * This is necessary for binary pre-splits (see later) to work.
14975  */
14976  for(j=idx1; j<=idx2; j++)
14977  {
14978  bufs->tmpbufr.ptr.p_double[j-idx1] = xy->ptr.pp_double[bufs->idxbuf.ptr.p_int[j]][varcur];
14979  }
14980  if( useevs )
14981  {
14982  bflag = ae_false;
14983  v = bufs->tmpbufr.ptr.p_double[0];
14984  for(j=0; j<=idx2-idx1; j++)
14985  {
14986  if( ae_fp_neq(bufs->tmpbufr.ptr.p_double[j],v) )
14987  {
14988  bflag = ae_true;
14989  break;
14990  }
14991  }
14992  if( !bflag )
14993  {
14994 
14995  /*
14996  * exclude variable from pool,
14997  * go to the next iteration.
14998  * I is not increased.
14999  */
15000  k = bufs->varpool.ptr.p_int[i];
15001  bufs->varpool.ptr.p_int[i] = bufs->varpool.ptr.p_int[nvarsinpool-1];
15002  bufs->varpool.ptr.p_int[nvarsinpool-1] = k;
15003  nvarsinpool = nvarsinpool-1;
15004  continue;
15005  }
15006  }
15007 
15008  /*
15009  * load labels to working array
15010  */
15011  if( nclasses>1 )
15012  {
15013  for(j=idx1; j<=idx2; j++)
15014  {
15015  bufs->tmpbufi.ptr.p_int[j-idx1] = ae_round(xy->ptr.pp_double[bufs->idxbuf.ptr.p_int[j]][nvars], _state);
15016  }
15017  }
15018  else
15019  {
15020  for(j=idx1; j<=idx2; j++)
15021  {
15022  bufs->tmpbufr2.ptr.p_double[j-idx1] = xy->ptr.pp_double[bufs->idxbuf.ptr.p_int[j]][nvars];
15023  }
15024  }
15025 
15026  /*
15027  * calculate split
15028  */
15029  if( useevs&&bufs->evsbin.ptr.p_bool[varcur] )
15030  {
15031 
15032  /*
15033  * Pre-calculated splits for binary variables.
15034  * Threshold is already known, just calculate RMS error
15035  */
15036  threshold = bufs->evssplits.ptr.p_double[varcur];
15037  if( nclasses>1 )
15038  {
15039 
15040  /*
15041  * classification-specific code
15042  */
15043  for(j=0; j<=2*nclasses-1; j++)
15044  {
15045  bufs->classibuf.ptr.p_int[j] = 0;
15046  }
15047  sl = 0;
15048  sr = 0;
15049  for(j=0; j<=idx2-idx1; j++)
15050  {
15051  k = bufs->tmpbufi.ptr.p_int[j];
15052  if( ae_fp_less(bufs->tmpbufr.ptr.p_double[j],threshold) )
15053  {
15054  bufs->classibuf.ptr.p_int[k] = bufs->classibuf.ptr.p_int[k]+1;
15055  sl = sl+1;
15056  }
15057  else
15058  {
15059  bufs->classibuf.ptr.p_int[k+nclasses] = bufs->classibuf.ptr.p_int[k+nclasses]+1;
15060  sr = sr+1;
15061  }
15062  }
15063  ae_assert(ae_fp_neq(sl,0)&&ae_fp_neq(sr,0), "DFBuildTreeRec: something strange!", _state);
15064  currms = 0;
15065  for(j=0; j<=nclasses-1; j++)
15066  {
15067  w = bufs->classibuf.ptr.p_int[j];
15068  currms = currms+w*ae_sqr(w/sl-1, _state);
15069  currms = currms+(sl-w)*ae_sqr(w/sl, _state);
15070  w = bufs->classibuf.ptr.p_int[nclasses+j];
15071  currms = currms+w*ae_sqr(w/sr-1, _state);
15072  currms = currms+(sr-w)*ae_sqr(w/sr, _state);
15073  }
15074  currms = ae_sqrt(currms/(nclasses*(idx2-idx1+1)), _state);
15075  }
15076  else
15077  {
15078 
15079  /*
15080  * regression-specific code
15081  */
15082  sl = 0;
15083  sr = 0;
15084  v1 = 0;
15085  v2 = 0;
15086  for(j=0; j<=idx2-idx1; j++)
15087  {
15088  if( ae_fp_less(bufs->tmpbufr.ptr.p_double[j],threshold) )
15089  {
15090  v1 = v1+bufs->tmpbufr2.ptr.p_double[j];
15091  sl = sl+1;
15092  }
15093  else
15094  {
15095  v2 = v2+bufs->tmpbufr2.ptr.p_double[j];
15096  sr = sr+1;
15097  }
15098  }
15099  ae_assert(ae_fp_neq(sl,0)&&ae_fp_neq(sr,0), "DFBuildTreeRec: something strange!", _state);
15100  v1 = v1/sl;
15101  v2 = v2/sr;
15102  currms = 0;
15103  for(j=0; j<=idx2-idx1; j++)
15104  {
15105  if( ae_fp_less(bufs->tmpbufr.ptr.p_double[j],threshold) )
15106  {
15107  currms = currms+ae_sqr(v1-bufs->tmpbufr2.ptr.p_double[j], _state);
15108  }
15109  else
15110  {
15111  currms = currms+ae_sqr(v2-bufs->tmpbufr2.ptr.p_double[j], _state);
15112  }
15113  }
15114  currms = ae_sqrt(currms/(idx2-idx1+1), _state);
15115  }
15116  info = 1;
15117  }
15118  else
15119  {
15120 
15121  /*
15122  * Generic splits
15123  */
15124  if( nclasses>1 )
15125  {
15126  dforest_dfsplitc(&bufs->tmpbufr, &bufs->tmpbufi, &bufs->classibuf, idx2-idx1+1, nclasses, dforest_dfusestrongsplits, &info, &threshold, &currms, &bufs->sortrbuf, &bufs->sortibuf, _state);
15127  }
15128  else
15129  {
15130  dforest_dfsplitr(&bufs->tmpbufr, &bufs->tmpbufr2, idx2-idx1+1, dforest_dfusestrongsplits, &info, &threshold, &currms, &bufs->sortrbuf, &bufs->sortrbuf2, _state);
15131  }
15132  }
15133  if( info>0 )
15134  {
15135  if( ae_fp_less_eq(currms,ebest) )
15136  {
15137  ebest = currms;
15138  idxbest = varcur;
15139  tbest = threshold;
15140  }
15141  }
15142 
15143  /*
15144  * Next iteration
15145  */
15146  i = i+1;
15147  }
15148 
15149  /*
15150  * to split or not to split
15151  */
15152  if( idxbest<0 )
15153  {
15154 
15155  /*
15156  * All values are same, cannot split.
15157  */
15158  bufs->treebuf.ptr.p_double[*numprocessed] = -1;
15159  if( nclasses>1 )
15160  {
15161 
15162  /*
15163  * Select random class label (randomness allows us to
15164  * approximate distribution of the classes)
15165  */
15166  bufs->treebuf.ptr.p_double[*numprocessed+1] = ae_round(xy->ptr.pp_double[bufs->idxbuf.ptr.p_int[idx1+hqrnduniformi(rs, idx2-idx1+1, _state)]][nvars], _state);
15167  }
15168  else
15169  {
15170 
15171  /*
15172  * Select average (for regression task).
15173  */
15174  v = 0;
15175  for(i=idx1; i<=idx2; i++)
15176  {
15177  v = v+xy->ptr.pp_double[bufs->idxbuf.ptr.p_int[i]][nvars]/(idx2-idx1+1);
15178  }
15179  bufs->treebuf.ptr.p_double[*numprocessed+1] = v;
15180  }
15181  *numprocessed = *numprocessed+dforest_leafnodewidth;
15182  }
15183  else
15184  {
15185 
15186  /*
15187  * we can split
15188  */
15189  bufs->treebuf.ptr.p_double[*numprocessed] = idxbest;
15190  bufs->treebuf.ptr.p_double[*numprocessed+1] = tbest;
15191  i1 = idx1;
15192  i2 = idx2;
15193  while(i1<=i2)
15194  {
15195 
15196  /*
15197  * Reorder indices so that left partition is in [Idx1..I1-1],
15198  * and right partition is in [I2+1..Idx2]
15199  */
15200  if( ae_fp_less(xy->ptr.pp_double[bufs->idxbuf.ptr.p_int[i1]][idxbest],tbest) )
15201  {
15202  i1 = i1+1;
15203  continue;
15204  }
15205  if( ae_fp_greater_eq(xy->ptr.pp_double[bufs->idxbuf.ptr.p_int[i2]][idxbest],tbest) )
15206  {
15207  i2 = i2-1;
15208  continue;
15209  }
15210  j = bufs->idxbuf.ptr.p_int[i1];
15211  bufs->idxbuf.ptr.p_int[i1] = bufs->idxbuf.ptr.p_int[i2];
15212  bufs->idxbuf.ptr.p_int[i2] = j;
15213  i1 = i1+1;
15214  i2 = i2-1;
15215  }
15216  oldnp = *numprocessed;
15217  *numprocessed = *numprocessed+dforest_innernodewidth;
15218  dforest_dfbuildtreerec(xy, npoints, nvars, nclasses, nfeatures, nvarsinpool, flags, numprocessed, idx1, i1-1, bufs, rs, _state);
15219  bufs->treebuf.ptr.p_double[oldnp+2] = *numprocessed;
15220  dforest_dfbuildtreerec(xy, npoints, nvars, nclasses, nfeatures, nvarsinpool, flags, numprocessed, i2+1, idx2, bufs, rs, _state);
15221  }
15222 }
15223 
15224 
15225 /*************************************************************************
15226 Makes split on attribute
15227 *************************************************************************/
15228 static void dforest_dfsplitc(/* Real */ ae_vector* x,
15229  /* Integer */ ae_vector* c,
15230  /* Integer */ ae_vector* cntbuf,
15231  ae_int_t n,
15232  ae_int_t nc,
15233  ae_int_t flags,
15234  ae_int_t* info,
15235  double* threshold,
15236  double* e,
15237  /* Real */ ae_vector* sortrbuf,
15238  /* Integer */ ae_vector* sortibuf,
15239  ae_state *_state)
15240 {
15241  ae_int_t i;
15242  ae_int_t neq;
15243  ae_int_t nless;
15244  ae_int_t ngreater;
15245  ae_int_t q;
15246  ae_int_t qmin;
15247  ae_int_t qmax;
15248  ae_int_t qcnt;
15249  double cursplit;
15250  ae_int_t nleft;
15251  double v;
15252  double cure;
15253  double w;
15254  double sl;
15255  double sr;
15256 
15257  *info = 0;
15258  *threshold = 0;
15259  *e = 0;
15260 
15261  tagsortfasti(x, c, sortrbuf, sortibuf, n, _state);
15262  *e = ae_maxrealnumber;
15263  *threshold = 0.5*(x->ptr.p_double[0]+x->ptr.p_double[n-1]);
15264  *info = -3;
15265  if( flags/dforest_dfusestrongsplits%2==0 )
15266  {
15267 
15268  /*
15269  * weak splits, split at half
15270  */
15271  qcnt = 2;
15272  qmin = 1;
15273  qmax = 1;
15274  }
15275  else
15276  {
15277 
15278  /*
15279  * strong splits: choose best quartile
15280  */
15281  qcnt = 4;
15282  qmin = 1;
15283  qmax = 3;
15284  }
15285  for(q=qmin; q<=qmax; q++)
15286  {
15287  cursplit = x->ptr.p_double[n*q/qcnt];
15288  neq = 0;
15289  nless = 0;
15290  ngreater = 0;
15291  for(i=0; i<=n-1; i++)
15292  {
15293  if( ae_fp_less(x->ptr.p_double[i],cursplit) )
15294  {
15295  nless = nless+1;
15296  }
15297  if( ae_fp_eq(x->ptr.p_double[i],cursplit) )
15298  {
15299  neq = neq+1;
15300  }
15301  if( ae_fp_greater(x->ptr.p_double[i],cursplit) )
15302  {
15303  ngreater = ngreater+1;
15304  }
15305  }
15306  ae_assert(neq!=0, "DFSplitR: NEq=0, something strange!!!", _state);
15307  if( nless!=0||ngreater!=0 )
15308  {
15309 
15310  /*
15311  * set threshold between two partitions, with
15312  * some tweaking to avoid problems with floating point
15313  * arithmetics.
15314  *
15315  * The problem is that when you calculates C = 0.5*(A+B) there
15316  * can be no C which lies strictly between A and B (for example,
15317  * there is no floating point number which is
15318  * greater than 1 and less than 1+eps). In such situations
15319  * we choose right side as threshold (remember that
15320  * points which lie on threshold falls to the right side).
15321  */
15322  if( nless<ngreater )
15323  {
15324  cursplit = 0.5*(x->ptr.p_double[nless+neq-1]+x->ptr.p_double[nless+neq]);
15325  nleft = nless+neq;
15326  if( ae_fp_less_eq(cursplit,x->ptr.p_double[nless+neq-1]) )
15327  {
15328  cursplit = x->ptr.p_double[nless+neq];
15329  }
15330  }
15331  else
15332  {
15333  cursplit = 0.5*(x->ptr.p_double[nless-1]+x->ptr.p_double[nless]);
15334  nleft = nless;
15335  if( ae_fp_less_eq(cursplit,x->ptr.p_double[nless-1]) )
15336  {
15337  cursplit = x->ptr.p_double[nless];
15338  }
15339  }
15340  *info = 1;
15341  cure = 0;
15342  for(i=0; i<=2*nc-1; i++)
15343  {
15344  cntbuf->ptr.p_int[i] = 0;
15345  }
15346  for(i=0; i<=nleft-1; i++)
15347  {
15348  cntbuf->ptr.p_int[c->ptr.p_int[i]] = cntbuf->ptr.p_int[c->ptr.p_int[i]]+1;
15349  }
15350  for(i=nleft; i<=n-1; i++)
15351  {
15352  cntbuf->ptr.p_int[nc+c->ptr.p_int[i]] = cntbuf->ptr.p_int[nc+c->ptr.p_int[i]]+1;
15353  }
15354  sl = nleft;
15355  sr = n-nleft;
15356  v = 0;
15357  for(i=0; i<=nc-1; i++)
15358  {
15359  w = cntbuf->ptr.p_int[i];
15360  v = v+w*ae_sqr(w/sl-1, _state);
15361  v = v+(sl-w)*ae_sqr(w/sl, _state);
15362  w = cntbuf->ptr.p_int[nc+i];
15363  v = v+w*ae_sqr(w/sr-1, _state);
15364  v = v+(sr-w)*ae_sqr(w/sr, _state);
15365  }
15366  cure = ae_sqrt(v/(nc*n), _state);
15367  if( ae_fp_less(cure,*e) )
15368  {
15369  *threshold = cursplit;
15370  *e = cure;
15371  }
15372  }
15373  }
15374 }
15375 
15376 
15377 /*************************************************************************
15378 Makes split on attribute
15379 *************************************************************************/
15380 static void dforest_dfsplitr(/* Real */ ae_vector* x,
15381  /* Real */ ae_vector* y,
15382  ae_int_t n,
15383  ae_int_t flags,
15384  ae_int_t* info,
15385  double* threshold,
15386  double* e,
15387  /* Real */ ae_vector* sortrbuf,
15388  /* Real */ ae_vector* sortrbuf2,
15389  ae_state *_state)
15390 {
15391  ae_int_t i;
15392  ae_int_t neq;
15393  ae_int_t nless;
15394  ae_int_t ngreater;
15395  ae_int_t q;
15396  ae_int_t qmin;
15397  ae_int_t qmax;
15398  ae_int_t qcnt;
15399  double cursplit;
15400  ae_int_t nleft;
15401  double v;
15402  double cure;
15403 
15404  *info = 0;
15405  *threshold = 0;
15406  *e = 0;
15407 
15408  tagsortfastr(x, y, sortrbuf, sortrbuf2, n, _state);
15409  *e = ae_maxrealnumber;
15410  *threshold = 0.5*(x->ptr.p_double[0]+x->ptr.p_double[n-1]);
15411  *info = -3;
15412  if( flags/dforest_dfusestrongsplits%2==0 )
15413  {
15414 
15415  /*
15416  * weak splits, split at half
15417  */
15418  qcnt = 2;
15419  qmin = 1;
15420  qmax = 1;
15421  }
15422  else
15423  {
15424 
15425  /*
15426  * strong splits: choose best quartile
15427  */
15428  qcnt = 4;
15429  qmin = 1;
15430  qmax = 3;
15431  }
15432  for(q=qmin; q<=qmax; q++)
15433  {
15434  cursplit = x->ptr.p_double[n*q/qcnt];
15435  neq = 0;
15436  nless = 0;
15437  ngreater = 0;
15438  for(i=0; i<=n-1; i++)
15439  {
15440  if( ae_fp_less(x->ptr.p_double[i],cursplit) )
15441  {
15442  nless = nless+1;
15443  }
15444  if( ae_fp_eq(x->ptr.p_double[i],cursplit) )
15445  {
15446  neq = neq+1;
15447  }
15448  if( ae_fp_greater(x->ptr.p_double[i],cursplit) )
15449  {
15450  ngreater = ngreater+1;
15451  }
15452  }
15453  ae_assert(neq!=0, "DFSplitR: NEq=0, something strange!!!", _state);
15454  if( nless!=0||ngreater!=0 )
15455  {
15456 
15457  /*
15458  * set threshold between two partitions, with
15459  * some tweaking to avoid problems with floating point
15460  * arithmetics.
15461  *
15462  * The problem is that when you calculates C = 0.5*(A+B) there
15463  * can be no C which lies strictly between A and B (for example,
15464  * there is no floating point number which is
15465  * greater than 1 and less than 1+eps). In such situations
15466  * we choose right side as threshold (remember that
15467  * points which lie on threshold falls to the right side).
15468  */
15469  if( nless<ngreater )
15470  {
15471  cursplit = 0.5*(x->ptr.p_double[nless+neq-1]+x->ptr.p_double[nless+neq]);
15472  nleft = nless+neq;
15473  if( ae_fp_less_eq(cursplit,x->ptr.p_double[nless+neq-1]) )
15474  {
15475  cursplit = x->ptr.p_double[nless+neq];
15476  }
15477  }
15478  else
15479  {
15480  cursplit = 0.5*(x->ptr.p_double[nless-1]+x->ptr.p_double[nless]);
15481  nleft = nless;
15482  if( ae_fp_less_eq(cursplit,x->ptr.p_double[nless-1]) )
15483  {
15484  cursplit = x->ptr.p_double[nless];
15485  }
15486  }
15487  *info = 1;
15488  cure = 0;
15489  v = 0;
15490  for(i=0; i<=nleft-1; i++)
15491  {
15492  v = v+y->ptr.p_double[i];
15493  }
15494  v = v/nleft;
15495  for(i=0; i<=nleft-1; i++)
15496  {
15497  cure = cure+ae_sqr(y->ptr.p_double[i]-v, _state);
15498  }
15499  v = 0;
15500  for(i=nleft; i<=n-1; i++)
15501  {
15502  v = v+y->ptr.p_double[i];
15503  }
15504  v = v/(n-nleft);
15505  for(i=nleft; i<=n-1; i++)
15506  {
15507  cure = cure+ae_sqr(y->ptr.p_double[i]-v, _state);
15508  }
15509  cure = ae_sqrt(cure/n, _state);
15510  if( ae_fp_less(cure,*e) )
15511  {
15512  *threshold = cursplit;
15513  *e = cure;
15514  }
15515  }
15516  }
15517 }
15518 
15519 
15520 ae_bool _decisionforest_init(void* _p, ae_state *_state, ae_bool make_automatic)
15521 {
15522  decisionforest *p = (decisionforest*)_p;
15523  ae_touch_ptr((void*)p);
15524  if( !ae_vector_init(&p->trees, 0, DT_REAL, _state, make_automatic) )
15525  return ae_false;
15526  return ae_true;
15527 }
15528 
15529 
15530 ae_bool _decisionforest_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
15531 {
15532  decisionforest *dst = (decisionforest*)_dst;
15533  decisionforest *src = (decisionforest*)_src;
15534  dst->nvars = src->nvars;
15535  dst->nclasses = src->nclasses;
15536  dst->ntrees = src->ntrees;
15537  dst->bufsize = src->bufsize;
15538  if( !ae_vector_init_copy(&dst->trees, &src->trees, _state, make_automatic) )
15539  return ae_false;
15540  return ae_true;
15541 }
15542 
15543 
15544 void _decisionforest_clear(void* _p)
15545 {
15546  decisionforest *p = (decisionforest*)_p;
15547  ae_touch_ptr((void*)p);
15548  ae_vector_clear(&p->trees);
15549 }
15550 
15551 
15552 void _decisionforest_destroy(void* _p)
15553 {
15554  decisionforest *p = (decisionforest*)_p;
15555  ae_touch_ptr((void*)p);
15556  ae_vector_destroy(&p->trees);
15557 }
15558 
15559 
15560 ae_bool _dfreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
15561 {
15562  dfreport *p = (dfreport*)_p;
15563  ae_touch_ptr((void*)p);
15564  return ae_true;
15565 }
15566 
15567 
15568 ae_bool _dfreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
15569 {
15570  dfreport *dst = (dfreport*)_dst;
15571  dfreport *src = (dfreport*)_src;
15572  dst->relclserror = src->relclserror;
15573  dst->avgce = src->avgce;
15574  dst->rmserror = src->rmserror;
15575  dst->avgerror = src->avgerror;
15576  dst->avgrelerror = src->avgrelerror;
15577  dst->oobrelclserror = src->oobrelclserror;
15578  dst->oobavgce = src->oobavgce;
15579  dst->oobrmserror = src->oobrmserror;
15580  dst->oobavgerror = src->oobavgerror;
15581  dst->oobavgrelerror = src->oobavgrelerror;
15582  return ae_true;
15583 }
15584 
15585 
15586 void _dfreport_clear(void* _p)
15587 {
15588  dfreport *p = (dfreport*)_p;
15589  ae_touch_ptr((void*)p);
15590 }
15591 
15592 
15593 void _dfreport_destroy(void* _p)
15594 {
15595  dfreport *p = (dfreport*)_p;
15596  ae_touch_ptr((void*)p);
15597 }
15598 
15599 
15600 ae_bool _dfinternalbuffers_init(void* _p, ae_state *_state, ae_bool make_automatic)
15601 {
15602  dfinternalbuffers *p = (dfinternalbuffers*)_p;
15603  ae_touch_ptr((void*)p);
15604  if( !ae_vector_init(&p->treebuf, 0, DT_REAL, _state, make_automatic) )
15605  return ae_false;
15606  if( !ae_vector_init(&p->idxbuf, 0, DT_INT, _state, make_automatic) )
15607  return ae_false;
15608  if( !ae_vector_init(&p->tmpbufr, 0, DT_REAL, _state, make_automatic) )
15609  return ae_false;
15610  if( !ae_vector_init(&p->tmpbufr2, 0, DT_REAL, _state, make_automatic) )
15611  return ae_false;
15612  if( !ae_vector_init(&p->tmpbufi, 0, DT_INT, _state, make_automatic) )
15613  return ae_false;
15614  if( !ae_vector_init(&p->classibuf, 0, DT_INT, _state, make_automatic) )
15615  return ae_false;
15616  if( !ae_vector_init(&p->sortrbuf, 0, DT_REAL, _state, make_automatic) )
15617  return ae_false;
15618  if( !ae_vector_init(&p->sortrbuf2, 0, DT_REAL, _state, make_automatic) )
15619  return ae_false;
15620  if( !ae_vector_init(&p->sortibuf, 0, DT_INT, _state, make_automatic) )
15621  return ae_false;
15622  if( !ae_vector_init(&p->varpool, 0, DT_INT, _state, make_automatic) )
15623  return ae_false;
15624  if( !ae_vector_init(&p->evsbin, 0, DT_BOOL, _state, make_automatic) )
15625  return ae_false;
15626  if( !ae_vector_init(&p->evssplits, 0, DT_REAL, _state, make_automatic) )
15627  return ae_false;
15628  return ae_true;
15629 }
15630 
15631 
15632 ae_bool _dfinternalbuffers_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
15633 {
15634  dfinternalbuffers *dst = (dfinternalbuffers*)_dst;
15635  dfinternalbuffers *src = (dfinternalbuffers*)_src;
15636  if( !ae_vector_init_copy(&dst->treebuf, &src->treebuf, _state, make_automatic) )
15637  return ae_false;
15638  if( !ae_vector_init_copy(&dst->idxbuf, &src->idxbuf, _state, make_automatic) )
15639  return ae_false;
15640  if( !ae_vector_init_copy(&dst->tmpbufr, &src->tmpbufr, _state, make_automatic) )
15641  return ae_false;
15642  if( !ae_vector_init_copy(&dst->tmpbufr2, &src->tmpbufr2, _state, make_automatic) )
15643  return ae_false;
15644  if( !ae_vector_init_copy(&dst->tmpbufi, &src->tmpbufi, _state, make_automatic) )
15645  return ae_false;
15646  if( !ae_vector_init_copy(&dst->classibuf, &src->classibuf, _state, make_automatic) )
15647  return ae_false;
15648  if( !ae_vector_init_copy(&dst->sortrbuf, &src->sortrbuf, _state, make_automatic) )
15649  return ae_false;
15650  if( !ae_vector_init_copy(&dst->sortrbuf2, &src->sortrbuf2, _state, make_automatic) )
15651  return ae_false;
15652  if( !ae_vector_init_copy(&dst->sortibuf, &src->sortibuf, _state, make_automatic) )
15653  return ae_false;
15654  if( !ae_vector_init_copy(&dst->varpool, &src->varpool, _state, make_automatic) )
15655  return ae_false;
15656  if( !ae_vector_init_copy(&dst->evsbin, &src->evsbin, _state, make_automatic) )
15657  return ae_false;
15658  if( !ae_vector_init_copy(&dst->evssplits, &src->evssplits, _state, make_automatic) )
15659  return ae_false;
15660  return ae_true;
15661 }
15662 
15663 
15664 void _dfinternalbuffers_clear(void* _p)
15665 {
15666  dfinternalbuffers *p = (dfinternalbuffers*)_p;
15667  ae_touch_ptr((void*)p);
15668  ae_vector_clear(&p->treebuf);
15669  ae_vector_clear(&p->idxbuf);
15670  ae_vector_clear(&p->tmpbufr);
15671  ae_vector_clear(&p->tmpbufr2);
15672  ae_vector_clear(&p->tmpbufi);
15673  ae_vector_clear(&p->classibuf);
15674  ae_vector_clear(&p->sortrbuf);
15675  ae_vector_clear(&p->sortrbuf2);
15676  ae_vector_clear(&p->sortibuf);
15677  ae_vector_clear(&p->varpool);
15678  ae_vector_clear(&p->evsbin);
15679  ae_vector_clear(&p->evssplits);
15680 }
15681 
15682 
15683 void _dfinternalbuffers_destroy(void* _p)
15684 {
15685  dfinternalbuffers *p = (dfinternalbuffers*)_p;
15686  ae_touch_ptr((void*)p);
15687  ae_vector_destroy(&p->treebuf);
15688  ae_vector_destroy(&p->idxbuf);
15689  ae_vector_destroy(&p->tmpbufr);
15690  ae_vector_destroy(&p->tmpbufr2);
15691  ae_vector_destroy(&p->tmpbufi);
15692  ae_vector_destroy(&p->classibuf);
15693  ae_vector_destroy(&p->sortrbuf);
15694  ae_vector_destroy(&p->sortrbuf2);
15695  ae_vector_destroy(&p->sortibuf);
15696  ae_vector_destroy(&p->varpool);
15697  ae_vector_destroy(&p->evsbin);
15698  ae_vector_destroy(&p->evssplits);
15699 }
15700 
15701 
15702 
15703 
15704 /*************************************************************************
15705 Linear regression
15706 
15707 Subroutine builds model:
15708 
15709  Y = A(0)*X[0] + ... + A(N-1)*X[N-1] + A(N)
15710 
15711 and model found in ALGLIB format, covariation matrix, training set errors
15712 (rms, average, average relative) and leave-one-out cross-validation
15713 estimate of the generalization error. CV estimate calculated using fast
15714 algorithm with O(NPoints*NVars) complexity.
15715 
15716 When covariation matrix is calculated standard deviations of function
15717 values are assumed to be equal to RMS error on the training set.
15718 
15719 INPUT PARAMETERS:
15720  XY - training set, array [0..NPoints-1,0..NVars]:
15721  * NVars columns - independent variables
15722  * last column - dependent variable
15723  NPoints - training set size, NPoints>NVars+1
15724  NVars - number of independent variables
15725 
15726 OUTPUT PARAMETERS:
15727  Info - return code:
15728  * -255, in case of unknown internal error
15729  * -4, if internal SVD subroutine haven't converged
15730  * -1, if incorrect parameters was passed (NPoints<NVars+2, NVars<1).
15731  * 1, if subroutine successfully finished
15732  LM - linear model in the ALGLIB format. Use subroutines of
15733  this unit to work with the model.
15734  AR - additional results
15735 
15736 
15737  -- ALGLIB --
15738  Copyright 02.08.2008 by Bochkanov Sergey
15739 *************************************************************************/
15740 void lrbuild(/* Real */ ae_matrix* xy,
15741  ae_int_t npoints,
15742  ae_int_t nvars,
15743  ae_int_t* info,
15744  linearmodel* lm,
15745  lrreport* ar,
15746  ae_state *_state)
15747 {
15748  ae_frame _frame_block;
15749  ae_vector s;
15750  ae_int_t i;
15751  double sigma2;
15752 
15753  ae_frame_make(_state, &_frame_block);
15754  *info = 0;
15755  _linearmodel_clear(lm);
15756  _lrreport_clear(ar);
15757  ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
15758 
15759  if( npoints<=nvars+1||nvars<1 )
15760  {
15761  *info = -1;
15762  ae_frame_leave(_state);
15763  return;
15764  }
15765  ae_vector_set_length(&s, npoints-1+1, _state);
15766  for(i=0; i<=npoints-1; i++)
15767  {
15768  s.ptr.p_double[i] = 1;
15769  }
15770  lrbuilds(xy, &s, npoints, nvars, info, lm, ar, _state);
15771  if( *info<0 )
15772  {
15773  ae_frame_leave(_state);
15774  return;
15775  }
15776  sigma2 = ae_sqr(ar->rmserror, _state)*npoints/(npoints-nvars-1);
15777  for(i=0; i<=nvars; i++)
15778  {
15779  ae_v_muld(&ar->c.ptr.pp_double[i][0], 1, ae_v_len(0,nvars), sigma2);
15780  }
15781  ae_frame_leave(_state);
15782 }
15783 
15784 
15785 /*************************************************************************
15786 Linear regression
15787 
15788 Variant of LRBuild which uses vector of standatd deviations (errors in
15789 function values).
15790 
15791 INPUT PARAMETERS:
15792  XY - training set, array [0..NPoints-1,0..NVars]:
15793  * NVars columns - independent variables
15794  * last column - dependent variable
15795  S - standard deviations (errors in function values)
15796  array[0..NPoints-1], S[i]>0.
15797  NPoints - training set size, NPoints>NVars+1
15798  NVars - number of independent variables
15799 
15800 OUTPUT PARAMETERS:
15801  Info - return code:
15802  * -255, in case of unknown internal error
15803  * -4, if internal SVD subroutine haven't converged
15804  * -1, if incorrect parameters was passed (NPoints<NVars+2, NVars<1).
15805  * -2, if S[I]<=0
15806  * 1, if subroutine successfully finished
15807  LM - linear model in the ALGLIB format. Use subroutines of
15808  this unit to work with the model.
15809  AR - additional results
15810 
15811 
15812  -- ALGLIB --
15813  Copyright 02.08.2008 by Bochkanov Sergey
15814 *************************************************************************/
15815 void lrbuilds(/* Real */ ae_matrix* xy,
15816  /* Real */ ae_vector* s,
15817  ae_int_t npoints,
15818  ae_int_t nvars,
15819  ae_int_t* info,
15820  linearmodel* lm,
15821  lrreport* ar,
15822  ae_state *_state)
15823 {
15824  ae_frame _frame_block;
15825  ae_matrix xyi;
15826  ae_vector x;
15827  ae_vector means;
15828  ae_vector sigmas;
15829  ae_int_t i;
15830  ae_int_t j;
15831  double v;
15832  ae_int_t offs;
15833  double mean;
15834  double variance;
15835  double skewness;
15836  double kurtosis;
15837 
15838  ae_frame_make(_state, &_frame_block);
15839  *info = 0;
15840  _linearmodel_clear(lm);
15841  _lrreport_clear(ar);
15842  ae_matrix_init(&xyi, 0, 0, DT_REAL, _state, ae_true);
15843  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
15844  ae_vector_init(&means, 0, DT_REAL, _state, ae_true);
15845  ae_vector_init(&sigmas, 0, DT_REAL, _state, ae_true);
15846 
15847 
15848  /*
15849  * Test parameters
15850  */
15851  if( npoints<=nvars+1||nvars<1 )
15852  {
15853  *info = -1;
15854  ae_frame_leave(_state);
15855  return;
15856  }
15857 
15858  /*
15859  * Copy data, add one more column (constant term)
15860  */
15861  ae_matrix_set_length(&xyi, npoints-1+1, nvars+1+1, _state);
15862  for(i=0; i<=npoints-1; i++)
15863  {
15864  ae_v_move(&xyi.ptr.pp_double[i][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
15865  xyi.ptr.pp_double[i][nvars] = 1;
15866  xyi.ptr.pp_double[i][nvars+1] = xy->ptr.pp_double[i][nvars];
15867  }
15868 
15869  /*
15870  * Standartization
15871  */
15872  ae_vector_set_length(&x, npoints-1+1, _state);
15873  ae_vector_set_length(&means, nvars-1+1, _state);
15874  ae_vector_set_length(&sigmas, nvars-1+1, _state);
15875  for(j=0; j<=nvars-1; j++)
15876  {
15877  ae_v_move(&x.ptr.p_double[0], 1, &xy->ptr.pp_double[0][j], xy->stride, ae_v_len(0,npoints-1));
15878  samplemoments(&x, npoints, &mean, &variance, &skewness, &kurtosis, _state);
15879  means.ptr.p_double[j] = mean;
15880  sigmas.ptr.p_double[j] = ae_sqrt(variance, _state);
15881  if( ae_fp_eq(sigmas.ptr.p_double[j],0) )
15882  {
15883  sigmas.ptr.p_double[j] = 1;
15884  }
15885  for(i=0; i<=npoints-1; i++)
15886  {
15887  xyi.ptr.pp_double[i][j] = (xyi.ptr.pp_double[i][j]-means.ptr.p_double[j])/sigmas.ptr.p_double[j];
15888  }
15889  }
15890 
15891  /*
15892  * Internal processing
15893  */
15894  linreg_lrinternal(&xyi, s, npoints, nvars+1, info, lm, ar, _state);
15895  if( *info<0 )
15896  {
15897  ae_frame_leave(_state);
15898  return;
15899  }
15900 
15901  /*
15902  * Un-standartization
15903  */
15904  offs = ae_round(lm->w.ptr.p_double[3], _state);
15905  for(j=0; j<=nvars-1; j++)
15906  {
15907 
15908  /*
15909  * Constant term is updated (and its covariance too,
15910  * since it gets some variance from J-th component)
15911  */
15912  lm->w.ptr.p_double[offs+nvars] = lm->w.ptr.p_double[offs+nvars]-lm->w.ptr.p_double[offs+j]*means.ptr.p_double[j]/sigmas.ptr.p_double[j];
15913  v = means.ptr.p_double[j]/sigmas.ptr.p_double[j];
15914  ae_v_subd(&ar->c.ptr.pp_double[nvars][0], 1, &ar->c.ptr.pp_double[j][0], 1, ae_v_len(0,nvars), v);
15915  ae_v_subd(&ar->c.ptr.pp_double[0][nvars], ar->c.stride, &ar->c.ptr.pp_double[0][j], ar->c.stride, ae_v_len(0,nvars), v);
15916 
15917  /*
15918  * J-th term is updated
15919  */
15920  lm->w.ptr.p_double[offs+j] = lm->w.ptr.p_double[offs+j]/sigmas.ptr.p_double[j];
15921  v = 1/sigmas.ptr.p_double[j];
15922  ae_v_muld(&ar->c.ptr.pp_double[j][0], 1, ae_v_len(0,nvars), v);
15923  ae_v_muld(&ar->c.ptr.pp_double[0][j], ar->c.stride, ae_v_len(0,nvars), v);
15924  }
15925  ae_frame_leave(_state);
15926 }
15927 
15928 
15929 /*************************************************************************
15930 Like LRBuildS, but builds model
15931 
15932  Y = A(0)*X[0] + ... + A(N-1)*X[N-1]
15933 
15934 i.e. with zero constant term.
15935 
15936  -- ALGLIB --
15937  Copyright 30.10.2008 by Bochkanov Sergey
15938 *************************************************************************/
15939 void lrbuildzs(/* Real */ ae_matrix* xy,
15940  /* Real */ ae_vector* s,
15941  ae_int_t npoints,
15942  ae_int_t nvars,
15943  ae_int_t* info,
15944  linearmodel* lm,
15945  lrreport* ar,
15946  ae_state *_state)
15947 {
15948  ae_frame _frame_block;
15949  ae_matrix xyi;
15950  ae_vector x;
15951  ae_vector c;
15952  ae_int_t i;
15953  ae_int_t j;
15954  double v;
15955  ae_int_t offs;
15956  double mean;
15957  double variance;
15958  double skewness;
15959  double kurtosis;
15960 
15961  ae_frame_make(_state, &_frame_block);
15962  *info = 0;
15963  _linearmodel_clear(lm);
15964  _lrreport_clear(ar);
15965  ae_matrix_init(&xyi, 0, 0, DT_REAL, _state, ae_true);
15966  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
15967  ae_vector_init(&c, 0, DT_REAL, _state, ae_true);
15968 
15969 
15970  /*
15971  * Test parameters
15972  */
15973  if( npoints<=nvars+1||nvars<1 )
15974  {
15975  *info = -1;
15976  ae_frame_leave(_state);
15977  return;
15978  }
15979 
15980  /*
15981  * Copy data, add one more column (constant term)
15982  */
15983  ae_matrix_set_length(&xyi, npoints-1+1, nvars+1+1, _state);
15984  for(i=0; i<=npoints-1; i++)
15985  {
15986  ae_v_move(&xyi.ptr.pp_double[i][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
15987  xyi.ptr.pp_double[i][nvars] = 0;
15988  xyi.ptr.pp_double[i][nvars+1] = xy->ptr.pp_double[i][nvars];
15989  }
15990 
15991  /*
15992  * Standartization: unusual scaling
15993  */
15994  ae_vector_set_length(&x, npoints-1+1, _state);
15995  ae_vector_set_length(&c, nvars-1+1, _state);
15996  for(j=0; j<=nvars-1; j++)
15997  {
15998  ae_v_move(&x.ptr.p_double[0], 1, &xy->ptr.pp_double[0][j], xy->stride, ae_v_len(0,npoints-1));
15999  samplemoments(&x, npoints, &mean, &variance, &skewness, &kurtosis, _state);
16000  if( ae_fp_greater(ae_fabs(mean, _state),ae_sqrt(variance, _state)) )
16001  {
16002 
16003  /*
16004  * variation is relatively small, it is better to
16005  * bring mean value to 1
16006  */
16007  c.ptr.p_double[j] = mean;
16008  }
16009  else
16010  {
16011 
16012  /*
16013  * variation is large, it is better to bring variance to 1
16014  */
16015  if( ae_fp_eq(variance,0) )
16016  {
16017  variance = 1;
16018  }
16019  c.ptr.p_double[j] = ae_sqrt(variance, _state);
16020  }
16021  for(i=0; i<=npoints-1; i++)
16022  {
16023  xyi.ptr.pp_double[i][j] = xyi.ptr.pp_double[i][j]/c.ptr.p_double[j];
16024  }
16025  }
16026 
16027  /*
16028  * Internal processing
16029  */
16030  linreg_lrinternal(&xyi, s, npoints, nvars+1, info, lm, ar, _state);
16031  if( *info<0 )
16032  {
16033  ae_frame_leave(_state);
16034  return;
16035  }
16036 
16037  /*
16038  * Un-standartization
16039  */
16040  offs = ae_round(lm->w.ptr.p_double[3], _state);
16041  for(j=0; j<=nvars-1; j++)
16042  {
16043 
16044  /*
16045  * J-th term is updated
16046  */
16047  lm->w.ptr.p_double[offs+j] = lm->w.ptr.p_double[offs+j]/c.ptr.p_double[j];
16048  v = 1/c.ptr.p_double[j];
16049  ae_v_muld(&ar->c.ptr.pp_double[j][0], 1, ae_v_len(0,nvars), v);
16050  ae_v_muld(&ar->c.ptr.pp_double[0][j], ar->c.stride, ae_v_len(0,nvars), v);
16051  }
16052  ae_frame_leave(_state);
16053 }
16054 
16055 
16056 /*************************************************************************
16057 Like LRBuild but builds model
16058 
16059  Y = A(0)*X[0] + ... + A(N-1)*X[N-1]
16060 
16061 i.e. with zero constant term.
16062 
16063  -- ALGLIB --
16064  Copyright 30.10.2008 by Bochkanov Sergey
16065 *************************************************************************/
16066 void lrbuildz(/* Real */ ae_matrix* xy,
16067  ae_int_t npoints,
16068  ae_int_t nvars,
16069  ae_int_t* info,
16070  linearmodel* lm,
16071  lrreport* ar,
16072  ae_state *_state)
16073 {
16074  ae_frame _frame_block;
16075  ae_vector s;
16076  ae_int_t i;
16077  double sigma2;
16078 
16079  ae_frame_make(_state, &_frame_block);
16080  *info = 0;
16081  _linearmodel_clear(lm);
16082  _lrreport_clear(ar);
16083  ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
16084 
16085  if( npoints<=nvars+1||nvars<1 )
16086  {
16087  *info = -1;
16088  ae_frame_leave(_state);
16089  return;
16090  }
16091  ae_vector_set_length(&s, npoints-1+1, _state);
16092  for(i=0; i<=npoints-1; i++)
16093  {
16094  s.ptr.p_double[i] = 1;
16095  }
16096  lrbuildzs(xy, &s, npoints, nvars, info, lm, ar, _state);
16097  if( *info<0 )
16098  {
16099  ae_frame_leave(_state);
16100  return;
16101  }
16102  sigma2 = ae_sqr(ar->rmserror, _state)*npoints/(npoints-nvars-1);
16103  for(i=0; i<=nvars; i++)
16104  {
16105  ae_v_muld(&ar->c.ptr.pp_double[i][0], 1, ae_v_len(0,nvars), sigma2);
16106  }
16107  ae_frame_leave(_state);
16108 }
16109 
16110 
16111 /*************************************************************************
16112 Unpacks coefficients of linear model.
16113 
16114 INPUT PARAMETERS:
16115  LM - linear model in ALGLIB format
16116 
16117 OUTPUT PARAMETERS:
16118  V - coefficients, array[0..NVars]
16119  constant term (intercept) is stored in the V[NVars].
16120  NVars - number of independent variables (one less than number
16121  of coefficients)
16122 
16123  -- ALGLIB --
16124  Copyright 30.08.2008 by Bochkanov Sergey
16125 *************************************************************************/
16126 void lrunpack(linearmodel* lm,
16127  /* Real */ ae_vector* v,
16128  ae_int_t* nvars,
16129  ae_state *_state)
16130 {
16131  ae_int_t offs;
16132 
16133  ae_vector_clear(v);
16134  *nvars = 0;
16135 
16136  ae_assert(ae_round(lm->w.ptr.p_double[1], _state)==linreg_lrvnum, "LINREG: Incorrect LINREG version!", _state);
16137  *nvars = ae_round(lm->w.ptr.p_double[2], _state);
16138  offs = ae_round(lm->w.ptr.p_double[3], _state);
16139  ae_vector_set_length(v, *nvars+1, _state);
16140  ae_v_move(&v->ptr.p_double[0], 1, &lm->w.ptr.p_double[offs], 1, ae_v_len(0,*nvars));
16141 }
16142 
16143 
16144 /*************************************************************************
16145 "Packs" coefficients and creates linear model in ALGLIB format (LRUnpack
16146 reversed).
16147 
16148 INPUT PARAMETERS:
16149  V - coefficients, array[0..NVars]
16150  NVars - number of independent variables
16151 
16152 OUTPUT PAREMETERS:
16153  LM - linear model.
16154 
16155  -- ALGLIB --
16156  Copyright 30.08.2008 by Bochkanov Sergey
16157 *************************************************************************/
16158 void lrpack(/* Real */ ae_vector* v,
16159  ae_int_t nvars,
16160  linearmodel* lm,
16161  ae_state *_state)
16162 {
16163  ae_int_t offs;
16164 
16165  _linearmodel_clear(lm);
16166 
16167  ae_vector_set_length(&lm->w, 4+nvars+1, _state);
16168  offs = 4;
16169  lm->w.ptr.p_double[0] = 4+nvars+1;
16170  lm->w.ptr.p_double[1] = linreg_lrvnum;
16171  lm->w.ptr.p_double[2] = nvars;
16172  lm->w.ptr.p_double[3] = offs;
16173  ae_v_move(&lm->w.ptr.p_double[offs], 1, &v->ptr.p_double[0], 1, ae_v_len(offs,offs+nvars));
16174 }
16175 
16176 
16177 /*************************************************************************
16178 Procesing
16179 
16180 INPUT PARAMETERS:
16181  LM - linear model
16182  X - input vector, array[0..NVars-1].
16183 
16184 Result:
16185  value of linear model regression estimate
16186 
16187  -- ALGLIB --
16188  Copyright 03.09.2008 by Bochkanov Sergey
16189 *************************************************************************/
16190 double lrprocess(linearmodel* lm,
16191  /* Real */ ae_vector* x,
16192  ae_state *_state)
16193 {
16194  double v;
16195  ae_int_t offs;
16196  ae_int_t nvars;
16197  double result;
16198 
16199 
16200  ae_assert(ae_round(lm->w.ptr.p_double[1], _state)==linreg_lrvnum, "LINREG: Incorrect LINREG version!", _state);
16201  nvars = ae_round(lm->w.ptr.p_double[2], _state);
16202  offs = ae_round(lm->w.ptr.p_double[3], _state);
16203  v = ae_v_dotproduct(&x->ptr.p_double[0], 1, &lm->w.ptr.p_double[offs], 1, ae_v_len(0,nvars-1));
16204  result = v+lm->w.ptr.p_double[offs+nvars];
16205  return result;
16206 }
16207 
16208 
16209 /*************************************************************************
16210 RMS error on the test set
16211 
16212 INPUT PARAMETERS:
16213  LM - linear model
16214  XY - test set
16215  NPoints - test set size
16216 
16217 RESULT:
16218  root mean square error.
16219 
16220  -- ALGLIB --
16221  Copyright 30.08.2008 by Bochkanov Sergey
16222 *************************************************************************/
16223 double lrrmserror(linearmodel* lm,
16224  /* Real */ ae_matrix* xy,
16225  ae_int_t npoints,
16226  ae_state *_state)
16227 {
16228  ae_int_t i;
16229  double v;
16230  ae_int_t offs;
16231  ae_int_t nvars;
16232  double result;
16233 
16234 
16235  ae_assert(ae_round(lm->w.ptr.p_double[1], _state)==linreg_lrvnum, "LINREG: Incorrect LINREG version!", _state);
16236  nvars = ae_round(lm->w.ptr.p_double[2], _state);
16237  offs = ae_round(lm->w.ptr.p_double[3], _state);
16238  result = 0;
16239  for(i=0; i<=npoints-1; i++)
16240  {
16241  v = ae_v_dotproduct(&xy->ptr.pp_double[i][0], 1, &lm->w.ptr.p_double[offs], 1, ae_v_len(0,nvars-1));
16242  v = v+lm->w.ptr.p_double[offs+nvars];
16243  result = result+ae_sqr(v-xy->ptr.pp_double[i][nvars], _state);
16244  }
16245  result = ae_sqrt(result/npoints, _state);
16246  return result;
16247 }
16248 
16249 
16250 /*************************************************************************
16251 Average error on the test set
16252 
16253 INPUT PARAMETERS:
16254  LM - linear model
16255  XY - test set
16256  NPoints - test set size
16257 
16258 RESULT:
16259  average error.
16260 
16261  -- ALGLIB --
16262  Copyright 30.08.2008 by Bochkanov Sergey
16263 *************************************************************************/
16264 double lravgerror(linearmodel* lm,
16265  /* Real */ ae_matrix* xy,
16266  ae_int_t npoints,
16267  ae_state *_state)
16268 {
16269  ae_int_t i;
16270  double v;
16271  ae_int_t offs;
16272  ae_int_t nvars;
16273  double result;
16274 
16275 
16276  ae_assert(ae_round(lm->w.ptr.p_double[1], _state)==linreg_lrvnum, "LINREG: Incorrect LINREG version!", _state);
16277  nvars = ae_round(lm->w.ptr.p_double[2], _state);
16278  offs = ae_round(lm->w.ptr.p_double[3], _state);
16279  result = 0;
16280  for(i=0; i<=npoints-1; i++)
16281  {
16282  v = ae_v_dotproduct(&xy->ptr.pp_double[i][0], 1, &lm->w.ptr.p_double[offs], 1, ae_v_len(0,nvars-1));
16283  v = v+lm->w.ptr.p_double[offs+nvars];
16284  result = result+ae_fabs(v-xy->ptr.pp_double[i][nvars], _state);
16285  }
16286  result = result/npoints;
16287  return result;
16288 }
16289 
16290 
16291 /*************************************************************************
16292 RMS error on the test set
16293 
16294 INPUT PARAMETERS:
16295  LM - linear model
16296  XY - test set
16297  NPoints - test set size
16298 
16299 RESULT:
16300  average relative error.
16301 
16302  -- ALGLIB --
16303  Copyright 30.08.2008 by Bochkanov Sergey
16304 *************************************************************************/
16305 double lravgrelerror(linearmodel* lm,
16306  /* Real */ ae_matrix* xy,
16307  ae_int_t npoints,
16308  ae_state *_state)
16309 {
16310  ae_int_t i;
16311  ae_int_t k;
16312  double v;
16313  ae_int_t offs;
16314  ae_int_t nvars;
16315  double result;
16316 
16317 
16318  ae_assert(ae_round(lm->w.ptr.p_double[1], _state)==linreg_lrvnum, "LINREG: Incorrect LINREG version!", _state);
16319  nvars = ae_round(lm->w.ptr.p_double[2], _state);
16320  offs = ae_round(lm->w.ptr.p_double[3], _state);
16321  result = 0;
16322  k = 0;
16323  for(i=0; i<=npoints-1; i++)
16324  {
16325  if( ae_fp_neq(xy->ptr.pp_double[i][nvars],0) )
16326  {
16327  v = ae_v_dotproduct(&xy->ptr.pp_double[i][0], 1, &lm->w.ptr.p_double[offs], 1, ae_v_len(0,nvars-1));
16328  v = v+lm->w.ptr.p_double[offs+nvars];
16329  result = result+ae_fabs((v-xy->ptr.pp_double[i][nvars])/xy->ptr.pp_double[i][nvars], _state);
16330  k = k+1;
16331  }
16332  }
16333  if( k!=0 )
16334  {
16335  result = result/k;
16336  }
16337  return result;
16338 }
16339 
16340 
16341 /*************************************************************************
16342 Copying of LinearModel strucure
16343 
16344 INPUT PARAMETERS:
16345  LM1 - original
16346 
16347 OUTPUT PARAMETERS:
16348  LM2 - copy
16349 
16350  -- ALGLIB --
16351  Copyright 15.03.2009 by Bochkanov Sergey
16352 *************************************************************************/
16353 void lrcopy(linearmodel* lm1, linearmodel* lm2, ae_state *_state)
16354 {
16355  ae_int_t k;
16356 
16357  _linearmodel_clear(lm2);
16358 
16359  k = ae_round(lm1->w.ptr.p_double[0], _state);
16360  ae_vector_set_length(&lm2->w, k-1+1, _state);
16361  ae_v_move(&lm2->w.ptr.p_double[0], 1, &lm1->w.ptr.p_double[0], 1, ae_v_len(0,k-1));
16362 }
16363 
16364 
16365 void lrlines(/* Real */ ae_matrix* xy,
16366  /* Real */ ae_vector* s,
16367  ae_int_t n,
16368  ae_int_t* info,
16369  double* a,
16370  double* b,
16371  double* vara,
16372  double* varb,
16373  double* covab,
16374  double* corrab,
16375  double* p,
16376  ae_state *_state)
16377 {
16378  ae_int_t i;
16379  double ss;
16380  double sx;
16381  double sxx;
16382  double sy;
16383  double stt;
16384  double e1;
16385  double e2;
16386  double t;
16387  double chi2;
16388 
16389  *info = 0;
16390  *a = 0;
16391  *b = 0;
16392  *vara = 0;
16393  *varb = 0;
16394  *covab = 0;
16395  *corrab = 0;
16396  *p = 0;
16397 
16398  if( n<2 )
16399  {
16400  *info = -1;
16401  return;
16402  }
16403  for(i=0; i<=n-1; i++)
16404  {
16405  if( ae_fp_less_eq(s->ptr.p_double[i],0) )
16406  {
16407  *info = -2;
16408  return;
16409  }
16410  }
16411  *info = 1;
16412 
16413  /*
16414  * Calculate S, SX, SY, SXX
16415  */
16416  ss = 0;
16417  sx = 0;
16418  sy = 0;
16419  sxx = 0;
16420  for(i=0; i<=n-1; i++)
16421  {
16422  t = ae_sqr(s->ptr.p_double[i], _state);
16423  ss = ss+1/t;
16424  sx = sx+xy->ptr.pp_double[i][0]/t;
16425  sy = sy+xy->ptr.pp_double[i][1]/t;
16426  sxx = sxx+ae_sqr(xy->ptr.pp_double[i][0], _state)/t;
16427  }
16428 
16429  /*
16430  * Test for condition number
16431  */
16432  t = ae_sqrt(4*ae_sqr(sx, _state)+ae_sqr(ss-sxx, _state), _state);
16433  e1 = 0.5*(ss+sxx+t);
16434  e2 = 0.5*(ss+sxx-t);
16435  if( ae_fp_less_eq(ae_minreal(e1, e2, _state),1000*ae_machineepsilon*ae_maxreal(e1, e2, _state)) )
16436  {
16437  *info = -3;
16438  return;
16439  }
16440 
16441  /*
16442  * Calculate A, B
16443  */
16444  *a = 0;
16445  *b = 0;
16446  stt = 0;
16447  for(i=0; i<=n-1; i++)
16448  {
16449  t = (xy->ptr.pp_double[i][0]-sx/ss)/s->ptr.p_double[i];
16450  *b = *b+t*xy->ptr.pp_double[i][1]/s->ptr.p_double[i];
16451  stt = stt+ae_sqr(t, _state);
16452  }
16453  *b = *b/stt;
16454  *a = (sy-sx*(*b))/ss;
16455 
16456  /*
16457  * Calculate goodness-of-fit
16458  */
16459  if( n>2 )
16460  {
16461  chi2 = 0;
16462  for(i=0; i<=n-1; i++)
16463  {
16464  chi2 = chi2+ae_sqr((xy->ptr.pp_double[i][1]-(*a)-*b*xy->ptr.pp_double[i][0])/s->ptr.p_double[i], _state);
16465  }
16466  *p = incompletegammac((double)(n-2)/(double)2, chi2/2, _state);
16467  }
16468  else
16469  {
16470  *p = 1;
16471  }
16472 
16473  /*
16474  * Calculate other parameters
16475  */
16476  *vara = (1+ae_sqr(sx, _state)/(ss*stt))/ss;
16477  *varb = 1/stt;
16478  *covab = -sx/(ss*stt);
16479  *corrab = *covab/ae_sqrt(*vara*(*varb), _state);
16480 }
16481 
16482 
16483 void lrline(/* Real */ ae_matrix* xy,
16484  ae_int_t n,
16485  ae_int_t* info,
16486  double* a,
16487  double* b,
16488  ae_state *_state)
16489 {
16490  ae_frame _frame_block;
16491  ae_vector s;
16492  ae_int_t i;
16493  double vara;
16494  double varb;
16495  double covab;
16496  double corrab;
16497  double p;
16498 
16499  ae_frame_make(_state, &_frame_block);
16500  *info = 0;
16501  *a = 0;
16502  *b = 0;
16503  ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
16504 
16505  if( n<2 )
16506  {
16507  *info = -1;
16508  ae_frame_leave(_state);
16509  return;
16510  }
16511  ae_vector_set_length(&s, n-1+1, _state);
16512  for(i=0; i<=n-1; i++)
16513  {
16514  s.ptr.p_double[i] = 1;
16515  }
16516  lrlines(xy, &s, n, info, a, b, &vara, &varb, &covab, &corrab, &p, _state);
16517  ae_frame_leave(_state);
16518 }
16519 
16520 
16521 /*************************************************************************
16522 Internal linear regression subroutine
16523 *************************************************************************/
16524 static void linreg_lrinternal(/* Real */ ae_matrix* xy,
16525  /* Real */ ae_vector* s,
16526  ae_int_t npoints,
16527  ae_int_t nvars,
16528  ae_int_t* info,
16529  linearmodel* lm,
16530  lrreport* ar,
16531  ae_state *_state)
16532 {
16533  ae_frame _frame_block;
16534  ae_matrix a;
16535  ae_matrix u;
16536  ae_matrix vt;
16537  ae_matrix vm;
16538  ae_matrix xym;
16539  ae_vector b;
16540  ae_vector sv;
16541  ae_vector t;
16542  ae_vector svi;
16543  ae_vector work;
16544  ae_int_t i;
16545  ae_int_t j;
16546  ae_int_t k;
16547  ae_int_t ncv;
16548  ae_int_t na;
16549  ae_int_t nacv;
16550  double r;
16551  double p;
16552  double epstol;
16553  lrreport ar2;
16554  ae_int_t offs;
16555  linearmodel tlm;
16556 
16557  ae_frame_make(_state, &_frame_block);
16558  *info = 0;
16559  _linearmodel_clear(lm);
16560  _lrreport_clear(ar);
16561  ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
16562  ae_matrix_init(&u, 0, 0, DT_REAL, _state, ae_true);
16563  ae_matrix_init(&vt, 0, 0, DT_REAL, _state, ae_true);
16564  ae_matrix_init(&vm, 0, 0, DT_REAL, _state, ae_true);
16565  ae_matrix_init(&xym, 0, 0, DT_REAL, _state, ae_true);
16566  ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
16567  ae_vector_init(&sv, 0, DT_REAL, _state, ae_true);
16568  ae_vector_init(&t, 0, DT_REAL, _state, ae_true);
16569  ae_vector_init(&svi, 0, DT_REAL, _state, ae_true);
16570  ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
16571  _lrreport_init(&ar2, _state, ae_true);
16572  _linearmodel_init(&tlm, _state, ae_true);
16573 
16574  epstol = 1000;
16575 
16576  /*
16577  * Check for errors in data
16578  */
16579  if( npoints<nvars||nvars<1 )
16580  {
16581  *info = -1;
16582  ae_frame_leave(_state);
16583  return;
16584  }
16585  for(i=0; i<=npoints-1; i++)
16586  {
16587  if( ae_fp_less_eq(s->ptr.p_double[i],0) )
16588  {
16589  *info = -2;
16590  ae_frame_leave(_state);
16591  return;
16592  }
16593  }
16594  *info = 1;
16595 
16596  /*
16597  * Create design matrix
16598  */
16599  ae_matrix_set_length(&a, npoints-1+1, nvars-1+1, _state);
16600  ae_vector_set_length(&b, npoints-1+1, _state);
16601  for(i=0; i<=npoints-1; i++)
16602  {
16603  r = 1/s->ptr.p_double[i];
16604  ae_v_moved(&a.ptr.pp_double[i][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1), r);
16605  b.ptr.p_double[i] = xy->ptr.pp_double[i][nvars]/s->ptr.p_double[i];
16606  }
16607 
16608  /*
16609  * Allocate W:
16610  * W[0] array size
16611  * W[1] version number, 0
16612  * W[2] NVars (minus 1, to be compatible with external representation)
16613  * W[3] coefficients offset
16614  */
16615  ae_vector_set_length(&lm->w, 4+nvars-1+1, _state);
16616  offs = 4;
16617  lm->w.ptr.p_double[0] = 4+nvars;
16618  lm->w.ptr.p_double[1] = linreg_lrvnum;
16619  lm->w.ptr.p_double[2] = nvars-1;
16620  lm->w.ptr.p_double[3] = offs;
16621 
16622  /*
16623  * Solve problem using SVD:
16624  *
16625  * 0. check for degeneracy (different types)
16626  * 1. A = U*diag(sv)*V'
16627  * 2. T = b'*U
16628  * 3. w = SUM((T[i]/sv[i])*V[..,i])
16629  * 4. cov(wi,wj) = SUM(Vji*Vjk/sv[i]^2,K=1..M)
16630  *
16631  * see $15.4 of "Numerical Recipes in C" for more information
16632  */
16633  ae_vector_set_length(&t, nvars-1+1, _state);
16634  ae_vector_set_length(&svi, nvars-1+1, _state);
16635  ae_matrix_set_length(&ar->c, nvars-1+1, nvars-1+1, _state);
16636  ae_matrix_set_length(&vm, nvars-1+1, nvars-1+1, _state);
16637  if( !rmatrixsvd(&a, npoints, nvars, 1, 1, 2, &sv, &u, &vt, _state) )
16638  {
16639  *info = -4;
16640  ae_frame_leave(_state);
16641  return;
16642  }
16643  if( ae_fp_less_eq(sv.ptr.p_double[0],0) )
16644  {
16645 
16646  /*
16647  * Degenerate case: zero design matrix.
16648  */
16649  for(i=offs; i<=offs+nvars-1; i++)
16650  {
16651  lm->w.ptr.p_double[i] = 0;
16652  }
16653  ar->rmserror = lrrmserror(lm, xy, npoints, _state);
16654  ar->avgerror = lravgerror(lm, xy, npoints, _state);
16655  ar->avgrelerror = lravgrelerror(lm, xy, npoints, _state);
16656  ar->cvrmserror = ar->rmserror;
16657  ar->cvavgerror = ar->avgerror;
16658  ar->cvavgrelerror = ar->avgrelerror;
16659  ar->ncvdefects = 0;
16660  ae_vector_set_length(&ar->cvdefects, nvars-1+1, _state);
16661  ae_matrix_set_length(&ar->c, nvars-1+1, nvars-1+1, _state);
16662  for(i=0; i<=nvars-1; i++)
16663  {
16664  for(j=0; j<=nvars-1; j++)
16665  {
16666  ar->c.ptr.pp_double[i][j] = 0;
16667  }
16668  }
16669  ae_frame_leave(_state);
16670  return;
16671  }
16672  if( ae_fp_less_eq(sv.ptr.p_double[nvars-1],epstol*ae_machineepsilon*sv.ptr.p_double[0]) )
16673  {
16674 
16675  /*
16676  * Degenerate case, non-zero design matrix.
16677  *
16678  * We can leave it and solve task in SVD least squares fashion.
16679  * Solution and covariance matrix will be obtained correctly,
16680  * but CV error estimates - will not. It is better to reduce
16681  * it to non-degenerate task and to obtain correct CV estimates.
16682  */
16683  for(k=nvars; k>=1; k--)
16684  {
16685  if( ae_fp_greater(sv.ptr.p_double[k-1],epstol*ae_machineepsilon*sv.ptr.p_double[0]) )
16686  {
16687 
16688  /*
16689  * Reduce
16690  */
16691  ae_matrix_set_length(&xym, npoints-1+1, k+1, _state);
16692  for(i=0; i<=npoints-1; i++)
16693  {
16694  for(j=0; j<=k-1; j++)
16695  {
16696  r = ae_v_dotproduct(&xy->ptr.pp_double[i][0], 1, &vt.ptr.pp_double[j][0], 1, ae_v_len(0,nvars-1));
16697  xym.ptr.pp_double[i][j] = r;
16698  }
16699  xym.ptr.pp_double[i][k] = xy->ptr.pp_double[i][nvars];
16700  }
16701 
16702  /*
16703  * Solve
16704  */
16705  linreg_lrinternal(&xym, s, npoints, k, info, &tlm, &ar2, _state);
16706  if( *info!=1 )
16707  {
16708  ae_frame_leave(_state);
16709  return;
16710  }
16711 
16712  /*
16713  * Convert back to un-reduced format
16714  */
16715  for(j=0; j<=nvars-1; j++)
16716  {
16717  lm->w.ptr.p_double[offs+j] = 0;
16718  }
16719  for(j=0; j<=k-1; j++)
16720  {
16721  r = tlm.w.ptr.p_double[offs+j];
16722  ae_v_addd(&lm->w.ptr.p_double[offs], 1, &vt.ptr.pp_double[j][0], 1, ae_v_len(offs,offs+nvars-1), r);
16723  }
16724  ar->rmserror = ar2.rmserror;
16725  ar->avgerror = ar2.avgerror;
16726  ar->avgrelerror = ar2.avgrelerror;
16727  ar->cvrmserror = ar2.cvrmserror;
16728  ar->cvavgerror = ar2.cvavgerror;
16729  ar->cvavgrelerror = ar2.cvavgrelerror;
16730  ar->ncvdefects = ar2.ncvdefects;
16731  ae_vector_set_length(&ar->cvdefects, nvars-1+1, _state);
16732  for(j=0; j<=ar->ncvdefects-1; j++)
16733  {
16734  ar->cvdefects.ptr.p_int[j] = ar2.cvdefects.ptr.p_int[j];
16735  }
16736  ae_matrix_set_length(&ar->c, nvars-1+1, nvars-1+1, _state);
16737  ae_vector_set_length(&work, nvars+1, _state);
16738  matrixmatrixmultiply(&ar2.c, 0, k-1, 0, k-1, ae_false, &vt, 0, k-1, 0, nvars-1, ae_false, 1.0, &vm, 0, k-1, 0, nvars-1, 0.0, &work, _state);
16739  matrixmatrixmultiply(&vt, 0, k-1, 0, nvars-1, ae_true, &vm, 0, k-1, 0, nvars-1, ae_false, 1.0, &ar->c, 0, nvars-1, 0, nvars-1, 0.0, &work, _state);
16740  ae_frame_leave(_state);
16741  return;
16742  }
16743  }
16744  *info = -255;
16745  ae_frame_leave(_state);
16746  return;
16747  }
16748  for(i=0; i<=nvars-1; i++)
16749  {
16750  if( ae_fp_greater(sv.ptr.p_double[i],epstol*ae_machineepsilon*sv.ptr.p_double[0]) )
16751  {
16752  svi.ptr.p_double[i] = 1/sv.ptr.p_double[i];
16753  }
16754  else
16755  {
16756  svi.ptr.p_double[i] = 0;
16757  }
16758  }
16759  for(i=0; i<=nvars-1; i++)
16760  {
16761  t.ptr.p_double[i] = 0;
16762  }
16763  for(i=0; i<=npoints-1; i++)
16764  {
16765  r = b.ptr.p_double[i];
16766  ae_v_addd(&t.ptr.p_double[0], 1, &u.ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1), r);
16767  }
16768  for(i=0; i<=nvars-1; i++)
16769  {
16770  lm->w.ptr.p_double[offs+i] = 0;
16771  }
16772  for(i=0; i<=nvars-1; i++)
16773  {
16774  r = t.ptr.p_double[i]*svi.ptr.p_double[i];
16775  ae_v_addd(&lm->w.ptr.p_double[offs], 1, &vt.ptr.pp_double[i][0], 1, ae_v_len(offs,offs+nvars-1), r);
16776  }
16777  for(j=0; j<=nvars-1; j++)
16778  {
16779  r = svi.ptr.p_double[j];
16780  ae_v_moved(&vm.ptr.pp_double[0][j], vm.stride, &vt.ptr.pp_double[j][0], 1, ae_v_len(0,nvars-1), r);
16781  }
16782  for(i=0; i<=nvars-1; i++)
16783  {
16784  for(j=i; j<=nvars-1; j++)
16785  {
16786  r = ae_v_dotproduct(&vm.ptr.pp_double[i][0], 1, &vm.ptr.pp_double[j][0], 1, ae_v_len(0,nvars-1));
16787  ar->c.ptr.pp_double[i][j] = r;
16788  ar->c.ptr.pp_double[j][i] = r;
16789  }
16790  }
16791 
16792  /*
16793  * Leave-1-out cross-validation error.
16794  *
16795  * NOTATIONS:
16796  * A design matrix
16797  * A*x = b original linear least squares task
16798  * U*S*V' SVD of A
16799  * ai i-th row of the A
16800  * bi i-th element of the b
16801  * xf solution of the original LLS task
16802  *
16803  * Cross-validation error of i-th element from a sample is
16804  * calculated using following formula:
16805  *
16806  * ERRi = ai*xf - (ai*xf-bi*(ui*ui'))/(1-ui*ui') (1)
16807  *
16808  * This formula can be derived from normal equations of the
16809  * original task
16810  *
16811  * (A'*A)x = A'*b (2)
16812  *
16813  * by applying modification (zeroing out i-th row of A) to (2):
16814  *
16815  * (A-ai)'*(A-ai) = (A-ai)'*b
16816  *
16817  * and using Sherman-Morrison formula for updating matrix inverse
16818  *
16819  * NOTE 1: b is not zeroed out since it is much simpler and
16820  * does not influence final result.
16821  *
16822  * NOTE 2: some design matrices A have such ui that 1-ui*ui'=0.
16823  * Formula (1) can't be applied for such cases and they are skipped
16824  * from CV calculation (which distorts resulting CV estimate).
16825  * But from the properties of U we can conclude that there can
16826  * be no more than NVars such vectors. Usually
16827  * NVars << NPoints, so in a normal case it only slightly
16828  * influences result.
16829  */
16830  ncv = 0;
16831  na = 0;
16832  nacv = 0;
16833  ar->rmserror = 0;
16834  ar->avgerror = 0;
16835  ar->avgrelerror = 0;
16836  ar->cvrmserror = 0;
16837  ar->cvavgerror = 0;
16838  ar->cvavgrelerror = 0;
16839  ar->ncvdefects = 0;
16840  ae_vector_set_length(&ar->cvdefects, nvars-1+1, _state);
16841  for(i=0; i<=npoints-1; i++)
16842  {
16843 
16844  /*
16845  * Error on a training set
16846  */
16847  r = ae_v_dotproduct(&xy->ptr.pp_double[i][0], 1, &lm->w.ptr.p_double[offs], 1, ae_v_len(0,nvars-1));
16848  ar->rmserror = ar->rmserror+ae_sqr(r-xy->ptr.pp_double[i][nvars], _state);
16849  ar->avgerror = ar->avgerror+ae_fabs(r-xy->ptr.pp_double[i][nvars], _state);
16850  if( ae_fp_neq(xy->ptr.pp_double[i][nvars],0) )
16851  {
16852  ar->avgrelerror = ar->avgrelerror+ae_fabs((r-xy->ptr.pp_double[i][nvars])/xy->ptr.pp_double[i][nvars], _state);
16853  na = na+1;
16854  }
16855 
16856  /*
16857  * Error using fast leave-one-out cross-validation
16858  */
16859  p = ae_v_dotproduct(&u.ptr.pp_double[i][0], 1, &u.ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
16860  if( ae_fp_greater(p,1-epstol*ae_machineepsilon) )
16861  {
16862  ar->cvdefects.ptr.p_int[ar->ncvdefects] = i;
16863  ar->ncvdefects = ar->ncvdefects+1;
16864  continue;
16865  }
16866  r = s->ptr.p_double[i]*(r/s->ptr.p_double[i]-b.ptr.p_double[i]*p)/(1-p);
16867  ar->cvrmserror = ar->cvrmserror+ae_sqr(r-xy->ptr.pp_double[i][nvars], _state);
16868  ar->cvavgerror = ar->cvavgerror+ae_fabs(r-xy->ptr.pp_double[i][nvars], _state);
16869  if( ae_fp_neq(xy->ptr.pp_double[i][nvars],0) )
16870  {
16871  ar->cvavgrelerror = ar->cvavgrelerror+ae_fabs((r-xy->ptr.pp_double[i][nvars])/xy->ptr.pp_double[i][nvars], _state);
16872  nacv = nacv+1;
16873  }
16874  ncv = ncv+1;
16875  }
16876  if( ncv==0 )
16877  {
16878 
16879  /*
16880  * Something strange: ALL ui are degenerate.
16881  * Unexpected...
16882  */
16883  *info = -255;
16884  ae_frame_leave(_state);
16885  return;
16886  }
16887  ar->rmserror = ae_sqrt(ar->rmserror/npoints, _state);
16888  ar->avgerror = ar->avgerror/npoints;
16889  if( na!=0 )
16890  {
16891  ar->avgrelerror = ar->avgrelerror/na;
16892  }
16893  ar->cvrmserror = ae_sqrt(ar->cvrmserror/ncv, _state);
16894  ar->cvavgerror = ar->cvavgerror/ncv;
16895  if( nacv!=0 )
16896  {
16897  ar->cvavgrelerror = ar->cvavgrelerror/nacv;
16898  }
16899  ae_frame_leave(_state);
16900 }
16901 
16902 
16903 ae_bool _linearmodel_init(void* _p, ae_state *_state, ae_bool make_automatic)
16904 {
16905  linearmodel *p = (linearmodel*)_p;
16906  ae_touch_ptr((void*)p);
16907  if( !ae_vector_init(&p->w, 0, DT_REAL, _state, make_automatic) )
16908  return ae_false;
16909  return ae_true;
16910 }
16911 
16912 
16913 ae_bool _linearmodel_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
16914 {
16915  linearmodel *dst = (linearmodel*)_dst;
16916  linearmodel *src = (linearmodel*)_src;
16917  if( !ae_vector_init_copy(&dst->w, &src->w, _state, make_automatic) )
16918  return ae_false;
16919  return ae_true;
16920 }
16921 
16922 
16923 void _linearmodel_clear(void* _p)
16924 {
16925  linearmodel *p = (linearmodel*)_p;
16926  ae_touch_ptr((void*)p);
16927  ae_vector_clear(&p->w);
16928 }
16929 
16930 
16931 void _linearmodel_destroy(void* _p)
16932 {
16933  linearmodel *p = (linearmodel*)_p;
16934  ae_touch_ptr((void*)p);
16935  ae_vector_destroy(&p->w);
16936 }
16937 
16938 
16939 ae_bool _lrreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
16940 {
16941  lrreport *p = (lrreport*)_p;
16942  ae_touch_ptr((void*)p);
16943  if( !ae_matrix_init(&p->c, 0, 0, DT_REAL, _state, make_automatic) )
16944  return ae_false;
16945  if( !ae_vector_init(&p->cvdefects, 0, DT_INT, _state, make_automatic) )
16946  return ae_false;
16947  return ae_true;
16948 }
16949 
16950 
16951 ae_bool _lrreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
16952 {
16953  lrreport *dst = (lrreport*)_dst;
16954  lrreport *src = (lrreport*)_src;
16955  if( !ae_matrix_init_copy(&dst->c, &src->c, _state, make_automatic) )
16956  return ae_false;
16957  dst->rmserror = src->rmserror;
16958  dst->avgerror = src->avgerror;
16959  dst->avgrelerror = src->avgrelerror;
16960  dst->cvrmserror = src->cvrmserror;
16961  dst->cvavgerror = src->cvavgerror;
16962  dst->cvavgrelerror = src->cvavgrelerror;
16963  dst->ncvdefects = src->ncvdefects;
16964  if( !ae_vector_init_copy(&dst->cvdefects, &src->cvdefects, _state, make_automatic) )
16965  return ae_false;
16966  return ae_true;
16967 }
16968 
16969 
16970 void _lrreport_clear(void* _p)
16971 {
16972  lrreport *p = (lrreport*)_p;
16973  ae_touch_ptr((void*)p);
16974  ae_matrix_clear(&p->c);
16975  ae_vector_clear(&p->cvdefects);
16976 }
16977 
16978 
16979 void _lrreport_destroy(void* _p)
16980 {
16981  lrreport *p = (lrreport*)_p;
16982  ae_touch_ptr((void*)p);
16983  ae_matrix_destroy(&p->c);
16984  ae_vector_destroy(&p->cvdefects);
16985 }
16986 
16987 
16988 
16989 
16990 /*************************************************************************
16991 Filters: simple moving averages (unsymmetric).
16992 
16993 This filter replaces array by results of SMA(K) filter. SMA(K) is defined
16994 as filter which averages at most K previous points (previous - not points
16995 AROUND central point) - or less, in case of the first K-1 points.
16996 
16997 INPUT PARAMETERS:
16998  X - array[N], array to process. It can be larger than N,
16999  in this case only first N points are processed.
17000  N - points count, N>=0
17001  K - K>=1 (K can be larger than N , such cases will be
17002  correctly handled). Window width. K=1 corresponds to
17003  identity transformation (nothing changes).
17004 
17005 OUTPUT PARAMETERS:
17006  X - array, whose first N elements were processed with SMA(K)
17007 
17008 NOTE 1: this function uses efficient in-place algorithm which does not
17009  allocate temporary arrays.
17010 
17011 NOTE 2: this algorithm makes only one pass through array and uses running
17012  sum to speed-up calculation of the averages. Additional measures
17013  are taken to ensure that running sum on a long sequence of zero
17014  elements will be correctly reset to zero even in the presence of
17015  round-off error.
17016 
17017 NOTE 3: this is unsymmetric version of the algorithm, which does NOT
17018  averages points after the current one. Only X[i], X[i-1], ... are
17019  used when calculating new value of X[i]. We should also note that
17020  this algorithm uses BOTH previous points and current one, i.e.
17021  new value of X[i] depends on BOTH previous point and X[i] itself.
17022 
17023  -- ALGLIB --
17024  Copyright 25.10.2011 by Bochkanov Sergey
17025 *************************************************************************/
17026 void filtersma(/* Real */ ae_vector* x,
17027  ae_int_t n,
17028  ae_int_t k,
17029  ae_state *_state)
17030 {
17031  ae_int_t i;
17032  double runningsum;
17033  double termsinsum;
17034  ae_int_t zeroprefix;
17035  double v;
17036 
17037 
17038  ae_assert(n>=0, "FilterSMA: N<0", _state);
17039  ae_assert(x->cnt>=n, "FilterSMA: Length(X)<N", _state);
17040  ae_assert(isfinitevector(x, n, _state), "FilterSMA: X contains INF or NAN", _state);
17041  ae_assert(k>=1, "FilterSMA: K<1", _state);
17042 
17043  /*
17044  * Quick exit, if necessary
17045  */
17046  if( n<=1||k==1 )
17047  {
17048  return;
17049  }
17050 
17051  /*
17052  * Prepare variables (see below for explanation)
17053  */
17054  runningsum = 0.0;
17055  termsinsum = 0;
17056  for(i=ae_maxint(n-k, 0, _state); i<=n-1; i++)
17057  {
17058  runningsum = runningsum+x->ptr.p_double[i];
17059  termsinsum = termsinsum+1;
17060  }
17061  i = ae_maxint(n-k, 0, _state);
17062  zeroprefix = 0;
17063  while(i<=n-1&&ae_fp_eq(x->ptr.p_double[i],0))
17064  {
17065  zeroprefix = zeroprefix+1;
17066  i = i+1;
17067  }
17068 
17069  /*
17070  * General case: we assume that N>1 and K>1
17071  *
17072  * Make one pass through all elements. At the beginning of
17073  * the iteration we have:
17074  * * I element being processed
17075  * * RunningSum current value of the running sum
17076  * (including I-th element)
17077  * * TermsInSum number of terms in sum, 0<=TermsInSum<=K
17078  * * ZeroPrefix length of the sequence of zero elements
17079  * which starts at X[I-K+1] and continues towards X[I].
17080  * Equal to zero in case X[I-K+1] is non-zero.
17081  * This value is used to make RunningSum exactly zero
17082  * when it follows from the problem properties.
17083  */
17084  for(i=n-1; i>=0; i--)
17085  {
17086 
17087  /*
17088  * Store new value of X[i], save old value in V
17089  */
17090  v = x->ptr.p_double[i];
17091  x->ptr.p_double[i] = runningsum/termsinsum;
17092 
17093  /*
17094  * Update RunningSum and TermsInSum
17095  */
17096  if( i-k>=0 )
17097  {
17098  runningsum = runningsum-v+x->ptr.p_double[i-k];
17099  }
17100  else
17101  {
17102  runningsum = runningsum-v;
17103  termsinsum = termsinsum-1;
17104  }
17105 
17106  /*
17107  * Update ZeroPrefix.
17108  * In case we have ZeroPrefix=TermsInSum,
17109  * RunningSum is reset to zero.
17110  */
17111  if( i-k>=0 )
17112  {
17113  if( ae_fp_neq(x->ptr.p_double[i-k],0) )
17114  {
17115  zeroprefix = 0;
17116  }
17117  else
17118  {
17119  zeroprefix = ae_minint(zeroprefix+1, k, _state);
17120  }
17121  }
17122  else
17123  {
17124  zeroprefix = ae_minint(zeroprefix, i+1, _state);
17125  }
17126  if( ae_fp_eq(zeroprefix,termsinsum) )
17127  {
17128  runningsum = 0;
17129  }
17130  }
17131 }
17132 
17133 
17134 /*************************************************************************
17135 Filters: exponential moving averages.
17136 
17137 This filter replaces array by results of EMA(alpha) filter. EMA(alpha) is
17138 defined as filter which replaces X[] by S[]:
17139  S[0] = X[0]
17140  S[t] = alpha*X[t] + (1-alpha)*S[t-1]
17141 
17142 INPUT PARAMETERS:
17143  X - array[N], array to process. It can be larger than N,
17144  in this case only first N points are processed.
17145  N - points count, N>=0
17146  alpha - 0<alpha<=1, smoothing parameter.
17147 
17148 OUTPUT PARAMETERS:
17149  X - array, whose first N elements were processed
17150  with EMA(alpha)
17151 
17152 NOTE 1: this function uses efficient in-place algorithm which does not
17153  allocate temporary arrays.
17154 
17155 NOTE 2: this algorithm uses BOTH previous points and current one, i.e.
17156  new value of X[i] depends on BOTH previous point and X[i] itself.
17157 
17158 NOTE 3: technical analytis users quite often work with EMA coefficient
17159  expressed in DAYS instead of fractions. If you want to calculate
17160  EMA(N), where N is a number of days, you can use alpha=2/(N+1).
17161 
17162  -- ALGLIB --
17163  Copyright 25.10.2011 by Bochkanov Sergey
17164 *************************************************************************/
17165 void filterema(/* Real */ ae_vector* x,
17166  ae_int_t n,
17167  double alpha,
17168  ae_state *_state)
17169 {
17170  ae_int_t i;
17171 
17172 
17173  ae_assert(n>=0, "FilterEMA: N<0", _state);
17174  ae_assert(x->cnt>=n, "FilterEMA: Length(X)<N", _state);
17175  ae_assert(isfinitevector(x, n, _state), "FilterEMA: X contains INF or NAN", _state);
17176  ae_assert(ae_fp_greater(alpha,0), "FilterEMA: Alpha<=0", _state);
17177  ae_assert(ae_fp_less_eq(alpha,1), "FilterEMA: Alpha>1", _state);
17178 
17179  /*
17180  * Quick exit, if necessary
17181  */
17182  if( n<=1||ae_fp_eq(alpha,1) )
17183  {
17184  return;
17185  }
17186 
17187  /*
17188  * Process
17189  */
17190  for(i=1; i<=n-1; i++)
17191  {
17192  x->ptr.p_double[i] = alpha*x->ptr.p_double[i]+(1-alpha)*x->ptr.p_double[i-1];
17193  }
17194 }
17195 
17196 
17197 /*************************************************************************
17198 Filters: linear regression moving averages.
17199 
17200 This filter replaces array by results of LRMA(K) filter.
17201 
17202 LRMA(K) is defined as filter which, for each data point, builds linear
17203 regression model using K prevous points (point itself is included in
17204 these K points) and calculates value of this linear model at the point in
17205 question.
17206 
17207 INPUT PARAMETERS:
17208  X - array[N], array to process. It can be larger than N,
17209  in this case only first N points are processed.
17210  N - points count, N>=0
17211  K - K>=1 (K can be larger than N , such cases will be
17212  correctly handled). Window width. K=1 corresponds to
17213  identity transformation (nothing changes).
17214 
17215 OUTPUT PARAMETERS:
17216  X - array, whose first N elements were processed with SMA(K)
17217 
17218 NOTE 1: this function uses efficient in-place algorithm which does not
17219  allocate temporary arrays.
17220 
17221 NOTE 2: this algorithm makes only one pass through array and uses running
17222  sum to speed-up calculation of the averages. Additional measures
17223  are taken to ensure that running sum on a long sequence of zero
17224  elements will be correctly reset to zero even in the presence of
17225  round-off error.
17226 
17227 NOTE 3: this is unsymmetric version of the algorithm, which does NOT
17228  averages points after the current one. Only X[i], X[i-1], ... are
17229  used when calculating new value of X[i]. We should also note that
17230  this algorithm uses BOTH previous points and current one, i.e.
17231  new value of X[i] depends on BOTH previous point and X[i] itself.
17232 
17233  -- ALGLIB --
17234  Copyright 25.10.2011 by Bochkanov Sergey
17235 *************************************************************************/
17236 void filterlrma(/* Real */ ae_vector* x,
17237  ae_int_t n,
17238  ae_int_t k,
17239  ae_state *_state)
17240 {
17241  ae_frame _frame_block;
17242  ae_int_t i;
17243  ae_int_t m;
17244  ae_matrix xy;
17245  ae_vector s;
17246  ae_int_t info;
17247  double a;
17248  double b;
17249  double vara;
17250  double varb;
17251  double covab;
17252  double corrab;
17253  double p;
17254 
17255  ae_frame_make(_state, &_frame_block);
17256  ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
17257  ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
17258 
17259  ae_assert(n>=0, "FilterLRMA: N<0", _state);
17260  ae_assert(x->cnt>=n, "FilterLRMA: Length(X)<N", _state);
17261  ae_assert(isfinitevector(x, n, _state), "FilterLRMA: X contains INF or NAN", _state);
17262  ae_assert(k>=1, "FilterLRMA: K<1", _state);
17263 
17264  /*
17265  * Quick exit, if necessary:
17266  * * either N is equal to 1 (nothing to average)
17267  * * or K is 1 (only point itself is used) or 2 (model is too simple,
17268  * we will always get identity transformation)
17269  */
17270  if( n<=1||k<=2 )
17271  {
17272  ae_frame_leave(_state);
17273  return;
17274  }
17275 
17276  /*
17277  * General case: K>2, N>1.
17278  * We do not process points with I<2 because first two points (I=0 and I=1) will be
17279  * left unmodified by LRMA filter in any case.
17280  */
17281  ae_matrix_set_length(&xy, k, 2, _state);
17282  ae_vector_set_length(&s, k, _state);
17283  for(i=0; i<=k-1; i++)
17284  {
17285  xy.ptr.pp_double[i][0] = i;
17286  s.ptr.p_double[i] = 1.0;
17287  }
17288  for(i=n-1; i>=2; i--)
17289  {
17290  m = ae_minint(i+1, k, _state);
17291  ae_v_move(&xy.ptr.pp_double[0][1], xy.stride, &x->ptr.p_double[i-m+1], 1, ae_v_len(0,m-1));
17292  lrlines(&xy, &s, m, &info, &a, &b, &vara, &varb, &covab, &corrab, &p, _state);
17293  ae_assert(info==1, "FilterLRMA: internal error", _state);
17294  x->ptr.p_double[i] = a+b*(m-1);
17295  }
17296  ae_frame_leave(_state);
17297 }
17298 
17299 
17300 
17301 
17302 /*************************************************************************
17303 Multiclass Fisher LDA
17304 
17305 Subroutine finds coefficients of linear combination which optimally separates
17306 training set on classes.
17307 
17308 INPUT PARAMETERS:
17309  XY - training set, array[0..NPoints-1,0..NVars].
17310  First NVars columns store values of independent
17311  variables, next column stores number of class (from 0
17312  to NClasses-1) which dataset element belongs to. Fractional
17313  values are rounded to nearest integer.
17314  NPoints - training set size, NPoints>=0
17315  NVars - number of independent variables, NVars>=1
17316  NClasses - number of classes, NClasses>=2
17317 
17318 
17319 OUTPUT PARAMETERS:
17320  Info - return code:
17321  * -4, if internal EVD subroutine hasn't converged
17322  * -2, if there is a point with class number
17323  outside of [0..NClasses-1].
17324  * -1, if incorrect parameters was passed (NPoints<0,
17325  NVars<1, NClasses<2)
17326  * 1, if task has been solved
17327  * 2, if there was a multicollinearity in training set,
17328  but task has been solved.
17329  W - linear combination coefficients, array[0..NVars-1]
17330 
17331  -- ALGLIB --
17332  Copyright 31.05.2008 by Bochkanov Sergey
17333 *************************************************************************/
17334 void fisherlda(/* Real */ ae_matrix* xy,
17335  ae_int_t npoints,
17336  ae_int_t nvars,
17337  ae_int_t nclasses,
17338  ae_int_t* info,
17339  /* Real */ ae_vector* w,
17340  ae_state *_state)
17341 {
17342  ae_frame _frame_block;
17343  ae_matrix w2;
17344 
17345  ae_frame_make(_state, &_frame_block);
17346  *info = 0;
17347  ae_vector_clear(w);
17348  ae_matrix_init(&w2, 0, 0, DT_REAL, _state, ae_true);
17349 
17350  fisherldan(xy, npoints, nvars, nclasses, info, &w2, _state);
17351  if( *info>0 )
17352  {
17353  ae_vector_set_length(w, nvars-1+1, _state);
17354  ae_v_move(&w->ptr.p_double[0], 1, &w2.ptr.pp_double[0][0], w2.stride, ae_v_len(0,nvars-1));
17355  }
17356  ae_frame_leave(_state);
17357 }
17358 
17359 
17360 /*************************************************************************
17361 N-dimensional multiclass Fisher LDA
17362 
17363 Subroutine finds coefficients of linear combinations which optimally separates
17364 training set on classes. It returns N-dimensional basis whose vector are sorted
17365 by quality of training set separation (in descending order).
17366 
17367 INPUT PARAMETERS:
17368  XY - training set, array[0..NPoints-1,0..NVars].
17369  First NVars columns store values of independent
17370  variables, next column stores number of class (from 0
17371  to NClasses-1) which dataset element belongs to. Fractional
17372  values are rounded to nearest integer.
17373  NPoints - training set size, NPoints>=0
17374  NVars - number of independent variables, NVars>=1
17375  NClasses - number of classes, NClasses>=2
17376 
17377 
17378 OUTPUT PARAMETERS:
17379  Info - return code:
17380  * -4, if internal EVD subroutine hasn't converged
17381  * -2, if there is a point with class number
17382  outside of [0..NClasses-1].
17383  * -1, if incorrect parameters was passed (NPoints<0,
17384  NVars<1, NClasses<2)
17385  * 1, if task has been solved
17386  * 2, if there was a multicollinearity in training set,
17387  but task has been solved.
17388  W - basis, array[0..NVars-1,0..NVars-1]
17389  columns of matrix stores basis vectors, sorted by
17390  quality of training set separation (in descending order)
17391 
17392  -- ALGLIB --
17393  Copyright 31.05.2008 by Bochkanov Sergey
17394 *************************************************************************/
17395 void fisherldan(/* Real */ ae_matrix* xy,
17396  ae_int_t npoints,
17397  ae_int_t nvars,
17398  ae_int_t nclasses,
17399  ae_int_t* info,
17400  /* Real */ ae_matrix* w,
17401  ae_state *_state)
17402 {
17403  ae_frame _frame_block;
17404  ae_int_t i;
17405  ae_int_t j;
17406  ae_int_t k;
17407  ae_int_t m;
17408  double v;
17409  ae_vector c;
17410  ae_vector mu;
17411  ae_matrix muc;
17412  ae_vector nc;
17413  ae_matrix sw;
17414  ae_matrix st;
17415  ae_matrix z;
17416  ae_matrix z2;
17417  ae_matrix tm;
17418  ae_matrix sbroot;
17419  ae_matrix a;
17420  ae_matrix xyproj;
17421  ae_matrix wproj;
17422  ae_vector tf;
17423  ae_vector d;
17424  ae_vector d2;
17425  ae_vector work;
17426 
17427  ae_frame_make(_state, &_frame_block);
17428  *info = 0;
17429  ae_matrix_clear(w);
17430  ae_vector_init(&c, 0, DT_INT, _state, ae_true);
17431  ae_vector_init(&mu, 0, DT_REAL, _state, ae_true);
17432  ae_matrix_init(&muc, 0, 0, DT_REAL, _state, ae_true);
17433  ae_vector_init(&nc, 0, DT_INT, _state, ae_true);
17434  ae_matrix_init(&sw, 0, 0, DT_REAL, _state, ae_true);
17435  ae_matrix_init(&st, 0, 0, DT_REAL, _state, ae_true);
17436  ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true);
17437  ae_matrix_init(&z2, 0, 0, DT_REAL, _state, ae_true);
17438  ae_matrix_init(&tm, 0, 0, DT_REAL, _state, ae_true);
17439  ae_matrix_init(&sbroot, 0, 0, DT_REAL, _state, ae_true);
17440  ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
17441  ae_matrix_init(&xyproj, 0, 0, DT_REAL, _state, ae_true);
17442  ae_matrix_init(&wproj, 0, 0, DT_REAL, _state, ae_true);
17443  ae_vector_init(&tf, 0, DT_REAL, _state, ae_true);
17444  ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
17445  ae_vector_init(&d2, 0, DT_REAL, _state, ae_true);
17446  ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
17447 
17448 
17449  /*
17450  * Test data
17451  */
17452  if( (npoints<0||nvars<1)||nclasses<2 )
17453  {
17454  *info = -1;
17455  ae_frame_leave(_state);
17456  return;
17457  }
17458  for(i=0; i<=npoints-1; i++)
17459  {
17460  if( ae_round(xy->ptr.pp_double[i][nvars], _state)<0||ae_round(xy->ptr.pp_double[i][nvars], _state)>=nclasses )
17461  {
17462  *info = -2;
17463  ae_frame_leave(_state);
17464  return;
17465  }
17466  }
17467  *info = 1;
17468 
17469  /*
17470  * Special case: NPoints<=1
17471  * Degenerate task.
17472  */
17473  if( npoints<=1 )
17474  {
17475  *info = 2;
17476  ae_matrix_set_length(w, nvars-1+1, nvars-1+1, _state);
17477  for(i=0; i<=nvars-1; i++)
17478  {
17479  for(j=0; j<=nvars-1; j++)
17480  {
17481  if( i==j )
17482  {
17483  w->ptr.pp_double[i][j] = 1;
17484  }
17485  else
17486  {
17487  w->ptr.pp_double[i][j] = 0;
17488  }
17489  }
17490  }
17491  ae_frame_leave(_state);
17492  return;
17493  }
17494 
17495  /*
17496  * Prepare temporaries
17497  */
17498  ae_vector_set_length(&tf, nvars-1+1, _state);
17499  ae_vector_set_length(&work, ae_maxint(nvars, npoints, _state)+1, _state);
17500 
17501  /*
17502  * Convert class labels from reals to integers (just for convenience)
17503  */
17504  ae_vector_set_length(&c, npoints-1+1, _state);
17505  for(i=0; i<=npoints-1; i++)
17506  {
17507  c.ptr.p_int[i] = ae_round(xy->ptr.pp_double[i][nvars], _state);
17508  }
17509 
17510  /*
17511  * Calculate class sizes and means
17512  */
17513  ae_vector_set_length(&mu, nvars-1+1, _state);
17514  ae_matrix_set_length(&muc, nclasses-1+1, nvars-1+1, _state);
17515  ae_vector_set_length(&nc, nclasses-1+1, _state);
17516  for(j=0; j<=nvars-1; j++)
17517  {
17518  mu.ptr.p_double[j] = 0;
17519  }
17520  for(i=0; i<=nclasses-1; i++)
17521  {
17522  nc.ptr.p_int[i] = 0;
17523  for(j=0; j<=nvars-1; j++)
17524  {
17525  muc.ptr.pp_double[i][j] = 0;
17526  }
17527  }
17528  for(i=0; i<=npoints-1; i++)
17529  {
17530  ae_v_add(&mu.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
17531  ae_v_add(&muc.ptr.pp_double[c.ptr.p_int[i]][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
17532  nc.ptr.p_int[c.ptr.p_int[i]] = nc.ptr.p_int[c.ptr.p_int[i]]+1;
17533  }
17534  for(i=0; i<=nclasses-1; i++)
17535  {
17536  v = (double)1/(double)nc.ptr.p_int[i];
17537  ae_v_muld(&muc.ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1), v);
17538  }
17539  v = (double)1/(double)npoints;
17540  ae_v_muld(&mu.ptr.p_double[0], 1, ae_v_len(0,nvars-1), v);
17541 
17542  /*
17543  * Create ST matrix
17544  */
17545  ae_matrix_set_length(&st, nvars-1+1, nvars-1+1, _state);
17546  for(i=0; i<=nvars-1; i++)
17547  {
17548  for(j=0; j<=nvars-1; j++)
17549  {
17550  st.ptr.pp_double[i][j] = 0;
17551  }
17552  }
17553  for(k=0; k<=npoints-1; k++)
17554  {
17555  ae_v_move(&tf.ptr.p_double[0], 1, &xy->ptr.pp_double[k][0], 1, ae_v_len(0,nvars-1));
17556  ae_v_sub(&tf.ptr.p_double[0], 1, &mu.ptr.p_double[0], 1, ae_v_len(0,nvars-1));
17557  for(i=0; i<=nvars-1; i++)
17558  {
17559  v = tf.ptr.p_double[i];
17560  ae_v_addd(&st.ptr.pp_double[i][0], 1, &tf.ptr.p_double[0], 1, ae_v_len(0,nvars-1), v);
17561  }
17562  }
17563 
17564  /*
17565  * Create SW matrix
17566  */
17567  ae_matrix_set_length(&sw, nvars-1+1, nvars-1+1, _state);
17568  for(i=0; i<=nvars-1; i++)
17569  {
17570  for(j=0; j<=nvars-1; j++)
17571  {
17572  sw.ptr.pp_double[i][j] = 0;
17573  }
17574  }
17575  for(k=0; k<=npoints-1; k++)
17576  {
17577  ae_v_move(&tf.ptr.p_double[0], 1, &xy->ptr.pp_double[k][0], 1, ae_v_len(0,nvars-1));
17578  ae_v_sub(&tf.ptr.p_double[0], 1, &muc.ptr.pp_double[c.ptr.p_int[k]][0], 1, ae_v_len(0,nvars-1));
17579  for(i=0; i<=nvars-1; i++)
17580  {
17581  v = tf.ptr.p_double[i];
17582  ae_v_addd(&sw.ptr.pp_double[i][0], 1, &tf.ptr.p_double[0], 1, ae_v_len(0,nvars-1), v);
17583  }
17584  }
17585 
17586  /*
17587  * Maximize ratio J=(w'*ST*w)/(w'*SW*w).
17588  *
17589  * First, make transition from w to v such that w'*ST*w becomes v'*v:
17590  * v = root(ST)*w = R*w
17591  * R = root(D)*Z'
17592  * w = (root(ST)^-1)*v = RI*v
17593  * RI = Z*inv(root(D))
17594  * J = (v'*v)/(v'*(RI'*SW*RI)*v)
17595  * ST = Z*D*Z'
17596  *
17597  * so we have
17598  *
17599  * J = (v'*v) / (v'*(inv(root(D))*Z'*SW*Z*inv(root(D)))*v) =
17600  * = (v'*v) / (v'*A*v)
17601  */
17602  if( !smatrixevd(&st, nvars, 1, ae_true, &d, &z, _state) )
17603  {
17604  *info = -4;
17605  ae_frame_leave(_state);
17606  return;
17607  }
17608  ae_matrix_set_length(w, nvars-1+1, nvars-1+1, _state);
17609  if( ae_fp_less_eq(d.ptr.p_double[nvars-1],0)||ae_fp_less_eq(d.ptr.p_double[0],1000*ae_machineepsilon*d.ptr.p_double[nvars-1]) )
17610  {
17611 
17612  /*
17613  * Special case: D[NVars-1]<=0
17614  * Degenerate task (all variables takes the same value).
17615  */
17616  if( ae_fp_less_eq(d.ptr.p_double[nvars-1],0) )
17617  {
17618  *info = 2;
17619  for(i=0; i<=nvars-1; i++)
17620  {
17621  for(j=0; j<=nvars-1; j++)
17622  {
17623  if( i==j )
17624  {
17625  w->ptr.pp_double[i][j] = 1;
17626  }
17627  else
17628  {
17629  w->ptr.pp_double[i][j] = 0;
17630  }
17631  }
17632  }
17633  ae_frame_leave(_state);
17634  return;
17635  }
17636 
17637  /*
17638  * Special case: degenerate ST matrix, multicollinearity found.
17639  * Since we know ST eigenvalues/vectors we can translate task to
17640  * non-degenerate form.
17641  *
17642  * Let WG is orthogonal basis of the non zero variance subspace
17643  * of the ST and let WZ is orthogonal basis of the zero variance
17644  * subspace.
17645  *
17646  * Projection on WG allows us to use LDA on reduced M-dimensional
17647  * subspace, N-M vectors of WZ allows us to update reduced LDA
17648  * factors to full N-dimensional subspace.
17649  */
17650  m = 0;
17651  for(k=0; k<=nvars-1; k++)
17652  {
17653  if( ae_fp_less_eq(d.ptr.p_double[k],1000*ae_machineepsilon*d.ptr.p_double[nvars-1]) )
17654  {
17655  m = k+1;
17656  }
17657  }
17658  ae_assert(m!=0, "FisherLDAN: internal error #1", _state);
17659  ae_matrix_set_length(&xyproj, npoints-1+1, nvars-m+1, _state);
17660  matrixmatrixmultiply(xy, 0, npoints-1, 0, nvars-1, ae_false, &z, 0, nvars-1, m, nvars-1, ae_false, 1.0, &xyproj, 0, npoints-1, 0, nvars-m-1, 0.0, &work, _state);
17661  for(i=0; i<=npoints-1; i++)
17662  {
17663  xyproj.ptr.pp_double[i][nvars-m] = xy->ptr.pp_double[i][nvars];
17664  }
17665  fisherldan(&xyproj, npoints, nvars-m, nclasses, info, &wproj, _state);
17666  if( *info<0 )
17667  {
17668  ae_frame_leave(_state);
17669  return;
17670  }
17671  matrixmatrixmultiply(&z, 0, nvars-1, m, nvars-1, ae_false, &wproj, 0, nvars-m-1, 0, nvars-m-1, ae_false, 1.0, w, 0, nvars-1, 0, nvars-m-1, 0.0, &work, _state);
17672  for(k=nvars-m; k<=nvars-1; k++)
17673  {
17674  ae_v_move(&w->ptr.pp_double[0][k], w->stride, &z.ptr.pp_double[0][k-(nvars-m)], z.stride, ae_v_len(0,nvars-1));
17675  }
17676  *info = 2;
17677  }
17678  else
17679  {
17680 
17681  /*
17682  * General case: no multicollinearity
17683  */
17684  ae_matrix_set_length(&tm, nvars-1+1, nvars-1+1, _state);
17685  ae_matrix_set_length(&a, nvars-1+1, nvars-1+1, _state);
17686  matrixmatrixmultiply(&sw, 0, nvars-1, 0, nvars-1, ae_false, &z, 0, nvars-1, 0, nvars-1, ae_false, 1.0, &tm, 0, nvars-1, 0, nvars-1, 0.0, &work, _state);
17687  matrixmatrixmultiply(&z, 0, nvars-1, 0, nvars-1, ae_true, &tm, 0, nvars-1, 0, nvars-1, ae_false, 1.0, &a, 0, nvars-1, 0, nvars-1, 0.0, &work, _state);
17688  for(i=0; i<=nvars-1; i++)
17689  {
17690  for(j=0; j<=nvars-1; j++)
17691  {
17692  a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]/ae_sqrt(d.ptr.p_double[i]*d.ptr.p_double[j], _state);
17693  }
17694  }
17695  if( !smatrixevd(&a, nvars, 1, ae_true, &d2, &z2, _state) )
17696  {
17697  *info = -4;
17698  ae_frame_leave(_state);
17699  return;
17700  }
17701  for(k=0; k<=nvars-1; k++)
17702  {
17703  for(i=0; i<=nvars-1; i++)
17704  {
17705  tf.ptr.p_double[i] = z2.ptr.pp_double[i][k]/ae_sqrt(d.ptr.p_double[i], _state);
17706  }
17707  for(i=0; i<=nvars-1; i++)
17708  {
17709  v = ae_v_dotproduct(&z.ptr.pp_double[i][0], 1, &tf.ptr.p_double[0], 1, ae_v_len(0,nvars-1));
17710  w->ptr.pp_double[i][k] = v;
17711  }
17712  }
17713  }
17714 
17715  /*
17716  * Post-processing:
17717  * * normalization
17718  * * converting to non-negative form, if possible
17719  */
17720  for(k=0; k<=nvars-1; k++)
17721  {
17722  v = ae_v_dotproduct(&w->ptr.pp_double[0][k], w->stride, &w->ptr.pp_double[0][k], w->stride, ae_v_len(0,nvars-1));
17723  v = 1/ae_sqrt(v, _state);
17724  ae_v_muld(&w->ptr.pp_double[0][k], w->stride, ae_v_len(0,nvars-1), v);
17725  v = 0;
17726  for(i=0; i<=nvars-1; i++)
17727  {
17728  v = v+w->ptr.pp_double[i][k];
17729  }
17730  if( ae_fp_less(v,0) )
17731  {
17732  ae_v_muld(&w->ptr.pp_double[0][k], w->stride, ae_v_len(0,nvars-1), -1);
17733  }
17734  }
17735  ae_frame_leave(_state);
17736 }
17737 
17738 
17739 
17740 
17741 /*************************************************************************
17742 This function returns number of weights updates which is required for
17743 gradient calculation problem to be splitted.
17744 *************************************************************************/
17745 ae_int_t mlpgradsplitcost(ae_state *_state)
17746 {
17747  ae_int_t result;
17748 
17749 
17750  result = mlpbase_gradbasecasecost;
17751  return result;
17752 }
17753 
17754 
17755 /*************************************************************************
17756 This function returns number of elements in subset of dataset which is
17757 required for gradient calculation problem to be splitted.
17758 *************************************************************************/
17759 ae_int_t mlpgradsplitsize(ae_state *_state)
17760 {
17761  ae_int_t result;
17762 
17763 
17764  result = mlpbase_microbatchsize;
17765  return result;
17766 }
17767 
17768 
17769 /*************************************************************************
17770 Creates neural network with NIn inputs, NOut outputs, without hidden
17771 layers, with linear output layer. Network weights are filled with small
17772 random values.
17773 
17774  -- ALGLIB --
17775  Copyright 04.11.2007 by Bochkanov Sergey
17776 *************************************************************************/
17777 void mlpcreate0(ae_int_t nin,
17778  ae_int_t nout,
17779  multilayerperceptron* network,
17780  ae_state *_state)
17781 {
17782  ae_frame _frame_block;
17783  ae_vector lsizes;
17784  ae_vector ltypes;
17785  ae_vector lconnfirst;
17786  ae_vector lconnlast;
17787  ae_int_t layerscount;
17788  ae_int_t lastproc;
17789 
17790  ae_frame_make(_state, &_frame_block);
17791  _multilayerperceptron_clear(network);
17792  ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true);
17793  ae_vector_init(&ltypes, 0, DT_INT, _state, ae_true);
17794  ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true);
17795  ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true);
17796 
17797  layerscount = 1+3;
17798 
17799  /*
17800  * Allocate arrays
17801  */
17802  ae_vector_set_length(&lsizes, layerscount-1+1, _state);
17803  ae_vector_set_length(&ltypes, layerscount-1+1, _state);
17804  ae_vector_set_length(&lconnfirst, layerscount-1+1, _state);
17805  ae_vector_set_length(&lconnlast, layerscount-1+1, _state);
17806 
17807  /*
17808  * Layers
17809  */
17810  mlpbase_addinputlayer(nin, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
17811  mlpbase_addbiasedsummatorlayer(nout, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
17812  mlpbase_addactivationlayer(-5, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
17813 
17814  /*
17815  * Create
17816  */
17817  mlpbase_mlpcreate(nin, nout, &lsizes, &ltypes, &lconnfirst, &lconnlast, layerscount, ae_false, network, _state);
17818  mlpbase_fillhighlevelinformation(network, nin, 0, 0, nout, ae_false, ae_true, _state);
17819  ae_frame_leave(_state);
17820 }
17821 
17822 
17823 /*************************************************************************
17824 Same as MLPCreate0, but with one hidden layer (NHid neurons) with
17825 non-linear activation function. Output layer is linear.
17826 
17827  -- ALGLIB --
17828  Copyright 04.11.2007 by Bochkanov Sergey
17829 *************************************************************************/
17830 void mlpcreate1(ae_int_t nin,
17831  ae_int_t nhid,
17832  ae_int_t nout,
17833  multilayerperceptron* network,
17834  ae_state *_state)
17835 {
17836  ae_frame _frame_block;
17837  ae_vector lsizes;
17838  ae_vector ltypes;
17839  ae_vector lconnfirst;
17840  ae_vector lconnlast;
17841  ae_int_t layerscount;
17842  ae_int_t lastproc;
17843 
17844  ae_frame_make(_state, &_frame_block);
17845  _multilayerperceptron_clear(network);
17846  ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true);
17847  ae_vector_init(&ltypes, 0, DT_INT, _state, ae_true);
17848  ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true);
17849  ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true);
17850 
17851  layerscount = 1+3+3;
17852 
17853  /*
17854  * Allocate arrays
17855  */
17856  ae_vector_set_length(&lsizes, layerscount-1+1, _state);
17857  ae_vector_set_length(&ltypes, layerscount-1+1, _state);
17858  ae_vector_set_length(&lconnfirst, layerscount-1+1, _state);
17859  ae_vector_set_length(&lconnlast, layerscount-1+1, _state);
17860 
17861  /*
17862  * Layers
17863  */
17864  mlpbase_addinputlayer(nin, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
17865  mlpbase_addbiasedsummatorlayer(nhid, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
17866  mlpbase_addactivationlayer(1, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
17867  mlpbase_addbiasedsummatorlayer(nout, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
17868  mlpbase_addactivationlayer(-5, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
17869 
17870  /*
17871  * Create
17872  */
17873  mlpbase_mlpcreate(nin, nout, &lsizes, &ltypes, &lconnfirst, &lconnlast, layerscount, ae_false, network, _state);
17874  mlpbase_fillhighlevelinformation(network, nin, nhid, 0, nout, ae_false, ae_true, _state);
17875  ae_frame_leave(_state);
17876 }
17877 
17878 
17879 /*************************************************************************
17880 Same as MLPCreate0, but with two hidden layers (NHid1 and NHid2 neurons)
17881 with non-linear activation function. Output layer is linear.
17882  $ALL
17883 
17884  -- ALGLIB --
17885  Copyright 04.11.2007 by Bochkanov Sergey
17886 *************************************************************************/
17887 void mlpcreate2(ae_int_t nin,
17888  ae_int_t nhid1,
17889  ae_int_t nhid2,
17890  ae_int_t nout,
17891  multilayerperceptron* network,
17892  ae_state *_state)
17893 {
17894  ae_frame _frame_block;
17895  ae_vector lsizes;
17896  ae_vector ltypes;
17897  ae_vector lconnfirst;
17898  ae_vector lconnlast;
17899  ae_int_t layerscount;
17900  ae_int_t lastproc;
17901 
17902  ae_frame_make(_state, &_frame_block);
17903  _multilayerperceptron_clear(network);
17904  ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true);
17905  ae_vector_init(&ltypes, 0, DT_INT, _state, ae_true);
17906  ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true);
17907  ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true);
17908 
17909  layerscount = 1+3+3+3;
17910 
17911  /*
17912  * Allocate arrays
17913  */
17914  ae_vector_set_length(&lsizes, layerscount-1+1, _state);
17915  ae_vector_set_length(&ltypes, layerscount-1+1, _state);
17916  ae_vector_set_length(&lconnfirst, layerscount-1+1, _state);
17917  ae_vector_set_length(&lconnlast, layerscount-1+1, _state);
17918 
17919  /*
17920  * Layers
17921  */
17922  mlpbase_addinputlayer(nin, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
17923  mlpbase_addbiasedsummatorlayer(nhid1, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
17924  mlpbase_addactivationlayer(1, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
17925  mlpbase_addbiasedsummatorlayer(nhid2, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
17926  mlpbase_addactivationlayer(1, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
17927  mlpbase_addbiasedsummatorlayer(nout, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
17928  mlpbase_addactivationlayer(-5, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
17929 
17930  /*
17931  * Create
17932  */
17933  mlpbase_mlpcreate(nin, nout, &lsizes, &ltypes, &lconnfirst, &lconnlast, layerscount, ae_false, network, _state);
17934  mlpbase_fillhighlevelinformation(network, nin, nhid1, nhid2, nout, ae_false, ae_true, _state);
17935  ae_frame_leave(_state);
17936 }
17937 
17938 
17939 /*************************************************************************
17940 Creates neural network with NIn inputs, NOut outputs, without hidden
17941 layers with non-linear output layer. Network weights are filled with small
17942 random values.
17943 
17944 Activation function of the output layer takes values:
17945 
17946  (B, +INF), if D>=0
17947 
17948 or
17949 
17950  (-INF, B), if D<0.
17951 
17952 
17953  -- ALGLIB --
17954  Copyright 30.03.2008 by Bochkanov Sergey
17955 *************************************************************************/
17956 void mlpcreateb0(ae_int_t nin,
17957  ae_int_t nout,
17958  double b,
17959  double d,
17960  multilayerperceptron* network,
17961  ae_state *_state)
17962 {
17963  ae_frame _frame_block;
17964  ae_vector lsizes;
17965  ae_vector ltypes;
17966  ae_vector lconnfirst;
17967  ae_vector lconnlast;
17968  ae_int_t layerscount;
17969  ae_int_t lastproc;
17970  ae_int_t i;
17971 
17972  ae_frame_make(_state, &_frame_block);
17973  _multilayerperceptron_clear(network);
17974  ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true);
17975  ae_vector_init(&ltypes, 0, DT_INT, _state, ae_true);
17976  ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true);
17977  ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true);
17978 
17979  layerscount = 1+3;
17980  if( ae_fp_greater_eq(d,0) )
17981  {
17982  d = 1;
17983  }
17984  else
17985  {
17986  d = -1;
17987  }
17988 
17989  /*
17990  * Allocate arrays
17991  */
17992  ae_vector_set_length(&lsizes, layerscount-1+1, _state);
17993  ae_vector_set_length(&ltypes, layerscount-1+1, _state);
17994  ae_vector_set_length(&lconnfirst, layerscount-1+1, _state);
17995  ae_vector_set_length(&lconnlast, layerscount-1+1, _state);
17996 
17997  /*
17998  * Layers
17999  */
18000  mlpbase_addinputlayer(nin, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18001  mlpbase_addbiasedsummatorlayer(nout, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18002  mlpbase_addactivationlayer(3, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18003 
18004  /*
18005  * Create
18006  */
18007  mlpbase_mlpcreate(nin, nout, &lsizes, &ltypes, &lconnfirst, &lconnlast, layerscount, ae_false, network, _state);
18008  mlpbase_fillhighlevelinformation(network, nin, 0, 0, nout, ae_false, ae_false, _state);
18009 
18010  /*
18011  * Turn on ouputs shift/scaling.
18012  */
18013  for(i=nin; i<=nin+nout-1; i++)
18014  {
18015  network->columnmeans.ptr.p_double[i] = b;
18016  network->columnsigmas.ptr.p_double[i] = d;
18017  }
18018  ae_frame_leave(_state);
18019 }
18020 
18021 
18022 /*************************************************************************
18023 Same as MLPCreateB0 but with non-linear hidden layer.
18024 
18025  -- ALGLIB --
18026  Copyright 30.03.2008 by Bochkanov Sergey
18027 *************************************************************************/
18028 void mlpcreateb1(ae_int_t nin,
18029  ae_int_t nhid,
18030  ae_int_t nout,
18031  double b,
18032  double d,
18033  multilayerperceptron* network,
18034  ae_state *_state)
18035 {
18036  ae_frame _frame_block;
18037  ae_vector lsizes;
18038  ae_vector ltypes;
18039  ae_vector lconnfirst;
18040  ae_vector lconnlast;
18041  ae_int_t layerscount;
18042  ae_int_t lastproc;
18043  ae_int_t i;
18044 
18045  ae_frame_make(_state, &_frame_block);
18046  _multilayerperceptron_clear(network);
18047  ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true);
18048  ae_vector_init(&ltypes, 0, DT_INT, _state, ae_true);
18049  ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true);
18050  ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true);
18051 
18052  layerscount = 1+3+3;
18053  if( ae_fp_greater_eq(d,0) )
18054  {
18055  d = 1;
18056  }
18057  else
18058  {
18059  d = -1;
18060  }
18061 
18062  /*
18063  * Allocate arrays
18064  */
18065  ae_vector_set_length(&lsizes, layerscount-1+1, _state);
18066  ae_vector_set_length(&ltypes, layerscount-1+1, _state);
18067  ae_vector_set_length(&lconnfirst, layerscount-1+1, _state);
18068  ae_vector_set_length(&lconnlast, layerscount-1+1, _state);
18069 
18070  /*
18071  * Layers
18072  */
18073  mlpbase_addinputlayer(nin, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18074  mlpbase_addbiasedsummatorlayer(nhid, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18075  mlpbase_addactivationlayer(1, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18076  mlpbase_addbiasedsummatorlayer(nout, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18077  mlpbase_addactivationlayer(3, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18078 
18079  /*
18080  * Create
18081  */
18082  mlpbase_mlpcreate(nin, nout, &lsizes, &ltypes, &lconnfirst, &lconnlast, layerscount, ae_false, network, _state);
18083  mlpbase_fillhighlevelinformation(network, nin, nhid, 0, nout, ae_false, ae_false, _state);
18084 
18085  /*
18086  * Turn on ouputs shift/scaling.
18087  */
18088  for(i=nin; i<=nin+nout-1; i++)
18089  {
18090  network->columnmeans.ptr.p_double[i] = b;
18091  network->columnsigmas.ptr.p_double[i] = d;
18092  }
18093  ae_frame_leave(_state);
18094 }
18095 
18096 
18097 /*************************************************************************
18098 Same as MLPCreateB0 but with two non-linear hidden layers.
18099 
18100  -- ALGLIB --
18101  Copyright 30.03.2008 by Bochkanov Sergey
18102 *************************************************************************/
18103 void mlpcreateb2(ae_int_t nin,
18104  ae_int_t nhid1,
18105  ae_int_t nhid2,
18106  ae_int_t nout,
18107  double b,
18108  double d,
18109  multilayerperceptron* network,
18110  ae_state *_state)
18111 {
18112  ae_frame _frame_block;
18113  ae_vector lsizes;
18114  ae_vector ltypes;
18115  ae_vector lconnfirst;
18116  ae_vector lconnlast;
18117  ae_int_t layerscount;
18118  ae_int_t lastproc;
18119  ae_int_t i;
18120 
18121  ae_frame_make(_state, &_frame_block);
18122  _multilayerperceptron_clear(network);
18123  ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true);
18124  ae_vector_init(&ltypes, 0, DT_INT, _state, ae_true);
18125  ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true);
18126  ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true);
18127 
18128  layerscount = 1+3+3+3;
18129  if( ae_fp_greater_eq(d,0) )
18130  {
18131  d = 1;
18132  }
18133  else
18134  {
18135  d = -1;
18136  }
18137 
18138  /*
18139  * Allocate arrays
18140  */
18141  ae_vector_set_length(&lsizes, layerscount-1+1, _state);
18142  ae_vector_set_length(&ltypes, layerscount-1+1, _state);
18143  ae_vector_set_length(&lconnfirst, layerscount-1+1, _state);
18144  ae_vector_set_length(&lconnlast, layerscount-1+1, _state);
18145 
18146  /*
18147  * Layers
18148  */
18149  mlpbase_addinputlayer(nin, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18150  mlpbase_addbiasedsummatorlayer(nhid1, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18151  mlpbase_addactivationlayer(1, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18152  mlpbase_addbiasedsummatorlayer(nhid2, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18153  mlpbase_addactivationlayer(1, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18154  mlpbase_addbiasedsummatorlayer(nout, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18155  mlpbase_addactivationlayer(3, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18156 
18157  /*
18158  * Create
18159  */
18160  mlpbase_mlpcreate(nin, nout, &lsizes, &ltypes, &lconnfirst, &lconnlast, layerscount, ae_false, network, _state);
18161  mlpbase_fillhighlevelinformation(network, nin, nhid1, nhid2, nout, ae_false, ae_false, _state);
18162 
18163  /*
18164  * Turn on ouputs shift/scaling.
18165  */
18166  for(i=nin; i<=nin+nout-1; i++)
18167  {
18168  network->columnmeans.ptr.p_double[i] = b;
18169  network->columnsigmas.ptr.p_double[i] = d;
18170  }
18171  ae_frame_leave(_state);
18172 }
18173 
18174 
18175 /*************************************************************************
18176 Creates neural network with NIn inputs, NOut outputs, without hidden
18177 layers with non-linear output layer. Network weights are filled with small
18178 random values. Activation function of the output layer takes values [A,B].
18179 
18180  -- ALGLIB --
18181  Copyright 30.03.2008 by Bochkanov Sergey
18182 *************************************************************************/
18183 void mlpcreater0(ae_int_t nin,
18184  ae_int_t nout,
18185  double a,
18186  double b,
18187  multilayerperceptron* network,
18188  ae_state *_state)
18189 {
18190  ae_frame _frame_block;
18191  ae_vector lsizes;
18192  ae_vector ltypes;
18193  ae_vector lconnfirst;
18194  ae_vector lconnlast;
18195  ae_int_t layerscount;
18196  ae_int_t lastproc;
18197  ae_int_t i;
18198 
18199  ae_frame_make(_state, &_frame_block);
18200  _multilayerperceptron_clear(network);
18201  ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true);
18202  ae_vector_init(&ltypes, 0, DT_INT, _state, ae_true);
18203  ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true);
18204  ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true);
18205 
18206  layerscount = 1+3;
18207 
18208  /*
18209  * Allocate arrays
18210  */
18211  ae_vector_set_length(&lsizes, layerscount-1+1, _state);
18212  ae_vector_set_length(&ltypes, layerscount-1+1, _state);
18213  ae_vector_set_length(&lconnfirst, layerscount-1+1, _state);
18214  ae_vector_set_length(&lconnlast, layerscount-1+1, _state);
18215 
18216  /*
18217  * Layers
18218  */
18219  mlpbase_addinputlayer(nin, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18220  mlpbase_addbiasedsummatorlayer(nout, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18221  mlpbase_addactivationlayer(1, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18222 
18223  /*
18224  * Create
18225  */
18226  mlpbase_mlpcreate(nin, nout, &lsizes, &ltypes, &lconnfirst, &lconnlast, layerscount, ae_false, network, _state);
18227  mlpbase_fillhighlevelinformation(network, nin, 0, 0, nout, ae_false, ae_false, _state);
18228 
18229  /*
18230  * Turn on outputs shift/scaling.
18231  */
18232  for(i=nin; i<=nin+nout-1; i++)
18233  {
18234  network->columnmeans.ptr.p_double[i] = 0.5*(a+b);
18235  network->columnsigmas.ptr.p_double[i] = 0.5*(a-b);
18236  }
18237  ae_frame_leave(_state);
18238 }
18239 
18240 
18241 /*************************************************************************
18242 Same as MLPCreateR0, but with non-linear hidden layer.
18243 
18244  -- ALGLIB --
18245  Copyright 30.03.2008 by Bochkanov Sergey
18246 *************************************************************************/
18247 void mlpcreater1(ae_int_t nin,
18248  ae_int_t nhid,
18249  ae_int_t nout,
18250  double a,
18251  double b,
18252  multilayerperceptron* network,
18253  ae_state *_state)
18254 {
18255  ae_frame _frame_block;
18256  ae_vector lsizes;
18257  ae_vector ltypes;
18258  ae_vector lconnfirst;
18259  ae_vector lconnlast;
18260  ae_int_t layerscount;
18261  ae_int_t lastproc;
18262  ae_int_t i;
18263 
18264  ae_frame_make(_state, &_frame_block);
18265  _multilayerperceptron_clear(network);
18266  ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true);
18267  ae_vector_init(&ltypes, 0, DT_INT, _state, ae_true);
18268  ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true);
18269  ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true);
18270 
18271  layerscount = 1+3+3;
18272 
18273  /*
18274  * Allocate arrays
18275  */
18276  ae_vector_set_length(&lsizes, layerscount-1+1, _state);
18277  ae_vector_set_length(&ltypes, layerscount-1+1, _state);
18278  ae_vector_set_length(&lconnfirst, layerscount-1+1, _state);
18279  ae_vector_set_length(&lconnlast, layerscount-1+1, _state);
18280 
18281  /*
18282  * Layers
18283  */
18284  mlpbase_addinputlayer(nin, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18285  mlpbase_addbiasedsummatorlayer(nhid, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18286  mlpbase_addactivationlayer(1, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18287  mlpbase_addbiasedsummatorlayer(nout, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18288  mlpbase_addactivationlayer(1, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18289 
18290  /*
18291  * Create
18292  */
18293  mlpbase_mlpcreate(nin, nout, &lsizes, &ltypes, &lconnfirst, &lconnlast, layerscount, ae_false, network, _state);
18294  mlpbase_fillhighlevelinformation(network, nin, nhid, 0, nout, ae_false, ae_false, _state);
18295 
18296  /*
18297  * Turn on outputs shift/scaling.
18298  */
18299  for(i=nin; i<=nin+nout-1; i++)
18300  {
18301  network->columnmeans.ptr.p_double[i] = 0.5*(a+b);
18302  network->columnsigmas.ptr.p_double[i] = 0.5*(a-b);
18303  }
18304  ae_frame_leave(_state);
18305 }
18306 
18307 
18308 /*************************************************************************
18309 Same as MLPCreateR0, but with two non-linear hidden layers.
18310 
18311  -- ALGLIB --
18312  Copyright 30.03.2008 by Bochkanov Sergey
18313 *************************************************************************/
18314 void mlpcreater2(ae_int_t nin,
18315  ae_int_t nhid1,
18316  ae_int_t nhid2,
18317  ae_int_t nout,
18318  double a,
18319  double b,
18320  multilayerperceptron* network,
18321  ae_state *_state)
18322 {
18323  ae_frame _frame_block;
18324  ae_vector lsizes;
18325  ae_vector ltypes;
18326  ae_vector lconnfirst;
18327  ae_vector lconnlast;
18328  ae_int_t layerscount;
18329  ae_int_t lastproc;
18330  ae_int_t i;
18331 
18332  ae_frame_make(_state, &_frame_block);
18333  _multilayerperceptron_clear(network);
18334  ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true);
18335  ae_vector_init(&ltypes, 0, DT_INT, _state, ae_true);
18336  ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true);
18337  ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true);
18338 
18339  layerscount = 1+3+3+3;
18340 
18341  /*
18342  * Allocate arrays
18343  */
18344  ae_vector_set_length(&lsizes, layerscount-1+1, _state);
18345  ae_vector_set_length(&ltypes, layerscount-1+1, _state);
18346  ae_vector_set_length(&lconnfirst, layerscount-1+1, _state);
18347  ae_vector_set_length(&lconnlast, layerscount-1+1, _state);
18348 
18349  /*
18350  * Layers
18351  */
18352  mlpbase_addinputlayer(nin, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18353  mlpbase_addbiasedsummatorlayer(nhid1, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18354  mlpbase_addactivationlayer(1, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18355  mlpbase_addbiasedsummatorlayer(nhid2, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18356  mlpbase_addactivationlayer(1, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18357  mlpbase_addbiasedsummatorlayer(nout, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18358  mlpbase_addactivationlayer(1, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18359 
18360  /*
18361  * Create
18362  */
18363  mlpbase_mlpcreate(nin, nout, &lsizes, &ltypes, &lconnfirst, &lconnlast, layerscount, ae_false, network, _state);
18364  mlpbase_fillhighlevelinformation(network, nin, nhid1, nhid2, nout, ae_false, ae_false, _state);
18365 
18366  /*
18367  * Turn on outputs shift/scaling.
18368  */
18369  for(i=nin; i<=nin+nout-1; i++)
18370  {
18371  network->columnmeans.ptr.p_double[i] = 0.5*(a+b);
18372  network->columnsigmas.ptr.p_double[i] = 0.5*(a-b);
18373  }
18374  ae_frame_leave(_state);
18375 }
18376 
18377 
18378 /*************************************************************************
18379 Creates classifier network with NIn inputs and NOut possible classes.
18380 Network contains no hidden layers and linear output layer with SOFTMAX-
18381 normalization (so outputs sums up to 1.0 and converge to posterior
18382 probabilities).
18383 
18384  -- ALGLIB --
18385  Copyright 04.11.2007 by Bochkanov Sergey
18386 *************************************************************************/
18387 void mlpcreatec0(ae_int_t nin,
18388  ae_int_t nout,
18389  multilayerperceptron* network,
18390  ae_state *_state)
18391 {
18392  ae_frame _frame_block;
18393  ae_vector lsizes;
18394  ae_vector ltypes;
18395  ae_vector lconnfirst;
18396  ae_vector lconnlast;
18397  ae_int_t layerscount;
18398  ae_int_t lastproc;
18399 
18400  ae_frame_make(_state, &_frame_block);
18401  _multilayerperceptron_clear(network);
18402  ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true);
18403  ae_vector_init(&ltypes, 0, DT_INT, _state, ae_true);
18404  ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true);
18405  ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true);
18406 
18407  ae_assert(nout>=2, "MLPCreateC0: NOut<2!", _state);
18408  layerscount = 1+2+1;
18409 
18410  /*
18411  * Allocate arrays
18412  */
18413  ae_vector_set_length(&lsizes, layerscount-1+1, _state);
18414  ae_vector_set_length(&ltypes, layerscount-1+1, _state);
18415  ae_vector_set_length(&lconnfirst, layerscount-1+1, _state);
18416  ae_vector_set_length(&lconnlast, layerscount-1+1, _state);
18417 
18418  /*
18419  * Layers
18420  */
18421  mlpbase_addinputlayer(nin, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18422  mlpbase_addbiasedsummatorlayer(nout-1, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18423  mlpbase_addzerolayer(&lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18424 
18425  /*
18426  * Create
18427  */
18428  mlpbase_mlpcreate(nin, nout, &lsizes, &ltypes, &lconnfirst, &lconnlast, layerscount, ae_true, network, _state);
18429  mlpbase_fillhighlevelinformation(network, nin, 0, 0, nout, ae_true, ae_true, _state);
18430  ae_frame_leave(_state);
18431 }
18432 
18433 
18434 /*************************************************************************
18435 Same as MLPCreateC0, but with one non-linear hidden layer.
18436 
18437  -- ALGLIB --
18438  Copyright 04.11.2007 by Bochkanov Sergey
18439 *************************************************************************/
18440 void mlpcreatec1(ae_int_t nin,
18441  ae_int_t nhid,
18442  ae_int_t nout,
18443  multilayerperceptron* network,
18444  ae_state *_state)
18445 {
18446  ae_frame _frame_block;
18447  ae_vector lsizes;
18448  ae_vector ltypes;
18449  ae_vector lconnfirst;
18450  ae_vector lconnlast;
18451  ae_int_t layerscount;
18452  ae_int_t lastproc;
18453 
18454  ae_frame_make(_state, &_frame_block);
18455  _multilayerperceptron_clear(network);
18456  ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true);
18457  ae_vector_init(&ltypes, 0, DT_INT, _state, ae_true);
18458  ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true);
18459  ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true);
18460 
18461  ae_assert(nout>=2, "MLPCreateC1: NOut<2!", _state);
18462  layerscount = 1+3+2+1;
18463 
18464  /*
18465  * Allocate arrays
18466  */
18467  ae_vector_set_length(&lsizes, layerscount-1+1, _state);
18468  ae_vector_set_length(&ltypes, layerscount-1+1, _state);
18469  ae_vector_set_length(&lconnfirst, layerscount-1+1, _state);
18470  ae_vector_set_length(&lconnlast, layerscount-1+1, _state);
18471 
18472  /*
18473  * Layers
18474  */
18475  mlpbase_addinputlayer(nin, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18476  mlpbase_addbiasedsummatorlayer(nhid, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18477  mlpbase_addactivationlayer(1, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18478  mlpbase_addbiasedsummatorlayer(nout-1, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18479  mlpbase_addzerolayer(&lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18480 
18481  /*
18482  * Create
18483  */
18484  mlpbase_mlpcreate(nin, nout, &lsizes, &ltypes, &lconnfirst, &lconnlast, layerscount, ae_true, network, _state);
18485  mlpbase_fillhighlevelinformation(network, nin, nhid, 0, nout, ae_true, ae_true, _state);
18486  ae_frame_leave(_state);
18487 }
18488 
18489 
18490 /*************************************************************************
18491 Same as MLPCreateC0, but with two non-linear hidden layers.
18492 
18493  -- ALGLIB --
18494  Copyright 04.11.2007 by Bochkanov Sergey
18495 *************************************************************************/
18496 void mlpcreatec2(ae_int_t nin,
18497  ae_int_t nhid1,
18498  ae_int_t nhid2,
18499  ae_int_t nout,
18500  multilayerperceptron* network,
18501  ae_state *_state)
18502 {
18503  ae_frame _frame_block;
18504  ae_vector lsizes;
18505  ae_vector ltypes;
18506  ae_vector lconnfirst;
18507  ae_vector lconnlast;
18508  ae_int_t layerscount;
18509  ae_int_t lastproc;
18510 
18511  ae_frame_make(_state, &_frame_block);
18512  _multilayerperceptron_clear(network);
18513  ae_vector_init(&lsizes, 0, DT_INT, _state, ae_true);
18514  ae_vector_init(&ltypes, 0, DT_INT, _state, ae_true);
18515  ae_vector_init(&lconnfirst, 0, DT_INT, _state, ae_true);
18516  ae_vector_init(&lconnlast, 0, DT_INT, _state, ae_true);
18517 
18518  ae_assert(nout>=2, "MLPCreateC2: NOut<2!", _state);
18519  layerscount = 1+3+3+2+1;
18520 
18521  /*
18522  * Allocate arrays
18523  */
18524  ae_vector_set_length(&lsizes, layerscount-1+1, _state);
18525  ae_vector_set_length(&ltypes, layerscount-1+1, _state);
18526  ae_vector_set_length(&lconnfirst, layerscount-1+1, _state);
18527  ae_vector_set_length(&lconnlast, layerscount-1+1, _state);
18528 
18529  /*
18530  * Layers
18531  */
18532  mlpbase_addinputlayer(nin, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18533  mlpbase_addbiasedsummatorlayer(nhid1, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18534  mlpbase_addactivationlayer(1, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18535  mlpbase_addbiasedsummatorlayer(nhid2, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18536  mlpbase_addactivationlayer(1, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18537  mlpbase_addbiasedsummatorlayer(nout-1, &lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18538  mlpbase_addzerolayer(&lsizes, &ltypes, &lconnfirst, &lconnlast, &lastproc, _state);
18539 
18540  /*
18541  * Create
18542  */
18543  mlpbase_mlpcreate(nin, nout, &lsizes, &ltypes, &lconnfirst, &lconnlast, layerscount, ae_true, network, _state);
18544  mlpbase_fillhighlevelinformation(network, nin, nhid1, nhid2, nout, ae_true, ae_true, _state);
18545  ae_frame_leave(_state);
18546 }
18547 
18548 
18549 /*************************************************************************
18550 Copying of neural network
18551 
18552 INPUT PARAMETERS:
18553  Network1 - original
18554 
18555 OUTPUT PARAMETERS:
18556  Network2 - copy
18557 
18558  -- ALGLIB --
18559  Copyright 04.11.2007 by Bochkanov Sergey
18560 *************************************************************************/
18561 void mlpcopy(multilayerperceptron* network1,
18562  multilayerperceptron* network2,
18563  ae_state *_state)
18564 {
18565 
18566  _multilayerperceptron_clear(network2);
18567 
18568  mlpcopyshared(network1, network2, _state);
18569 }
18570 
18571 
18572 /*************************************************************************
18573 Copying of neural network (second parameter is passed as shared object).
18574 
18575 INPUT PARAMETERS:
18576  Network1 - original
18577 
18578 OUTPUT PARAMETERS:
18579  Network2 - copy
18580 
18581  -- ALGLIB --
18582  Copyright 04.11.2007 by Bochkanov Sergey
18583 *************************************************************************/
18584 void mlpcopyshared(multilayerperceptron* network1,
18585  multilayerperceptron* network2,
18586  ae_state *_state)
18587 {
18588  ae_frame _frame_block;
18589  ae_int_t wcount;
18590  ae_int_t i;
18591  mlpbuffers buf;
18592  smlpgrad sgrad;
18593 
18594  ae_frame_make(_state, &_frame_block);
18595  _mlpbuffers_init(&buf, _state, ae_true);
18596  _smlpgrad_init(&sgrad, _state, ae_true);
18597 
18598 
18599  /*
18600  * Copy scalar and array fields
18601  */
18602  network2->hlnetworktype = network1->hlnetworktype;
18603  network2->hlnormtype = network1->hlnormtype;
18604  copyintegerarray(&network1->hllayersizes, &network2->hllayersizes, _state);
18605  copyintegerarray(&network1->hlconnections, &network2->hlconnections, _state);
18606  copyintegerarray(&network1->hlneurons, &network2->hlneurons, _state);
18607  copyintegerarray(&network1->structinfo, &network2->structinfo, _state);
18608  copyrealarray(&network1->weights, &network2->weights, _state);
18609  copyrealarray(&network1->columnmeans, &network2->columnmeans, _state);
18610  copyrealarray(&network1->columnsigmas, &network2->columnsigmas, _state);
18611  copyrealarray(&network1->neurons, &network2->neurons, _state);
18612  copyrealarray(&network1->dfdnet, &network2->dfdnet, _state);
18613  copyrealarray(&network1->derror, &network2->derror, _state);
18614  copyrealarray(&network1->x, &network2->x, _state);
18615  copyrealarray(&network1->y, &network2->y, _state);
18616  copyrealarray(&network1->nwbuf, &network2->nwbuf, _state);
18617  copyintegerarray(&network1->integerbuf, &network2->integerbuf, _state);
18618 
18619  /*
18620  * copy buffers
18621  */
18622  wcount = mlpgetweightscount(network1, _state);
18623  ae_shared_pool_set_seed(&network2->buf, &buf, sizeof(buf), _mlpbuffers_init, _mlpbuffers_init_copy, _mlpbuffers_destroy, _state);
18624  ae_vector_set_length(&sgrad.g, wcount, _state);
18625  sgrad.f = 0.0;
18626  for(i=0; i<=wcount-1; i++)
18627  {
18628  sgrad.g.ptr.p_double[i] = 0.0;
18629  }
18630  ae_shared_pool_set_seed(&network2->gradbuf, &sgrad, sizeof(sgrad), _smlpgrad_init, _smlpgrad_init_copy, _smlpgrad_destroy, _state);
18631  ae_frame_leave(_state);
18632 }
18633 
18634 
18635 /*************************************************************************
18636 This function compares architectures of neural networks. Only geometries
18637 are compared, weights and other parameters are not tested.
18638 
18639  -- ALGLIB --
18640  Copyright 20.06.2013 by Bochkanov Sergey
18641 *************************************************************************/
18642 ae_bool mlpsamearchitecture(multilayerperceptron* network1,
18643  multilayerperceptron* network2,
18644  ae_state *_state)
18645 {
18646  ae_int_t i;
18647  ae_int_t ninfo;
18648  ae_bool result;
18649 
18650 
18651  ae_assert(network1->structinfo.cnt>0&&network1->structinfo.cnt>=network1->structinfo.ptr.p_int[0], "MLPSameArchitecture: Network1 is uninitialized", _state);
18652  ae_assert(network2->structinfo.cnt>0&&network2->structinfo.cnt>=network2->structinfo.ptr.p_int[0], "MLPSameArchitecture: Network2 is uninitialized", _state);
18653  result = ae_false;
18654  if( network1->structinfo.ptr.p_int[0]!=network2->structinfo.ptr.p_int[0] )
18655  {
18656  return result;
18657  }
18658  ninfo = network1->structinfo.ptr.p_int[0];
18659  for(i=0; i<=ninfo-1; i++)
18660  {
18661  if( network1->structinfo.ptr.p_int[i]!=network2->structinfo.ptr.p_int[i] )
18662  {
18663  return result;
18664  }
18665  }
18666  result = ae_true;
18667  return result;
18668 }
18669 
18670 
18671 /*************************************************************************
18672 This function copies tunable parameters (weights/means/sigmas) from one
18673 network to another with same architecture. It performs some rudimentary
18674 checks that architectures are same, and throws exception if check fails.
18675 
18676 It is intended for fast copying of states between two network which are
18677 known to have same geometry.
18678 
18679 INPUT PARAMETERS:
18680  Network1 - source, must be correctly initialized
18681  Network2 - target, must have same architecture
18682 
18683 OUTPUT PARAMETERS:
18684  Network2 - network state is copied from source to target
18685 
18686  -- ALGLIB --
18687  Copyright 20.06.2013 by Bochkanov Sergey
18688 *************************************************************************/
18689 void mlpcopytunableparameters(multilayerperceptron* network1,
18690  multilayerperceptron* network2,
18691  ae_state *_state)
18692 {
18693  ae_int_t i;
18694  ae_int_t ninfo;
18695  ae_int_t nin;
18696  ae_int_t nout;
18697  ae_int_t wcount;
18698 
18699 
18700  ae_assert(network1->structinfo.cnt>0&&network1->structinfo.cnt>=network1->structinfo.ptr.p_int[0], "MLPCopyTunableParameters: Network1 is uninitialized", _state);
18701  ae_assert(network2->structinfo.cnt>0&&network2->structinfo.cnt>=network2->structinfo.ptr.p_int[0], "MLPCopyTunableParameters: Network2 is uninitialized", _state);
18702  ae_assert(network1->structinfo.ptr.p_int[0]==network2->structinfo.ptr.p_int[0], "MLPCopyTunableParameters: Network1 geometry differs from that of Network2", _state);
18703  ninfo = network1->structinfo.ptr.p_int[0];
18704  for(i=0; i<=ninfo-1; i++)
18705  {
18706  ae_assert(network1->structinfo.ptr.p_int[i]==network2->structinfo.ptr.p_int[i], "MLPCopyTunableParameters: Network1 geometry differs from that of Network2", _state);
18707  }
18708  mlpproperties(network1, &nin, &nout, &wcount, _state);
18709  for(i=0; i<=wcount-1; i++)
18710  {
18711  network2->weights.ptr.p_double[i] = network1->weights.ptr.p_double[i];
18712  }
18713  if( mlpissoftmax(network1, _state) )
18714  {
18715  for(i=0; i<=nin-1; i++)
18716  {
18717  network2->columnmeans.ptr.p_double[i] = network1->columnmeans.ptr.p_double[i];
18718  network2->columnsigmas.ptr.p_double[i] = network1->columnsigmas.ptr.p_double[i];
18719  }
18720  }
18721  else
18722  {
18723  for(i=0; i<=nin+nout-1; i++)
18724  {
18725  network2->columnmeans.ptr.p_double[i] = network1->columnmeans.ptr.p_double[i];
18726  network2->columnsigmas.ptr.p_double[i] = network1->columnsigmas.ptr.p_double[i];
18727  }
18728  }
18729 }
18730 
18731 
18732 /*************************************************************************
18733 This function exports tunable parameters (weights/means/sigmas) from
18734 network to contiguous array. Nothing is guaranteed about array format, the
18735 only thing you can count for is that MLPImportTunableParameters() will be
18736 able to parse it.
18737 
18738 It is intended for fast copying of states between network and backup array
18739 
18740 INPUT PARAMETERS:
18741  Network - source, must be correctly initialized
18742  P - array to use. If its size is enough to store data, it
18743  is reused.
18744 
18745 OUTPUT PARAMETERS:
18746  P - array which stores network parameters, resized if needed
18747  PCount - number of parameters stored in array.
18748 
18749  -- ALGLIB --
18750  Copyright 20.06.2013 by Bochkanov Sergey
18751 *************************************************************************/
18752 void mlpexporttunableparameters(multilayerperceptron* network,
18753  /* Real */ ae_vector* p,
18754  ae_int_t* pcount,
18755  ae_state *_state)
18756 {
18757  ae_int_t i;
18758  ae_int_t k;
18759  ae_int_t nin;
18760  ae_int_t nout;
18761  ae_int_t wcount;
18762 
18763  *pcount = 0;
18764 
18765  ae_assert(network->structinfo.cnt>0&&network->structinfo.cnt>=network->structinfo.ptr.p_int[0], "MLPExportTunableParameters: Network is uninitialized", _state);
18766  mlpproperties(network, &nin, &nout, &wcount, _state);
18767  if( mlpissoftmax(network, _state) )
18768  {
18769  *pcount = wcount+2*nin;
18770  rvectorsetlengthatleast(p, *pcount, _state);
18771  k = 0;
18772  for(i=0; i<=wcount-1; i++)
18773  {
18774  p->ptr.p_double[k] = network->weights.ptr.p_double[i];
18775  k = k+1;
18776  }
18777  for(i=0; i<=nin-1; i++)
18778  {
18779  p->ptr.p_double[k] = network->columnmeans.ptr.p_double[i];
18780  k = k+1;
18781  p->ptr.p_double[k] = network->columnsigmas.ptr.p_double[i];
18782  k = k+1;
18783  }
18784  }
18785  else
18786  {
18787  *pcount = wcount+2*(nin+nout);
18788  rvectorsetlengthatleast(p, *pcount, _state);
18789  k = 0;
18790  for(i=0; i<=wcount-1; i++)
18791  {
18792  p->ptr.p_double[k] = network->weights.ptr.p_double[i];
18793  k = k+1;
18794  }
18795  for(i=0; i<=nin+nout-1; i++)
18796  {
18797  p->ptr.p_double[k] = network->columnmeans.ptr.p_double[i];
18798  k = k+1;
18799  p->ptr.p_double[k] = network->columnsigmas.ptr.p_double[i];
18800  k = k+1;
18801  }
18802  }
18803 }
18804 
18805 
18806 /*************************************************************************
18807 This function imports tunable parameters (weights/means/sigmas) which
18808 were exported by MLPExportTunableParameters().
18809 
18810 It is intended for fast copying of states between network and backup array
18811 
18812 INPUT PARAMETERS:
18813  Network - target:
18814  * must be correctly initialized
18815  * must have same geometry as network used to export params
18816  P - array with parameters
18817 
18818  -- ALGLIB --
18819  Copyright 20.06.2013 by Bochkanov Sergey
18820 *************************************************************************/
18821 void mlpimporttunableparameters(multilayerperceptron* network,
18822  /* Real */ ae_vector* p,
18823  ae_state *_state)
18824 {
18825  ae_int_t i;
18826  ae_int_t k;
18827  ae_int_t nin;
18828  ae_int_t nout;
18829  ae_int_t wcount;
18830 
18831 
18832  ae_assert(network->structinfo.cnt>0&&network->structinfo.cnt>=network->structinfo.ptr.p_int[0], "MLPImportTunableParameters: Network is uninitialized", _state);
18833  mlpproperties(network, &nin, &nout, &wcount, _state);
18834  if( mlpissoftmax(network, _state) )
18835  {
18836  k = 0;
18837  for(i=0; i<=wcount-1; i++)
18838  {
18839  network->weights.ptr.p_double[i] = p->ptr.p_double[k];
18840  k = k+1;
18841  }
18842  for(i=0; i<=nin-1; i++)
18843  {
18844  network->columnmeans.ptr.p_double[i] = p->ptr.p_double[k];
18845  k = k+1;
18846  network->columnsigmas.ptr.p_double[i] = p->ptr.p_double[k];
18847  k = k+1;
18848  }
18849  }
18850  else
18851  {
18852  k = 0;
18853  for(i=0; i<=wcount-1; i++)
18854  {
18855  network->weights.ptr.p_double[i] = p->ptr.p_double[k];
18856  k = k+1;
18857  }
18858  for(i=0; i<=nin+nout-1; i++)
18859  {
18860  network->columnmeans.ptr.p_double[i] = p->ptr.p_double[k];
18861  k = k+1;
18862  network->columnsigmas.ptr.p_double[i] = p->ptr.p_double[k];
18863  k = k+1;
18864  }
18865  }
18866 }
18867 
18868 
18869 /*************************************************************************
18870 Serialization of MultiLayerPerceptron strucure
18871 
18872 INPUT PARAMETERS:
18873  Network - original
18874 
18875 OUTPUT PARAMETERS:
18876  RA - array of real numbers which stores network,
18877  array[0..RLen-1]
18878  RLen - RA length
18879 
18880  -- ALGLIB --
18881  Copyright 29.03.2008 by Bochkanov Sergey
18882 *************************************************************************/
18883 void mlpserializeold(multilayerperceptron* network,
18884  /* Real */ ae_vector* ra,
18885  ae_int_t* rlen,
18886  ae_state *_state)
18887 {
18888  ae_int_t i;
18889  ae_int_t ssize;
18890  ae_int_t nin;
18891  ae_int_t nout;
18892  ae_int_t wcount;
18893  ae_int_t sigmalen;
18894  ae_int_t offs;
18895 
18896  ae_vector_clear(ra);
18897  *rlen = 0;
18898 
18899 
18900  /*
18901  * Unload info
18902  */
18903  ssize = network->structinfo.ptr.p_int[0];
18904  nin = network->structinfo.ptr.p_int[1];
18905  nout = network->structinfo.ptr.p_int[2];
18906  wcount = network->structinfo.ptr.p_int[4];
18907  if( mlpissoftmax(network, _state) )
18908  {
18909  sigmalen = nin;
18910  }
18911  else
18912  {
18913  sigmalen = nin+nout;
18914  }
18915 
18916  /*
18917  * RA format:
18918  * LEN DESRC.
18919  * 1 RLen
18920  * 1 version (MLPVNum)
18921  * 1 StructInfo size
18922  * SSize StructInfo
18923  * WCount Weights
18924  * SigmaLen ColumnMeans
18925  * SigmaLen ColumnSigmas
18926  */
18927  *rlen = 3+ssize+wcount+2*sigmalen;
18928  ae_vector_set_length(ra, *rlen-1+1, _state);
18929  ra->ptr.p_double[0] = *rlen;
18930  ra->ptr.p_double[1] = mlpbase_mlpvnum;
18931  ra->ptr.p_double[2] = ssize;
18932  offs = 3;
18933  for(i=0; i<=ssize-1; i++)
18934  {
18935  ra->ptr.p_double[offs+i] = network->structinfo.ptr.p_int[i];
18936  }
18937  offs = offs+ssize;
18938  ae_v_move(&ra->ptr.p_double[offs], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(offs,offs+wcount-1));
18939  offs = offs+wcount;
18940  ae_v_move(&ra->ptr.p_double[offs], 1, &network->columnmeans.ptr.p_double[0], 1, ae_v_len(offs,offs+sigmalen-1));
18941  offs = offs+sigmalen;
18942  ae_v_move(&ra->ptr.p_double[offs], 1, &network->columnsigmas.ptr.p_double[0], 1, ae_v_len(offs,offs+sigmalen-1));
18943  offs = offs+sigmalen;
18944 }
18945 
18946 
18947 /*************************************************************************
18948 Unserialization of MultiLayerPerceptron strucure
18949 
18950 INPUT PARAMETERS:
18951  RA - real array which stores network
18952 
18953 OUTPUT PARAMETERS:
18954  Network - restored network
18955 
18956  -- ALGLIB --
18957  Copyright 29.03.2008 by Bochkanov Sergey
18958 *************************************************************************/
18959 void mlpunserializeold(/* Real */ ae_vector* ra,
18960  multilayerperceptron* network,
18961  ae_state *_state)
18962 {
18963  ae_int_t i;
18964  ae_int_t ssize;
18965  ae_int_t ntotal;
18966  ae_int_t nin;
18967  ae_int_t nout;
18968  ae_int_t wcount;
18969  ae_int_t sigmalen;
18970  ae_int_t offs;
18971 
18972  _multilayerperceptron_clear(network);
18973 
18974  ae_assert(ae_round(ra->ptr.p_double[1], _state)==mlpbase_mlpvnum, "MLPUnserialize: incorrect array!", _state);
18975 
18976  /*
18977  * Unload StructInfo from IA
18978  */
18979  offs = 3;
18980  ssize = ae_round(ra->ptr.p_double[2], _state);
18981  ae_vector_set_length(&network->structinfo, ssize-1+1, _state);
18982  for(i=0; i<=ssize-1; i++)
18983  {
18984  network->structinfo.ptr.p_int[i] = ae_round(ra->ptr.p_double[offs+i], _state);
18985  }
18986  offs = offs+ssize;
18987 
18988  /*
18989  * Unload info from StructInfo
18990  */
18991  ssize = network->structinfo.ptr.p_int[0];
18992  nin = network->structinfo.ptr.p_int[1];
18993  nout = network->structinfo.ptr.p_int[2];
18994  ntotal = network->structinfo.ptr.p_int[3];
18995  wcount = network->structinfo.ptr.p_int[4];
18996  if( network->structinfo.ptr.p_int[6]==0 )
18997  {
18998  sigmalen = nin+nout;
18999  }
19000  else
19001  {
19002  sigmalen = nin;
19003  }
19004 
19005  /*
19006  * Allocate space for other fields
19007  */
19008  ae_vector_set_length(&network->weights, wcount-1+1, _state);
19009  ae_vector_set_length(&network->columnmeans, sigmalen-1+1, _state);
19010  ae_vector_set_length(&network->columnsigmas, sigmalen-1+1, _state);
19011  ae_vector_set_length(&network->neurons, ntotal-1+1, _state);
19012  ae_vector_set_length(&network->nwbuf, ae_maxint(wcount, 2*nout, _state)-1+1, _state);
19013  ae_vector_set_length(&network->dfdnet, ntotal-1+1, _state);
19014  ae_vector_set_length(&network->x, nin-1+1, _state);
19015  ae_vector_set_length(&network->y, nout-1+1, _state);
19016  ae_vector_set_length(&network->derror, ntotal-1+1, _state);
19017 
19018  /*
19019  * Copy parameters from RA
19020  */
19021  ae_v_move(&network->weights.ptr.p_double[0], 1, &ra->ptr.p_double[offs], 1, ae_v_len(0,wcount-1));
19022  offs = offs+wcount;
19023  ae_v_move(&network->columnmeans.ptr.p_double[0], 1, &ra->ptr.p_double[offs], 1, ae_v_len(0,sigmalen-1));
19024  offs = offs+sigmalen;
19025  ae_v_move(&network->columnsigmas.ptr.p_double[0], 1, &ra->ptr.p_double[offs], 1, ae_v_len(0,sigmalen-1));
19026  offs = offs+sigmalen;
19027 }
19028 
19029 
19030 /*************************************************************************
19031 Randomization of neural network weights
19032 
19033  -- ALGLIB --
19034  Copyright 06.11.2007 by Bochkanov Sergey
19035 *************************************************************************/
19036 void mlprandomize(multilayerperceptron* network, ae_state *_state)
19037 {
19038  ae_frame _frame_block;
19039  ae_int_t nin;
19040  ae_int_t nout;
19041  ae_int_t wcount;
19042  ae_int_t ntotal;
19043  ae_int_t istart;
19044  hqrndstate r;
19045  ae_int_t entrysize;
19046  ae_int_t entryoffs;
19047  ae_int_t neuronidx;
19048  ae_int_t neurontype;
19049  double vmean;
19050  double vvar;
19051  ae_int_t i;
19052  ae_int_t n1;
19053  ae_int_t n2;
19054  double desiredsigma;
19055  ae_int_t montecarlocnt;
19056  double ef;
19057  double ef2;
19058  double v;
19059  double wscale;
19060 
19061  ae_frame_make(_state, &_frame_block);
19062  _hqrndstate_init(&r, _state, ae_true);
19063 
19064  hqrndrandomize(&r, _state);
19065  mlpproperties(network, &nin, &nout, &wcount, _state);
19066  ntotal = network->structinfo.ptr.p_int[3];
19067  istart = network->structinfo.ptr.p_int[5];
19068  desiredsigma = 0.5;
19069  montecarlocnt = 20;
19070 
19071  /*
19072  * Stage 1:
19073  * * Network.Weights is filled by standard deviation of weights
19074  * * default values: sigma=1
19075  */
19076  for(i=0; i<=wcount-1; i++)
19077  {
19078  network->weights.ptr.p_double[i] = 1.0;
19079  }
19080 
19081  /*
19082  * Stage 2:
19083  * * assume that input neurons have zero mean and unit standard deviation
19084  * * assume that constant neurons have zero standard deviation
19085  * * perform forward pass along neurons
19086  * * for each non-input non-constant neuron:
19087  * * calculate mean and standard deviation of neuron's output
19088  * assuming that we know means/deviations of neurons which feed it
19089  * and assuming that weights has unit variance and zero mean.
19090  * * for each nonlinear neuron additionally we perform backward pass:
19091  * * scale variances of weights which feed it in such way that neuron's
19092  * input has unit standard deviation
19093  *
19094  * NOTE: this algorithm assumes that each connection feeds at most one
19095  * non-linear neuron. This assumption can be incorrect in upcoming
19096  * architectures with strong neurons. However, algorithm should
19097  * work smoothly even in this case.
19098  *
19099  * During this stage we use Network.RndBuf, which is grouped into NTotal
19100  * entries, each of them having following format:
19101  *
19102  * Buf[Offset+0] mean value of neuron's output
19103  * Buf[Offset+1] standard deviation of neuron's output
19104  *
19105  *
19106  */
19107  entrysize = 2;
19108  rvectorsetlengthatleast(&network->rndbuf, entrysize*ntotal, _state);
19109  for(neuronidx=0; neuronidx<=ntotal-1; neuronidx++)
19110  {
19111  neurontype = network->structinfo.ptr.p_int[istart+neuronidx*mlpbase_nfieldwidth+0];
19112  entryoffs = entrysize*neuronidx;
19113  if( neurontype==-2 )
19114  {
19115 
19116  /*
19117  * Input neuron: zero mean, unit variance.
19118  */
19119  network->rndbuf.ptr.p_double[entryoffs+0] = 0.0;
19120  network->rndbuf.ptr.p_double[entryoffs+1] = 1.0;
19121  continue;
19122  }
19123  if( neurontype==-3 )
19124  {
19125 
19126  /*
19127  * "-1" neuron: mean=-1, zero variance.
19128  */
19129  network->rndbuf.ptr.p_double[entryoffs+0] = -1.0;
19130  network->rndbuf.ptr.p_double[entryoffs+1] = 0.0;
19131  continue;
19132  }
19133  if( neurontype==-4 )
19134  {
19135 
19136  /*
19137  * "0" neuron: mean=0, zero variance.
19138  */
19139  network->rndbuf.ptr.p_double[entryoffs+0] = 0.0;
19140  network->rndbuf.ptr.p_double[entryoffs+1] = 0.0;
19141  continue;
19142  }
19143  if( neurontype==0 )
19144  {
19145 
19146  /*
19147  * Adaptive summator neuron:
19148  * * calculate its mean and variance.
19149  * * we assume that weights of this neuron have unit variance and zero mean.
19150  * * thus, neuron's output is always have zero mean
19151  * * as for variance, it is a bit more interesting:
19152  * * let n[i] is i-th input neuron
19153  * * let w[i] is i-th weight
19154  * * we assume that n[i] and w[i] are independently distributed
19155  * * Var(n0*w0+n1*w1+...) = Var(n0*w0)+Var(n1*w1)+...
19156  * * Var(X*Y) = mean(X)^2*Var(Y) + mean(Y)^2*Var(X) + Var(X)*Var(Y)
19157  * * mean(w[i])=0, var(w[i])=1
19158  * * Var(n[i]*w[i]) = mean(n[i])^2 + Var(n[i])
19159  */
19160  n1 = network->structinfo.ptr.p_int[istart+neuronidx*mlpbase_nfieldwidth+2];
19161  n2 = n1+network->structinfo.ptr.p_int[istart+neuronidx*mlpbase_nfieldwidth+1]-1;
19162  vmean = 0.0;
19163  vvar = 0.0;
19164  for(i=n1; i<=n2; i++)
19165  {
19166  vvar = vvar+ae_sqr(network->rndbuf.ptr.p_double[entrysize*i+0], _state)+ae_sqr(network->rndbuf.ptr.p_double[entrysize*i+1], _state);
19167  }
19168  network->rndbuf.ptr.p_double[entryoffs+0] = vmean;
19169  network->rndbuf.ptr.p_double[entryoffs+1] = ae_sqrt(vvar, _state);
19170  continue;
19171  }
19172  if( neurontype==-5 )
19173  {
19174 
19175  /*
19176  * Linear activation function
19177  */
19178  i = network->structinfo.ptr.p_int[istart+neuronidx*mlpbase_nfieldwidth+2];
19179  vmean = network->rndbuf.ptr.p_double[entrysize*i+0];
19180  vvar = ae_sqr(network->rndbuf.ptr.p_double[entrysize*i+1], _state);
19181  if( ae_fp_greater(vvar,0) )
19182  {
19183  wscale = desiredsigma/ae_sqrt(vvar, _state);
19184  }
19185  else
19186  {
19187  wscale = 1.0;
19188  }
19189  mlpbase_randomizebackwardpass(network, i, wscale, _state);
19190  network->rndbuf.ptr.p_double[entryoffs+0] = vmean*wscale;
19191  network->rndbuf.ptr.p_double[entryoffs+1] = desiredsigma;
19192  continue;
19193  }
19194  if( neurontype>0 )
19195  {
19196 
19197  /*
19198  * Nonlinear activation function:
19199  * * scale its inputs
19200  * * estimate mean/sigma of its output using Monte-Carlo method
19201  * (we simulate different inputs with unit deviation and
19202  * sample activation function output on such inputs)
19203  */
19204  i = network->structinfo.ptr.p_int[istart+neuronidx*mlpbase_nfieldwidth+2];
19205  vmean = network->rndbuf.ptr.p_double[entrysize*i+0];
19206  vvar = ae_sqr(network->rndbuf.ptr.p_double[entrysize*i+1], _state);
19207  if( ae_fp_greater(vvar,0) )
19208  {
19209  wscale = desiredsigma/ae_sqrt(vvar, _state);
19210  }
19211  else
19212  {
19213  wscale = 1.0;
19214  }
19215  mlpbase_randomizebackwardpass(network, i, wscale, _state);
19216  ef = 0.0;
19217  ef2 = 0.0;
19218  vmean = vmean*wscale;
19219  for(i=0; i<=montecarlocnt-1; i++)
19220  {
19221  v = vmean+desiredsigma*hqrndnormal(&r, _state);
19222  ef = ef+v;
19223  ef2 = ef2+v*v;
19224  }
19225  ef = ef/montecarlocnt;
19226  ef2 = ef2/montecarlocnt;
19227  network->rndbuf.ptr.p_double[entryoffs+0] = ef;
19228  network->rndbuf.ptr.p_double[entryoffs+1] = ae_maxreal(ef2-ef*ef, 0.0, _state);
19229  continue;
19230  }
19231  ae_assert(ae_false, "MLPRandomize: unexpected neuron type", _state);
19232  }
19233 
19234  /*
19235  * Stage 3: generate weights.
19236  */
19237  for(i=0; i<=wcount-1; i++)
19238  {
19239  network->weights.ptr.p_double[i] = network->weights.ptr.p_double[i]*hqrndnormal(&r, _state);
19240  }
19241  ae_frame_leave(_state);
19242 }
19243 
19244 
19245 /*************************************************************************
19246 Randomization of neural network weights and standartisator
19247 
19248  -- ALGLIB --
19249  Copyright 10.03.2008 by Bochkanov Sergey
19250 *************************************************************************/
19251 void mlprandomizefull(multilayerperceptron* network, ae_state *_state)
19252 {
19253  ae_int_t i;
19254  ae_int_t nin;
19255  ae_int_t nout;
19256  ae_int_t wcount;
19257  ae_int_t ntotal;
19258  ae_int_t istart;
19259  ae_int_t offs;
19260  ae_int_t ntype;
19261 
19262 
19263  mlpproperties(network, &nin, &nout, &wcount, _state);
19264  ntotal = network->structinfo.ptr.p_int[3];
19265  istart = network->structinfo.ptr.p_int[5];
19266 
19267  /*
19268  * Process network
19269  */
19270  mlprandomize(network, _state);
19271  for(i=0; i<=nin-1; i++)
19272  {
19273  network->columnmeans.ptr.p_double[i] = ae_randomreal(_state)-0.5;
19274  network->columnsigmas.ptr.p_double[i] = ae_randomreal(_state)+0.5;
19275  }
19276  if( !mlpissoftmax(network, _state) )
19277  {
19278  for(i=0; i<=nout-1; i++)
19279  {
19280  offs = istart+(ntotal-nout+i)*mlpbase_nfieldwidth;
19281  ntype = network->structinfo.ptr.p_int[offs+0];
19282  if( ntype==0 )
19283  {
19284 
19285  /*
19286  * Shifts are changed only for linear outputs neurons
19287  */
19288  network->columnmeans.ptr.p_double[nin+i] = 2*ae_randomreal(_state)-1;
19289  }
19290  if( ntype==0||ntype==3 )
19291  {
19292 
19293  /*
19294  * Scales are changed only for linear or bounded outputs neurons.
19295  * Note that scale randomization preserves sign.
19296  */
19297  network->columnsigmas.ptr.p_double[nin+i] = ae_sign(network->columnsigmas.ptr.p_double[nin+i], _state)*(1.5*ae_randomreal(_state)+0.5);
19298  }
19299  }
19300  }
19301 }
19302 
19303 
19304 /*************************************************************************
19305 Internal subroutine.
19306 
19307  -- ALGLIB --
19308  Copyright 30.03.2008 by Bochkanov Sergey
19309 *************************************************************************/
19310 void mlpinitpreprocessor(multilayerperceptron* network,
19311  /* Real */ ae_matrix* xy,
19312  ae_int_t ssize,
19313  ae_state *_state)
19314 {
19315  ae_frame _frame_block;
19316  ae_int_t i;
19317  ae_int_t j;
19318  ae_int_t jmax;
19319  ae_int_t nin;
19320  ae_int_t nout;
19321  ae_int_t wcount;
19322  ae_int_t ntotal;
19323  ae_int_t istart;
19324  ae_int_t offs;
19325  ae_int_t ntype;
19326  ae_vector means;
19327  ae_vector sigmas;
19328  double s;
19329 
19330  ae_frame_make(_state, &_frame_block);
19331  ae_vector_init(&means, 0, DT_REAL, _state, ae_true);
19332  ae_vector_init(&sigmas, 0, DT_REAL, _state, ae_true);
19333 
19334  mlpproperties(network, &nin, &nout, &wcount, _state);
19335  ntotal = network->structinfo.ptr.p_int[3];
19336  istart = network->structinfo.ptr.p_int[5];
19337 
19338  /*
19339  * Means/Sigmas
19340  */
19341  if( mlpissoftmax(network, _state) )
19342  {
19343  jmax = nin-1;
19344  }
19345  else
19346  {
19347  jmax = nin+nout-1;
19348  }
19349  ae_vector_set_length(&means, jmax+1, _state);
19350  ae_vector_set_length(&sigmas, jmax+1, _state);
19351  for(i=0; i<=jmax; i++)
19352  {
19353  means.ptr.p_double[i] = 0;
19354  sigmas.ptr.p_double[i] = 0;
19355  }
19356  for(i=0; i<=ssize-1; i++)
19357  {
19358  for(j=0; j<=jmax; j++)
19359  {
19360  means.ptr.p_double[j] = means.ptr.p_double[j]+xy->ptr.pp_double[i][j];
19361  }
19362  }
19363  for(i=0; i<=jmax; i++)
19364  {
19365  means.ptr.p_double[i] = means.ptr.p_double[i]/ssize;
19366  }
19367  for(i=0; i<=ssize-1; i++)
19368  {
19369  for(j=0; j<=jmax; j++)
19370  {
19371  sigmas.ptr.p_double[j] = sigmas.ptr.p_double[j]+ae_sqr(xy->ptr.pp_double[i][j]-means.ptr.p_double[j], _state);
19372  }
19373  }
19374  for(i=0; i<=jmax; i++)
19375  {
19376  sigmas.ptr.p_double[i] = ae_sqrt(sigmas.ptr.p_double[i]/ssize, _state);
19377  }
19378 
19379  /*
19380  * Inputs
19381  */
19382  for(i=0; i<=nin-1; i++)
19383  {
19384  network->columnmeans.ptr.p_double[i] = means.ptr.p_double[i];
19385  network->columnsigmas.ptr.p_double[i] = sigmas.ptr.p_double[i];
19386  if( ae_fp_eq(network->columnsigmas.ptr.p_double[i],0) )
19387  {
19388  network->columnsigmas.ptr.p_double[i] = 1;
19389  }
19390  }
19391 
19392  /*
19393  * Outputs
19394  */
19395  if( !mlpissoftmax(network, _state) )
19396  {
19397  for(i=0; i<=nout-1; i++)
19398  {
19399  offs = istart+(ntotal-nout+i)*mlpbase_nfieldwidth;
19400  ntype = network->structinfo.ptr.p_int[offs+0];
19401 
19402  /*
19403  * Linear outputs
19404  */
19405  if( ntype==0 )
19406  {
19407  network->columnmeans.ptr.p_double[nin+i] = means.ptr.p_double[nin+i];
19408  network->columnsigmas.ptr.p_double[nin+i] = sigmas.ptr.p_double[nin+i];
19409  if( ae_fp_eq(network->columnsigmas.ptr.p_double[nin+i],0) )
19410  {
19411  network->columnsigmas.ptr.p_double[nin+i] = 1;
19412  }
19413  }
19414 
19415  /*
19416  * Bounded outputs (half-interval)
19417  */
19418  if( ntype==3 )
19419  {
19420  s = means.ptr.p_double[nin+i]-network->columnmeans.ptr.p_double[nin+i];
19421  if( ae_fp_eq(s,0) )
19422  {
19423  s = ae_sign(network->columnsigmas.ptr.p_double[nin+i], _state);
19424  }
19425  if( ae_fp_eq(s,0) )
19426  {
19427  s = 1.0;
19428  }
19429  network->columnsigmas.ptr.p_double[nin+i] = ae_sign(network->columnsigmas.ptr.p_double[nin+i], _state)*ae_fabs(s, _state);
19430  if( ae_fp_eq(network->columnsigmas.ptr.p_double[nin+i],0) )
19431  {
19432  network->columnsigmas.ptr.p_double[nin+i] = 1;
19433  }
19434  }
19435  }
19436  }
19437  ae_frame_leave(_state);
19438 }
19439 
19440 
19441 /*************************************************************************
19442 Internal subroutine.
19443 Initialization for preprocessor based on a sample.
19444 
19445 INPUT
19446  Network - initialized neural network;
19447  XY - sample, given by sparse matrix;
19448  SSize - sample size.
19449 
19450 OUTPUT
19451  Network - neural network with initialised preprocessor.
19452 
19453  -- ALGLIB --
19454  Copyright 26.07.2012 by Bochkanov Sergey
19455 *************************************************************************/
19456 void mlpinitpreprocessorsparse(multilayerperceptron* network,
19457  sparsematrix* xy,
19458  ae_int_t ssize,
19459  ae_state *_state)
19460 {
19461  ae_frame _frame_block;
19462  ae_int_t jmax;
19463  ae_int_t nin;
19464  ae_int_t nout;
19465  ae_int_t wcount;
19466  ae_int_t ntotal;
19467  ae_int_t istart;
19468  ae_int_t offs;
19469  ae_int_t ntype;
19470  ae_vector means;
19471  ae_vector sigmas;
19472  double s;
19473  ae_int_t i;
19474  ae_int_t j;
19475 
19476  ae_frame_make(_state, &_frame_block);
19477  ae_vector_init(&means, 0, DT_REAL, _state, ae_true);
19478  ae_vector_init(&sigmas, 0, DT_REAL, _state, ae_true);
19479 
19480  mlpproperties(network, &nin, &nout, &wcount, _state);
19481  ntotal = network->structinfo.ptr.p_int[3];
19482  istart = network->structinfo.ptr.p_int[5];
19483 
19484  /*
19485  * Means/Sigmas
19486  */
19487  if( mlpissoftmax(network, _state) )
19488  {
19489  jmax = nin-1;
19490  }
19491  else
19492  {
19493  jmax = nin+nout-1;
19494  }
19495  ae_vector_set_length(&means, jmax+1, _state);
19496  ae_vector_set_length(&sigmas, jmax+1, _state);
19497  for(i=0; i<=jmax; i++)
19498  {
19499  means.ptr.p_double[i] = 0;
19500  sigmas.ptr.p_double[i] = 0;
19501  }
19502  for(i=0; i<=ssize-1; i++)
19503  {
19504  sparsegetrow(xy, i, &network->xyrow, _state);
19505  for(j=0; j<=jmax; j++)
19506  {
19507  means.ptr.p_double[j] = means.ptr.p_double[j]+network->xyrow.ptr.p_double[j];
19508  }
19509  }
19510  for(i=0; i<=jmax; i++)
19511  {
19512  means.ptr.p_double[i] = means.ptr.p_double[i]/ssize;
19513  }
19514  for(i=0; i<=ssize-1; i++)
19515  {
19516  sparsegetrow(xy, i, &network->xyrow, _state);
19517  for(j=0; j<=jmax; j++)
19518  {
19519  sigmas.ptr.p_double[j] = sigmas.ptr.p_double[j]+ae_sqr(network->xyrow.ptr.p_double[j]-means.ptr.p_double[j], _state);
19520  }
19521  }
19522  for(i=0; i<=jmax; i++)
19523  {
19524  sigmas.ptr.p_double[i] = ae_sqrt(sigmas.ptr.p_double[i]/ssize, _state);
19525  }
19526 
19527  /*
19528  * Inputs
19529  */
19530  for(i=0; i<=nin-1; i++)
19531  {
19532  network->columnmeans.ptr.p_double[i] = means.ptr.p_double[i];
19533  network->columnsigmas.ptr.p_double[i] = sigmas.ptr.p_double[i];
19534  if( ae_fp_eq(network->columnsigmas.ptr.p_double[i],0) )
19535  {
19536  network->columnsigmas.ptr.p_double[i] = 1;
19537  }
19538  }
19539 
19540  /*
19541  * Outputs
19542  */
19543  if( !mlpissoftmax(network, _state) )
19544  {
19545  for(i=0; i<=nout-1; i++)
19546  {
19547  offs = istart+(ntotal-nout+i)*mlpbase_nfieldwidth;
19548  ntype = network->structinfo.ptr.p_int[offs+0];
19549 
19550  /*
19551  * Linear outputs
19552  */
19553  if( ntype==0 )
19554  {
19555  network->columnmeans.ptr.p_double[nin+i] = means.ptr.p_double[nin+i];
19556  network->columnsigmas.ptr.p_double[nin+i] = sigmas.ptr.p_double[nin+i];
19557  if( ae_fp_eq(network->columnsigmas.ptr.p_double[nin+i],0) )
19558  {
19559  network->columnsigmas.ptr.p_double[nin+i] = 1;
19560  }
19561  }
19562 
19563  /*
19564  * Bounded outputs (half-interval)
19565  */
19566  if( ntype==3 )
19567  {
19568  s = means.ptr.p_double[nin+i]-network->columnmeans.ptr.p_double[nin+i];
19569  if( ae_fp_eq(s,0) )
19570  {
19571  s = ae_sign(network->columnsigmas.ptr.p_double[nin+i], _state);
19572  }
19573  if( ae_fp_eq(s,0) )
19574  {
19575  s = 1.0;
19576  }
19577  network->columnsigmas.ptr.p_double[nin+i] = ae_sign(network->columnsigmas.ptr.p_double[nin+i], _state)*ae_fabs(s, _state);
19578  if( ae_fp_eq(network->columnsigmas.ptr.p_double[nin+i],0) )
19579  {
19580  network->columnsigmas.ptr.p_double[nin+i] = 1;
19581  }
19582  }
19583  }
19584  }
19585  ae_frame_leave(_state);
19586 }
19587 
19588 
19589 /*************************************************************************
19590 Internal subroutine.
19591 Initialization for preprocessor based on a subsample.
19592 
19593 INPUT PARAMETERS:
19594  Network - network initialized with one of the network creation funcs
19595  XY - original dataset; one sample = one row;
19596  first NIn columns contain inputs,
19597  next NOut columns - desired outputs.
19598  SetSize - real size of XY, SetSize>=0;
19599  Idx - subset of SubsetSize elements, array[SubsetSize]:
19600  * Idx[I] stores row index in the original dataset which is
19601  given by XY. Gradient is calculated with respect to rows
19602  whose indexes are stored in Idx[].
19603  * Idx[] must store correct indexes; this function throws
19604  an exception in case incorrect index (less than 0 or
19605  larger than rows(XY)) is given
19606  * Idx[] may store indexes in any order and even with
19607  repetitions.
19608  SubsetSize- number of elements in Idx[] array.
19609 
19610 OUTPUT:
19611  Network - neural network with initialised preprocessor.
19612 
19613 NOTE: when SubsetSize<0 is used full dataset by call MLPInitPreprocessor
19614  function.
19615 
19616  -- ALGLIB --
19617  Copyright 23.08.2012 by Bochkanov Sergey
19618 *************************************************************************/
19619 void mlpinitpreprocessorsubset(multilayerperceptron* network,
19620  /* Real */ ae_matrix* xy,
19621  ae_int_t setsize,
19622  /* Integer */ ae_vector* idx,
19623  ae_int_t subsetsize,
19624  ae_state *_state)
19625 {
19626  ae_frame _frame_block;
19627  ae_int_t jmax;
19628  ae_int_t nin;
19629  ae_int_t nout;
19630  ae_int_t wcount;
19631  ae_int_t ntotal;
19632  ae_int_t istart;
19633  ae_int_t offs;
19634  ae_int_t ntype;
19635  ae_vector means;
19636  ae_vector sigmas;
19637  double s;
19638  ae_int_t npoints;
19639  ae_int_t i;
19640  ae_int_t j;
19641 
19642  ae_frame_make(_state, &_frame_block);
19643  ae_vector_init(&means, 0, DT_REAL, _state, ae_true);
19644  ae_vector_init(&sigmas, 0, DT_REAL, _state, ae_true);
19645 
19646  ae_assert(setsize>=0, "MLPInitPreprocessorSubset: SetSize<0", _state);
19647  if( subsetsize<0 )
19648  {
19649  mlpinitpreprocessor(network, xy, setsize, _state);
19650  ae_frame_leave(_state);
19651  return;
19652  }
19653  ae_assert(subsetsize<=idx->cnt, "MLPInitPreprocessorSubset: SubsetSize>Length(Idx)", _state);
19654  npoints = setsize;
19655  for(i=0; i<=subsetsize-1; i++)
19656  {
19657  ae_assert(idx->ptr.p_int[i]>=0, "MLPInitPreprocessorSubset: incorrect index of XY row(Idx[I]<0)", _state);
19658  ae_assert(idx->ptr.p_int[i]<=npoints-1, "MLPInitPreprocessorSubset: incorrect index of XY row(Idx[I]>Rows(XY)-1)", _state);
19659  }
19660  mlpproperties(network, &nin, &nout, &wcount, _state);
19661  ntotal = network->structinfo.ptr.p_int[3];
19662  istart = network->structinfo.ptr.p_int[5];
19663 
19664  /*
19665  * Means/Sigmas
19666  */
19667  if( mlpissoftmax(network, _state) )
19668  {
19669  jmax = nin-1;
19670  }
19671  else
19672  {
19673  jmax = nin+nout-1;
19674  }
19675  ae_vector_set_length(&means, jmax+1, _state);
19676  ae_vector_set_length(&sigmas, jmax+1, _state);
19677  for(i=0; i<=jmax; i++)
19678  {
19679  means.ptr.p_double[i] = 0;
19680  sigmas.ptr.p_double[i] = 0;
19681  }
19682  for(i=0; i<=subsetsize-1; i++)
19683  {
19684  for(j=0; j<=jmax; j++)
19685  {
19686  means.ptr.p_double[j] = means.ptr.p_double[j]+xy->ptr.pp_double[idx->ptr.p_int[i]][j];
19687  }
19688  }
19689  for(i=0; i<=jmax; i++)
19690  {
19691  means.ptr.p_double[i] = means.ptr.p_double[i]/subsetsize;
19692  }
19693  for(i=0; i<=subsetsize-1; i++)
19694  {
19695  for(j=0; j<=jmax; j++)
19696  {
19697  sigmas.ptr.p_double[j] = sigmas.ptr.p_double[j]+ae_sqr(xy->ptr.pp_double[idx->ptr.p_int[i]][j]-means.ptr.p_double[j], _state);
19698  }
19699  }
19700  for(i=0; i<=jmax; i++)
19701  {
19702  sigmas.ptr.p_double[i] = ae_sqrt(sigmas.ptr.p_double[i]/subsetsize, _state);
19703  }
19704 
19705  /*
19706  * Inputs
19707  */
19708  for(i=0; i<=nin-1; i++)
19709  {
19710  network->columnmeans.ptr.p_double[i] = means.ptr.p_double[i];
19711  network->columnsigmas.ptr.p_double[i] = sigmas.ptr.p_double[i];
19712  if( ae_fp_eq(network->columnsigmas.ptr.p_double[i],0) )
19713  {
19714  network->columnsigmas.ptr.p_double[i] = 1;
19715  }
19716  }
19717 
19718  /*
19719  * Outputs
19720  */
19721  if( !mlpissoftmax(network, _state) )
19722  {
19723  for(i=0; i<=nout-1; i++)
19724  {
19725  offs = istart+(ntotal-nout+i)*mlpbase_nfieldwidth;
19726  ntype = network->structinfo.ptr.p_int[offs+0];
19727 
19728  /*
19729  * Linear outputs
19730  */
19731  if( ntype==0 )
19732  {
19733  network->columnmeans.ptr.p_double[nin+i] = means.ptr.p_double[nin+i];
19734  network->columnsigmas.ptr.p_double[nin+i] = sigmas.ptr.p_double[nin+i];
19735  if( ae_fp_eq(network->columnsigmas.ptr.p_double[nin+i],0) )
19736  {
19737  network->columnsigmas.ptr.p_double[nin+i] = 1;
19738  }
19739  }
19740 
19741  /*
19742  * Bounded outputs (half-interval)
19743  */
19744  if( ntype==3 )
19745  {
19746  s = means.ptr.p_double[nin+i]-network->columnmeans.ptr.p_double[nin+i];
19747  if( ae_fp_eq(s,0) )
19748  {
19749  s = ae_sign(network->columnsigmas.ptr.p_double[nin+i], _state);
19750  }
19751  if( ae_fp_eq(s,0) )
19752  {
19753  s = 1.0;
19754  }
19755  network->columnsigmas.ptr.p_double[nin+i] = ae_sign(network->columnsigmas.ptr.p_double[nin+i], _state)*ae_fabs(s, _state);
19756  if( ae_fp_eq(network->columnsigmas.ptr.p_double[nin+i],0) )
19757  {
19758  network->columnsigmas.ptr.p_double[nin+i] = 1;
19759  }
19760  }
19761  }
19762  }
19763  ae_frame_leave(_state);
19764 }
19765 
19766 
19767 /*************************************************************************
19768 Internal subroutine.
19769 Initialization for preprocessor based on a subsample.
19770 
19771 INPUT PARAMETERS:
19772  Network - network initialized with one of the network creation funcs
19773  XY - original dataset, given by sparse matrix;
19774  one sample = one row;
19775  first NIn columns contain inputs,
19776  next NOut columns - desired outputs.
19777  SetSize - real size of XY, SetSize>=0;
19778  Idx - subset of SubsetSize elements, array[SubsetSize]:
19779  * Idx[I] stores row index in the original dataset which is
19780  given by XY. Gradient is calculated with respect to rows
19781  whose indexes are stored in Idx[].
19782  * Idx[] must store correct indexes; this function throws
19783  an exception in case incorrect index (less than 0 or
19784  larger than rows(XY)) is given
19785  * Idx[] may store indexes in any order and even with
19786  repetitions.
19787  SubsetSize- number of elements in Idx[] array.
19788 
19789 OUTPUT:
19790  Network - neural network with initialised preprocessor.
19791 
19792 NOTE: when SubsetSize<0 is used full dataset by call
19793  MLPInitPreprocessorSparse function.
19794 
19795  -- ALGLIB --
19796  Copyright 26.07.2012 by Bochkanov Sergey
19797 *************************************************************************/
19798 void mlpinitpreprocessorsparsesubset(multilayerperceptron* network,
19799  sparsematrix* xy,
19800  ae_int_t setsize,
19801  /* Integer */ ae_vector* idx,
19802  ae_int_t subsetsize,
19803  ae_state *_state)
19804 {
19805  ae_frame _frame_block;
19806  ae_int_t jmax;
19807  ae_int_t nin;
19808  ae_int_t nout;
19809  ae_int_t wcount;
19810  ae_int_t ntotal;
19811  ae_int_t istart;
19812  ae_int_t offs;
19813  ae_int_t ntype;
19814  ae_vector means;
19815  ae_vector sigmas;
19816  double s;
19817  ae_int_t npoints;
19818  ae_int_t i;
19819  ae_int_t j;
19820 
19821  ae_frame_make(_state, &_frame_block);
19822  ae_vector_init(&means, 0, DT_REAL, _state, ae_true);
19823  ae_vector_init(&sigmas, 0, DT_REAL, _state, ae_true);
19824 
19825  ae_assert(setsize>=0, "MLPInitPreprocessorSparseSubset: SetSize<0", _state);
19826  if( subsetsize<0 )
19827  {
19828  mlpinitpreprocessorsparse(network, xy, setsize, _state);
19829  ae_frame_leave(_state);
19830  return;
19831  }
19832  ae_assert(subsetsize<=idx->cnt, "MLPInitPreprocessorSparseSubset: SubsetSize>Length(Idx)", _state);
19833  npoints = setsize;
19834  for(i=0; i<=subsetsize-1; i++)
19835  {
19836  ae_assert(idx->ptr.p_int[i]>=0, "MLPInitPreprocessorSparseSubset: incorrect index of XY row(Idx[I]<0)", _state);
19837  ae_assert(idx->ptr.p_int[i]<=npoints-1, "MLPInitPreprocessorSparseSubset: incorrect index of XY row(Idx[I]>Rows(XY)-1)", _state);
19838  }
19839  mlpproperties(network, &nin, &nout, &wcount, _state);
19840  ntotal = network->structinfo.ptr.p_int[3];
19841  istart = network->structinfo.ptr.p_int[5];
19842 
19843  /*
19844  * Means/Sigmas
19845  */
19846  if( mlpissoftmax(network, _state) )
19847  {
19848  jmax = nin-1;
19849  }
19850  else
19851  {
19852  jmax = nin+nout-1;
19853  }
19854  ae_vector_set_length(&means, jmax+1, _state);
19855  ae_vector_set_length(&sigmas, jmax+1, _state);
19856  for(i=0; i<=jmax; i++)
19857  {
19858  means.ptr.p_double[i] = 0;
19859  sigmas.ptr.p_double[i] = 0;
19860  }
19861  for(i=0; i<=subsetsize-1; i++)
19862  {
19863  sparsegetrow(xy, idx->ptr.p_int[i], &network->xyrow, _state);
19864  for(j=0; j<=jmax; j++)
19865  {
19866  means.ptr.p_double[j] = means.ptr.p_double[j]+network->xyrow.ptr.p_double[j];
19867  }
19868  }
19869  for(i=0; i<=jmax; i++)
19870  {
19871  means.ptr.p_double[i] = means.ptr.p_double[i]/subsetsize;
19872  }
19873  for(i=0; i<=subsetsize-1; i++)
19874  {
19875  sparsegetrow(xy, idx->ptr.p_int[i], &network->xyrow, _state);
19876  for(j=0; j<=jmax; j++)
19877  {
19878  sigmas.ptr.p_double[j] = sigmas.ptr.p_double[j]+ae_sqr(network->xyrow.ptr.p_double[j]-means.ptr.p_double[j], _state);
19879  }
19880  }
19881  for(i=0; i<=jmax; i++)
19882  {
19883  sigmas.ptr.p_double[i] = ae_sqrt(sigmas.ptr.p_double[i]/subsetsize, _state);
19884  }
19885 
19886  /*
19887  * Inputs
19888  */
19889  for(i=0; i<=nin-1; i++)
19890  {
19891  network->columnmeans.ptr.p_double[i] = means.ptr.p_double[i];
19892  network->columnsigmas.ptr.p_double[i] = sigmas.ptr.p_double[i];
19893  if( ae_fp_eq(network->columnsigmas.ptr.p_double[i],0) )
19894  {
19895  network->columnsigmas.ptr.p_double[i] = 1;
19896  }
19897  }
19898 
19899  /*
19900  * Outputs
19901  */
19902  if( !mlpissoftmax(network, _state) )
19903  {
19904  for(i=0; i<=nout-1; i++)
19905  {
19906  offs = istart+(ntotal-nout+i)*mlpbase_nfieldwidth;
19907  ntype = network->structinfo.ptr.p_int[offs+0];
19908 
19909  /*
19910  * Linear outputs
19911  */
19912  if( ntype==0 )
19913  {
19914  network->columnmeans.ptr.p_double[nin+i] = means.ptr.p_double[nin+i];
19915  network->columnsigmas.ptr.p_double[nin+i] = sigmas.ptr.p_double[nin+i];
19916  if( ae_fp_eq(network->columnsigmas.ptr.p_double[nin+i],0) )
19917  {
19918  network->columnsigmas.ptr.p_double[nin+i] = 1;
19919  }
19920  }
19921 
19922  /*
19923  * Bounded outputs (half-interval)
19924  */
19925  if( ntype==3 )
19926  {
19927  s = means.ptr.p_double[nin+i]-network->columnmeans.ptr.p_double[nin+i];
19928  if( ae_fp_eq(s,0) )
19929  {
19930  s = ae_sign(network->columnsigmas.ptr.p_double[nin+i], _state);
19931  }
19932  if( ae_fp_eq(s,0) )
19933  {
19934  s = 1.0;
19935  }
19936  network->columnsigmas.ptr.p_double[nin+i] = ae_sign(network->columnsigmas.ptr.p_double[nin+i], _state)*ae_fabs(s, _state);
19937  if( ae_fp_eq(network->columnsigmas.ptr.p_double[nin+i],0) )
19938  {
19939  network->columnsigmas.ptr.p_double[nin+i] = 1;
19940  }
19941  }
19942  }
19943  }
19944  ae_frame_leave(_state);
19945 }
19946 
19947 
19948 /*************************************************************************
19949 Returns information about initialized network: number of inputs, outputs,
19950 weights.
19951 
19952  -- ALGLIB --
19953  Copyright 04.11.2007 by Bochkanov Sergey
19954 *************************************************************************/
19955 void mlpproperties(multilayerperceptron* network,
19956  ae_int_t* nin,
19957  ae_int_t* nout,
19958  ae_int_t* wcount,
19959  ae_state *_state)
19960 {
19961 
19962  *nin = 0;
19963  *nout = 0;
19964  *wcount = 0;
19965 
19966  *nin = network->structinfo.ptr.p_int[1];
19967  *nout = network->structinfo.ptr.p_int[2];
19968  *wcount = network->structinfo.ptr.p_int[4];
19969 }
19970 
19971 
19972 /*************************************************************************
19973 Returns number of "internal", low-level neurons in the network (one which
19974 is stored in StructInfo).
19975 
19976  -- ALGLIB --
19977  Copyright 04.11.2007 by Bochkanov Sergey
19978 *************************************************************************/
19979 ae_int_t mlpntotal(multilayerperceptron* network, ae_state *_state)
19980 {
19981  ae_int_t result;
19982 
19983 
19984  result = network->structinfo.ptr.p_int[3];
19985  return result;
19986 }
19987 
19988 
19989 /*************************************************************************
19990 Returns number of inputs.
19991 
19992  -- ALGLIB --
19993  Copyright 19.10.2011 by Bochkanov Sergey
19994 *************************************************************************/
19995 ae_int_t mlpgetinputscount(multilayerperceptron* network,
19996  ae_state *_state)
19997 {
19998  ae_int_t result;
19999 
20000 
20001  result = network->structinfo.ptr.p_int[1];
20002  return result;
20003 }
20004 
20005 
20006 /*************************************************************************
20007 Returns number of outputs.
20008 
20009  -- ALGLIB --
20010  Copyright 19.10.2011 by Bochkanov Sergey
20011 *************************************************************************/
20012 ae_int_t mlpgetoutputscount(multilayerperceptron* network,
20013  ae_state *_state)
20014 {
20015  ae_int_t result;
20016 
20017 
20018  result = network->structinfo.ptr.p_int[2];
20019  return result;
20020 }
20021 
20022 
20023 /*************************************************************************
20024 Returns number of weights.
20025 
20026  -- ALGLIB --
20027  Copyright 19.10.2011 by Bochkanov Sergey
20028 *************************************************************************/
20029 ae_int_t mlpgetweightscount(multilayerperceptron* network,
20030  ae_state *_state)
20031 {
20032  ae_int_t result;
20033 
20034 
20035  result = network->structinfo.ptr.p_int[4];
20036  return result;
20037 }
20038 
20039 
20040 /*************************************************************************
20041 Tells whether network is SOFTMAX-normalized (i.e. classifier) or not.
20042 
20043  -- ALGLIB --
20044  Copyright 04.11.2007 by Bochkanov Sergey
20045 *************************************************************************/
20046 ae_bool mlpissoftmax(multilayerperceptron* network, ae_state *_state)
20047 {
20048  ae_bool result;
20049 
20050 
20051  result = network->structinfo.ptr.p_int[6]==1;
20052  return result;
20053 }
20054 
20055 
20056 /*************************************************************************
20057 This function returns total number of layers (including input, hidden and
20058 output layers).
20059 
20060  -- ALGLIB --
20061  Copyright 25.03.2011 by Bochkanov Sergey
20062 *************************************************************************/
20063 ae_int_t mlpgetlayerscount(multilayerperceptron* network,
20064  ae_state *_state)
20065 {
20066  ae_int_t result;
20067 
20068 
20069  result = network->hllayersizes.cnt;
20070  return result;
20071 }
20072 
20073 
20074 /*************************************************************************
20075 This function returns size of K-th layer.
20076 
20077 K=0 corresponds to input layer, K=CNT-1 corresponds to output layer.
20078 
20079 Size of the output layer is always equal to the number of outputs, although
20080 when we have softmax-normalized network, last neuron doesn't have any
20081 connections - it is just zero.
20082 
20083  -- ALGLIB --
20084  Copyright 25.03.2011 by Bochkanov Sergey
20085 *************************************************************************/
20086 ae_int_t mlpgetlayersize(multilayerperceptron* network,
20087  ae_int_t k,
20088  ae_state *_state)
20089 {
20090  ae_int_t result;
20091 
20092 
20093  ae_assert(k>=0&&k<network->hllayersizes.cnt, "MLPGetLayerSize: incorrect layer index", _state);
20094  result = network->hllayersizes.ptr.p_int[k];
20095  return result;
20096 }
20097 
20098 
20099 /*************************************************************************
20100 This function returns offset/scaling coefficients for I-th input of the
20101 network.
20102 
20103 INPUT PARAMETERS:
20104  Network - network
20105  I - input index
20106 
20107 OUTPUT PARAMETERS:
20108  Mean - mean term
20109  Sigma - sigma term, guaranteed to be nonzero.
20110 
20111 I-th input is passed through linear transformation
20112  IN[i] = (IN[i]-Mean)/Sigma
20113 before feeding to the network
20114 
20115  -- ALGLIB --
20116  Copyright 25.03.2011 by Bochkanov Sergey
20117 *************************************************************************/
20118 void mlpgetinputscaling(multilayerperceptron* network,
20119  ae_int_t i,
20120  double* mean,
20121  double* sigma,
20122  ae_state *_state)
20123 {
20124 
20125  *mean = 0;
20126  *sigma = 0;
20127 
20128  ae_assert(i>=0&&i<network->hllayersizes.ptr.p_int[0], "MLPGetInputScaling: incorrect (nonexistent) I", _state);
20129  *mean = network->columnmeans.ptr.p_double[i];
20130  *sigma = network->columnsigmas.ptr.p_double[i];
20131  if( ae_fp_eq(*sigma,0) )
20132  {
20133  *sigma = 1;
20134  }
20135 }
20136 
20137 
20138 /*************************************************************************
20139 This function returns offset/scaling coefficients for I-th output of the
20140 network.
20141 
20142 INPUT PARAMETERS:
20143  Network - network
20144  I - input index
20145 
20146 OUTPUT PARAMETERS:
20147  Mean - mean term
20148  Sigma - sigma term, guaranteed to be nonzero.
20149 
20150 I-th output is passed through linear transformation
20151  OUT[i] = OUT[i]*Sigma+Mean
20152 before returning it to user. In case we have SOFTMAX-normalized network,
20153 we return (Mean,Sigma)=(0.0,1.0).
20154 
20155  -- ALGLIB --
20156  Copyright 25.03.2011 by Bochkanov Sergey
20157 *************************************************************************/
20158 void mlpgetoutputscaling(multilayerperceptron* network,
20159  ae_int_t i,
20160  double* mean,
20161  double* sigma,
20162  ae_state *_state)
20163 {
20164 
20165  *mean = 0;
20166  *sigma = 0;
20167 
20168  ae_assert(i>=0&&i<network->hllayersizes.ptr.p_int[network->hllayersizes.cnt-1], "MLPGetOutputScaling: incorrect (nonexistent) I", _state);
20169  if( network->structinfo.ptr.p_int[6]==1 )
20170  {
20171  *mean = 0;
20172  *sigma = 1;
20173  }
20174  else
20175  {
20176  *mean = network->columnmeans.ptr.p_double[network->hllayersizes.ptr.p_int[0]+i];
20177  *sigma = network->columnsigmas.ptr.p_double[network->hllayersizes.ptr.p_int[0]+i];
20178  }
20179 }
20180 
20181 
20182 /*************************************************************************
20183 This function returns information about Ith neuron of Kth layer
20184 
20185 INPUT PARAMETERS:
20186  Network - network
20187  K - layer index
20188  I - neuron index (within layer)
20189 
20190 OUTPUT PARAMETERS:
20191  FKind - activation function type (used by MLPActivationFunction())
20192  this value is zero for input or linear neurons
20193  Threshold - also called offset, bias
20194  zero for input neurons
20195 
20196 NOTE: this function throws exception if layer or neuron with given index
20197 do not exists.
20198 
20199  -- ALGLIB --
20200  Copyright 25.03.2011 by Bochkanov Sergey
20201 *************************************************************************/
20202 void mlpgetneuroninfo(multilayerperceptron* network,
20203  ae_int_t k,
20204  ae_int_t i,
20205  ae_int_t* fkind,
20206  double* threshold,
20207  ae_state *_state)
20208 {
20209  ae_int_t ncnt;
20210  ae_int_t istart;
20211  ae_int_t highlevelidx;
20212  ae_int_t activationoffset;
20213 
20214  *fkind = 0;
20215  *threshold = 0;
20216 
20217  ncnt = network->hlneurons.cnt/mlpbase_hlnfieldwidth;
20218  istart = network->structinfo.ptr.p_int[5];
20219 
20220  /*
20221  * search
20222  */
20223  network->integerbuf.ptr.p_int[0] = k;
20224  network->integerbuf.ptr.p_int[1] = i;
20225  highlevelidx = recsearch(&network->hlneurons, mlpbase_hlnfieldwidth, 2, 0, ncnt, &network->integerbuf, _state);
20226  ae_assert(highlevelidx>=0, "MLPGetNeuronInfo: incorrect (nonexistent) layer or neuron index", _state);
20227 
20228  /*
20229  * 1. find offset of the activation function record in the
20230  */
20231  if( network->hlneurons.ptr.p_int[highlevelidx*mlpbase_hlnfieldwidth+2]>=0 )
20232  {
20233  activationoffset = istart+network->hlneurons.ptr.p_int[highlevelidx*mlpbase_hlnfieldwidth+2]*mlpbase_nfieldwidth;
20234  *fkind = network->structinfo.ptr.p_int[activationoffset+0];
20235  }
20236  else
20237  {
20238  *fkind = 0;
20239  }
20240  if( network->hlneurons.ptr.p_int[highlevelidx*mlpbase_hlnfieldwidth+3]>=0 )
20241  {
20242  *threshold = network->weights.ptr.p_double[network->hlneurons.ptr.p_int[highlevelidx*mlpbase_hlnfieldwidth+3]];
20243  }
20244  else
20245  {
20246  *threshold = 0;
20247  }
20248 }
20249 
20250 
20251 /*************************************************************************
20252 This function returns information about connection from I0-th neuron of
20253 K0-th layer to I1-th neuron of K1-th layer.
20254 
20255 INPUT PARAMETERS:
20256  Network - network
20257  K0 - layer index
20258  I0 - neuron index (within layer)
20259  K1 - layer index
20260  I1 - neuron index (within layer)
20261 
20262 RESULT:
20263  connection weight (zero for non-existent connections)
20264 
20265 This function:
20266 1. throws exception if layer or neuron with given index do not exists.
20267 2. returns zero if neurons exist, but there is no connection between them
20268 
20269  -- ALGLIB --
20270  Copyright 25.03.2011 by Bochkanov Sergey
20271 *************************************************************************/
20272 double mlpgetweight(multilayerperceptron* network,
20273  ae_int_t k0,
20274  ae_int_t i0,
20275  ae_int_t k1,
20276  ae_int_t i1,
20277  ae_state *_state)
20278 {
20279  ae_int_t ccnt;
20280  ae_int_t highlevelidx;
20281  double result;
20282 
20283 
20284  ccnt = network->hlconnections.cnt/mlpbase_hlconnfieldwidth;
20285 
20286  /*
20287  * check params
20288  */
20289  ae_assert(k0>=0&&k0<network->hllayersizes.cnt, "MLPGetWeight: incorrect (nonexistent) K0", _state);
20290  ae_assert(i0>=0&&i0<network->hllayersizes.ptr.p_int[k0], "MLPGetWeight: incorrect (nonexistent) I0", _state);
20291  ae_assert(k1>=0&&k1<network->hllayersizes.cnt, "MLPGetWeight: incorrect (nonexistent) K1", _state);
20292  ae_assert(i1>=0&&i1<network->hllayersizes.ptr.p_int[k1], "MLPGetWeight: incorrect (nonexistent) I1", _state);
20293 
20294  /*
20295  * search
20296  */
20297  network->integerbuf.ptr.p_int[0] = k0;
20298  network->integerbuf.ptr.p_int[1] = i0;
20299  network->integerbuf.ptr.p_int[2] = k1;
20300  network->integerbuf.ptr.p_int[3] = i1;
20301  highlevelidx = recsearch(&network->hlconnections, mlpbase_hlconnfieldwidth, 4, 0, ccnt, &network->integerbuf, _state);
20302  if( highlevelidx>=0 )
20303  {
20304  result = network->weights.ptr.p_double[network->hlconnections.ptr.p_int[highlevelidx*mlpbase_hlconnfieldwidth+4]];
20305  }
20306  else
20307  {
20308  result = 0;
20309  }
20310  return result;
20311 }
20312 
20313 
20314 /*************************************************************************
20315 This function sets offset/scaling coefficients for I-th input of the
20316 network.
20317 
20318 INPUT PARAMETERS:
20319  Network - network
20320  I - input index
20321  Mean - mean term
20322  Sigma - sigma term (if zero, will be replaced by 1.0)
20323 
20324 NTE: I-th input is passed through linear transformation
20325  IN[i] = (IN[i]-Mean)/Sigma
20326 before feeding to the network. This function sets Mean and Sigma.
20327 
20328  -- ALGLIB --
20329  Copyright 25.03.2011 by Bochkanov Sergey
20330 *************************************************************************/
20331 void mlpsetinputscaling(multilayerperceptron* network,
20332  ae_int_t i,
20333  double mean,
20334  double sigma,
20335  ae_state *_state)
20336 {
20337 
20338 
20339  ae_assert(i>=0&&i<network->hllayersizes.ptr.p_int[0], "MLPSetInputScaling: incorrect (nonexistent) I", _state);
20340  ae_assert(ae_isfinite(mean, _state), "MLPSetInputScaling: infinite or NAN Mean", _state);
20341  ae_assert(ae_isfinite(sigma, _state), "MLPSetInputScaling: infinite or NAN Sigma", _state);
20342  if( ae_fp_eq(sigma,0) )
20343  {
20344  sigma = 1;
20345  }
20346  network->columnmeans.ptr.p_double[i] = mean;
20347  network->columnsigmas.ptr.p_double[i] = sigma;
20348 }
20349 
20350 
20351 /*************************************************************************
20352 This function sets offset/scaling coefficients for I-th output of the
20353 network.
20354 
20355 INPUT PARAMETERS:
20356  Network - network
20357  I - input index
20358  Mean - mean term
20359  Sigma - sigma term (if zero, will be replaced by 1.0)
20360 
20361 OUTPUT PARAMETERS:
20362 
20363 NOTE: I-th output is passed through linear transformation
20364  OUT[i] = OUT[i]*Sigma+Mean
20365 before returning it to user. This function sets Sigma/Mean. In case we
20366 have SOFTMAX-normalized network, you can not set (Sigma,Mean) to anything
20367 other than(0.0,1.0) - this function will throw exception.
20368 
20369  -- ALGLIB --
20370  Copyright 25.03.2011 by Bochkanov Sergey
20371 *************************************************************************/
20372 void mlpsetoutputscaling(multilayerperceptron* network,
20373  ae_int_t i,
20374  double mean,
20375  double sigma,
20376  ae_state *_state)
20377 {
20378 
20379 
20380  ae_assert(i>=0&&i<network->hllayersizes.ptr.p_int[network->hllayersizes.cnt-1], "MLPSetOutputScaling: incorrect (nonexistent) I", _state);
20381  ae_assert(ae_isfinite(mean, _state), "MLPSetOutputScaling: infinite or NAN Mean", _state);
20382  ae_assert(ae_isfinite(sigma, _state), "MLPSetOutputScaling: infinite or NAN Sigma", _state);
20383  if( network->structinfo.ptr.p_int[6]==1 )
20384  {
20385  ae_assert(ae_fp_eq(mean,0), "MLPSetOutputScaling: you can not set non-zero Mean term for classifier network", _state);
20386  ae_assert(ae_fp_eq(sigma,1), "MLPSetOutputScaling: you can not set non-unit Sigma term for classifier network", _state);
20387  }
20388  else
20389  {
20390  if( ae_fp_eq(sigma,0) )
20391  {
20392  sigma = 1;
20393  }
20394  network->columnmeans.ptr.p_double[network->hllayersizes.ptr.p_int[0]+i] = mean;
20395  network->columnsigmas.ptr.p_double[network->hllayersizes.ptr.p_int[0]+i] = sigma;
20396  }
20397 }
20398 
20399 
20400 /*************************************************************************
20401 This function modifies information about Ith neuron of Kth layer
20402 
20403 INPUT PARAMETERS:
20404  Network - network
20405  K - layer index
20406  I - neuron index (within layer)
20407  FKind - activation function type (used by MLPActivationFunction())
20408  this value must be zero for input neurons
20409  (you can not set activation function for input neurons)
20410  Threshold - also called offset, bias
20411  this value must be zero for input neurons
20412  (you can not set threshold for input neurons)
20413 
20414 NOTES:
20415 1. this function throws exception if layer or neuron with given index do
20416  not exists.
20417 2. this function also throws exception when you try to set non-linear
20418  activation function for input neurons (any kind of network) or for output
20419  neurons of classifier network.
20420 3. this function throws exception when you try to set non-zero threshold for
20421  input neurons (any kind of network).
20422 
20423  -- ALGLIB --
20424  Copyright 25.03.2011 by Bochkanov Sergey
20425 *************************************************************************/
20426 void mlpsetneuroninfo(multilayerperceptron* network,
20427  ae_int_t k,
20428  ae_int_t i,
20429  ae_int_t fkind,
20430  double threshold,
20431  ae_state *_state)
20432 {
20433  ae_int_t ncnt;
20434  ae_int_t istart;
20435  ae_int_t highlevelidx;
20436  ae_int_t activationoffset;
20437 
20438 
20439  ae_assert(ae_isfinite(threshold, _state), "MLPSetNeuronInfo: infinite or NAN Threshold", _state);
20440 
20441  /*
20442  * convenience vars
20443  */
20444  ncnt = network->hlneurons.cnt/mlpbase_hlnfieldwidth;
20445  istart = network->structinfo.ptr.p_int[5];
20446 
20447  /*
20448  * search
20449  */
20450  network->integerbuf.ptr.p_int[0] = k;
20451  network->integerbuf.ptr.p_int[1] = i;
20452  highlevelidx = recsearch(&network->hlneurons, mlpbase_hlnfieldwidth, 2, 0, ncnt, &network->integerbuf, _state);
20453  ae_assert(highlevelidx>=0, "MLPSetNeuronInfo: incorrect (nonexistent) layer or neuron index", _state);
20454 
20455  /*
20456  * activation function
20457  */
20458  if( network->hlneurons.ptr.p_int[highlevelidx*mlpbase_hlnfieldwidth+2]>=0 )
20459  {
20460  activationoffset = istart+network->hlneurons.ptr.p_int[highlevelidx*mlpbase_hlnfieldwidth+2]*mlpbase_nfieldwidth;
20461  network->structinfo.ptr.p_int[activationoffset+0] = fkind;
20462  }
20463  else
20464  {
20465  ae_assert(fkind==0, "MLPSetNeuronInfo: you try to set activation function for neuron which can not have one", _state);
20466  }
20467 
20468  /*
20469  * Threshold
20470  */
20471  if( network->hlneurons.ptr.p_int[highlevelidx*mlpbase_hlnfieldwidth+3]>=0 )
20472  {
20473  network->weights.ptr.p_double[network->hlneurons.ptr.p_int[highlevelidx*mlpbase_hlnfieldwidth+3]] = threshold;
20474  }
20475  else
20476  {
20477  ae_assert(ae_fp_eq(threshold,0), "MLPSetNeuronInfo: you try to set non-zero threshold for neuron which can not have one", _state);
20478  }
20479 }
20480 
20481 
20482 /*************************************************************************
20483 This function modifies information about connection from I0-th neuron of
20484 K0-th layer to I1-th neuron of K1-th layer.
20485 
20486 INPUT PARAMETERS:
20487  Network - network
20488  K0 - layer index
20489  I0 - neuron index (within layer)
20490  K1 - layer index
20491  I1 - neuron index (within layer)
20492  W - connection weight (must be zero for non-existent
20493  connections)
20494 
20495 This function:
20496 1. throws exception if layer or neuron with given index do not exists.
20497 2. throws exception if you try to set non-zero weight for non-existent
20498  connection
20499 
20500  -- ALGLIB --
20501  Copyright 25.03.2011 by Bochkanov Sergey
20502 *************************************************************************/
20503 void mlpsetweight(multilayerperceptron* network,
20504  ae_int_t k0,
20505  ae_int_t i0,
20506  ae_int_t k1,
20507  ae_int_t i1,
20508  double w,
20509  ae_state *_state)
20510 {
20511  ae_int_t ccnt;
20512  ae_int_t highlevelidx;
20513 
20514 
20515  ccnt = network->hlconnections.cnt/mlpbase_hlconnfieldwidth;
20516 
20517  /*
20518  * check params
20519  */
20520  ae_assert(k0>=0&&k0<network->hllayersizes.cnt, "MLPSetWeight: incorrect (nonexistent) K0", _state);
20521  ae_assert(i0>=0&&i0<network->hllayersizes.ptr.p_int[k0], "MLPSetWeight: incorrect (nonexistent) I0", _state);
20522  ae_assert(k1>=0&&k1<network->hllayersizes.cnt, "MLPSetWeight: incorrect (nonexistent) K1", _state);
20523  ae_assert(i1>=0&&i1<network->hllayersizes.ptr.p_int[k1], "MLPSetWeight: incorrect (nonexistent) I1", _state);
20524  ae_assert(ae_isfinite(w, _state), "MLPSetWeight: infinite or NAN weight", _state);
20525 
20526  /*
20527  * search
20528  */
20529  network->integerbuf.ptr.p_int[0] = k0;
20530  network->integerbuf.ptr.p_int[1] = i0;
20531  network->integerbuf.ptr.p_int[2] = k1;
20532  network->integerbuf.ptr.p_int[3] = i1;
20533  highlevelidx = recsearch(&network->hlconnections, mlpbase_hlconnfieldwidth, 4, 0, ccnt, &network->integerbuf, _state);
20534  if( highlevelidx>=0 )
20535  {
20536  network->weights.ptr.p_double[network->hlconnections.ptr.p_int[highlevelidx*mlpbase_hlconnfieldwidth+4]] = w;
20537  }
20538  else
20539  {
20540  ae_assert(ae_fp_eq(w,0), "MLPSetWeight: you try to set non-zero weight for non-existent connection", _state);
20541  }
20542 }
20543 
20544 
20545 /*************************************************************************
20546 Neural network activation function
20547 
20548 INPUT PARAMETERS:
20549  NET - neuron input
20550  K - function index (zero for linear function)
20551 
20552 OUTPUT PARAMETERS:
20553  F - function
20554  DF - its derivative
20555  D2F - its second derivative
20556 
20557  -- ALGLIB --
20558  Copyright 04.11.2007 by Bochkanov Sergey
20559 *************************************************************************/
20560 void mlpactivationfunction(double net,
20561  ae_int_t k,
20562  double* f,
20563  double* df,
20564  double* d2f,
20565  ae_state *_state)
20566 {
20567  double net2;
20568  double arg;
20569  double root;
20570  double r;
20571 
20572  *f = 0;
20573  *df = 0;
20574  *d2f = 0;
20575 
20576  if( k==0||k==-5 )
20577  {
20578  *f = net;
20579  *df = 1;
20580  *d2f = 0;
20581  return;
20582  }
20583  if( k==1 )
20584  {
20585 
20586  /*
20587  * TanH activation function
20588  */
20589  if( ae_fp_less(ae_fabs(net, _state),100) )
20590  {
20591  *f = ae_tanh(net, _state);
20592  }
20593  else
20594  {
20595  *f = ae_sign(net, _state);
20596  }
20597  *df = 1-*f*(*f);
20598  *d2f = -2*(*f)*(*df);
20599  return;
20600  }
20601  if( k==3 )
20602  {
20603 
20604  /*
20605  * EX activation function
20606  */
20607  if( ae_fp_greater_eq(net,0) )
20608  {
20609  net2 = net*net;
20610  arg = net2+1;
20611  root = ae_sqrt(arg, _state);
20612  *f = net+root;
20613  r = net/root;
20614  *df = 1+r;
20615  *d2f = (root-net*r)/arg;
20616  }
20617  else
20618  {
20619  *f = ae_exp(net, _state);
20620  *df = *f;
20621  *d2f = *f;
20622  }
20623  return;
20624  }
20625  if( k==2 )
20626  {
20627  *f = ae_exp(-ae_sqr(net, _state), _state);
20628  *df = -2*net*(*f);
20629  *d2f = -2*(*f+*df*net);
20630  return;
20631  }
20632  *f = 0;
20633  *df = 0;
20634  *d2f = 0;
20635 }
20636 
20637 
20638 /*************************************************************************
20639 Procesing
20640 
20641 INPUT PARAMETERS:
20642  Network - neural network
20643  X - input vector, array[0..NIn-1].
20644 
20645 OUTPUT PARAMETERS:
20646  Y - result. Regression estimate when solving regression task,
20647  vector of posterior probabilities for classification task.
20648 
20649 See also MLPProcessI
20650 
20651  -- ALGLIB --
20652  Copyright 04.11.2007 by Bochkanov Sergey
20653 *************************************************************************/
20654 void mlpprocess(multilayerperceptron* network,
20655  /* Real */ ae_vector* x,
20656  /* Real */ ae_vector* y,
20657  ae_state *_state)
20658 {
20659 
20660 
20661  if( y->cnt<network->structinfo.ptr.p_int[2] )
20662  {
20663  ae_vector_set_length(y, network->structinfo.ptr.p_int[2], _state);
20664  }
20665  mlpinternalprocessvector(&network->structinfo, &network->weights, &network->columnmeans, &network->columnsigmas, &network->neurons, &network->dfdnet, x, y, _state);
20666 }
20667 
20668 
20669 /*************************************************************************
20670 'interactive' variant of MLPProcess for languages like Python which
20671 support constructs like "Y = MLPProcess(NN,X)" and interactive mode of the
20672 interpreter
20673 
20674 This function allocates new array on each call, so it is significantly
20675 slower than its 'non-interactive' counterpart, but it is more convenient
20676 when you call it from command line.
20677 
20678  -- ALGLIB --
20679  Copyright 21.09.2010 by Bochkanov Sergey
20680 *************************************************************************/
20681 void mlpprocessi(multilayerperceptron* network,
20682  /* Real */ ae_vector* x,
20683  /* Real */ ae_vector* y,
20684  ae_state *_state)
20685 {
20686 
20687  ae_vector_clear(y);
20688 
20689  mlpprocess(network, x, y, _state);
20690 }
20691 
20692 
20693 /*************************************************************************
20694 Error of the neural network on dataset.
20695 
20696 
20697 FOR USERS OF COMMERCIAL EDITION:
20698 
20699  ! Commercial version of ALGLIB includes two important improvements of
20700  ! this function:
20701  ! * multicore support (C++ and C# computational cores)
20702  ! * SSE support
20703  !
20704  ! First improvement gives close-to-linear speedup on multicore systems.
20705  ! Second improvement gives constant speedup (2-3x, depending on your CPU)
20706  !
20707  ! In order to use multicore features you have to:
20708  ! * use commercial version of ALGLIB
20709  ! * call this function with "smp_" prefix, which indicates that
20710  ! multicore code will be used (for multicore support)
20711  !
20712  ! In order to use SSE features you have to:
20713  ! * use commercial version of ALGLIB on Intel processors
20714  ! * use C++ computational core
20715  !
20716  ! This note is given for users of commercial edition; if you use GPL
20717  ! edition, you still will be able to call smp-version of this function,
20718  ! but all computations will be done serially.
20719  !
20720  ! We recommend you to carefully read ALGLIB Reference Manual, section
20721  ! called 'SMP support', before using parallel version of this function.
20722 
20723 
20724 INPUT PARAMETERS:
20725  Network - neural network;
20726  XY - training set, see below for information on the
20727  training set format;
20728  NPoints - points count.
20729 
20730 RESULT:
20731  sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2)
20732 
20733 DATASET FORMAT:
20734 
20735 This function uses two different dataset formats - one for regression
20736 networks, another one for classification networks.
20737 
20738 For regression networks with NIn inputs and NOut outputs following dataset
20739 format is used:
20740 * dataset is given by NPoints*(NIn+NOut) matrix
20741 * each row corresponds to one example
20742 * first NIn columns are inputs, next NOut columns are outputs
20743 
20744 For classification networks with NIn inputs and NClasses clases following
20745 dataset format is used:
20746 * dataset is given by NPoints*(NIn+1) matrix
20747 * each row corresponds to one example
20748 * first NIn columns are inputs, last column stores class number (from 0 to
20749  NClasses-1).
20750 
20751  -- ALGLIB --
20752  Copyright 04.11.2007 by Bochkanov Sergey
20753 *************************************************************************/
20754 double mlperror(multilayerperceptron* network,
20755  /* Real */ ae_matrix* xy,
20756  ae_int_t npoints,
20757  ae_state *_state)
20758 {
20759  double result;
20760 
20761 
20762  ae_assert(xy->rows>=npoints, "MLPError: XY has less than NPoints rows", _state);
20763  if( npoints>0 )
20764  {
20765  if( mlpissoftmax(network, _state) )
20766  {
20767  ae_assert(xy->cols>=mlpgetinputscount(network, _state)+1, "MLPError: XY has less than NIn+1 columns", _state);
20768  }
20769  else
20770  {
20771  ae_assert(xy->cols>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPError: XY has less than NIn+NOut columns", _state);
20772  }
20773  }
20774  mlpallerrorsx(network, xy, &network->dummysxy, npoints, 0, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state);
20775  result = ae_sqr(network->err.rmserror, _state)*npoints*mlpgetoutputscount(network, _state)/2;
20776  return result;
20777 }
20778 
20779 
20780 /*************************************************************************
20781 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
20782 *************************************************************************/
20783 double _pexec_mlperror(multilayerperceptron* network,
20784  /* Real */ ae_matrix* xy,
20785  ae_int_t npoints, ae_state *_state)
20786 {
20787  return mlperror(network,xy,npoints, _state);
20788 }
20789 
20790 
20791 /*************************************************************************
20792 Error of the neural network on dataset given by sparse matrix.
20793 
20794 
20795 FOR USERS OF COMMERCIAL EDITION:
20796 
20797  ! Commercial version of ALGLIB includes two important improvements of
20798  ! this function:
20799  ! * multicore support (C++ and C# computational cores)
20800  ! * SSE support
20801  !
20802  ! First improvement gives close-to-linear speedup on multicore systems.
20803  ! Second improvement gives constant speedup (2-3x, depending on your CPU)
20804  !
20805  ! In order to use multicore features you have to:
20806  ! * use commercial version of ALGLIB
20807  ! * call this function with "smp_" prefix, which indicates that
20808  ! multicore code will be used (for multicore support)
20809  !
20810  ! In order to use SSE features you have to:
20811  ! * use commercial version of ALGLIB on Intel processors
20812  ! * use C++ computational core
20813  !
20814  ! This note is given for users of commercial edition; if you use GPL
20815  ! edition, you still will be able to call smp-version of this function,
20816  ! but all computations will be done serially.
20817  !
20818  ! We recommend you to carefully read ALGLIB Reference Manual, section
20819  ! called 'SMP support', before using parallel version of this function.
20820 
20821 
20822 INPUT PARAMETERS:
20823  Network - neural network
20824  XY - training set, see below for information on the
20825  training set format. This function checks correctness
20826  of the dataset (no NANs/INFs, class numbers are
20827  correct) and throws exception when incorrect dataset
20828  is passed. Sparse matrix must use CRS format for
20829  storage.
20830  NPoints - points count, >=0
20831 
20832 RESULT:
20833  sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2)
20834 
20835 DATASET FORMAT:
20836 
20837 This function uses two different dataset formats - one for regression
20838 networks, another one for classification networks.
20839 
20840 For regression networks with NIn inputs and NOut outputs following dataset
20841 format is used:
20842 * dataset is given by NPoints*(NIn+NOut) matrix
20843 * each row corresponds to one example
20844 * first NIn columns are inputs, next NOut columns are outputs
20845 
20846 For classification networks with NIn inputs and NClasses clases following
20847 dataset format is used:
20848 * dataset is given by NPoints*(NIn+1) matrix
20849 * each row corresponds to one example
20850 * first NIn columns are inputs, last column stores class number (from 0 to
20851  NClasses-1).
20852 
20853  -- ALGLIB --
20854  Copyright 23.07.2012 by Bochkanov Sergey
20855 *************************************************************************/
20856 double mlperrorsparse(multilayerperceptron* network,
20857  sparsematrix* xy,
20858  ae_int_t npoints,
20859  ae_state *_state)
20860 {
20861  double result;
20862 
20863 
20864  ae_assert(sparseiscrs(xy, _state), "MLPErrorSparse: XY is not in CRS format.", _state);
20865  ae_assert(sparsegetnrows(xy, _state)>=npoints, "MLPErrorSparse: XY has less than NPoints rows", _state);
20866  if( npoints>0 )
20867  {
20868  if( mlpissoftmax(network, _state) )
20869  {
20870  ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+1, "MLPErrorSparse: XY has less than NIn+1 columns", _state);
20871  }
20872  else
20873  {
20874  ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPErrorSparse: XY has less than NIn+NOut columns", _state);
20875  }
20876  }
20877  mlpallerrorsx(network, &network->dummydxy, xy, npoints, 1, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state);
20878  result = ae_sqr(network->err.rmserror, _state)*npoints*mlpgetoutputscount(network, _state)/2;
20879  return result;
20880 }
20881 
20882 
20883 /*************************************************************************
20884 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
20885 *************************************************************************/
20886 double _pexec_mlperrorsparse(multilayerperceptron* network,
20887  sparsematrix* xy,
20888  ae_int_t npoints, ae_state *_state)
20889 {
20890  return mlperrorsparse(network,xy,npoints, _state);
20891 }
20892 
20893 
20894 /*************************************************************************
20895 Natural error function for neural network, internal subroutine.
20896 
20897 NOTE: this function is single-threaded. Unlike other error function, it
20898 receives no speed-up from being executed in SMP mode.
20899 
20900  -- ALGLIB --
20901  Copyright 04.11.2007 by Bochkanov Sergey
20902 *************************************************************************/
20903 double mlperrorn(multilayerperceptron* network,
20904  /* Real */ ae_matrix* xy,
20905  ae_int_t ssize,
20906  ae_state *_state)
20907 {
20908  ae_int_t i;
20909  ae_int_t k;
20910  ae_int_t nin;
20911  ae_int_t nout;
20912  ae_int_t wcount;
20913  double e;
20914  double result;
20915 
20916 
20917  mlpproperties(network, &nin, &nout, &wcount, _state);
20918  result = 0;
20919  for(i=0; i<=ssize-1; i++)
20920  {
20921 
20922  /*
20923  * Process vector
20924  */
20925  ae_v_move(&network->x.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nin-1));
20926  mlpprocess(network, &network->x, &network->y, _state);
20927 
20928  /*
20929  * Update error function
20930  */
20931  if( network->structinfo.ptr.p_int[6]==0 )
20932  {
20933 
20934  /*
20935  * Least squares error function
20936  */
20937  ae_v_sub(&network->y.ptr.p_double[0], 1, &xy->ptr.pp_double[i][nin], 1, ae_v_len(0,nout-1));
20938  e = ae_v_dotproduct(&network->y.ptr.p_double[0], 1, &network->y.ptr.p_double[0], 1, ae_v_len(0,nout-1));
20939  result = result+e/2;
20940  }
20941  else
20942  {
20943 
20944  /*
20945  * Cross-entropy error function
20946  */
20947  k = ae_round(xy->ptr.pp_double[i][nin], _state);
20948  if( k>=0&&k<nout )
20949  {
20950  result = result+mlpbase_safecrossentropy(1, network->y.ptr.p_double[k], _state);
20951  }
20952  }
20953  }
20954  return result;
20955 }
20956 
20957 
20958 /*************************************************************************
20959 Classification error of the neural network on dataset.
20960 
20961 
20962 FOR USERS OF COMMERCIAL EDITION:
20963 
20964  ! Commercial version of ALGLIB includes two important improvements of
20965  ! this function:
20966  ! * multicore support (C++ and C# computational cores)
20967  ! * SSE support
20968  !
20969  ! First improvement gives close-to-linear speedup on multicore systems.
20970  ! Second improvement gives constant speedup (2-3x depending on your CPU)
20971  !
20972  ! In order to use multicore features you have to:
20973  ! * use commercial version of ALGLIB
20974  ! * call this function with "smp_" prefix, which indicates that
20975  ! multicore code will be used (for multicore support)
20976  !
20977  ! In order to use SSE features you have to:
20978  ! * use commercial version of ALGLIB on Intel processors
20979  ! * use C++ computational core
20980  !
20981  ! This note is given for users of commercial edition; if you use GPL
20982  ! edition, you still will be able to call smp-version of this function,
20983  ! but all computations will be done serially.
20984  !
20985  ! We recommend you to carefully read ALGLIB Reference Manual, section
20986  ! called 'SMP support', before using parallel version of this function.
20987 
20988 
20989 INPUT PARAMETERS:
20990  Network - neural network;
20991  XY - training set, see below for information on the
20992  training set format;
20993  NPoints - points count.
20994 
20995 RESULT:
20996  classification error (number of misclassified cases)
20997 
20998 DATASET FORMAT:
20999 
21000 This function uses two different dataset formats - one for regression
21001 networks, another one for classification networks.
21002 
21003 For regression networks with NIn inputs and NOut outputs following dataset
21004 format is used:
21005 * dataset is given by NPoints*(NIn+NOut) matrix
21006 * each row corresponds to one example
21007 * first NIn columns are inputs, next NOut columns are outputs
21008 
21009 For classification networks with NIn inputs and NClasses clases following
21010 dataset format is used:
21011 * dataset is given by NPoints*(NIn+1) matrix
21012 * each row corresponds to one example
21013 * first NIn columns are inputs, last column stores class number (from 0 to
21014  NClasses-1).
21015 
21016  -- ALGLIB --
21017  Copyright 04.11.2007 by Bochkanov Sergey
21018 *************************************************************************/
21019 ae_int_t mlpclserror(multilayerperceptron* network,
21020  /* Real */ ae_matrix* xy,
21021  ae_int_t npoints,
21022  ae_state *_state)
21023 {
21024  ae_int_t result;
21025 
21026 
21027  ae_assert(xy->rows>=npoints, "MLPClsError: XY has less than NPoints rows", _state);
21028  if( npoints>0 )
21029  {
21030  if( mlpissoftmax(network, _state) )
21031  {
21032  ae_assert(xy->cols>=mlpgetinputscount(network, _state)+1, "MLPClsError: XY has less than NIn+1 columns", _state);
21033  }
21034  else
21035  {
21036  ae_assert(xy->cols>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPClsError: XY has less than NIn+NOut columns", _state);
21037  }
21038  }
21039  mlpallerrorsx(network, xy, &network->dummysxy, npoints, 0, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state);
21040  result = ae_round(npoints*network->err.relclserror, _state);
21041  return result;
21042 }
21043 
21044 
21045 /*************************************************************************
21046 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
21047 *************************************************************************/
21048 ae_int_t _pexec_mlpclserror(multilayerperceptron* network,
21049  /* Real */ ae_matrix* xy,
21050  ae_int_t npoints, ae_state *_state)
21051 {
21052  return mlpclserror(network,xy,npoints, _state);
21053 }
21054 
21055 
21056 /*************************************************************************
21057 Relative classification error on the test set.
21058 
21059 
21060 FOR USERS OF COMMERCIAL EDITION:
21061 
21062  ! Commercial version of ALGLIB includes two important improvements of
21063  ! this function:
21064  ! * multicore support (C++ and C# computational cores)
21065  ! * SSE support
21066  !
21067  ! First improvement gives close-to-linear speedup on multicore systems.
21068  ! Second improvement gives constant speedup (2-3x depending on your CPU)
21069  !
21070  ! In order to use multicore features you have to:
21071  ! * use commercial version of ALGLIB
21072  ! * call this function with "smp_" prefix, which indicates that
21073  ! multicore code will be used (for multicore support)
21074  !
21075  ! In order to use SSE features you have to:
21076  ! * use commercial version of ALGLIB on Intel processors
21077  ! * use C++ computational core
21078  !
21079  ! This note is given for users of commercial edition; if you use GPL
21080  ! edition, you still will be able to call smp-version of this function,
21081  ! but all computations will be done serially.
21082  !
21083  ! We recommend you to carefully read ALGLIB Reference Manual, section
21084  ! called 'SMP support', before using parallel version of this function.
21085 
21086 
21087 INPUT PARAMETERS:
21088  Network - neural network;
21089  XY - training set, see below for information on the
21090  training set format;
21091  NPoints - points count.
21092 
21093 RESULT:
21094 Percent of incorrectly classified cases. Works both for classifier
21095 networks and general purpose networks used as classifiers.
21096 
21097 DATASET FORMAT:
21098 
21099 This function uses two different dataset formats - one for regression
21100 networks, another one for classification networks.
21101 
21102 For regression networks with NIn inputs and NOut outputs following dataset
21103 format is used:
21104 * dataset is given by NPoints*(NIn+NOut) matrix
21105 * each row corresponds to one example
21106 * first NIn columns are inputs, next NOut columns are outputs
21107 
21108 For classification networks with NIn inputs and NClasses clases following
21109 dataset format is used:
21110 * dataset is given by NPoints*(NIn+1) matrix
21111 * each row corresponds to one example
21112 * first NIn columns are inputs, last column stores class number (from 0 to
21113  NClasses-1).
21114 
21115  -- ALGLIB --
21116  Copyright 25.12.2008 by Bochkanov Sergey
21117 *************************************************************************/
21118 double mlprelclserror(multilayerperceptron* network,
21119  /* Real */ ae_matrix* xy,
21120  ae_int_t npoints,
21121  ae_state *_state)
21122 {
21123  double result;
21124 
21125 
21126  ae_assert(xy->rows>=npoints, "MLPRelClsError: XY has less than NPoints rows", _state);
21127  if( npoints>0 )
21128  {
21129  if( mlpissoftmax(network, _state) )
21130  {
21131  ae_assert(xy->cols>=mlpgetinputscount(network, _state)+1, "MLPRelClsError: XY has less than NIn+1 columns", _state);
21132  }
21133  else
21134  {
21135  ae_assert(xy->cols>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPRelClsError: XY has less than NIn+NOut columns", _state);
21136  }
21137  }
21138  if( npoints>0 )
21139  {
21140  result = (double)mlpclserror(network, xy, npoints, _state)/(double)npoints;
21141  }
21142  else
21143  {
21144  result = 0.0;
21145  }
21146  return result;
21147 }
21148 
21149 
21150 /*************************************************************************
21151 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
21152 *************************************************************************/
21153 double _pexec_mlprelclserror(multilayerperceptron* network,
21154  /* Real */ ae_matrix* xy,
21155  ae_int_t npoints, ae_state *_state)
21156 {
21157  return mlprelclserror(network,xy,npoints, _state);
21158 }
21159 
21160 
21161 /*************************************************************************
21162 Relative classification error on the test set given by sparse matrix.
21163 
21164 
21165 FOR USERS OF COMMERCIAL EDITION:
21166 
21167  ! Commercial version of ALGLIB includes two important improvements of
21168  ! this function:
21169  ! * multicore support (C++ and C# computational cores)
21170  ! * SSE support
21171  !
21172  ! First improvement gives close-to-linear speedup on multicore systems.
21173  ! Second improvement gives constant speedup (2-3x depending on your CPU)
21174  !
21175  ! In order to use multicore features you have to:
21176  ! * use commercial version of ALGLIB
21177  ! * call this function with "smp_" prefix, which indicates that
21178  ! multicore code will be used (for multicore support)
21179  !
21180  ! In order to use SSE features you have to:
21181  ! * use commercial version of ALGLIB on Intel processors
21182  ! * use C++ computational core
21183  !
21184  ! This note is given for users of commercial edition; if you use GPL
21185  ! edition, you still will be able to call smp-version of this function,
21186  ! but all computations will be done serially.
21187  !
21188  ! We recommend you to carefully read ALGLIB Reference Manual, section
21189  ! called 'SMP support', before using parallel version of this function.
21190 
21191 
21192 INPUT PARAMETERS:
21193  Network - neural network;
21194  XY - training set, see below for information on the
21195  training set format. Sparse matrix must use CRS format
21196  for storage.
21197  NPoints - points count, >=0.
21198 
21199 RESULT:
21200 Percent of incorrectly classified cases. Works both for classifier
21201 networks and general purpose networks used as classifiers.
21202 
21203 DATASET FORMAT:
21204 
21205 This function uses two different dataset formats - one for regression
21206 networks, another one for classification networks.
21207 
21208 For regression networks with NIn inputs and NOut outputs following dataset
21209 format is used:
21210 * dataset is given by NPoints*(NIn+NOut) matrix
21211 * each row corresponds to one example
21212 * first NIn columns are inputs, next NOut columns are outputs
21213 
21214 For classification networks with NIn inputs and NClasses clases following
21215 dataset format is used:
21216 * dataset is given by NPoints*(NIn+1) matrix
21217 * each row corresponds to one example
21218 * first NIn columns are inputs, last column stores class number (from 0 to
21219  NClasses-1).
21220 
21221  -- ALGLIB --
21222  Copyright 09.08.2012 by Bochkanov Sergey
21223 *************************************************************************/
21224 double mlprelclserrorsparse(multilayerperceptron* network,
21225  sparsematrix* xy,
21226  ae_int_t npoints,
21227  ae_state *_state)
21228 {
21229  double result;
21230 
21231 
21232  ae_assert(sparseiscrs(xy, _state), "MLPRelClsErrorSparse: sparse matrix XY is not in CRS format.", _state);
21233  ae_assert(sparsegetnrows(xy, _state)>=npoints, "MLPRelClsErrorSparse: sparse matrix XY has less than NPoints rows", _state);
21234  if( npoints>0 )
21235  {
21236  if( mlpissoftmax(network, _state) )
21237  {
21238  ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+1, "MLPRelClsErrorSparse: sparse matrix XY has less than NIn+1 columns", _state);
21239  }
21240  else
21241  {
21242  ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPRelClsErrorSparse: sparse matrix XY has less than NIn+NOut columns", _state);
21243  }
21244  }
21245  mlpallerrorsx(network, &network->dummydxy, xy, npoints, 1, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state);
21246  result = network->err.relclserror;
21247  return result;
21248 }
21249 
21250 
21251 /*************************************************************************
21252 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
21253 *************************************************************************/
21254 double _pexec_mlprelclserrorsparse(multilayerperceptron* network,
21255  sparsematrix* xy,
21256  ae_int_t npoints, ae_state *_state)
21257 {
21258  return mlprelclserrorsparse(network,xy,npoints, _state);
21259 }
21260 
21261 
21262 /*************************************************************************
21263 Average cross-entropy (in bits per element) on the test set.
21264 
21265 
21266 FOR USERS OF COMMERCIAL EDITION:
21267 
21268  ! Commercial version of ALGLIB includes two important improvements of
21269  ! this function:
21270  ! * multicore support (C++ and C# computational cores)
21271  ! * SSE support
21272  !
21273  ! First improvement gives close-to-linear speedup on multicore systems.
21274  ! Second improvement gives constant speedup (2-3x depending on your CPU)
21275  !
21276  ! In order to use multicore features you have to:
21277  ! * use commercial version of ALGLIB
21278  ! * call this function with "smp_" prefix, which indicates that
21279  ! multicore code will be used (for multicore support)
21280  !
21281  ! In order to use SSE features you have to:
21282  ! * use commercial version of ALGLIB on Intel processors
21283  ! * use C++ computational core
21284  !
21285  ! This note is given for users of commercial edition; if you use GPL
21286  ! edition, you still will be able to call smp-version of this function,
21287  ! but all computations will be done serially.
21288  !
21289  ! We recommend you to carefully read ALGLIB Reference Manual, section
21290  ! called 'SMP support', before using parallel version of this function.
21291 
21292 
21293 INPUT PARAMETERS:
21294  Network - neural network;
21295  XY - training set, see below for information on the
21296  training set format;
21297  NPoints - points count.
21298 
21299 RESULT:
21300 CrossEntropy/(NPoints*LN(2)).
21301 Zero if network solves regression task.
21302 
21303 DATASET FORMAT:
21304 
21305 This function uses two different dataset formats - one for regression
21306 networks, another one for classification networks.
21307 
21308 For regression networks with NIn inputs and NOut outputs following dataset
21309 format is used:
21310 * dataset is given by NPoints*(NIn+NOut) matrix
21311 * each row corresponds to one example
21312 * first NIn columns are inputs, next NOut columns are outputs
21313 
21314 For classification networks with NIn inputs and NClasses clases following
21315 dataset format is used:
21316 * dataset is given by NPoints*(NIn+1) matrix
21317 * each row corresponds to one example
21318 * first NIn columns are inputs, last column stores class number (from 0 to
21319  NClasses-1).
21320 
21321  -- ALGLIB --
21322  Copyright 08.01.2009 by Bochkanov Sergey
21323 *************************************************************************/
21324 double mlpavgce(multilayerperceptron* network,
21325  /* Real */ ae_matrix* xy,
21326  ae_int_t npoints,
21327  ae_state *_state)
21328 {
21329  double result;
21330 
21331 
21332  ae_assert(xy->rows>=npoints, "MLPAvgCE: XY has less than NPoints rows", _state);
21333  if( npoints>0 )
21334  {
21335  if( mlpissoftmax(network, _state) )
21336  {
21337  ae_assert(xy->cols>=mlpgetinputscount(network, _state)+1, "MLPAvgCE: XY has less than NIn+1 columns", _state);
21338  }
21339  else
21340  {
21341  ae_assert(xy->cols>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPAvgCE: XY has less than NIn+NOut columns", _state);
21342  }
21343  }
21344  mlpallerrorsx(network, xy, &network->dummysxy, npoints, 0, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state);
21345  result = network->err.avgce;
21346  return result;
21347 }
21348 
21349 
21350 /*************************************************************************
21351 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
21352 *************************************************************************/
21353 double _pexec_mlpavgce(multilayerperceptron* network,
21354  /* Real */ ae_matrix* xy,
21355  ae_int_t npoints, ae_state *_state)
21356 {
21357  return mlpavgce(network,xy,npoints, _state);
21358 }
21359 
21360 
21361 /*************************************************************************
21362 Average cross-entropy (in bits per element) on the test set given by
21363 sparse matrix.
21364 
21365 
21366 FOR USERS OF COMMERCIAL EDITION:
21367 
21368  ! Commercial version of ALGLIB includes two important improvements of
21369  ! this function:
21370  ! * multicore support (C++ and C# computational cores)
21371  ! * SSE support
21372  !
21373  ! First improvement gives close-to-linear speedup on multicore systems.
21374  ! Second improvement gives constant speedup (2-3x depending on your CPU)
21375  !
21376  ! In order to use multicore features you have to:
21377  ! * use commercial version of ALGLIB
21378  ! * call this function with "smp_" prefix, which indicates that
21379  ! multicore code will be used (for multicore support)
21380  !
21381  ! In order to use SSE features you have to:
21382  ! * use commercial version of ALGLIB on Intel processors
21383  ! * use C++ computational core
21384  !
21385  ! This note is given for users of commercial edition; if you use GPL
21386  ! edition, you still will be able to call smp-version of this function,
21387  ! but all computations will be done serially.
21388  !
21389  ! We recommend you to carefully read ALGLIB Reference Manual, section
21390  ! called 'SMP support', before using parallel version of this function.
21391 
21392 
21393 INPUT PARAMETERS:
21394  Network - neural network;
21395  XY - training set, see below for information on the
21396  training set format. This function checks correctness
21397  of the dataset (no NANs/INFs, class numbers are
21398  correct) and throws exception when incorrect dataset
21399  is passed. Sparse matrix must use CRS format for
21400  storage.
21401  NPoints - points count, >=0.
21402 
21403 RESULT:
21404 CrossEntropy/(NPoints*LN(2)).
21405 Zero if network solves regression task.
21406 
21407 DATASET FORMAT:
21408 
21409 This function uses two different dataset formats - one for regression
21410 networks, another one for classification networks.
21411 
21412 For regression networks with NIn inputs and NOut outputs following dataset
21413 format is used:
21414 * dataset is given by NPoints*(NIn+NOut) matrix
21415 * each row corresponds to one example
21416 * first NIn columns are inputs, next NOut columns are outputs
21417 
21418 For classification networks with NIn inputs and NClasses clases following
21419 dataset format is used:
21420 * dataset is given by NPoints*(NIn+1) matrix
21421 * each row corresponds to one example
21422 * first NIn columns are inputs, last column stores class number (from 0 to
21423  NClasses-1).
21424 
21425  -- ALGLIB --
21426  Copyright 9.08.2012 by Bochkanov Sergey
21427 *************************************************************************/
21428 double mlpavgcesparse(multilayerperceptron* network,
21429  sparsematrix* xy,
21430  ae_int_t npoints,
21431  ae_state *_state)
21432 {
21433  double result;
21434 
21435 
21436  ae_assert(sparseiscrs(xy, _state), "MLPAvgCESparse: sparse matrix XY is not in CRS format.", _state);
21437  ae_assert(sparsegetnrows(xy, _state)>=npoints, "MLPAvgCESparse: sparse matrix XY has less than NPoints rows", _state);
21438  if( npoints>0 )
21439  {
21440  if( mlpissoftmax(network, _state) )
21441  {
21442  ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+1, "MLPAvgCESparse: sparse matrix XY has less than NIn+1 columns", _state);
21443  }
21444  else
21445  {
21446  ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPAvgCESparse: sparse matrix XY has less than NIn+NOut columns", _state);
21447  }
21448  }
21449  mlpallerrorsx(network, &network->dummydxy, xy, npoints, 1, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state);
21450  result = network->err.avgce;
21451  return result;
21452 }
21453 
21454 
21455 /*************************************************************************
21456 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
21457 *************************************************************************/
21458 double _pexec_mlpavgcesparse(multilayerperceptron* network,
21459  sparsematrix* xy,
21460  ae_int_t npoints, ae_state *_state)
21461 {
21462  return mlpavgcesparse(network,xy,npoints, _state);
21463 }
21464 
21465 
21466 /*************************************************************************
21467 RMS error on the test set given.
21468 
21469 
21470 FOR USERS OF COMMERCIAL EDITION:
21471 
21472  ! Commercial version of ALGLIB includes two important improvements of
21473  ! this function:
21474  ! * multicore support (C++ and C# computational cores)
21475  ! * SSE support
21476  !
21477  ! First improvement gives close-to-linear speedup on multicore systems.
21478  ! Second improvement gives constant speedup (2-3x depending on your CPU)
21479  !
21480  ! In order to use multicore features you have to:
21481  ! * use commercial version of ALGLIB
21482  ! * call this function with "smp_" prefix, which indicates that
21483  ! multicore code will be used (for multicore support)
21484  !
21485  ! In order to use SSE features you have to:
21486  ! * use commercial version of ALGLIB on Intel processors
21487  ! * use C++ computational core
21488  !
21489  ! This note is given for users of commercial edition; if you use GPL
21490  ! edition, you still will be able to call smp-version of this function,
21491  ! but all computations will be done serially.
21492  !
21493  ! We recommend you to carefully read ALGLIB Reference Manual, section
21494  ! called 'SMP support', before using parallel version of this function.
21495 
21496 
21497 INPUT PARAMETERS:
21498  Network - neural network;
21499  XY - training set, see below for information on the
21500  training set format;
21501  NPoints - points count.
21502 
21503 RESULT:
21504 Root mean square error. Its meaning for regression task is obvious. As for
21505 classification task, RMS error means error when estimating posterior
21506 probabilities.
21507 
21508 DATASET FORMAT:
21509 
21510 This function uses two different dataset formats - one for regression
21511 networks, another one for classification networks.
21512 
21513 For regression networks with NIn inputs and NOut outputs following dataset
21514 format is used:
21515 * dataset is given by NPoints*(NIn+NOut) matrix
21516 * each row corresponds to one example
21517 * first NIn columns are inputs, next NOut columns are outputs
21518 
21519 For classification networks with NIn inputs and NClasses clases following
21520 dataset format is used:
21521 * dataset is given by NPoints*(NIn+1) matrix
21522 * each row corresponds to one example
21523 * first NIn columns are inputs, last column stores class number (from 0 to
21524  NClasses-1).
21525 
21526  -- ALGLIB --
21527  Copyright 04.11.2007 by Bochkanov Sergey
21528 *************************************************************************/
21529 double mlprmserror(multilayerperceptron* network,
21530  /* Real */ ae_matrix* xy,
21531  ae_int_t npoints,
21532  ae_state *_state)
21533 {
21534  double result;
21535 
21536 
21537  ae_assert(xy->rows>=npoints, "MLPRMSError: XY has less than NPoints rows", _state);
21538  if( npoints>0 )
21539  {
21540  if( mlpissoftmax(network, _state) )
21541  {
21542  ae_assert(xy->cols>=mlpgetinputscount(network, _state)+1, "MLPRMSError: XY has less than NIn+1 columns", _state);
21543  }
21544  else
21545  {
21546  ae_assert(xy->cols>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPRMSError: XY has less than NIn+NOut columns", _state);
21547  }
21548  }
21549  mlpallerrorsx(network, xy, &network->dummysxy, npoints, 0, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state);
21550  result = network->err.rmserror;
21551  return result;
21552 }
21553 
21554 
21555 /*************************************************************************
21556 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
21557 *************************************************************************/
21558 double _pexec_mlprmserror(multilayerperceptron* network,
21559  /* Real */ ae_matrix* xy,
21560  ae_int_t npoints, ae_state *_state)
21561 {
21562  return mlprmserror(network,xy,npoints, _state);
21563 }
21564 
21565 
21566 /*************************************************************************
21567 RMS error on the test set given by sparse matrix.
21568 
21569 
21570 FOR USERS OF COMMERCIAL EDITION:
21571 
21572  ! Commercial version of ALGLIB includes two important improvements of
21573  ! this function:
21574  ! * multicore support (C++ and C# computational cores)
21575  ! * SSE support
21576  !
21577  ! First improvement gives close-to-linear speedup on multicore systems.
21578  ! Second improvement gives constant speedup (2-3x depending on your CPU)
21579  !
21580  ! In order to use multicore features you have to:
21581  ! * use commercial version of ALGLIB
21582  ! * call this function with "smp_" prefix, which indicates that
21583  ! multicore code will be used (for multicore support)
21584  !
21585  ! In order to use SSE features you have to:
21586  ! * use commercial version of ALGLIB on Intel processors
21587  ! * use C++ computational core
21588  !
21589  ! This note is given for users of commercial edition; if you use GPL
21590  ! edition, you still will be able to call smp-version of this function,
21591  ! but all computations will be done serially.
21592  !
21593  ! We recommend you to carefully read ALGLIB Reference Manual, section
21594  ! called 'SMP support', before using parallel version of this function.
21595 
21596 
21597 INPUT PARAMETERS:
21598  Network - neural network;
21599  XY - training set, see below for information on the
21600  training set format. This function checks correctness
21601  of the dataset (no NANs/INFs, class numbers are
21602  correct) and throws exception when incorrect dataset
21603  is passed. Sparse matrix must use CRS format for
21604  storage.
21605  NPoints - points count, >=0.
21606 
21607 RESULT:
21608 Root mean square error. Its meaning for regression task is obvious. As for
21609 classification task, RMS error means error when estimating posterior
21610 probabilities.
21611 
21612 DATASET FORMAT:
21613 
21614 This function uses two different dataset formats - one for regression
21615 networks, another one for classification networks.
21616 
21617 For regression networks with NIn inputs and NOut outputs following dataset
21618 format is used:
21619 * dataset is given by NPoints*(NIn+NOut) matrix
21620 * each row corresponds to one example
21621 * first NIn columns are inputs, next NOut columns are outputs
21622 
21623 For classification networks with NIn inputs and NClasses clases following
21624 dataset format is used:
21625 * dataset is given by NPoints*(NIn+1) matrix
21626 * each row corresponds to one example
21627 * first NIn columns are inputs, last column stores class number (from 0 to
21628  NClasses-1).
21629 
21630  -- ALGLIB --
21631  Copyright 09.08.2012 by Bochkanov Sergey
21632 *************************************************************************/
21633 double mlprmserrorsparse(multilayerperceptron* network,
21634  sparsematrix* xy,
21635  ae_int_t npoints,
21636  ae_state *_state)
21637 {
21638  double result;
21639 
21640 
21641  ae_assert(sparseiscrs(xy, _state), "MLPRMSErrorSparse: sparse matrix XY is not in CRS format.", _state);
21642  ae_assert(sparsegetnrows(xy, _state)>=npoints, "MLPRMSErrorSparse: sparse matrix XY has less than NPoints rows", _state);
21643  if( npoints>0 )
21644  {
21645  if( mlpissoftmax(network, _state) )
21646  {
21647  ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+1, "MLPRMSErrorSparse: sparse matrix XY has less than NIn+1 columns", _state);
21648  }
21649  else
21650  {
21651  ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPRMSErrorSparse: sparse matrix XY has less than NIn+NOut columns", _state);
21652  }
21653  }
21654  mlpallerrorsx(network, &network->dummydxy, xy, npoints, 1, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state);
21655  result = network->err.rmserror;
21656  return result;
21657 }
21658 
21659 
21660 /*************************************************************************
21661 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
21662 *************************************************************************/
21663 double _pexec_mlprmserrorsparse(multilayerperceptron* network,
21664  sparsematrix* xy,
21665  ae_int_t npoints, ae_state *_state)
21666 {
21667  return mlprmserrorsparse(network,xy,npoints, _state);
21668 }
21669 
21670 
21671 /*************************************************************************
21672 Average absolute error on the test set.
21673 
21674 
21675 FOR USERS OF COMMERCIAL EDITION:
21676 
21677  ! Commercial version of ALGLIB includes two important improvements of
21678  ! this function:
21679  ! * multicore support (C++ and C# computational cores)
21680  ! * SSE support
21681  !
21682  ! First improvement gives close-to-linear speedup on multicore systems.
21683  ! Second improvement gives constant speedup (2-3x depending on your CPU)
21684  !
21685  ! In order to use multicore features you have to:
21686  ! * use commercial version of ALGLIB
21687  ! * call this function with "smp_" prefix, which indicates that
21688  ! multicore code will be used (for multicore support)
21689  !
21690  ! In order to use SSE features you have to:
21691  ! * use commercial version of ALGLIB on Intel processors
21692  ! * use C++ computational core
21693  !
21694  ! This note is given for users of commercial edition; if you use GPL
21695  ! edition, you still will be able to call smp-version of this function,
21696  ! but all computations will be done serially.
21697  !
21698  ! We recommend you to carefully read ALGLIB Reference Manual, section
21699  ! called 'SMP support', before using parallel version of this function.
21700 
21701 
21702 INPUT PARAMETERS:
21703  Network - neural network;
21704  XY - training set, see below for information on the
21705  training set format;
21706  NPoints - points count.
21707 
21708 RESULT:
21709 Its meaning for regression task is obvious. As for classification task, it
21710 means average error when estimating posterior probabilities.
21711 
21712 DATASET FORMAT:
21713 
21714 This function uses two different dataset formats - one for regression
21715 networks, another one for classification networks.
21716 
21717 For regression networks with NIn inputs and NOut outputs following dataset
21718 format is used:
21719 * dataset is given by NPoints*(NIn+NOut) matrix
21720 * each row corresponds to one example
21721 * first NIn columns are inputs, next NOut columns are outputs
21722 
21723 For classification networks with NIn inputs and NClasses clases following
21724 dataset format is used:
21725 * dataset is given by NPoints*(NIn+1) matrix
21726 * each row corresponds to one example
21727 * first NIn columns are inputs, last column stores class number (from 0 to
21728  NClasses-1).
21729 
21730  -- ALGLIB --
21731  Copyright 11.03.2008 by Bochkanov Sergey
21732 *************************************************************************/
21733 double mlpavgerror(multilayerperceptron* network,
21734  /* Real */ ae_matrix* xy,
21735  ae_int_t npoints,
21736  ae_state *_state)
21737 {
21738  double result;
21739 
21740 
21741  ae_assert(xy->rows>=npoints, "MLPAvgError: XY has less than NPoints rows", _state);
21742  if( npoints>0 )
21743  {
21744  if( mlpissoftmax(network, _state) )
21745  {
21746  ae_assert(xy->cols>=mlpgetinputscount(network, _state)+1, "MLPAvgError: XY has less than NIn+1 columns", _state);
21747  }
21748  else
21749  {
21750  ae_assert(xy->cols>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPAvgError: XY has less than NIn+NOut columns", _state);
21751  }
21752  }
21753  mlpallerrorsx(network, xy, &network->dummysxy, npoints, 0, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state);
21754  result = network->err.avgerror;
21755  return result;
21756 }
21757 
21758 
21759 /*************************************************************************
21760 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
21761 *************************************************************************/
21762 double _pexec_mlpavgerror(multilayerperceptron* network,
21763  /* Real */ ae_matrix* xy,
21764  ae_int_t npoints, ae_state *_state)
21765 {
21766  return mlpavgerror(network,xy,npoints, _state);
21767 }
21768 
21769 
21770 /*************************************************************************
21771 Average absolute error on the test set given by sparse matrix.
21772 
21773 
21774 FOR USERS OF COMMERCIAL EDITION:
21775 
21776  ! Commercial version of ALGLIB includes two important improvements of
21777  ! this function:
21778  ! * multicore support (C++ and C# computational cores)
21779  ! * SSE support
21780  !
21781  ! First improvement gives close-to-linear speedup on multicore systems.
21782  ! Second improvement gives constant speedup (2-3x depending on your CPU)
21783  !
21784  ! In order to use multicore features you have to:
21785  ! * use commercial version of ALGLIB
21786  ! * call this function with "smp_" prefix, which indicates that
21787  ! multicore code will be used (for multicore support)
21788  !
21789  ! In order to use SSE features you have to:
21790  ! * use commercial version of ALGLIB on Intel processors
21791  ! * use C++ computational core
21792  !
21793  ! This note is given for users of commercial edition; if you use GPL
21794  ! edition, you still will be able to call smp-version of this function,
21795  ! but all computations will be done serially.
21796  !
21797  ! We recommend you to carefully read ALGLIB Reference Manual, section
21798  ! called 'SMP support', before using parallel version of this function.
21799 
21800 
21801 INPUT PARAMETERS:
21802  Network - neural network;
21803  XY - training set, see below for information on the
21804  training set format. This function checks correctness
21805  of the dataset (no NANs/INFs, class numbers are
21806  correct) and throws exception when incorrect dataset
21807  is passed. Sparse matrix must use CRS format for
21808  storage.
21809  NPoints - points count, >=0.
21810 
21811 RESULT:
21812 Its meaning for regression task is obvious. As for classification task, it
21813 means average error when estimating posterior probabilities.
21814 
21815 DATASET FORMAT:
21816 
21817 This function uses two different dataset formats - one for regression
21818 networks, another one for classification networks.
21819 
21820 For regression networks with NIn inputs and NOut outputs following dataset
21821 format is used:
21822 * dataset is given by NPoints*(NIn+NOut) matrix
21823 * each row corresponds to one example
21824 * first NIn columns are inputs, next NOut columns are outputs
21825 
21826 For classification networks with NIn inputs and NClasses clases following
21827 dataset format is used:
21828 * dataset is given by NPoints*(NIn+1) matrix
21829 * each row corresponds to one example
21830 * first NIn columns are inputs, last column stores class number (from 0 to
21831  NClasses-1).
21832 
21833  -- ALGLIB --
21834  Copyright 09.08.2012 by Bochkanov Sergey
21835 *************************************************************************/
21836 double mlpavgerrorsparse(multilayerperceptron* network,
21837  sparsematrix* xy,
21838  ae_int_t npoints,
21839  ae_state *_state)
21840 {
21841  double result;
21842 
21843 
21844  ae_assert(sparseiscrs(xy, _state), "MLPAvgErrorSparse: XY is not in CRS format.", _state);
21845  ae_assert(sparsegetnrows(xy, _state)>=npoints, "MLPAvgErrorSparse: XY has less than NPoints rows", _state);
21846  if( npoints>0 )
21847  {
21848  if( mlpissoftmax(network, _state) )
21849  {
21850  ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+1, "MLPAvgErrorSparse: XY has less than NIn+1 columns", _state);
21851  }
21852  else
21853  {
21854  ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPAvgErrorSparse: XY has less than NIn+NOut columns", _state);
21855  }
21856  }
21857  mlpallerrorsx(network, &network->dummydxy, xy, npoints, 1, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state);
21858  result = network->err.avgerror;
21859  return result;
21860 }
21861 
21862 
21863 /*************************************************************************
21864 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
21865 *************************************************************************/
21866 double _pexec_mlpavgerrorsparse(multilayerperceptron* network,
21867  sparsematrix* xy,
21868  ae_int_t npoints, ae_state *_state)
21869 {
21870  return mlpavgerrorsparse(network,xy,npoints, _state);
21871 }
21872 
21873 
21874 /*************************************************************************
21875 Average relative error on the test set.
21876 
21877 
21878 FOR USERS OF COMMERCIAL EDITION:
21879 
21880  ! Commercial version of ALGLIB includes two important improvements of
21881  ! this function:
21882  ! * multicore support (C++ and C# computational cores)
21883  ! * SSE support
21884  !
21885  ! First improvement gives close-to-linear speedup on multicore systems.
21886  ! Second improvement gives constant speedup (2-3x depending on your CPU)
21887  !
21888  ! In order to use multicore features you have to:
21889  ! * use commercial version of ALGLIB
21890  ! * call this function with "smp_" prefix, which indicates that
21891  ! multicore code will be used (for multicore support)
21892  !
21893  ! In order to use SSE features you have to:
21894  ! * use commercial version of ALGLIB on Intel processors
21895  ! * use C++ computational core
21896  !
21897  ! This note is given for users of commercial edition; if you use GPL
21898  ! edition, you still will be able to call smp-version of this function,
21899  ! but all computations will be done serially.
21900  !
21901  ! We recommend you to carefully read ALGLIB Reference Manual, section
21902  ! called 'SMP support', before using parallel version of this function.
21903 
21904 
21905 INPUT PARAMETERS:
21906  Network - neural network;
21907  XY - training set, see below for information on the
21908  training set format;
21909  NPoints - points count.
21910 
21911 RESULT:
21912 Its meaning for regression task is obvious. As for classification task, it
21913 means average relative error when estimating posterior probability of
21914 belonging to the correct class.
21915 
21916 DATASET FORMAT:
21917 
21918 This function uses two different dataset formats - one for regression
21919 networks, another one for classification networks.
21920 
21921 For regression networks with NIn inputs and NOut outputs following dataset
21922 format is used:
21923 * dataset is given by NPoints*(NIn+NOut) matrix
21924 * each row corresponds to one example
21925 * first NIn columns are inputs, next NOut columns are outputs
21926 
21927 For classification networks with NIn inputs and NClasses clases following
21928 dataset format is used:
21929 * dataset is given by NPoints*(NIn+1) matrix
21930 * each row corresponds to one example
21931 * first NIn columns are inputs, last column stores class number (from 0 to
21932  NClasses-1).
21933 
21934  -- ALGLIB --
21935  Copyright 11.03.2008 by Bochkanov Sergey
21936 *************************************************************************/
21937 double mlpavgrelerror(multilayerperceptron* network,
21938  /* Real */ ae_matrix* xy,
21939  ae_int_t npoints,
21940  ae_state *_state)
21941 {
21942  double result;
21943 
21944 
21945  ae_assert(xy->rows>=npoints, "MLPAvgRelError: XY has less than NPoints rows", _state);
21946  if( npoints>0 )
21947  {
21948  if( mlpissoftmax(network, _state) )
21949  {
21950  ae_assert(xy->cols>=mlpgetinputscount(network, _state)+1, "MLPAvgRelError: XY has less than NIn+1 columns", _state);
21951  }
21952  else
21953  {
21954  ae_assert(xy->cols>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPAvgRelError: XY has less than NIn+NOut columns", _state);
21955  }
21956  }
21957  mlpallerrorsx(network, xy, &network->dummysxy, npoints, 0, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state);
21958  result = network->err.avgrelerror;
21959  return result;
21960 }
21961 
21962 
21963 /*************************************************************************
21964 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
21965 *************************************************************************/
21966 double _pexec_mlpavgrelerror(multilayerperceptron* network,
21967  /* Real */ ae_matrix* xy,
21968  ae_int_t npoints, ae_state *_state)
21969 {
21970  return mlpavgrelerror(network,xy,npoints, _state);
21971 }
21972 
21973 
21974 /*************************************************************************
21975 Average relative error on the test set given by sparse matrix.
21976 
21977 
21978 FOR USERS OF COMMERCIAL EDITION:
21979 
21980  ! Commercial version of ALGLIB includes two important improvements of
21981  ! this function:
21982  ! * multicore support (C++ and C# computational cores)
21983  ! * SSE support
21984  !
21985  ! First improvement gives close-to-linear speedup on multicore systems.
21986  ! Second improvement gives constant speedup (2-3x depending on your CPU)
21987  !
21988  ! In order to use multicore features you have to:
21989  ! * use commercial version of ALGLIB
21990  ! * call this function with "smp_" prefix, which indicates that
21991  ! multicore code will be used (for multicore support)
21992  !
21993  ! In order to use SSE features you have to:
21994  ! * use commercial version of ALGLIB on Intel processors
21995  ! * use C++ computational core
21996  !
21997  ! This note is given for users of commercial edition; if you use GPL
21998  ! edition, you still will be able to call smp-version of this function,
21999  ! but all computations will be done serially.
22000  !
22001  ! We recommend you to carefully read ALGLIB Reference Manual, section
22002  ! called 'SMP support', before using parallel version of this function.
22003 
22004 
22005 INPUT PARAMETERS:
22006  Network - neural network;
22007  XY - training set, see below for information on the
22008  training set format. This function checks correctness
22009  of the dataset (no NANs/INFs, class numbers are
22010  correct) and throws exception when incorrect dataset
22011  is passed. Sparse matrix must use CRS format for
22012  storage.
22013  NPoints - points count, >=0.
22014 
22015 RESULT:
22016 Its meaning for regression task is obvious. As for classification task, it
22017 means average relative error when estimating posterior probability of
22018 belonging to the correct class.
22019 
22020 DATASET FORMAT:
22021 
22022 This function uses two different dataset formats - one for regression
22023 networks, another one for classification networks.
22024 
22025 For regression networks with NIn inputs and NOut outputs following dataset
22026 format is used:
22027 * dataset is given by NPoints*(NIn+NOut) matrix
22028 * each row corresponds to one example
22029 * first NIn columns are inputs, next NOut columns are outputs
22030 
22031 For classification networks with NIn inputs and NClasses clases following
22032 dataset format is used:
22033 * dataset is given by NPoints*(NIn+1) matrix
22034 * each row corresponds to one example
22035 * first NIn columns are inputs, last column stores class number (from 0 to
22036  NClasses-1).
22037 
22038  -- ALGLIB --
22039  Copyright 09.08.2012 by Bochkanov Sergey
22040 *************************************************************************/
22041 double mlpavgrelerrorsparse(multilayerperceptron* network,
22042  sparsematrix* xy,
22043  ae_int_t npoints,
22044  ae_state *_state)
22045 {
22046  double result;
22047 
22048 
22049  ae_assert(sparseiscrs(xy, _state), "MLPAvgRelErrorSparse: XY is not in CRS format.", _state);
22050  ae_assert(sparsegetnrows(xy, _state)>=npoints, "MLPAvgRelErrorSparse: XY has less than NPoints rows", _state);
22051  if( npoints>0 )
22052  {
22053  if( mlpissoftmax(network, _state) )
22054  {
22055  ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+1, "MLPAvgRelErrorSparse: XY has less than NIn+1 columns", _state);
22056  }
22057  else
22058  {
22059  ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPAvgRelErrorSparse: XY has less than NIn+NOut columns", _state);
22060  }
22061  }
22062  mlpallerrorsx(network, &network->dummydxy, xy, npoints, 1, &network->dummyidx, 0, npoints, 0, &network->buf, &network->err, _state);
22063  result = network->err.avgrelerror;
22064  return result;
22065 }
22066 
22067 
22068 /*************************************************************************
22069 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
22070 *************************************************************************/
22071 double _pexec_mlpavgrelerrorsparse(multilayerperceptron* network,
22072  sparsematrix* xy,
22073  ae_int_t npoints, ae_state *_state)
22074 {
22075  return mlpavgrelerrorsparse(network,xy,npoints, _state);
22076 }
22077 
22078 
22079 /*************************************************************************
22080 Gradient calculation
22081 
22082 INPUT PARAMETERS:
22083  Network - network initialized with one of the network creation funcs
22084  X - input vector, length of array must be at least NIn
22085  DesiredY- desired outputs, length of array must be at least NOut
22086  Grad - possibly preallocated array. If size of array is smaller
22087  than WCount, it will be reallocated. It is recommended to
22088  reuse previously allocated array to reduce allocation
22089  overhead.
22090 
22091 OUTPUT PARAMETERS:
22092  E - error function, SUM(sqr(y[i]-desiredy[i])/2,i)
22093  Grad - gradient of E with respect to weights of network, array[WCount]
22094 
22095  -- ALGLIB --
22096  Copyright 04.11.2007 by Bochkanov Sergey
22097 *************************************************************************/
22098 void mlpgrad(multilayerperceptron* network,
22099  /* Real */ ae_vector* x,
22100  /* Real */ ae_vector* desiredy,
22101  double* e,
22102  /* Real */ ae_vector* grad,
22103  ae_state *_state)
22104 {
22105  ae_int_t i;
22106  ae_int_t nout;
22107  ae_int_t ntotal;
22108 
22109  *e = 0;
22110 
22111 
22112  /*
22113  * Alloc
22114  */
22115  rvectorsetlengthatleast(grad, network->structinfo.ptr.p_int[4], _state);
22116 
22117  /*
22118  * Prepare dError/dOut, internal structures
22119  */
22120  mlpprocess(network, x, &network->y, _state);
22121  nout = network->structinfo.ptr.p_int[2];
22122  ntotal = network->structinfo.ptr.p_int[3];
22123  *e = 0;
22124  for(i=0; i<=ntotal-1; i++)
22125  {
22126  network->derror.ptr.p_double[i] = 0;
22127  }
22128  for(i=0; i<=nout-1; i++)
22129  {
22130  network->derror.ptr.p_double[ntotal-nout+i] = network->y.ptr.p_double[i]-desiredy->ptr.p_double[i];
22131  *e = *e+ae_sqr(network->y.ptr.p_double[i]-desiredy->ptr.p_double[i], _state)/2;
22132  }
22133 
22134  /*
22135  * gradient
22136  */
22137  mlpbase_mlpinternalcalculategradient(network, &network->neurons, &network->weights, &network->derror, grad, ae_false, _state);
22138 }
22139 
22140 
22141 /*************************************************************************
22142 Gradient calculation (natural error function is used)
22143 
22144 INPUT PARAMETERS:
22145  Network - network initialized with one of the network creation funcs
22146  X - input vector, length of array must be at least NIn
22147  DesiredY- desired outputs, length of array must be at least NOut
22148  Grad - possibly preallocated array. If size of array is smaller
22149  than WCount, it will be reallocated. It is recommended to
22150  reuse previously allocated array to reduce allocation
22151  overhead.
22152 
22153 OUTPUT PARAMETERS:
22154  E - error function, sum-of-squares for regression networks,
22155  cross-entropy for classification networks.
22156  Grad - gradient of E with respect to weights of network, array[WCount]
22157 
22158  -- ALGLIB --
22159  Copyright 04.11.2007 by Bochkanov Sergey
22160 *************************************************************************/
22161 void mlpgradn(multilayerperceptron* network,
22162  /* Real */ ae_vector* x,
22163  /* Real */ ae_vector* desiredy,
22164  double* e,
22165  /* Real */ ae_vector* grad,
22166  ae_state *_state)
22167 {
22168  double s;
22169  ae_int_t i;
22170  ae_int_t nout;
22171  ae_int_t ntotal;
22172 
22173  *e = 0;
22174 
22175 
22176  /*
22177  * Alloc
22178  */
22179  rvectorsetlengthatleast(grad, network->structinfo.ptr.p_int[4], _state);
22180 
22181  /*
22182  * Prepare dError/dOut, internal structures
22183  */
22184  mlpprocess(network, x, &network->y, _state);
22185  nout = network->structinfo.ptr.p_int[2];
22186  ntotal = network->structinfo.ptr.p_int[3];
22187  for(i=0; i<=ntotal-1; i++)
22188  {
22189  network->derror.ptr.p_double[i] = 0;
22190  }
22191  *e = 0;
22192  if( network->structinfo.ptr.p_int[6]==0 )
22193  {
22194 
22195  /*
22196  * Regression network, least squares
22197  */
22198  for(i=0; i<=nout-1; i++)
22199  {
22200  network->derror.ptr.p_double[ntotal-nout+i] = network->y.ptr.p_double[i]-desiredy->ptr.p_double[i];
22201  *e = *e+ae_sqr(network->y.ptr.p_double[i]-desiredy->ptr.p_double[i], _state)/2;
22202  }
22203  }
22204  else
22205  {
22206 
22207  /*
22208  * Classification network, cross-entropy
22209  */
22210  s = 0;
22211  for(i=0; i<=nout-1; i++)
22212  {
22213  s = s+desiredy->ptr.p_double[i];
22214  }
22215  for(i=0; i<=nout-1; i++)
22216  {
22217  network->derror.ptr.p_double[ntotal-nout+i] = s*network->y.ptr.p_double[i]-desiredy->ptr.p_double[i];
22218  *e = *e+mlpbase_safecrossentropy(desiredy->ptr.p_double[i], network->y.ptr.p_double[i], _state);
22219  }
22220  }
22221 
22222  /*
22223  * gradient
22224  */
22225  mlpbase_mlpinternalcalculategradient(network, &network->neurons, &network->weights, &network->derror, grad, ae_true, _state);
22226 }
22227 
22228 
22229 /*************************************************************************
22230 Batch gradient calculation for a set of inputs/outputs
22231 
22232 
22233 FOR USERS OF COMMERCIAL EDITION:
22234 
22235  ! Commercial version of ALGLIB includes two important improvements of
22236  ! this function:
22237  ! * multicore support (C++ and C# computational cores)
22238  ! * SSE support
22239  !
22240  ! First improvement gives close-to-linear speedup on multicore systems.
22241  ! Second improvement gives constant speedup (2-3x depending on your CPU)
22242  !
22243  ! In order to use multicore features you have to:
22244  ! * use commercial version of ALGLIB
22245  ! * call this function with "smp_" prefix, which indicates that
22246  ! multicore code will be used (for multicore support)
22247  !
22248  ! In order to use SSE features you have to:
22249  ! * use commercial version of ALGLIB on Intel processors
22250  ! * use C++ computational core
22251  !
22252  ! This note is given for users of commercial edition; if you use GPL
22253  ! edition, you still will be able to call smp-version of this function,
22254  ! but all computations will be done serially.
22255  !
22256  ! We recommend you to carefully read ALGLIB Reference Manual, section
22257  ! called 'SMP support', before using parallel version of this function.
22258 
22259 
22260 INPUT PARAMETERS:
22261  Network - network initialized with one of the network creation funcs
22262  XY - original dataset in dense format; one sample = one row:
22263  * first NIn columns contain inputs,
22264  * for regression problem, next NOut columns store
22265  desired outputs.
22266  * for classification problem, next column (just one!)
22267  stores class number.
22268  SSize - number of elements in XY
22269  Grad - possibly preallocated array. If size of array is smaller
22270  than WCount, it will be reallocated. It is recommended to
22271  reuse previously allocated array to reduce allocation
22272  overhead.
22273 
22274 OUTPUT PARAMETERS:
22275  E - error function, SUM(sqr(y[i]-desiredy[i])/2,i)
22276  Grad - gradient of E with respect to weights of network, array[WCount]
22277 
22278  -- ALGLIB --
22279  Copyright 04.11.2007 by Bochkanov Sergey
22280 *************************************************************************/
22281 void mlpgradbatch(multilayerperceptron* network,
22282  /* Real */ ae_matrix* xy,
22283  ae_int_t ssize,
22284  double* e,
22285  /* Real */ ae_vector* grad,
22286  ae_state *_state)
22287 {
22288  ae_frame _frame_block;
22289  ae_int_t i;
22290  ae_int_t nin;
22291  ae_int_t nout;
22292  ae_int_t wcount;
22293  ae_int_t subset0;
22294  ae_int_t subset1;
22295  ae_int_t subsettype;
22296  smlpgrad *sgrad;
22297  ae_smart_ptr _sgrad;
22298 
22299  ae_frame_make(_state, &_frame_block);
22300  *e = 0;
22301  ae_smart_ptr_init(&_sgrad, (void**)&sgrad, _state, ae_true);
22302 
22303  ae_assert(ssize>=0, "MLPGradBatchSparse: SSize<0", _state);
22304  subset0 = 0;
22305  subset1 = ssize;
22306  subsettype = 0;
22307  mlpproperties(network, &nin, &nout, &wcount, _state);
22308  rvectorsetlengthatleast(grad, wcount, _state);
22309  ae_shared_pool_first_recycled(&network->gradbuf, &_sgrad, _state);
22310  while(sgrad!=NULL)
22311  {
22312  sgrad->f = 0.0;
22313  for(i=0; i<=wcount-1; i++)
22314  {
22315  sgrad->g.ptr.p_double[i] = 0.0;
22316  }
22317  ae_shared_pool_next_recycled(&network->gradbuf, &_sgrad, _state);
22318  }
22319  mlpgradbatchx(network, xy, &network->dummysxy, ssize, 0, &network->dummyidx, subset0, subset1, subsettype, &network->buf, &network->gradbuf, _state);
22320  *e = 0.0;
22321  for(i=0; i<=wcount-1; i++)
22322  {
22323  grad->ptr.p_double[i] = 0.0;
22324  }
22325  ae_shared_pool_first_recycled(&network->gradbuf, &_sgrad, _state);
22326  while(sgrad!=NULL)
22327  {
22328  *e = *e+sgrad->f;
22329  for(i=0; i<=wcount-1; i++)
22330  {
22331  grad->ptr.p_double[i] = grad->ptr.p_double[i]+sgrad->g.ptr.p_double[i];
22332  }
22333  ae_shared_pool_next_recycled(&network->gradbuf, &_sgrad, _state);
22334  }
22335  ae_frame_leave(_state);
22336 }
22337 
22338 
22339 /*************************************************************************
22340 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
22341 *************************************************************************/
22342 void _pexec_mlpgradbatch(multilayerperceptron* network,
22343  /* Real */ ae_matrix* xy,
22344  ae_int_t ssize,
22345  double* e,
22346  /* Real */ ae_vector* grad, ae_state *_state)
22347 {
22348  mlpgradbatch(network,xy,ssize,e,grad, _state);
22349 }
22350 
22351 
22352 /*************************************************************************
22353 Batch gradient calculation for a set of inputs/outputs given by sparse
22354 matrices
22355 
22356 
22357 FOR USERS OF COMMERCIAL EDITION:
22358 
22359  ! Commercial version of ALGLIB includes two important improvements of
22360  ! this function:
22361  ! * multicore support (C++ and C# computational cores)
22362  ! * SSE support
22363  !
22364  ! First improvement gives close-to-linear speedup on multicore systems.
22365  ! Second improvement gives constant speedup (2-3x depending on your CPU)
22366  !
22367  ! In order to use multicore features you have to:
22368  ! * use commercial version of ALGLIB
22369  ! * call this function with "smp_" prefix, which indicates that
22370  ! multicore code will be used (for multicore support)
22371  !
22372  ! In order to use SSE features you have to:
22373  ! * use commercial version of ALGLIB on Intel processors
22374  ! * use C++ computational core
22375  !
22376  ! This note is given for users of commercial edition; if you use GPL
22377  ! edition, you still will be able to call smp-version of this function,
22378  ! but all computations will be done serially.
22379  !
22380  ! We recommend you to carefully read ALGLIB Reference Manual, section
22381  ! called 'SMP support', before using parallel version of this function.
22382 
22383 
22384 INPUT PARAMETERS:
22385  Network - network initialized with one of the network creation funcs
22386  XY - original dataset in sparse format; one sample = one row:
22387  * MATRIX MUST BE STORED IN CRS FORMAT
22388  * first NIn columns contain inputs.
22389  * for regression problem, next NOut columns store
22390  desired outputs.
22391  * for classification problem, next column (just one!)
22392  stores class number.
22393  SSize - number of elements in XY
22394  Grad - possibly preallocated array. If size of array is smaller
22395  than WCount, it will be reallocated. It is recommended to
22396  reuse previously allocated array to reduce allocation
22397  overhead.
22398 
22399 OUTPUT PARAMETERS:
22400  E - error function, SUM(sqr(y[i]-desiredy[i])/2,i)
22401  Grad - gradient of E with respect to weights of network, array[WCount]
22402 
22403  -- ALGLIB --
22404  Copyright 26.07.2012 by Bochkanov Sergey
22405 *************************************************************************/
22406 void mlpgradbatchsparse(multilayerperceptron* network,
22407  sparsematrix* xy,
22408  ae_int_t ssize,
22409  double* e,
22410  /* Real */ ae_vector* grad,
22411  ae_state *_state)
22412 {
22413  ae_frame _frame_block;
22414  ae_int_t i;
22415  ae_int_t nin;
22416  ae_int_t nout;
22417  ae_int_t wcount;
22418  ae_int_t subset0;
22419  ae_int_t subset1;
22420  ae_int_t subsettype;
22421  smlpgrad *sgrad;
22422  ae_smart_ptr _sgrad;
22423 
22424  ae_frame_make(_state, &_frame_block);
22425  *e = 0;
22426  ae_smart_ptr_init(&_sgrad, (void**)&sgrad, _state, ae_true);
22427 
22428  ae_assert(ssize>=0, "MLPGradBatchSparse: SSize<0", _state);
22429  ae_assert(sparseiscrs(xy, _state), "MLPGradBatchSparse: sparse matrix XY must be in CRS format.", _state);
22430  subset0 = 0;
22431  subset1 = ssize;
22432  subsettype = 0;
22433  mlpproperties(network, &nin, &nout, &wcount, _state);
22434  rvectorsetlengthatleast(grad, wcount, _state);
22435  ae_shared_pool_first_recycled(&network->gradbuf, &_sgrad, _state);
22436  while(sgrad!=NULL)
22437  {
22438  sgrad->f = 0.0;
22439  for(i=0; i<=wcount-1; i++)
22440  {
22441  sgrad->g.ptr.p_double[i] = 0.0;
22442  }
22443  ae_shared_pool_next_recycled(&network->gradbuf, &_sgrad, _state);
22444  }
22445  mlpgradbatchx(network, &network->dummydxy, xy, ssize, 1, &network->dummyidx, subset0, subset1, subsettype, &network->buf, &network->gradbuf, _state);
22446  *e = 0.0;
22447  for(i=0; i<=wcount-1; i++)
22448  {
22449  grad->ptr.p_double[i] = 0.0;
22450  }
22451  ae_shared_pool_first_recycled(&network->gradbuf, &_sgrad, _state);
22452  while(sgrad!=NULL)
22453  {
22454  *e = *e+sgrad->f;
22455  for(i=0; i<=wcount-1; i++)
22456  {
22457  grad->ptr.p_double[i] = grad->ptr.p_double[i]+sgrad->g.ptr.p_double[i];
22458  }
22459  ae_shared_pool_next_recycled(&network->gradbuf, &_sgrad, _state);
22460  }
22461  ae_frame_leave(_state);
22462 }
22463 
22464 
22465 /*************************************************************************
22466 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
22467 *************************************************************************/
22468 void _pexec_mlpgradbatchsparse(multilayerperceptron* network,
22469  sparsematrix* xy,
22470  ae_int_t ssize,
22471  double* e,
22472  /* Real */ ae_vector* grad, ae_state *_state)
22473 {
22474  mlpgradbatchsparse(network,xy,ssize,e,grad, _state);
22475 }
22476 
22477 
22478 /*************************************************************************
22479 Batch gradient calculation for a subset of dataset
22480 
22481 
22482 FOR USERS OF COMMERCIAL EDITION:
22483 
22484  ! Commercial version of ALGLIB includes two important improvements of
22485  ! this function:
22486  ! * multicore support (C++ and C# computational cores)
22487  ! * SSE support
22488  !
22489  ! First improvement gives close-to-linear speedup on multicore systems.
22490  ! Second improvement gives constant speedup (2-3x depending on your CPU)
22491  !
22492  ! In order to use multicore features you have to:
22493  ! * use commercial version of ALGLIB
22494  ! * call this function with "smp_" prefix, which indicates that
22495  ! multicore code will be used (for multicore support)
22496  !
22497  ! In order to use SSE features you have to:
22498  ! * use commercial version of ALGLIB on Intel processors
22499  ! * use C++ computational core
22500  !
22501  ! This note is given for users of commercial edition; if you use GPL
22502  ! edition, you still will be able to call smp-version of this function,
22503  ! but all computations will be done serially.
22504  !
22505  ! We recommend you to carefully read ALGLIB Reference Manual, section
22506  ! called 'SMP support', before using parallel version of this function.
22507 
22508 
22509 INPUT PARAMETERS:
22510  Network - network initialized with one of the network creation funcs
22511  XY - original dataset in dense format; one sample = one row:
22512  * first NIn columns contain inputs,
22513  * for regression problem, next NOut columns store
22514  desired outputs.
22515  * for classification problem, next column (just one!)
22516  stores class number.
22517  SetSize - real size of XY, SetSize>=0;
22518  Idx - subset of SubsetSize elements, array[SubsetSize]:
22519  * Idx[I] stores row index in the original dataset which is
22520  given by XY. Gradient is calculated with respect to rows
22521  whose indexes are stored in Idx[].
22522  * Idx[] must store correct indexes; this function throws
22523  an exception in case incorrect index (less than 0 or
22524  larger than rows(XY)) is given
22525  * Idx[] may store indexes in any order and even with
22526  repetitions.
22527  SubsetSize- number of elements in Idx[] array:
22528  * positive value means that subset given by Idx[] is processed
22529  * zero value results in zero gradient
22530  * negative value means that full dataset is processed
22531  Grad - possibly preallocated array. If size of array is smaller
22532  than WCount, it will be reallocated. It is recommended to
22533  reuse previously allocated array to reduce allocation
22534  overhead.
22535 
22536 OUTPUT PARAMETERS:
22537  E - error function, SUM(sqr(y[i]-desiredy[i])/2,i)
22538  Grad - gradient of E with respect to weights of network,
22539  array[WCount]
22540 
22541  -- ALGLIB --
22542  Copyright 26.07.2012 by Bochkanov Sergey
22543 *************************************************************************/
22544 void mlpgradbatchsubset(multilayerperceptron* network,
22545  /* Real */ ae_matrix* xy,
22546  ae_int_t setsize,
22547  /* Integer */ ae_vector* idx,
22548  ae_int_t subsetsize,
22549  double* e,
22550  /* Real */ ae_vector* grad,
22551  ae_state *_state)
22552 {
22553  ae_frame _frame_block;
22554  ae_int_t i;
22555  ae_int_t nin;
22556  ae_int_t nout;
22557  ae_int_t wcount;
22558  ae_int_t npoints;
22559  ae_int_t subset0;
22560  ae_int_t subset1;
22561  ae_int_t subsettype;
22562  smlpgrad *sgrad;
22563  ae_smart_ptr _sgrad;
22564 
22565  ae_frame_make(_state, &_frame_block);
22566  *e = 0;
22567  ae_smart_ptr_init(&_sgrad, (void**)&sgrad, _state, ae_true);
22568 
22569  ae_assert(setsize>=0, "MLPGradBatchSubset: SetSize<0", _state);
22570  ae_assert(subsetsize<=idx->cnt, "MLPGradBatchSubset: SubsetSize>Length(Idx)", _state);
22571  npoints = setsize;
22572  if( subsetsize<0 )
22573  {
22574  subset0 = 0;
22575  subset1 = setsize;
22576  subsettype = 0;
22577  }
22578  else
22579  {
22580  subset0 = 0;
22581  subset1 = subsetsize;
22582  subsettype = 1;
22583  for(i=0; i<=subsetsize-1; i++)
22584  {
22585  ae_assert(idx->ptr.p_int[i]>=0, "MLPGradBatchSubset: incorrect index of XY row(Idx[I]<0)", _state);
22586  ae_assert(idx->ptr.p_int[i]<=npoints-1, "MLPGradBatchSubset: incorrect index of XY row(Idx[I]>Rows(XY)-1)", _state);
22587  }
22588  }
22589  mlpproperties(network, &nin, &nout, &wcount, _state);
22590  rvectorsetlengthatleast(grad, wcount, _state);
22591  ae_shared_pool_first_recycled(&network->gradbuf, &_sgrad, _state);
22592  while(sgrad!=NULL)
22593  {
22594  sgrad->f = 0.0;
22595  for(i=0; i<=wcount-1; i++)
22596  {
22597  sgrad->g.ptr.p_double[i] = 0.0;
22598  }
22599  ae_shared_pool_next_recycled(&network->gradbuf, &_sgrad, _state);
22600  }
22601  mlpgradbatchx(network, xy, &network->dummysxy, setsize, 0, idx, subset0, subset1, subsettype, &network->buf, &network->gradbuf, _state);
22602  *e = 0.0;
22603  for(i=0; i<=wcount-1; i++)
22604  {
22605  grad->ptr.p_double[i] = 0.0;
22606  }
22607  ae_shared_pool_first_recycled(&network->gradbuf, &_sgrad, _state);
22608  while(sgrad!=NULL)
22609  {
22610  *e = *e+sgrad->f;
22611  for(i=0; i<=wcount-1; i++)
22612  {
22613  grad->ptr.p_double[i] = grad->ptr.p_double[i]+sgrad->g.ptr.p_double[i];
22614  }
22615  ae_shared_pool_next_recycled(&network->gradbuf, &_sgrad, _state);
22616  }
22617  ae_frame_leave(_state);
22618 }
22619 
22620 
22621 /*************************************************************************
22622 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
22623 *************************************************************************/
22624 void _pexec_mlpgradbatchsubset(multilayerperceptron* network,
22625  /* Real */ ae_matrix* xy,
22626  ae_int_t setsize,
22627  /* Integer */ ae_vector* idx,
22628  ae_int_t subsetsize,
22629  double* e,
22630  /* Real */ ae_vector* grad, ae_state *_state)
22631 {
22632  mlpgradbatchsubset(network,xy,setsize,idx,subsetsize,e,grad, _state);
22633 }
22634 
22635 
22636 /*************************************************************************
22637 Batch gradient calculation for a set of inputs/outputs for a subset of
22638 dataset given by set of indexes.
22639 
22640 
22641 FOR USERS OF COMMERCIAL EDITION:
22642 
22643  ! Commercial version of ALGLIB includes two important improvements of
22644  ! this function:
22645  ! * multicore support (C++ and C# computational cores)
22646  ! * SSE support
22647  !
22648  ! First improvement gives close-to-linear speedup on multicore systems.
22649  ! Second improvement gives constant speedup (2-3x depending on your CPU)
22650  !
22651  ! In order to use multicore features you have to:
22652  ! * use commercial version of ALGLIB
22653  ! * call this function with "smp_" prefix, which indicates that
22654  ! multicore code will be used (for multicore support)
22655  !
22656  ! In order to use SSE features you have to:
22657  ! * use commercial version of ALGLIB on Intel processors
22658  ! * use C++ computational core
22659  !
22660  ! This note is given for users of commercial edition; if you use GPL
22661  ! edition, you still will be able to call smp-version of this function,
22662  ! but all computations will be done serially.
22663  !
22664  ! We recommend you to carefully read ALGLIB Reference Manual, section
22665  ! called 'SMP support', before using parallel version of this function.
22666 
22667 
22668 INPUT PARAMETERS:
22669  Network - network initialized with one of the network creation funcs
22670  XY - original dataset in sparse format; one sample = one row:
22671  * MATRIX MUST BE STORED IN CRS FORMAT
22672  * first NIn columns contain inputs,
22673  * for regression problem, next NOut columns store
22674  desired outputs.
22675  * for classification problem, next column (just one!)
22676  stores class number.
22677  SetSize - real size of XY, SetSize>=0;
22678  Idx - subset of SubsetSize elements, array[SubsetSize]:
22679  * Idx[I] stores row index in the original dataset which is
22680  given by XY. Gradient is calculated with respect to rows
22681  whose indexes are stored in Idx[].
22682  * Idx[] must store correct indexes; this function throws
22683  an exception in case incorrect index (less than 0 or
22684  larger than rows(XY)) is given
22685  * Idx[] may store indexes in any order and even with
22686  repetitions.
22687  SubsetSize- number of elements in Idx[] array:
22688  * positive value means that subset given by Idx[] is processed
22689  * zero value results in zero gradient
22690  * negative value means that full dataset is processed
22691  Grad - possibly preallocated array. If size of array is smaller
22692  than WCount, it will be reallocated. It is recommended to
22693  reuse previously allocated array to reduce allocation
22694  overhead.
22695 
22696 OUTPUT PARAMETERS:
22697  E - error function, SUM(sqr(y[i]-desiredy[i])/2,i)
22698  Grad - gradient of E with respect to weights of network,
22699  array[WCount]
22700 
22701 NOTE: when SubsetSize<0 is used full dataset by call MLPGradBatchSparse
22702  function.
22703 
22704  -- ALGLIB --
22705  Copyright 26.07.2012 by Bochkanov Sergey
22706 *************************************************************************/
22707 void mlpgradbatchsparsesubset(multilayerperceptron* network,
22708  sparsematrix* xy,
22709  ae_int_t setsize,
22710  /* Integer */ ae_vector* idx,
22711  ae_int_t subsetsize,
22712  double* e,
22713  /* Real */ ae_vector* grad,
22714  ae_state *_state)
22715 {
22716  ae_frame _frame_block;
22717  ae_int_t i;
22718  ae_int_t nin;
22719  ae_int_t nout;
22720  ae_int_t wcount;
22721  ae_int_t npoints;
22722  ae_int_t subset0;
22723  ae_int_t subset1;
22724  ae_int_t subsettype;
22725  smlpgrad *sgrad;
22726  ae_smart_ptr _sgrad;
22727 
22728  ae_frame_make(_state, &_frame_block);
22729  *e = 0;
22730  ae_smart_ptr_init(&_sgrad, (void**)&sgrad, _state, ae_true);
22731 
22732  ae_assert(setsize>=0, "MLPGradBatchSparseSubset: SetSize<0", _state);
22733  ae_assert(subsetsize<=idx->cnt, "MLPGradBatchSparseSubset: SubsetSize>Length(Idx)", _state);
22734  ae_assert(sparseiscrs(xy, _state), "MLPGradBatchSparseSubset: sparse matrix XY must be in CRS format.", _state);
22735  npoints = setsize;
22736  if( subsetsize<0 )
22737  {
22738  subset0 = 0;
22739  subset1 = setsize;
22740  subsettype = 0;
22741  }
22742  else
22743  {
22744  subset0 = 0;
22745  subset1 = subsetsize;
22746  subsettype = 1;
22747  for(i=0; i<=subsetsize-1; i++)
22748  {
22749  ae_assert(idx->ptr.p_int[i]>=0, "MLPGradBatchSparseSubset: incorrect index of XY row(Idx[I]<0)", _state);
22750  ae_assert(idx->ptr.p_int[i]<=npoints-1, "MLPGradBatchSparseSubset: incorrect index of XY row(Idx[I]>Rows(XY)-1)", _state);
22751  }
22752  }
22753  mlpproperties(network, &nin, &nout, &wcount, _state);
22754  rvectorsetlengthatleast(grad, wcount, _state);
22755  ae_shared_pool_first_recycled(&network->gradbuf, &_sgrad, _state);
22756  while(sgrad!=NULL)
22757  {
22758  sgrad->f = 0.0;
22759  for(i=0; i<=wcount-1; i++)
22760  {
22761  sgrad->g.ptr.p_double[i] = 0.0;
22762  }
22763  ae_shared_pool_next_recycled(&network->gradbuf, &_sgrad, _state);
22764  }
22765  mlpgradbatchx(network, &network->dummydxy, xy, setsize, 1, idx, subset0, subset1, subsettype, &network->buf, &network->gradbuf, _state);
22766  *e = 0.0;
22767  for(i=0; i<=wcount-1; i++)
22768  {
22769  grad->ptr.p_double[i] = 0.0;
22770  }
22771  ae_shared_pool_first_recycled(&network->gradbuf, &_sgrad, _state);
22772  while(sgrad!=NULL)
22773  {
22774  *e = *e+sgrad->f;
22775  for(i=0; i<=wcount-1; i++)
22776  {
22777  grad->ptr.p_double[i] = grad->ptr.p_double[i]+sgrad->g.ptr.p_double[i];
22778  }
22779  ae_shared_pool_next_recycled(&network->gradbuf, &_sgrad, _state);
22780  }
22781  ae_frame_leave(_state);
22782 }
22783 
22784 
22785 /*************************************************************************
22786 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
22787 *************************************************************************/
22788 void _pexec_mlpgradbatchsparsesubset(multilayerperceptron* network,
22789  sparsematrix* xy,
22790  ae_int_t setsize,
22791  /* Integer */ ae_vector* idx,
22792  ae_int_t subsetsize,
22793  double* e,
22794  /* Real */ ae_vector* grad, ae_state *_state)
22795 {
22796  mlpgradbatchsparsesubset(network,xy,setsize,idx,subsetsize,e,grad, _state);
22797 }
22798 
22799 
22800 void mlpgradbatchx(multilayerperceptron* network,
22801  /* Real */ ae_matrix* densexy,
22802  sparsematrix* sparsexy,
22803  ae_int_t datasetsize,
22804  ae_int_t datasettype,
22805  /* Integer */ ae_vector* idx,
22806  ae_int_t subset0,
22807  ae_int_t subset1,
22808  ae_int_t subsettype,
22809  ae_shared_pool* buf,
22810  ae_shared_pool* gradbuf,
22811  ae_state *_state)
22812 {
22813  ae_frame _frame_block;
22814  ae_int_t nin;
22815  ae_int_t nout;
22816  ae_int_t wcount;
22817  ae_int_t rowsize;
22818  ae_int_t srcidx;
22819  ae_int_t cstart;
22820  ae_int_t csize;
22821  ae_int_t j;
22822  double problemcost;
22823  mlpbuffers *buf2;
22824  ae_smart_ptr _buf2;
22825  ae_int_t len0;
22826  ae_int_t len1;
22827  mlpbuffers *pbuf;
22828  ae_smart_ptr _pbuf;
22829  smlpgrad *sgrad;
22830  ae_smart_ptr _sgrad;
22831 
22832  ae_frame_make(_state, &_frame_block);
22833  ae_smart_ptr_init(&_buf2, (void**)&buf2, _state, ae_true);
22834  ae_smart_ptr_init(&_pbuf, (void**)&pbuf, _state, ae_true);
22835  ae_smart_ptr_init(&_sgrad, (void**)&sgrad, _state, ae_true);
22836 
22837  ae_assert(datasetsize>=0, "MLPGradBatchX: SetSize<0", _state);
22838  ae_assert(datasettype==0||datasettype==1, "MLPGradBatchX: DatasetType is incorrect", _state);
22839  ae_assert(subsettype==0||subsettype==1, "MLPGradBatchX: SubsetType is incorrect", _state);
22840 
22841  /*
22842  * Determine network and dataset properties
22843  */
22844  mlpproperties(network, &nin, &nout, &wcount, _state);
22845  if( mlpissoftmax(network, _state) )
22846  {
22847  rowsize = nin+1;
22848  }
22849  else
22850  {
22851  rowsize = nin+nout;
22852  }
22853 
22854  /*
22855  * Split problem.
22856  *
22857  * Splitting problem allows us to reduce effect of single-precision
22858  * arithmetics (SSE-optimized version of MLPChunkedGradient uses single
22859  * precision internally, but converts them to double precision after
22860  * results are exported from HPC buffer to network). Small batches are
22861  * calculated in single precision, results are aggregated in double
22862  * precision, and it allows us to avoid accumulation of errors when
22863  * we process very large batches (tens of thousands of items).
22864  *
22865  * NOTE: it is important to use real arithmetics for ProblemCost
22866  * because ProblemCost may be larger than MAXINT.
22867  */
22868  problemcost = subset1-subset0;
22869  problemcost = problemcost*wcount;
22870  if( subset1-subset0>=2*mlpbase_microbatchsize&&ae_fp_greater(problemcost,mlpbase_gradbasecasecost) )
22871  {
22872  splitlength(subset1-subset0, mlpbase_microbatchsize, &len0, &len1, _state);
22873  mlpgradbatchx(network, densexy, sparsexy, datasetsize, datasettype, idx, subset0, subset0+len0, subsettype, buf, gradbuf, _state);
22874  mlpgradbatchx(network, densexy, sparsexy, datasetsize, datasettype, idx, subset0+len0, subset1, subsettype, buf, gradbuf, _state);
22875  ae_frame_leave(_state);
22876  return;
22877  }
22878 
22879  /*
22880  * Chunked processing
22881  */
22882  ae_shared_pool_retrieve(gradbuf, &_sgrad, _state);
22883  ae_shared_pool_retrieve(buf, &_pbuf, _state);
22884  hpcpreparechunkedgradient(&network->weights, wcount, mlpntotal(network, _state), nin, nout, pbuf, _state);
22885  cstart = subset0;
22886  while(cstart<subset1)
22887  {
22888 
22889  /*
22890  * Determine size of current chunk and copy it to PBuf.XY
22891  */
22892  csize = ae_minint(subset1, cstart+pbuf->chunksize, _state)-cstart;
22893  for(j=0; j<=csize-1; j++)
22894  {
22895  srcidx = -1;
22896  if( subsettype==0 )
22897  {
22898  srcidx = cstart+j;
22899  }
22900  if( subsettype==1 )
22901  {
22902  srcidx = idx->ptr.p_int[cstart+j];
22903  }
22904  ae_assert(srcidx>=0, "MLPGradBatchX: internal error", _state);
22905  if( datasettype==0 )
22906  {
22907  ae_v_move(&pbuf->xy.ptr.pp_double[j][0], 1, &densexy->ptr.pp_double[srcidx][0], 1, ae_v_len(0,rowsize-1));
22908  }
22909  if( datasettype==1 )
22910  {
22911  sparsegetrow(sparsexy, srcidx, &pbuf->xyrow, _state);
22912  ae_v_move(&pbuf->xy.ptr.pp_double[j][0], 1, &pbuf->xyrow.ptr.p_double[0], 1, ae_v_len(0,rowsize-1));
22913  }
22914  }
22915 
22916  /*
22917  * Process chunk and advance line pointer
22918  */
22919  mlpbase_mlpchunkedgradient(network, &pbuf->xy, 0, csize, &pbuf->batch4buf, &pbuf->hpcbuf, &sgrad->f, ae_false, _state);
22920  cstart = cstart+pbuf->chunksize;
22921  }
22922  hpcfinalizechunkedgradient(pbuf, &sgrad->g, _state);
22923  ae_shared_pool_recycle(buf, &_pbuf, _state);
22924  ae_shared_pool_recycle(gradbuf, &_sgrad, _state);
22925  ae_frame_leave(_state);
22926 }
22927 
22928 
22929 /*************************************************************************
22930 Batch gradient calculation for a set of inputs/outputs
22931 (natural error function is used)
22932 
22933 INPUT PARAMETERS:
22934  Network - network initialized with one of the network creation funcs
22935  XY - set of inputs/outputs; one sample = one row;
22936  first NIn columns contain inputs,
22937  next NOut columns - desired outputs.
22938  SSize - number of elements in XY
22939  Grad - possibly preallocated array. If size of array is smaller
22940  than WCount, it will be reallocated. It is recommended to
22941  reuse previously allocated array to reduce allocation
22942  overhead.
22943 
22944 OUTPUT PARAMETERS:
22945  E - error function, sum-of-squares for regression networks,
22946  cross-entropy for classification networks.
22947  Grad - gradient of E with respect to weights of network, array[WCount]
22948 
22949  -- ALGLIB --
22950  Copyright 04.11.2007 by Bochkanov Sergey
22951 *************************************************************************/
22952 void mlpgradnbatch(multilayerperceptron* network,
22953  /* Real */ ae_matrix* xy,
22954  ae_int_t ssize,
22955  double* e,
22956  /* Real */ ae_vector* grad,
22957  ae_state *_state)
22958 {
22959  ae_frame _frame_block;
22960  ae_int_t i;
22961  ae_int_t nin;
22962  ae_int_t nout;
22963  ae_int_t wcount;
22964  mlpbuffers *pbuf;
22965  ae_smart_ptr _pbuf;
22966 
22967  ae_frame_make(_state, &_frame_block);
22968  *e = 0;
22969  ae_smart_ptr_init(&_pbuf, (void**)&pbuf, _state, ae_true);
22970 
22971 
22972  /*
22973  * Alloc
22974  */
22975  mlpproperties(network, &nin, &nout, &wcount, _state);
22976  ae_shared_pool_retrieve(&network->buf, &_pbuf, _state);
22977  hpcpreparechunkedgradient(&network->weights, wcount, mlpntotal(network, _state), nin, nout, pbuf, _state);
22978  rvectorsetlengthatleast(grad, wcount, _state);
22979  for(i=0; i<=wcount-1; i++)
22980  {
22981  grad->ptr.p_double[i] = 0;
22982  }
22983  *e = 0;
22984  i = 0;
22985  while(i<=ssize-1)
22986  {
22987  mlpbase_mlpchunkedgradient(network, xy, i, ae_minint(ssize, i+pbuf->chunksize, _state)-i, &pbuf->batch4buf, &pbuf->hpcbuf, e, ae_true, _state);
22988  i = i+pbuf->chunksize;
22989  }
22990  hpcfinalizechunkedgradient(pbuf, grad, _state);
22991  ae_shared_pool_recycle(&network->buf, &_pbuf, _state);
22992  ae_frame_leave(_state);
22993 }
22994 
22995 
22996 /*************************************************************************
22997 Batch Hessian calculation (natural error function) using R-algorithm.
22998 Internal subroutine.
22999 
23000  -- ALGLIB --
23001  Copyright 26.01.2008 by Bochkanov Sergey.
23002 
23003  Hessian calculation based on R-algorithm described in
23004  "Fast Exact Multiplication by the Hessian",
23005  B. A. Pearlmutter,
23006  Neural Computation, 1994.
23007 *************************************************************************/
23008 void mlphessiannbatch(multilayerperceptron* network,
23009  /* Real */ ae_matrix* xy,
23010  ae_int_t ssize,
23011  double* e,
23012  /* Real */ ae_vector* grad,
23013  /* Real */ ae_matrix* h,
23014  ae_state *_state)
23015 {
23016 
23017  *e = 0;
23018 
23019  mlpbase_mlphessianbatchinternal(network, xy, ssize, ae_true, e, grad, h, _state);
23020 }
23021 
23022 
23023 /*************************************************************************
23024 Batch Hessian calculation using R-algorithm.
23025 Internal subroutine.
23026 
23027  -- ALGLIB --
23028  Copyright 26.01.2008 by Bochkanov Sergey.
23029 
23030  Hessian calculation based on R-algorithm described in
23031  "Fast Exact Multiplication by the Hessian",
23032  B. A. Pearlmutter,
23033  Neural Computation, 1994.
23034 *************************************************************************/
23035 void mlphessianbatch(multilayerperceptron* network,
23036  /* Real */ ae_matrix* xy,
23037  ae_int_t ssize,
23038  double* e,
23039  /* Real */ ae_vector* grad,
23040  /* Real */ ae_matrix* h,
23041  ae_state *_state)
23042 {
23043 
23044  *e = 0;
23045 
23046  mlpbase_mlphessianbatchinternal(network, xy, ssize, ae_false, e, grad, h, _state);
23047 }
23048 
23049 
23050 /*************************************************************************
23051 Internal subroutine, shouldn't be called by user.
23052 *************************************************************************/
23053 void mlpinternalprocessvector(/* Integer */ ae_vector* structinfo,
23054  /* Real */ ae_vector* weights,
23055  /* Real */ ae_vector* columnmeans,
23056  /* Real */ ae_vector* columnsigmas,
23057  /* Real */ ae_vector* neurons,
23058  /* Real */ ae_vector* dfdnet,
23059  /* Real */ ae_vector* x,
23060  /* Real */ ae_vector* y,
23061  ae_state *_state)
23062 {
23063  ae_int_t i;
23064  ae_int_t n1;
23065  ae_int_t n2;
23066  ae_int_t w1;
23067  ae_int_t w2;
23068  ae_int_t ntotal;
23069  ae_int_t nin;
23070  ae_int_t nout;
23071  ae_int_t istart;
23072  ae_int_t offs;
23073  double net;
23074  double f;
23075  double df;
23076  double d2f;
23077  double mx;
23078  ae_bool perr;
23079 
23080 
23081 
23082  /*
23083  * Read network geometry
23084  */
23085  nin = structinfo->ptr.p_int[1];
23086  nout = structinfo->ptr.p_int[2];
23087  ntotal = structinfo->ptr.p_int[3];
23088  istart = structinfo->ptr.p_int[5];
23089 
23090  /*
23091  * Inputs standartisation and putting in the network
23092  */
23093  for(i=0; i<=nin-1; i++)
23094  {
23095  if( ae_fp_neq(columnsigmas->ptr.p_double[i],0) )
23096  {
23097  neurons->ptr.p_double[i] = (x->ptr.p_double[i]-columnmeans->ptr.p_double[i])/columnsigmas->ptr.p_double[i];
23098  }
23099  else
23100  {
23101  neurons->ptr.p_double[i] = x->ptr.p_double[i]-columnmeans->ptr.p_double[i];
23102  }
23103  }
23104 
23105  /*
23106  * Process network
23107  */
23108  for(i=0; i<=ntotal-1; i++)
23109  {
23110  offs = istart+i*mlpbase_nfieldwidth;
23111  if( structinfo->ptr.p_int[offs+0]>0||structinfo->ptr.p_int[offs+0]==-5 )
23112  {
23113 
23114  /*
23115  * Activation function
23116  */
23117  mlpactivationfunction(neurons->ptr.p_double[structinfo->ptr.p_int[offs+2]], structinfo->ptr.p_int[offs+0], &f, &df, &d2f, _state);
23118  neurons->ptr.p_double[i] = f;
23119  dfdnet->ptr.p_double[i] = df;
23120  continue;
23121  }
23122  if( structinfo->ptr.p_int[offs+0]==0 )
23123  {
23124 
23125  /*
23126  * Adaptive summator
23127  */
23128  n1 = structinfo->ptr.p_int[offs+2];
23129  n2 = n1+structinfo->ptr.p_int[offs+1]-1;
23130  w1 = structinfo->ptr.p_int[offs+3];
23131  w2 = w1+structinfo->ptr.p_int[offs+1]-1;
23132  net = ae_v_dotproduct(&weights->ptr.p_double[w1], 1, &neurons->ptr.p_double[n1], 1, ae_v_len(w1,w2));
23133  neurons->ptr.p_double[i] = net;
23134  dfdnet->ptr.p_double[i] = 1.0;
23135  touchint(&n2, _state);
23136  continue;
23137  }
23138  if( structinfo->ptr.p_int[offs+0]<0 )
23139  {
23140  perr = ae_true;
23141  if( structinfo->ptr.p_int[offs+0]==-2 )
23142  {
23143 
23144  /*
23145  * input neuron, left unchanged
23146  */
23147  perr = ae_false;
23148  }
23149  if( structinfo->ptr.p_int[offs+0]==-3 )
23150  {
23151 
23152  /*
23153  * "-1" neuron
23154  */
23155  neurons->ptr.p_double[i] = -1;
23156  perr = ae_false;
23157  }
23158  if( structinfo->ptr.p_int[offs+0]==-4 )
23159  {
23160 
23161  /*
23162  * "0" neuron
23163  */
23164  neurons->ptr.p_double[i] = 0;
23165  perr = ae_false;
23166  }
23167  ae_assert(!perr, "MLPInternalProcessVector: internal error - unknown neuron type!", _state);
23168  continue;
23169  }
23170  }
23171 
23172  /*
23173  * Extract result
23174  */
23175  ae_v_move(&y->ptr.p_double[0], 1, &neurons->ptr.p_double[ntotal-nout], 1, ae_v_len(0,nout-1));
23176 
23177  /*
23178  * Softmax post-processing or standardisation if needed
23179  */
23180  ae_assert(structinfo->ptr.p_int[6]==0||structinfo->ptr.p_int[6]==1, "MLPInternalProcessVector: unknown normalization type!", _state);
23181  if( structinfo->ptr.p_int[6]==1 )
23182  {
23183 
23184  /*
23185  * Softmax
23186  */
23187  mx = y->ptr.p_double[0];
23188  for(i=1; i<=nout-1; i++)
23189  {
23190  mx = ae_maxreal(mx, y->ptr.p_double[i], _state);
23191  }
23192  net = 0;
23193  for(i=0; i<=nout-1; i++)
23194  {
23195  y->ptr.p_double[i] = ae_exp(y->ptr.p_double[i]-mx, _state);
23196  net = net+y->ptr.p_double[i];
23197  }
23198  for(i=0; i<=nout-1; i++)
23199  {
23200  y->ptr.p_double[i] = y->ptr.p_double[i]/net;
23201  }
23202  }
23203  else
23204  {
23205 
23206  /*
23207  * Standardisation
23208  */
23209  for(i=0; i<=nout-1; i++)
23210  {
23211  y->ptr.p_double[i] = y->ptr.p_double[i]*columnsigmas->ptr.p_double[nin+i]+columnmeans->ptr.p_double[nin+i];
23212  }
23213  }
23214 }
23215 
23216 
23217 /*************************************************************************
23218 Serializer: allocation
23219 
23220  -- ALGLIB --
23221  Copyright 14.03.2011 by Bochkanov Sergey
23222 *************************************************************************/
23223 void mlpalloc(ae_serializer* s,
23224  multilayerperceptron* network,
23225  ae_state *_state)
23226 {
23227  ae_int_t i;
23228  ae_int_t j;
23229  ae_int_t k;
23230  ae_int_t fkind;
23231  double threshold;
23232  double v0;
23233  double v1;
23234  ae_int_t nin;
23235  ae_int_t nout;
23236 
23237 
23238  nin = network->hllayersizes.ptr.p_int[0];
23239  nout = network->hllayersizes.ptr.p_int[network->hllayersizes.cnt-1];
23240  ae_serializer_alloc_entry(s);
23241  ae_serializer_alloc_entry(s);
23242  ae_serializer_alloc_entry(s);
23243  allocintegerarray(s, &network->hllayersizes, -1, _state);
23244  for(i=1; i<=network->hllayersizes.cnt-1; i++)
23245  {
23246  for(j=0; j<=network->hllayersizes.ptr.p_int[i]-1; j++)
23247  {
23248  mlpgetneuroninfo(network, i, j, &fkind, &threshold, _state);
23249  ae_serializer_alloc_entry(s);
23250  ae_serializer_alloc_entry(s);
23251  for(k=0; k<=network->hllayersizes.ptr.p_int[i-1]-1; k++)
23252  {
23253  ae_serializer_alloc_entry(s);
23254  }
23255  }
23256  }
23257  for(j=0; j<=nin-1; j++)
23258  {
23259  mlpgetinputscaling(network, j, &v0, &v1, _state);
23260  ae_serializer_alloc_entry(s);
23261  ae_serializer_alloc_entry(s);
23262  }
23263  for(j=0; j<=nout-1; j++)
23264  {
23265  mlpgetoutputscaling(network, j, &v0, &v1, _state);
23266  ae_serializer_alloc_entry(s);
23267  ae_serializer_alloc_entry(s);
23268  }
23269 }
23270 
23271 
23272 /*************************************************************************
23273 Serializer: serialization
23274 
23275  -- ALGLIB --
23276  Copyright 14.03.2011 by Bochkanov Sergey
23277 *************************************************************************/
23278 void mlpserialize(ae_serializer* s,
23279  multilayerperceptron* network,
23280  ae_state *_state)
23281 {
23282  ae_int_t i;
23283  ae_int_t j;
23284  ae_int_t k;
23285  ae_int_t fkind;
23286  double threshold;
23287  double v0;
23288  double v1;
23289  ae_int_t nin;
23290  ae_int_t nout;
23291 
23292 
23293  nin = network->hllayersizes.ptr.p_int[0];
23294  nout = network->hllayersizes.ptr.p_int[network->hllayersizes.cnt-1];
23295  ae_serializer_serialize_int(s, getmlpserializationcode(_state), _state);
23296  ae_serializer_serialize_int(s, mlpbase_mlpfirstversion, _state);
23297  ae_serializer_serialize_bool(s, mlpissoftmax(network, _state), _state);
23298  serializeintegerarray(s, &network->hllayersizes, -1, _state);
23299  for(i=1; i<=network->hllayersizes.cnt-1; i++)
23300  {
23301  for(j=0; j<=network->hllayersizes.ptr.p_int[i]-1; j++)
23302  {
23303  mlpgetneuroninfo(network, i, j, &fkind, &threshold, _state);
23304  ae_serializer_serialize_int(s, fkind, _state);
23305  ae_serializer_serialize_double(s, threshold, _state);
23306  for(k=0; k<=network->hllayersizes.ptr.p_int[i-1]-1; k++)
23307  {
23308  ae_serializer_serialize_double(s, mlpgetweight(network, i-1, k, i, j, _state), _state);
23309  }
23310  }
23311  }
23312  for(j=0; j<=nin-1; j++)
23313  {
23314  mlpgetinputscaling(network, j, &v0, &v1, _state);
23315  ae_serializer_serialize_double(s, v0, _state);
23316  ae_serializer_serialize_double(s, v1, _state);
23317  }
23318  for(j=0; j<=nout-1; j++)
23319  {
23320  mlpgetoutputscaling(network, j, &v0, &v1, _state);
23321  ae_serializer_serialize_double(s, v0, _state);
23322  ae_serializer_serialize_double(s, v1, _state);
23323  }
23324 }
23325 
23326 
23327 /*************************************************************************
23328 Serializer: unserialization
23329 
23330  -- ALGLIB --
23331  Copyright 14.03.2011 by Bochkanov Sergey
23332 *************************************************************************/
23333 void mlpunserialize(ae_serializer* s,
23334  multilayerperceptron* network,
23335  ae_state *_state)
23336 {
23337  ae_frame _frame_block;
23338  ae_int_t i0;
23339  ae_int_t i1;
23340  ae_int_t i;
23341  ae_int_t j;
23342  ae_int_t k;
23343  ae_int_t fkind;
23344  double threshold;
23345  double v0;
23346  double v1;
23347  ae_int_t nin;
23348  ae_int_t nout;
23349  ae_bool issoftmax;
23350  ae_vector layersizes;
23351 
23352  ae_frame_make(_state, &_frame_block);
23353  _multilayerperceptron_clear(network);
23354  ae_vector_init(&layersizes, 0, DT_INT, _state, ae_true);
23355 
23356 
23357  /*
23358  * check correctness of header
23359  */
23360  ae_serializer_unserialize_int(s, &i0, _state);
23361  ae_assert(i0==getmlpserializationcode(_state), "MLPUnserialize: stream header corrupted", _state);
23362  ae_serializer_unserialize_int(s, &i1, _state);
23363  ae_assert(i1==mlpbase_mlpfirstversion, "MLPUnserialize: stream header corrupted", _state);
23364 
23365  /*
23366  * Create network
23367  */
23368  ae_serializer_unserialize_bool(s, &issoftmax, _state);
23369  unserializeintegerarray(s, &layersizes, _state);
23370  ae_assert((layersizes.cnt==2||layersizes.cnt==3)||layersizes.cnt==4, "MLPUnserialize: too many hidden layers!", _state);
23371  nin = layersizes.ptr.p_int[0];
23372  nout = layersizes.ptr.p_int[layersizes.cnt-1];
23373  if( layersizes.cnt==2 )
23374  {
23375  if( issoftmax )
23376  {
23377  mlpcreatec0(layersizes.ptr.p_int[0], layersizes.ptr.p_int[1], network, _state);
23378  }
23379  else
23380  {
23381  mlpcreate0(layersizes.ptr.p_int[0], layersizes.ptr.p_int[1], network, _state);
23382  }
23383  }
23384  if( layersizes.cnt==3 )
23385  {
23386  if( issoftmax )
23387  {
23388  mlpcreatec1(layersizes.ptr.p_int[0], layersizes.ptr.p_int[1], layersizes.ptr.p_int[2], network, _state);
23389  }
23390  else
23391  {
23392  mlpcreate1(layersizes.ptr.p_int[0], layersizes.ptr.p_int[1], layersizes.ptr.p_int[2], network, _state);
23393  }
23394  }
23395  if( layersizes.cnt==4 )
23396  {
23397  if( issoftmax )
23398  {
23399  mlpcreatec2(layersizes.ptr.p_int[0], layersizes.ptr.p_int[1], layersizes.ptr.p_int[2], layersizes.ptr.p_int[3], network, _state);
23400  }
23401  else
23402  {
23403  mlpcreate2(layersizes.ptr.p_int[0], layersizes.ptr.p_int[1], layersizes.ptr.p_int[2], layersizes.ptr.p_int[3], network, _state);
23404  }
23405  }
23406 
23407  /*
23408  * Load neurons and weights
23409  */
23410  for(i=1; i<=layersizes.cnt-1; i++)
23411  {
23412  for(j=0; j<=layersizes.ptr.p_int[i]-1; j++)
23413  {
23414  ae_serializer_unserialize_int(s, &fkind, _state);
23415  ae_serializer_unserialize_double(s, &threshold, _state);
23416  mlpsetneuroninfo(network, i, j, fkind, threshold, _state);
23417  for(k=0; k<=layersizes.ptr.p_int[i-1]-1; k++)
23418  {
23419  ae_serializer_unserialize_double(s, &v0, _state);
23420  mlpsetweight(network, i-1, k, i, j, v0, _state);
23421  }
23422  }
23423  }
23424 
23425  /*
23426  * Load standartizator
23427  */
23428  for(j=0; j<=nin-1; j++)
23429  {
23430  ae_serializer_unserialize_double(s, &v0, _state);
23431  ae_serializer_unserialize_double(s, &v1, _state);
23432  mlpsetinputscaling(network, j, v0, v1, _state);
23433  }
23434  for(j=0; j<=nout-1; j++)
23435  {
23436  ae_serializer_unserialize_double(s, &v0, _state);
23437  ae_serializer_unserialize_double(s, &v1, _state);
23438  mlpsetoutputscaling(network, j, v0, v1, _state);
23439  }
23440  ae_frame_leave(_state);
23441 }
23442 
23443 
23444 /*************************************************************************
23445 Calculation of all types of errors.
23446 
23447 
23448 FOR USERS OF COMMERCIAL EDITION:
23449 
23450  ! Commercial version of ALGLIB includes two important improvements of
23451  ! this function:
23452  ! * multicore support (C++ and C# computational cores)
23453  ! * SSE support
23454  !
23455  ! First improvement gives close-to-linear speedup on multicore systems.
23456  ! Second improvement gives constant speedup (2-3x depending on your CPU)
23457  !
23458  ! In order to use multicore features you have to:
23459  ! * use commercial version of ALGLIB
23460  ! * call this function with "smp_" prefix, which indicates that
23461  ! multicore code will be used (for multicore support)
23462  !
23463  ! In order to use SSE features you have to:
23464  ! * use commercial version of ALGLIB on Intel processors
23465  ! * use C++ computational core
23466  !
23467  ! This note is given for users of commercial edition; if you use GPL
23468  ! edition, you still will be able to call smp-version of this function,
23469  ! but all computations will be done serially.
23470  !
23471  ! We recommend you to carefully read ALGLIB Reference Manual, section
23472  ! called 'SMP support', before using parallel version of this function.
23473 
23474 
23475 INPUT PARAMETERS:
23476  Network - network initialized with one of the network creation funcs
23477  XY - original dataset; one sample = one row;
23478  first NIn columns contain inputs,
23479  next NOut columns - desired outputs.
23480  SetSize - real size of XY, SetSize>=0;
23481  Subset - subset of SubsetSize elements, array[SubsetSize];
23482  SubsetSize- number of elements in Subset[] array.
23483 
23484 OUTPUT PARAMETERS:
23485  Rep - it contains all type of errors.
23486 
23487 NOTE: when SubsetSize<0 is used full dataset by call MLPGradBatch function.
23488 
23489  -- ALGLIB --
23490  Copyright 04.09.2012 by Bochkanov Sergey
23491 *************************************************************************/
23492 void mlpallerrorssubset(multilayerperceptron* network,
23493  /* Real */ ae_matrix* xy,
23494  ae_int_t setsize,
23495  /* Integer */ ae_vector* subset,
23496  ae_int_t subsetsize,
23497  modelerrors* rep,
23498  ae_state *_state)
23499 {
23500  ae_int_t idx0;
23501  ae_int_t idx1;
23502  ae_int_t idxtype;
23503 
23504  _modelerrors_clear(rep);
23505 
23506  ae_assert(xy->rows>=setsize, "MLPAllErrorsSubset: XY has less than SetSize rows", _state);
23507  if( setsize>0 )
23508  {
23509  if( mlpissoftmax(network, _state) )
23510  {
23511  ae_assert(xy->cols>=mlpgetinputscount(network, _state)+1, "MLPAllErrorsSubset: XY has less than NIn+1 columns", _state);
23512  }
23513  else
23514  {
23515  ae_assert(xy->cols>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPAllErrorsSubset: XY has less than NIn+NOut columns", _state);
23516  }
23517  }
23518  if( subsetsize>=0 )
23519  {
23520  idx0 = 0;
23521  idx1 = subsetsize;
23522  idxtype = 1;
23523  }
23524  else
23525  {
23526  idx0 = 0;
23527  idx1 = setsize;
23528  idxtype = 0;
23529  }
23530  mlpallerrorsx(network, xy, &network->dummysxy, setsize, 0, subset, idx0, idx1, idxtype, &network->buf, rep, _state);
23531 }
23532 
23533 
23534 /*************************************************************************
23535 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
23536 *************************************************************************/
23537 void _pexec_mlpallerrorssubset(multilayerperceptron* network,
23538  /* Real */ ae_matrix* xy,
23539  ae_int_t setsize,
23540  /* Integer */ ae_vector* subset,
23541  ae_int_t subsetsize,
23542  modelerrors* rep, ae_state *_state)
23543 {
23544  mlpallerrorssubset(network,xy,setsize,subset,subsetsize,rep, _state);
23545 }
23546 
23547 
23548 /*************************************************************************
23549 Calculation of all types of errors on sparse dataset.
23550 
23551 
23552 FOR USERS OF COMMERCIAL EDITION:
23553 
23554  ! Commercial version of ALGLIB includes two important improvements of
23555  ! this function:
23556  ! * multicore support (C++ and C# computational cores)
23557  ! * SSE support
23558  !
23559  ! First improvement gives close-to-linear speedup on multicore systems.
23560  ! Second improvement gives constant speedup (2-3x depending on your CPU)
23561  !
23562  ! In order to use multicore features you have to:
23563  ! * use commercial version of ALGLIB
23564  ! * call this function with "smp_" prefix, which indicates that
23565  ! multicore code will be used (for multicore support)
23566  !
23567  ! In order to use SSE features you have to:
23568  ! * use commercial version of ALGLIB on Intel processors
23569  ! * use C++ computational core
23570  !
23571  ! This note is given for users of commercial edition; if you use GPL
23572  ! edition, you still will be able to call smp-version of this function,
23573  ! but all computations will be done serially.
23574  !
23575  ! We recommend you to carefully read ALGLIB Reference Manual, section
23576  ! called 'SMP support', before using parallel version of this function.
23577 
23578 
23579 INPUT PARAMETERS:
23580  Network - network initialized with one of the network creation funcs
23581  XY - original dataset given by sparse matrix;
23582  one sample = one row;
23583  first NIn columns contain inputs,
23584  next NOut columns - desired outputs.
23585  SetSize - real size of XY, SetSize>=0;
23586  Subset - subset of SubsetSize elements, array[SubsetSize];
23587  SubsetSize- number of elements in Subset[] array.
23588 
23589 OUTPUT PARAMETERS:
23590  Rep - it contains all type of errors.
23591 
23592 NOTE: when SubsetSize<0 is used full dataset by call MLPGradBatch function.
23593 
23594  -- ALGLIB --
23595  Copyright 04.09.2012 by Bochkanov Sergey
23596 *************************************************************************/
23597 void mlpallerrorssparsesubset(multilayerperceptron* network,
23598  sparsematrix* xy,
23599  ae_int_t setsize,
23600  /* Integer */ ae_vector* subset,
23601  ae_int_t subsetsize,
23602  modelerrors* rep,
23603  ae_state *_state)
23604 {
23605  ae_int_t idx0;
23606  ae_int_t idx1;
23607  ae_int_t idxtype;
23608 
23609  _modelerrors_clear(rep);
23610 
23611  ae_assert(sparseiscrs(xy, _state), "MLPAllErrorsSparseSubset: XY is not in CRS format.", _state);
23612  ae_assert(sparsegetnrows(xy, _state)>=setsize, "MLPAllErrorsSparseSubset: XY has less than SetSize rows", _state);
23613  if( setsize>0 )
23614  {
23615  if( mlpissoftmax(network, _state) )
23616  {
23617  ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+1, "MLPAllErrorsSparseSubset: XY has less than NIn+1 columns", _state);
23618  }
23619  else
23620  {
23621  ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPAllErrorsSparseSubset: XY has less than NIn+NOut columns", _state);
23622  }
23623  }
23624  if( subsetsize>=0 )
23625  {
23626  idx0 = 0;
23627  idx1 = subsetsize;
23628  idxtype = 1;
23629  }
23630  else
23631  {
23632  idx0 = 0;
23633  idx1 = setsize;
23634  idxtype = 0;
23635  }
23636  mlpallerrorsx(network, &network->dummydxy, xy, setsize, 1, subset, idx0, idx1, idxtype, &network->buf, rep, _state);
23637 }
23638 
23639 
23640 /*************************************************************************
23641 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
23642 *************************************************************************/
23643 void _pexec_mlpallerrorssparsesubset(multilayerperceptron* network,
23644  sparsematrix* xy,
23645  ae_int_t setsize,
23646  /* Integer */ ae_vector* subset,
23647  ae_int_t subsetsize,
23648  modelerrors* rep, ae_state *_state)
23649 {
23650  mlpallerrorssparsesubset(network,xy,setsize,subset,subsetsize,rep, _state);
23651 }
23652 
23653 
23654 /*************************************************************************
23655 Error of the neural network on dataset.
23656 
23657 
23658 FOR USERS OF COMMERCIAL EDITION:
23659 
23660  ! Commercial version of ALGLIB includes two important improvements of
23661  ! this function:
23662  ! * multicore support (C++ and C# computational cores)
23663  ! * SSE support
23664  !
23665  ! First improvement gives close-to-linear speedup on multicore systems.
23666  ! Second improvement gives constant speedup (2-3x depending on your CPU)
23667  !
23668  ! In order to use multicore features you have to:
23669  ! * use commercial version of ALGLIB
23670  ! * call this function with "smp_" prefix, which indicates that
23671  ! multicore code will be used (for multicore support)
23672  !
23673  ! In order to use SSE features you have to:
23674  ! * use commercial version of ALGLIB on Intel processors
23675  ! * use C++ computational core
23676  !
23677  ! This note is given for users of commercial edition; if you use GPL
23678  ! edition, you still will be able to call smp-version of this function,
23679  ! but all computations will be done serially.
23680  !
23681  ! We recommend you to carefully read ALGLIB Reference Manual, section
23682  ! called 'SMP support', before using parallel version of this function.
23683 
23684 
23685 INPUT PARAMETERS:
23686  Network - neural network;
23687  XY - training set, see below for information on the
23688  training set format;
23689  SetSize - real size of XY, SetSize>=0;
23690  Subset - subset of SubsetSize elements, array[SubsetSize];
23691  SubsetSize- number of elements in Subset[] array.
23692 
23693 RESULT:
23694  sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2)
23695 
23696 DATASET FORMAT:
23697 
23698 This function uses two different dataset formats - one for regression
23699 networks, another one for classification networks.
23700 
23701 For regression networks with NIn inputs and NOut outputs following dataset
23702 format is used:
23703 * dataset is given by NPoints*(NIn+NOut) matrix
23704 * each row corresponds to one example
23705 * first NIn columns are inputs, next NOut columns are outputs
23706 
23707 For classification networks with NIn inputs and NClasses clases following
23708 dataset format is used:
23709 * dataset is given by NPoints*(NIn+1) matrix
23710 * each row corresponds to one example
23711 * first NIn columns are inputs, last column stores class number (from 0 to
23712  NClasses-1).
23713 
23714  -- ALGLIB --
23715  Copyright 04.09.2012 by Bochkanov Sergey
23716 *************************************************************************/
23717 double mlperrorsubset(multilayerperceptron* network,
23718  /* Real */ ae_matrix* xy,
23719  ae_int_t setsize,
23720  /* Integer */ ae_vector* subset,
23721  ae_int_t subsetsize,
23722  ae_state *_state)
23723 {
23724  ae_int_t idx0;
23725  ae_int_t idx1;
23726  ae_int_t idxtype;
23727  double result;
23728 
23729 
23730  ae_assert(xy->rows>=setsize, "MLPErrorSubset: XY has less than SetSize rows", _state);
23731  if( setsize>0 )
23732  {
23733  if( mlpissoftmax(network, _state) )
23734  {
23735  ae_assert(xy->cols>=mlpgetinputscount(network, _state)+1, "MLPErrorSubset: XY has less than NIn+1 columns", _state);
23736  }
23737  else
23738  {
23739  ae_assert(xy->cols>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPErrorSubset: XY has less than NIn+NOut columns", _state);
23740  }
23741  }
23742  if( subsetsize>=0 )
23743  {
23744  idx0 = 0;
23745  idx1 = subsetsize;
23746  idxtype = 1;
23747  }
23748  else
23749  {
23750  idx0 = 0;
23751  idx1 = setsize;
23752  idxtype = 0;
23753  }
23754  mlpallerrorsx(network, xy, &network->dummysxy, setsize, 0, subset, idx0, idx1, idxtype, &network->buf, &network->err, _state);
23755  result = ae_sqr(network->err.rmserror, _state)*(idx1-idx0)*mlpgetoutputscount(network, _state)/2;
23756  return result;
23757 }
23758 
23759 
23760 /*************************************************************************
23761 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
23762 *************************************************************************/
23763 double _pexec_mlperrorsubset(multilayerperceptron* network,
23764  /* Real */ ae_matrix* xy,
23765  ae_int_t setsize,
23766  /* Integer */ ae_vector* subset,
23767  ae_int_t subsetsize, ae_state *_state)
23768 {
23769  return mlperrorsubset(network,xy,setsize,subset,subsetsize, _state);
23770 }
23771 
23772 
23773 /*************************************************************************
23774 Error of the neural network on sparse dataset.
23775 
23776 
23777 FOR USERS OF COMMERCIAL EDITION:
23778 
23779  ! Commercial version of ALGLIB includes two important improvements of
23780  ! this function:
23781  ! * multicore support (C++ and C# computational cores)
23782  ! * SSE support
23783  !
23784  ! First improvement gives close-to-linear speedup on multicore systems.
23785  ! Second improvement gives constant speedup (2-3x depending on your CPU)
23786  !
23787  ! In order to use multicore features you have to:
23788  ! * use commercial version of ALGLIB
23789  ! * call this function with "smp_" prefix, which indicates that
23790  ! multicore code will be used (for multicore support)
23791  !
23792  ! In order to use SSE features you have to:
23793  ! * use commercial version of ALGLIB on Intel processors
23794  ! * use C++ computational core
23795  !
23796  ! This note is given for users of commercial edition; if you use GPL
23797  ! edition, you still will be able to call smp-version of this function,
23798  ! but all computations will be done serially.
23799  !
23800  ! We recommend you to carefully read ALGLIB Reference Manual, section
23801  ! called 'SMP support', before using parallel version of this function.
23802 
23803 
23804 INPUT PARAMETERS:
23805  Network - neural network;
23806  XY - training set, see below for information on the
23807  training set format. This function checks correctness
23808  of the dataset (no NANs/INFs, class numbers are
23809  correct) and throws exception when incorrect dataset
23810  is passed. Sparse matrix must use CRS format for
23811  storage.
23812  SetSize - real size of XY, SetSize>=0;
23813  it is used when SubsetSize<0;
23814  Subset - subset of SubsetSize elements, array[SubsetSize];
23815  SubsetSize- number of elements in Subset[] array.
23816 
23817 RESULT:
23818  sum-of-squares error, SUM(sqr(y[i]-desired_y[i])/2)
23819 
23820 DATASET FORMAT:
23821 
23822 This function uses two different dataset formats - one for regression
23823 networks, another one for classification networks.
23824 
23825 For regression networks with NIn inputs and NOut outputs following dataset
23826 format is used:
23827 * dataset is given by NPoints*(NIn+NOut) matrix
23828 * each row corresponds to one example
23829 * first NIn columns are inputs, next NOut columns are outputs
23830 
23831 For classification networks with NIn inputs and NClasses clases following
23832 dataset format is used:
23833 * dataset is given by NPoints*(NIn+1) matrix
23834 * each row corresponds to one example
23835 * first NIn columns are inputs, last column stores class number (from 0 to
23836  NClasses-1).
23837 
23838  -- ALGLIB --
23839  Copyright 04.09.2012 by Bochkanov Sergey
23840 *************************************************************************/
23841 double mlperrorsparsesubset(multilayerperceptron* network,
23842  sparsematrix* xy,
23843  ae_int_t setsize,
23844  /* Integer */ ae_vector* subset,
23845  ae_int_t subsetsize,
23846  ae_state *_state)
23847 {
23848  ae_int_t idx0;
23849  ae_int_t idx1;
23850  ae_int_t idxtype;
23851  double result;
23852 
23853 
23854  ae_assert(sparseiscrs(xy, _state), "MLPErrorSparseSubset: XY is not in CRS format.", _state);
23855  ae_assert(sparsegetnrows(xy, _state)>=setsize, "MLPErrorSparseSubset: XY has less than SetSize rows", _state);
23856  if( setsize>0 )
23857  {
23858  if( mlpissoftmax(network, _state) )
23859  {
23860  ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+1, "MLPErrorSparseSubset: XY has less than NIn+1 columns", _state);
23861  }
23862  else
23863  {
23864  ae_assert(sparsegetncols(xy, _state)>=mlpgetinputscount(network, _state)+mlpgetoutputscount(network, _state), "MLPErrorSparseSubset: XY has less than NIn+NOut columns", _state);
23865  }
23866  }
23867  if( subsetsize>=0 )
23868  {
23869  idx0 = 0;
23870  idx1 = subsetsize;
23871  idxtype = 1;
23872  }
23873  else
23874  {
23875  idx0 = 0;
23876  idx1 = setsize;
23877  idxtype = 0;
23878  }
23879  mlpallerrorsx(network, &network->dummydxy, xy, setsize, 1, subset, idx0, idx1, idxtype, &network->buf, &network->err, _state);
23880  result = ae_sqr(network->err.rmserror, _state)*(idx1-idx0)*mlpgetoutputscount(network, _state)/2;
23881  return result;
23882 }
23883 
23884 
23885 /*************************************************************************
23886 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
23887 *************************************************************************/
23888 double _pexec_mlperrorsparsesubset(multilayerperceptron* network,
23889  sparsematrix* xy,
23890  ae_int_t setsize,
23891  /* Integer */ ae_vector* subset,
23892  ae_int_t subsetsize, ae_state *_state)
23893 {
23894  return mlperrorsparsesubset(network,xy,setsize,subset,subsetsize, _state);
23895 }
23896 
23897 
23898 void mlpallerrorsx(multilayerperceptron* network,
23899  /* Real */ ae_matrix* densexy,
23900  sparsematrix* sparsexy,
23901  ae_int_t datasetsize,
23902  ae_int_t datasettype,
23903  /* Integer */ ae_vector* idx,
23904  ae_int_t subset0,
23905  ae_int_t subset1,
23906  ae_int_t subsettype,
23907  ae_shared_pool* buf,
23908  modelerrors* rep,
23909  ae_state *_state)
23910 {
23911  ae_frame _frame_block;
23912  ae_int_t nin;
23913  ae_int_t nout;
23914  ae_int_t wcount;
23915  ae_int_t rowsize;
23916  ae_bool iscls;
23917  ae_int_t srcidx;
23918  ae_int_t cstart;
23919  ae_int_t csize;
23920  ae_int_t j;
23921  mlpbuffers *pbuf;
23922  ae_smart_ptr _pbuf;
23923  ae_int_t len0;
23924  ae_int_t len1;
23925  modelerrors rep0;
23926  modelerrors rep1;
23927 
23928  ae_frame_make(_state, &_frame_block);
23929  ae_smart_ptr_init(&_pbuf, (void**)&pbuf, _state, ae_true);
23930  _modelerrors_init(&rep0, _state, ae_true);
23931  _modelerrors_init(&rep1, _state, ae_true);
23932 
23933  ae_assert(datasetsize>=0, "MLPAllErrorsX: SetSize<0", _state);
23934  ae_assert(datasettype==0||datasettype==1, "MLPAllErrorsX: DatasetType is incorrect", _state);
23935  ae_assert(subsettype==0||subsettype==1, "MLPAllErrorsX: SubsetType is incorrect", _state);
23936 
23937  /*
23938  * Determine network properties
23939  */
23940  mlpproperties(network, &nin, &nout, &wcount, _state);
23941  iscls = mlpissoftmax(network, _state);
23942 
23943  /*
23944  * Split problem.
23945  *
23946  * Splitting problem allows us to reduce effect of single-precision
23947  * arithmetics (SSE-optimized version of MLPChunkedProcess uses single
23948  * precision internally, but converts them to double precision after
23949  * results are exported from HPC buffer to network). Small batches are
23950  * calculated in single precision, results are aggregated in double
23951  * precision, and it allows us to avoid accumulation of errors when
23952  * we process very large batches (tens of thousands of items).
23953  *
23954  * NOTE: it is important to use real arithmetics for ProblemCost
23955  * because ProblemCost may be larger than MAXINT.
23956  */
23957  if( subset1-subset0>=2*mlpbase_microbatchsize&&ae_fp_greater(inttoreal(subset1-subset0, _state)*inttoreal(wcount, _state),mlpbase_gradbasecasecost) )
23958  {
23959  splitlength(subset1-subset0, mlpbase_microbatchsize, &len0, &len1, _state);
23960  mlpallerrorsx(network, densexy, sparsexy, datasetsize, datasettype, idx, subset0, subset0+len0, subsettype, buf, &rep0, _state);
23961  mlpallerrorsx(network, densexy, sparsexy, datasetsize, datasettype, idx, subset0+len0, subset1, subsettype, buf, &rep1, _state);
23962  rep->relclserror = (len0*rep0.relclserror+len1*rep1.relclserror)/(len0+len1);
23963  rep->avgce = (len0*rep0.avgce+len1*rep1.avgce)/(len0+len1);
23964  rep->rmserror = ae_sqrt((len0*ae_sqr(rep0.rmserror, _state)+len1*ae_sqr(rep1.rmserror, _state))/(len0+len1), _state);
23965  rep->avgerror = (len0*rep0.avgerror+len1*rep1.avgerror)/(len0+len1);
23966  rep->avgrelerror = (len0*rep0.avgrelerror+len1*rep1.avgrelerror)/(len0+len1);
23967  ae_frame_leave(_state);
23968  return;
23969  }
23970 
23971  /*
23972  * Retrieve and prepare
23973  */
23974  ae_shared_pool_retrieve(buf, &_pbuf, _state);
23975  if( iscls )
23976  {
23977  rowsize = nin+1;
23978  dserrallocate(nout, &pbuf->tmp0, _state);
23979  }
23980  else
23981  {
23982  rowsize = nin+nout;
23983  dserrallocate(-nout, &pbuf->tmp0, _state);
23984  }
23985 
23986  /*
23987  * Processing
23988  */
23989  hpcpreparechunkedgradient(&network->weights, wcount, mlpntotal(network, _state), nin, nout, pbuf, _state);
23990  cstart = subset0;
23991  while(cstart<subset1)
23992  {
23993 
23994  /*
23995  * Determine size of current chunk and copy it to PBuf.XY
23996  */
23997  csize = ae_minint(subset1, cstart+pbuf->chunksize, _state)-cstart;
23998  for(j=0; j<=csize-1; j++)
23999  {
24000  srcidx = -1;
24001  if( subsettype==0 )
24002  {
24003  srcidx = cstart+j;
24004  }
24005  if( subsettype==1 )
24006  {
24007  srcidx = idx->ptr.p_int[cstart+j];
24008  }
24009  ae_assert(srcidx>=0, "MLPAllErrorsX: internal error", _state);
24010  if( datasettype==0 )
24011  {
24012  ae_v_move(&pbuf->xy.ptr.pp_double[j][0], 1, &densexy->ptr.pp_double[srcidx][0], 1, ae_v_len(0,rowsize-1));
24013  }
24014  if( datasettype==1 )
24015  {
24016  sparsegetrow(sparsexy, srcidx, &pbuf->xyrow, _state);
24017  ae_v_move(&pbuf->xy.ptr.pp_double[j][0], 1, &pbuf->xyrow.ptr.p_double[0], 1, ae_v_len(0,rowsize-1));
24018  }
24019  }
24020 
24021  /*
24022  * Unpack XY and process (temporary code, to be replaced by chunked processing)
24023  */
24024  for(j=0; j<=csize-1; j++)
24025  {
24026  ae_v_move(&pbuf->xy2.ptr.pp_double[j][0], 1, &pbuf->xy.ptr.pp_double[j][0], 1, ae_v_len(0,rowsize-1));
24027  }
24028  mlpbase_mlpchunkedprocess(network, &pbuf->xy2, 0, csize, &pbuf->batch4buf, &pbuf->hpcbuf, _state);
24029  for(j=0; j<=csize-1; j++)
24030  {
24031  ae_v_move(&pbuf->x.ptr.p_double[0], 1, &pbuf->xy2.ptr.pp_double[j][0], 1, ae_v_len(0,nin-1));
24032  ae_v_move(&pbuf->y.ptr.p_double[0], 1, &pbuf->xy2.ptr.pp_double[j][nin], 1, ae_v_len(0,nout-1));
24033  if( iscls )
24034  {
24035  pbuf->desiredy.ptr.p_double[0] = pbuf->xy.ptr.pp_double[j][nin];
24036  }
24037  else
24038  {
24039  ae_v_move(&pbuf->desiredy.ptr.p_double[0], 1, &pbuf->xy.ptr.pp_double[j][nin], 1, ae_v_len(0,nout-1));
24040  }
24041  dserraccumulate(&pbuf->tmp0, &pbuf->y, &pbuf->desiredy, _state);
24042  }
24043 
24044  /*
24045  * Process chunk and advance line pointer
24046  */
24047  cstart = cstart+pbuf->chunksize;
24048  }
24049  dserrfinish(&pbuf->tmp0, _state);
24050  rep->relclserror = pbuf->tmp0.ptr.p_double[0];
24051  rep->avgce = pbuf->tmp0.ptr.p_double[1]/ae_log(2, _state);
24052  rep->rmserror = pbuf->tmp0.ptr.p_double[2];
24053  rep->avgerror = pbuf->tmp0.ptr.p_double[3];
24054  rep->avgrelerror = pbuf->tmp0.ptr.p_double[4];
24055 
24056  /*
24057  * Recycle
24058  */
24059  ae_shared_pool_recycle(buf, &_pbuf, _state);
24060  ae_frame_leave(_state);
24061 }
24062 
24063 
24064 /*************************************************************************
24065 Internal subroutine: adding new input layer to network
24066 *************************************************************************/
24067 static void mlpbase_addinputlayer(ae_int_t ncount,
24068  /* Integer */ ae_vector* lsizes,
24069  /* Integer */ ae_vector* ltypes,
24070  /* Integer */ ae_vector* lconnfirst,
24071  /* Integer */ ae_vector* lconnlast,
24072  ae_int_t* lastproc,
24073  ae_state *_state)
24074 {
24075 
24076 
24077  lsizes->ptr.p_int[0] = ncount;
24078  ltypes->ptr.p_int[0] = -2;
24079  lconnfirst->ptr.p_int[0] = 0;
24080  lconnlast->ptr.p_int[0] = 0;
24081  *lastproc = 0;
24082 }
24083 
24084 
24085 /*************************************************************************
24086 Internal subroutine: adding new summator layer to network
24087 *************************************************************************/
24088 static void mlpbase_addbiasedsummatorlayer(ae_int_t ncount,
24089  /* Integer */ ae_vector* lsizes,
24090  /* Integer */ ae_vector* ltypes,
24091  /* Integer */ ae_vector* lconnfirst,
24092  /* Integer */ ae_vector* lconnlast,
24093  ae_int_t* lastproc,
24094  ae_state *_state)
24095 {
24096 
24097 
24098  lsizes->ptr.p_int[*lastproc+1] = 1;
24099  ltypes->ptr.p_int[*lastproc+1] = -3;
24100  lconnfirst->ptr.p_int[*lastproc+1] = 0;
24101  lconnlast->ptr.p_int[*lastproc+1] = 0;
24102  lsizes->ptr.p_int[*lastproc+2] = ncount;
24103  ltypes->ptr.p_int[*lastproc+2] = 0;
24104  lconnfirst->ptr.p_int[*lastproc+2] = *lastproc;
24105  lconnlast->ptr.p_int[*lastproc+2] = *lastproc+1;
24106  *lastproc = *lastproc+2;
24107 }
24108 
24109 
24110 /*************************************************************************
24111 Internal subroutine: adding new summator layer to network
24112 *************************************************************************/
24113 static void mlpbase_addactivationlayer(ae_int_t functype,
24114  /* Integer */ ae_vector* lsizes,
24115  /* Integer */ ae_vector* ltypes,
24116  /* Integer */ ae_vector* lconnfirst,
24117  /* Integer */ ae_vector* lconnlast,
24118  ae_int_t* lastproc,
24119  ae_state *_state)
24120 {
24121 
24122 
24123  ae_assert(functype>0||functype==-5, "AddActivationLayer: incorrect function type", _state);
24124  lsizes->ptr.p_int[*lastproc+1] = lsizes->ptr.p_int[*lastproc];
24125  ltypes->ptr.p_int[*lastproc+1] = functype;
24126  lconnfirst->ptr.p_int[*lastproc+1] = *lastproc;
24127  lconnlast->ptr.p_int[*lastproc+1] = *lastproc;
24128  *lastproc = *lastproc+1;
24129 }
24130 
24131 
24132 /*************************************************************************
24133 Internal subroutine: adding new zero layer to network
24134 *************************************************************************/
24135 static void mlpbase_addzerolayer(/* Integer */ ae_vector* lsizes,
24136  /* Integer */ ae_vector* ltypes,
24137  /* Integer */ ae_vector* lconnfirst,
24138  /* Integer */ ae_vector* lconnlast,
24139  ae_int_t* lastproc,
24140  ae_state *_state)
24141 {
24142 
24143 
24144  lsizes->ptr.p_int[*lastproc+1] = 1;
24145  ltypes->ptr.p_int[*lastproc+1] = -4;
24146  lconnfirst->ptr.p_int[*lastproc+1] = 0;
24147  lconnlast->ptr.p_int[*lastproc+1] = 0;
24148  *lastproc = *lastproc+1;
24149 }
24150 
24151 
24152 /*************************************************************************
24153 This routine adds input layer to the high-level description of the network.
24154 
24155 It modifies Network.HLConnections and Network.HLNeurons and assumes that
24156 these arrays have enough place to store data. It accepts following
24157 parameters:
24158  Network - network
24159  ConnIdx - index of the first free entry in the HLConnections
24160  NeuroIdx - index of the first free entry in the HLNeurons
24161  StructInfoIdx- index of the first entry in the low level description
24162  of the current layer (in the StructInfo array)
24163  NIn - number of inputs
24164 
24165 It modified Network and indices.
24166 *************************************************************************/
24167 static void mlpbase_hladdinputlayer(multilayerperceptron* network,
24168  ae_int_t* connidx,
24169  ae_int_t* neuroidx,
24170  ae_int_t* structinfoidx,
24171  ae_int_t nin,
24172  ae_state *_state)
24173 {
24174  ae_int_t i;
24175  ae_int_t offs;
24176 
24177 
24178  offs = mlpbase_hlnfieldwidth*(*neuroidx);
24179  for(i=0; i<=nin-1; i++)
24180  {
24181  network->hlneurons.ptr.p_int[offs+0] = 0;
24182  network->hlneurons.ptr.p_int[offs+1] = i;
24183  network->hlneurons.ptr.p_int[offs+2] = -1;
24184  network->hlneurons.ptr.p_int[offs+3] = -1;
24185  offs = offs+mlpbase_hlnfieldwidth;
24186  }
24187  *neuroidx = *neuroidx+nin;
24188  *structinfoidx = *structinfoidx+nin;
24189 }
24190 
24191 
24192 /*************************************************************************
24193 This routine adds output layer to the high-level description of
24194 the network.
24195 
24196 It modifies Network.HLConnections and Network.HLNeurons and assumes that
24197 these arrays have enough place to store data. It accepts following
24198 parameters:
24199  Network - network
24200  ConnIdx - index of the first free entry in the HLConnections
24201  NeuroIdx - index of the first free entry in the HLNeurons
24202  StructInfoIdx- index of the first entry in the low level description
24203  of the current layer (in the StructInfo array)
24204  WeightsIdx - index of the first entry in the Weights array which
24205  corresponds to the current layer
24206  K - current layer index
24207  NPrev - number of neurons in the previous layer
24208  NOut - number of outputs
24209  IsCls - is it classifier network?
24210  IsLinear - is it network with linear output?
24211 
24212 It modified Network and ConnIdx/NeuroIdx/StructInfoIdx/WeightsIdx.
24213 *************************************************************************/
24214 static void mlpbase_hladdoutputlayer(multilayerperceptron* network,
24215  ae_int_t* connidx,
24216  ae_int_t* neuroidx,
24217  ae_int_t* structinfoidx,
24218  ae_int_t* weightsidx,
24219  ae_int_t k,
24220  ae_int_t nprev,
24221  ae_int_t nout,
24222  ae_bool iscls,
24223  ae_bool islinearout,
24224  ae_state *_state)
24225 {
24226  ae_int_t i;
24227  ae_int_t j;
24228  ae_int_t neurooffs;
24229  ae_int_t connoffs;
24230 
24231 
24232  ae_assert((iscls&&islinearout)||!iscls, "HLAddOutputLayer: internal error", _state);
24233  neurooffs = mlpbase_hlnfieldwidth*(*neuroidx);
24234  connoffs = mlpbase_hlconnfieldwidth*(*connidx);
24235  if( !iscls )
24236  {
24237 
24238  /*
24239  * Regression network
24240  */
24241  for(i=0; i<=nout-1; i++)
24242  {
24243  network->hlneurons.ptr.p_int[neurooffs+0] = k;
24244  network->hlneurons.ptr.p_int[neurooffs+1] = i;
24245  network->hlneurons.ptr.p_int[neurooffs+2] = *structinfoidx+1+nout+i;
24246  network->hlneurons.ptr.p_int[neurooffs+3] = *weightsidx+nprev+(nprev+1)*i;
24247  neurooffs = neurooffs+mlpbase_hlnfieldwidth;
24248  }
24249  for(i=0; i<=nprev-1; i++)
24250  {
24251  for(j=0; j<=nout-1; j++)
24252  {
24253  network->hlconnections.ptr.p_int[connoffs+0] = k-1;
24254  network->hlconnections.ptr.p_int[connoffs+1] = i;
24255  network->hlconnections.ptr.p_int[connoffs+2] = k;
24256  network->hlconnections.ptr.p_int[connoffs+3] = j;
24257  network->hlconnections.ptr.p_int[connoffs+4] = *weightsidx+i+j*(nprev+1);
24258  connoffs = connoffs+mlpbase_hlconnfieldwidth;
24259  }
24260  }
24261  *connidx = *connidx+nprev*nout;
24262  *neuroidx = *neuroidx+nout;
24263  *structinfoidx = *structinfoidx+2*nout+1;
24264  *weightsidx = *weightsidx+nout*(nprev+1);
24265  }
24266  else
24267  {
24268 
24269  /*
24270  * Classification network
24271  */
24272  for(i=0; i<=nout-2; i++)
24273  {
24274  network->hlneurons.ptr.p_int[neurooffs+0] = k;
24275  network->hlneurons.ptr.p_int[neurooffs+1] = i;
24276  network->hlneurons.ptr.p_int[neurooffs+2] = -1;
24277  network->hlneurons.ptr.p_int[neurooffs+3] = *weightsidx+nprev+(nprev+1)*i;
24278  neurooffs = neurooffs+mlpbase_hlnfieldwidth;
24279  }
24280  network->hlneurons.ptr.p_int[neurooffs+0] = k;
24281  network->hlneurons.ptr.p_int[neurooffs+1] = i;
24282  network->hlneurons.ptr.p_int[neurooffs+2] = -1;
24283  network->hlneurons.ptr.p_int[neurooffs+3] = -1;
24284  for(i=0; i<=nprev-1; i++)
24285  {
24286  for(j=0; j<=nout-2; j++)
24287  {
24288  network->hlconnections.ptr.p_int[connoffs+0] = k-1;
24289  network->hlconnections.ptr.p_int[connoffs+1] = i;
24290  network->hlconnections.ptr.p_int[connoffs+2] = k;
24291  network->hlconnections.ptr.p_int[connoffs+3] = j;
24292  network->hlconnections.ptr.p_int[connoffs+4] = *weightsidx+i+j*(nprev+1);
24293  connoffs = connoffs+mlpbase_hlconnfieldwidth;
24294  }
24295  }
24296  *connidx = *connidx+nprev*(nout-1);
24297  *neuroidx = *neuroidx+nout;
24298  *structinfoidx = *structinfoidx+nout+2;
24299  *weightsidx = *weightsidx+(nout-1)*(nprev+1);
24300  }
24301 }
24302 
24303 
24304 /*************************************************************************
24305 This routine adds hidden layer to the high-level description of
24306 the network.
24307 
24308 It modifies Network.HLConnections and Network.HLNeurons and assumes that
24309 these arrays have enough place to store data. It accepts following
24310 parameters:
24311  Network - network
24312  ConnIdx - index of the first free entry in the HLConnections
24313  NeuroIdx - index of the first free entry in the HLNeurons
24314  StructInfoIdx- index of the first entry in the low level description
24315  of the current layer (in the StructInfo array)
24316  WeightsIdx - index of the first entry in the Weights array which
24317  corresponds to the current layer
24318  K - current layer index
24319  NPrev - number of neurons in the previous layer
24320  NCur - number of neurons in the current layer
24321 
24322 It modified Network and ConnIdx/NeuroIdx/StructInfoIdx/WeightsIdx.
24323 *************************************************************************/
24324 static void mlpbase_hladdhiddenlayer(multilayerperceptron* network,
24325  ae_int_t* connidx,
24326  ae_int_t* neuroidx,
24327  ae_int_t* structinfoidx,
24328  ae_int_t* weightsidx,
24329  ae_int_t k,
24330  ae_int_t nprev,
24331  ae_int_t ncur,
24332  ae_state *_state)
24333 {
24334  ae_int_t i;
24335  ae_int_t j;
24336  ae_int_t neurooffs;
24337  ae_int_t connoffs;
24338 
24339 
24340  neurooffs = mlpbase_hlnfieldwidth*(*neuroidx);
24341  connoffs = mlpbase_hlconnfieldwidth*(*connidx);
24342  for(i=0; i<=ncur-1; i++)
24343  {
24344  network->hlneurons.ptr.p_int[neurooffs+0] = k;
24345  network->hlneurons.ptr.p_int[neurooffs+1] = i;
24346  network->hlneurons.ptr.p_int[neurooffs+2] = *structinfoidx+1+ncur+i;
24347  network->hlneurons.ptr.p_int[neurooffs+3] = *weightsidx+nprev+(nprev+1)*i;
24348  neurooffs = neurooffs+mlpbase_hlnfieldwidth;
24349  }
24350  for(i=0; i<=nprev-1; i++)
24351  {
24352  for(j=0; j<=ncur-1; j++)
24353  {
24354  network->hlconnections.ptr.p_int[connoffs+0] = k-1;
24355  network->hlconnections.ptr.p_int[connoffs+1] = i;
24356  network->hlconnections.ptr.p_int[connoffs+2] = k;
24357  network->hlconnections.ptr.p_int[connoffs+3] = j;
24358  network->hlconnections.ptr.p_int[connoffs+4] = *weightsidx+i+j*(nprev+1);
24359  connoffs = connoffs+mlpbase_hlconnfieldwidth;
24360  }
24361  }
24362  *connidx = *connidx+nprev*ncur;
24363  *neuroidx = *neuroidx+ncur;
24364  *structinfoidx = *structinfoidx+2*ncur+1;
24365  *weightsidx = *weightsidx+ncur*(nprev+1);
24366 }
24367 
24368 
24369 /*************************************************************************
24370 This function fills high level information about network created using
24371 internal MLPCreate() function.
24372 
24373 This function does NOT examine StructInfo for low level information, it
24374 just expects that network has following structure:
24375 
24376  input neuron \
24377  ... | input layer
24378  input neuron /
24379 
24380  "-1" neuron \
24381  biased summator |
24382  ... |
24383  biased summator | hidden layer(s), if there are exists any
24384  activation function |
24385  ... |
24386  activation function /
24387 
24388  "-1" neuron \
24389  biased summator | output layer:
24390  ... |
24391  biased summator | * we have NOut summators/activators for regression networks
24392  activation function | * we have only NOut-1 summators and no activators for classifiers
24393  ... | * we have "0" neuron only when we have classifier
24394  activation function |
24395  "0" neuron /
24396 
24397 
24398  -- ALGLIB --
24399  Copyright 30.03.2008 by Bochkanov Sergey
24400 *************************************************************************/
24401 static void mlpbase_fillhighlevelinformation(multilayerperceptron* network,
24402  ae_int_t nin,
24403  ae_int_t nhid1,
24404  ae_int_t nhid2,
24405  ae_int_t nout,
24406  ae_bool iscls,
24407  ae_bool islinearout,
24408  ae_state *_state)
24409 {
24410  ae_int_t idxweights;
24411  ae_int_t idxstruct;
24412  ae_int_t idxneuro;
24413  ae_int_t idxconn;
24414 
24415 
24416  ae_assert((iscls&&islinearout)||!iscls, "FillHighLevelInformation: internal error", _state);
24417 
24418  /*
24419  * Preparations common to all types of networks
24420  */
24421  idxweights = 0;
24422  idxneuro = 0;
24423  idxstruct = 0;
24424  idxconn = 0;
24425  network->hlnetworktype = 0;
24426 
24427  /*
24428  * network without hidden layers
24429  */
24430  if( nhid1==0 )
24431  {
24432  ae_vector_set_length(&network->hllayersizes, 2, _state);
24433  network->hllayersizes.ptr.p_int[0] = nin;
24434  network->hllayersizes.ptr.p_int[1] = nout;
24435  if( !iscls )
24436  {
24437  ae_vector_set_length(&network->hlconnections, mlpbase_hlconnfieldwidth*nin*nout, _state);
24438  ae_vector_set_length(&network->hlneurons, mlpbase_hlnfieldwidth*(nin+nout), _state);
24439  network->hlnormtype = 0;
24440  }
24441  else
24442  {
24443  ae_vector_set_length(&network->hlconnections, mlpbase_hlconnfieldwidth*nin*(nout-1), _state);
24444  ae_vector_set_length(&network->hlneurons, mlpbase_hlnfieldwidth*(nin+nout), _state);
24445  network->hlnormtype = 1;
24446  }
24447  mlpbase_hladdinputlayer(network, &idxconn, &idxneuro, &idxstruct, nin, _state);
24448  mlpbase_hladdoutputlayer(network, &idxconn, &idxneuro, &idxstruct, &idxweights, 1, nin, nout, iscls, islinearout, _state);
24449  return;
24450  }
24451 
24452  /*
24453  * network with one hidden layers
24454  */
24455  if( nhid2==0 )
24456  {
24457  ae_vector_set_length(&network->hllayersizes, 3, _state);
24458  network->hllayersizes.ptr.p_int[0] = nin;
24459  network->hllayersizes.ptr.p_int[1] = nhid1;
24460  network->hllayersizes.ptr.p_int[2] = nout;
24461  if( !iscls )
24462  {
24463  ae_vector_set_length(&network->hlconnections, mlpbase_hlconnfieldwidth*(nin*nhid1+nhid1*nout), _state);
24464  ae_vector_set_length(&network->hlneurons, mlpbase_hlnfieldwidth*(nin+nhid1+nout), _state);
24465  network->hlnormtype = 0;
24466  }
24467  else
24468  {
24469  ae_vector_set_length(&network->hlconnections, mlpbase_hlconnfieldwidth*(nin*nhid1+nhid1*(nout-1)), _state);
24470  ae_vector_set_length(&network->hlneurons, mlpbase_hlnfieldwidth*(nin+nhid1+nout), _state);
24471  network->hlnormtype = 1;
24472  }
24473  mlpbase_hladdinputlayer(network, &idxconn, &idxneuro, &idxstruct, nin, _state);
24474  mlpbase_hladdhiddenlayer(network, &idxconn, &idxneuro, &idxstruct, &idxweights, 1, nin, nhid1, _state);
24475  mlpbase_hladdoutputlayer(network, &idxconn, &idxneuro, &idxstruct, &idxweights, 2, nhid1, nout, iscls, islinearout, _state);
24476  return;
24477  }
24478 
24479  /*
24480  * Two hidden layers
24481  */
24482  ae_vector_set_length(&network->hllayersizes, 4, _state);
24483  network->hllayersizes.ptr.p_int[0] = nin;
24484  network->hllayersizes.ptr.p_int[1] = nhid1;
24485  network->hllayersizes.ptr.p_int[2] = nhid2;
24486  network->hllayersizes.ptr.p_int[3] = nout;
24487  if( !iscls )
24488  {
24489  ae_vector_set_length(&network->hlconnections, mlpbase_hlconnfieldwidth*(nin*nhid1+nhid1*nhid2+nhid2*nout), _state);
24490  ae_vector_set_length(&network->hlneurons, mlpbase_hlnfieldwidth*(nin+nhid1+nhid2+nout), _state);
24491  network->hlnormtype = 0;
24492  }
24493  else
24494  {
24495  ae_vector_set_length(&network->hlconnections, mlpbase_hlconnfieldwidth*(nin*nhid1+nhid1*nhid2+nhid2*(nout-1)), _state);
24496  ae_vector_set_length(&network->hlneurons, mlpbase_hlnfieldwidth*(nin+nhid1+nhid2+nout), _state);
24497  network->hlnormtype = 1;
24498  }
24499  mlpbase_hladdinputlayer(network, &idxconn, &idxneuro, &idxstruct, nin, _state);
24500  mlpbase_hladdhiddenlayer(network, &idxconn, &idxneuro, &idxstruct, &idxweights, 1, nin, nhid1, _state);
24501  mlpbase_hladdhiddenlayer(network, &idxconn, &idxneuro, &idxstruct, &idxweights, 2, nhid1, nhid2, _state);
24502  mlpbase_hladdoutputlayer(network, &idxconn, &idxneuro, &idxstruct, &idxweights, 3, nhid2, nout, iscls, islinearout, _state);
24503 }
24504 
24505 
24506 /*************************************************************************
24507 Internal subroutine.
24508 
24509  -- ALGLIB --
24510  Copyright 04.11.2007 by Bochkanov Sergey
24511 *************************************************************************/
24512 static void mlpbase_mlpcreate(ae_int_t nin,
24513  ae_int_t nout,
24514  /* Integer */ ae_vector* lsizes,
24515  /* Integer */ ae_vector* ltypes,
24516  /* Integer */ ae_vector* lconnfirst,
24517  /* Integer */ ae_vector* lconnlast,
24518  ae_int_t layerscount,
24519  ae_bool isclsnet,
24520  multilayerperceptron* network,
24521  ae_state *_state)
24522 {
24523  ae_frame _frame_block;
24524  ae_int_t i;
24525  ae_int_t j;
24526  ae_int_t ssize;
24527  ae_int_t ntotal;
24528  ae_int_t wcount;
24529  ae_int_t offs;
24530  ae_int_t nprocessed;
24531  ae_int_t wallocated;
24532  ae_vector localtemp;
24533  ae_vector lnfirst;
24534  ae_vector lnsyn;
24535  mlpbuffers buf;
24536  smlpgrad sgrad;
24537 
24538  ae_frame_make(_state, &_frame_block);
24539  _multilayerperceptron_clear(network);
24540  ae_vector_init(&localtemp, 0, DT_INT, _state, ae_true);
24541  ae_vector_init(&lnfirst, 0, DT_INT, _state, ae_true);
24542  ae_vector_init(&lnsyn, 0, DT_INT, _state, ae_true);
24543  _mlpbuffers_init(&buf, _state, ae_true);
24544  _smlpgrad_init(&sgrad, _state, ae_true);
24545 
24546 
24547  /*
24548  * Check
24549  */
24550  ae_assert(layerscount>0, "MLPCreate: wrong parameters!", _state);
24551  ae_assert(ltypes->ptr.p_int[0]==-2, "MLPCreate: wrong LTypes[0] (must be -2)!", _state);
24552  for(i=0; i<=layerscount-1; i++)
24553  {
24554  ae_assert(lsizes->ptr.p_int[i]>0, "MLPCreate: wrong LSizes!", _state);
24555  ae_assert(lconnfirst->ptr.p_int[i]>=0&&(lconnfirst->ptr.p_int[i]<i||i==0), "MLPCreate: wrong LConnFirst!", _state);
24556  ae_assert(lconnlast->ptr.p_int[i]>=lconnfirst->ptr.p_int[i]&&(lconnlast->ptr.p_int[i]<i||i==0), "MLPCreate: wrong LConnLast!", _state);
24557  }
24558 
24559  /*
24560  * Build network geometry
24561  */
24562  ae_vector_set_length(&lnfirst, layerscount-1+1, _state);
24563  ae_vector_set_length(&lnsyn, layerscount-1+1, _state);
24564  ntotal = 0;
24565  wcount = 0;
24566  for(i=0; i<=layerscount-1; i++)
24567  {
24568 
24569  /*
24570  * Analyze connections.
24571  * This code must throw an assertion in case of unknown LTypes[I]
24572  */
24573  lnsyn.ptr.p_int[i] = -1;
24574  if( ltypes->ptr.p_int[i]>=0||ltypes->ptr.p_int[i]==-5 )
24575  {
24576  lnsyn.ptr.p_int[i] = 0;
24577  for(j=lconnfirst->ptr.p_int[i]; j<=lconnlast->ptr.p_int[i]; j++)
24578  {
24579  lnsyn.ptr.p_int[i] = lnsyn.ptr.p_int[i]+lsizes->ptr.p_int[j];
24580  }
24581  }
24582  else
24583  {
24584  if( (ltypes->ptr.p_int[i]==-2||ltypes->ptr.p_int[i]==-3)||ltypes->ptr.p_int[i]==-4 )
24585  {
24586  lnsyn.ptr.p_int[i] = 0;
24587  }
24588  }
24589  ae_assert(lnsyn.ptr.p_int[i]>=0, "MLPCreate: internal error #0!", _state);
24590 
24591  /*
24592  * Other info
24593  */
24594  lnfirst.ptr.p_int[i] = ntotal;
24595  ntotal = ntotal+lsizes->ptr.p_int[i];
24596  if( ltypes->ptr.p_int[i]==0 )
24597  {
24598  wcount = wcount+lnsyn.ptr.p_int[i]*lsizes->ptr.p_int[i];
24599  }
24600  }
24601  ssize = 7+ntotal*mlpbase_nfieldwidth;
24602 
24603  /*
24604  * Allocate
24605  */
24606  ae_vector_set_length(&network->structinfo, ssize-1+1, _state);
24607  ae_vector_set_length(&network->weights, wcount-1+1, _state);
24608  if( isclsnet )
24609  {
24610  ae_vector_set_length(&network->columnmeans, nin-1+1, _state);
24611  ae_vector_set_length(&network->columnsigmas, nin-1+1, _state);
24612  }
24613  else
24614  {
24615  ae_vector_set_length(&network->columnmeans, nin+nout-1+1, _state);
24616  ae_vector_set_length(&network->columnsigmas, nin+nout-1+1, _state);
24617  }
24618  ae_vector_set_length(&network->neurons, ntotal-1+1, _state);
24619  ae_vector_set_length(&network->nwbuf, ae_maxint(wcount, 2*nout, _state)-1+1, _state);
24620  ae_vector_set_length(&network->integerbuf, 3+1, _state);
24621  ae_vector_set_length(&network->dfdnet, ntotal-1+1, _state);
24622  ae_vector_set_length(&network->x, nin-1+1, _state);
24623  ae_vector_set_length(&network->y, nout-1+1, _state);
24624  ae_vector_set_length(&network->derror, ntotal-1+1, _state);
24625 
24626  /*
24627  * Fill structure: global info
24628  */
24629  network->structinfo.ptr.p_int[0] = ssize;
24630  network->structinfo.ptr.p_int[1] = nin;
24631  network->structinfo.ptr.p_int[2] = nout;
24632  network->structinfo.ptr.p_int[3] = ntotal;
24633  network->structinfo.ptr.p_int[4] = wcount;
24634  network->structinfo.ptr.p_int[5] = 7;
24635  if( isclsnet )
24636  {
24637  network->structinfo.ptr.p_int[6] = 1;
24638  }
24639  else
24640  {
24641  network->structinfo.ptr.p_int[6] = 0;
24642  }
24643 
24644  /*
24645  * Fill structure: neuron connections
24646  */
24647  nprocessed = 0;
24648  wallocated = 0;
24649  for(i=0; i<=layerscount-1; i++)
24650  {
24651  for(j=0; j<=lsizes->ptr.p_int[i]-1; j++)
24652  {
24653  offs = network->structinfo.ptr.p_int[5]+nprocessed*mlpbase_nfieldwidth;
24654  network->structinfo.ptr.p_int[offs+0] = ltypes->ptr.p_int[i];
24655  if( ltypes->ptr.p_int[i]==0 )
24656  {
24657 
24658  /*
24659  * Adaptive summator:
24660  * * connections with weights to previous neurons
24661  */
24662  network->structinfo.ptr.p_int[offs+1] = lnsyn.ptr.p_int[i];
24663  network->structinfo.ptr.p_int[offs+2] = lnfirst.ptr.p_int[lconnfirst->ptr.p_int[i]];
24664  network->structinfo.ptr.p_int[offs+3] = wallocated;
24665  wallocated = wallocated+lnsyn.ptr.p_int[i];
24666  nprocessed = nprocessed+1;
24667  }
24668  if( ltypes->ptr.p_int[i]>0||ltypes->ptr.p_int[i]==-5 )
24669  {
24670 
24671  /*
24672  * Activation layer:
24673  * * each neuron connected to one (only one) of previous neurons.
24674  * * no weights
24675  */
24676  network->structinfo.ptr.p_int[offs+1] = 1;
24677  network->structinfo.ptr.p_int[offs+2] = lnfirst.ptr.p_int[lconnfirst->ptr.p_int[i]]+j;
24678  network->structinfo.ptr.p_int[offs+3] = -1;
24679  nprocessed = nprocessed+1;
24680  }
24681  if( (ltypes->ptr.p_int[i]==-2||ltypes->ptr.p_int[i]==-3)||ltypes->ptr.p_int[i]==-4 )
24682  {
24683  nprocessed = nprocessed+1;
24684  }
24685  }
24686  }
24687  ae_assert(wallocated==wcount, "MLPCreate: internal error #1!", _state);
24688  ae_assert(nprocessed==ntotal, "MLPCreate: internal error #2!", _state);
24689 
24690  /*
24691  * Fill weights by small random values
24692  * Initialize means and sigmas
24693  */
24694  for(i=0; i<=nin-1; i++)
24695  {
24696  network->columnmeans.ptr.p_double[i] = 0;
24697  network->columnsigmas.ptr.p_double[i] = 1;
24698  }
24699  if( !isclsnet )
24700  {
24701  for(i=0; i<=nout-1; i++)
24702  {
24703  network->columnmeans.ptr.p_double[nin+i] = 0;
24704  network->columnsigmas.ptr.p_double[nin+i] = 1;
24705  }
24706  }
24707  mlprandomize(network, _state);
24708 
24709  /*
24710  * Seed buffers
24711  */
24712  ae_shared_pool_set_seed(&network->buf, &buf, sizeof(buf), _mlpbuffers_init, _mlpbuffers_init_copy, _mlpbuffers_destroy, _state);
24713  ae_vector_set_length(&sgrad.g, wcount, _state);
24714  sgrad.f = 0.0;
24715  for(i=0; i<=wcount-1; i++)
24716  {
24717  sgrad.g.ptr.p_double[i] = 0.0;
24718  }
24719  ae_shared_pool_set_seed(&network->gradbuf, &sgrad, sizeof(sgrad), _smlpgrad_init, _smlpgrad_init_copy, _smlpgrad_destroy, _state);
24720  ae_frame_leave(_state);
24721 }
24722 
24723 
24724 /*************************************************************************
24725 Internal subroutine for Hessian calculation.
24726 
24727 WARNING! Unspeakable math far beyong human capabilities :)
24728 *************************************************************************/
24729 static void mlpbase_mlphessianbatchinternal(multilayerperceptron* network,
24730  /* Real */ ae_matrix* xy,
24731  ae_int_t ssize,
24732  ae_bool naturalerr,
24733  double* e,
24734  /* Real */ ae_vector* grad,
24735  /* Real */ ae_matrix* h,
24736  ae_state *_state)
24737 {
24738  ae_frame _frame_block;
24739  ae_int_t nin;
24740  ae_int_t nout;
24741  ae_int_t wcount;
24742  ae_int_t ntotal;
24743  ae_int_t istart;
24744  ae_int_t i;
24745  ae_int_t j;
24746  ae_int_t k;
24747  ae_int_t kl;
24748  ae_int_t offs;
24749  ae_int_t n1;
24750  ae_int_t n2;
24751  ae_int_t w1;
24752  ae_int_t w2;
24753  double s;
24754  double t;
24755  double v;
24756  double et;
24757  ae_bool bflag;
24758  double f;
24759  double df;
24760  double d2f;
24761  double deidyj;
24762  double mx;
24763  double q;
24764  double z;
24765  double s2;
24766  double expi;
24767  double expj;
24768  ae_vector x;
24769  ae_vector desiredy;
24770  ae_vector gt;
24771  ae_vector zeros;
24772  ae_matrix rx;
24773  ae_matrix ry;
24774  ae_matrix rdx;
24775  ae_matrix rdy;
24776 
24777  ae_frame_make(_state, &_frame_block);
24778  *e = 0;
24779  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
24780  ae_vector_init(&desiredy, 0, DT_REAL, _state, ae_true);
24781  ae_vector_init(&gt, 0, DT_REAL, _state, ae_true);
24782  ae_vector_init(&zeros, 0, DT_REAL, _state, ae_true);
24783  ae_matrix_init(&rx, 0, 0, DT_REAL, _state, ae_true);
24784  ae_matrix_init(&ry, 0, 0, DT_REAL, _state, ae_true);
24785  ae_matrix_init(&rdx, 0, 0, DT_REAL, _state, ae_true);
24786  ae_matrix_init(&rdy, 0, 0, DT_REAL, _state, ae_true);
24787 
24788  mlpproperties(network, &nin, &nout, &wcount, _state);
24789  ntotal = network->structinfo.ptr.p_int[3];
24790  istart = network->structinfo.ptr.p_int[5];
24791 
24792  /*
24793  * Prepare
24794  */
24795  ae_vector_set_length(&x, nin-1+1, _state);
24796  ae_vector_set_length(&desiredy, nout-1+1, _state);
24797  ae_vector_set_length(&zeros, wcount-1+1, _state);
24798  ae_vector_set_length(&gt, wcount-1+1, _state);
24799  ae_matrix_set_length(&rx, ntotal+nout-1+1, wcount-1+1, _state);
24800  ae_matrix_set_length(&ry, ntotal+nout-1+1, wcount-1+1, _state);
24801  ae_matrix_set_length(&rdx, ntotal+nout-1+1, wcount-1+1, _state);
24802  ae_matrix_set_length(&rdy, ntotal+nout-1+1, wcount-1+1, _state);
24803  *e = 0;
24804  for(i=0; i<=wcount-1; i++)
24805  {
24806  zeros.ptr.p_double[i] = 0;
24807  }
24808  ae_v_move(&grad->ptr.p_double[0], 1, &zeros.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
24809  for(i=0; i<=wcount-1; i++)
24810  {
24811  ae_v_move(&h->ptr.pp_double[i][0], 1, &zeros.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
24812  }
24813 
24814  /*
24815  * Process
24816  */
24817  for(k=0; k<=ssize-1; k++)
24818  {
24819 
24820  /*
24821  * Process vector with MLPGradN.
24822  * Now Neurons, DFDNET and DError contains results of the last run.
24823  */
24824  ae_v_move(&x.ptr.p_double[0], 1, &xy->ptr.pp_double[k][0], 1, ae_v_len(0,nin-1));
24825  if( mlpissoftmax(network, _state) )
24826  {
24827 
24828  /*
24829  * class labels outputs
24830  */
24831  kl = ae_round(xy->ptr.pp_double[k][nin], _state);
24832  for(i=0; i<=nout-1; i++)
24833  {
24834  if( i==kl )
24835  {
24836  desiredy.ptr.p_double[i] = 1;
24837  }
24838  else
24839  {
24840  desiredy.ptr.p_double[i] = 0;
24841  }
24842  }
24843  }
24844  else
24845  {
24846 
24847  /*
24848  * real outputs
24849  */
24850  ae_v_move(&desiredy.ptr.p_double[0], 1, &xy->ptr.pp_double[k][nin], 1, ae_v_len(0,nout-1));
24851  }
24852  if( naturalerr )
24853  {
24854  mlpgradn(network, &x, &desiredy, &et, &gt, _state);
24855  }
24856  else
24857  {
24858  mlpgrad(network, &x, &desiredy, &et, &gt, _state);
24859  }
24860 
24861  /*
24862  * grad, error
24863  */
24864  *e = *e+et;
24865  ae_v_add(&grad->ptr.p_double[0], 1, &gt.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
24866 
24867  /*
24868  * Hessian.
24869  * Forward pass of the R-algorithm
24870  */
24871  for(i=0; i<=ntotal-1; i++)
24872  {
24873  offs = istart+i*mlpbase_nfieldwidth;
24874  ae_v_move(&rx.ptr.pp_double[i][0], 1, &zeros.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
24875  ae_v_move(&ry.ptr.pp_double[i][0], 1, &zeros.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
24876  if( network->structinfo.ptr.p_int[offs+0]>0||network->structinfo.ptr.p_int[offs+0]==-5 )
24877  {
24878 
24879  /*
24880  * Activation function
24881  */
24882  n1 = network->structinfo.ptr.p_int[offs+2];
24883  ae_v_move(&rx.ptr.pp_double[i][0], 1, &ry.ptr.pp_double[n1][0], 1, ae_v_len(0,wcount-1));
24884  v = network->dfdnet.ptr.p_double[i];
24885  ae_v_moved(&ry.ptr.pp_double[i][0], 1, &rx.ptr.pp_double[i][0], 1, ae_v_len(0,wcount-1), v);
24886  continue;
24887  }
24888  if( network->structinfo.ptr.p_int[offs+0]==0 )
24889  {
24890 
24891  /*
24892  * Adaptive summator
24893  */
24894  n1 = network->structinfo.ptr.p_int[offs+2];
24895  n2 = n1+network->structinfo.ptr.p_int[offs+1]-1;
24896  w1 = network->structinfo.ptr.p_int[offs+3];
24897  w2 = w1+network->structinfo.ptr.p_int[offs+1]-1;
24898  for(j=n1; j<=n2; j++)
24899  {
24900  v = network->weights.ptr.p_double[w1+j-n1];
24901  ae_v_addd(&rx.ptr.pp_double[i][0], 1, &ry.ptr.pp_double[j][0], 1, ae_v_len(0,wcount-1), v);
24902  rx.ptr.pp_double[i][w1+j-n1] = rx.ptr.pp_double[i][w1+j-n1]+network->neurons.ptr.p_double[j];
24903  }
24904  ae_v_move(&ry.ptr.pp_double[i][0], 1, &rx.ptr.pp_double[i][0], 1, ae_v_len(0,wcount-1));
24905  continue;
24906  }
24907  if( network->structinfo.ptr.p_int[offs+0]<0 )
24908  {
24909  bflag = ae_true;
24910  if( network->structinfo.ptr.p_int[offs+0]==-2 )
24911  {
24912 
24913  /*
24914  * input neuron, left unchanged
24915  */
24916  bflag = ae_false;
24917  }
24918  if( network->structinfo.ptr.p_int[offs+0]==-3 )
24919  {
24920 
24921  /*
24922  * "-1" neuron, left unchanged
24923  */
24924  bflag = ae_false;
24925  }
24926  if( network->structinfo.ptr.p_int[offs+0]==-4 )
24927  {
24928 
24929  /*
24930  * "0" neuron, left unchanged
24931  */
24932  bflag = ae_false;
24933  }
24934  ae_assert(!bflag, "MLPHessianNBatch: internal error - unknown neuron type!", _state);
24935  continue;
24936  }
24937  }
24938 
24939  /*
24940  * Hessian. Backward pass of the R-algorithm.
24941  *
24942  * Stage 1. Initialize RDY
24943  */
24944  for(i=0; i<=ntotal+nout-1; i++)
24945  {
24946  ae_v_move(&rdy.ptr.pp_double[i][0], 1, &zeros.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
24947  }
24948  if( network->structinfo.ptr.p_int[6]==0 )
24949  {
24950 
24951  /*
24952  * Standardisation.
24953  *
24954  * In context of the Hessian calculation standardisation
24955  * is considered as additional layer with weightless
24956  * activation function:
24957  *
24958  * F(NET) := Sigma*NET
24959  *
24960  * So we add one more layer to forward pass, and
24961  * make forward/backward pass through this layer.
24962  */
24963  for(i=0; i<=nout-1; i++)
24964  {
24965  n1 = ntotal-nout+i;
24966  n2 = ntotal+i;
24967 
24968  /*
24969  * Forward pass from N1 to N2
24970  */
24971  ae_v_move(&rx.ptr.pp_double[n2][0], 1, &ry.ptr.pp_double[n1][0], 1, ae_v_len(0,wcount-1));
24972  v = network->columnsigmas.ptr.p_double[nin+i];
24973  ae_v_moved(&ry.ptr.pp_double[n2][0], 1, &rx.ptr.pp_double[n2][0], 1, ae_v_len(0,wcount-1), v);
24974 
24975  /*
24976  * Initialization of RDY
24977  */
24978  ae_v_move(&rdy.ptr.pp_double[n2][0], 1, &ry.ptr.pp_double[n2][0], 1, ae_v_len(0,wcount-1));
24979 
24980  /*
24981  * Backward pass from N2 to N1:
24982  * 1. Calculate R(dE/dX).
24983  * 2. No R(dE/dWij) is needed since weight of activation neuron
24984  * is fixed to 1. So we can update R(dE/dY) for
24985  * the connected neuron (note that Vij=0, Wij=1)
24986  */
24987  df = network->columnsigmas.ptr.p_double[nin+i];
24988  ae_v_moved(&rdx.ptr.pp_double[n2][0], 1, &rdy.ptr.pp_double[n2][0], 1, ae_v_len(0,wcount-1), df);
24989  ae_v_add(&rdy.ptr.pp_double[n1][0], 1, &rdx.ptr.pp_double[n2][0], 1, ae_v_len(0,wcount-1));
24990  }
24991  }
24992  else
24993  {
24994 
24995  /*
24996  * Softmax.
24997  *
24998  * Initialize RDY using generalized expression for ei'(yi)
24999  * (see expression (9) from p. 5 of "Fast Exact Multiplication by the Hessian").
25000  *
25001  * When we are working with softmax network, generalized
25002  * expression for ei'(yi) is used because softmax
25003  * normalization leads to ei, which depends on all y's
25004  */
25005  if( naturalerr )
25006  {
25007 
25008  /*
25009  * softmax + cross-entropy.
25010  * We have:
25011  *
25012  * S = sum(exp(yk)),
25013  * ei = sum(trn)*exp(yi)/S-trn_i
25014  *
25015  * j=i: d(ei)/d(yj) = T*exp(yi)*(S-exp(yi))/S^2
25016  * j<>i: d(ei)/d(yj) = -T*exp(yi)*exp(yj)/S^2
25017  */
25018  t = 0;
25019  for(i=0; i<=nout-1; i++)
25020  {
25021  t = t+desiredy.ptr.p_double[i];
25022  }
25023  mx = network->neurons.ptr.p_double[ntotal-nout];
25024  for(i=0; i<=nout-1; i++)
25025  {
25026  mx = ae_maxreal(mx, network->neurons.ptr.p_double[ntotal-nout+i], _state);
25027  }
25028  s = 0;
25029  for(i=0; i<=nout-1; i++)
25030  {
25031  network->nwbuf.ptr.p_double[i] = ae_exp(network->neurons.ptr.p_double[ntotal-nout+i]-mx, _state);
25032  s = s+network->nwbuf.ptr.p_double[i];
25033  }
25034  for(i=0; i<=nout-1; i++)
25035  {
25036  for(j=0; j<=nout-1; j++)
25037  {
25038  if( j==i )
25039  {
25040  deidyj = t*network->nwbuf.ptr.p_double[i]*(s-network->nwbuf.ptr.p_double[i])/ae_sqr(s, _state);
25041  ae_v_addd(&rdy.ptr.pp_double[ntotal-nout+i][0], 1, &ry.ptr.pp_double[ntotal-nout+i][0], 1, ae_v_len(0,wcount-1), deidyj);
25042  }
25043  else
25044  {
25045  deidyj = -t*network->nwbuf.ptr.p_double[i]*network->nwbuf.ptr.p_double[j]/ae_sqr(s, _state);
25046  ae_v_addd(&rdy.ptr.pp_double[ntotal-nout+i][0], 1, &ry.ptr.pp_double[ntotal-nout+j][0], 1, ae_v_len(0,wcount-1), deidyj);
25047  }
25048  }
25049  }
25050  }
25051  else
25052  {
25053 
25054  /*
25055  * For a softmax + squared error we have expression
25056  * far beyond human imagination so we don't even try
25057  * to comment on it. Just enjoy the code...
25058  *
25059  * P.S. That's why "natural error" is called "natural" -
25060  * compact beautiful expressions, fast code....
25061  */
25062  mx = network->neurons.ptr.p_double[ntotal-nout];
25063  for(i=0; i<=nout-1; i++)
25064  {
25065  mx = ae_maxreal(mx, network->neurons.ptr.p_double[ntotal-nout+i], _state);
25066  }
25067  s = 0;
25068  s2 = 0;
25069  for(i=0; i<=nout-1; i++)
25070  {
25071  network->nwbuf.ptr.p_double[i] = ae_exp(network->neurons.ptr.p_double[ntotal-nout+i]-mx, _state);
25072  s = s+network->nwbuf.ptr.p_double[i];
25073  s2 = s2+ae_sqr(network->nwbuf.ptr.p_double[i], _state);
25074  }
25075  q = 0;
25076  for(i=0; i<=nout-1; i++)
25077  {
25078  q = q+(network->y.ptr.p_double[i]-desiredy.ptr.p_double[i])*network->nwbuf.ptr.p_double[i];
25079  }
25080  for(i=0; i<=nout-1; i++)
25081  {
25082  z = -q+(network->y.ptr.p_double[i]-desiredy.ptr.p_double[i])*s;
25083  expi = network->nwbuf.ptr.p_double[i];
25084  for(j=0; j<=nout-1; j++)
25085  {
25086  expj = network->nwbuf.ptr.p_double[j];
25087  if( j==i )
25088  {
25089  deidyj = expi/ae_sqr(s, _state)*((z+expi)*(s-2*expi)/s+expi*s2/ae_sqr(s, _state));
25090  }
25091  else
25092  {
25093  deidyj = expi*expj/ae_sqr(s, _state)*(s2/ae_sqr(s, _state)-2*z/s-(expi+expj)/s+(network->y.ptr.p_double[i]-desiredy.ptr.p_double[i])-(network->y.ptr.p_double[j]-desiredy.ptr.p_double[j]));
25094  }
25095  ae_v_addd(&rdy.ptr.pp_double[ntotal-nout+i][0], 1, &ry.ptr.pp_double[ntotal-nout+j][0], 1, ae_v_len(0,wcount-1), deidyj);
25096  }
25097  }
25098  }
25099  }
25100 
25101  /*
25102  * Hessian. Backward pass of the R-algorithm
25103  *
25104  * Stage 2. Process.
25105  */
25106  for(i=ntotal-1; i>=0; i--)
25107  {
25108 
25109  /*
25110  * Possible variants:
25111  * 1. Activation function
25112  * 2. Adaptive summator
25113  * 3. Special neuron
25114  */
25115  offs = istart+i*mlpbase_nfieldwidth;
25116  if( network->structinfo.ptr.p_int[offs+0]>0||network->structinfo.ptr.p_int[offs+0]==-5 )
25117  {
25118  n1 = network->structinfo.ptr.p_int[offs+2];
25119 
25120  /*
25121  * First, calculate R(dE/dX).
25122  */
25123  mlpactivationfunction(network->neurons.ptr.p_double[n1], network->structinfo.ptr.p_int[offs+0], &f, &df, &d2f, _state);
25124  v = d2f*network->derror.ptr.p_double[i];
25125  ae_v_moved(&rdx.ptr.pp_double[i][0], 1, &rdy.ptr.pp_double[i][0], 1, ae_v_len(0,wcount-1), df);
25126  ae_v_addd(&rdx.ptr.pp_double[i][0], 1, &rx.ptr.pp_double[i][0], 1, ae_v_len(0,wcount-1), v);
25127 
25128  /*
25129  * No R(dE/dWij) is needed since weight of activation neuron
25130  * is fixed to 1.
25131  *
25132  * So we can update R(dE/dY) for the connected neuron.
25133  * (note that Vij=0, Wij=1)
25134  */
25135  ae_v_add(&rdy.ptr.pp_double[n1][0], 1, &rdx.ptr.pp_double[i][0], 1, ae_v_len(0,wcount-1));
25136  continue;
25137  }
25138  if( network->structinfo.ptr.p_int[offs+0]==0 )
25139  {
25140 
25141  /*
25142  * Adaptive summator
25143  */
25144  n1 = network->structinfo.ptr.p_int[offs+2];
25145  n2 = n1+network->structinfo.ptr.p_int[offs+1]-1;
25146  w1 = network->structinfo.ptr.p_int[offs+3];
25147  w2 = w1+network->structinfo.ptr.p_int[offs+1]-1;
25148 
25149  /*
25150  * First, calculate R(dE/dX).
25151  */
25152  ae_v_move(&rdx.ptr.pp_double[i][0], 1, &rdy.ptr.pp_double[i][0], 1, ae_v_len(0,wcount-1));
25153 
25154  /*
25155  * Then, calculate R(dE/dWij)
25156  */
25157  for(j=w1; j<=w2; j++)
25158  {
25159  v = network->neurons.ptr.p_double[n1+j-w1];
25160  ae_v_addd(&h->ptr.pp_double[j][0], 1, &rdx.ptr.pp_double[i][0], 1, ae_v_len(0,wcount-1), v);
25161  v = network->derror.ptr.p_double[i];
25162  ae_v_addd(&h->ptr.pp_double[j][0], 1, &ry.ptr.pp_double[n1+j-w1][0], 1, ae_v_len(0,wcount-1), v);
25163  }
25164 
25165  /*
25166  * And finally, update R(dE/dY) for connected neurons.
25167  */
25168  for(j=w1; j<=w2; j++)
25169  {
25170  v = network->weights.ptr.p_double[j];
25171  ae_v_addd(&rdy.ptr.pp_double[n1+j-w1][0], 1, &rdx.ptr.pp_double[i][0], 1, ae_v_len(0,wcount-1), v);
25172  rdy.ptr.pp_double[n1+j-w1][j] = rdy.ptr.pp_double[n1+j-w1][j]+network->derror.ptr.p_double[i];
25173  }
25174  continue;
25175  }
25176  if( network->structinfo.ptr.p_int[offs+0]<0 )
25177  {
25178  bflag = ae_false;
25179  if( (network->structinfo.ptr.p_int[offs+0]==-2||network->structinfo.ptr.p_int[offs+0]==-3)||network->structinfo.ptr.p_int[offs+0]==-4 )
25180  {
25181 
25182  /*
25183  * Special neuron type, no back-propagation required
25184  */
25185  bflag = ae_true;
25186  }
25187  ae_assert(bflag, "MLPHessianNBatch: unknown neuron type!", _state);
25188  continue;
25189  }
25190  }
25191  }
25192  ae_frame_leave(_state);
25193 }
25194 
25195 
25196 /*************************************************************************
25197 Internal subroutine
25198 
25199 Network must be processed by MLPProcess on X
25200 *************************************************************************/
25201 static void mlpbase_mlpinternalcalculategradient(multilayerperceptron* network,
25202  /* Real */ ae_vector* neurons,
25203  /* Real */ ae_vector* weights,
25204  /* Real */ ae_vector* derror,
25205  /* Real */ ae_vector* grad,
25206  ae_bool naturalerrorfunc,
25207  ae_state *_state)
25208 {
25209  ae_int_t i;
25210  ae_int_t n1;
25211  ae_int_t n2;
25212  ae_int_t w1;
25213  ae_int_t w2;
25214  ae_int_t ntotal;
25215  ae_int_t istart;
25216  ae_int_t nin;
25217  ae_int_t nout;
25218  ae_int_t offs;
25219  double dedf;
25220  double dfdnet;
25221  double v;
25222  double fown;
25223  double deown;
25224  double net;
25225  double mx;
25226  ae_bool bflag;
25227 
25228 
25229 
25230  /*
25231  * Read network geometry
25232  */
25233  nin = network->structinfo.ptr.p_int[1];
25234  nout = network->structinfo.ptr.p_int[2];
25235  ntotal = network->structinfo.ptr.p_int[3];
25236  istart = network->structinfo.ptr.p_int[5];
25237 
25238  /*
25239  * Pre-processing of dError/dOut:
25240  * from dError/dOut(normalized) to dError/dOut(non-normalized)
25241  */
25242  ae_assert(network->structinfo.ptr.p_int[6]==0||network->structinfo.ptr.p_int[6]==1, "MLPInternalCalculateGradient: unknown normalization type!", _state);
25243  if( network->structinfo.ptr.p_int[6]==1 )
25244  {
25245 
25246  /*
25247  * Softmax
25248  */
25249  if( !naturalerrorfunc )
25250  {
25251  mx = network->neurons.ptr.p_double[ntotal-nout];
25252  for(i=0; i<=nout-1; i++)
25253  {
25254  mx = ae_maxreal(mx, network->neurons.ptr.p_double[ntotal-nout+i], _state);
25255  }
25256  net = 0;
25257  for(i=0; i<=nout-1; i++)
25258  {
25259  network->nwbuf.ptr.p_double[i] = ae_exp(network->neurons.ptr.p_double[ntotal-nout+i]-mx, _state);
25260  net = net+network->nwbuf.ptr.p_double[i];
25261  }
25262  v = ae_v_dotproduct(&network->derror.ptr.p_double[ntotal-nout], 1, &network->nwbuf.ptr.p_double[0], 1, ae_v_len(ntotal-nout,ntotal-1));
25263  for(i=0; i<=nout-1; i++)
25264  {
25265  fown = network->nwbuf.ptr.p_double[i];
25266  deown = network->derror.ptr.p_double[ntotal-nout+i];
25267  network->nwbuf.ptr.p_double[nout+i] = (-v+deown*fown+deown*(net-fown))*fown/ae_sqr(net, _state);
25268  }
25269  for(i=0; i<=nout-1; i++)
25270  {
25271  network->derror.ptr.p_double[ntotal-nout+i] = network->nwbuf.ptr.p_double[nout+i];
25272  }
25273  }
25274  }
25275  else
25276  {
25277 
25278  /*
25279  * Un-standardisation
25280  */
25281  for(i=0; i<=nout-1; i++)
25282  {
25283  network->derror.ptr.p_double[ntotal-nout+i] = network->derror.ptr.p_double[ntotal-nout+i]*network->columnsigmas.ptr.p_double[nin+i];
25284  }
25285  }
25286 
25287  /*
25288  * Backpropagation
25289  */
25290  for(i=ntotal-1; i>=0; i--)
25291  {
25292 
25293  /*
25294  * Extract info
25295  */
25296  offs = istart+i*mlpbase_nfieldwidth;
25297  if( network->structinfo.ptr.p_int[offs+0]>0||network->structinfo.ptr.p_int[offs+0]==-5 )
25298  {
25299 
25300  /*
25301  * Activation function
25302  */
25303  dedf = network->derror.ptr.p_double[i];
25304  dfdnet = network->dfdnet.ptr.p_double[i];
25305  derror->ptr.p_double[network->structinfo.ptr.p_int[offs+2]] = derror->ptr.p_double[network->structinfo.ptr.p_int[offs+2]]+dedf*dfdnet;
25306  continue;
25307  }
25308  if( network->structinfo.ptr.p_int[offs+0]==0 )
25309  {
25310 
25311  /*
25312  * Adaptive summator
25313  */
25314  n1 = network->structinfo.ptr.p_int[offs+2];
25315  n2 = n1+network->structinfo.ptr.p_int[offs+1]-1;
25316  w1 = network->structinfo.ptr.p_int[offs+3];
25317  w2 = w1+network->structinfo.ptr.p_int[offs+1]-1;
25318  dedf = network->derror.ptr.p_double[i];
25319  dfdnet = 1.0;
25320  v = dedf*dfdnet;
25321  ae_v_moved(&grad->ptr.p_double[w1], 1, &neurons->ptr.p_double[n1], 1, ae_v_len(w1,w2), v);
25322  ae_v_addd(&derror->ptr.p_double[n1], 1, &weights->ptr.p_double[w1], 1, ae_v_len(n1,n2), v);
25323  continue;
25324  }
25325  if( network->structinfo.ptr.p_int[offs+0]<0 )
25326  {
25327  bflag = ae_false;
25328  if( (network->structinfo.ptr.p_int[offs+0]==-2||network->structinfo.ptr.p_int[offs+0]==-3)||network->structinfo.ptr.p_int[offs+0]==-4 )
25329  {
25330 
25331  /*
25332  * Special neuron type, no back-propagation required
25333  */
25334  bflag = ae_true;
25335  }
25336  ae_assert(bflag, "MLPInternalCalculateGradient: unknown neuron type!", _state);
25337  continue;
25338  }
25339  }
25340 }
25341 
25342 
25343 static void mlpbase_mlpchunkedgradient(multilayerperceptron* network,
25344  /* Real */ ae_matrix* xy,
25345  ae_int_t cstart,
25346  ae_int_t csize,
25347  /* Real */ ae_vector* batch4buf,
25348  /* Real */ ae_vector* hpcbuf,
25349  double* e,
25350  ae_bool naturalerrorfunc,
25351  ae_state *_state)
25352 {
25353  ae_int_t i;
25354  ae_int_t j;
25355  ae_int_t k;
25356  ae_int_t kl;
25357  ae_int_t ntotal;
25358  ae_int_t nin;
25359  ae_int_t nout;
25360  ae_int_t offs;
25361  double f;
25362  double df;
25363  double d2f;
25364  double v;
25365  double vv;
25366  double s;
25367  double fown;
25368  double deown;
25369  ae_bool bflag;
25370  ae_int_t istart;
25371  ae_int_t entrysize;
25372  ae_int_t dfoffs;
25373  ae_int_t derroroffs;
25374  ae_int_t entryoffs;
25375  ae_int_t neuronidx;
25376  ae_int_t srcentryoffs;
25377  ae_int_t srcneuronidx;
25378  ae_int_t srcweightidx;
25379  ae_int_t neurontype;
25380  ae_int_t nweights;
25381  ae_int_t offs0;
25382  ae_int_t offs1;
25383  ae_int_t offs2;
25384  double v0;
25385  double v1;
25386  double v2;
25387  double v3;
25388  double s0;
25389  double s1;
25390  double s2;
25391  double s3;
25392  ae_int_t chunksize;
25393 
25394 
25395  chunksize = 4;
25396  ae_assert(csize<=chunksize, "MLPChunkedGradient: internal error (CSize>ChunkSize)", _state);
25397 
25398  /*
25399  * Try to use HPC core, if possible
25400  */
25401  if( hpcchunkedgradient(&network->weights, &network->structinfo, &network->columnmeans, &network->columnsigmas, xy, cstart, csize, batch4buf, hpcbuf, e, naturalerrorfunc, _state) )
25402  {
25403  return;
25404  }
25405 
25406  /*
25407  * Read network geometry, prepare data
25408  */
25409  nin = network->structinfo.ptr.p_int[1];
25410  nout = network->structinfo.ptr.p_int[2];
25411  ntotal = network->structinfo.ptr.p_int[3];
25412  istart = network->structinfo.ptr.p_int[5];
25413  entrysize = 12;
25414  dfoffs = 4;
25415  derroroffs = 8;
25416 
25417  /*
25418  * Fill Batch4Buf by zeros.
25419  *
25420  * THIS STAGE IS VERY IMPORTANT!
25421  *
25422  * We fill all components of entry - neuron values, dF/dNET, dError/dF.
25423  * It allows us to easily handle situations when CSize<ChunkSize by
25424  * simply working with ALL components of Batch4Buf, without ever
25425  * looking at CSize. The idea is that dError/dF for absent components
25426  * will be initialized by zeros - and won't be rewritten by non-zero
25427  * values during backpropagation.
25428  */
25429  for(i=0; i<=entrysize*ntotal-1; i++)
25430  {
25431  batch4buf->ptr.p_double[i] = 0;
25432  }
25433 
25434  /*
25435  * Forward pass:
25436  * 1. Load data into Batch4Buf. If CSize<ChunkSize, data are padded by zeros.
25437  * 2. Perform forward pass through network
25438  */
25439  for(i=0; i<=nin-1; i++)
25440  {
25441  entryoffs = entrysize*i;
25442  for(j=0; j<=csize-1; j++)
25443  {
25444  if( ae_fp_neq(network->columnsigmas.ptr.p_double[i],0) )
25445  {
25446  batch4buf->ptr.p_double[entryoffs+j] = (xy->ptr.pp_double[cstart+j][i]-network->columnmeans.ptr.p_double[i])/network->columnsigmas.ptr.p_double[i];
25447  }
25448  else
25449  {
25450  batch4buf->ptr.p_double[entryoffs+j] = xy->ptr.pp_double[cstart+j][i]-network->columnmeans.ptr.p_double[i];
25451  }
25452  }
25453  }
25454  for(neuronidx=0; neuronidx<=ntotal-1; neuronidx++)
25455  {
25456  entryoffs = entrysize*neuronidx;
25457  offs = istart+neuronidx*mlpbase_nfieldwidth;
25458  neurontype = network->structinfo.ptr.p_int[offs+0];
25459  if( neurontype>0||neurontype==-5 )
25460  {
25461 
25462  /*
25463  * "activation function" neuron, which takes value of neuron SrcNeuronIdx
25464  * and applies activation function to it.
25465  *
25466  * This neuron has no weights and no tunable parameters.
25467  */
25468  srcneuronidx = network->structinfo.ptr.p_int[offs+2];
25469  srcentryoffs = entrysize*srcneuronidx;
25470  mlpactivationfunction(batch4buf->ptr.p_double[srcentryoffs+0], neurontype, &f, &df, &d2f, _state);
25471  batch4buf->ptr.p_double[entryoffs+0] = f;
25472  batch4buf->ptr.p_double[entryoffs+0+dfoffs] = df;
25473  mlpactivationfunction(batch4buf->ptr.p_double[srcentryoffs+1], neurontype, &f, &df, &d2f, _state);
25474  batch4buf->ptr.p_double[entryoffs+1] = f;
25475  batch4buf->ptr.p_double[entryoffs+1+dfoffs] = df;
25476  mlpactivationfunction(batch4buf->ptr.p_double[srcentryoffs+2], neurontype, &f, &df, &d2f, _state);
25477  batch4buf->ptr.p_double[entryoffs+2] = f;
25478  batch4buf->ptr.p_double[entryoffs+2+dfoffs] = df;
25479  mlpactivationfunction(batch4buf->ptr.p_double[srcentryoffs+3], neurontype, &f, &df, &d2f, _state);
25480  batch4buf->ptr.p_double[entryoffs+3] = f;
25481  batch4buf->ptr.p_double[entryoffs+3+dfoffs] = df;
25482  continue;
25483  }
25484  if( neurontype==0 )
25485  {
25486 
25487  /*
25488  * "adaptive summator" neuron, whose output is a weighted sum of inputs.
25489  * It has weights, but has no activation function.
25490  */
25491  nweights = network->structinfo.ptr.p_int[offs+1];
25492  srcneuronidx = network->structinfo.ptr.p_int[offs+2];
25493  srcentryoffs = entrysize*srcneuronidx;
25494  srcweightidx = network->structinfo.ptr.p_int[offs+3];
25495  v0 = 0;
25496  v1 = 0;
25497  v2 = 0;
25498  v3 = 0;
25499  for(j=0; j<=nweights-1; j++)
25500  {
25501  v = network->weights.ptr.p_double[srcweightidx];
25502  srcweightidx = srcweightidx+1;
25503  v0 = v0+v*batch4buf->ptr.p_double[srcentryoffs+0];
25504  v1 = v1+v*batch4buf->ptr.p_double[srcentryoffs+1];
25505  v2 = v2+v*batch4buf->ptr.p_double[srcentryoffs+2];
25506  v3 = v3+v*batch4buf->ptr.p_double[srcentryoffs+3];
25507  srcentryoffs = srcentryoffs+entrysize;
25508  }
25509  batch4buf->ptr.p_double[entryoffs+0] = v0;
25510  batch4buf->ptr.p_double[entryoffs+1] = v1;
25511  batch4buf->ptr.p_double[entryoffs+2] = v2;
25512  batch4buf->ptr.p_double[entryoffs+3] = v3;
25513  batch4buf->ptr.p_double[entryoffs+0+dfoffs] = 1;
25514  batch4buf->ptr.p_double[entryoffs+1+dfoffs] = 1;
25515  batch4buf->ptr.p_double[entryoffs+2+dfoffs] = 1;
25516  batch4buf->ptr.p_double[entryoffs+3+dfoffs] = 1;
25517  continue;
25518  }
25519  if( neurontype<0 )
25520  {
25521  bflag = ae_false;
25522  if( neurontype==-2 )
25523  {
25524 
25525  /*
25526  * Input neuron, left unchanged
25527  */
25528  bflag = ae_true;
25529  }
25530  if( neurontype==-3 )
25531  {
25532 
25533  /*
25534  * "-1" neuron
25535  */
25536  batch4buf->ptr.p_double[entryoffs+0] = -1;
25537  batch4buf->ptr.p_double[entryoffs+1] = -1;
25538  batch4buf->ptr.p_double[entryoffs+2] = -1;
25539  batch4buf->ptr.p_double[entryoffs+3] = -1;
25540  batch4buf->ptr.p_double[entryoffs+0+dfoffs] = 0;
25541  batch4buf->ptr.p_double[entryoffs+1+dfoffs] = 0;
25542  batch4buf->ptr.p_double[entryoffs+2+dfoffs] = 0;
25543  batch4buf->ptr.p_double[entryoffs+3+dfoffs] = 0;
25544  bflag = ae_true;
25545  }
25546  if( neurontype==-4 )
25547  {
25548 
25549  /*
25550  * "0" neuron
25551  */
25552  batch4buf->ptr.p_double[entryoffs+0] = 0;
25553  batch4buf->ptr.p_double[entryoffs+1] = 0;
25554  batch4buf->ptr.p_double[entryoffs+2] = 0;
25555  batch4buf->ptr.p_double[entryoffs+3] = 0;
25556  batch4buf->ptr.p_double[entryoffs+0+dfoffs] = 0;
25557  batch4buf->ptr.p_double[entryoffs+1+dfoffs] = 0;
25558  batch4buf->ptr.p_double[entryoffs+2+dfoffs] = 0;
25559  batch4buf->ptr.p_double[entryoffs+3+dfoffs] = 0;
25560  bflag = ae_true;
25561  }
25562  ae_assert(bflag, "MLPChunkedGradient: internal error - unknown neuron type!", _state);
25563  continue;
25564  }
25565  }
25566 
25567  /*
25568  * Intermediate phase between forward and backward passes.
25569  *
25570  * For regression networks:
25571  * * forward pass is completely done (no additional post-processing is
25572  * needed).
25573  * * before starting backward pass, we have to calculate dError/dOut
25574  * for output neurons. We also update error at this phase.
25575  *
25576  * For classification networks:
25577  * * in addition to forward pass we apply SOFTMAX normalization to
25578  * output neurons.
25579  * * after applying normalization, we have to calculate dError/dOut,
25580  * which is calculated in two steps:
25581  * * first, we calculate derivative of error with respect to SOFTMAX
25582  * normalized outputs (normalized dError)
25583  * * then, we calculate derivative of error with respect to values
25584  * of outputs BEFORE normalization was applied to them
25585  */
25586  ae_assert(network->structinfo.ptr.p_int[6]==0||network->structinfo.ptr.p_int[6]==1, "MLPChunkedGradient: unknown normalization type!", _state);
25587  if( network->structinfo.ptr.p_int[6]==1 )
25588  {
25589 
25590  /*
25591  * SOFTMAX-normalized network.
25592  *
25593  * First, calculate (V0,V1,V2,V3) - component-wise maximum
25594  * of output neurons. This vector of maximum values will be
25595  * used for normalization of outputs prior to calculating
25596  * exponentials.
25597  *
25598  * NOTE: the only purpose of this stage is to prevent overflow
25599  * during calculation of exponentials. With this stage
25600  * we make sure that all exponentials are calculated
25601  * with non-positive argument. If you load (0,0,0,0) to
25602  * (V0,V1,V2,V3), your program will continue working -
25603  * although with less robustness.
25604  */
25605  entryoffs = entrysize*(ntotal-nout);
25606  v0 = batch4buf->ptr.p_double[entryoffs+0];
25607  v1 = batch4buf->ptr.p_double[entryoffs+1];
25608  v2 = batch4buf->ptr.p_double[entryoffs+2];
25609  v3 = batch4buf->ptr.p_double[entryoffs+3];
25610  entryoffs = entryoffs+entrysize;
25611  for(i=1; i<=nout-1; i++)
25612  {
25613  v = batch4buf->ptr.p_double[entryoffs+0];
25614  if( v>v0 )
25615  {
25616  v0 = v;
25617  }
25618  v = batch4buf->ptr.p_double[entryoffs+1];
25619  if( v>v1 )
25620  {
25621  v1 = v;
25622  }
25623  v = batch4buf->ptr.p_double[entryoffs+2];
25624  if( v>v2 )
25625  {
25626  v2 = v;
25627  }
25628  v = batch4buf->ptr.p_double[entryoffs+3];
25629  if( v>v3 )
25630  {
25631  v3 = v;
25632  }
25633  entryoffs = entryoffs+entrysize;
25634  }
25635 
25636  /*
25637  * Then, calculate exponentials and place them to part of the
25638  * array which is located past the last entry. We also
25639  * calculate sum of exponentials which will be stored past the
25640  * exponentials.
25641  */
25642  entryoffs = entrysize*(ntotal-nout);
25643  offs0 = entrysize*ntotal;
25644  s0 = 0;
25645  s1 = 0;
25646  s2 = 0;
25647  s3 = 0;
25648  for(i=0; i<=nout-1; i++)
25649  {
25650  v = ae_exp(batch4buf->ptr.p_double[entryoffs+0]-v0, _state);
25651  s0 = s0+v;
25652  batch4buf->ptr.p_double[offs0+0] = v;
25653  v = ae_exp(batch4buf->ptr.p_double[entryoffs+1]-v1, _state);
25654  s1 = s1+v;
25655  batch4buf->ptr.p_double[offs0+1] = v;
25656  v = ae_exp(batch4buf->ptr.p_double[entryoffs+2]-v2, _state);
25657  s2 = s2+v;
25658  batch4buf->ptr.p_double[offs0+2] = v;
25659  v = ae_exp(batch4buf->ptr.p_double[entryoffs+3]-v3, _state);
25660  s3 = s3+v;
25661  batch4buf->ptr.p_double[offs0+3] = v;
25662  entryoffs = entryoffs+entrysize;
25663  offs0 = offs0+chunksize;
25664  }
25665  offs0 = entrysize*ntotal+2*nout*chunksize;
25666  batch4buf->ptr.p_double[offs0+0] = s0;
25667  batch4buf->ptr.p_double[offs0+1] = s1;
25668  batch4buf->ptr.p_double[offs0+2] = s2;
25669  batch4buf->ptr.p_double[offs0+3] = s3;
25670 
25671  /*
25672  * Now we have:
25673  * * Batch4Buf[0...EntrySize*NTotal-1] stores:
25674  * * NTotal*ChunkSize neuron output values (SOFTMAX normalization
25675  * was not applied to these values),
25676  * * NTotal*ChunkSize values of dF/dNET (derivative of neuron
25677  * output with respect to its input)
25678  * * NTotal*ChunkSize zeros in the elements which correspond to
25679  * dError/dOut (derivative of error with respect to neuron output).
25680  * * Batch4Buf[EntrySize*NTotal...EntrySize*NTotal+ChunkSize*NOut-1] -
25681  * stores exponentials of last NOut neurons.
25682  * * Batch4Buf[EntrySize*NTotal+ChunkSize*NOut-1...EntrySize*NTotal+ChunkSize*2*NOut-1]
25683  * - can be used for temporary calculations
25684  * * Batch4Buf[EntrySize*NTotal+ChunkSize*2*NOut...EntrySize*NTotal+ChunkSize*2*NOut+ChunkSize-1]
25685  * - stores sum-of-exponentials
25686  *
25687  * Block below calculates derivatives of error function with respect
25688  * to non-SOFTMAX-normalized output values of last NOut neurons.
25689  *
25690  * It is quite complicated; we do not describe algebra behind it,
25691  * but if you want you may check it yourself :)
25692  */
25693  if( naturalerrorfunc )
25694  {
25695 
25696  /*
25697  * Calculate derivative of error with respect to values of
25698  * output neurons PRIOR TO SOFTMAX NORMALIZATION. Because we
25699  * use natural error function (cross-entropy), we can do so
25700  * very easy.
25701  */
25702  offs0 = entrysize*ntotal+2*nout*chunksize;
25703  for(k=0; k<=csize-1; k++)
25704  {
25705  s = batch4buf->ptr.p_double[offs0+k];
25706  kl = ae_round(xy->ptr.pp_double[cstart+k][nin], _state);
25707  offs1 = (ntotal-nout)*entrysize+derroroffs+k;
25708  offs2 = entrysize*ntotal+k;
25709  for(i=0; i<=nout-1; i++)
25710  {
25711  if( i==kl )
25712  {
25713  v = 1;
25714  }
25715  else
25716  {
25717  v = 0;
25718  }
25719  vv = batch4buf->ptr.p_double[offs2];
25720  batch4buf->ptr.p_double[offs1] = vv/s-v;
25721  *e = *e+mlpbase_safecrossentropy(v, vv/s, _state);
25722  offs1 = offs1+entrysize;
25723  offs2 = offs2+chunksize;
25724  }
25725  }
25726  }
25727  else
25728  {
25729 
25730  /*
25731  * SOFTMAX normalization makes things very difficult.
25732  * Sorry, we do not dare to describe this esoteric math
25733  * in details.
25734  */
25735  offs0 = entrysize*ntotal+chunksize*2*nout;
25736  for(k=0; k<=csize-1; k++)
25737  {
25738  s = batch4buf->ptr.p_double[offs0+k];
25739  kl = ae_round(xy->ptr.pp_double[cstart+k][nin], _state);
25740  vv = 0;
25741  offs1 = entrysize*ntotal+k;
25742  offs2 = entrysize*ntotal+nout*chunksize+k;
25743  for(i=0; i<=nout-1; i++)
25744  {
25745  fown = batch4buf->ptr.p_double[offs1];
25746  if( i==kl )
25747  {
25748  deown = fown/s-1;
25749  }
25750  else
25751  {
25752  deown = fown/s;
25753  }
25754  batch4buf->ptr.p_double[offs2] = deown;
25755  vv = vv+deown*fown;
25756  *e = *e+deown*deown/2;
25757  offs1 = offs1+chunksize;
25758  offs2 = offs2+chunksize;
25759  }
25760  offs1 = entrysize*ntotal+k;
25761  offs2 = entrysize*ntotal+nout*chunksize+k;
25762  for(i=0; i<=nout-1; i++)
25763  {
25764  fown = batch4buf->ptr.p_double[offs1];
25765  deown = batch4buf->ptr.p_double[offs2];
25766  batch4buf->ptr.p_double[(ntotal-nout+i)*entrysize+derroroffs+k] = (-vv+deown*fown+deown*(s-fown))*fown/ae_sqr(s, _state);
25767  offs1 = offs1+chunksize;
25768  offs2 = offs2+chunksize;
25769  }
25770  }
25771  }
25772  }
25773  else
25774  {
25775 
25776  /*
25777  * Regression network with sum-of-squares function.
25778  *
25779  * For each NOut of last neurons:
25780  * * calculate difference between actual and desired output
25781  * * calculate dError/dOut for this neuron (proportional to difference)
25782  * * store in in last 4 components of entry (these values are used
25783  * to start backpropagation)
25784  * * update error
25785  */
25786  for(i=0; i<=nout-1; i++)
25787  {
25788  v0 = network->columnsigmas.ptr.p_double[nin+i];
25789  v1 = network->columnmeans.ptr.p_double[nin+i];
25790  entryoffs = entrysize*(ntotal-nout+i);
25791  offs0 = entryoffs;
25792  offs1 = entryoffs+derroroffs;
25793  for(j=0; j<=csize-1; j++)
25794  {
25795  v = batch4buf->ptr.p_double[offs0+j]*v0+v1-xy->ptr.pp_double[cstart+j][nin+i];
25796  batch4buf->ptr.p_double[offs1+j] = v*v0;
25797  *e = *e+v*v/2;
25798  }
25799  }
25800  }
25801 
25802  /*
25803  * Backpropagation
25804  */
25805  for(neuronidx=ntotal-1; neuronidx>=0; neuronidx--)
25806  {
25807  entryoffs = entrysize*neuronidx;
25808  offs = istart+neuronidx*mlpbase_nfieldwidth;
25809  neurontype = network->structinfo.ptr.p_int[offs+0];
25810  if( neurontype>0||neurontype==-5 )
25811  {
25812 
25813  /*
25814  * Activation function
25815  */
25816  srcneuronidx = network->structinfo.ptr.p_int[offs+2];
25817  srcentryoffs = entrysize*srcneuronidx;
25818  offs0 = srcentryoffs+derroroffs;
25819  offs1 = entryoffs+derroroffs;
25820  offs2 = entryoffs+dfoffs;
25821  batch4buf->ptr.p_double[offs0+0] = batch4buf->ptr.p_double[offs0+0]+batch4buf->ptr.p_double[offs1+0]*batch4buf->ptr.p_double[offs2+0];
25822  batch4buf->ptr.p_double[offs0+1] = batch4buf->ptr.p_double[offs0+1]+batch4buf->ptr.p_double[offs1+1]*batch4buf->ptr.p_double[offs2+1];
25823  batch4buf->ptr.p_double[offs0+2] = batch4buf->ptr.p_double[offs0+2]+batch4buf->ptr.p_double[offs1+2]*batch4buf->ptr.p_double[offs2+2];
25824  batch4buf->ptr.p_double[offs0+3] = batch4buf->ptr.p_double[offs0+3]+batch4buf->ptr.p_double[offs1+3]*batch4buf->ptr.p_double[offs2+3];
25825  continue;
25826  }
25827  if( neurontype==0 )
25828  {
25829 
25830  /*
25831  * Adaptive summator
25832  */
25833  nweights = network->structinfo.ptr.p_int[offs+1];
25834  srcneuronidx = network->structinfo.ptr.p_int[offs+2];
25835  srcentryoffs = entrysize*srcneuronidx;
25836  srcweightidx = network->structinfo.ptr.p_int[offs+3];
25837  v0 = batch4buf->ptr.p_double[entryoffs+derroroffs+0];
25838  v1 = batch4buf->ptr.p_double[entryoffs+derroroffs+1];
25839  v2 = batch4buf->ptr.p_double[entryoffs+derroroffs+2];
25840  v3 = batch4buf->ptr.p_double[entryoffs+derroroffs+3];
25841  for(j=0; j<=nweights-1; j++)
25842  {
25843  offs0 = srcentryoffs;
25844  offs1 = srcentryoffs+derroroffs;
25845  v = network->weights.ptr.p_double[srcweightidx];
25846  hpcbuf->ptr.p_double[srcweightidx] = hpcbuf->ptr.p_double[srcweightidx]+batch4buf->ptr.p_double[offs0+0]*v0+batch4buf->ptr.p_double[offs0+1]*v1+batch4buf->ptr.p_double[offs0+2]*v2+batch4buf->ptr.p_double[offs0+3]*v3;
25847  batch4buf->ptr.p_double[offs1+0] = batch4buf->ptr.p_double[offs1+0]+v*v0;
25848  batch4buf->ptr.p_double[offs1+1] = batch4buf->ptr.p_double[offs1+1]+v*v1;
25849  batch4buf->ptr.p_double[offs1+2] = batch4buf->ptr.p_double[offs1+2]+v*v2;
25850  batch4buf->ptr.p_double[offs1+3] = batch4buf->ptr.p_double[offs1+3]+v*v3;
25851  srcentryoffs = srcentryoffs+entrysize;
25852  srcweightidx = srcweightidx+1;
25853  }
25854  continue;
25855  }
25856  if( neurontype<0 )
25857  {
25858  bflag = ae_false;
25859  if( (neurontype==-2||neurontype==-3)||neurontype==-4 )
25860  {
25861 
25862  /*
25863  * Special neuron type, no back-propagation required
25864  */
25865  bflag = ae_true;
25866  }
25867  ae_assert(bflag, "MLPInternalCalculateGradient: unknown neuron type!", _state);
25868  continue;
25869  }
25870  }
25871 }
25872 
25873 
25874 static void mlpbase_mlpchunkedprocess(multilayerperceptron* network,
25875  /* Real */ ae_matrix* xy,
25876  ae_int_t cstart,
25877  ae_int_t csize,
25878  /* Real */ ae_vector* batch4buf,
25879  /* Real */ ae_vector* hpcbuf,
25880  ae_state *_state)
25881 {
25882  ae_int_t i;
25883  ae_int_t j;
25884  ae_int_t ntotal;
25885  ae_int_t nin;
25886  ae_int_t nout;
25887  ae_int_t offs;
25888  double f;
25889  double df;
25890  double d2f;
25891  double v;
25892  ae_bool bflag;
25893  ae_int_t istart;
25894  ae_int_t entrysize;
25895  ae_int_t entryoffs;
25896  ae_int_t neuronidx;
25897  ae_int_t srcentryoffs;
25898  ae_int_t srcneuronidx;
25899  ae_int_t srcweightidx;
25900  ae_int_t neurontype;
25901  ae_int_t nweights;
25902  ae_int_t offs0;
25903  double v0;
25904  double v1;
25905  double v2;
25906  double v3;
25907  double s0;
25908  double s1;
25909  double s2;
25910  double s3;
25911  ae_int_t chunksize;
25912 
25913 
25914  chunksize = 4;
25915  ae_assert(csize<=chunksize, "MLPChunkedProcess: internal error (CSize>ChunkSize)", _state);
25916 
25917  /*
25918  * Try to use HPC core, if possible
25919  */
25920  if( hpcchunkedprocess(&network->weights, &network->structinfo, &network->columnmeans, &network->columnsigmas, xy, cstart, csize, batch4buf, hpcbuf, _state) )
25921  {
25922  return;
25923  }
25924 
25925  /*
25926  * Read network geometry, prepare data
25927  */
25928  nin = network->structinfo.ptr.p_int[1];
25929  nout = network->structinfo.ptr.p_int[2];
25930  ntotal = network->structinfo.ptr.p_int[3];
25931  istart = network->structinfo.ptr.p_int[5];
25932  entrysize = 4;
25933 
25934  /*
25935  * Fill Batch4Buf by zeros.
25936  *
25937  * THIS STAGE IS VERY IMPORTANT!
25938  *
25939  * We fill all components of entry - neuron values, dF/dNET, dError/dF.
25940  * It allows us to easily handle situations when CSize<ChunkSize by
25941  * simply working with ALL components of Batch4Buf, without ever
25942  * looking at CSize.
25943  */
25944  for(i=0; i<=entrysize*ntotal-1; i++)
25945  {
25946  batch4buf->ptr.p_double[i] = 0;
25947  }
25948 
25949  /*
25950  * Forward pass:
25951  * 1. Load data into Batch4Buf. If CSize<ChunkSize, data are padded by zeros.
25952  * 2. Perform forward pass through network
25953  */
25954  for(i=0; i<=nin-1; i++)
25955  {
25956  entryoffs = entrysize*i;
25957  for(j=0; j<=csize-1; j++)
25958  {
25959  if( ae_fp_neq(network->columnsigmas.ptr.p_double[i],0) )
25960  {
25961  batch4buf->ptr.p_double[entryoffs+j] = (xy->ptr.pp_double[cstart+j][i]-network->columnmeans.ptr.p_double[i])/network->columnsigmas.ptr.p_double[i];
25962  }
25963  else
25964  {
25965  batch4buf->ptr.p_double[entryoffs+j] = xy->ptr.pp_double[cstart+j][i]-network->columnmeans.ptr.p_double[i];
25966  }
25967  }
25968  }
25969  for(neuronidx=0; neuronidx<=ntotal-1; neuronidx++)
25970  {
25971  entryoffs = entrysize*neuronidx;
25972  offs = istart+neuronidx*mlpbase_nfieldwidth;
25973  neurontype = network->structinfo.ptr.p_int[offs+0];
25974  if( neurontype>0||neurontype==-5 )
25975  {
25976 
25977  /*
25978  * "activation function" neuron, which takes value of neuron SrcNeuronIdx
25979  * and applies activation function to it.
25980  *
25981  * This neuron has no weights and no tunable parameters.
25982  */
25983  srcneuronidx = network->structinfo.ptr.p_int[offs+2];
25984  srcentryoffs = entrysize*srcneuronidx;
25985  mlpactivationfunction(batch4buf->ptr.p_double[srcentryoffs+0], neurontype, &f, &df, &d2f, _state);
25986  batch4buf->ptr.p_double[entryoffs+0] = f;
25987  mlpactivationfunction(batch4buf->ptr.p_double[srcentryoffs+1], neurontype, &f, &df, &d2f, _state);
25988  batch4buf->ptr.p_double[entryoffs+1] = f;
25989  mlpactivationfunction(batch4buf->ptr.p_double[srcentryoffs+2], neurontype, &f, &df, &d2f, _state);
25990  batch4buf->ptr.p_double[entryoffs+2] = f;
25991  mlpactivationfunction(batch4buf->ptr.p_double[srcentryoffs+3], neurontype, &f, &df, &d2f, _state);
25992  batch4buf->ptr.p_double[entryoffs+3] = f;
25993  continue;
25994  }
25995  if( neurontype==0 )
25996  {
25997 
25998  /*
25999  * "adaptive summator" neuron, whose output is a weighted sum of inputs.
26000  * It has weights, but has no activation function.
26001  */
26002  nweights = network->structinfo.ptr.p_int[offs+1];
26003  srcneuronidx = network->structinfo.ptr.p_int[offs+2];
26004  srcentryoffs = entrysize*srcneuronidx;
26005  srcweightidx = network->structinfo.ptr.p_int[offs+3];
26006  v0 = 0;
26007  v1 = 0;
26008  v2 = 0;
26009  v3 = 0;
26010  for(j=0; j<=nweights-1; j++)
26011  {
26012  v = network->weights.ptr.p_double[srcweightidx];
26013  srcweightidx = srcweightidx+1;
26014  v0 = v0+v*batch4buf->ptr.p_double[srcentryoffs+0];
26015  v1 = v1+v*batch4buf->ptr.p_double[srcentryoffs+1];
26016  v2 = v2+v*batch4buf->ptr.p_double[srcentryoffs+2];
26017  v3 = v3+v*batch4buf->ptr.p_double[srcentryoffs+3];
26018  srcentryoffs = srcentryoffs+entrysize;
26019  }
26020  batch4buf->ptr.p_double[entryoffs+0] = v0;
26021  batch4buf->ptr.p_double[entryoffs+1] = v1;
26022  batch4buf->ptr.p_double[entryoffs+2] = v2;
26023  batch4buf->ptr.p_double[entryoffs+3] = v3;
26024  continue;
26025  }
26026  if( neurontype<0 )
26027  {
26028  bflag = ae_false;
26029  if( neurontype==-2 )
26030  {
26031 
26032  /*
26033  * Input neuron, left unchanged
26034  */
26035  bflag = ae_true;
26036  }
26037  if( neurontype==-3 )
26038  {
26039 
26040  /*
26041  * "-1" neuron
26042  */
26043  batch4buf->ptr.p_double[entryoffs+0] = -1;
26044  batch4buf->ptr.p_double[entryoffs+1] = -1;
26045  batch4buf->ptr.p_double[entryoffs+2] = -1;
26046  batch4buf->ptr.p_double[entryoffs+3] = -1;
26047  bflag = ae_true;
26048  }
26049  if( neurontype==-4 )
26050  {
26051 
26052  /*
26053  * "0" neuron
26054  */
26055  batch4buf->ptr.p_double[entryoffs+0] = 0;
26056  batch4buf->ptr.p_double[entryoffs+1] = 0;
26057  batch4buf->ptr.p_double[entryoffs+2] = 0;
26058  batch4buf->ptr.p_double[entryoffs+3] = 0;
26059  bflag = ae_true;
26060  }
26061  ae_assert(bflag, "MLPChunkedProcess: internal error - unknown neuron type!", _state);
26062  continue;
26063  }
26064  }
26065 
26066  /*
26067  * SOFTMAX normalization or scaling.
26068  */
26069  ae_assert(network->structinfo.ptr.p_int[6]==0||network->structinfo.ptr.p_int[6]==1, "MLPChunkedProcess: unknown normalization type!", _state);
26070  if( network->structinfo.ptr.p_int[6]==1 )
26071  {
26072 
26073  /*
26074  * SOFTMAX-normalized network.
26075  *
26076  * First, calculate (V0,V1,V2,V3) - component-wise maximum
26077  * of output neurons. This vector of maximum values will be
26078  * used for normalization of outputs prior to calculating
26079  * exponentials.
26080  *
26081  * NOTE: the only purpose of this stage is to prevent overflow
26082  * during calculation of exponentials. With this stage
26083  * we make sure that all exponentials are calculated
26084  * with non-positive argument. If you load (0,0,0,0) to
26085  * (V0,V1,V2,V3), your program will continue working -
26086  * although with less robustness.
26087  */
26088  entryoffs = entrysize*(ntotal-nout);
26089  v0 = batch4buf->ptr.p_double[entryoffs+0];
26090  v1 = batch4buf->ptr.p_double[entryoffs+1];
26091  v2 = batch4buf->ptr.p_double[entryoffs+2];
26092  v3 = batch4buf->ptr.p_double[entryoffs+3];
26093  entryoffs = entryoffs+entrysize;
26094  for(i=1; i<=nout-1; i++)
26095  {
26096  v = batch4buf->ptr.p_double[entryoffs+0];
26097  if( v>v0 )
26098  {
26099  v0 = v;
26100  }
26101  v = batch4buf->ptr.p_double[entryoffs+1];
26102  if( v>v1 )
26103  {
26104  v1 = v;
26105  }
26106  v = batch4buf->ptr.p_double[entryoffs+2];
26107  if( v>v2 )
26108  {
26109  v2 = v;
26110  }
26111  v = batch4buf->ptr.p_double[entryoffs+3];
26112  if( v>v3 )
26113  {
26114  v3 = v;
26115  }
26116  entryoffs = entryoffs+entrysize;
26117  }
26118 
26119  /*
26120  * Then, calculate exponentials and place them to part of the
26121  * array which is located past the last entry. We also
26122  * calculate sum of exponentials.
26123  */
26124  entryoffs = entrysize*(ntotal-nout);
26125  offs0 = entrysize*ntotal;
26126  s0 = 0;
26127  s1 = 0;
26128  s2 = 0;
26129  s3 = 0;
26130  for(i=0; i<=nout-1; i++)
26131  {
26132  v = ae_exp(batch4buf->ptr.p_double[entryoffs+0]-v0, _state);
26133  s0 = s0+v;
26134  batch4buf->ptr.p_double[offs0+0] = v;
26135  v = ae_exp(batch4buf->ptr.p_double[entryoffs+1]-v1, _state);
26136  s1 = s1+v;
26137  batch4buf->ptr.p_double[offs0+1] = v;
26138  v = ae_exp(batch4buf->ptr.p_double[entryoffs+2]-v2, _state);
26139  s2 = s2+v;
26140  batch4buf->ptr.p_double[offs0+2] = v;
26141  v = ae_exp(batch4buf->ptr.p_double[entryoffs+3]-v3, _state);
26142  s3 = s3+v;
26143  batch4buf->ptr.p_double[offs0+3] = v;
26144  entryoffs = entryoffs+entrysize;
26145  offs0 = offs0+chunksize;
26146  }
26147 
26148  /*
26149  * Write SOFTMAX-normalized values to the output array.
26150  */
26151  offs0 = entrysize*ntotal;
26152  for(i=0; i<=nout-1; i++)
26153  {
26154  if( csize>0 )
26155  {
26156  xy->ptr.pp_double[cstart+0][nin+i] = batch4buf->ptr.p_double[offs0+0]/s0;
26157  }
26158  if( csize>1 )
26159  {
26160  xy->ptr.pp_double[cstart+1][nin+i] = batch4buf->ptr.p_double[offs0+1]/s1;
26161  }
26162  if( csize>2 )
26163  {
26164  xy->ptr.pp_double[cstart+2][nin+i] = batch4buf->ptr.p_double[offs0+2]/s2;
26165  }
26166  if( csize>3 )
26167  {
26168  xy->ptr.pp_double[cstart+3][nin+i] = batch4buf->ptr.p_double[offs0+3]/s3;
26169  }
26170  offs0 = offs0+chunksize;
26171  }
26172  }
26173  else
26174  {
26175 
26176  /*
26177  * Regression network with sum-of-squares function.
26178  *
26179  * For each NOut of last neurons:
26180  * * calculate difference between actual and desired output
26181  * * calculate dError/dOut for this neuron (proportional to difference)
26182  * * store in in last 4 components of entry (these values are used
26183  * to start backpropagation)
26184  * * update error
26185  */
26186  for(i=0; i<=nout-1; i++)
26187  {
26188  v0 = network->columnsigmas.ptr.p_double[nin+i];
26189  v1 = network->columnmeans.ptr.p_double[nin+i];
26190  entryoffs = entrysize*(ntotal-nout+i);
26191  for(j=0; j<=csize-1; j++)
26192  {
26193  xy->ptr.pp_double[cstart+j][nin+i] = batch4buf->ptr.p_double[entryoffs+j]*v0+v1;
26194  }
26195  }
26196  }
26197 }
26198 
26199 
26200 /*************************************************************************
26201 Returns T*Ln(T/Z), guarded against overflow/underflow.
26202 Internal subroutine.
26203 *************************************************************************/
26204 static double mlpbase_safecrossentropy(double t,
26205  double z,
26206  ae_state *_state)
26207 {
26208  double r;
26209  double result;
26210 
26211 
26212  if( ae_fp_eq(t,0) )
26213  {
26214  result = 0;
26215  }
26216  else
26217  {
26218  if( ae_fp_greater(ae_fabs(z, _state),1) )
26219  {
26220 
26221  /*
26222  * Shouldn't be the case with softmax,
26223  * but we just want to be sure.
26224  */
26225  if( ae_fp_eq(t/z,0) )
26226  {
26227  r = ae_minrealnumber;
26228  }
26229  else
26230  {
26231  r = t/z;
26232  }
26233  }
26234  else
26235  {
26236 
26237  /*
26238  * Normal case
26239  */
26240  if( ae_fp_eq(z,0)||ae_fp_greater_eq(ae_fabs(t, _state),ae_maxrealnumber*ae_fabs(z, _state)) )
26241  {
26242  r = ae_maxrealnumber;
26243  }
26244  else
26245  {
26246  r = t/z;
26247  }
26248  }
26249  result = t*ae_log(r, _state);
26250  }
26251  return result;
26252 }
26253 
26254 
26255 /*************************************************************************
26256 This function performs backward pass of neural network randimization:
26257 * it assumes that Network.Weights stores standard deviation of weights
26258  (weights are not generated yet, only their deviations are present)
26259 * it sets deviations of weights which feed NeuronIdx-th neuron to specified value
26260 * it recursively passes to deeper neuron and modifies their weights
26261 * it stops after encountering nonlinear neurons, linear activation function,
26262  input neurons, "0" and "-1" neurons
26263 
26264  -- ALGLIB --
26265  Copyright 27.06.2013 by Bochkanov Sergey
26266 *************************************************************************/
26267 static void mlpbase_randomizebackwardpass(multilayerperceptron* network,
26268  ae_int_t neuronidx,
26269  double v,
26270  ae_state *_state)
26271 {
26272  ae_int_t istart;
26273  ae_int_t neurontype;
26274  ae_int_t n1;
26275  ae_int_t n2;
26276  ae_int_t w1;
26277  ae_int_t w2;
26278  ae_int_t offs;
26279  ae_int_t i;
26280 
26281 
26282  istart = network->structinfo.ptr.p_int[5];
26283  neurontype = network->structinfo.ptr.p_int[istart+neuronidx*mlpbase_nfieldwidth+0];
26284  if( neurontype==-2 )
26285  {
26286 
26287  /*
26288  * Input neuron - stop
26289  */
26290  return;
26291  }
26292  if( neurontype==-3 )
26293  {
26294 
26295  /*
26296  * "-1" neuron: stop
26297  */
26298  return;
26299  }
26300  if( neurontype==-4 )
26301  {
26302 
26303  /*
26304  * "0" neuron: stop
26305  */
26306  return;
26307  }
26308  if( neurontype==0 )
26309  {
26310 
26311  /*
26312  * Adaptive summator neuron:
26313  * * modify deviations of its weights
26314  * * recursively call this function for its inputs
26315  */
26316  offs = istart+neuronidx*mlpbase_nfieldwidth;
26317  n1 = network->structinfo.ptr.p_int[offs+2];
26318  n2 = n1+network->structinfo.ptr.p_int[offs+1]-1;
26319  w1 = network->structinfo.ptr.p_int[offs+3];
26320  w2 = w1+network->structinfo.ptr.p_int[offs+1]-1;
26321  for(i=w1; i<=w2; i++)
26322  {
26323  network->weights.ptr.p_double[i] = v;
26324  }
26325  for(i=n1; i<=n2; i++)
26326  {
26327  mlpbase_randomizebackwardpass(network, i, v, _state);
26328  }
26329  return;
26330  }
26331  if( neurontype==-5 )
26332  {
26333 
26334  /*
26335  * Linear activation function: stop
26336  */
26337  return;
26338  }
26339  if( neurontype>0 )
26340  {
26341 
26342  /*
26343  * Nonlinear activation function: stop
26344  */
26345  return;
26346  }
26347  ae_assert(ae_false, "RandomizeBackwardPass: unexpected neuron type", _state);
26348 }
26349 
26350 
26351 ae_bool _modelerrors_init(void* _p, ae_state *_state, ae_bool make_automatic)
26352 {
26353  modelerrors *p = (modelerrors*)_p;
26354  ae_touch_ptr((void*)p);
26355  return ae_true;
26356 }
26357 
26358 
26359 ae_bool _modelerrors_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
26360 {
26361  modelerrors *dst = (modelerrors*)_dst;
26362  modelerrors *src = (modelerrors*)_src;
26363  dst->relclserror = src->relclserror;
26364  dst->avgce = src->avgce;
26365  dst->rmserror = src->rmserror;
26366  dst->avgerror = src->avgerror;
26367  dst->avgrelerror = src->avgrelerror;
26368  return ae_true;
26369 }
26370 
26371 
26372 void _modelerrors_clear(void* _p)
26373 {
26374  modelerrors *p = (modelerrors*)_p;
26375  ae_touch_ptr((void*)p);
26376 }
26377 
26378 
26379 void _modelerrors_destroy(void* _p)
26380 {
26381  modelerrors *p = (modelerrors*)_p;
26382  ae_touch_ptr((void*)p);
26383 }
26384 
26385 
26386 ae_bool _smlpgrad_init(void* _p, ae_state *_state, ae_bool make_automatic)
26387 {
26388  smlpgrad *p = (smlpgrad*)_p;
26389  ae_touch_ptr((void*)p);
26390  if( !ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic) )
26391  return ae_false;
26392  return ae_true;
26393 }
26394 
26395 
26396 ae_bool _smlpgrad_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
26397 {
26398  smlpgrad *dst = (smlpgrad*)_dst;
26399  smlpgrad *src = (smlpgrad*)_src;
26400  dst->f = src->f;
26401  if( !ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic) )
26402  return ae_false;
26403  return ae_true;
26404 }
26405 
26406 
26407 void _smlpgrad_clear(void* _p)
26408 {
26409  smlpgrad *p = (smlpgrad*)_p;
26410  ae_touch_ptr((void*)p);
26411  ae_vector_clear(&p->g);
26412 }
26413 
26414 
26415 void _smlpgrad_destroy(void* _p)
26416 {
26417  smlpgrad *p = (smlpgrad*)_p;
26418  ae_touch_ptr((void*)p);
26419  ae_vector_destroy(&p->g);
26420 }
26421 
26422 
26423 ae_bool _multilayerperceptron_init(void* _p, ae_state *_state, ae_bool make_automatic)
26424 {
26425  multilayerperceptron *p = (multilayerperceptron*)_p;
26426  ae_touch_ptr((void*)p);
26427  if( !ae_vector_init(&p->hllayersizes, 0, DT_INT, _state, make_automatic) )
26428  return ae_false;
26429  if( !ae_vector_init(&p->hlconnections, 0, DT_INT, _state, make_automatic) )
26430  return ae_false;
26431  if( !ae_vector_init(&p->hlneurons, 0, DT_INT, _state, make_automatic) )
26432  return ae_false;
26433  if( !ae_vector_init(&p->structinfo, 0, DT_INT, _state, make_automatic) )
26434  return ae_false;
26435  if( !ae_vector_init(&p->weights, 0, DT_REAL, _state, make_automatic) )
26436  return ae_false;
26437  if( !ae_vector_init(&p->columnmeans, 0, DT_REAL, _state, make_automatic) )
26438  return ae_false;
26439  if( !ae_vector_init(&p->columnsigmas, 0, DT_REAL, _state, make_automatic) )
26440  return ae_false;
26441  if( !ae_vector_init(&p->neurons, 0, DT_REAL, _state, make_automatic) )
26442  return ae_false;
26443  if( !ae_vector_init(&p->dfdnet, 0, DT_REAL, _state, make_automatic) )
26444  return ae_false;
26445  if( !ae_vector_init(&p->derror, 0, DT_REAL, _state, make_automatic) )
26446  return ae_false;
26447  if( !ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic) )
26448  return ae_false;
26449  if( !ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic) )
26450  return ae_false;
26451  if( !ae_matrix_init(&p->xy, 0, 0, DT_REAL, _state, make_automatic) )
26452  return ae_false;
26453  if( !ae_vector_init(&p->xyrow, 0, DT_REAL, _state, make_automatic) )
26454  return ae_false;
26455  if( !ae_vector_init(&p->nwbuf, 0, DT_REAL, _state, make_automatic) )
26456  return ae_false;
26457  if( !ae_vector_init(&p->integerbuf, 0, DT_INT, _state, make_automatic) )
26458  return ae_false;
26459  if( !_modelerrors_init(&p->err, _state, make_automatic) )
26460  return ae_false;
26461  if( !ae_vector_init(&p->rndbuf, 0, DT_REAL, _state, make_automatic) )
26462  return ae_false;
26463  if( !ae_shared_pool_init(&p->buf, _state, make_automatic) )
26464  return ae_false;
26465  if( !ae_shared_pool_init(&p->gradbuf, _state, make_automatic) )
26466  return ae_false;
26467  if( !ae_matrix_init(&p->dummydxy, 0, 0, DT_REAL, _state, make_automatic) )
26468  return ae_false;
26469  if( !_sparsematrix_init(&p->dummysxy, _state, make_automatic) )
26470  return ae_false;
26471  if( !ae_vector_init(&p->dummyidx, 0, DT_INT, _state, make_automatic) )
26472  return ae_false;
26473  if( !ae_shared_pool_init(&p->dummypool, _state, make_automatic) )
26474  return ae_false;
26475  return ae_true;
26476 }
26477 
26478 
26479 ae_bool _multilayerperceptron_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
26480 {
26481  multilayerperceptron *dst = (multilayerperceptron*)_dst;
26482  multilayerperceptron *src = (multilayerperceptron*)_src;
26483  dst->hlnetworktype = src->hlnetworktype;
26484  dst->hlnormtype = src->hlnormtype;
26485  if( !ae_vector_init_copy(&dst->hllayersizes, &src->hllayersizes, _state, make_automatic) )
26486  return ae_false;
26487  if( !ae_vector_init_copy(&dst->hlconnections, &src->hlconnections, _state, make_automatic) )
26488  return ae_false;
26489  if( !ae_vector_init_copy(&dst->hlneurons, &src->hlneurons, _state, make_automatic) )
26490  return ae_false;
26491  if( !ae_vector_init_copy(&dst->structinfo, &src->structinfo, _state, make_automatic) )
26492  return ae_false;
26493  if( !ae_vector_init_copy(&dst->weights, &src->weights, _state, make_automatic) )
26494  return ae_false;
26495  if( !ae_vector_init_copy(&dst->columnmeans, &src->columnmeans, _state, make_automatic) )
26496  return ae_false;
26497  if( !ae_vector_init_copy(&dst->columnsigmas, &src->columnsigmas, _state, make_automatic) )
26498  return ae_false;
26499  if( !ae_vector_init_copy(&dst->neurons, &src->neurons, _state, make_automatic) )
26500  return ae_false;
26501  if( !ae_vector_init_copy(&dst->dfdnet, &src->dfdnet, _state, make_automatic) )
26502  return ae_false;
26503  if( !ae_vector_init_copy(&dst->derror, &src->derror, _state, make_automatic) )
26504  return ae_false;
26505  if( !ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic) )
26506  return ae_false;
26507  if( !ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic) )
26508  return ae_false;
26509  if( !ae_matrix_init_copy(&dst->xy, &src->xy, _state, make_automatic) )
26510  return ae_false;
26511  if( !ae_vector_init_copy(&dst->xyrow, &src->xyrow, _state, make_automatic) )
26512  return ae_false;
26513  if( !ae_vector_init_copy(&dst->nwbuf, &src->nwbuf, _state, make_automatic) )
26514  return ae_false;
26515  if( !ae_vector_init_copy(&dst->integerbuf, &src->integerbuf, _state, make_automatic) )
26516  return ae_false;
26517  if( !_modelerrors_init_copy(&dst->err, &src->err, _state, make_automatic) )
26518  return ae_false;
26519  if( !ae_vector_init_copy(&dst->rndbuf, &src->rndbuf, _state, make_automatic) )
26520  return ae_false;
26521  if( !ae_shared_pool_init_copy(&dst->buf, &src->buf, _state, make_automatic) )
26522  return ae_false;
26523  if( !ae_shared_pool_init_copy(&dst->gradbuf, &src->gradbuf, _state, make_automatic) )
26524  return ae_false;
26525  if( !ae_matrix_init_copy(&dst->dummydxy, &src->dummydxy, _state, make_automatic) )
26526  return ae_false;
26527  if( !_sparsematrix_init_copy(&dst->dummysxy, &src->dummysxy, _state, make_automatic) )
26528  return ae_false;
26529  if( !ae_vector_init_copy(&dst->dummyidx, &src->dummyidx, _state, make_automatic) )
26530  return ae_false;
26531  if( !ae_shared_pool_init_copy(&dst->dummypool, &src->dummypool, _state, make_automatic) )
26532  return ae_false;
26533  return ae_true;
26534 }
26535 
26536 
26537 void _multilayerperceptron_clear(void* _p)
26538 {
26539  multilayerperceptron *p = (multilayerperceptron*)_p;
26540  ae_touch_ptr((void*)p);
26541  ae_vector_clear(&p->hllayersizes);
26542  ae_vector_clear(&p->hlconnections);
26543  ae_vector_clear(&p->hlneurons);
26544  ae_vector_clear(&p->structinfo);
26545  ae_vector_clear(&p->weights);
26546  ae_vector_clear(&p->columnmeans);
26547  ae_vector_clear(&p->columnsigmas);
26548  ae_vector_clear(&p->neurons);
26549  ae_vector_clear(&p->dfdnet);
26550  ae_vector_clear(&p->derror);
26551  ae_vector_clear(&p->x);
26552  ae_vector_clear(&p->y);
26553  ae_matrix_clear(&p->xy);
26554  ae_vector_clear(&p->xyrow);
26555  ae_vector_clear(&p->nwbuf);
26556  ae_vector_clear(&p->integerbuf);
26557  _modelerrors_clear(&p->err);
26558  ae_vector_clear(&p->rndbuf);
26559  ae_shared_pool_clear(&p->buf);
26560  ae_shared_pool_clear(&p->gradbuf);
26561  ae_matrix_clear(&p->dummydxy);
26562  _sparsematrix_clear(&p->dummysxy);
26563  ae_vector_clear(&p->dummyidx);
26564  ae_shared_pool_clear(&p->dummypool);
26565 }
26566 
26567 
26568 void _multilayerperceptron_destroy(void* _p)
26569 {
26570  multilayerperceptron *p = (multilayerperceptron*)_p;
26571  ae_touch_ptr((void*)p);
26572  ae_vector_destroy(&p->hllayersizes);
26573  ae_vector_destroy(&p->hlconnections);
26574  ae_vector_destroy(&p->hlneurons);
26575  ae_vector_destroy(&p->structinfo);
26576  ae_vector_destroy(&p->weights);
26577  ae_vector_destroy(&p->columnmeans);
26578  ae_vector_destroy(&p->columnsigmas);
26579  ae_vector_destroy(&p->neurons);
26580  ae_vector_destroy(&p->dfdnet);
26581  ae_vector_destroy(&p->derror);
26582  ae_vector_destroy(&p->x);
26583  ae_vector_destroy(&p->y);
26584  ae_matrix_destroy(&p->xy);
26585  ae_vector_destroy(&p->xyrow);
26586  ae_vector_destroy(&p->nwbuf);
26587  ae_vector_destroy(&p->integerbuf);
26588  _modelerrors_destroy(&p->err);
26589  ae_vector_destroy(&p->rndbuf);
26590  ae_shared_pool_destroy(&p->buf);
26591  ae_shared_pool_destroy(&p->gradbuf);
26592  ae_matrix_destroy(&p->dummydxy);
26593  _sparsematrix_destroy(&p->dummysxy);
26594  ae_vector_destroy(&p->dummyidx);
26595  ae_shared_pool_destroy(&p->dummypool);
26596 }
26597 
26598 
26599 
26600 
26601 /*************************************************************************
26602 This subroutine trains logit model.
26603 
26604 INPUT PARAMETERS:
26605  XY - training set, array[0..NPoints-1,0..NVars]
26606  First NVars columns store values of independent
26607  variables, next column stores number of class (from 0
26608  to NClasses-1) which dataset element belongs to. Fractional
26609  values are rounded to nearest integer.
26610  NPoints - training set size, NPoints>=1
26611  NVars - number of independent variables, NVars>=1
26612  NClasses - number of classes, NClasses>=2
26613 
26614 OUTPUT PARAMETERS:
26615  Info - return code:
26616  * -2, if there is a point with class number
26617  outside of [0..NClasses-1].
26618  * -1, if incorrect parameters was passed
26619  (NPoints<NVars+2, NVars<1, NClasses<2).
26620  * 1, if task has been solved
26621  LM - model built
26622  Rep - training report
26623 
26624  -- ALGLIB --
26625  Copyright 10.09.2008 by Bochkanov Sergey
26626 *************************************************************************/
26627 void mnltrainh(/* Real */ ae_matrix* xy,
26628  ae_int_t npoints,
26629  ae_int_t nvars,
26630  ae_int_t nclasses,
26631  ae_int_t* info,
26632  logitmodel* lm,
26633  mnlreport* rep,
26634  ae_state *_state)
26635 {
26636  ae_frame _frame_block;
26637  ae_int_t i;
26638  ae_int_t j;
26639  ae_int_t k;
26640  ae_int_t ssize;
26641  ae_bool allsame;
26642  ae_int_t offs;
26643  double decay;
26644  double v;
26645  double s;
26646  multilayerperceptron network;
26647  ae_int_t nin;
26648  ae_int_t nout;
26649  ae_int_t wcount;
26650  double e;
26651  ae_vector g;
26652  ae_matrix h;
26653  ae_bool spd;
26654  ae_vector x;
26655  ae_vector y;
26656  ae_vector wbase;
26657  double wstep;
26658  ae_vector wdir;
26659  ae_vector work;
26660  ae_int_t mcstage;
26661  logitmcstate mcstate;
26662  ae_int_t mcinfo;
26663  ae_int_t mcnfev;
26664  ae_int_t solverinfo;
26665  densesolverreport solverrep;
26666 
26667  ae_frame_make(_state, &_frame_block);
26668  *info = 0;
26669  _logitmodel_clear(lm);
26670  _mnlreport_clear(rep);
26671  _multilayerperceptron_init(&network, _state, ae_true);
26672  ae_vector_init(&g, 0, DT_REAL, _state, ae_true);
26673  ae_matrix_init(&h, 0, 0, DT_REAL, _state, ae_true);
26674  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
26675  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
26676  ae_vector_init(&wbase, 0, DT_REAL, _state, ae_true);
26677  ae_vector_init(&wdir, 0, DT_REAL, _state, ae_true);
26678  ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
26679  _logitmcstate_init(&mcstate, _state, ae_true);
26680  _densesolverreport_init(&solverrep, _state, ae_true);
26681 
26682  decay = 0.001;
26683 
26684  /*
26685  * Test for inputs
26686  */
26687  if( (npoints<nvars+2||nvars<1)||nclasses<2 )
26688  {
26689  *info = -1;
26690  ae_frame_leave(_state);
26691  return;
26692  }
26693  for(i=0; i<=npoints-1; i++)
26694  {
26695  if( ae_round(xy->ptr.pp_double[i][nvars], _state)<0||ae_round(xy->ptr.pp_double[i][nvars], _state)>=nclasses )
26696  {
26697  *info = -2;
26698  ae_frame_leave(_state);
26699  return;
26700  }
26701  }
26702  *info = 1;
26703 
26704  /*
26705  * Initialize data
26706  */
26707  rep->ngrad = 0;
26708  rep->nhess = 0;
26709 
26710  /*
26711  * Allocate array
26712  */
26713  offs = 5;
26714  ssize = 5+(nvars+1)*(nclasses-1)+nclasses;
26715  ae_vector_set_length(&lm->w, ssize-1+1, _state);
26716  lm->w.ptr.p_double[0] = ssize;
26717  lm->w.ptr.p_double[1] = logit_logitvnum;
26718  lm->w.ptr.p_double[2] = nvars;
26719  lm->w.ptr.p_double[3] = nclasses;
26720  lm->w.ptr.p_double[4] = offs;
26721 
26722  /*
26723  * Degenerate case: all outputs are equal
26724  */
26725  allsame = ae_true;
26726  for(i=1; i<=npoints-1; i++)
26727  {
26728  if( ae_round(xy->ptr.pp_double[i][nvars], _state)!=ae_round(xy->ptr.pp_double[i-1][nvars], _state) )
26729  {
26730  allsame = ae_false;
26731  }
26732  }
26733  if( allsame )
26734  {
26735  for(i=0; i<=(nvars+1)*(nclasses-1)-1; i++)
26736  {
26737  lm->w.ptr.p_double[offs+i] = 0;
26738  }
26739  v = -2*ae_log(ae_minrealnumber, _state);
26740  k = ae_round(xy->ptr.pp_double[0][nvars], _state);
26741  if( k==nclasses-1 )
26742  {
26743  for(i=0; i<=nclasses-2; i++)
26744  {
26745  lm->w.ptr.p_double[offs+i*(nvars+1)+nvars] = -v;
26746  }
26747  }
26748  else
26749  {
26750  for(i=0; i<=nclasses-2; i++)
26751  {
26752  if( i==k )
26753  {
26754  lm->w.ptr.p_double[offs+i*(nvars+1)+nvars] = v;
26755  }
26756  else
26757  {
26758  lm->w.ptr.p_double[offs+i*(nvars+1)+nvars] = 0;
26759  }
26760  }
26761  }
26762  ae_frame_leave(_state);
26763  return;
26764  }
26765 
26766  /*
26767  * General case.
26768  * Prepare task and network. Allocate space.
26769  */
26770  mlpcreatec0(nvars, nclasses, &network, _state);
26771  mlpinitpreprocessor(&network, xy, npoints, _state);
26772  mlpproperties(&network, &nin, &nout, &wcount, _state);
26773  for(i=0; i<=wcount-1; i++)
26774  {
26775  network.weights.ptr.p_double[i] = (2*ae_randomreal(_state)-1)/nvars;
26776  }
26777  ae_vector_set_length(&g, wcount-1+1, _state);
26778  ae_matrix_set_length(&h, wcount-1+1, wcount-1+1, _state);
26779  ae_vector_set_length(&wbase, wcount-1+1, _state);
26780  ae_vector_set_length(&wdir, wcount-1+1, _state);
26781  ae_vector_set_length(&work, wcount-1+1, _state);
26782 
26783  /*
26784  * First stage: optimize in gradient direction.
26785  */
26786  for(k=0; k<=wcount/3+10; k++)
26787  {
26788 
26789  /*
26790  * Calculate gradient in starting point
26791  */
26792  mlpgradnbatch(&network, xy, npoints, &e, &g, _state);
26793  v = ae_v_dotproduct(&network.weights.ptr.p_double[0], 1, &network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
26794  e = e+0.5*decay*v;
26795  ae_v_addd(&g.ptr.p_double[0], 1, &network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1), decay);
26796  rep->ngrad = rep->ngrad+1;
26797 
26798  /*
26799  * Setup optimization scheme
26800  */
26801  ae_v_moveneg(&wdir.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
26802  v = ae_v_dotproduct(&wdir.ptr.p_double[0], 1, &wdir.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
26803  wstep = ae_sqrt(v, _state);
26804  v = 1/ae_sqrt(v, _state);
26805  ae_v_muld(&wdir.ptr.p_double[0], 1, ae_v_len(0,wcount-1), v);
26806  mcstage = 0;
26807  logit_mnlmcsrch(wcount, &network.weights, &e, &g, &wdir, &wstep, &mcinfo, &mcnfev, &work, &mcstate, &mcstage, _state);
26808  while(mcstage!=0)
26809  {
26810  mlpgradnbatch(&network, xy, npoints, &e, &g, _state);
26811  v = ae_v_dotproduct(&network.weights.ptr.p_double[0], 1, &network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
26812  e = e+0.5*decay*v;
26813  ae_v_addd(&g.ptr.p_double[0], 1, &network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1), decay);
26814  rep->ngrad = rep->ngrad+1;
26815  logit_mnlmcsrch(wcount, &network.weights, &e, &g, &wdir, &wstep, &mcinfo, &mcnfev, &work, &mcstate, &mcstage, _state);
26816  }
26817  }
26818 
26819  /*
26820  * Second stage: use Hessian when we are close to the minimum
26821  */
26822  for(;;)
26823  {
26824 
26825  /*
26826  * Calculate and update E/G/H
26827  */
26828  mlphessiannbatch(&network, xy, npoints, &e, &g, &h, _state);
26829  v = ae_v_dotproduct(&network.weights.ptr.p_double[0], 1, &network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
26830  e = e+0.5*decay*v;
26831  ae_v_addd(&g.ptr.p_double[0], 1, &network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1), decay);
26832  for(k=0; k<=wcount-1; k++)
26833  {
26834  h.ptr.pp_double[k][k] = h.ptr.pp_double[k][k]+decay;
26835  }
26836  rep->nhess = rep->nhess+1;
26837 
26838  /*
26839  * Select step direction
26840  * NOTE: it is important to use lower-triangle Cholesky
26841  * factorization since it is much faster than higher-triangle version.
26842  */
26843  spd = spdmatrixcholesky(&h, wcount, ae_false, _state);
26844  spdmatrixcholeskysolve(&h, wcount, ae_false, &g, &solverinfo, &solverrep, &wdir, _state);
26845  spd = solverinfo>0;
26846  if( spd )
26847  {
26848 
26849  /*
26850  * H is positive definite.
26851  * Step in Newton direction.
26852  */
26853  ae_v_muld(&wdir.ptr.p_double[0], 1, ae_v_len(0,wcount-1), -1);
26854  spd = ae_true;
26855  }
26856  else
26857  {
26858 
26859  /*
26860  * H is indefinite.
26861  * Step in gradient direction.
26862  */
26863  ae_v_moveneg(&wdir.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
26864  spd = ae_false;
26865  }
26866 
26867  /*
26868  * Optimize in WDir direction
26869  */
26870  v = ae_v_dotproduct(&wdir.ptr.p_double[0], 1, &wdir.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
26871  wstep = ae_sqrt(v, _state);
26872  v = 1/ae_sqrt(v, _state);
26873  ae_v_muld(&wdir.ptr.p_double[0], 1, ae_v_len(0,wcount-1), v);
26874  mcstage = 0;
26875  logit_mnlmcsrch(wcount, &network.weights, &e, &g, &wdir, &wstep, &mcinfo, &mcnfev, &work, &mcstate, &mcstage, _state);
26876  while(mcstage!=0)
26877  {
26878  mlpgradnbatch(&network, xy, npoints, &e, &g, _state);
26879  v = ae_v_dotproduct(&network.weights.ptr.p_double[0], 1, &network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
26880  e = e+0.5*decay*v;
26881  ae_v_addd(&g.ptr.p_double[0], 1, &network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1), decay);
26882  rep->ngrad = rep->ngrad+1;
26883  logit_mnlmcsrch(wcount, &network.weights, &e, &g, &wdir, &wstep, &mcinfo, &mcnfev, &work, &mcstate, &mcstage, _state);
26884  }
26885  if( spd&&((mcinfo==2||mcinfo==4)||mcinfo==6) )
26886  {
26887  break;
26888  }
26889  }
26890 
26891  /*
26892  * Convert from NN format to MNL format
26893  */
26894  ae_v_move(&lm->w.ptr.p_double[offs], 1, &network.weights.ptr.p_double[0], 1, ae_v_len(offs,offs+wcount-1));
26895  for(k=0; k<=nvars-1; k++)
26896  {
26897  for(i=0; i<=nclasses-2; i++)
26898  {
26899  s = network.columnsigmas.ptr.p_double[k];
26900  if( ae_fp_eq(s,0) )
26901  {
26902  s = 1;
26903  }
26904  j = offs+(nvars+1)*i;
26905  v = lm->w.ptr.p_double[j+k];
26906  lm->w.ptr.p_double[j+k] = v/s;
26907  lm->w.ptr.p_double[j+nvars] = lm->w.ptr.p_double[j+nvars]+v*network.columnmeans.ptr.p_double[k]/s;
26908  }
26909  }
26910  for(k=0; k<=nclasses-2; k++)
26911  {
26912  lm->w.ptr.p_double[offs+(nvars+1)*k+nvars] = -lm->w.ptr.p_double[offs+(nvars+1)*k+nvars];
26913  }
26914  ae_frame_leave(_state);
26915 }
26916 
26917 
26918 /*************************************************************************
26919 Procesing
26920 
26921 INPUT PARAMETERS:
26922  LM - logit model, passed by non-constant reference
26923  (some fields of structure are used as temporaries
26924  when calculating model output).
26925  X - input vector, array[0..NVars-1].
26926  Y - (possibly) preallocated buffer; if size of Y is less than
26927  NClasses, it will be reallocated.If it is large enough, it
26928  is NOT reallocated, so we can save some time on reallocation.
26929 
26930 OUTPUT PARAMETERS:
26931  Y - result, array[0..NClasses-1]
26932  Vector of posterior probabilities for classification task.
26933 
26934  -- ALGLIB --
26935  Copyright 10.09.2008 by Bochkanov Sergey
26936 *************************************************************************/
26937 void mnlprocess(logitmodel* lm,
26938  /* Real */ ae_vector* x,
26939  /* Real */ ae_vector* y,
26940  ae_state *_state)
26941 {
26942  ae_int_t nvars;
26943  ae_int_t nclasses;
26944  ae_int_t offs;
26945  ae_int_t i;
26946  ae_int_t i1;
26947  double s;
26948 
26949 
26950  ae_assert(ae_fp_eq(lm->w.ptr.p_double[1],logit_logitvnum), "MNLProcess: unexpected model version", _state);
26951  nvars = ae_round(lm->w.ptr.p_double[2], _state);
26952  nclasses = ae_round(lm->w.ptr.p_double[3], _state);
26953  offs = ae_round(lm->w.ptr.p_double[4], _state);
26954  logit_mnliexp(&lm->w, x, _state);
26955  s = 0;
26956  i1 = offs+(nvars+1)*(nclasses-1);
26957  for(i=i1; i<=i1+nclasses-1; i++)
26958  {
26959  s = s+lm->w.ptr.p_double[i];
26960  }
26961  if( y->cnt<nclasses )
26962  {
26963  ae_vector_set_length(y, nclasses, _state);
26964  }
26965  for(i=0; i<=nclasses-1; i++)
26966  {
26967  y->ptr.p_double[i] = lm->w.ptr.p_double[i1+i]/s;
26968  }
26969 }
26970 
26971 
26972 /*************************************************************************
26973 'interactive' variant of MNLProcess for languages like Python which
26974 support constructs like "Y = MNLProcess(LM,X)" and interactive mode of the
26975 interpreter
26976 
26977 This function allocates new array on each call, so it is significantly
26978 slower than its 'non-interactive' counterpart, but it is more convenient
26979 when you call it from command line.
26980 
26981  -- ALGLIB --
26982  Copyright 10.09.2008 by Bochkanov Sergey
26983 *************************************************************************/
26984 void mnlprocessi(logitmodel* lm,
26985  /* Real */ ae_vector* x,
26986  /* Real */ ae_vector* y,
26987  ae_state *_state)
26988 {
26989 
26990  ae_vector_clear(y);
26991 
26992  mnlprocess(lm, x, y, _state);
26993 }
26994 
26995 
26996 /*************************************************************************
26997 Unpacks coefficients of logit model. Logit model have form:
26998 
26999  P(class=i) = S(i) / (S(0) + S(1) + ... +S(M-1))
27000  S(i) = Exp(A[i,0]*X[0] + ... + A[i,N-1]*X[N-1] + A[i,N]), when i<M-1
27001  S(M-1) = 1
27002 
27003 INPUT PARAMETERS:
27004  LM - logit model in ALGLIB format
27005 
27006 OUTPUT PARAMETERS:
27007  V - coefficients, array[0..NClasses-2,0..NVars]
27008  NVars - number of independent variables
27009  NClasses - number of classes
27010 
27011  -- ALGLIB --
27012  Copyright 10.09.2008 by Bochkanov Sergey
27013 *************************************************************************/
27014 void mnlunpack(logitmodel* lm,
27015  /* Real */ ae_matrix* a,
27016  ae_int_t* nvars,
27017  ae_int_t* nclasses,
27018  ae_state *_state)
27019 {
27020  ae_int_t offs;
27021  ae_int_t i;
27022 
27023  ae_matrix_clear(a);
27024  *nvars = 0;
27025  *nclasses = 0;
27026 
27027  ae_assert(ae_fp_eq(lm->w.ptr.p_double[1],logit_logitvnum), "MNLUnpack: unexpected model version", _state);
27028  *nvars = ae_round(lm->w.ptr.p_double[2], _state);
27029  *nclasses = ae_round(lm->w.ptr.p_double[3], _state);
27030  offs = ae_round(lm->w.ptr.p_double[4], _state);
27031  ae_matrix_set_length(a, *nclasses-2+1, *nvars+1, _state);
27032  for(i=0; i<=*nclasses-2; i++)
27033  {
27034  ae_v_move(&a->ptr.pp_double[i][0], 1, &lm->w.ptr.p_double[offs+i*(*nvars+1)], 1, ae_v_len(0,*nvars));
27035  }
27036 }
27037 
27038 
27039 /*************************************************************************
27040 "Packs" coefficients and creates logit model in ALGLIB format (MNLUnpack
27041 reversed).
27042 
27043 INPUT PARAMETERS:
27044  A - model (see MNLUnpack)
27045  NVars - number of independent variables
27046  NClasses - number of classes
27047 
27048 OUTPUT PARAMETERS:
27049  LM - logit model.
27050 
27051  -- ALGLIB --
27052  Copyright 10.09.2008 by Bochkanov Sergey
27053 *************************************************************************/
27054 void mnlpack(/* Real */ ae_matrix* a,
27055  ae_int_t nvars,
27056  ae_int_t nclasses,
27057  logitmodel* lm,
27058  ae_state *_state)
27059 {
27060  ae_int_t offs;
27061  ae_int_t i;
27062  ae_int_t ssize;
27063 
27064  _logitmodel_clear(lm);
27065 
27066  offs = 5;
27067  ssize = 5+(nvars+1)*(nclasses-1)+nclasses;
27068  ae_vector_set_length(&lm->w, ssize-1+1, _state);
27069  lm->w.ptr.p_double[0] = ssize;
27070  lm->w.ptr.p_double[1] = logit_logitvnum;
27071  lm->w.ptr.p_double[2] = nvars;
27072  lm->w.ptr.p_double[3] = nclasses;
27073  lm->w.ptr.p_double[4] = offs;
27074  for(i=0; i<=nclasses-2; i++)
27075  {
27076  ae_v_move(&lm->w.ptr.p_double[offs+i*(nvars+1)], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(offs+i*(nvars+1),offs+i*(nvars+1)+nvars));
27077  }
27078 }
27079 
27080 
27081 /*************************************************************************
27082 Copying of LogitModel strucure
27083 
27084 INPUT PARAMETERS:
27085  LM1 - original
27086 
27087 OUTPUT PARAMETERS:
27088  LM2 - copy
27089 
27090  -- ALGLIB --
27091  Copyright 15.03.2009 by Bochkanov Sergey
27092 *************************************************************************/
27093 void mnlcopy(logitmodel* lm1, logitmodel* lm2, ae_state *_state)
27094 {
27095  ae_int_t k;
27096 
27097  _logitmodel_clear(lm2);
27098 
27099  k = ae_round(lm1->w.ptr.p_double[0], _state);
27100  ae_vector_set_length(&lm2->w, k-1+1, _state);
27101  ae_v_move(&lm2->w.ptr.p_double[0], 1, &lm1->w.ptr.p_double[0], 1, ae_v_len(0,k-1));
27102 }
27103 
27104 
27105 /*************************************************************************
27106 Average cross-entropy (in bits per element) on the test set
27107 
27108 INPUT PARAMETERS:
27109  LM - logit model
27110  XY - test set
27111  NPoints - test set size
27112 
27113 RESULT:
27114  CrossEntropy/(NPoints*ln(2)).
27115 
27116  -- ALGLIB --
27117  Copyright 10.09.2008 by Bochkanov Sergey
27118 *************************************************************************/
27119 double mnlavgce(logitmodel* lm,
27120  /* Real */ ae_matrix* xy,
27121  ae_int_t npoints,
27122  ae_state *_state)
27123 {
27124  ae_frame _frame_block;
27125  ae_int_t nvars;
27126  ae_int_t nclasses;
27127  ae_int_t i;
27128  ae_vector workx;
27129  ae_vector worky;
27130  double result;
27131 
27132  ae_frame_make(_state, &_frame_block);
27133  ae_vector_init(&workx, 0, DT_REAL, _state, ae_true);
27134  ae_vector_init(&worky, 0, DT_REAL, _state, ae_true);
27135 
27136  ae_assert(ae_fp_eq(lm->w.ptr.p_double[1],logit_logitvnum), "MNLClsError: unexpected model version", _state);
27137  nvars = ae_round(lm->w.ptr.p_double[2], _state);
27138  nclasses = ae_round(lm->w.ptr.p_double[3], _state);
27139  ae_vector_set_length(&workx, nvars-1+1, _state);
27140  ae_vector_set_length(&worky, nclasses-1+1, _state);
27141  result = 0;
27142  for(i=0; i<=npoints-1; i++)
27143  {
27144  ae_assert(ae_round(xy->ptr.pp_double[i][nvars], _state)>=0&&ae_round(xy->ptr.pp_double[i][nvars], _state)<nclasses, "MNLAvgCE: incorrect class number!", _state);
27145 
27146  /*
27147  * Process
27148  */
27149  ae_v_move(&workx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
27150  mnlprocess(lm, &workx, &worky, _state);
27151  if( ae_fp_greater(worky.ptr.p_double[ae_round(xy->ptr.pp_double[i][nvars], _state)],0) )
27152  {
27153  result = result-ae_log(worky.ptr.p_double[ae_round(xy->ptr.pp_double[i][nvars], _state)], _state);
27154  }
27155  else
27156  {
27157  result = result-ae_log(ae_minrealnumber, _state);
27158  }
27159  }
27160  result = result/(npoints*ae_log(2, _state));
27161  ae_frame_leave(_state);
27162  return result;
27163 }
27164 
27165 
27166 /*************************************************************************
27167 Relative classification error on the test set
27168 
27169 INPUT PARAMETERS:
27170  LM - logit model
27171  XY - test set
27172  NPoints - test set size
27173 
27174 RESULT:
27175  percent of incorrectly classified cases.
27176 
27177  -- ALGLIB --
27178  Copyright 10.09.2008 by Bochkanov Sergey
27179 *************************************************************************/
27180 double mnlrelclserror(logitmodel* lm,
27181  /* Real */ ae_matrix* xy,
27182  ae_int_t npoints,
27183  ae_state *_state)
27184 {
27185  double result;
27186 
27187 
27188  result = (double)mnlclserror(lm, xy, npoints, _state)/(double)npoints;
27189  return result;
27190 }
27191 
27192 
27193 /*************************************************************************
27194 RMS error on the test set
27195 
27196 INPUT PARAMETERS:
27197  LM - logit model
27198  XY - test set
27199  NPoints - test set size
27200 
27201 RESULT:
27202  root mean square error (error when estimating posterior probabilities).
27203 
27204  -- ALGLIB --
27205  Copyright 30.08.2008 by Bochkanov Sergey
27206 *************************************************************************/
27207 double mnlrmserror(logitmodel* lm,
27208  /* Real */ ae_matrix* xy,
27209  ae_int_t npoints,
27210  ae_state *_state)
27211 {
27212  double relcls;
27213  double avgce;
27214  double rms;
27215  double avg;
27216  double avgrel;
27217  double result;
27218 
27219 
27220  ae_assert(ae_round(lm->w.ptr.p_double[1], _state)==logit_logitvnum, "MNLRMSError: Incorrect MNL version!", _state);
27221  logit_mnlallerrors(lm, xy, npoints, &relcls, &avgce, &rms, &avg, &avgrel, _state);
27222  result = rms;
27223  return result;
27224 }
27225 
27226 
27227 /*************************************************************************
27228 Average error on the test set
27229 
27230 INPUT PARAMETERS:
27231  LM - logit model
27232  XY - test set
27233  NPoints - test set size
27234 
27235 RESULT:
27236  average error (error when estimating posterior probabilities).
27237 
27238  -- ALGLIB --
27239  Copyright 30.08.2008 by Bochkanov Sergey
27240 *************************************************************************/
27241 double mnlavgerror(logitmodel* lm,
27242  /* Real */ ae_matrix* xy,
27243  ae_int_t npoints,
27244  ae_state *_state)
27245 {
27246  double relcls;
27247  double avgce;
27248  double rms;
27249  double avg;
27250  double avgrel;
27251  double result;
27252 
27253 
27254  ae_assert(ae_round(lm->w.ptr.p_double[1], _state)==logit_logitvnum, "MNLRMSError: Incorrect MNL version!", _state);
27255  logit_mnlallerrors(lm, xy, npoints, &relcls, &avgce, &rms, &avg, &avgrel, _state);
27256  result = avg;
27257  return result;
27258 }
27259 
27260 
27261 /*************************************************************************
27262 Average relative error on the test set
27263 
27264 INPUT PARAMETERS:
27265  LM - logit model
27266  XY - test set
27267  NPoints - test set size
27268 
27269 RESULT:
27270  average relative error (error when estimating posterior probabilities).
27271 
27272  -- ALGLIB --
27273  Copyright 30.08.2008 by Bochkanov Sergey
27274 *************************************************************************/
27275 double mnlavgrelerror(logitmodel* lm,
27276  /* Real */ ae_matrix* xy,
27277  ae_int_t ssize,
27278  ae_state *_state)
27279 {
27280  double relcls;
27281  double avgce;
27282  double rms;
27283  double avg;
27284  double avgrel;
27285  double result;
27286 
27287 
27288  ae_assert(ae_round(lm->w.ptr.p_double[1], _state)==logit_logitvnum, "MNLRMSError: Incorrect MNL version!", _state);
27289  logit_mnlallerrors(lm, xy, ssize, &relcls, &avgce, &rms, &avg, &avgrel, _state);
27290  result = avgrel;
27291  return result;
27292 }
27293 
27294 
27295 /*************************************************************************
27296 Classification error on test set = MNLRelClsError*NPoints
27297 
27298  -- ALGLIB --
27299  Copyright 10.09.2008 by Bochkanov Sergey
27300 *************************************************************************/
27301 ae_int_t mnlclserror(logitmodel* lm,
27302  /* Real */ ae_matrix* xy,
27303  ae_int_t npoints,
27304  ae_state *_state)
27305 {
27306  ae_frame _frame_block;
27307  ae_int_t nvars;
27308  ae_int_t nclasses;
27309  ae_int_t i;
27310  ae_int_t j;
27311  ae_vector workx;
27312  ae_vector worky;
27313  ae_int_t nmax;
27314  ae_int_t result;
27315 
27316  ae_frame_make(_state, &_frame_block);
27317  ae_vector_init(&workx, 0, DT_REAL, _state, ae_true);
27318  ae_vector_init(&worky, 0, DT_REAL, _state, ae_true);
27319 
27320  ae_assert(ae_fp_eq(lm->w.ptr.p_double[1],logit_logitvnum), "MNLClsError: unexpected model version", _state);
27321  nvars = ae_round(lm->w.ptr.p_double[2], _state);
27322  nclasses = ae_round(lm->w.ptr.p_double[3], _state);
27323  ae_vector_set_length(&workx, nvars-1+1, _state);
27324  ae_vector_set_length(&worky, nclasses-1+1, _state);
27325  result = 0;
27326  for(i=0; i<=npoints-1; i++)
27327  {
27328 
27329  /*
27330  * Process
27331  */
27332  ae_v_move(&workx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
27333  mnlprocess(lm, &workx, &worky, _state);
27334 
27335  /*
27336  * Logit version of the answer
27337  */
27338  nmax = 0;
27339  for(j=0; j<=nclasses-1; j++)
27340  {
27341  if( ae_fp_greater(worky.ptr.p_double[j],worky.ptr.p_double[nmax]) )
27342  {
27343  nmax = j;
27344  }
27345  }
27346 
27347  /*
27348  * compare
27349  */
27350  if( nmax!=ae_round(xy->ptr.pp_double[i][nvars], _state) )
27351  {
27352  result = result+1;
27353  }
27354  }
27355  ae_frame_leave(_state);
27356  return result;
27357 }
27358 
27359 
27360 /*************************************************************************
27361 Internal subroutine. Places exponents of the anti-overflow shifted
27362 internal linear outputs into the service part of the W array.
27363 *************************************************************************/
27364 static void logit_mnliexp(/* Real */ ae_vector* w,
27365  /* Real */ ae_vector* x,
27366  ae_state *_state)
27367 {
27368  ae_int_t nvars;
27369  ae_int_t nclasses;
27370  ae_int_t offs;
27371  ae_int_t i;
27372  ae_int_t i1;
27373  double v;
27374  double mx;
27375 
27376 
27377  ae_assert(ae_fp_eq(w->ptr.p_double[1],logit_logitvnum), "LOGIT: unexpected model version", _state);
27378  nvars = ae_round(w->ptr.p_double[2], _state);
27379  nclasses = ae_round(w->ptr.p_double[3], _state);
27380  offs = ae_round(w->ptr.p_double[4], _state);
27381  i1 = offs+(nvars+1)*(nclasses-1);
27382  for(i=0; i<=nclasses-2; i++)
27383  {
27384  v = ae_v_dotproduct(&w->ptr.p_double[offs+i*(nvars+1)], 1, &x->ptr.p_double[0], 1, ae_v_len(offs+i*(nvars+1),offs+i*(nvars+1)+nvars-1));
27385  w->ptr.p_double[i1+i] = v+w->ptr.p_double[offs+i*(nvars+1)+nvars];
27386  }
27387  w->ptr.p_double[i1+nclasses-1] = 0;
27388  mx = 0;
27389  for(i=i1; i<=i1+nclasses-1; i++)
27390  {
27391  mx = ae_maxreal(mx, w->ptr.p_double[i], _state);
27392  }
27393  for(i=i1; i<=i1+nclasses-1; i++)
27394  {
27395  w->ptr.p_double[i] = ae_exp(w->ptr.p_double[i]-mx, _state);
27396  }
27397 }
27398 
27399 
27400 /*************************************************************************
27401 Calculation of all types of errors
27402 
27403  -- ALGLIB --
27404  Copyright 30.08.2008 by Bochkanov Sergey
27405 *************************************************************************/
27406 static void logit_mnlallerrors(logitmodel* lm,
27407  /* Real */ ae_matrix* xy,
27408  ae_int_t npoints,
27409  double* relcls,
27410  double* avgce,
27411  double* rms,
27412  double* avg,
27413  double* avgrel,
27414  ae_state *_state)
27415 {
27416  ae_frame _frame_block;
27417  ae_int_t nvars;
27418  ae_int_t nclasses;
27419  ae_int_t i;
27420  ae_vector buf;
27421  ae_vector workx;
27422  ae_vector y;
27423  ae_vector dy;
27424 
27425  ae_frame_make(_state, &_frame_block);
27426  *relcls = 0;
27427  *avgce = 0;
27428  *rms = 0;
27429  *avg = 0;
27430  *avgrel = 0;
27431  ae_vector_init(&buf, 0, DT_REAL, _state, ae_true);
27432  ae_vector_init(&workx, 0, DT_REAL, _state, ae_true);
27433  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
27434  ae_vector_init(&dy, 0, DT_REAL, _state, ae_true);
27435 
27436  ae_assert(ae_round(lm->w.ptr.p_double[1], _state)==logit_logitvnum, "MNL unit: Incorrect MNL version!", _state);
27437  nvars = ae_round(lm->w.ptr.p_double[2], _state);
27438  nclasses = ae_round(lm->w.ptr.p_double[3], _state);
27439  ae_vector_set_length(&workx, nvars-1+1, _state);
27440  ae_vector_set_length(&y, nclasses-1+1, _state);
27441  ae_vector_set_length(&dy, 0+1, _state);
27442  dserrallocate(nclasses, &buf, _state);
27443  for(i=0; i<=npoints-1; i++)
27444  {
27445  ae_v_move(&workx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
27446  mnlprocess(lm, &workx, &y, _state);
27447  dy.ptr.p_double[0] = xy->ptr.pp_double[i][nvars];
27448  dserraccumulate(&buf, &y, &dy, _state);
27449  }
27450  dserrfinish(&buf, _state);
27451  *relcls = buf.ptr.p_double[0];
27452  *avgce = buf.ptr.p_double[1];
27453  *rms = buf.ptr.p_double[2];
27454  *avg = buf.ptr.p_double[3];
27455  *avgrel = buf.ptr.p_double[4];
27456  ae_frame_leave(_state);
27457 }
27458 
27459 
27460 /*************************************************************************
27461 THE PURPOSE OF MCSRCH IS TO FIND A STEP WHICH SATISFIES A SUFFICIENT
27462 DECREASE CONDITION AND A CURVATURE CONDITION.
27463 
27464 AT EACH STAGE THE SUBROUTINE UPDATES AN INTERVAL OF UNCERTAINTY WITH
27465 ENDPOINTS STX AND STY. THE INTERVAL OF UNCERTAINTY IS INITIALLY CHOSEN
27466 SO THAT IT CONTAINS A MINIMIZER OF THE MODIFIED FUNCTION
27467 
27468  F(X+STP*S) - F(X) - FTOL*STP*(GRADF(X)'S).
27469 
27470 IF A STEP IS OBTAINED FOR WHICH THE MODIFIED FUNCTION HAS A NONPOSITIVE
27471 FUNCTION VALUE AND NONNEGATIVE DERIVATIVE, THEN THE INTERVAL OF
27472 UNCERTAINTY IS CHOSEN SO THAT IT CONTAINS A MINIMIZER OF F(X+STP*S).
27473 
27474 THE ALGORITHM IS DESIGNED TO FIND A STEP WHICH SATISFIES THE SUFFICIENT
27475 DECREASE CONDITION
27476 
27477  F(X+STP*S) .LE. F(X) + FTOL*STP*(GRADF(X)'S),
27478 
27479 AND THE CURVATURE CONDITION
27480 
27481  ABS(GRADF(X+STP*S)'S)) .LE. GTOL*ABS(GRADF(X)'S).
27482 
27483 IF FTOL IS LESS THAN GTOL AND IF, FOR EXAMPLE, THE FUNCTION IS BOUNDED
27484 BELOW, THEN THERE IS ALWAYS A STEP WHICH SATISFIES BOTH CONDITIONS.
27485 IF NO STEP CAN BE FOUND WHICH SATISFIES BOTH CONDITIONS, THEN THE
27486 ALGORITHM USUALLY STOPS WHEN ROUNDING ERRORS PREVENT FURTHER PROGRESS.
27487 IN THIS CASE STP ONLY SATISFIES THE SUFFICIENT DECREASE CONDITION.
27488 
27489 PARAMETERS DESCRIPRION
27490 
27491 N IS A POSITIVE INTEGER INPUT VARIABLE SET TO THE NUMBER OF VARIABLES.
27492 
27493 X IS AN ARRAY OF LENGTH N. ON INPUT IT MUST CONTAIN THE BASE POINT FOR
27494 THE LINE SEARCH. ON OUTPUT IT CONTAINS X+STP*S.
27495 
27496 F IS A VARIABLE. ON INPUT IT MUST CONTAIN THE VALUE OF F AT X. ON OUTPUT
27497 IT CONTAINS THE VALUE OF F AT X + STP*S.
27498 
27499 G IS AN ARRAY OF LENGTH N. ON INPUT IT MUST CONTAIN THE GRADIENT OF F AT X.
27500 ON OUTPUT IT CONTAINS THE GRADIENT OF F AT X + STP*S.
27501 
27502 S IS AN INPUT ARRAY OF LENGTH N WHICH SPECIFIES THE SEARCH DIRECTION.
27503 
27504 STP IS A NONNEGATIVE VARIABLE. ON INPUT STP CONTAINS AN INITIAL ESTIMATE
27505 OF A SATISFACTORY STEP. ON OUTPUT STP CONTAINS THE FINAL ESTIMATE.
27506 
27507 FTOL AND GTOL ARE NONNEGATIVE INPUT VARIABLES. TERMINATION OCCURS WHEN THE
27508 SUFFICIENT DECREASE CONDITION AND THE DIRECTIONAL DERIVATIVE CONDITION ARE
27509 SATISFIED.
27510 
27511 XTOL IS A NONNEGATIVE INPUT VARIABLE. TERMINATION OCCURS WHEN THE RELATIVE
27512 WIDTH OF THE INTERVAL OF UNCERTAINTY IS AT MOST XTOL.
27513 
27514 STPMIN AND STPMAX ARE NONNEGATIVE INPUT VARIABLES WHICH SPECIFY LOWER AND
27515 UPPER BOUNDS FOR THE STEP.
27516 
27517 MAXFEV IS A POSITIVE INTEGER INPUT VARIABLE. TERMINATION OCCURS WHEN THE
27518 NUMBER OF CALLS TO FCN IS AT LEAST MAXFEV BY THE END OF AN ITERATION.
27519 
27520 INFO IS AN INTEGER OUTPUT VARIABLE SET AS FOLLOWS:
27521  INFO = 0 IMPROPER INPUT PARAMETERS.
27522 
27523  INFO = 1 THE SUFFICIENT DECREASE CONDITION AND THE
27524  DIRECTIONAL DERIVATIVE CONDITION HOLD.
27525 
27526  INFO = 2 RELATIVE WIDTH OF THE INTERVAL OF UNCERTAINTY
27527  IS AT MOST XTOL.
27528 
27529  INFO = 3 NUMBER OF CALLS TO FCN HAS REACHED MAXFEV.
27530 
27531  INFO = 4 THE STEP IS AT THE LOWER BOUND STPMIN.
27532 
27533  INFO = 5 THE STEP IS AT THE UPPER BOUND STPMAX.
27534 
27535  INFO = 6 ROUNDING ERRORS PREVENT FURTHER PROGRESS.
27536  THERE MAY NOT BE A STEP WHICH SATISFIES THE
27537  SUFFICIENT DECREASE AND CURVATURE CONDITIONS.
27538  TOLERANCES MAY BE TOO SMALL.
27539 
27540 NFEV IS AN INTEGER OUTPUT VARIABLE SET TO THE NUMBER OF CALLS TO FCN.
27541 
27542 WA IS A WORK ARRAY OF LENGTH N.
27543 
27544 ARGONNE NATIONAL LABORATORY. MINPACK PROJECT. JUNE 1983
27545 JORGE J. MORE', DAVID J. THUENTE
27546 *************************************************************************/
27547 static void logit_mnlmcsrch(ae_int_t n,
27548  /* Real */ ae_vector* x,
27549  double* f,
27550  /* Real */ ae_vector* g,
27551  /* Real */ ae_vector* s,
27552  double* stp,
27553  ae_int_t* info,
27554  ae_int_t* nfev,
27555  /* Real */ ae_vector* wa,
27556  logitmcstate* state,
27557  ae_int_t* stage,
27558  ae_state *_state)
27559 {
27560  double v;
27561  double p5;
27562  double p66;
27563  double zero;
27564 
27565 
27566 
27567  /*
27568  * init
27569  */
27570  p5 = 0.5;
27571  p66 = 0.66;
27572  state->xtrapf = 4.0;
27573  zero = 0;
27574 
27575  /*
27576  * Main cycle
27577  */
27578  for(;;)
27579  {
27580  if( *stage==0 )
27581  {
27582 
27583  /*
27584  * NEXT
27585  */
27586  *stage = 2;
27587  continue;
27588  }
27589  if( *stage==2 )
27590  {
27591  state->infoc = 1;
27592  *info = 0;
27593 
27594  /*
27595  * CHECK THE INPUT PARAMETERS FOR ERRORS.
27596  */
27597  if( ((((((n<=0||ae_fp_less_eq(*stp,0))||ae_fp_less(logit_ftol,0))||ae_fp_less(logit_gtol,zero))||ae_fp_less(logit_xtol,zero))||ae_fp_less(logit_stpmin,zero))||ae_fp_less(logit_stpmax,logit_stpmin))||logit_maxfev<=0 )
27598  {
27599  *stage = 0;
27600  return;
27601  }
27602 
27603  /*
27604  * COMPUTE THE INITIAL GRADIENT IN THE SEARCH DIRECTION
27605  * AND CHECK THAT S IS A DESCENT DIRECTION.
27606  */
27607  v = ae_v_dotproduct(&g->ptr.p_double[0], 1, &s->ptr.p_double[0], 1, ae_v_len(0,n-1));
27608  state->dginit = v;
27609  if( ae_fp_greater_eq(state->dginit,0) )
27610  {
27611  *stage = 0;
27612  return;
27613  }
27614 
27615  /*
27616  * INITIALIZE LOCAL VARIABLES.
27617  */
27618  state->brackt = ae_false;
27619  state->stage1 = ae_true;
27620  *nfev = 0;
27621  state->finit = *f;
27622  state->dgtest = logit_ftol*state->dginit;
27623  state->width = logit_stpmax-logit_stpmin;
27624  state->width1 = state->width/p5;
27625  ae_v_move(&wa->ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
27626 
27627  /*
27628  * THE VARIABLES STX, FX, DGX CONTAIN THE VALUES OF THE STEP,
27629  * FUNCTION, AND DIRECTIONAL DERIVATIVE AT THE BEST STEP.
27630  * THE VARIABLES STY, FY, DGY CONTAIN THE VALUE OF THE STEP,
27631  * FUNCTION, AND DERIVATIVE AT THE OTHER ENDPOINT OF
27632  * THE INTERVAL OF UNCERTAINTY.
27633  * THE VARIABLES STP, F, DG CONTAIN THE VALUES OF THE STEP,
27634  * FUNCTION, AND DERIVATIVE AT THE CURRENT STEP.
27635  */
27636  state->stx = 0;
27637  state->fx = state->finit;
27638  state->dgx = state->dginit;
27639  state->sty = 0;
27640  state->fy = state->finit;
27641  state->dgy = state->dginit;
27642 
27643  /*
27644  * NEXT
27645  */
27646  *stage = 3;
27647  continue;
27648  }
27649  if( *stage==3 )
27650  {
27651 
27652  /*
27653  * START OF ITERATION.
27654  *
27655  * SET THE MINIMUM AND MAXIMUM STEPS TO CORRESPOND
27656  * TO THE PRESENT INTERVAL OF UNCERTAINTY.
27657  */
27658  if( state->brackt )
27659  {
27660  if( ae_fp_less(state->stx,state->sty) )
27661  {
27662  state->stmin = state->stx;
27663  state->stmax = state->sty;
27664  }
27665  else
27666  {
27667  state->stmin = state->sty;
27668  state->stmax = state->stx;
27669  }
27670  }
27671  else
27672  {
27673  state->stmin = state->stx;
27674  state->stmax = *stp+state->xtrapf*(*stp-state->stx);
27675  }
27676 
27677  /*
27678  * FORCE THE STEP TO BE WITHIN THE BOUNDS STPMAX AND STPMIN.
27679  */
27680  if( ae_fp_greater(*stp,logit_stpmax) )
27681  {
27682  *stp = logit_stpmax;
27683  }
27684  if( ae_fp_less(*stp,logit_stpmin) )
27685  {
27686  *stp = logit_stpmin;
27687  }
27688 
27689  /*
27690  * IF AN UNUSUAL TERMINATION IS TO OCCUR THEN LET
27691  * STP BE THE LOWEST POINT OBTAINED SO FAR.
27692  */
27693  if( (((state->brackt&&(ae_fp_less_eq(*stp,state->stmin)||ae_fp_greater_eq(*stp,state->stmax)))||*nfev>=logit_maxfev-1)||state->infoc==0)||(state->brackt&&ae_fp_less_eq(state->stmax-state->stmin,logit_xtol*state->stmax)) )
27694  {
27695  *stp = state->stx;
27696  }
27697 
27698  /*
27699  * EVALUATE THE FUNCTION AND GRADIENT AT STP
27700  * AND COMPUTE THE DIRECTIONAL DERIVATIVE.
27701  */
27702  ae_v_move(&x->ptr.p_double[0], 1, &wa->ptr.p_double[0], 1, ae_v_len(0,n-1));
27703  ae_v_addd(&x->ptr.p_double[0], 1, &s->ptr.p_double[0], 1, ae_v_len(0,n-1), *stp);
27704 
27705  /*
27706  * NEXT
27707  */
27708  *stage = 4;
27709  return;
27710  }
27711  if( *stage==4 )
27712  {
27713  *info = 0;
27714  *nfev = *nfev+1;
27715  v = ae_v_dotproduct(&g->ptr.p_double[0], 1, &s->ptr.p_double[0], 1, ae_v_len(0,n-1));
27716  state->dg = v;
27717  state->ftest1 = state->finit+*stp*state->dgtest;
27718 
27719  /*
27720  * TEST FOR CONVERGENCE.
27721  */
27722  if( (state->brackt&&(ae_fp_less_eq(*stp,state->stmin)||ae_fp_greater_eq(*stp,state->stmax)))||state->infoc==0 )
27723  {
27724  *info = 6;
27725  }
27726  if( (ae_fp_eq(*stp,logit_stpmax)&&ae_fp_less_eq(*f,state->ftest1))&&ae_fp_less_eq(state->dg,state->dgtest) )
27727  {
27728  *info = 5;
27729  }
27730  if( ae_fp_eq(*stp,logit_stpmin)&&(ae_fp_greater(*f,state->ftest1)||ae_fp_greater_eq(state->dg,state->dgtest)) )
27731  {
27732  *info = 4;
27733  }
27734  if( *nfev>=logit_maxfev )
27735  {
27736  *info = 3;
27737  }
27738  if( state->brackt&&ae_fp_less_eq(state->stmax-state->stmin,logit_xtol*state->stmax) )
27739  {
27740  *info = 2;
27741  }
27742  if( ae_fp_less_eq(*f,state->ftest1)&&ae_fp_less_eq(ae_fabs(state->dg, _state),-logit_gtol*state->dginit) )
27743  {
27744  *info = 1;
27745  }
27746 
27747  /*
27748  * CHECK FOR TERMINATION.
27749  */
27750  if( *info!=0 )
27751  {
27752  *stage = 0;
27753  return;
27754  }
27755 
27756  /*
27757  * IN THE FIRST STAGE WE SEEK A STEP FOR WHICH THE MODIFIED
27758  * FUNCTION HAS A NONPOSITIVE VALUE AND NONNEGATIVE DERIVATIVE.
27759  */
27760  if( (state->stage1&&ae_fp_less_eq(*f,state->ftest1))&&ae_fp_greater_eq(state->dg,ae_minreal(logit_ftol, logit_gtol, _state)*state->dginit) )
27761  {
27762  state->stage1 = ae_false;
27763  }
27764 
27765  /*
27766  * A MODIFIED FUNCTION IS USED TO PREDICT THE STEP ONLY IF
27767  * WE HAVE NOT OBTAINED A STEP FOR WHICH THE MODIFIED
27768  * FUNCTION HAS A NONPOSITIVE FUNCTION VALUE AND NONNEGATIVE
27769  * DERIVATIVE, AND IF A LOWER FUNCTION VALUE HAS BEEN
27770  * OBTAINED BUT THE DECREASE IS NOT SUFFICIENT.
27771  */
27772  if( (state->stage1&&ae_fp_less_eq(*f,state->fx))&&ae_fp_greater(*f,state->ftest1) )
27773  {
27774 
27775  /*
27776  * DEFINE THE MODIFIED FUNCTION AND DERIVATIVE VALUES.
27777  */
27778  state->fm = *f-*stp*state->dgtest;
27779  state->fxm = state->fx-state->stx*state->dgtest;
27780  state->fym = state->fy-state->sty*state->dgtest;
27781  state->dgm = state->dg-state->dgtest;
27782  state->dgxm = state->dgx-state->dgtest;
27783  state->dgym = state->dgy-state->dgtest;
27784 
27785  /*
27786  * CALL CSTEP TO UPDATE THE INTERVAL OF UNCERTAINTY
27787  * AND TO COMPUTE THE NEW STEP.
27788  */
27789  logit_mnlmcstep(&state->stx, &state->fxm, &state->dgxm, &state->sty, &state->fym, &state->dgym, stp, state->fm, state->dgm, &state->brackt, state->stmin, state->stmax, &state->infoc, _state);
27790 
27791  /*
27792  * RESET THE FUNCTION AND GRADIENT VALUES FOR F.
27793  */
27794  state->fx = state->fxm+state->stx*state->dgtest;
27795  state->fy = state->fym+state->sty*state->dgtest;
27796  state->dgx = state->dgxm+state->dgtest;
27797  state->dgy = state->dgym+state->dgtest;
27798  }
27799  else
27800  {
27801 
27802  /*
27803  * CALL MCSTEP TO UPDATE THE INTERVAL OF UNCERTAINTY
27804  * AND TO COMPUTE THE NEW STEP.
27805  */
27806  logit_mnlmcstep(&state->stx, &state->fx, &state->dgx, &state->sty, &state->fy, &state->dgy, stp, *f, state->dg, &state->brackt, state->stmin, state->stmax, &state->infoc, _state);
27807  }
27808 
27809  /*
27810  * FORCE A SUFFICIENT DECREASE IN THE SIZE OF THE
27811  * INTERVAL OF UNCERTAINTY.
27812  */
27813  if( state->brackt )
27814  {
27815  if( ae_fp_greater_eq(ae_fabs(state->sty-state->stx, _state),p66*state->width1) )
27816  {
27817  *stp = state->stx+p5*(state->sty-state->stx);
27818  }
27819  state->width1 = state->width;
27820  state->width = ae_fabs(state->sty-state->stx, _state);
27821  }
27822 
27823  /*
27824  * NEXT.
27825  */
27826  *stage = 3;
27827  continue;
27828  }
27829  }
27830 }
27831 
27832 
27833 static void logit_mnlmcstep(double* stx,
27834  double* fx,
27835  double* dx,
27836  double* sty,
27837  double* fy,
27838  double* dy,
27839  double* stp,
27840  double fp,
27841  double dp,
27842  ae_bool* brackt,
27843  double stmin,
27844  double stmax,
27845  ae_int_t* info,
27846  ae_state *_state)
27847 {
27848  ae_bool bound;
27849  double gamma;
27850  double p;
27851  double q;
27852  double r;
27853  double s;
27854  double sgnd;
27855  double stpc;
27856  double stpf;
27857  double stpq;
27858  double theta;
27859 
27860 
27861  *info = 0;
27862 
27863  /*
27864  * CHECK THE INPUT PARAMETERS FOR ERRORS.
27865  */
27866  if( ((*brackt&&(ae_fp_less_eq(*stp,ae_minreal(*stx, *sty, _state))||ae_fp_greater_eq(*stp,ae_maxreal(*stx, *sty, _state))))||ae_fp_greater_eq(*dx*(*stp-(*stx)),0))||ae_fp_less(stmax,stmin) )
27867  {
27868  return;
27869  }
27870 
27871  /*
27872  * DETERMINE IF THE DERIVATIVES HAVE OPPOSITE SIGN.
27873  */
27874  sgnd = dp*(*dx/ae_fabs(*dx, _state));
27875 
27876  /*
27877  * FIRST CASE. A HIGHER FUNCTION VALUE.
27878  * THE MINIMUM IS BRACKETED. IF THE CUBIC STEP IS CLOSER
27879  * TO STX THAN THE QUADRATIC STEP, THE CUBIC STEP IS TAKEN,
27880  * ELSE THE AVERAGE OF THE CUBIC AND QUADRATIC STEPS IS TAKEN.
27881  */
27882  if( ae_fp_greater(fp,*fx) )
27883  {
27884  *info = 1;
27885  bound = ae_true;
27886  theta = 3*(*fx-fp)/(*stp-(*stx))+(*dx)+dp;
27887  s = ae_maxreal(ae_fabs(theta, _state), ae_maxreal(ae_fabs(*dx, _state), ae_fabs(dp, _state), _state), _state);
27888  gamma = s*ae_sqrt(ae_sqr(theta/s, _state)-*dx/s*(dp/s), _state);
27889  if( ae_fp_less(*stp,*stx) )
27890  {
27891  gamma = -gamma;
27892  }
27893  p = gamma-(*dx)+theta;
27894  q = gamma-(*dx)+gamma+dp;
27895  r = p/q;
27896  stpc = *stx+r*(*stp-(*stx));
27897  stpq = *stx+*dx/((*fx-fp)/(*stp-(*stx))+(*dx))/2*(*stp-(*stx));
27898  if( ae_fp_less(ae_fabs(stpc-(*stx), _state),ae_fabs(stpq-(*stx), _state)) )
27899  {
27900  stpf = stpc;
27901  }
27902  else
27903  {
27904  stpf = stpc+(stpq-stpc)/2;
27905  }
27906  *brackt = ae_true;
27907  }
27908  else
27909  {
27910  if( ae_fp_less(sgnd,0) )
27911  {
27912 
27913  /*
27914  * SECOND CASE. A LOWER FUNCTION VALUE AND DERIVATIVES OF
27915  * OPPOSITE SIGN. THE MINIMUM IS BRACKETED. IF THE CUBIC
27916  * STEP IS CLOSER TO STX THAN THE QUADRATIC (SECANT) STEP,
27917  * THE CUBIC STEP IS TAKEN, ELSE THE QUADRATIC STEP IS TAKEN.
27918  */
27919  *info = 2;
27920  bound = ae_false;
27921  theta = 3*(*fx-fp)/(*stp-(*stx))+(*dx)+dp;
27922  s = ae_maxreal(ae_fabs(theta, _state), ae_maxreal(ae_fabs(*dx, _state), ae_fabs(dp, _state), _state), _state);
27923  gamma = s*ae_sqrt(ae_sqr(theta/s, _state)-*dx/s*(dp/s), _state);
27924  if( ae_fp_greater(*stp,*stx) )
27925  {
27926  gamma = -gamma;
27927  }
27928  p = gamma-dp+theta;
27929  q = gamma-dp+gamma+(*dx);
27930  r = p/q;
27931  stpc = *stp+r*(*stx-(*stp));
27932  stpq = *stp+dp/(dp-(*dx))*(*stx-(*stp));
27933  if( ae_fp_greater(ae_fabs(stpc-(*stp), _state),ae_fabs(stpq-(*stp), _state)) )
27934  {
27935  stpf = stpc;
27936  }
27937  else
27938  {
27939  stpf = stpq;
27940  }
27941  *brackt = ae_true;
27942  }
27943  else
27944  {
27945  if( ae_fp_less(ae_fabs(dp, _state),ae_fabs(*dx, _state)) )
27946  {
27947 
27948  /*
27949  * THIRD CASE. A LOWER FUNCTION VALUE, DERIVATIVES OF THE
27950  * SAME SIGN, AND THE MAGNITUDE OF THE DERIVATIVE DECREASES.
27951  * THE CUBIC STEP IS ONLY USED IF THE CUBIC TENDS TO INFINITY
27952  * IN THE DIRECTION OF THE STEP OR IF THE MINIMUM OF THE CUBIC
27953  * IS BEYOND STP. OTHERWISE THE CUBIC STEP IS DEFINED TO BE
27954  * EITHER STPMIN OR STPMAX. THE QUADRATIC (SECANT) STEP IS ALSO
27955  * COMPUTED AND IF THE MINIMUM IS BRACKETED THEN THE THE STEP
27956  * CLOSEST TO STX IS TAKEN, ELSE THE STEP FARTHEST AWAY IS TAKEN.
27957  */
27958  *info = 3;
27959  bound = ae_true;
27960  theta = 3*(*fx-fp)/(*stp-(*stx))+(*dx)+dp;
27961  s = ae_maxreal(ae_fabs(theta, _state), ae_maxreal(ae_fabs(*dx, _state), ae_fabs(dp, _state), _state), _state);
27962 
27963  /*
27964  * THE CASE GAMMA = 0 ONLY ARISES IF THE CUBIC DOES NOT TEND
27965  * TO INFINITY IN THE DIRECTION OF THE STEP.
27966  */
27967  gamma = s*ae_sqrt(ae_maxreal(0, ae_sqr(theta/s, _state)-*dx/s*(dp/s), _state), _state);
27968  if( ae_fp_greater(*stp,*stx) )
27969  {
27970  gamma = -gamma;
27971  }
27972  p = gamma-dp+theta;
27973  q = gamma+(*dx-dp)+gamma;
27974  r = p/q;
27975  if( ae_fp_less(r,0)&&ae_fp_neq(gamma,0) )
27976  {
27977  stpc = *stp+r*(*stx-(*stp));
27978  }
27979  else
27980  {
27981  if( ae_fp_greater(*stp,*stx) )
27982  {
27983  stpc = stmax;
27984  }
27985  else
27986  {
27987  stpc = stmin;
27988  }
27989  }
27990  stpq = *stp+dp/(dp-(*dx))*(*stx-(*stp));
27991  if( *brackt )
27992  {
27993  if( ae_fp_less(ae_fabs(*stp-stpc, _state),ae_fabs(*stp-stpq, _state)) )
27994  {
27995  stpf = stpc;
27996  }
27997  else
27998  {
27999  stpf = stpq;
28000  }
28001  }
28002  else
28003  {
28004  if( ae_fp_greater(ae_fabs(*stp-stpc, _state),ae_fabs(*stp-stpq, _state)) )
28005  {
28006  stpf = stpc;
28007  }
28008  else
28009  {
28010  stpf = stpq;
28011  }
28012  }
28013  }
28014  else
28015  {
28016 
28017  /*
28018  * FOURTH CASE. A LOWER FUNCTION VALUE, DERIVATIVES OF THE
28019  * SAME SIGN, AND THE MAGNITUDE OF THE DERIVATIVE DOES
28020  * NOT DECREASE. IF THE MINIMUM IS NOT BRACKETED, THE STEP
28021  * IS EITHER STPMIN OR STPMAX, ELSE THE CUBIC STEP IS TAKEN.
28022  */
28023  *info = 4;
28024  bound = ae_false;
28025  if( *brackt )
28026  {
28027  theta = 3*(fp-(*fy))/(*sty-(*stp))+(*dy)+dp;
28028  s = ae_maxreal(ae_fabs(theta, _state), ae_maxreal(ae_fabs(*dy, _state), ae_fabs(dp, _state), _state), _state);
28029  gamma = s*ae_sqrt(ae_sqr(theta/s, _state)-*dy/s*(dp/s), _state);
28030  if( ae_fp_greater(*stp,*sty) )
28031  {
28032  gamma = -gamma;
28033  }
28034  p = gamma-dp+theta;
28035  q = gamma-dp+gamma+(*dy);
28036  r = p/q;
28037  stpc = *stp+r*(*sty-(*stp));
28038  stpf = stpc;
28039  }
28040  else
28041  {
28042  if( ae_fp_greater(*stp,*stx) )
28043  {
28044  stpf = stmax;
28045  }
28046  else
28047  {
28048  stpf = stmin;
28049  }
28050  }
28051  }
28052  }
28053  }
28054 
28055  /*
28056  * UPDATE THE INTERVAL OF UNCERTAINTY. THIS UPDATE DOES NOT
28057  * DEPEND ON THE NEW STEP OR THE CASE ANALYSIS ABOVE.
28058  */
28059  if( ae_fp_greater(fp,*fx) )
28060  {
28061  *sty = *stp;
28062  *fy = fp;
28063  *dy = dp;
28064  }
28065  else
28066  {
28067  if( ae_fp_less(sgnd,0.0) )
28068  {
28069  *sty = *stx;
28070  *fy = *fx;
28071  *dy = *dx;
28072  }
28073  *stx = *stp;
28074  *fx = fp;
28075  *dx = dp;
28076  }
28077 
28078  /*
28079  * COMPUTE THE NEW STEP AND SAFEGUARD IT.
28080  */
28081  stpf = ae_minreal(stmax, stpf, _state);
28082  stpf = ae_maxreal(stmin, stpf, _state);
28083  *stp = stpf;
28084  if( *brackt&&bound )
28085  {
28086  if( ae_fp_greater(*sty,*stx) )
28087  {
28088  *stp = ae_minreal(*stx+0.66*(*sty-(*stx)), *stp, _state);
28089  }
28090  else
28091  {
28092  *stp = ae_maxreal(*stx+0.66*(*sty-(*stx)), *stp, _state);
28093  }
28094  }
28095 }
28096 
28097 
28098 ae_bool _logitmodel_init(void* _p, ae_state *_state, ae_bool make_automatic)
28099 {
28100  logitmodel *p = (logitmodel*)_p;
28101  ae_touch_ptr((void*)p);
28102  if( !ae_vector_init(&p->w, 0, DT_REAL, _state, make_automatic) )
28103  return ae_false;
28104  return ae_true;
28105 }
28106 
28107 
28108 ae_bool _logitmodel_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
28109 {
28110  logitmodel *dst = (logitmodel*)_dst;
28111  logitmodel *src = (logitmodel*)_src;
28112  if( !ae_vector_init_copy(&dst->w, &src->w, _state, make_automatic) )
28113  return ae_false;
28114  return ae_true;
28115 }
28116 
28117 
28118 void _logitmodel_clear(void* _p)
28119 {
28120  logitmodel *p = (logitmodel*)_p;
28121  ae_touch_ptr((void*)p);
28122  ae_vector_clear(&p->w);
28123 }
28124 
28125 
28126 void _logitmodel_destroy(void* _p)
28127 {
28128  logitmodel *p = (logitmodel*)_p;
28129  ae_touch_ptr((void*)p);
28130  ae_vector_destroy(&p->w);
28131 }
28132 
28133 
28134 ae_bool _logitmcstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
28135 {
28136  logitmcstate *p = (logitmcstate*)_p;
28137  ae_touch_ptr((void*)p);
28138  return ae_true;
28139 }
28140 
28141 
28142 ae_bool _logitmcstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
28143 {
28144  logitmcstate *dst = (logitmcstate*)_dst;
28145  logitmcstate *src = (logitmcstate*)_src;
28146  dst->brackt = src->brackt;
28147  dst->stage1 = src->stage1;
28148  dst->infoc = src->infoc;
28149  dst->dg = src->dg;
28150  dst->dgm = src->dgm;
28151  dst->dginit = src->dginit;
28152  dst->dgtest = src->dgtest;
28153  dst->dgx = src->dgx;
28154  dst->dgxm = src->dgxm;
28155  dst->dgy = src->dgy;
28156  dst->dgym = src->dgym;
28157  dst->finit = src->finit;
28158  dst->ftest1 = src->ftest1;
28159  dst->fm = src->fm;
28160  dst->fx = src->fx;
28161  dst->fxm = src->fxm;
28162  dst->fy = src->fy;
28163  dst->fym = src->fym;
28164  dst->stx = src->stx;
28165  dst->sty = src->sty;
28166  dst->stmin = src->stmin;
28167  dst->stmax = src->stmax;
28168  dst->width = src->width;
28169  dst->width1 = src->width1;
28170  dst->xtrapf = src->xtrapf;
28171  return ae_true;
28172 }
28173 
28174 
28175 void _logitmcstate_clear(void* _p)
28176 {
28177  logitmcstate *p = (logitmcstate*)_p;
28178  ae_touch_ptr((void*)p);
28179 }
28180 
28181 
28182 void _logitmcstate_destroy(void* _p)
28183 {
28184  logitmcstate *p = (logitmcstate*)_p;
28185  ae_touch_ptr((void*)p);
28186 }
28187 
28188 
28189 ae_bool _mnlreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
28190 {
28191  mnlreport *p = (mnlreport*)_p;
28192  ae_touch_ptr((void*)p);
28193  return ae_true;
28194 }
28195 
28196 
28197 ae_bool _mnlreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
28198 {
28199  mnlreport *dst = (mnlreport*)_dst;
28200  mnlreport *src = (mnlreport*)_src;
28201  dst->ngrad = src->ngrad;
28202  dst->nhess = src->nhess;
28203  return ae_true;
28204 }
28205 
28206 
28207 void _mnlreport_clear(void* _p)
28208 {
28209  mnlreport *p = (mnlreport*)_p;
28210  ae_touch_ptr((void*)p);
28211 }
28212 
28213 
28214 void _mnlreport_destroy(void* _p)
28215 {
28216  mnlreport *p = (mnlreport*)_p;
28217  ae_touch_ptr((void*)p);
28218 }
28219 
28220 
28221 
28222 
28223 /*************************************************************************
28224 DESCRIPTION:
28225 
28226 This function creates MCPD (Markov Chains for Population Data) solver.
28227 
28228 This solver can be used to find transition matrix P for N-dimensional
28229 prediction problem where transition from X[i] to X[i+1] is modelled as
28230  X[i+1] = P*X[i]
28231 where X[i] and X[i+1] are N-dimensional population vectors (components of
28232 each X are non-negative), and P is a N*N transition matrix (elements of P
28233 are non-negative, each column sums to 1.0).
28234 
28235 Such models arise when when:
28236 * there is some population of individuals
28237 * individuals can have different states
28238 * individuals can transit from one state to another
28239 * population size is constant, i.e. there is no new individuals and no one
28240  leaves population
28241 * you want to model transitions of individuals from one state into another
28242 
28243 USAGE:
28244 
28245 Here we give very brief outline of the MCPD. We strongly recommend you to
28246 read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide
28247 on data analysis which is available at http://www.alglib.net/dataanalysis/
28248 
28249 1. User initializes algorithm state with MCPDCreate() call
28250 
28251 2. User adds one or more tracks - sequences of states which describe
28252  evolution of a system being modelled from different starting conditions
28253 
28254 3. User may add optional boundary, equality and/or linear constraints on
28255  the coefficients of P by calling one of the following functions:
28256  * MCPDSetEC() to set equality constraints
28257  * MCPDSetBC() to set bound constraints
28258  * MCPDSetLC() to set linear constraints
28259 
28260 4. Optionally, user may set custom weights for prediction errors (by
28261  default, algorithm assigns non-equal, automatically chosen weights for
28262  errors in the prediction of different components of X). It can be done
28263  with a call of MCPDSetPredictionWeights() function.
28264 
28265 5. User calls MCPDSolve() function which takes algorithm state and
28266  pointer (delegate, etc.) to callback function which calculates F/G.
28267 
28268 6. User calls MCPDResults() to get solution
28269 
28270 INPUT PARAMETERS:
28271  N - problem dimension, N>=1
28272 
28273 OUTPUT PARAMETERS:
28274  State - structure stores algorithm state
28275 
28276  -- ALGLIB --
28277  Copyright 23.05.2010 by Bochkanov Sergey
28278 *************************************************************************/
28279 void mcpdcreate(ae_int_t n, mcpdstate* s, ae_state *_state)
28280 {
28281 
28282  _mcpdstate_clear(s);
28283 
28284  ae_assert(n>=1, "MCPDCreate: N<1", _state);
28285  mcpd_mcpdinit(n, -1, -1, s, _state);
28286 }
28287 
28288 
28289 /*************************************************************************
28290 DESCRIPTION:
28291 
28292 This function is a specialized version of MCPDCreate() function, and we
28293 recommend you to read comments for this function for general information
28294 about MCPD solver.
28295 
28296 This function creates MCPD (Markov Chains for Population Data) solver
28297 for "Entry-state" model, i.e. model where transition from X[i] to X[i+1]
28298 is modelled as
28299  X[i+1] = P*X[i]
28300 where
28301  X[i] and X[i+1] are N-dimensional state vectors
28302  P is a N*N transition matrix
28303 and one selected component of X[] is called "entry" state and is treated
28304 in a special way:
28305  system state always transits from "entry" state to some another state
28306  system state can not transit from any state into "entry" state
28307 Such conditions basically mean that row of P which corresponds to "entry"
28308 state is zero.
28309 
28310 Such models arise when:
28311 * there is some population of individuals
28312 * individuals can have different states
28313 * individuals can transit from one state to another
28314 * population size is NOT constant - at every moment of time there is some
28315  (unpredictable) amount of "new" individuals, which can transit into one
28316  of the states at the next turn, but still no one leaves population
28317 * you want to model transitions of individuals from one state into another
28318 * but you do NOT want to predict amount of "new" individuals because it
28319  does not depends on individuals already present (hence system can not
28320  transit INTO entry state - it can only transit FROM it).
28321 
28322 This model is discussed in more details in the ALGLIB User Guide (see
28323 http://www.alglib.net/dataanalysis/ for more data).
28324 
28325 INPUT PARAMETERS:
28326  N - problem dimension, N>=2
28327  EntryState- index of entry state, in 0..N-1
28328 
28329 OUTPUT PARAMETERS:
28330  State - structure stores algorithm state
28331 
28332  -- ALGLIB --
28333  Copyright 23.05.2010 by Bochkanov Sergey
28334 *************************************************************************/
28335 void mcpdcreateentry(ae_int_t n,
28336  ae_int_t entrystate,
28337  mcpdstate* s,
28338  ae_state *_state)
28339 {
28340 
28341  _mcpdstate_clear(s);
28342 
28343  ae_assert(n>=2, "MCPDCreateEntry: N<2", _state);
28344  ae_assert(entrystate>=0, "MCPDCreateEntry: EntryState<0", _state);
28345  ae_assert(entrystate<n, "MCPDCreateEntry: EntryState>=N", _state);
28346  mcpd_mcpdinit(n, entrystate, -1, s, _state);
28347 }
28348 
28349 
28350 /*************************************************************************
28351 DESCRIPTION:
28352 
28353 This function is a specialized version of MCPDCreate() function, and we
28354 recommend you to read comments for this function for general information
28355 about MCPD solver.
28356 
28357 This function creates MCPD (Markov Chains for Population Data) solver
28358 for "Exit-state" model, i.e. model where transition from X[i] to X[i+1]
28359 is modelled as
28360  X[i+1] = P*X[i]
28361 where
28362  X[i] and X[i+1] are N-dimensional state vectors
28363  P is a N*N transition matrix
28364 and one selected component of X[] is called "exit" state and is treated
28365 in a special way:
28366  system state can transit from any state into "exit" state
28367  system state can not transit from "exit" state into any other state
28368  transition operator discards "exit" state (makes it zero at each turn)
28369 Such conditions basically mean that column of P which corresponds to
28370 "exit" state is zero. Multiplication by such P may decrease sum of vector
28371 components.
28372 
28373 Such models arise when:
28374 * there is some population of individuals
28375 * individuals can have different states
28376 * individuals can transit from one state to another
28377 * population size is NOT constant - individuals can move into "exit" state
28378  and leave population at the next turn, but there are no new individuals
28379 * amount of individuals which leave population can be predicted
28380 * you want to model transitions of individuals from one state into another
28381  (including transitions into the "exit" state)
28382 
28383 This model is discussed in more details in the ALGLIB User Guide (see
28384 http://www.alglib.net/dataanalysis/ for more data).
28385 
28386 INPUT PARAMETERS:
28387  N - problem dimension, N>=2
28388  ExitState- index of exit state, in 0..N-1
28389 
28390 OUTPUT PARAMETERS:
28391  State - structure stores algorithm state
28392 
28393  -- ALGLIB --
28394  Copyright 23.05.2010 by Bochkanov Sergey
28395 *************************************************************************/
28396 void mcpdcreateexit(ae_int_t n,
28397  ae_int_t exitstate,
28398  mcpdstate* s,
28399  ae_state *_state)
28400 {
28401 
28402  _mcpdstate_clear(s);
28403 
28404  ae_assert(n>=2, "MCPDCreateExit: N<2", _state);
28405  ae_assert(exitstate>=0, "MCPDCreateExit: ExitState<0", _state);
28406  ae_assert(exitstate<n, "MCPDCreateExit: ExitState>=N", _state);
28407  mcpd_mcpdinit(n, -1, exitstate, s, _state);
28408 }
28409 
28410 
28411 /*************************************************************************
28412 DESCRIPTION:
28413 
28414 This function is a specialized version of MCPDCreate() function, and we
28415 recommend you to read comments for this function for general information
28416 about MCPD solver.
28417 
28418 This function creates MCPD (Markov Chains for Population Data) solver
28419 for "Entry-Exit-states" model, i.e. model where transition from X[i] to
28420 X[i+1] is modelled as
28421  X[i+1] = P*X[i]
28422 where
28423  X[i] and X[i+1] are N-dimensional state vectors
28424  P is a N*N transition matrix
28425 one selected component of X[] is called "entry" state and is treated in a
28426 special way:
28427  system state always transits from "entry" state to some another state
28428  system state can not transit from any state into "entry" state
28429 and another one component of X[] is called "exit" state and is treated in
28430 a special way too:
28431  system state can transit from any state into "exit" state
28432  system state can not transit from "exit" state into any other state
28433  transition operator discards "exit" state (makes it zero at each turn)
28434 Such conditions basically mean that:
28435  row of P which corresponds to "entry" state is zero
28436  column of P which corresponds to "exit" state is zero
28437 Multiplication by such P may decrease sum of vector components.
28438 
28439 Such models arise when:
28440 * there is some population of individuals
28441 * individuals can have different states
28442 * individuals can transit from one state to another
28443 * population size is NOT constant
28444 * at every moment of time there is some (unpredictable) amount of "new"
28445  individuals, which can transit into one of the states at the next turn
28446 * some individuals can move (predictably) into "exit" state and leave
28447  population at the next turn
28448 * you want to model transitions of individuals from one state into another,
28449  including transitions from the "entry" state and into the "exit" state.
28450 * but you do NOT want to predict amount of "new" individuals because it
28451  does not depends on individuals already present (hence system can not
28452  transit INTO entry state - it can only transit FROM it).
28453 
28454 This model is discussed in more details in the ALGLIB User Guide (see
28455 http://www.alglib.net/dataanalysis/ for more data).
28456 
28457 INPUT PARAMETERS:
28458  N - problem dimension, N>=2
28459  EntryState- index of entry state, in 0..N-1
28460  ExitState- index of exit state, in 0..N-1
28461 
28462 OUTPUT PARAMETERS:
28463  State - structure stores algorithm state
28464 
28465  -- ALGLIB --
28466  Copyright 23.05.2010 by Bochkanov Sergey
28467 *************************************************************************/
28468 void mcpdcreateentryexit(ae_int_t n,
28469  ae_int_t entrystate,
28470  ae_int_t exitstate,
28471  mcpdstate* s,
28472  ae_state *_state)
28473 {
28474 
28475  _mcpdstate_clear(s);
28476 
28477  ae_assert(n>=2, "MCPDCreateEntryExit: N<2", _state);
28478  ae_assert(entrystate>=0, "MCPDCreateEntryExit: EntryState<0", _state);
28479  ae_assert(entrystate<n, "MCPDCreateEntryExit: EntryState>=N", _state);
28480  ae_assert(exitstate>=0, "MCPDCreateEntryExit: ExitState<0", _state);
28481  ae_assert(exitstate<n, "MCPDCreateEntryExit: ExitState>=N", _state);
28482  ae_assert(entrystate!=exitstate, "MCPDCreateEntryExit: EntryState=ExitState", _state);
28483  mcpd_mcpdinit(n, entrystate, exitstate, s, _state);
28484 }
28485 
28486 
28487 /*************************************************************************
28488 This function is used to add a track - sequence of system states at the
28489 different moments of its evolution.
28490 
28491 You may add one or several tracks to the MCPD solver. In case you have
28492 several tracks, they won't overwrite each other. For example, if you pass
28493 two tracks, A1-A2-A3 (system at t=A+1, t=A+2 and t=A+3) and B1-B2-B3, then
28494 solver will try to model transitions from t=A+1 to t=A+2, t=A+2 to t=A+3,
28495 t=B+1 to t=B+2, t=B+2 to t=B+3. But it WON'T mix these two tracks - i.e. it
28496 won't try to model transition from t=A+3 to t=B+1.
28497 
28498 INPUT PARAMETERS:
28499  S - solver
28500  XY - track, array[K,N]:
28501  * I-th row is a state at t=I
28502  * elements of XY must be non-negative (exception will be
28503  thrown on negative elements)
28504  K - number of points in a track
28505  * if given, only leading K rows of XY are used
28506  * if not given, automatically determined from size of XY
28507 
28508 NOTES:
28509 
28510 1. Track may contain either proportional or population data:
28511  * with proportional data all rows of XY must sum to 1.0, i.e. we have
28512  proportions instead of absolute population values
28513  * with population data rows of XY contain population counts and generally
28514  do not sum to 1.0 (although they still must be non-negative)
28515 
28516  -- ALGLIB --
28517  Copyright 23.05.2010 by Bochkanov Sergey
28518 *************************************************************************/
28519 void mcpdaddtrack(mcpdstate* s,
28520  /* Real */ ae_matrix* xy,
28521  ae_int_t k,
28522  ae_state *_state)
28523 {
28524  ae_int_t i;
28525  ae_int_t j;
28526  ae_int_t n;
28527  double s0;
28528  double s1;
28529 
28530 
28531  n = s->n;
28532  ae_assert(k>=0, "MCPDAddTrack: K<0", _state);
28533  ae_assert(xy->cols>=n, "MCPDAddTrack: Cols(XY)<N", _state);
28534  ae_assert(xy->rows>=k, "MCPDAddTrack: Rows(XY)<K", _state);
28535  ae_assert(apservisfinitematrix(xy, k, n, _state), "MCPDAddTrack: XY contains infinite or NaN elements", _state);
28536  for(i=0; i<=k-1; i++)
28537  {
28538  for(j=0; j<=n-1; j++)
28539  {
28540  ae_assert(ae_fp_greater_eq(xy->ptr.pp_double[i][j],0), "MCPDAddTrack: XY contains negative elements", _state);
28541  }
28542  }
28543  if( k<2 )
28544  {
28545  return;
28546  }
28547  if( s->data.rows<s->npairs+k-1 )
28548  {
28549  rmatrixresize(&s->data, ae_maxint(2*s->data.rows, s->npairs+k-1, _state), 2*n, _state);
28550  }
28551  for(i=0; i<=k-2; i++)
28552  {
28553  s0 = 0;
28554  s1 = 0;
28555  for(j=0; j<=n-1; j++)
28556  {
28557  if( s->states.ptr.p_int[j]>=0 )
28558  {
28559  s0 = s0+xy->ptr.pp_double[i][j];
28560  }
28561  if( s->states.ptr.p_int[j]<=0 )
28562  {
28563  s1 = s1+xy->ptr.pp_double[i+1][j];
28564  }
28565  }
28566  if( ae_fp_greater(s0,0)&&ae_fp_greater(s1,0) )
28567  {
28568  for(j=0; j<=n-1; j++)
28569  {
28570  if( s->states.ptr.p_int[j]>=0 )
28571  {
28572  s->data.ptr.pp_double[s->npairs][j] = xy->ptr.pp_double[i][j]/s0;
28573  }
28574  else
28575  {
28576  s->data.ptr.pp_double[s->npairs][j] = 0.0;
28577  }
28578  if( s->states.ptr.p_int[j]<=0 )
28579  {
28580  s->data.ptr.pp_double[s->npairs][n+j] = xy->ptr.pp_double[i+1][j]/s1;
28581  }
28582  else
28583  {
28584  s->data.ptr.pp_double[s->npairs][n+j] = 0.0;
28585  }
28586  }
28587  s->npairs = s->npairs+1;
28588  }
28589  }
28590 }
28591 
28592 
28593 /*************************************************************************
28594 This function is used to add equality constraints on the elements of the
28595 transition matrix P.
28596 
28597 MCPD solver has four types of constraints which can be placed on P:
28598 * user-specified equality constraints (optional)
28599 * user-specified bound constraints (optional)
28600 * user-specified general linear constraints (optional)
28601 * basic constraints (always present):
28602  * non-negativity: P[i,j]>=0
28603  * consistency: every column of P sums to 1.0
28604 
28605 Final constraints which are passed to the underlying optimizer are
28606 calculated as intersection of all present constraints. For example, you
28607 may specify boundary constraint on P[0,0] and equality one:
28608  0.1<=P[0,0]<=0.9
28609  P[0,0]=0.5
28610 Such combination of constraints will be silently reduced to their
28611 intersection, which is P[0,0]=0.5.
28612 
28613 This function can be used to place equality constraints on arbitrary
28614 subset of elements of P. Set of constraints is specified by EC, which may
28615 contain either NAN's or finite numbers from [0,1]. NAN denotes absence of
28616 constraint, finite number denotes equality constraint on specific element
28617 of P.
28618 
28619 You can also use MCPDAddEC() function which allows to ADD equality
28620 constraint for one element of P without changing constraints for other
28621 elements.
28622 
28623 These functions (MCPDSetEC and MCPDAddEC) interact as follows:
28624 * there is internal matrix of equality constraints which is stored in the
28625  MCPD solver
28626 * MCPDSetEC() replaces this matrix by another one (SET)
28627 * MCPDAddEC() modifies one element of this matrix and leaves other ones
28628  unchanged (ADD)
28629 * thus MCPDAddEC() call preserves all modifications done by previous
28630  calls, while MCPDSetEC() completely discards all changes done to the
28631  equality constraints.
28632 
28633 INPUT PARAMETERS:
28634  S - solver
28635  EC - equality constraints, array[N,N]. Elements of EC can be
28636  either NAN's or finite numbers from [0,1]. NAN denotes
28637  absence of constraints, while finite value denotes
28638  equality constraint on the corresponding element of P.
28639 
28640 NOTES:
28641 
28642 1. infinite values of EC will lead to exception being thrown. Values less
28643 than 0.0 or greater than 1.0 will lead to error code being returned after
28644 call to MCPDSolve().
28645 
28646  -- ALGLIB --
28647  Copyright 23.05.2010 by Bochkanov Sergey
28648 *************************************************************************/
28649 void mcpdsetec(mcpdstate* s,
28650  /* Real */ ae_matrix* ec,
28651  ae_state *_state)
28652 {
28653  ae_int_t i;
28654  ae_int_t j;
28655  ae_int_t n;
28656 
28657 
28658  n = s->n;
28659  ae_assert(ec->cols>=n, "MCPDSetEC: Cols(EC)<N", _state);
28660  ae_assert(ec->rows>=n, "MCPDSetEC: Rows(EC)<N", _state);
28661  for(i=0; i<=n-1; i++)
28662  {
28663  for(j=0; j<=n-1; j++)
28664  {
28665  ae_assert(ae_isfinite(ec->ptr.pp_double[i][j], _state)||ae_isnan(ec->ptr.pp_double[i][j], _state), "MCPDSetEC: EC containts infinite elements", _state);
28666  s->ec.ptr.pp_double[i][j] = ec->ptr.pp_double[i][j];
28667  }
28668  }
28669 }
28670 
28671 
28672 /*************************************************************************
28673 This function is used to add equality constraints on the elements of the
28674 transition matrix P.
28675 
28676 MCPD solver has four types of constraints which can be placed on P:
28677 * user-specified equality constraints (optional)
28678 * user-specified bound constraints (optional)
28679 * user-specified general linear constraints (optional)
28680 * basic constraints (always present):
28681  * non-negativity: P[i,j]>=0
28682  * consistency: every column of P sums to 1.0
28683 
28684 Final constraints which are passed to the underlying optimizer are
28685 calculated as intersection of all present constraints. For example, you
28686 may specify boundary constraint on P[0,0] and equality one:
28687  0.1<=P[0,0]<=0.9
28688  P[0,0]=0.5
28689 Such combination of constraints will be silently reduced to their
28690 intersection, which is P[0,0]=0.5.
28691 
28692 This function can be used to ADD equality constraint for one element of P
28693 without changing constraints for other elements.
28694 
28695 You can also use MCPDSetEC() function which allows you to specify
28696 arbitrary set of equality constraints in one call.
28697 
28698 These functions (MCPDSetEC and MCPDAddEC) interact as follows:
28699 * there is internal matrix of equality constraints which is stored in the
28700  MCPD solver
28701 * MCPDSetEC() replaces this matrix by another one (SET)
28702 * MCPDAddEC() modifies one element of this matrix and leaves other ones
28703  unchanged (ADD)
28704 * thus MCPDAddEC() call preserves all modifications done by previous
28705  calls, while MCPDSetEC() completely discards all changes done to the
28706  equality constraints.
28707 
28708 INPUT PARAMETERS:
28709  S - solver
28710  I - row index of element being constrained
28711  J - column index of element being constrained
28712  C - value (constraint for P[I,J]). Can be either NAN (no
28713  constraint) or finite value from [0,1].
28714 
28715 NOTES:
28716 
28717 1. infinite values of C will lead to exception being thrown. Values less
28718 than 0.0 or greater than 1.0 will lead to error code being returned after
28719 call to MCPDSolve().
28720 
28721  -- ALGLIB --
28722  Copyright 23.05.2010 by Bochkanov Sergey
28723 *************************************************************************/
28724 void mcpdaddec(mcpdstate* s,
28725  ae_int_t i,
28726  ae_int_t j,
28727  double c,
28728  ae_state *_state)
28729 {
28730 
28731 
28732  ae_assert(i>=0, "MCPDAddEC: I<0", _state);
28733  ae_assert(i<s->n, "MCPDAddEC: I>=N", _state);
28734  ae_assert(j>=0, "MCPDAddEC: J<0", _state);
28735  ae_assert(j<s->n, "MCPDAddEC: J>=N", _state);
28736  ae_assert(ae_isnan(c, _state)||ae_isfinite(c, _state), "MCPDAddEC: C is not finite number or NAN", _state);
28737  s->ec.ptr.pp_double[i][j] = c;
28738 }
28739 
28740 
28741 /*************************************************************************
28742 This function is used to add bound constraints on the elements of the
28743 transition matrix P.
28744 
28745 MCPD solver has four types of constraints which can be placed on P:
28746 * user-specified equality constraints (optional)
28747 * user-specified bound constraints (optional)
28748 * user-specified general linear constraints (optional)
28749 * basic constraints (always present):
28750  * non-negativity: P[i,j]>=0
28751  * consistency: every column of P sums to 1.0
28752 
28753 Final constraints which are passed to the underlying optimizer are
28754 calculated as intersection of all present constraints. For example, you
28755 may specify boundary constraint on P[0,0] and equality one:
28756  0.1<=P[0,0]<=0.9
28757  P[0,0]=0.5
28758 Such combination of constraints will be silently reduced to their
28759 intersection, which is P[0,0]=0.5.
28760 
28761 This function can be used to place bound constraints on arbitrary
28762 subset of elements of P. Set of constraints is specified by BndL/BndU
28763 matrices, which may contain arbitrary combination of finite numbers or
28764 infinities (like -INF<x<=0.5 or 0.1<=x<+INF).
28765 
28766 You can also use MCPDAddBC() function which allows to ADD bound constraint
28767 for one element of P without changing constraints for other elements.
28768 
28769 These functions (MCPDSetBC and MCPDAddBC) interact as follows:
28770 * there is internal matrix of bound constraints which is stored in the
28771  MCPD solver
28772 * MCPDSetBC() replaces this matrix by another one (SET)
28773 * MCPDAddBC() modifies one element of this matrix and leaves other ones
28774  unchanged (ADD)
28775 * thus MCPDAddBC() call preserves all modifications done by previous
28776  calls, while MCPDSetBC() completely discards all changes done to the
28777  equality constraints.
28778 
28779 INPUT PARAMETERS:
28780  S - solver
28781  BndL - lower bounds constraints, array[N,N]. Elements of BndL can
28782  be finite numbers or -INF.
28783  BndU - upper bounds constraints, array[N,N]. Elements of BndU can
28784  be finite numbers or +INF.
28785 
28786  -- ALGLIB --
28787  Copyright 23.05.2010 by Bochkanov Sergey
28788 *************************************************************************/
28789 void mcpdsetbc(mcpdstate* s,
28790  /* Real */ ae_matrix* bndl,
28791  /* Real */ ae_matrix* bndu,
28792  ae_state *_state)
28793 {
28794  ae_int_t i;
28795  ae_int_t j;
28796  ae_int_t n;
28797 
28798 
28799  n = s->n;
28800  ae_assert(bndl->cols>=n, "MCPDSetBC: Cols(BndL)<N", _state);
28801  ae_assert(bndl->rows>=n, "MCPDSetBC: Rows(BndL)<N", _state);
28802  ae_assert(bndu->cols>=n, "MCPDSetBC: Cols(BndU)<N", _state);
28803  ae_assert(bndu->rows>=n, "MCPDSetBC: Rows(BndU)<N", _state);
28804  for(i=0; i<=n-1; i++)
28805  {
28806  for(j=0; j<=n-1; j++)
28807  {
28808  ae_assert(ae_isfinite(bndl->ptr.pp_double[i][j], _state)||ae_isneginf(bndl->ptr.pp_double[i][j], _state), "MCPDSetBC: BndL containts NAN or +INF", _state);
28809  ae_assert(ae_isfinite(bndu->ptr.pp_double[i][j], _state)||ae_isposinf(bndu->ptr.pp_double[i][j], _state), "MCPDSetBC: BndU containts NAN or -INF", _state);
28810  s->bndl.ptr.pp_double[i][j] = bndl->ptr.pp_double[i][j];
28811  s->bndu.ptr.pp_double[i][j] = bndu->ptr.pp_double[i][j];
28812  }
28813  }
28814 }
28815 
28816 
28817 /*************************************************************************
28818 This function is used to add bound constraints on the elements of the
28819 transition matrix P.
28820 
28821 MCPD solver has four types of constraints which can be placed on P:
28822 * user-specified equality constraints (optional)
28823 * user-specified bound constraints (optional)
28824 * user-specified general linear constraints (optional)
28825 * basic constraints (always present):
28826  * non-negativity: P[i,j]>=0
28827  * consistency: every column of P sums to 1.0
28828 
28829 Final constraints which are passed to the underlying optimizer are
28830 calculated as intersection of all present constraints. For example, you
28831 may specify boundary constraint on P[0,0] and equality one:
28832  0.1<=P[0,0]<=0.9
28833  P[0,0]=0.5
28834 Such combination of constraints will be silently reduced to their
28835 intersection, which is P[0,0]=0.5.
28836 
28837 This function can be used to ADD bound constraint for one element of P
28838 without changing constraints for other elements.
28839 
28840 You can also use MCPDSetBC() function which allows to place bound
28841 constraints on arbitrary subset of elements of P. Set of constraints is
28842 specified by BndL/BndU matrices, which may contain arbitrary combination
28843 of finite numbers or infinities (like -INF<x<=0.5 or 0.1<=x<+INF).
28844 
28845 These functions (MCPDSetBC and MCPDAddBC) interact as follows:
28846 * there is internal matrix of bound constraints which is stored in the
28847  MCPD solver
28848 * MCPDSetBC() replaces this matrix by another one (SET)
28849 * MCPDAddBC() modifies one element of this matrix and leaves other ones
28850  unchanged (ADD)
28851 * thus MCPDAddBC() call preserves all modifications done by previous
28852  calls, while MCPDSetBC() completely discards all changes done to the
28853  equality constraints.
28854 
28855 INPUT PARAMETERS:
28856  S - solver
28857  I - row index of element being constrained
28858  J - column index of element being constrained
28859  BndL - lower bound
28860  BndU - upper bound
28861 
28862  -- ALGLIB --
28863  Copyright 23.05.2010 by Bochkanov Sergey
28864 *************************************************************************/
28865 void mcpdaddbc(mcpdstate* s,
28866  ae_int_t i,
28867  ae_int_t j,
28868  double bndl,
28869  double bndu,
28870  ae_state *_state)
28871 {
28872 
28873 
28874  ae_assert(i>=0, "MCPDAddBC: I<0", _state);
28875  ae_assert(i<s->n, "MCPDAddBC: I>=N", _state);
28876  ae_assert(j>=0, "MCPDAddBC: J<0", _state);
28877  ae_assert(j<s->n, "MCPDAddBC: J>=N", _state);
28878  ae_assert(ae_isfinite(bndl, _state)||ae_isneginf(bndl, _state), "MCPDAddBC: BndL is NAN or +INF", _state);
28879  ae_assert(ae_isfinite(bndu, _state)||ae_isposinf(bndu, _state), "MCPDAddBC: BndU is NAN or -INF", _state);
28880  s->bndl.ptr.pp_double[i][j] = bndl;
28881  s->bndu.ptr.pp_double[i][j] = bndu;
28882 }
28883 
28884 
28885 /*************************************************************************
28886 This function is used to set linear equality/inequality constraints on the
28887 elements of the transition matrix P.
28888 
28889 This function can be used to set one or several general linear constraints
28890 on the elements of P. Two types of constraints are supported:
28891 * equality constraints
28892 * inequality constraints (both less-or-equal and greater-or-equal)
28893 
28894 Coefficients of constraints are specified by matrix C (one of the
28895 parameters). One row of C corresponds to one constraint. Because
28896 transition matrix P has N*N elements, we need N*N columns to store all
28897 coefficients (they are stored row by row), and one more column to store
28898 right part - hence C has N*N+1 columns. Constraint kind is stored in the
28899 CT array.
28900 
28901 Thus, I-th linear constraint is
28902  P[0,0]*C[I,0] + P[0,1]*C[I,1] + .. + P[0,N-1]*C[I,N-1] +
28903  + P[1,0]*C[I,N] + P[1,1]*C[I,N+1] + ... +
28904  + P[N-1,N-1]*C[I,N*N-1] ?=? C[I,N*N]
28905 where ?=? can be either "=" (CT[i]=0), "<=" (CT[i]<0) or ">=" (CT[i]>0).
28906 
28907 Your constraint may involve only some subset of P (less than N*N elements).
28908 For example it can be something like
28909  P[0,0] + P[0,1] = 0.5
28910 In this case you still should pass matrix with N*N+1 columns, but all its
28911 elements (except for C[0,0], C[0,1] and C[0,N*N-1]) will be zero.
28912 
28913 INPUT PARAMETERS:
28914  S - solver
28915  C - array[K,N*N+1] - coefficients of constraints
28916  (see above for complete description)
28917  CT - array[K] - constraint types
28918  (see above for complete description)
28919  K - number of equality/inequality constraints, K>=0:
28920  * if given, only leading K elements of C/CT are used
28921  * if not given, automatically determined from sizes of C/CT
28922 
28923  -- ALGLIB --
28924  Copyright 23.05.2010 by Bochkanov Sergey
28925 *************************************************************************/
28926 void mcpdsetlc(mcpdstate* s,
28927  /* Real */ ae_matrix* c,
28928  /* Integer */ ae_vector* ct,
28929  ae_int_t k,
28930  ae_state *_state)
28931 {
28932  ae_int_t i;
28933  ae_int_t j;
28934  ae_int_t n;
28935 
28936 
28937  n = s->n;
28938  ae_assert(c->cols>=n*n+1, "MCPDSetLC: Cols(C)<N*N+1", _state);
28939  ae_assert(c->rows>=k, "MCPDSetLC: Rows(C)<K", _state);
28940  ae_assert(ct->cnt>=k, "MCPDSetLC: Len(CT)<K", _state);
28941  ae_assert(apservisfinitematrix(c, k, n*n+1, _state), "MCPDSetLC: C contains infinite or NaN values!", _state);
28942  rmatrixsetlengthatleast(&s->c, k, n*n+1, _state);
28943  ivectorsetlengthatleast(&s->ct, k, _state);
28944  for(i=0; i<=k-1; i++)
28945  {
28946  for(j=0; j<=n*n; j++)
28947  {
28948  s->c.ptr.pp_double[i][j] = c->ptr.pp_double[i][j];
28949  }
28950  s->ct.ptr.p_int[i] = ct->ptr.p_int[i];
28951  }
28952  s->ccnt = k;
28953 }
28954 
28955 
28956 /*************************************************************************
28957 This function allows to tune amount of Tikhonov regularization being
28958 applied to your problem.
28959 
28960 By default, regularizing term is equal to r*||P-prior_P||^2, where r is a
28961 small non-zero value, P is transition matrix, prior_P is identity matrix,
28962 ||X||^2 is a sum of squared elements of X.
28963 
28964 This function allows you to change coefficient r. You can also change
28965 prior values with MCPDSetPrior() function.
28966 
28967 INPUT PARAMETERS:
28968  S - solver
28969  V - regularization coefficient, finite non-negative value. It
28970  is not recommended to specify zero value unless you are
28971  pretty sure that you want it.
28972 
28973  -- ALGLIB --
28974  Copyright 23.05.2010 by Bochkanov Sergey
28975 *************************************************************************/
28976 void mcpdsettikhonovregularizer(mcpdstate* s, double v, ae_state *_state)
28977 {
28978 
28979 
28980  ae_assert(ae_isfinite(v, _state), "MCPDSetTikhonovRegularizer: V is infinite or NAN", _state);
28981  ae_assert(ae_fp_greater_eq(v,0.0), "MCPDSetTikhonovRegularizer: V is less than zero", _state);
28982  s->regterm = v;
28983 }
28984 
28985 
28986 /*************************************************************************
28987 This function allows to set prior values used for regularization of your
28988 problem.
28989 
28990 By default, regularizing term is equal to r*||P-prior_P||^2, where r is a
28991 small non-zero value, P is transition matrix, prior_P is identity matrix,
28992 ||X||^2 is a sum of squared elements of X.
28993 
28994 This function allows you to change prior values prior_P. You can also
28995 change r with MCPDSetTikhonovRegularizer() function.
28996 
28997 INPUT PARAMETERS:
28998  S - solver
28999  PP - array[N,N], matrix of prior values:
29000  1. elements must be real numbers from [0,1]
29001  2. columns must sum to 1.0.
29002  First property is checked (exception is thrown otherwise),
29003  while second one is not checked/enforced.
29004 
29005  -- ALGLIB --
29006  Copyright 23.05.2010 by Bochkanov Sergey
29007 *************************************************************************/
29008 void mcpdsetprior(mcpdstate* s,
29009  /* Real */ ae_matrix* pp,
29010  ae_state *_state)
29011 {
29012  ae_frame _frame_block;
29013  ae_matrix _pp;
29014  ae_int_t i;
29015  ae_int_t j;
29016  ae_int_t n;
29017 
29018  ae_frame_make(_state, &_frame_block);
29019  ae_matrix_init_copy(&_pp, pp, _state, ae_true);
29020  pp = &_pp;
29021 
29022  n = s->n;
29023  ae_assert(pp->cols>=n, "MCPDSetPrior: Cols(PP)<N", _state);
29024  ae_assert(pp->rows>=n, "MCPDSetPrior: Rows(PP)<K", _state);
29025  for(i=0; i<=n-1; i++)
29026  {
29027  for(j=0; j<=n-1; j++)
29028  {
29029  ae_assert(ae_isfinite(pp->ptr.pp_double[i][j], _state), "MCPDSetPrior: PP containts infinite elements", _state);
29030  ae_assert(ae_fp_greater_eq(pp->ptr.pp_double[i][j],0.0)&&ae_fp_less_eq(pp->ptr.pp_double[i][j],1.0), "MCPDSetPrior: PP[i,j] is less than 0.0 or greater than 1.0", _state);
29031  s->priorp.ptr.pp_double[i][j] = pp->ptr.pp_double[i][j];
29032  }
29033  }
29034  ae_frame_leave(_state);
29035 }
29036 
29037 
29038 /*************************************************************************
29039 This function is used to change prediction weights
29040 
29041 MCPD solver scales prediction errors as follows
29042  Error(P) = ||W*(y-P*x)||^2
29043 where
29044  x is a system state at time t
29045  y is a system state at time t+1
29046  P is a transition matrix
29047  W is a diagonal scaling matrix
29048 
29049 By default, weights are chosen in order to minimize relative prediction
29050 error instead of absolute one. For example, if one component of state is
29051 about 0.5 in magnitude and another one is about 0.05, then algorithm will
29052 make corresponding weights equal to 2.0 and 20.0.
29053 
29054 INPUT PARAMETERS:
29055  S - solver
29056  PW - array[N], weights:
29057  * must be non-negative values (exception will be thrown otherwise)
29058  * zero values will be replaced by automatically chosen values
29059 
29060  -- ALGLIB --
29061  Copyright 23.05.2010 by Bochkanov Sergey
29062 *************************************************************************/
29063 void mcpdsetpredictionweights(mcpdstate* s,
29064  /* Real */ ae_vector* pw,
29065  ae_state *_state)
29066 {
29067  ae_int_t i;
29068  ae_int_t n;
29069 
29070 
29071  n = s->n;
29072  ae_assert(pw->cnt>=n, "MCPDSetPredictionWeights: Length(PW)<N", _state);
29073  for(i=0; i<=n-1; i++)
29074  {
29075  ae_assert(ae_isfinite(pw->ptr.p_double[i], _state), "MCPDSetPredictionWeights: PW containts infinite or NAN elements", _state);
29076  ae_assert(ae_fp_greater_eq(pw->ptr.p_double[i],0), "MCPDSetPredictionWeights: PW containts negative elements", _state);
29077  s->pw.ptr.p_double[i] = pw->ptr.p_double[i];
29078  }
29079 }
29080 
29081 
29082 /*************************************************************************
29083 This function is used to start solution of the MCPD problem.
29084 
29085 After return from this function, you can use MCPDResults() to get solution
29086 and completion code.
29087 
29088  -- ALGLIB --
29089  Copyright 23.05.2010 by Bochkanov Sergey
29090 *************************************************************************/
29091 void mcpdsolve(mcpdstate* s, ae_state *_state)
29092 {
29093  ae_int_t n;
29094  ae_int_t npairs;
29095  ae_int_t ccnt;
29096  ae_int_t i;
29097  ae_int_t j;
29098  ae_int_t k;
29099  ae_int_t k2;
29100  double v;
29101  double vv;
29102 
29103 
29104  n = s->n;
29105  npairs = s->npairs;
29106 
29107  /*
29108  * init fields of S
29109  */
29110  s->repterminationtype = 0;
29111  s->repinneriterationscount = 0;
29112  s->repouteriterationscount = 0;
29113  s->repnfev = 0;
29114  for(k=0; k<=n-1; k++)
29115  {
29116  for(k2=0; k2<=n-1; k2++)
29117  {
29118  s->p.ptr.pp_double[k][k2] = _state->v_nan;
29119  }
29120  }
29121 
29122  /*
29123  * Generate "effective" weights for prediction and calculate preconditioner
29124  */
29125  for(i=0; i<=n-1; i++)
29126  {
29127  if( ae_fp_eq(s->pw.ptr.p_double[i],0) )
29128  {
29129  v = 0;
29130  k = 0;
29131  for(j=0; j<=npairs-1; j++)
29132  {
29133  if( ae_fp_neq(s->data.ptr.pp_double[j][n+i],0) )
29134  {
29135  v = v+s->data.ptr.pp_double[j][n+i];
29136  k = k+1;
29137  }
29138  }
29139  if( k!=0 )
29140  {
29141  s->effectivew.ptr.p_double[i] = k/v;
29142  }
29143  else
29144  {
29145  s->effectivew.ptr.p_double[i] = 1.0;
29146  }
29147  }
29148  else
29149  {
29150  s->effectivew.ptr.p_double[i] = s->pw.ptr.p_double[i];
29151  }
29152  }
29153  for(i=0; i<=n-1; i++)
29154  {
29155  for(j=0; j<=n-1; j++)
29156  {
29157  s->h.ptr.p_double[i*n+j] = 2*s->regterm;
29158  }
29159  }
29160  for(k=0; k<=npairs-1; k++)
29161  {
29162  for(i=0; i<=n-1; i++)
29163  {
29164  for(j=0; j<=n-1; j++)
29165  {
29166  s->h.ptr.p_double[i*n+j] = s->h.ptr.p_double[i*n+j]+2*ae_sqr(s->effectivew.ptr.p_double[i], _state)*ae_sqr(s->data.ptr.pp_double[k][j], _state);
29167  }
29168  }
29169  }
29170  for(i=0; i<=n-1; i++)
29171  {
29172  for(j=0; j<=n-1; j++)
29173  {
29174  if( ae_fp_eq(s->h.ptr.p_double[i*n+j],0) )
29175  {
29176  s->h.ptr.p_double[i*n+j] = 1;
29177  }
29178  }
29179  }
29180 
29181  /*
29182  * Generate "effective" BndL/BndU
29183  */
29184  for(i=0; i<=n-1; i++)
29185  {
29186  for(j=0; j<=n-1; j++)
29187  {
29188 
29189  /*
29190  * Set default boundary constraints.
29191  * Lower bound is always zero, upper bound is calculated
29192  * with respect to entry/exit states.
29193  */
29194  s->effectivebndl.ptr.p_double[i*n+j] = 0.0;
29195  if( s->states.ptr.p_int[i]>0||s->states.ptr.p_int[j]<0 )
29196  {
29197  s->effectivebndu.ptr.p_double[i*n+j] = 0.0;
29198  }
29199  else
29200  {
29201  s->effectivebndu.ptr.p_double[i*n+j] = 1.0;
29202  }
29203 
29204  /*
29205  * Calculate intersection of the default and user-specified bound constraints.
29206  * This code checks consistency of such combination.
29207  */
29208  if( ae_isfinite(s->bndl.ptr.pp_double[i][j], _state)&&ae_fp_greater(s->bndl.ptr.pp_double[i][j],s->effectivebndl.ptr.p_double[i*n+j]) )
29209  {
29210  s->effectivebndl.ptr.p_double[i*n+j] = s->bndl.ptr.pp_double[i][j];
29211  }
29212  if( ae_isfinite(s->bndu.ptr.pp_double[i][j], _state)&&ae_fp_less(s->bndu.ptr.pp_double[i][j],s->effectivebndu.ptr.p_double[i*n+j]) )
29213  {
29214  s->effectivebndu.ptr.p_double[i*n+j] = s->bndu.ptr.pp_double[i][j];
29215  }
29216  if( ae_fp_greater(s->effectivebndl.ptr.p_double[i*n+j],s->effectivebndu.ptr.p_double[i*n+j]) )
29217  {
29218  s->repterminationtype = -3;
29219  return;
29220  }
29221 
29222  /*
29223  * Calculate intersection of the effective bound constraints
29224  * and user-specified equality constraints.
29225  * This code checks consistency of such combination.
29226  */
29227  if( ae_isfinite(s->ec.ptr.pp_double[i][j], _state) )
29228  {
29229  if( ae_fp_less(s->ec.ptr.pp_double[i][j],s->effectivebndl.ptr.p_double[i*n+j])||ae_fp_greater(s->ec.ptr.pp_double[i][j],s->effectivebndu.ptr.p_double[i*n+j]) )
29230  {
29231  s->repterminationtype = -3;
29232  return;
29233  }
29234  s->effectivebndl.ptr.p_double[i*n+j] = s->ec.ptr.pp_double[i][j];
29235  s->effectivebndu.ptr.p_double[i*n+j] = s->ec.ptr.pp_double[i][j];
29236  }
29237  }
29238  }
29239 
29240  /*
29241  * Generate linear constraints:
29242  * * "default" sums-to-one constraints (not generated for "exit" states)
29243  */
29244  rmatrixsetlengthatleast(&s->effectivec, s->ccnt+n, n*n+1, _state);
29245  ivectorsetlengthatleast(&s->effectivect, s->ccnt+n, _state);
29246  ccnt = s->ccnt;
29247  for(i=0; i<=s->ccnt-1; i++)
29248  {
29249  for(j=0; j<=n*n; j++)
29250  {
29251  s->effectivec.ptr.pp_double[i][j] = s->c.ptr.pp_double[i][j];
29252  }
29253  s->effectivect.ptr.p_int[i] = s->ct.ptr.p_int[i];
29254  }
29255  for(i=0; i<=n-1; i++)
29256  {
29257  if( s->states.ptr.p_int[i]>=0 )
29258  {
29259  for(k=0; k<=n*n-1; k++)
29260  {
29261  s->effectivec.ptr.pp_double[ccnt][k] = 0;
29262  }
29263  for(k=0; k<=n-1; k++)
29264  {
29265  s->effectivec.ptr.pp_double[ccnt][k*n+i] = 1;
29266  }
29267  s->effectivec.ptr.pp_double[ccnt][n*n] = 1.0;
29268  s->effectivect.ptr.p_int[ccnt] = 0;
29269  ccnt = ccnt+1;
29270  }
29271  }
29272 
29273  /*
29274  * create optimizer
29275  */
29276  for(i=0; i<=n-1; i++)
29277  {
29278  for(j=0; j<=n-1; j++)
29279  {
29280  s->tmpp.ptr.p_double[i*n+j] = (double)1/(double)n;
29281  }
29282  }
29283  minbleicrestartfrom(&s->bs, &s->tmpp, _state);
29284  minbleicsetbc(&s->bs, &s->effectivebndl, &s->effectivebndu, _state);
29285  minbleicsetlc(&s->bs, &s->effectivec, &s->effectivect, ccnt, _state);
29286  minbleicsetcond(&s->bs, 0.0, 0.0, mcpd_xtol, 0, _state);
29287  minbleicsetprecdiag(&s->bs, &s->h, _state);
29288 
29289  /*
29290  * solve problem
29291  */
29292  while(minbleiciteration(&s->bs, _state))
29293  {
29294  ae_assert(s->bs.needfg, "MCPDSolve: internal error", _state);
29295  if( s->bs.needfg )
29296  {
29297 
29298  /*
29299  * Calculate regularization term
29300  */
29301  s->bs.f = 0.0;
29302  vv = s->regterm;
29303  for(i=0; i<=n-1; i++)
29304  {
29305  for(j=0; j<=n-1; j++)
29306  {
29307  s->bs.f = s->bs.f+vv*ae_sqr(s->bs.x.ptr.p_double[i*n+j]-s->priorp.ptr.pp_double[i][j], _state);
29308  s->bs.g.ptr.p_double[i*n+j] = 2*vv*(s->bs.x.ptr.p_double[i*n+j]-s->priorp.ptr.pp_double[i][j]);
29309  }
29310  }
29311 
29312  /*
29313  * calculate prediction error/gradient for K-th pair
29314  */
29315  for(k=0; k<=npairs-1; k++)
29316  {
29317  for(i=0; i<=n-1; i++)
29318  {
29319  v = ae_v_dotproduct(&s->bs.x.ptr.p_double[i*n], 1, &s->data.ptr.pp_double[k][0], 1, ae_v_len(i*n,i*n+n-1));
29320  vv = s->effectivew.ptr.p_double[i];
29321  s->bs.f = s->bs.f+ae_sqr(vv*(v-s->data.ptr.pp_double[k][n+i]), _state);
29322  for(j=0; j<=n-1; j++)
29323  {
29324  s->bs.g.ptr.p_double[i*n+j] = s->bs.g.ptr.p_double[i*n+j]+2*vv*vv*(v-s->data.ptr.pp_double[k][n+i])*s->data.ptr.pp_double[k][j];
29325  }
29326  }
29327  }
29328 
29329  /*
29330  * continue
29331  */
29332  continue;
29333  }
29334  }
29335  minbleicresultsbuf(&s->bs, &s->tmpp, &s->br, _state);
29336  for(i=0; i<=n-1; i++)
29337  {
29338  for(j=0; j<=n-1; j++)
29339  {
29340  s->p.ptr.pp_double[i][j] = s->tmpp.ptr.p_double[i*n+j];
29341  }
29342  }
29343  s->repterminationtype = s->br.terminationtype;
29344  s->repinneriterationscount = s->br.inneriterationscount;
29345  s->repouteriterationscount = s->br.outeriterationscount;
29346  s->repnfev = s->br.nfev;
29347 }
29348 
29349 
29350 /*************************************************************************
29351 MCPD results
29352 
29353 INPUT PARAMETERS:
29354  State - algorithm state
29355 
29356 OUTPUT PARAMETERS:
29357  P - array[N,N], transition matrix
29358  Rep - optimization report. You should check Rep.TerminationType
29359  in order to distinguish successful termination from
29360  unsuccessful one. Speaking short, positive values denote
29361  success, negative ones are failures.
29362  More information about fields of this structure can be
29363  found in the comments on MCPDReport datatype.
29364 
29365 
29366  -- ALGLIB --
29367  Copyright 23.05.2010 by Bochkanov Sergey
29368 *************************************************************************/
29369 void mcpdresults(mcpdstate* s,
29370  /* Real */ ae_matrix* p,
29371  mcpdreport* rep,
29372  ae_state *_state)
29373 {
29374  ae_int_t i;
29375  ae_int_t j;
29376 
29377  ae_matrix_clear(p);
29378  _mcpdreport_clear(rep);
29379 
29380  ae_matrix_set_length(p, s->n, s->n, _state);
29381  for(i=0; i<=s->n-1; i++)
29382  {
29383  for(j=0; j<=s->n-1; j++)
29384  {
29385  p->ptr.pp_double[i][j] = s->p.ptr.pp_double[i][j];
29386  }
29387  }
29388  rep->terminationtype = s->repterminationtype;
29389  rep->inneriterationscount = s->repinneriterationscount;
29390  rep->outeriterationscount = s->repouteriterationscount;
29391  rep->nfev = s->repnfev;
29392 }
29393 
29394 
29395 /*************************************************************************
29396 Internal initialization function
29397 
29398  -- ALGLIB --
29399  Copyright 23.05.2010 by Bochkanov Sergey
29400 *************************************************************************/
29401 static void mcpd_mcpdinit(ae_int_t n,
29402  ae_int_t entrystate,
29403  ae_int_t exitstate,
29404  mcpdstate* s,
29405  ae_state *_state)
29406 {
29407  ae_int_t i;
29408  ae_int_t j;
29409 
29410 
29411  ae_assert(n>=1, "MCPDCreate: N<1", _state);
29412  s->n = n;
29413  ae_vector_set_length(&s->states, n, _state);
29414  for(i=0; i<=n-1; i++)
29415  {
29416  s->states.ptr.p_int[i] = 0;
29417  }
29418  if( entrystate>=0 )
29419  {
29420  s->states.ptr.p_int[entrystate] = 1;
29421  }
29422  if( exitstate>=0 )
29423  {
29424  s->states.ptr.p_int[exitstate] = -1;
29425  }
29426  s->npairs = 0;
29427  s->regterm = 1.0E-8;
29428  s->ccnt = 0;
29429  ae_matrix_set_length(&s->p, n, n, _state);
29430  ae_matrix_set_length(&s->ec, n, n, _state);
29431  ae_matrix_set_length(&s->bndl, n, n, _state);
29432  ae_matrix_set_length(&s->bndu, n, n, _state);
29433  ae_vector_set_length(&s->pw, n, _state);
29434  ae_matrix_set_length(&s->priorp, n, n, _state);
29435  ae_vector_set_length(&s->tmpp, n*n, _state);
29436  ae_vector_set_length(&s->effectivew, n, _state);
29437  ae_vector_set_length(&s->effectivebndl, n*n, _state);
29438  ae_vector_set_length(&s->effectivebndu, n*n, _state);
29439  ae_vector_set_length(&s->h, n*n, _state);
29440  for(i=0; i<=n-1; i++)
29441  {
29442  for(j=0; j<=n-1; j++)
29443  {
29444  s->p.ptr.pp_double[i][j] = 0.0;
29445  s->priorp.ptr.pp_double[i][j] = 0.0;
29446  s->bndl.ptr.pp_double[i][j] = _state->v_neginf;
29447  s->bndu.ptr.pp_double[i][j] = _state->v_posinf;
29448  s->ec.ptr.pp_double[i][j] = _state->v_nan;
29449  }
29450  s->pw.ptr.p_double[i] = 0.0;
29451  s->priorp.ptr.pp_double[i][i] = 1.0;
29452  }
29453  ae_matrix_set_length(&s->data, 1, 2*n, _state);
29454  for(i=0; i<=2*n-1; i++)
29455  {
29456  s->data.ptr.pp_double[0][i] = 0.0;
29457  }
29458  for(i=0; i<=n*n-1; i++)
29459  {
29460  s->tmpp.ptr.p_double[i] = 0.0;
29461  }
29462  minbleiccreate(n*n, &s->tmpp, &s->bs, _state);
29463 }
29464 
29465 
29466 ae_bool _mcpdstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
29467 {
29468  mcpdstate *p = (mcpdstate*)_p;
29469  ae_touch_ptr((void*)p);
29470  if( !ae_vector_init(&p->states, 0, DT_INT, _state, make_automatic) )
29471  return ae_false;
29472  if( !ae_matrix_init(&p->data, 0, 0, DT_REAL, _state, make_automatic) )
29473  return ae_false;
29474  if( !ae_matrix_init(&p->ec, 0, 0, DT_REAL, _state, make_automatic) )
29475  return ae_false;
29476  if( !ae_matrix_init(&p->bndl, 0, 0, DT_REAL, _state, make_automatic) )
29477  return ae_false;
29478  if( !ae_matrix_init(&p->bndu, 0, 0, DT_REAL, _state, make_automatic) )
29479  return ae_false;
29480  if( !ae_matrix_init(&p->c, 0, 0, DT_REAL, _state, make_automatic) )
29481  return ae_false;
29482  if( !ae_vector_init(&p->ct, 0, DT_INT, _state, make_automatic) )
29483  return ae_false;
29484  if( !ae_vector_init(&p->pw, 0, DT_REAL, _state, make_automatic) )
29485  return ae_false;
29486  if( !ae_matrix_init(&p->priorp, 0, 0, DT_REAL, _state, make_automatic) )
29487  return ae_false;
29488  if( !_minbleicstate_init(&p->bs, _state, make_automatic) )
29489  return ae_false;
29490  if( !_minbleicreport_init(&p->br, _state, make_automatic) )
29491  return ae_false;
29492  if( !ae_vector_init(&p->tmpp, 0, DT_REAL, _state, make_automatic) )
29493  return ae_false;
29494  if( !ae_vector_init(&p->effectivew, 0, DT_REAL, _state, make_automatic) )
29495  return ae_false;
29496  if( !ae_vector_init(&p->effectivebndl, 0, DT_REAL, _state, make_automatic) )
29497  return ae_false;
29498  if( !ae_vector_init(&p->effectivebndu, 0, DT_REAL, _state, make_automatic) )
29499  return ae_false;
29500  if( !ae_matrix_init(&p->effectivec, 0, 0, DT_REAL, _state, make_automatic) )
29501  return ae_false;
29502  if( !ae_vector_init(&p->effectivect, 0, DT_INT, _state, make_automatic) )
29503  return ae_false;
29504  if( !ae_vector_init(&p->h, 0, DT_REAL, _state, make_automatic) )
29505  return ae_false;
29506  if( !ae_matrix_init(&p->p, 0, 0, DT_REAL, _state, make_automatic) )
29507  return ae_false;
29508  return ae_true;
29509 }
29510 
29511 
29512 ae_bool _mcpdstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
29513 {
29514  mcpdstate *dst = (mcpdstate*)_dst;
29515  mcpdstate *src = (mcpdstate*)_src;
29516  dst->n = src->n;
29517  if( !ae_vector_init_copy(&dst->states, &src->states, _state, make_automatic) )
29518  return ae_false;
29519  dst->npairs = src->npairs;
29520  if( !ae_matrix_init_copy(&dst->data, &src->data, _state, make_automatic) )
29521  return ae_false;
29522  if( !ae_matrix_init_copy(&dst->ec, &src->ec, _state, make_automatic) )
29523  return ae_false;
29524  if( !ae_matrix_init_copy(&dst->bndl, &src->bndl, _state, make_automatic) )
29525  return ae_false;
29526  if( !ae_matrix_init_copy(&dst->bndu, &src->bndu, _state, make_automatic) )
29527  return ae_false;
29528  if( !ae_matrix_init_copy(&dst->c, &src->c, _state, make_automatic) )
29529  return ae_false;
29530  if( !ae_vector_init_copy(&dst->ct, &src->ct, _state, make_automatic) )
29531  return ae_false;
29532  dst->ccnt = src->ccnt;
29533  if( !ae_vector_init_copy(&dst->pw, &src->pw, _state, make_automatic) )
29534  return ae_false;
29535  if( !ae_matrix_init_copy(&dst->priorp, &src->priorp, _state, make_automatic) )
29536  return ae_false;
29537  dst->regterm = src->regterm;
29538  if( !_minbleicstate_init_copy(&dst->bs, &src->bs, _state, make_automatic) )
29539  return ae_false;
29540  dst->repinneriterationscount = src->repinneriterationscount;
29541  dst->repouteriterationscount = src->repouteriterationscount;
29542  dst->repnfev = src->repnfev;
29543  dst->repterminationtype = src->repterminationtype;
29544  if( !_minbleicreport_init_copy(&dst->br, &src->br, _state, make_automatic) )
29545  return ae_false;
29546  if( !ae_vector_init_copy(&dst->tmpp, &src->tmpp, _state, make_automatic) )
29547  return ae_false;
29548  if( !ae_vector_init_copy(&dst->effectivew, &src->effectivew, _state, make_automatic) )
29549  return ae_false;
29550  if( !ae_vector_init_copy(&dst->effectivebndl, &src->effectivebndl, _state, make_automatic) )
29551  return ae_false;
29552  if( !ae_vector_init_copy(&dst->effectivebndu, &src->effectivebndu, _state, make_automatic) )
29553  return ae_false;
29554  if( !ae_matrix_init_copy(&dst->effectivec, &src->effectivec, _state, make_automatic) )
29555  return ae_false;
29556  if( !ae_vector_init_copy(&dst->effectivect, &src->effectivect, _state, make_automatic) )
29557  return ae_false;
29558  if( !ae_vector_init_copy(&dst->h, &src->h, _state, make_automatic) )
29559  return ae_false;
29560  if( !ae_matrix_init_copy(&dst->p, &src->p, _state, make_automatic) )
29561  return ae_false;
29562  return ae_true;
29563 }
29564 
29565 
29566 void _mcpdstate_clear(void* _p)
29567 {
29568  mcpdstate *p = (mcpdstate*)_p;
29569  ae_touch_ptr((void*)p);
29570  ae_vector_clear(&p->states);
29571  ae_matrix_clear(&p->data);
29572  ae_matrix_clear(&p->ec);
29573  ae_matrix_clear(&p->bndl);
29574  ae_matrix_clear(&p->bndu);
29575  ae_matrix_clear(&p->c);
29576  ae_vector_clear(&p->ct);
29577  ae_vector_clear(&p->pw);
29578  ae_matrix_clear(&p->priorp);
29579  _minbleicstate_clear(&p->bs);
29580  _minbleicreport_clear(&p->br);
29581  ae_vector_clear(&p->tmpp);
29582  ae_vector_clear(&p->effectivew);
29583  ae_vector_clear(&p->effectivebndl);
29584  ae_vector_clear(&p->effectivebndu);
29585  ae_matrix_clear(&p->effectivec);
29586  ae_vector_clear(&p->effectivect);
29587  ae_vector_clear(&p->h);
29588  ae_matrix_clear(&p->p);
29589 }
29590 
29591 
29592 void _mcpdstate_destroy(void* _p)
29593 {
29594  mcpdstate *p = (mcpdstate*)_p;
29595  ae_touch_ptr((void*)p);
29596  ae_vector_destroy(&p->states);
29597  ae_matrix_destroy(&p->data);
29598  ae_matrix_destroy(&p->ec);
29599  ae_matrix_destroy(&p->bndl);
29600  ae_matrix_destroy(&p->bndu);
29601  ae_matrix_destroy(&p->c);
29602  ae_vector_destroy(&p->ct);
29603  ae_vector_destroy(&p->pw);
29604  ae_matrix_destroy(&p->priorp);
29605  _minbleicstate_destroy(&p->bs);
29606  _minbleicreport_destroy(&p->br);
29607  ae_vector_destroy(&p->tmpp);
29608  ae_vector_destroy(&p->effectivew);
29609  ae_vector_destroy(&p->effectivebndl);
29610  ae_vector_destroy(&p->effectivebndu);
29611  ae_matrix_destroy(&p->effectivec);
29612  ae_vector_destroy(&p->effectivect);
29613  ae_vector_destroy(&p->h);
29614  ae_matrix_destroy(&p->p);
29615 }
29616 
29617 
29618 ae_bool _mcpdreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
29619 {
29620  mcpdreport *p = (mcpdreport*)_p;
29621  ae_touch_ptr((void*)p);
29622  return ae_true;
29623 }
29624 
29625 
29626 ae_bool _mcpdreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
29627 {
29628  mcpdreport *dst = (mcpdreport*)_dst;
29629  mcpdreport *src = (mcpdreport*)_src;
29630  dst->inneriterationscount = src->inneriterationscount;
29631  dst->outeriterationscount = src->outeriterationscount;
29632  dst->nfev = src->nfev;
29633  dst->terminationtype = src->terminationtype;
29634  return ae_true;
29635 }
29636 
29637 
29638 void _mcpdreport_clear(void* _p)
29639 {
29640  mcpdreport *p = (mcpdreport*)_p;
29641  ae_touch_ptr((void*)p);
29642 }
29643 
29644 
29645 void _mcpdreport_destroy(void* _p)
29646 {
29647  mcpdreport *p = (mcpdreport*)_p;
29648  ae_touch_ptr((void*)p);
29649 }
29650 
29651 
29652 
29653 
29654 /*************************************************************************
29655 Like MLPCreate0, but for ensembles.
29656 
29657  -- ALGLIB --
29658  Copyright 18.02.2009 by Bochkanov Sergey
29659 *************************************************************************/
29660 void mlpecreate0(ae_int_t nin,
29661  ae_int_t nout,
29662  ae_int_t ensemblesize,
29663  mlpensemble* ensemble,
29664  ae_state *_state)
29665 {
29666  ae_frame _frame_block;
29667  multilayerperceptron net;
29668 
29669  ae_frame_make(_state, &_frame_block);
29670  _mlpensemble_clear(ensemble);
29671  _multilayerperceptron_init(&net, _state, ae_true);
29672 
29673  mlpcreate0(nin, nout, &net, _state);
29674  mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state);
29675  ae_frame_leave(_state);
29676 }
29677 
29678 
29679 /*************************************************************************
29680 Like MLPCreate1, but for ensembles.
29681 
29682  -- ALGLIB --
29683  Copyright 18.02.2009 by Bochkanov Sergey
29684 *************************************************************************/
29685 void mlpecreate1(ae_int_t nin,
29686  ae_int_t nhid,
29687  ae_int_t nout,
29688  ae_int_t ensemblesize,
29689  mlpensemble* ensemble,
29690  ae_state *_state)
29691 {
29692  ae_frame _frame_block;
29693  multilayerperceptron net;
29694 
29695  ae_frame_make(_state, &_frame_block);
29696  _mlpensemble_clear(ensemble);
29697  _multilayerperceptron_init(&net, _state, ae_true);
29698 
29699  mlpcreate1(nin, nhid, nout, &net, _state);
29700  mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state);
29701  ae_frame_leave(_state);
29702 }
29703 
29704 
29705 /*************************************************************************
29706 Like MLPCreate2, but for ensembles.
29707 
29708  -- ALGLIB --
29709  Copyright 18.02.2009 by Bochkanov Sergey
29710 *************************************************************************/
29711 void mlpecreate2(ae_int_t nin,
29712  ae_int_t nhid1,
29713  ae_int_t nhid2,
29714  ae_int_t nout,
29715  ae_int_t ensemblesize,
29716  mlpensemble* ensemble,
29717  ae_state *_state)
29718 {
29719  ae_frame _frame_block;
29720  multilayerperceptron net;
29721 
29722  ae_frame_make(_state, &_frame_block);
29723  _mlpensemble_clear(ensemble);
29724  _multilayerperceptron_init(&net, _state, ae_true);
29725 
29726  mlpcreate2(nin, nhid1, nhid2, nout, &net, _state);
29727  mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state);
29728  ae_frame_leave(_state);
29729 }
29730 
29731 
29732 /*************************************************************************
29733 Like MLPCreateB0, but for ensembles.
29734 
29735  -- ALGLIB --
29736  Copyright 18.02.2009 by Bochkanov Sergey
29737 *************************************************************************/
29738 void mlpecreateb0(ae_int_t nin,
29739  ae_int_t nout,
29740  double b,
29741  double d,
29742  ae_int_t ensemblesize,
29743  mlpensemble* ensemble,
29744  ae_state *_state)
29745 {
29746  ae_frame _frame_block;
29747  multilayerperceptron net;
29748 
29749  ae_frame_make(_state, &_frame_block);
29750  _mlpensemble_clear(ensemble);
29751  _multilayerperceptron_init(&net, _state, ae_true);
29752 
29753  mlpcreateb0(nin, nout, b, d, &net, _state);
29754  mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state);
29755  ae_frame_leave(_state);
29756 }
29757 
29758 
29759 /*************************************************************************
29760 Like MLPCreateB1, but for ensembles.
29761 
29762  -- ALGLIB --
29763  Copyright 18.02.2009 by Bochkanov Sergey
29764 *************************************************************************/
29765 void mlpecreateb1(ae_int_t nin,
29766  ae_int_t nhid,
29767  ae_int_t nout,
29768  double b,
29769  double d,
29770  ae_int_t ensemblesize,
29771  mlpensemble* ensemble,
29772  ae_state *_state)
29773 {
29774  ae_frame _frame_block;
29775  multilayerperceptron net;
29776 
29777  ae_frame_make(_state, &_frame_block);
29778  _mlpensemble_clear(ensemble);
29779  _multilayerperceptron_init(&net, _state, ae_true);
29780 
29781  mlpcreateb1(nin, nhid, nout, b, d, &net, _state);
29782  mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state);
29783  ae_frame_leave(_state);
29784 }
29785 
29786 
29787 /*************************************************************************
29788 Like MLPCreateB2, but for ensembles.
29789 
29790  -- ALGLIB --
29791  Copyright 18.02.2009 by Bochkanov Sergey
29792 *************************************************************************/
29793 void mlpecreateb2(ae_int_t nin,
29794  ae_int_t nhid1,
29795  ae_int_t nhid2,
29796  ae_int_t nout,
29797  double b,
29798  double d,
29799  ae_int_t ensemblesize,
29800  mlpensemble* ensemble,
29801  ae_state *_state)
29802 {
29803  ae_frame _frame_block;
29804  multilayerperceptron net;
29805 
29806  ae_frame_make(_state, &_frame_block);
29807  _mlpensemble_clear(ensemble);
29808  _multilayerperceptron_init(&net, _state, ae_true);
29809 
29810  mlpcreateb2(nin, nhid1, nhid2, nout, b, d, &net, _state);
29811  mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state);
29812  ae_frame_leave(_state);
29813 }
29814 
29815 
29816 /*************************************************************************
29817 Like MLPCreateR0, but for ensembles.
29818 
29819  -- ALGLIB --
29820  Copyright 18.02.2009 by Bochkanov Sergey
29821 *************************************************************************/
29822 void mlpecreater0(ae_int_t nin,
29823  ae_int_t nout,
29824  double a,
29825  double b,
29826  ae_int_t ensemblesize,
29827  mlpensemble* ensemble,
29828  ae_state *_state)
29829 {
29830  ae_frame _frame_block;
29831  multilayerperceptron net;
29832 
29833  ae_frame_make(_state, &_frame_block);
29834  _mlpensemble_clear(ensemble);
29835  _multilayerperceptron_init(&net, _state, ae_true);
29836 
29837  mlpcreater0(nin, nout, a, b, &net, _state);
29838  mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state);
29839  ae_frame_leave(_state);
29840 }
29841 
29842 
29843 /*************************************************************************
29844 Like MLPCreateR1, but for ensembles.
29845 
29846  -- ALGLIB --
29847  Copyright 18.02.2009 by Bochkanov Sergey
29848 *************************************************************************/
29849 void mlpecreater1(ae_int_t nin,
29850  ae_int_t nhid,
29851  ae_int_t nout,
29852  double a,
29853  double b,
29854  ae_int_t ensemblesize,
29855  mlpensemble* ensemble,
29856  ae_state *_state)
29857 {
29858  ae_frame _frame_block;
29859  multilayerperceptron net;
29860 
29861  ae_frame_make(_state, &_frame_block);
29862  _mlpensemble_clear(ensemble);
29863  _multilayerperceptron_init(&net, _state, ae_true);
29864 
29865  mlpcreater1(nin, nhid, nout, a, b, &net, _state);
29866  mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state);
29867  ae_frame_leave(_state);
29868 }
29869 
29870 
29871 /*************************************************************************
29872 Like MLPCreateR2, but for ensembles.
29873 
29874  -- ALGLIB --
29875  Copyright 18.02.2009 by Bochkanov Sergey
29876 *************************************************************************/
29877 void mlpecreater2(ae_int_t nin,
29878  ae_int_t nhid1,
29879  ae_int_t nhid2,
29880  ae_int_t nout,
29881  double a,
29882  double b,
29883  ae_int_t ensemblesize,
29884  mlpensemble* ensemble,
29885  ae_state *_state)
29886 {
29887  ae_frame _frame_block;
29888  multilayerperceptron net;
29889 
29890  ae_frame_make(_state, &_frame_block);
29891  _mlpensemble_clear(ensemble);
29892  _multilayerperceptron_init(&net, _state, ae_true);
29893 
29894  mlpcreater2(nin, nhid1, nhid2, nout, a, b, &net, _state);
29895  mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state);
29896  ae_frame_leave(_state);
29897 }
29898 
29899 
29900 /*************************************************************************
29901 Like MLPCreateC0, but for ensembles.
29902 
29903  -- ALGLIB --
29904  Copyright 18.02.2009 by Bochkanov Sergey
29905 *************************************************************************/
29906 void mlpecreatec0(ae_int_t nin,
29907  ae_int_t nout,
29908  ae_int_t ensemblesize,
29909  mlpensemble* ensemble,
29910  ae_state *_state)
29911 {
29912  ae_frame _frame_block;
29913  multilayerperceptron net;
29914 
29915  ae_frame_make(_state, &_frame_block);
29916  _mlpensemble_clear(ensemble);
29917  _multilayerperceptron_init(&net, _state, ae_true);
29918 
29919  mlpcreatec0(nin, nout, &net, _state);
29920  mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state);
29921  ae_frame_leave(_state);
29922 }
29923 
29924 
29925 /*************************************************************************
29926 Like MLPCreateC1, but for ensembles.
29927 
29928  -- ALGLIB --
29929  Copyright 18.02.2009 by Bochkanov Sergey
29930 *************************************************************************/
29931 void mlpecreatec1(ae_int_t nin,
29932  ae_int_t nhid,
29933  ae_int_t nout,
29934  ae_int_t ensemblesize,
29935  mlpensemble* ensemble,
29936  ae_state *_state)
29937 {
29938  ae_frame _frame_block;
29939  multilayerperceptron net;
29940 
29941  ae_frame_make(_state, &_frame_block);
29942  _mlpensemble_clear(ensemble);
29943  _multilayerperceptron_init(&net, _state, ae_true);
29944 
29945  mlpcreatec1(nin, nhid, nout, &net, _state);
29946  mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state);
29947  ae_frame_leave(_state);
29948 }
29949 
29950 
29951 /*************************************************************************
29952 Like MLPCreateC2, but for ensembles.
29953 
29954  -- ALGLIB --
29955  Copyright 18.02.2009 by Bochkanov Sergey
29956 *************************************************************************/
29957 void mlpecreatec2(ae_int_t nin,
29958  ae_int_t nhid1,
29959  ae_int_t nhid2,
29960  ae_int_t nout,
29961  ae_int_t ensemblesize,
29962  mlpensemble* ensemble,
29963  ae_state *_state)
29964 {
29965  ae_frame _frame_block;
29966  multilayerperceptron net;
29967 
29968  ae_frame_make(_state, &_frame_block);
29969  _mlpensemble_clear(ensemble);
29970  _multilayerperceptron_init(&net, _state, ae_true);
29971 
29972  mlpcreatec2(nin, nhid1, nhid2, nout, &net, _state);
29973  mlpecreatefromnetwork(&net, ensemblesize, ensemble, _state);
29974  ae_frame_leave(_state);
29975 }
29976 
29977 
29978 /*************************************************************************
29979 Creates ensemble from network. Only network geometry is copied.
29980 
29981  -- ALGLIB --
29982  Copyright 17.02.2009 by Bochkanov Sergey
29983 *************************************************************************/
29984 void mlpecreatefromnetwork(multilayerperceptron* network,
29985  ae_int_t ensemblesize,
29986  mlpensemble* ensemble,
29987  ae_state *_state)
29988 {
29989  ae_int_t i;
29990  ae_int_t ccount;
29991  ae_int_t wcount;
29992 
29993  _mlpensemble_clear(ensemble);
29994 
29995  ae_assert(ensemblesize>0, "MLPECreate: incorrect ensemble size!", _state);
29996 
29997  /*
29998  * Copy network
29999  */
30000  mlpcopy(network, &ensemble->network, _state);
30001 
30002  /*
30003  * network properties
30004  */
30005  if( mlpissoftmax(network, _state) )
30006  {
30007  ccount = mlpgetinputscount(&ensemble->network, _state);
30008  }
30009  else
30010  {
30011  ccount = mlpgetinputscount(&ensemble->network, _state)+mlpgetoutputscount(&ensemble->network, _state);
30012  }
30013  wcount = mlpgetweightscount(&ensemble->network, _state);
30014  ensemble->ensemblesize = ensemblesize;
30015 
30016  /*
30017  * weights, means, sigmas
30018  */
30019  ae_vector_set_length(&ensemble->weights, ensemblesize*wcount, _state);
30020  ae_vector_set_length(&ensemble->columnmeans, ensemblesize*ccount, _state);
30021  ae_vector_set_length(&ensemble->columnsigmas, ensemblesize*ccount, _state);
30022  for(i=0; i<=ensemblesize*wcount-1; i++)
30023  {
30024  ensemble->weights.ptr.p_double[i] = ae_randomreal(_state)-0.5;
30025  }
30026  for(i=0; i<=ensemblesize-1; i++)
30027  {
30028  ae_v_move(&ensemble->columnmeans.ptr.p_double[i*ccount], 1, &network->columnmeans.ptr.p_double[0], 1, ae_v_len(i*ccount,(i+1)*ccount-1));
30029  ae_v_move(&ensemble->columnsigmas.ptr.p_double[i*ccount], 1, &network->columnsigmas.ptr.p_double[0], 1, ae_v_len(i*ccount,(i+1)*ccount-1));
30030  }
30031 
30032  /*
30033  * temporaries, internal buffers
30034  */
30035  ae_vector_set_length(&ensemble->y, mlpgetoutputscount(&ensemble->network, _state), _state);
30036 }
30037 
30038 
30039 /*************************************************************************
30040 Copying of MLPEnsemble strucure
30041 
30042 INPUT PARAMETERS:
30043  Ensemble1 - original
30044 
30045 OUTPUT PARAMETERS:
30046  Ensemble2 - copy
30047 
30048  -- ALGLIB --
30049  Copyright 17.02.2009 by Bochkanov Sergey
30050 *************************************************************************/
30051 void mlpecopy(mlpensemble* ensemble1,
30052  mlpensemble* ensemble2,
30053  ae_state *_state)
30054 {
30055  ae_int_t ccount;
30056  ae_int_t wcount;
30057 
30058  _mlpensemble_clear(ensemble2);
30059 
30060 
30061  /*
30062  * Unload info
30063  */
30064  if( mlpissoftmax(&ensemble1->network, _state) )
30065  {
30066  ccount = mlpgetinputscount(&ensemble1->network, _state);
30067  }
30068  else
30069  {
30070  ccount = mlpgetinputscount(&ensemble1->network, _state)+mlpgetoutputscount(&ensemble1->network, _state);
30071  }
30072  wcount = mlpgetweightscount(&ensemble1->network, _state);
30073 
30074  /*
30075  * Allocate space
30076  */
30077  ae_vector_set_length(&ensemble2->weights, ensemble1->ensemblesize*wcount, _state);
30078  ae_vector_set_length(&ensemble2->columnmeans, ensemble1->ensemblesize*ccount, _state);
30079  ae_vector_set_length(&ensemble2->columnsigmas, ensemble1->ensemblesize*ccount, _state);
30080  ae_vector_set_length(&ensemble2->y, mlpgetoutputscount(&ensemble1->network, _state), _state);
30081 
30082  /*
30083  * Copy
30084  */
30085  ensemble2->ensemblesize = ensemble1->ensemblesize;
30086  ae_v_move(&ensemble2->weights.ptr.p_double[0], 1, &ensemble1->weights.ptr.p_double[0], 1, ae_v_len(0,ensemble1->ensemblesize*wcount-1));
30087  ae_v_move(&ensemble2->columnmeans.ptr.p_double[0], 1, &ensemble1->columnmeans.ptr.p_double[0], 1, ae_v_len(0,ensemble1->ensemblesize*ccount-1));
30088  ae_v_move(&ensemble2->columnsigmas.ptr.p_double[0], 1, &ensemble1->columnsigmas.ptr.p_double[0], 1, ae_v_len(0,ensemble1->ensemblesize*ccount-1));
30089  mlpcopy(&ensemble1->network, &ensemble2->network, _state);
30090 }
30091 
30092 
30093 /*************************************************************************
30094 Randomization of MLP ensemble
30095 
30096  -- ALGLIB --
30097  Copyright 17.02.2009 by Bochkanov Sergey
30098 *************************************************************************/
30099 void mlperandomize(mlpensemble* ensemble, ae_state *_state)
30100 {
30101  ae_int_t i;
30102  ae_int_t wcount;
30103 
30104 
30105  wcount = mlpgetweightscount(&ensemble->network, _state);
30106  for(i=0; i<=ensemble->ensemblesize*wcount-1; i++)
30107  {
30108  ensemble->weights.ptr.p_double[i] = ae_randomreal(_state)-0.5;
30109  }
30110 }
30111 
30112 
30113 /*************************************************************************
30114 Return ensemble properties (number of inputs and outputs).
30115 
30116  -- ALGLIB --
30117  Copyright 17.02.2009 by Bochkanov Sergey
30118 *************************************************************************/
30119 void mlpeproperties(mlpensemble* ensemble,
30120  ae_int_t* nin,
30121  ae_int_t* nout,
30122  ae_state *_state)
30123 {
30124 
30125  *nin = 0;
30126  *nout = 0;
30127 
30128  *nin = mlpgetinputscount(&ensemble->network, _state);
30129  *nout = mlpgetoutputscount(&ensemble->network, _state);
30130 }
30131 
30132 
30133 /*************************************************************************
30134 Return normalization type (whether ensemble is SOFTMAX-normalized or not).
30135 
30136  -- ALGLIB --
30137  Copyright 17.02.2009 by Bochkanov Sergey
30138 *************************************************************************/
30139 ae_bool mlpeissoftmax(mlpensemble* ensemble, ae_state *_state)
30140 {
30141  ae_bool result;
30142 
30143 
30144  result = mlpissoftmax(&ensemble->network, _state);
30145  return result;
30146 }
30147 
30148 
30149 /*************************************************************************
30150 Procesing
30151 
30152 INPUT PARAMETERS:
30153  Ensemble- neural networks ensemble
30154  X - input vector, array[0..NIn-1].
30155  Y - (possibly) preallocated buffer; if size of Y is less than
30156  NOut, it will be reallocated. If it is large enough, it
30157  is NOT reallocated, so we can save some time on reallocation.
30158 
30159 
30160 OUTPUT PARAMETERS:
30161  Y - result. Regression estimate when solving regression task,
30162  vector of posterior probabilities for classification task.
30163 
30164  -- ALGLIB --
30165  Copyright 17.02.2009 by Bochkanov Sergey
30166 *************************************************************************/
30167 void mlpeprocess(mlpensemble* ensemble,
30168  /* Real */ ae_vector* x,
30169  /* Real */ ae_vector* y,
30170  ae_state *_state)
30171 {
30172  ae_int_t i;
30173  ae_int_t es;
30174  ae_int_t wc;
30175  ae_int_t cc;
30176  double v;
30177  ae_int_t nout;
30178 
30179 
30180  if( y->cnt<mlpgetoutputscount(&ensemble->network, _state) )
30181  {
30182  ae_vector_set_length(y, mlpgetoutputscount(&ensemble->network, _state), _state);
30183  }
30184  es = ensemble->ensemblesize;
30185  wc = mlpgetweightscount(&ensemble->network, _state);
30186  if( mlpissoftmax(&ensemble->network, _state) )
30187  {
30188  cc = mlpgetinputscount(&ensemble->network, _state);
30189  }
30190  else
30191  {
30192  cc = mlpgetinputscount(&ensemble->network, _state)+mlpgetoutputscount(&ensemble->network, _state);
30193  }
30194  v = (double)1/(double)es;
30195  nout = mlpgetoutputscount(&ensemble->network, _state);
30196  for(i=0; i<=nout-1; i++)
30197  {
30198  y->ptr.p_double[i] = 0;
30199  }
30200  for(i=0; i<=es-1; i++)
30201  {
30202  ae_v_move(&ensemble->network.weights.ptr.p_double[0], 1, &ensemble->weights.ptr.p_double[i*wc], 1, ae_v_len(0,wc-1));
30203  ae_v_move(&ensemble->network.columnmeans.ptr.p_double[0], 1, &ensemble->columnmeans.ptr.p_double[i*cc], 1, ae_v_len(0,cc-1));
30204  ae_v_move(&ensemble->network.columnsigmas.ptr.p_double[0], 1, &ensemble->columnsigmas.ptr.p_double[i*cc], 1, ae_v_len(0,cc-1));
30205  mlpprocess(&ensemble->network, x, &ensemble->y, _state);
30206  ae_v_addd(&y->ptr.p_double[0], 1, &ensemble->y.ptr.p_double[0], 1, ae_v_len(0,nout-1), v);
30207  }
30208 }
30209 
30210 
30211 /*************************************************************************
30212 'interactive' variant of MLPEProcess for languages like Python which
30213 support constructs like "Y = MLPEProcess(LM,X)" and interactive mode of the
30214 interpreter
30215 
30216 This function allocates new array on each call, so it is significantly
30217 slower than its 'non-interactive' counterpart, but it is more convenient
30218 when you call it from command line.
30219 
30220  -- ALGLIB --
30221  Copyright 17.02.2009 by Bochkanov Sergey
30222 *************************************************************************/
30223 void mlpeprocessi(mlpensemble* ensemble,
30224  /* Real */ ae_vector* x,
30225  /* Real */ ae_vector* y,
30226  ae_state *_state)
30227 {
30228 
30229  ae_vector_clear(y);
30230 
30231  mlpeprocess(ensemble, x, y, _state);
30232 }
30233 
30234 
30235 /*************************************************************************
30236 Calculation of all types of errors
30237 
30238  -- ALGLIB --
30239  Copyright 17.02.2009 by Bochkanov Sergey
30240 *************************************************************************/
30241 void mlpeallerrorsx(mlpensemble* ensemble,
30242  /* Real */ ae_matrix* densexy,
30243  sparsematrix* sparsexy,
30244  ae_int_t datasetsize,
30245  ae_int_t datasettype,
30246  /* Integer */ ae_vector* idx,
30247  ae_int_t subset0,
30248  ae_int_t subset1,
30249  ae_int_t subsettype,
30250  ae_shared_pool* buf,
30251  modelerrors* rep,
30252  ae_state *_state)
30253 {
30254  ae_frame _frame_block;
30255  ae_int_t i;
30256  ae_int_t j;
30257  ae_int_t nin;
30258  ae_int_t nout;
30259  ae_bool iscls;
30260  ae_int_t srcidx;
30261  mlpbuffers *pbuf;
30262  ae_smart_ptr _pbuf;
30263  modelerrors rep0;
30264  modelerrors rep1;
30265 
30266  ae_frame_make(_state, &_frame_block);
30267  ae_smart_ptr_init(&_pbuf, (void**)&pbuf, _state, ae_true);
30268  _modelerrors_init(&rep0, _state, ae_true);
30269  _modelerrors_init(&rep1, _state, ae_true);
30270 
30271 
30272  /*
30273  * Get network information
30274  */
30275  nin = mlpgetinputscount(&ensemble->network, _state);
30276  nout = mlpgetoutputscount(&ensemble->network, _state);
30277  iscls = mlpissoftmax(&ensemble->network, _state);
30278 
30279  /*
30280  * Retrieve buffer, prepare, process data, recycle buffer
30281  */
30282  ae_shared_pool_retrieve(buf, &_pbuf, _state);
30283  if( iscls )
30284  {
30285  dserrallocate(nout, &pbuf->tmp0, _state);
30286  }
30287  else
30288  {
30289  dserrallocate(-nout, &pbuf->tmp0, _state);
30290  }
30291  rvectorsetlengthatleast(&pbuf->x, nin, _state);
30292  rvectorsetlengthatleast(&pbuf->y, nout, _state);
30293  rvectorsetlengthatleast(&pbuf->desiredy, nout, _state);
30294  for(i=subset0; i<=subset1-1; i++)
30295  {
30296  srcidx = -1;
30297  if( subsettype==0 )
30298  {
30299  srcidx = i;
30300  }
30301  if( subsettype==1 )
30302  {
30303  srcidx = idx->ptr.p_int[i];
30304  }
30305  ae_assert(srcidx>=0, "MLPEAllErrorsX: internal error", _state);
30306  if( datasettype==0 )
30307  {
30308  ae_v_move(&pbuf->x.ptr.p_double[0], 1, &densexy->ptr.pp_double[srcidx][0], 1, ae_v_len(0,nin-1));
30309  }
30310  if( datasettype==1 )
30311  {
30312  sparsegetrow(sparsexy, srcidx, &pbuf->x, _state);
30313  }
30314  mlpeprocess(ensemble, &pbuf->x, &pbuf->y, _state);
30315  if( mlpissoftmax(&ensemble->network, _state) )
30316  {
30317  if( datasettype==0 )
30318  {
30319  pbuf->desiredy.ptr.p_double[0] = densexy->ptr.pp_double[srcidx][nin];
30320  }
30321  if( datasettype==1 )
30322  {
30323  pbuf->desiredy.ptr.p_double[0] = sparseget(sparsexy, srcidx, nin, _state);
30324  }
30325  }
30326  else
30327  {
30328  if( datasettype==0 )
30329  {
30330  ae_v_move(&pbuf->desiredy.ptr.p_double[0], 1, &densexy->ptr.pp_double[srcidx][nin], 1, ae_v_len(0,nout-1));
30331  }
30332  if( datasettype==1 )
30333  {
30334  for(j=0; j<=nout-1; j++)
30335  {
30336  pbuf->desiredy.ptr.p_double[j] = sparseget(sparsexy, srcidx, nin+j, _state);
30337  }
30338  }
30339  }
30340  dserraccumulate(&pbuf->tmp0, &pbuf->y, &pbuf->desiredy, _state);
30341  }
30342  dserrfinish(&pbuf->tmp0, _state);
30343  rep->relclserror = pbuf->tmp0.ptr.p_double[0];
30344  rep->avgce = pbuf->tmp0.ptr.p_double[1]/ae_log(2, _state);
30345  rep->rmserror = pbuf->tmp0.ptr.p_double[2];
30346  rep->avgerror = pbuf->tmp0.ptr.p_double[3];
30347  rep->avgrelerror = pbuf->tmp0.ptr.p_double[4];
30348  ae_shared_pool_recycle(buf, &_pbuf, _state);
30349  ae_frame_leave(_state);
30350 }
30351 
30352 
30353 /*************************************************************************
30354 Calculation of all types of errors on dataset given by sparse matrix
30355 
30356  -- ALGLIB --
30357  Copyright 10.09.2012 by Bochkanov Sergey
30358 *************************************************************************/
30359 void mlpeallerrorssparse(mlpensemble* ensemble,
30360  sparsematrix* xy,
30361  ae_int_t npoints,
30362  double* relcls,
30363  double* avgce,
30364  double* rms,
30365  double* avg,
30366  double* avgrel,
30367  ae_state *_state)
30368 {
30369  ae_frame _frame_block;
30370  ae_int_t i;
30371  ae_vector buf;
30372  ae_vector workx;
30373  ae_vector y;
30374  ae_vector dy;
30375  ae_int_t nin;
30376  ae_int_t nout;
30377 
30378  ae_frame_make(_state, &_frame_block);
30379  *relcls = 0;
30380  *avgce = 0;
30381  *rms = 0;
30382  *avg = 0;
30383  *avgrel = 0;
30384  ae_vector_init(&buf, 0, DT_REAL, _state, ae_true);
30385  ae_vector_init(&workx, 0, DT_REAL, _state, ae_true);
30386  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
30387  ae_vector_init(&dy, 0, DT_REAL, _state, ae_true);
30388 
30389  nin = mlpgetinputscount(&ensemble->network, _state);
30390  nout = mlpgetoutputscount(&ensemble->network, _state);
30391  if( mlpissoftmax(&ensemble->network, _state) )
30392  {
30393  ae_vector_set_length(&dy, 1, _state);
30394  dserrallocate(nout, &buf, _state);
30395  }
30396  else
30397  {
30398  ae_vector_set_length(&dy, nout, _state);
30399  dserrallocate(-nout, &buf, _state);
30400  }
30401  for(i=0; i<=npoints-1; i++)
30402  {
30403  sparsegetrow(xy, i, &workx, _state);
30404  mlpeprocess(ensemble, &workx, &y, _state);
30405  if( mlpissoftmax(&ensemble->network, _state) )
30406  {
30407  dy.ptr.p_double[0] = workx.ptr.p_double[nin];
30408  }
30409  else
30410  {
30411  ae_v_move(&dy.ptr.p_double[0], 1, &workx.ptr.p_double[nin], 1, ae_v_len(0,nout-1));
30412  }
30413  dserraccumulate(&buf, &y, &dy, _state);
30414  }
30415  dserrfinish(&buf, _state);
30416  *relcls = buf.ptr.p_double[0];
30417  *avgce = buf.ptr.p_double[1];
30418  *rms = buf.ptr.p_double[2];
30419  *avg = buf.ptr.p_double[3];
30420  *avgrel = buf.ptr.p_double[4];
30421  ae_frame_leave(_state);
30422 }
30423 
30424 
30425 /*************************************************************************
30426 Relative classification error on the test set
30427 
30428 INPUT PARAMETERS:
30429  Ensemble- ensemble
30430  XY - test set
30431  NPoints - test set size
30432 
30433 RESULT:
30434  percent of incorrectly classified cases.
30435  Works both for classifier betwork and for regression networks which
30436 are used as classifiers.
30437 
30438  -- ALGLIB --
30439  Copyright 17.02.2009 by Bochkanov Sergey
30440 *************************************************************************/
30441 double mlperelclserror(mlpensemble* ensemble,
30442  /* Real */ ae_matrix* xy,
30443  ae_int_t npoints,
30444  ae_state *_state)
30445 {
30446  ae_frame _frame_block;
30447  modelerrors rep;
30448  double result;
30449 
30450  ae_frame_make(_state, &_frame_block);
30451  _modelerrors_init(&rep, _state, ae_true);
30452 
30453  mlpeallerrorsx(ensemble, xy, &ensemble->network.dummysxy, npoints, 0, &ensemble->network.dummyidx, 0, npoints, 0, &ensemble->network.buf, &rep, _state);
30454  result = rep.relclserror;
30455  ae_frame_leave(_state);
30456  return result;
30457 }
30458 
30459 
30460 /*************************************************************************
30461 Average cross-entropy (in bits per element) on the test set
30462 
30463 INPUT PARAMETERS:
30464  Ensemble- ensemble
30465  XY - test set
30466  NPoints - test set size
30467 
30468 RESULT:
30469  CrossEntropy/(NPoints*LN(2)).
30470  Zero if ensemble solves regression task.
30471 
30472  -- ALGLIB --
30473  Copyright 17.02.2009 by Bochkanov Sergey
30474 *************************************************************************/
30475 double mlpeavgce(mlpensemble* ensemble,
30476  /* Real */ ae_matrix* xy,
30477  ae_int_t npoints,
30478  ae_state *_state)
30479 {
30480  ae_frame _frame_block;
30481  modelerrors rep;
30482  double result;
30483 
30484  ae_frame_make(_state, &_frame_block);
30485  _modelerrors_init(&rep, _state, ae_true);
30486 
30487  mlpeallerrorsx(ensemble, xy, &ensemble->network.dummysxy, npoints, 0, &ensemble->network.dummyidx, 0, npoints, 0, &ensemble->network.buf, &rep, _state);
30488  result = rep.avgce;
30489  ae_frame_leave(_state);
30490  return result;
30491 }
30492 
30493 
30494 /*************************************************************************
30495 RMS error on the test set
30496 
30497 INPUT PARAMETERS:
30498  Ensemble- ensemble
30499  XY - test set
30500  NPoints - test set size
30501 
30502 RESULT:
30503  root mean square error.
30504  Its meaning for regression task is obvious. As for classification task
30505 RMS error means error when estimating posterior probabilities.
30506 
30507  -- ALGLIB --
30508  Copyright 17.02.2009 by Bochkanov Sergey
30509 *************************************************************************/
30510 double mlpermserror(mlpensemble* ensemble,
30511  /* Real */ ae_matrix* xy,
30512  ae_int_t npoints,
30513  ae_state *_state)
30514 {
30515  ae_frame _frame_block;
30516  modelerrors rep;
30517  double result;
30518 
30519  ae_frame_make(_state, &_frame_block);
30520  _modelerrors_init(&rep, _state, ae_true);
30521 
30522  mlpeallerrorsx(ensemble, xy, &ensemble->network.dummysxy, npoints, 0, &ensemble->network.dummyidx, 0, npoints, 0, &ensemble->network.buf, &rep, _state);
30523  result = rep.rmserror;
30524  ae_frame_leave(_state);
30525  return result;
30526 }
30527 
30528 
30529 /*************************************************************************
30530 Average error on the test set
30531 
30532 INPUT PARAMETERS:
30533  Ensemble- ensemble
30534  XY - test set
30535  NPoints - test set size
30536 
30537 RESULT:
30538  Its meaning for regression task is obvious. As for classification task
30539 it means average error when estimating posterior probabilities.
30540 
30541  -- ALGLIB --
30542  Copyright 17.02.2009 by Bochkanov Sergey
30543 *************************************************************************/
30544 double mlpeavgerror(mlpensemble* ensemble,
30545  /* Real */ ae_matrix* xy,
30546  ae_int_t npoints,
30547  ae_state *_state)
30548 {
30549  ae_frame _frame_block;
30550  modelerrors rep;
30551  double result;
30552 
30553  ae_frame_make(_state, &_frame_block);
30554  _modelerrors_init(&rep, _state, ae_true);
30555 
30556  mlpeallerrorsx(ensemble, xy, &ensemble->network.dummysxy, npoints, 0, &ensemble->network.dummyidx, 0, npoints, 0, &ensemble->network.buf, &rep, _state);
30557  result = rep.avgerror;
30558  ae_frame_leave(_state);
30559  return result;
30560 }
30561 
30562 
30563 /*************************************************************************
30564 Average relative error on the test set
30565 
30566 INPUT PARAMETERS:
30567  Ensemble- ensemble
30568  XY - test set
30569  NPoints - test set size
30570 
30571 RESULT:
30572  Its meaning for regression task is obvious. As for classification task
30573 it means average relative error when estimating posterior probabilities.
30574 
30575  -- ALGLIB --
30576  Copyright 17.02.2009 by Bochkanov Sergey
30577 *************************************************************************/
30578 double mlpeavgrelerror(mlpensemble* ensemble,
30579  /* Real */ ae_matrix* xy,
30580  ae_int_t npoints,
30581  ae_state *_state)
30582 {
30583  ae_frame _frame_block;
30584  modelerrors rep;
30585  double result;
30586 
30587  ae_frame_make(_state, &_frame_block);
30588  _modelerrors_init(&rep, _state, ae_true);
30589 
30590  mlpeallerrorsx(ensemble, xy, &ensemble->network.dummysxy, npoints, 0, &ensemble->network.dummyidx, 0, npoints, 0, &ensemble->network.buf, &rep, _state);
30591  result = rep.avgrelerror;
30592  ae_frame_leave(_state);
30593  return result;
30594 }
30595 
30596 
30597 /*************************************************************************
30598 Serializer: allocation
30599 
30600  -- ALGLIB --
30601  Copyright 19.10.2011 by Bochkanov Sergey
30602 *************************************************************************/
30603 void mlpealloc(ae_serializer* s, mlpensemble* ensemble, ae_state *_state)
30604 {
30605 
30606 
30607  ae_serializer_alloc_entry(s);
30608  ae_serializer_alloc_entry(s);
30609  ae_serializer_alloc_entry(s);
30610  allocrealarray(s, &ensemble->weights, -1, _state);
30611  allocrealarray(s, &ensemble->columnmeans, -1, _state);
30612  allocrealarray(s, &ensemble->columnsigmas, -1, _state);
30613  mlpalloc(s, &ensemble->network, _state);
30614 }
30615 
30616 
30617 /*************************************************************************
30618 Serializer: serialization
30619 
30620  -- ALGLIB --
30621  Copyright 14.03.2011 by Bochkanov Sergey
30622 *************************************************************************/
30623 void mlpeserialize(ae_serializer* s,
30624  mlpensemble* ensemble,
30625  ae_state *_state)
30626 {
30627 
30628 
30629  ae_serializer_serialize_int(s, getmlpeserializationcode(_state), _state);
30630  ae_serializer_serialize_int(s, mlpe_mlpefirstversion, _state);
30631  ae_serializer_serialize_int(s, ensemble->ensemblesize, _state);
30632  serializerealarray(s, &ensemble->weights, -1, _state);
30633  serializerealarray(s, &ensemble->columnmeans, -1, _state);
30634  serializerealarray(s, &ensemble->columnsigmas, -1, _state);
30635  mlpserialize(s, &ensemble->network, _state);
30636 }
30637 
30638 
30639 /*************************************************************************
30640 Serializer: unserialization
30641 
30642  -- ALGLIB --
30643  Copyright 14.03.2011 by Bochkanov Sergey
30644 *************************************************************************/
30645 void mlpeunserialize(ae_serializer* s,
30646  mlpensemble* ensemble,
30647  ae_state *_state)
30648 {
30649  ae_int_t i0;
30650  ae_int_t i1;
30651 
30652  _mlpensemble_clear(ensemble);
30653 
30654 
30655  /*
30656  * check correctness of header
30657  */
30658  ae_serializer_unserialize_int(s, &i0, _state);
30659  ae_assert(i0==getmlpeserializationcode(_state), "MLPEUnserialize: stream header corrupted", _state);
30660  ae_serializer_unserialize_int(s, &i1, _state);
30661  ae_assert(i1==mlpe_mlpefirstversion, "MLPEUnserialize: stream header corrupted", _state);
30662 
30663  /*
30664  * Create network
30665  */
30666  ae_serializer_unserialize_int(s, &ensemble->ensemblesize, _state);
30667  unserializerealarray(s, &ensemble->weights, _state);
30668  unserializerealarray(s, &ensemble->columnmeans, _state);
30669  unserializerealarray(s, &ensemble->columnsigmas, _state);
30670  mlpunserialize(s, &ensemble->network, _state);
30671 
30672  /*
30673  * Allocate termoraries
30674  */
30675  ae_vector_set_length(&ensemble->y, mlpgetoutputscount(&ensemble->network, _state), _state);
30676 }
30677 
30678 
30679 ae_bool _mlpensemble_init(void* _p, ae_state *_state, ae_bool make_automatic)
30680 {
30681  mlpensemble *p = (mlpensemble*)_p;
30682  ae_touch_ptr((void*)p);
30683  if( !ae_vector_init(&p->weights, 0, DT_REAL, _state, make_automatic) )
30684  return ae_false;
30685  if( !ae_vector_init(&p->columnmeans, 0, DT_REAL, _state, make_automatic) )
30686  return ae_false;
30687  if( !ae_vector_init(&p->columnsigmas, 0, DT_REAL, _state, make_automatic) )
30688  return ae_false;
30689  if( !_multilayerperceptron_init(&p->network, _state, make_automatic) )
30690  return ae_false;
30691  if( !ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic) )
30692  return ae_false;
30693  return ae_true;
30694 }
30695 
30696 
30697 ae_bool _mlpensemble_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
30698 {
30699  mlpensemble *dst = (mlpensemble*)_dst;
30700  mlpensemble *src = (mlpensemble*)_src;
30701  dst->ensemblesize = src->ensemblesize;
30702  if( !ae_vector_init_copy(&dst->weights, &src->weights, _state, make_automatic) )
30703  return ae_false;
30704  if( !ae_vector_init_copy(&dst->columnmeans, &src->columnmeans, _state, make_automatic) )
30705  return ae_false;
30706  if( !ae_vector_init_copy(&dst->columnsigmas, &src->columnsigmas, _state, make_automatic) )
30707  return ae_false;
30708  if( !_multilayerperceptron_init_copy(&dst->network, &src->network, _state, make_automatic) )
30709  return ae_false;
30710  if( !ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic) )
30711  return ae_false;
30712  return ae_true;
30713 }
30714 
30715 
30716 void _mlpensemble_clear(void* _p)
30717 {
30718  mlpensemble *p = (mlpensemble*)_p;
30719  ae_touch_ptr((void*)p);
30720  ae_vector_clear(&p->weights);
30721  ae_vector_clear(&p->columnmeans);
30722  ae_vector_clear(&p->columnsigmas);
30723  _multilayerperceptron_clear(&p->network);
30724  ae_vector_clear(&p->y);
30725 }
30726 
30727 
30728 void _mlpensemble_destroy(void* _p)
30729 {
30730  mlpensemble *p = (mlpensemble*)_p;
30731  ae_touch_ptr((void*)p);
30732  ae_vector_destroy(&p->weights);
30733  ae_vector_destroy(&p->columnmeans);
30734  ae_vector_destroy(&p->columnsigmas);
30735  _multilayerperceptron_destroy(&p->network);
30736  ae_vector_destroy(&p->y);
30737 }
30738 
30739 
30740 
30741 
30742 /*************************************************************************
30743 Neural network training using modified Levenberg-Marquardt with exact
30744 Hessian calculation and regularization. Subroutine trains neural network
30745 with restarts from random positions. Algorithm is well suited for small
30746 and medium scale problems (hundreds of weights).
30747 
30748 INPUT PARAMETERS:
30749  Network - neural network with initialized geometry
30750  XY - training set
30751  NPoints - training set size
30752  Decay - weight decay constant, >=0.001
30753  Decay term 'Decay*||Weights||^2' is added to error
30754  function.
30755  If you don't know what Decay to choose, use 0.001.
30756  Restarts - number of restarts from random position, >0.
30757  If you don't know what Restarts to choose, use 2.
30758 
30759 OUTPUT PARAMETERS:
30760  Network - trained neural network.
30761  Info - return code:
30762  * -9, if internal matrix inverse subroutine failed
30763  * -2, if there is a point with class number
30764  outside of [0..NOut-1].
30765  * -1, if wrong parameters specified
30766  (NPoints<0, Restarts<1).
30767  * 2, if task has been solved.
30768  Rep - training report
30769 
30770  -- ALGLIB --
30771  Copyright 10.03.2009 by Bochkanov Sergey
30772 *************************************************************************/
30773 void mlptrainlm(multilayerperceptron* network,
30774  /* Real */ ae_matrix* xy,
30775  ae_int_t npoints,
30776  double decay,
30777  ae_int_t restarts,
30778  ae_int_t* info,
30779  mlpreport* rep,
30780  ae_state *_state)
30781 {
30782  ae_frame _frame_block;
30783  ae_int_t nin;
30784  ae_int_t nout;
30785  ae_int_t wcount;
30786  double lmsteptol;
30787  ae_int_t i;
30788  ae_int_t k;
30789  double v;
30790  double e;
30791  double enew;
30792  double xnorm2;
30793  double stepnorm;
30794  ae_vector g;
30795  ae_vector d;
30796  ae_matrix h;
30797  ae_matrix hmod;
30798  ae_matrix z;
30799  ae_bool spd;
30800  double nu;
30801  double lambdav;
30802  double lambdaup;
30803  double lambdadown;
30804  minlbfgsreport internalrep;
30805  minlbfgsstate state;
30806  ae_vector x;
30807  ae_vector y;
30808  ae_vector wbase;
30809  ae_vector wdir;
30810  ae_vector wt;
30811  ae_vector wx;
30812  ae_int_t pass;
30813  ae_vector wbest;
30814  double ebest;
30815  ae_int_t invinfo;
30816  matinvreport invrep;
30817  ae_int_t solverinfo;
30818  densesolverreport solverrep;
30819 
30820  ae_frame_make(_state, &_frame_block);
30821  *info = 0;
30822  _mlpreport_clear(rep);
30823  ae_vector_init(&g, 0, DT_REAL, _state, ae_true);
30824  ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
30825  ae_matrix_init(&h, 0, 0, DT_REAL, _state, ae_true);
30826  ae_matrix_init(&hmod, 0, 0, DT_REAL, _state, ae_true);
30827  ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true);
30828  _minlbfgsreport_init(&internalrep, _state, ae_true);
30829  _minlbfgsstate_init(&state, _state, ae_true);
30830  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
30831  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
30832  ae_vector_init(&wbase, 0, DT_REAL, _state, ae_true);
30833  ae_vector_init(&wdir, 0, DT_REAL, _state, ae_true);
30834  ae_vector_init(&wt, 0, DT_REAL, _state, ae_true);
30835  ae_vector_init(&wx, 0, DT_REAL, _state, ae_true);
30836  ae_vector_init(&wbest, 0, DT_REAL, _state, ae_true);
30837  _matinvreport_init(&invrep, _state, ae_true);
30838  _densesolverreport_init(&solverrep, _state, ae_true);
30839 
30840  mlpproperties(network, &nin, &nout, &wcount, _state);
30841  lambdaup = 10;
30842  lambdadown = 0.3;
30843  lmsteptol = 0.001;
30844 
30845  /*
30846  * Test for inputs
30847  */
30848  if( npoints<=0||restarts<1 )
30849  {
30850  *info = -1;
30851  ae_frame_leave(_state);
30852  return;
30853  }
30854  if( mlpissoftmax(network, _state) )
30855  {
30856  for(i=0; i<=npoints-1; i++)
30857  {
30858  if( ae_round(xy->ptr.pp_double[i][nin], _state)<0||ae_round(xy->ptr.pp_double[i][nin], _state)>=nout )
30859  {
30860  *info = -2;
30861  ae_frame_leave(_state);
30862  return;
30863  }
30864  }
30865  }
30866  decay = ae_maxreal(decay, mlptrain_mindecay, _state);
30867  *info = 2;
30868 
30869  /*
30870  * Initialize data
30871  */
30872  rep->ngrad = 0;
30873  rep->nhess = 0;
30874  rep->ncholesky = 0;
30875 
30876  /*
30877  * General case.
30878  * Prepare task and network. Allocate space.
30879  */
30880  mlpinitpreprocessor(network, xy, npoints, _state);
30881  ae_vector_set_length(&g, wcount-1+1, _state);
30882  ae_matrix_set_length(&h, wcount-1+1, wcount-1+1, _state);
30883  ae_matrix_set_length(&hmod, wcount-1+1, wcount-1+1, _state);
30884  ae_vector_set_length(&wbase, wcount-1+1, _state);
30885  ae_vector_set_length(&wdir, wcount-1+1, _state);
30886  ae_vector_set_length(&wbest, wcount-1+1, _state);
30887  ae_vector_set_length(&wt, wcount-1+1, _state);
30888  ae_vector_set_length(&wx, wcount-1+1, _state);
30889  ebest = ae_maxrealnumber;
30890 
30891  /*
30892  * Multiple passes
30893  */
30894  for(pass=1; pass<=restarts; pass++)
30895  {
30896 
30897  /*
30898  * Initialize weights
30899  */
30900  mlprandomize(network, _state);
30901 
30902  /*
30903  * First stage of the hybrid algorithm: LBFGS
30904  */
30905  ae_v_move(&wbase.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
30906  minlbfgscreate(wcount, ae_minint(wcount, 5, _state), &wbase, &state, _state);
30907  minlbfgssetcond(&state, 0, 0, 0, ae_maxint(25, wcount, _state), _state);
30908  while(minlbfgsiteration(&state, _state))
30909  {
30910 
30911  /*
30912  * gradient
30913  */
30914  ae_v_move(&network->weights.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
30915  mlpgradbatch(network, xy, npoints, &state.f, &state.g, _state);
30916 
30917  /*
30918  * weight decay
30919  */
30920  v = ae_v_dotproduct(&network->weights.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
30921  state.f = state.f+0.5*decay*v;
30922  ae_v_addd(&state.g.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1), decay);
30923 
30924  /*
30925  * next iteration
30926  */
30927  rep->ngrad = rep->ngrad+1;
30928  }
30929  minlbfgsresults(&state, &wbase, &internalrep, _state);
30930  ae_v_move(&network->weights.ptr.p_double[0], 1, &wbase.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
30931 
30932  /*
30933  * Second stage of the hybrid algorithm: LM
30934  *
30935  * Initialize H with identity matrix,
30936  * G with gradient,
30937  * E with regularized error.
30938  */
30939  mlphessianbatch(network, xy, npoints, &e, &g, &h, _state);
30940  v = ae_v_dotproduct(&network->weights.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
30941  e = e+0.5*decay*v;
30942  ae_v_addd(&g.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1), decay);
30943  for(k=0; k<=wcount-1; k++)
30944  {
30945  h.ptr.pp_double[k][k] = h.ptr.pp_double[k][k]+decay;
30946  }
30947  rep->nhess = rep->nhess+1;
30948  lambdav = 0.001;
30949  nu = 2;
30950  for(;;)
30951  {
30952 
30953  /*
30954  * 1. HMod = H+lambda*I
30955  * 2. Try to solve (H+Lambda*I)*dx = -g.
30956  * Increase lambda if left part is not positive definite.
30957  */
30958  for(i=0; i<=wcount-1; i++)
30959  {
30960  ae_v_move(&hmod.ptr.pp_double[i][0], 1, &h.ptr.pp_double[i][0], 1, ae_v_len(0,wcount-1));
30961  hmod.ptr.pp_double[i][i] = hmod.ptr.pp_double[i][i]+lambdav;
30962  }
30963  spd = spdmatrixcholesky(&hmod, wcount, ae_true, _state);
30964  rep->ncholesky = rep->ncholesky+1;
30965  if( !spd )
30966  {
30967  lambdav = lambdav*lambdaup*nu;
30968  nu = nu*2;
30969  continue;
30970  }
30971  spdmatrixcholeskysolve(&hmod, wcount, ae_true, &g, &solverinfo, &solverrep, &wdir, _state);
30972  if( solverinfo<0 )
30973  {
30974  lambdav = lambdav*lambdaup*nu;
30975  nu = nu*2;
30976  continue;
30977  }
30978  ae_v_muld(&wdir.ptr.p_double[0], 1, ae_v_len(0,wcount-1), -1);
30979 
30980  /*
30981  * Lambda found.
30982  * 1. Save old w in WBase
30983  * 1. Test some stopping criterions
30984  * 2. If error(w+wdir)>error(w), increase lambda
30985  */
30986  ae_v_add(&network->weights.ptr.p_double[0], 1, &wdir.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
30987  xnorm2 = ae_v_dotproduct(&network->weights.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
30988  stepnorm = ae_v_dotproduct(&wdir.ptr.p_double[0], 1, &wdir.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
30989  stepnorm = ae_sqrt(stepnorm, _state);
30990  enew = mlperror(network, xy, npoints, _state)+0.5*decay*xnorm2;
30991  if( ae_fp_less(stepnorm,lmsteptol*(1+ae_sqrt(xnorm2, _state))) )
30992  {
30993  break;
30994  }
30995  if( ae_fp_greater(enew,e) )
30996  {
30997  lambdav = lambdav*lambdaup*nu;
30998  nu = nu*2;
30999  continue;
31000  }
31001 
31002  /*
31003  * Optimize using inv(cholesky(H)) as preconditioner
31004  */
31005  rmatrixtrinverse(&hmod, wcount, ae_true, ae_false, &invinfo, &invrep, _state);
31006  if( invinfo<=0 )
31007  {
31008 
31009  /*
31010  * if matrix can't be inverted then exit with errors
31011  * TODO: make WCount steps in direction suggested by HMod
31012  */
31013  *info = -9;
31014  ae_frame_leave(_state);
31015  return;
31016  }
31017  ae_v_move(&wbase.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
31018  for(i=0; i<=wcount-1; i++)
31019  {
31020  wt.ptr.p_double[i] = 0;
31021  }
31022  minlbfgscreatex(wcount, wcount, &wt, 1, 0.0, &state, _state);
31023  minlbfgssetcond(&state, 0, 0, 0, 5, _state);
31024  while(minlbfgsiteration(&state, _state))
31025  {
31026 
31027  /*
31028  * gradient
31029  */
31030  for(i=0; i<=wcount-1; i++)
31031  {
31032  v = ae_v_dotproduct(&state.x.ptr.p_double[i], 1, &hmod.ptr.pp_double[i][i], 1, ae_v_len(i,wcount-1));
31033  network->weights.ptr.p_double[i] = wbase.ptr.p_double[i]+v;
31034  }
31035  mlpgradbatch(network, xy, npoints, &state.f, &g, _state);
31036  for(i=0; i<=wcount-1; i++)
31037  {
31038  state.g.ptr.p_double[i] = 0;
31039  }
31040  for(i=0; i<=wcount-1; i++)
31041  {
31042  v = g.ptr.p_double[i];
31043  ae_v_addd(&state.g.ptr.p_double[i], 1, &hmod.ptr.pp_double[i][i], 1, ae_v_len(i,wcount-1), v);
31044  }
31045 
31046  /*
31047  * weight decay
31048  * grad(x'*x) = A'*(x0+A*t)
31049  */
31050  v = ae_v_dotproduct(&network->weights.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
31051  state.f = state.f+0.5*decay*v;
31052  for(i=0; i<=wcount-1; i++)
31053  {
31054  v = decay*network->weights.ptr.p_double[i];
31055  ae_v_addd(&state.g.ptr.p_double[i], 1, &hmod.ptr.pp_double[i][i], 1, ae_v_len(i,wcount-1), v);
31056  }
31057 
31058  /*
31059  * next iteration
31060  */
31061  rep->ngrad = rep->ngrad+1;
31062  }
31063  minlbfgsresults(&state, &wt, &internalrep, _state);
31064 
31065  /*
31066  * Accept new position.
31067  * Calculate Hessian
31068  */
31069  for(i=0; i<=wcount-1; i++)
31070  {
31071  v = ae_v_dotproduct(&wt.ptr.p_double[i], 1, &hmod.ptr.pp_double[i][i], 1, ae_v_len(i,wcount-1));
31072  network->weights.ptr.p_double[i] = wbase.ptr.p_double[i]+v;
31073  }
31074  mlphessianbatch(network, xy, npoints, &e, &g, &h, _state);
31075  v = ae_v_dotproduct(&network->weights.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
31076  e = e+0.5*decay*v;
31077  ae_v_addd(&g.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1), decay);
31078  for(k=0; k<=wcount-1; k++)
31079  {
31080  h.ptr.pp_double[k][k] = h.ptr.pp_double[k][k]+decay;
31081  }
31082  rep->nhess = rep->nhess+1;
31083 
31084  /*
31085  * Update lambda
31086  */
31087  lambdav = lambdav*lambdadown;
31088  nu = 2;
31089  }
31090 
31091  /*
31092  * update WBest
31093  */
31094  v = ae_v_dotproduct(&network->weights.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
31095  e = 0.5*decay*v+mlperror(network, xy, npoints, _state);
31096  if( ae_fp_less(e,ebest) )
31097  {
31098  ebest = e;
31099  ae_v_move(&wbest.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
31100  }
31101  }
31102 
31103  /*
31104  * copy WBest to output
31105  */
31106  ae_v_move(&network->weights.ptr.p_double[0], 1, &wbest.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
31107  ae_frame_leave(_state);
31108 }
31109 
31110 
31111 /*************************************************************************
31112 Neural network training using L-BFGS algorithm with regularization.
31113 Subroutine trains neural network with restarts from random positions.
31114 Algorithm is well suited for problems of any dimensionality (memory
31115 requirements and step complexity are linear by weights number).
31116 
31117 INPUT PARAMETERS:
31118  Network - neural network with initialized geometry
31119  XY - training set
31120  NPoints - training set size
31121  Decay - weight decay constant, >=0.001
31122  Decay term 'Decay*||Weights||^2' is added to error
31123  function.
31124  If you don't know what Decay to choose, use 0.001.
31125  Restarts - number of restarts from random position, >0.
31126  If you don't know what Restarts to choose, use 2.
31127  WStep - stopping criterion. Algorithm stops if step size is
31128  less than WStep. Recommended value - 0.01. Zero step
31129  size means stopping after MaxIts iterations.
31130  MaxIts - stopping criterion. Algorithm stops after MaxIts
31131  iterations (NOT gradient calculations). Zero MaxIts
31132  means stopping when step is sufficiently small.
31133 
31134 OUTPUT PARAMETERS:
31135  Network - trained neural network.
31136  Info - return code:
31137  * -8, if both WStep=0 and MaxIts=0
31138  * -2, if there is a point with class number
31139  outside of [0..NOut-1].
31140  * -1, if wrong parameters specified
31141  (NPoints<0, Restarts<1).
31142  * 2, if task has been solved.
31143  Rep - training report
31144 
31145  -- ALGLIB --
31146  Copyright 09.12.2007 by Bochkanov Sergey
31147 *************************************************************************/
31148 void mlptrainlbfgs(multilayerperceptron* network,
31149  /* Real */ ae_matrix* xy,
31150  ae_int_t npoints,
31151  double decay,
31152  ae_int_t restarts,
31153  double wstep,
31154  ae_int_t maxits,
31155  ae_int_t* info,
31156  mlpreport* rep,
31157  ae_state *_state)
31158 {
31159  ae_frame _frame_block;
31160  ae_int_t i;
31161  ae_int_t pass;
31162  ae_int_t nin;
31163  ae_int_t nout;
31164  ae_int_t wcount;
31165  ae_vector w;
31166  ae_vector wbest;
31167  double e;
31168  double v;
31169  double ebest;
31170  minlbfgsreport internalrep;
31171  minlbfgsstate state;
31172 
31173  ae_frame_make(_state, &_frame_block);
31174  *info = 0;
31175  _mlpreport_clear(rep);
31176  ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
31177  ae_vector_init(&wbest, 0, DT_REAL, _state, ae_true);
31178  _minlbfgsreport_init(&internalrep, _state, ae_true);
31179  _minlbfgsstate_init(&state, _state, ae_true);
31180 
31181 
31182  /*
31183  * Test inputs, parse flags, read network geometry
31184  */
31185  if( ae_fp_eq(wstep,0)&&maxits==0 )
31186  {
31187  *info = -8;
31188  ae_frame_leave(_state);
31189  return;
31190  }
31191  if( ((npoints<=0||restarts<1)||ae_fp_less(wstep,0))||maxits<0 )
31192  {
31193  *info = -1;
31194  ae_frame_leave(_state);
31195  return;
31196  }
31197  mlpproperties(network, &nin, &nout, &wcount, _state);
31198  if( mlpissoftmax(network, _state) )
31199  {
31200  for(i=0; i<=npoints-1; i++)
31201  {
31202  if( ae_round(xy->ptr.pp_double[i][nin], _state)<0||ae_round(xy->ptr.pp_double[i][nin], _state)>=nout )
31203  {
31204  *info = -2;
31205  ae_frame_leave(_state);
31206  return;
31207  }
31208  }
31209  }
31210  decay = ae_maxreal(decay, mlptrain_mindecay, _state);
31211  *info = 2;
31212 
31213  /*
31214  * Prepare
31215  */
31216  mlpinitpreprocessor(network, xy, npoints, _state);
31217  ae_vector_set_length(&w, wcount-1+1, _state);
31218  ae_vector_set_length(&wbest, wcount-1+1, _state);
31219  ebest = ae_maxrealnumber;
31220 
31221  /*
31222  * Multiple starts
31223  */
31224  rep->ncholesky = 0;
31225  rep->nhess = 0;
31226  rep->ngrad = 0;
31227  for(pass=1; pass<=restarts; pass++)
31228  {
31229 
31230  /*
31231  * Process
31232  */
31233  mlprandomize(network, _state);
31234  ae_v_move(&w.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
31235  minlbfgscreate(wcount, ae_minint(wcount, 10, _state), &w, &state, _state);
31236  minlbfgssetcond(&state, 0.0, 0.0, wstep, maxits, _state);
31237  while(minlbfgsiteration(&state, _state))
31238  {
31239  ae_v_move(&network->weights.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
31240  mlpgradnbatch(network, xy, npoints, &state.f, &state.g, _state);
31241  v = ae_v_dotproduct(&network->weights.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
31242  state.f = state.f+0.5*decay*v;
31243  ae_v_addd(&state.g.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1), decay);
31244  rep->ngrad = rep->ngrad+1;
31245  }
31246  minlbfgsresults(&state, &w, &internalrep, _state);
31247  ae_v_move(&network->weights.ptr.p_double[0], 1, &w.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
31248 
31249  /*
31250  * Compare with best
31251  */
31252  v = ae_v_dotproduct(&network->weights.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
31253  e = mlperrorn(network, xy, npoints, _state)+0.5*decay*v;
31254  if( ae_fp_less(e,ebest) )
31255  {
31256  ae_v_move(&wbest.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
31257  ebest = e;
31258  }
31259  }
31260 
31261  /*
31262  * The best network
31263  */
31264  ae_v_move(&network->weights.ptr.p_double[0], 1, &wbest.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
31265  ae_frame_leave(_state);
31266 }
31267 
31268 
31269 /*************************************************************************
31270 Neural network training using early stopping (base algorithm - L-BFGS with
31271 regularization).
31272 
31273 INPUT PARAMETERS:
31274  Network - neural network with initialized geometry
31275  TrnXY - training set
31276  TrnSize - training set size, TrnSize>0
31277  ValXY - validation set
31278  ValSize - validation set size, ValSize>0
31279  Decay - weight decay constant, >=0.001
31280  Decay term 'Decay*||Weights||^2' is added to error
31281  function.
31282  If you don't know what Decay to choose, use 0.001.
31283  Restarts - number of restarts, either:
31284  * strictly positive number - algorithm make specified
31285  number of restarts from random position.
31286  * -1, in which case algorithm makes exactly one run
31287  from the initial state of the network (no randomization).
31288  If you don't know what Restarts to choose, choose one
31289  one the following:
31290  * -1 (deterministic start)
31291  * +1 (one random restart)
31292  * +5 (moderate amount of random restarts)
31293 
31294 OUTPUT PARAMETERS:
31295  Network - trained neural network.
31296  Info - return code:
31297  * -2, if there is a point with class number
31298  outside of [0..NOut-1].
31299  * -1, if wrong parameters specified
31300  (NPoints<0, Restarts<1, ...).
31301  * 2, task has been solved, stopping criterion met -
31302  sufficiently small step size. Not expected (we
31303  use EARLY stopping) but possible and not an
31304  error.
31305  * 6, task has been solved, stopping criterion met -
31306  increasing of validation set error.
31307  Rep - training report
31308 
31309 NOTE:
31310 
31311 Algorithm stops if validation set error increases for a long enough or
31312 step size is small enought (there are task where validation set may
31313 decrease for eternity). In any case solution returned corresponds to the
31314 minimum of validation set error.
31315 
31316  -- ALGLIB --
31317  Copyright 10.03.2009 by Bochkanov Sergey
31318 *************************************************************************/
31319 void mlptraines(multilayerperceptron* network,
31320  /* Real */ ae_matrix* trnxy,
31321  ae_int_t trnsize,
31322  /* Real */ ae_matrix* valxy,
31323  ae_int_t valsize,
31324  double decay,
31325  ae_int_t restarts,
31326  ae_int_t* info,
31327  mlpreport* rep,
31328  ae_state *_state)
31329 {
31330  ae_frame _frame_block;
31331  ae_int_t i;
31332  ae_int_t pass;
31333  ae_int_t nin;
31334  ae_int_t nout;
31335  ae_int_t wcount;
31336  ae_vector w;
31337  ae_vector wbest;
31338  double e;
31339  double v;
31340  double ebest;
31341  ae_vector wfinal;
31342  double efinal;
31343  ae_int_t itcnt;
31344  ae_int_t itbest;
31345  minlbfgsreport internalrep;
31346  minlbfgsstate state;
31347  double wstep;
31348  ae_bool needrandomization;
31349 
31350  ae_frame_make(_state, &_frame_block);
31351  *info = 0;
31352  _mlpreport_clear(rep);
31353  ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
31354  ae_vector_init(&wbest, 0, DT_REAL, _state, ae_true);
31355  ae_vector_init(&wfinal, 0, DT_REAL, _state, ae_true);
31356  _minlbfgsreport_init(&internalrep, _state, ae_true);
31357  _minlbfgsstate_init(&state, _state, ae_true);
31358 
31359  wstep = 0.001;
31360 
31361  /*
31362  * Test inputs, parse flags, read network geometry
31363  */
31364  if( ((trnsize<=0||valsize<=0)||(restarts<1&&restarts!=-1))||ae_fp_less(decay,0) )
31365  {
31366  *info = -1;
31367  ae_frame_leave(_state);
31368  return;
31369  }
31370  if( restarts==-1 )
31371  {
31372  needrandomization = ae_false;
31373  restarts = 1;
31374  }
31375  else
31376  {
31377  needrandomization = ae_true;
31378  }
31379  mlpproperties(network, &nin, &nout, &wcount, _state);
31380  if( mlpissoftmax(network, _state) )
31381  {
31382  for(i=0; i<=trnsize-1; i++)
31383  {
31384  if( ae_round(trnxy->ptr.pp_double[i][nin], _state)<0||ae_round(trnxy->ptr.pp_double[i][nin], _state)>=nout )
31385  {
31386  *info = -2;
31387  ae_frame_leave(_state);
31388  return;
31389  }
31390  }
31391  for(i=0; i<=valsize-1; i++)
31392  {
31393  if( ae_round(valxy->ptr.pp_double[i][nin], _state)<0||ae_round(valxy->ptr.pp_double[i][nin], _state)>=nout )
31394  {
31395  *info = -2;
31396  ae_frame_leave(_state);
31397  return;
31398  }
31399  }
31400  }
31401  *info = 2;
31402 
31403  /*
31404  * Prepare
31405  */
31406  mlpinitpreprocessor(network, trnxy, trnsize, _state);
31407  ae_vector_set_length(&w, wcount-1+1, _state);
31408  ae_vector_set_length(&wbest, wcount-1+1, _state);
31409  ae_vector_set_length(&wfinal, wcount-1+1, _state);
31410  efinal = ae_maxrealnumber;
31411  for(i=0; i<=wcount-1; i++)
31412  {
31413  wfinal.ptr.p_double[i] = 0;
31414  }
31415 
31416  /*
31417  * Multiple starts
31418  */
31419  rep->ncholesky = 0;
31420  rep->nhess = 0;
31421  rep->ngrad = 0;
31422  for(pass=1; pass<=restarts; pass++)
31423  {
31424 
31425  /*
31426  * Process
31427  */
31428  if( needrandomization )
31429  {
31430  mlprandomize(network, _state);
31431  }
31432  ebest = mlperror(network, valxy, valsize, _state);
31433  ae_v_move(&wbest.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
31434  itbest = 0;
31435  itcnt = 0;
31436  ae_v_move(&w.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
31437  minlbfgscreate(wcount, ae_minint(wcount, 10, _state), &w, &state, _state);
31438  minlbfgssetcond(&state, 0.0, 0.0, wstep, 0, _state);
31439  minlbfgssetxrep(&state, ae_true, _state);
31440  while(minlbfgsiteration(&state, _state))
31441  {
31442 
31443  /*
31444  * Calculate gradient
31445  */
31446  if( state.needfg )
31447  {
31448  ae_v_move(&network->weights.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
31449  mlpgradnbatch(network, trnxy, trnsize, &state.f, &state.g, _state);
31450  v = ae_v_dotproduct(&network->weights.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
31451  state.f = state.f+0.5*decay*v;
31452  ae_v_addd(&state.g.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1), decay);
31453  rep->ngrad = rep->ngrad+1;
31454  }
31455 
31456  /*
31457  * Validation set
31458  */
31459  if( state.xupdated )
31460  {
31461  ae_v_move(&network->weights.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
31462  e = mlperror(network, valxy, valsize, _state);
31463  if( ae_fp_less(e,ebest) )
31464  {
31465  ebest = e;
31466  ae_v_move(&wbest.ptr.p_double[0], 1, &network->weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
31467  itbest = itcnt;
31468  }
31469  if( itcnt>30&&ae_fp_greater(itcnt,1.5*itbest) )
31470  {
31471  *info = 6;
31472  break;
31473  }
31474  itcnt = itcnt+1;
31475  }
31476  }
31477  minlbfgsresults(&state, &w, &internalrep, _state);
31478 
31479  /*
31480  * Compare with final answer
31481  */
31482  if( ae_fp_less(ebest,efinal) )
31483  {
31484  ae_v_move(&wfinal.ptr.p_double[0], 1, &wbest.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
31485  efinal = ebest;
31486  }
31487  }
31488 
31489  /*
31490  * The best network
31491  */
31492  ae_v_move(&network->weights.ptr.p_double[0], 1, &wfinal.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
31493  ae_frame_leave(_state);
31494 }
31495 
31496 
31497 /*************************************************************************
31498 Cross-validation estimate of generalization error.
31499 
31500 Base algorithm - L-BFGS.
31501 
31502 INPUT PARAMETERS:
31503  Network - neural network with initialized geometry. Network is
31504  not changed during cross-validation - it is used only
31505  as a representative of its architecture.
31506  XY - training set.
31507  SSize - training set size
31508  Decay - weight decay, same as in MLPTrainLBFGS
31509  Restarts - number of restarts, >0.
31510  restarts are counted for each partition separately, so
31511  total number of restarts will be Restarts*FoldsCount.
31512  WStep - stopping criterion, same as in MLPTrainLBFGS
31513  MaxIts - stopping criterion, same as in MLPTrainLBFGS
31514  FoldsCount - number of folds in k-fold cross-validation,
31515  2<=FoldsCount<=SSize.
31516  recommended value: 10.
31517 
31518 OUTPUT PARAMETERS:
31519  Info - return code, same as in MLPTrainLBFGS
31520  Rep - report, same as in MLPTrainLM/MLPTrainLBFGS
31521  CVRep - generalization error estimates
31522 
31523  -- ALGLIB --
31524  Copyright 09.12.2007 by Bochkanov Sergey
31525 *************************************************************************/
31526 void mlpkfoldcvlbfgs(multilayerperceptron* network,
31527  /* Real */ ae_matrix* xy,
31528  ae_int_t npoints,
31529  double decay,
31530  ae_int_t restarts,
31531  double wstep,
31532  ae_int_t maxits,
31533  ae_int_t foldscount,
31534  ae_int_t* info,
31535  mlpreport* rep,
31536  mlpcvreport* cvrep,
31537  ae_state *_state)
31538 {
31539 
31540  *info = 0;
31541  _mlpreport_clear(rep);
31542  _mlpcvreport_clear(cvrep);
31543 
31544  mlptrain_mlpkfoldcvgeneral(network, xy, npoints, decay, restarts, foldscount, ae_false, wstep, maxits, info, rep, cvrep, _state);
31545 }
31546 
31547 
31548 /*************************************************************************
31549 Cross-validation estimate of generalization error.
31550 
31551 Base algorithm - Levenberg-Marquardt.
31552 
31553 INPUT PARAMETERS:
31554  Network - neural network with initialized geometry. Network is
31555  not changed during cross-validation - it is used only
31556  as a representative of its architecture.
31557  XY - training set.
31558  SSize - training set size
31559  Decay - weight decay, same as in MLPTrainLBFGS
31560  Restarts - number of restarts, >0.
31561  restarts are counted for each partition separately, so
31562  total number of restarts will be Restarts*FoldsCount.
31563  FoldsCount - number of folds in k-fold cross-validation,
31564  2<=FoldsCount<=SSize.
31565  recommended value: 10.
31566 
31567 OUTPUT PARAMETERS:
31568  Info - return code, same as in MLPTrainLBFGS
31569  Rep - report, same as in MLPTrainLM/MLPTrainLBFGS
31570  CVRep - generalization error estimates
31571 
31572  -- ALGLIB --
31573  Copyright 09.12.2007 by Bochkanov Sergey
31574 *************************************************************************/
31575 void mlpkfoldcvlm(multilayerperceptron* network,
31576  /* Real */ ae_matrix* xy,
31577  ae_int_t npoints,
31578  double decay,
31579  ae_int_t restarts,
31580  ae_int_t foldscount,
31581  ae_int_t* info,
31582  mlpreport* rep,
31583  mlpcvreport* cvrep,
31584  ae_state *_state)
31585 {
31586 
31587  *info = 0;
31588  _mlpreport_clear(rep);
31589  _mlpcvreport_clear(cvrep);
31590 
31591  mlptrain_mlpkfoldcvgeneral(network, xy, npoints, decay, restarts, foldscount, ae_true, 0.0, 0, info, rep, cvrep, _state);
31592 }
31593 
31594 
31595 /*************************************************************************
31596 This function estimates generalization error using cross-validation on the
31597 current dataset with current training settings.
31598 
31599 FOR USERS OF COMMERCIAL EDITION:
31600 
31601  ! Commercial version of ALGLIB includes two important improvements of
31602  ! this function:
31603  ! * multicore support (C++ and C# computational cores)
31604  ! * SSE support (C++ computational core)
31605  !
31606  ! Second improvement gives constant speedup (2-3X). First improvement
31607  ! gives close-to-linear speedup on multicore systems. Following
31608  ! operations can be executed in parallel:
31609  ! * FoldsCount cross-validation rounds (always)
31610  ! * NRestarts training sessions performed within each of
31611  ! cross-validation rounds (if NRestarts>1)
31612  ! * gradient calculation over large dataset (if dataset is large enough)
31613  !
31614  ! In order to use multicore features you have to:
31615  ! * use commercial version of ALGLIB
31616  ! * call this function with "smp_" prefix, which indicates that
31617  ! multicore code will be used (for multicore support)
31618  !
31619  ! In order to use SSE features you have to:
31620  ! * use commercial version of ALGLIB on Intel processors
31621  ! * use C++ computational core
31622  !
31623  ! This note is given for users of commercial edition; if you use GPL
31624  ! edition, you still will be able to call smp-version of this function,
31625  ! but all computations will be done serially.
31626  !
31627  ! We recommend you to carefully read ALGLIB Reference Manual, section
31628  ! called 'SMP support', before using parallel version of this function.
31629 
31630 INPUT PARAMETERS:
31631  S - trainer object
31632  Network - neural network. It must have same number of inputs and
31633  output/classes as was specified during creation of the
31634  trainer object. Network is not changed during cross-
31635  validation and is not trained - it is used only as
31636  representative of its architecture. I.e., we estimate
31637  generalization properties of ARCHITECTURE, not some
31638  specific network.
31639  NRestarts - number of restarts, >=0:
31640  * NRestarts>0 means that for each cross-validation
31641  round specified number of random restarts is
31642  performed, with best network being chosen after
31643  training.
31644  * NRestarts=0 is same as NRestarts=1
31645  FoldsCount - number of folds in k-fold cross-validation:
31646  * 2<=FoldsCount<=size of dataset
31647  * recommended value: 10.
31648  * values larger than dataset size will be silently
31649  truncated down to dataset size
31650 
31651 OUTPUT PARAMETERS:
31652  Rep - structure which contains cross-validation estimates:
31653  * Rep.RelCLSError - fraction of misclassified cases.
31654  * Rep.AvgCE - acerage cross-entropy
31655  * Rep.RMSError - root-mean-square error
31656  * Rep.AvgError - average error
31657  * Rep.AvgRelError - average relative error
31658 
31659 NOTE: when no dataset was specified with MLPSetDataset/SetSparseDataset(),
31660  or subset with only one point was given, zeros are returned as
31661  estimates.
31662 
31663 NOTE: this method performs FoldsCount cross-validation rounds, each one
31664  with NRestarts random starts. Thus, FoldsCount*NRestarts networks
31665  are trained in total.
31666 
31667 NOTE: Rep.RelCLSError/Rep.AvgCE are zero on regression problems.
31668 
31669 NOTE: on classification problems Rep.RMSError/Rep.AvgError/Rep.AvgRelError
31670  contain errors in prediction of posterior probabilities.
31671 
31672  -- ALGLIB --
31673  Copyright 23.07.2012 by Bochkanov Sergey
31674 *************************************************************************/
31675 void mlpkfoldcv(mlptrainer* s,
31676  multilayerperceptron* network,
31677  ae_int_t nrestarts,
31678  ae_int_t foldscount,
31679  mlpreport* rep,
31680  ae_state *_state)
31681 {
31682  ae_frame _frame_block;
31683  ae_shared_pool pooldatacv;
31684  mlpparallelizationcv datacv;
31685  mlpparallelizationcv *sdatacv;
31686  ae_smart_ptr _sdatacv;
31687  ae_matrix cvy;
31688  ae_vector folds;
31689  ae_vector buf;
31690  ae_vector dy;
31691  ae_int_t nin;
31692  ae_int_t nout;
31693  ae_int_t wcount;
31694  ae_int_t rowsize;
31695  ae_int_t ntype;
31696  ae_int_t ttype;
31697  ae_int_t i;
31698  ae_int_t j;
31699  ae_int_t k;
31700  hqrndstate rs;
31701 
31702  ae_frame_make(_state, &_frame_block);
31703  _mlpreport_clear(rep);
31704  ae_shared_pool_init(&pooldatacv, _state, ae_true);
31705  _mlpparallelizationcv_init(&datacv, _state, ae_true);
31706  ae_smart_ptr_init(&_sdatacv, (void**)&sdatacv, _state, ae_true);
31707  ae_matrix_init(&cvy, 0, 0, DT_REAL, _state, ae_true);
31708  ae_vector_init(&folds, 0, DT_INT, _state, ae_true);
31709  ae_vector_init(&buf, 0, DT_REAL, _state, ae_true);
31710  ae_vector_init(&dy, 0, DT_REAL, _state, ae_true);
31711  _hqrndstate_init(&rs, _state, ae_true);
31712 
31713  if( !mlpissoftmax(network, _state) )
31714  {
31715  ntype = 0;
31716  }
31717  else
31718  {
31719  ntype = 1;
31720  }
31721  if( s->rcpar )
31722  {
31723  ttype = 0;
31724  }
31725  else
31726  {
31727  ttype = 1;
31728  }
31729  ae_assert(ntype==ttype, "MLPKFoldCV: type of input network is not similar to network type in trainer object", _state);
31730  ae_assert(s->npoints>=0, "MLPKFoldCV: possible trainer S is not initialized(S.NPoints<0)", _state);
31731  mlpproperties(network, &nin, &nout, &wcount, _state);
31732  ae_assert(s->nin==nin, "MLPKFoldCV: number of inputs in trainer is not equal to number of inputs in network", _state);
31733  ae_assert(s->nout==nout, "MLPKFoldCV: number of outputs in trainer is not equal to number of outputs in network", _state);
31734  ae_assert(nrestarts>=0, "MLPKFoldCV: NRestarts<0", _state);
31735  ae_assert(foldscount>=2, "MLPKFoldCV: FoldsCount<2", _state);
31736  if( foldscount>s->npoints )
31737  {
31738  foldscount = s->npoints;
31739  }
31740  rep->relclserror = 0;
31741  rep->avgce = 0;
31742  rep->rmserror = 0;
31743  rep->avgerror = 0;
31744  rep->avgrelerror = 0;
31745  hqrndrandomize(&rs, _state);
31746  rep->ngrad = 0;
31747  rep->nhess = 0;
31748  rep->ncholesky = 0;
31749  if( s->npoints==0||s->npoints==1 )
31750  {
31751  ae_frame_leave(_state);
31752  return;
31753  }
31754 
31755  /*
31756  * Read network geometry, test parameters
31757  */
31758  if( s->rcpar )
31759  {
31760  rowsize = nin+nout;
31761  ae_vector_set_length(&dy, nout, _state);
31762  dserrallocate(-nout, &buf, _state);
31763  }
31764  else
31765  {
31766  rowsize = nin+1;
31767  ae_vector_set_length(&dy, 1, _state);
31768  dserrallocate(nout, &buf, _state);
31769  }
31770 
31771  /*
31772  * Folds
31773  */
31774  ae_vector_set_length(&folds, s->npoints, _state);
31775  for(i=0; i<=s->npoints-1; i++)
31776  {
31777  folds.ptr.p_int[i] = i*foldscount/s->npoints;
31778  }
31779  for(i=0; i<=s->npoints-2; i++)
31780  {
31781  j = i+hqrnduniformi(&rs, s->npoints-i, _state);
31782  if( j!=i )
31783  {
31784  k = folds.ptr.p_int[i];
31785  folds.ptr.p_int[i] = folds.ptr.p_int[j];
31786  folds.ptr.p_int[j] = k;
31787  }
31788  }
31789  ae_matrix_set_length(&cvy, s->npoints, nout, _state);
31790 
31791  /*
31792  * Initialize SEED-value for shared pool
31793  */
31794  datacv.ngrad = 0;
31795  mlpcopy(network, &datacv.network, _state);
31796  ae_vector_set_length(&datacv.subset, s->npoints, _state);
31797  ae_vector_set_length(&datacv.xyrow, rowsize, _state);
31798  ae_vector_set_length(&datacv.y, nout, _state);
31799 
31800  /*
31801  * Create shared pool
31802  */
31803  ae_shared_pool_set_seed(&pooldatacv, &datacv, sizeof(datacv), _mlpparallelizationcv_init, _mlpparallelizationcv_init_copy, _mlpparallelizationcv_destroy, _state);
31804 
31805  /*
31806  * Parallelization
31807  */
31808  mlptrain_mthreadcv(s, rowsize, nrestarts, &folds, 0, foldscount, &cvy, &pooldatacv, _state);
31809 
31810  /*
31811  * Calculate value for NGrad
31812  */
31813  ae_shared_pool_first_recycled(&pooldatacv, &_sdatacv, _state);
31814  while(sdatacv!=NULL)
31815  {
31816  rep->ngrad = rep->ngrad+sdatacv->ngrad;
31817  ae_shared_pool_next_recycled(&pooldatacv, &_sdatacv, _state);
31818  }
31819 
31820  /*
31821  * Connect of results and calculate cross-validation error
31822  */
31823  for(i=0; i<=s->npoints-1; i++)
31824  {
31825  if( s->datatype==0 )
31826  {
31827  ae_v_move(&datacv.xyrow.ptr.p_double[0], 1, &s->densexy.ptr.pp_double[i][0], 1, ae_v_len(0,rowsize-1));
31828  }
31829  if( s->datatype==1 )
31830  {
31831  sparsegetrow(&s->sparsexy, i, &datacv.xyrow, _state);
31832  }
31833  ae_v_move(&datacv.y.ptr.p_double[0], 1, &cvy.ptr.pp_double[i][0], 1, ae_v_len(0,nout-1));
31834  if( s->rcpar )
31835  {
31836  ae_v_move(&dy.ptr.p_double[0], 1, &datacv.xyrow.ptr.p_double[nin], 1, ae_v_len(0,nout-1));
31837  }
31838  else
31839  {
31840  dy.ptr.p_double[0] = datacv.xyrow.ptr.p_double[nin];
31841  }
31842  dserraccumulate(&buf, &datacv.y, &dy, _state);
31843  }
31844  dserrfinish(&buf, _state);
31845  rep->relclserror = buf.ptr.p_double[0];
31846  rep->avgce = buf.ptr.p_double[1];
31847  rep->rmserror = buf.ptr.p_double[2];
31848  rep->avgerror = buf.ptr.p_double[3];
31849  rep->avgrelerror = buf.ptr.p_double[4];
31850  ae_frame_leave(_state);
31851 }
31852 
31853 
31854 /*************************************************************************
31855 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
31856 *************************************************************************/
31857 void _pexec_mlpkfoldcv(mlptrainer* s,
31858  multilayerperceptron* network,
31859  ae_int_t nrestarts,
31860  ae_int_t foldscount,
31861  mlpreport* rep, ae_state *_state)
31862 {
31863  mlpkfoldcv(s,network,nrestarts,foldscount,rep, _state);
31864 }
31865 
31866 
31867 /*************************************************************************
31868 Creation of the network trainer object for regression networks
31869 
31870 INPUT PARAMETERS:
31871  NIn - number of inputs, NIn>=1
31872  NOut - number of outputs, NOut>=1
31873 
31874 OUTPUT PARAMETERS:
31875  S - neural network trainer object.
31876  This structure can be used to train any regression
31877  network with NIn inputs and NOut outputs.
31878 
31879  -- ALGLIB --
31880  Copyright 23.07.2012 by Bochkanov Sergey
31881 *************************************************************************/
31882 void mlpcreatetrainer(ae_int_t nin,
31883  ae_int_t nout,
31884  mlptrainer* s,
31885  ae_state *_state)
31886 {
31887 
31888  _mlptrainer_clear(s);
31889 
31890  ae_assert(nin>=1, "MLPCreateTrainer: NIn<1.", _state);
31891  ae_assert(nout>=1, "MLPCreateTrainer: NOut<1.", _state);
31892  s->nin = nin;
31893  s->nout = nout;
31894  s->rcpar = ae_true;
31895  s->lbfgsfactor = mlptrain_defaultlbfgsfactor;
31896  s->decay = 1.0E-6;
31897  mlpsetcond(s, 0, 0, _state);
31898  s->datatype = 0;
31899  s->npoints = 0;
31900  mlpsetalgobatch(s, _state);
31901 }
31902 
31903 
31904 /*************************************************************************
31905 Creation of the network trainer object for classification networks
31906 
31907 INPUT PARAMETERS:
31908  NIn - number of inputs, NIn>=1
31909  NClasses - number of classes, NClasses>=2
31910 
31911 OUTPUT PARAMETERS:
31912  S - neural network trainer object.
31913  This structure can be used to train any classification
31914  network with NIn inputs and NOut outputs.
31915 
31916  -- ALGLIB --
31917  Copyright 23.07.2012 by Bochkanov Sergey
31918 *************************************************************************/
31919 void mlpcreatetrainercls(ae_int_t nin,
31920  ae_int_t nclasses,
31921  mlptrainer* s,
31922  ae_state *_state)
31923 {
31924 
31925  _mlptrainer_clear(s);
31926 
31927  ae_assert(nin>=1, "MLPCreateTrainerCls: NIn<1.", _state);
31928  ae_assert(nclasses>=2, "MLPCreateTrainerCls: NClasses<2.", _state);
31929  s->nin = nin;
31930  s->nout = nclasses;
31931  s->rcpar = ae_false;
31932  s->lbfgsfactor = mlptrain_defaultlbfgsfactor;
31933  s->decay = 1.0E-6;
31934  mlpsetcond(s, 0, 0, _state);
31935  s->datatype = 0;
31936  s->npoints = 0;
31937  mlpsetalgobatch(s, _state);
31938 }
31939 
31940 
31941 /*************************************************************************
31942 This function sets "current dataset" of the trainer object to one passed
31943 by user.
31944 
31945 INPUT PARAMETERS:
31946  S - trainer object
31947  XY - training set, see below for information on the
31948  training set format. This function checks correctness
31949  of the dataset (no NANs/INFs, class numbers are
31950  correct) and throws exception when incorrect dataset
31951  is passed.
31952  NPoints - points count, >=0.
31953 
31954 DATASET FORMAT:
31955 
31956 This function uses two different dataset formats - one for regression
31957 networks, another one for classification networks.
31958 
31959 For regression networks with NIn inputs and NOut outputs following dataset
31960 format is used:
31961 * dataset is given by NPoints*(NIn+NOut) matrix
31962 * each row corresponds to one example
31963 * first NIn columns are inputs, next NOut columns are outputs
31964 
31965 For classification networks with NIn inputs and NClasses clases following
31966 datasetformat is used:
31967 * dataset is given by NPoints*(NIn+1) matrix
31968 * each row corresponds to one example
31969 * first NIn columns are inputs, last column stores class number (from 0 to
31970  NClasses-1).
31971 
31972  -- ALGLIB --
31973  Copyright 23.07.2012 by Bochkanov Sergey
31974 *************************************************************************/
31975 void mlpsetdataset(mlptrainer* s,
31976  /* Real */ ae_matrix* xy,
31977  ae_int_t npoints,
31978  ae_state *_state)
31979 {
31980  ae_int_t ndim;
31981  ae_int_t i;
31982  ae_int_t j;
31983 
31984 
31985  ae_assert(s->nin>=1, "MLPSetDataset: possible parameter S is not initialized or spoiled(S.NIn<=0).", _state);
31986  ae_assert(npoints>=0, "MLPSetDataset: NPoint<0", _state);
31987  ae_assert(npoints<=xy->rows, "MLPSetDataset: invalid size of matrix XY(NPoint more then rows of matrix XY)", _state);
31988  s->datatype = 0;
31989  s->npoints = npoints;
31990  if( npoints==0 )
31991  {
31992  return;
31993  }
31994  if( s->rcpar )
31995  {
31996  ae_assert(s->nout>=1, "MLPSetDataset: possible parameter S is not initialized or is spoiled(NOut<1 for regression).", _state);
31997  ndim = s->nin+s->nout;
31998  ae_assert(ndim<=xy->cols, "MLPSetDataset: invalid size of matrix XY(too few columns in matrix XY).", _state);
31999  ae_assert(apservisfinitematrix(xy, npoints, ndim, _state), "MLPSetDataset: parameter XY contains Infinite or NaN.", _state);
32000  }
32001  else
32002  {
32003  ae_assert(s->nout>=2, "MLPSetDataset: possible parameter S is not initialized or is spoiled(NClasses<2 for classifier).", _state);
32004  ndim = s->nin+1;
32005  ae_assert(ndim<=xy->cols, "MLPSetDataset: invalid size of matrix XY(too few columns in matrix XY).", _state);
32006  ae_assert(apservisfinitematrix(xy, npoints, ndim, _state), "MLPSetDataset: parameter XY contains Infinite or NaN.", _state);
32007  for(i=0; i<=npoints-1; i++)
32008  {
32009  ae_assert(ae_round(xy->ptr.pp_double[i][s->nin], _state)>=0&&ae_round(xy->ptr.pp_double[i][s->nin], _state)<s->nout, "MLPSetDataset: invalid parameter XY(in classifier used nonexistent class number: either XY[.,NIn]<0 or XY[.,NIn]>=NClasses).", _state);
32010  }
32011  }
32012  rmatrixsetlengthatleast(&s->densexy, npoints, ndim, _state);
32013  for(i=0; i<=npoints-1; i++)
32014  {
32015  for(j=0; j<=ndim-1; j++)
32016  {
32017  s->densexy.ptr.pp_double[i][j] = xy->ptr.pp_double[i][j];
32018  }
32019  }
32020 }
32021 
32022 
32023 /*************************************************************************
32024 This function sets "current dataset" of the trainer object to one passed
32025 by user (sparse matrix is used to store dataset).
32026 
32027 INPUT PARAMETERS:
32028  S - trainer object
32029  XY - training set, see below for information on the
32030  training set format. This function checks correctness
32031  of the dataset (no NANs/INFs, class numbers are
32032  correct) and throws exception when incorrect dataset
32033  is passed. Any sparse storage format can be used:
32034  Hash-table, CRS...
32035  NPoints - points count, >=0
32036 
32037 DATASET FORMAT:
32038 
32039 This function uses two different dataset formats - one for regression
32040 networks, another one for classification networks.
32041 
32042 For regression networks with NIn inputs and NOut outputs following dataset
32043 format is used:
32044 * dataset is given by NPoints*(NIn+NOut) matrix
32045 * each row corresponds to one example
32046 * first NIn columns are inputs, next NOut columns are outputs
32047 
32048 For classification networks with NIn inputs and NClasses clases following
32049 datasetformat is used:
32050 * dataset is given by NPoints*(NIn+1) matrix
32051 * each row corresponds to one example
32052 * first NIn columns are inputs, last column stores class number (from 0 to
32053  NClasses-1).
32054 
32055  -- ALGLIB --
32056  Copyright 23.07.2012 by Bochkanov Sergey
32057 *************************************************************************/
32058 void mlpsetsparsedataset(mlptrainer* s,
32059  sparsematrix* xy,
32060  ae_int_t npoints,
32061  ae_state *_state)
32062 {
32063  double v;
32064  ae_int_t t0;
32065  ae_int_t t1;
32066  ae_int_t i;
32067  ae_int_t j;
32068 
32069 
32070 
32071  /*
32072  * Check correctness of the data
32073  */
32074  ae_assert(s->nin>0, "MLPSetSparseDataset: possible parameter S is not initialized or spoiled(S.NIn<=0).", _state);
32075  ae_assert(npoints>=0, "MLPSetSparseDataset: NPoint<0", _state);
32076  ae_assert(npoints<=sparsegetnrows(xy, _state), "MLPSetSparseDataset: invalid size of sparse matrix XY(NPoint more then rows of matrix XY)", _state);
32077  if( npoints>0 )
32078  {
32079  t0 = 0;
32080  t1 = 0;
32081  if( s->rcpar )
32082  {
32083  ae_assert(s->nout>=1, "MLPSetSparseDataset: possible parameter S is not initialized or is spoiled(NOut<1 for regression).", _state);
32084  ae_assert(s->nin+s->nout<=sparsegetncols(xy, _state), "MLPSetSparseDataset: invalid size of sparse matrix XY(too few columns in sparse matrix XY).", _state);
32085  while(sparseenumerate(xy, &t0, &t1, &i, &j, &v, _state))
32086  {
32087  if( i<npoints&&j<s->nin+s->nout )
32088  {
32089  ae_assert(ae_isfinite(v, _state), "MLPSetSparseDataset: sparse matrix XY contains Infinite or NaN.", _state);
32090  }
32091  }
32092  }
32093  else
32094  {
32095  ae_assert(s->nout>=2, "MLPSetSparseDataset: possible parameter S is not initialized or is spoiled(NClasses<2 for classifier).", _state);
32096  ae_assert(s->nin+1<=sparsegetncols(xy, _state), "MLPSetSparseDataset: invalid size of sparse matrix XY(too few columns in sparse matrix XY).", _state);
32097  while(sparseenumerate(xy, &t0, &t1, &i, &j, &v, _state))
32098  {
32099  if( i<npoints&&j<=s->nin )
32100  {
32101  if( j!=s->nin )
32102  {
32103  ae_assert(ae_isfinite(v, _state), "MLPSetSparseDataset: sparse matrix XY contains Infinite or NaN.", _state);
32104  }
32105  else
32106  {
32107  ae_assert((ae_isfinite(v, _state)&&ae_round(v, _state)>=0)&&ae_round(v, _state)<s->nout, "MLPSetSparseDataset: invalid sparse matrix XY(in classifier used nonexistent class number: either XY[.,NIn]<0 or XY[.,NIn]>=NClasses).", _state);
32108  }
32109  }
32110  }
32111  }
32112  }
32113 
32114  /*
32115  * Set dataset
32116  */
32117  s->datatype = 1;
32118  s->npoints = npoints;
32119  sparsecopytocrs(xy, &s->sparsexy, _state);
32120 }
32121 
32122 
32123 /*************************************************************************
32124 This function sets weight decay coefficient which is used for training.
32125 
32126 INPUT PARAMETERS:
32127  S - trainer object
32128  Decay - weight decay coefficient, >=0. Weight decay term
32129  'Decay*||Weights||^2' is added to error function. If
32130  you don't know what Decay to choose, use 1.0E-3.
32131  Weight decay can be set to zero, in this case network
32132  is trained without weight decay.
32133 
32134 NOTE: by default network uses some small nonzero value for weight decay.
32135 
32136  -- ALGLIB --
32137  Copyright 23.07.2012 by Bochkanov Sergey
32138 *************************************************************************/
32139 void mlpsetdecay(mlptrainer* s, double decay, ae_state *_state)
32140 {
32141 
32142 
32143  ae_assert(ae_isfinite(decay, _state), "MLPSetDecay: parameter Decay contains Infinite or NaN.", _state);
32144  ae_assert(ae_fp_greater_eq(decay,0), "MLPSetDecay: Decay<0.", _state);
32145  s->decay = decay;
32146 }
32147 
32148 
32149 /*************************************************************************
32150 This function sets stopping criteria for the optimizer.
32151 
32152 INPUT PARAMETERS:
32153  S - trainer object
32154  WStep - stopping criterion. Algorithm stops if step size is
32155  less than WStep. Recommended value - 0.01. Zero step
32156  size means stopping after MaxIts iterations.
32157  WStep>=0.
32158  MaxIts - stopping criterion. Algorithm stops after MaxIts
32159  epochs (full passes over entire dataset). Zero MaxIts
32160  means stopping when step is sufficiently small.
32161  MaxIts>=0.
32162 
32163 NOTE: by default, WStep=0.005 and MaxIts=0 are used. These values are also
32164  used when MLPSetCond() is called with WStep=0 and MaxIts=0.
32165 
32166 NOTE: these stopping criteria are used for all kinds of neural training -
32167  from "conventional" networks to early stopping ensembles. When used
32168  for "conventional" networks, they are used as the only stopping
32169  criteria. When combined with early stopping, they used as ADDITIONAL
32170  stopping criteria which can terminate early stopping algorithm.
32171 
32172  -- ALGLIB --
32173  Copyright 23.07.2012 by Bochkanov Sergey
32174 *************************************************************************/
32175 void mlpsetcond(mlptrainer* s,
32176  double wstep,
32177  ae_int_t maxits,
32178  ae_state *_state)
32179 {
32180 
32181 
32182  ae_assert(ae_isfinite(wstep, _state), "MLPSetCond: parameter WStep contains Infinite or NaN.", _state);
32183  ae_assert(ae_fp_greater_eq(wstep,0), "MLPSetCond: WStep<0.", _state);
32184  ae_assert(maxits>=0, "MLPSetCond: MaxIts<0.", _state);
32185  if( ae_fp_neq(wstep,0)||maxits!=0 )
32186  {
32187  s->wstep = wstep;
32188  s->maxits = maxits;
32189  }
32190  else
32191  {
32192  s->wstep = 0.005;
32193  s->maxits = 0;
32194  }
32195 }
32196 
32197 
32198 /*************************************************************************
32199 This function sets training algorithm: batch training using L-BFGS will be
32200 used.
32201 
32202 This algorithm:
32203 * the most robust for small-scale problems, but may be too slow for large
32204  scale ones.
32205 * perfoms full pass through the dataset before performing step
32206 * uses conditions specified by MLPSetCond() for stopping
32207 * is default one used by trainer object
32208 
32209 INPUT PARAMETERS:
32210  S - trainer object
32211 
32212  -- ALGLIB --
32213  Copyright 23.07.2012 by Bochkanov Sergey
32214 *************************************************************************/
32215 void mlpsetalgobatch(mlptrainer* s, ae_state *_state)
32216 {
32217 
32218 
32219  s->algokind = 0;
32220 }
32221 
32222 
32223 /*************************************************************************
32224 This function trains neural network passed to this function, using current
32225 dataset (one which was passed to MLPSetDataset() or MLPSetSparseDataset())
32226 and current training settings. Training from NRestarts random starting
32227 positions is performed, best network is chosen.
32228 
32229 Training is performed using current training algorithm.
32230 
32231 FOR USERS OF COMMERCIAL EDITION:
32232 
32233  ! Commercial version of ALGLIB includes two important improvements of
32234  ! this function:
32235  ! * multicore support (C++ and C# computational cores)
32236  ! * SSE support (C++ computational core)
32237  !
32238  ! Second improvement gives constant speedup (2-3X). First improvement
32239  ! gives close-to-linear speedup on multicore systems. Following
32240  ! operations can be executed in parallel:
32241  ! * NRestarts training sessions performed within each of
32242  ! cross-validation rounds (if NRestarts>1)
32243  ! * gradient calculation over large dataset (if dataset is large enough)
32244  !
32245  ! In order to use multicore features you have to:
32246  ! * use commercial version of ALGLIB
32247  ! * call this function with "smp_" prefix, which indicates that
32248  ! multicore code will be used (for multicore support)
32249  !
32250  ! In order to use SSE features you have to:
32251  ! * use commercial version of ALGLIB on Intel processors
32252  ! * use C++ computational core
32253  !
32254  ! This note is given for users of commercial edition; if you use GPL
32255  ! edition, you still will be able to call smp-version of this function,
32256  ! but all computations will be done serially.
32257  !
32258  ! We recommend you to carefully read ALGLIB Reference Manual, section
32259  ! called 'SMP support', before using parallel version of this function.
32260 
32261 INPUT PARAMETERS:
32262  S - trainer object
32263  Network - neural network. It must have same number of inputs and
32264  output/classes as was specified during creation of the
32265  trainer object.
32266  NRestarts - number of restarts, >=0:
32267  * NRestarts>0 means that specified number of random
32268  restarts are performed, best network is chosen after
32269  training
32270  * NRestarts=0 means that current state of the network
32271  is used for training.
32272 
32273 OUTPUT PARAMETERS:
32274  Network - trained network
32275 
32276 NOTE: when no dataset was specified with MLPSetDataset/SetSparseDataset(),
32277  network is filled by zero values. Same behavior for functions
32278  MLPStartTraining and MLPContinueTraining.
32279 
32280 NOTE: this method uses sum-of-squares error function for training.
32281 
32282  -- ALGLIB --
32283  Copyright 23.07.2012 by Bochkanov Sergey
32284 *************************************************************************/
32285 void mlptrainnetwork(mlptrainer* s,
32286  multilayerperceptron* network,
32287  ae_int_t nrestarts,
32288  mlpreport* rep,
32289  ae_state *_state)
32290 {
32291  ae_frame _frame_block;
32292  ae_int_t nin;
32293  ae_int_t nout;
32294  ae_int_t wcount;
32295  ae_int_t ntype;
32296  ae_int_t ttype;
32297  ae_shared_pool trnpool;
32298 
32299  ae_frame_make(_state, &_frame_block);
32300  _mlpreport_clear(rep);
32301  ae_shared_pool_init(&trnpool, _state, ae_true);
32302 
32303  ae_assert(s->npoints>=0, "MLPTrainNetwork: parameter S is not initialized or is spoiled(S.NPoints<0)", _state);
32304  if( !mlpissoftmax(network, _state) )
32305  {
32306  ntype = 0;
32307  }
32308  else
32309  {
32310  ntype = 1;
32311  }
32312  if( s->rcpar )
32313  {
32314  ttype = 0;
32315  }
32316  else
32317  {
32318  ttype = 1;
32319  }
32320  ae_assert(ntype==ttype, "MLPTrainNetwork: type of input network is not similar to network type in trainer object", _state);
32321  mlpproperties(network, &nin, &nout, &wcount, _state);
32322  ae_assert(s->nin==nin, "MLPTrainNetwork: number of inputs in trainer is not equal to number of inputs in network", _state);
32323  ae_assert(s->nout==nout, "MLPTrainNetwork: number of outputs in trainer is not equal to number of outputs in network", _state);
32324  ae_assert(nrestarts>=0, "MLPTrainNetwork: NRestarts<0.", _state);
32325 
32326  /*
32327  * Train
32328  */
32329  mlptrain_mlptrainnetworkx(s, nrestarts, -1, &s->subset, -1, &s->subset, 0, network, rep, ae_true, &trnpool, _state);
32330  ae_frame_leave(_state);
32331 }
32332 
32333 
32334 /*************************************************************************
32335 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
32336 *************************************************************************/
32337 void _pexec_mlptrainnetwork(mlptrainer* s,
32338  multilayerperceptron* network,
32339  ae_int_t nrestarts,
32340  mlpreport* rep, ae_state *_state)
32341 {
32342  mlptrainnetwork(s,network,nrestarts,rep, _state);
32343 }
32344 
32345 
32346 /*************************************************************************
32347 IMPORTANT: this is an "expert" version of the MLPTrain() function. We do
32348  not recommend you to use it unless you are pretty sure that you
32349  need ability to monitor training progress.
32350 
32351 This function performs step-by-step training of the neural network. Here
32352 "step-by-step" means that training starts with MLPStartTraining() call,
32353 and then user subsequently calls MLPContinueTraining() to perform one more
32354 iteration of the training.
32355 
32356 After call to this function trainer object remembers network and is ready
32357 to train it. However, no training is performed until first call to
32358 MLPContinueTraining() function. Subsequent calls to MLPContinueTraining()
32359 will advance training progress one iteration further.
32360 
32361 EXAMPLE:
32362  >
32363  > ...initialize network and trainer object....
32364  >
32365  > MLPStartTraining(Trainer, Network, True)
32366  > while MLPContinueTraining(Trainer, Network) do
32367  > ...visualize training progress...
32368  >
32369 
32370 INPUT PARAMETERS:
32371  S - trainer object
32372  Network - neural network. It must have same number of inputs and
32373  output/classes as was specified during creation of the
32374  trainer object.
32375  RandomStart - randomize network before training or not:
32376  * True means that network is randomized and its
32377  initial state (one which was passed to the trainer
32378  object) is lost.
32379  * False means that training is started from the
32380  current state of the network
32381 
32382 OUTPUT PARAMETERS:
32383  Network - neural network which is ready to training (weights are
32384  initialized, preprocessor is initialized using current
32385  training set)
32386 
32387 NOTE: this method uses sum-of-squares error function for training.
32388 
32389 NOTE: it is expected that trainer object settings are NOT changed during
32390  step-by-step training, i.e. no one changes stopping criteria or
32391  training set during training. It is possible and there is no defense
32392  against such actions, but algorithm behavior in such cases is
32393  undefined and can be unpredictable.
32394 
32395  -- ALGLIB --
32396  Copyright 23.07.2012 by Bochkanov Sergey
32397 *************************************************************************/
32398 void mlpstarttraining(mlptrainer* s,
32399  multilayerperceptron* network,
32400  ae_bool randomstart,
32401  ae_state *_state)
32402 {
32403  ae_int_t nin;
32404  ae_int_t nout;
32405  ae_int_t wcount;
32406  ae_int_t ntype;
32407  ae_int_t ttype;
32408 
32409 
32410  ae_assert(s->npoints>=0, "MLPStartTraining: parameter S is not initialized or is spoiled(S.NPoints<0)", _state);
32411  if( !mlpissoftmax(network, _state) )
32412  {
32413  ntype = 0;
32414  }
32415  else
32416  {
32417  ntype = 1;
32418  }
32419  if( s->rcpar )
32420  {
32421  ttype = 0;
32422  }
32423  else
32424  {
32425  ttype = 1;
32426  }
32427  ae_assert(ntype==ttype, "MLPStartTraining: type of input network is not similar to network type in trainer object", _state);
32428  mlpproperties(network, &nin, &nout, &wcount, _state);
32429  ae_assert(s->nin==nin, "MLPStartTraining: number of inputs in trainer is not equal to number of inputs in the network.", _state);
32430  ae_assert(s->nout==nout, "MLPStartTraining: number of outputs in trainer is not equal to number of outputs in the network.", _state);
32431 
32432  /*
32433  * Initialize temporaries
32434  */
32435  mlptrain_initmlptrnsession(network, randomstart, s, &s->session, _state);
32436 
32437  /*
32438  * Train network
32439  */
32440  mlptrain_mlpstarttrainingx(s, randomstart, -1, &s->subset, -1, &s->session, _state);
32441 
32442  /*
32443  * Update network
32444  */
32445  mlpcopytunableparameters(&s->session.network, network, _state);
32446 }
32447 
32448 
32449 /*************************************************************************
32450 IMPORTANT: this is an "expert" version of the MLPTrain() function. We do
32451  not recommend you to use it unless you are pretty sure that you
32452  need ability to monitor training progress.
32453 
32454 FOR USERS OF COMMERCIAL EDITION:
32455 
32456  ! Commercial version of ALGLIB includes two important improvements of
32457  ! this function:
32458  ! * multicore support (C++ and C# computational cores)
32459  ! * SSE support (C++ computational core)
32460  !
32461  ! Second improvement gives constant speedup (2-3X). First improvement
32462  ! gives close-to-linear speedup on multicore systems. Following
32463  ! operations can be executed in parallel:
32464  ! * gradient calculation over large dataset (if dataset is large enough)
32465  !
32466  ! In order to use multicore features you have to:
32467  ! * use commercial version of ALGLIB
32468  ! * call this function with "smp_" prefix, which indicates that
32469  ! multicore code will be used (for multicore support)
32470  !
32471  ! In order to use SSE features you have to:
32472  ! * use commercial version of ALGLIB on Intel processors
32473  ! * use C++ computational core
32474  !
32475  ! This note is given for users of commercial edition; if you use GPL
32476  ! edition, you still will be able to call smp-version of this function,
32477  ! but all computations will be done serially.
32478  !
32479  ! We recommend you to carefully read ALGLIB Reference Manual, section
32480  ! called 'SMP support', before using parallel version of this function.
32481 
32482 This function performs step-by-step training of the neural network. Here
32483 "step-by-step" means that training starts with MLPStartTraining() call,
32484 and then user subsequently calls MLPContinueTraining() to perform one more
32485 iteration of the training.
32486 
32487 This function performs one more iteration of the training and returns
32488 either True (training continues) or False (training stopped). In case True
32489 was returned, Network weights are updated according to the current state
32490 of the optimization progress. In case False was returned, no additional
32491 updates is performed (previous update of the network weights moved us to
32492 the final point, and no additional updates is needed).
32493 
32494 EXAMPLE:
32495  >
32496  > [initialize network and trainer object]
32497  >
32498  > MLPStartTraining(Trainer, Network, True)
32499  > while MLPContinueTraining(Trainer, Network) do
32500  > [visualize training progress]
32501  >
32502 
32503 INPUT PARAMETERS:
32504  S - trainer object
32505  Network - neural network structure, which is used to store
32506  current state of the training process.
32507 
32508 OUTPUT PARAMETERS:
32509  Network - weights of the neural network are rewritten by the
32510  current approximation.
32511 
32512 NOTE: this method uses sum-of-squares error function for training.
32513 
32514 NOTE: it is expected that trainer object settings are NOT changed during
32515  step-by-step training, i.e. no one changes stopping criteria or
32516  training set during training. It is possible and there is no defense
32517  against such actions, but algorithm behavior in such cases is
32518  undefined and can be unpredictable.
32519 
32520 NOTE: It is expected that Network is the same one which was passed to
32521  MLPStartTraining() function. However, THIS function checks only
32522  following:
32523  * that number of network inputs is consistent with trainer object
32524  settings
32525  * that number of network outputs/classes is consistent with trainer
32526  object settings
32527  * that number of network weights is the same as number of weights in
32528  the network passed to MLPStartTraining() function
32529  Exception is thrown when these conditions are violated.
32530 
32531  It is also expected that you do not change state of the network on
32532  your own - the only party who has right to change network during its
32533  training is a trainer object. Any attempt to interfere with trainer
32534  may lead to unpredictable results.
32535 
32536 
32537  -- ALGLIB --
32538  Copyright 23.07.2012 by Bochkanov Sergey
32539 *************************************************************************/
32540 ae_bool mlpcontinuetraining(mlptrainer* s,
32541  multilayerperceptron* network,
32542  ae_state *_state)
32543 {
32544  ae_int_t nin;
32545  ae_int_t nout;
32546  ae_int_t wcount;
32547  ae_int_t ntype;
32548  ae_int_t ttype;
32549  ae_bool result;
32550 
32551 
32552  ae_assert(s->npoints>=0, "MLPContinueTraining: parameter S is not initialized or is spoiled(S.NPoints<0)", _state);
32553  if( s->rcpar )
32554  {
32555  ttype = 0;
32556  }
32557  else
32558  {
32559  ttype = 1;
32560  }
32561  if( !mlpissoftmax(network, _state) )
32562  {
32563  ntype = 0;
32564  }
32565  else
32566  {
32567  ntype = 1;
32568  }
32569  ae_assert(ntype==ttype, "MLPContinueTraining: type of input network is not similar to network type in trainer object.", _state);
32570  mlpproperties(network, &nin, &nout, &wcount, _state);
32571  ae_assert(s->nin==nin, "MLPContinueTraining: number of inputs in trainer is not equal to number of inputs in the network.", _state);
32572  ae_assert(s->nout==nout, "MLPContinueTraining: number of outputs in trainer is not equal to number of outputs in the network.", _state);
32573  result = mlptrain_mlpcontinuetrainingx(s, &s->subset, -1, &s->ngradbatch, &s->session, _state);
32574  if( result )
32575  {
32576  ae_v_move(&network->weights.ptr.p_double[0], 1, &s->session.network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
32577  }
32578  return result;
32579 }
32580 
32581 
32582 /*************************************************************************
32583 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
32584 *************************************************************************/
32585 ae_bool _pexec_mlpcontinuetraining(mlptrainer* s,
32586  multilayerperceptron* network, ae_state *_state)
32587 {
32588  return mlpcontinuetraining(s,network, _state);
32589 }
32590 
32591 
32592 /*************************************************************************
32593 Training neural networks ensemble using bootstrap aggregating (bagging).
32594 Modified Levenberg-Marquardt algorithm is used as base training method.
32595 
32596 INPUT PARAMETERS:
32597  Ensemble - model with initialized geometry
32598  XY - training set
32599  NPoints - training set size
32600  Decay - weight decay coefficient, >=0.001
32601  Restarts - restarts, >0.
32602 
32603 OUTPUT PARAMETERS:
32604  Ensemble - trained model
32605  Info - return code:
32606  * -2, if there is a point with class number
32607  outside of [0..NClasses-1].
32608  * -1, if incorrect parameters was passed
32609  (NPoints<0, Restarts<1).
32610  * 2, if task has been solved.
32611  Rep - training report.
32612  OOBErrors - out-of-bag generalization error estimate
32613 
32614  -- ALGLIB --
32615  Copyright 17.02.2009 by Bochkanov Sergey
32616 *************************************************************************/
32617 void mlpebagginglm(mlpensemble* ensemble,
32618  /* Real */ ae_matrix* xy,
32619  ae_int_t npoints,
32620  double decay,
32621  ae_int_t restarts,
32622  ae_int_t* info,
32623  mlpreport* rep,
32624  mlpcvreport* ooberrors,
32625  ae_state *_state)
32626 {
32627 
32628  *info = 0;
32629  _mlpreport_clear(rep);
32630  _mlpcvreport_clear(ooberrors);
32631 
32632  mlptrain_mlpebagginginternal(ensemble, xy, npoints, decay, restarts, 0.0, 0, ae_true, info, rep, ooberrors, _state);
32633 }
32634 
32635 
32636 /*************************************************************************
32637 Training neural networks ensemble using bootstrap aggregating (bagging).
32638 L-BFGS algorithm is used as base training method.
32639 
32640 INPUT PARAMETERS:
32641  Ensemble - model with initialized geometry
32642  XY - training set
32643  NPoints - training set size
32644  Decay - weight decay coefficient, >=0.001
32645  Restarts - restarts, >0.
32646  WStep - stopping criterion, same as in MLPTrainLBFGS
32647  MaxIts - stopping criterion, same as in MLPTrainLBFGS
32648 
32649 OUTPUT PARAMETERS:
32650  Ensemble - trained model
32651  Info - return code:
32652  * -8, if both WStep=0 and MaxIts=0
32653  * -2, if there is a point with class number
32654  outside of [0..NClasses-1].
32655  * -1, if incorrect parameters was passed
32656  (NPoints<0, Restarts<1).
32657  * 2, if task has been solved.
32658  Rep - training report.
32659  OOBErrors - out-of-bag generalization error estimate
32660 
32661  -- ALGLIB --
32662  Copyright 17.02.2009 by Bochkanov Sergey
32663 *************************************************************************/
32664 void mlpebagginglbfgs(mlpensemble* ensemble,
32665  /* Real */ ae_matrix* xy,
32666  ae_int_t npoints,
32667  double decay,
32668  ae_int_t restarts,
32669  double wstep,
32670  ae_int_t maxits,
32671  ae_int_t* info,
32672  mlpreport* rep,
32673  mlpcvreport* ooberrors,
32674  ae_state *_state)
32675 {
32676 
32677  *info = 0;
32678  _mlpreport_clear(rep);
32679  _mlpcvreport_clear(ooberrors);
32680 
32681  mlptrain_mlpebagginginternal(ensemble, xy, npoints, decay, restarts, wstep, maxits, ae_false, info, rep, ooberrors, _state);
32682 }
32683 
32684 
32685 /*************************************************************************
32686 Training neural networks ensemble using early stopping.
32687 
32688 INPUT PARAMETERS:
32689  Ensemble - model with initialized geometry
32690  XY - training set
32691  NPoints - training set size
32692  Decay - weight decay coefficient, >=0.001
32693  Restarts - restarts, >0.
32694 
32695 OUTPUT PARAMETERS:
32696  Ensemble - trained model
32697  Info - return code:
32698  * -2, if there is a point with class number
32699  outside of [0..NClasses-1].
32700  * -1, if incorrect parameters was passed
32701  (NPoints<0, Restarts<1).
32702  * 6, if task has been solved.
32703  Rep - training report.
32704  OOBErrors - out-of-bag generalization error estimate
32705 
32706  -- ALGLIB --
32707  Copyright 10.03.2009 by Bochkanov Sergey
32708 *************************************************************************/
32709 void mlpetraines(mlpensemble* ensemble,
32710  /* Real */ ae_matrix* xy,
32711  ae_int_t npoints,
32712  double decay,
32713  ae_int_t restarts,
32714  ae_int_t* info,
32715  mlpreport* rep,
32716  ae_state *_state)
32717 {
32718  ae_frame _frame_block;
32719  ae_int_t i;
32720  ae_int_t k;
32721  ae_int_t ccount;
32722  ae_int_t pcount;
32723  ae_matrix trnxy;
32724  ae_matrix valxy;
32725  ae_int_t trnsize;
32726  ae_int_t valsize;
32727  ae_int_t tmpinfo;
32728  mlpreport tmprep;
32729  modelerrors moderr;
32730  ae_int_t nin;
32731  ae_int_t nout;
32732  ae_int_t wcount;
32733 
32734  ae_frame_make(_state, &_frame_block);
32735  *info = 0;
32736  _mlpreport_clear(rep);
32737  ae_matrix_init(&trnxy, 0, 0, DT_REAL, _state, ae_true);
32738  ae_matrix_init(&valxy, 0, 0, DT_REAL, _state, ae_true);
32739  _mlpreport_init(&tmprep, _state, ae_true);
32740  _modelerrors_init(&moderr, _state, ae_true);
32741 
32742  nin = mlpgetinputscount(&ensemble->network, _state);
32743  nout = mlpgetoutputscount(&ensemble->network, _state);
32744  wcount = mlpgetweightscount(&ensemble->network, _state);
32745  if( (npoints<2||restarts<1)||ae_fp_less(decay,0) )
32746  {
32747  *info = -1;
32748  ae_frame_leave(_state);
32749  return;
32750  }
32751  if( mlpissoftmax(&ensemble->network, _state) )
32752  {
32753  for(i=0; i<=npoints-1; i++)
32754  {
32755  if( ae_round(xy->ptr.pp_double[i][nin], _state)<0||ae_round(xy->ptr.pp_double[i][nin], _state)>=nout )
32756  {
32757  *info = -2;
32758  ae_frame_leave(_state);
32759  return;
32760  }
32761  }
32762  }
32763  *info = 6;
32764 
32765  /*
32766  * allocate
32767  */
32768  if( mlpissoftmax(&ensemble->network, _state) )
32769  {
32770  ccount = nin+1;
32771  pcount = nin;
32772  }
32773  else
32774  {
32775  ccount = nin+nout;
32776  pcount = nin+nout;
32777  }
32778  ae_matrix_set_length(&trnxy, npoints, ccount, _state);
32779  ae_matrix_set_length(&valxy, npoints, ccount, _state);
32780  rep->ngrad = 0;
32781  rep->nhess = 0;
32782  rep->ncholesky = 0;
32783 
32784  /*
32785  * train networks
32786  */
32787  for(k=0; k<=ensemble->ensemblesize-1; k++)
32788  {
32789 
32790  /*
32791  * Split set
32792  */
32793  do
32794  {
32795  trnsize = 0;
32796  valsize = 0;
32797  for(i=0; i<=npoints-1; i++)
32798  {
32799  if( ae_fp_less(ae_randomreal(_state),0.66) )
32800  {
32801 
32802  /*
32803  * Assign sample to training set
32804  */
32805  ae_v_move(&trnxy.ptr.pp_double[trnsize][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,ccount-1));
32806  trnsize = trnsize+1;
32807  }
32808  else
32809  {
32810 
32811  /*
32812  * Assign sample to validation set
32813  */
32814  ae_v_move(&valxy.ptr.pp_double[valsize][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,ccount-1));
32815  valsize = valsize+1;
32816  }
32817  }
32818  }
32819  while(!(trnsize!=0&&valsize!=0));
32820 
32821  /*
32822  * Train
32823  */
32824  mlptraines(&ensemble->network, &trnxy, trnsize, &valxy, valsize, decay, restarts, &tmpinfo, &tmprep, _state);
32825  if( tmpinfo<0 )
32826  {
32827  *info = tmpinfo;
32828  ae_frame_leave(_state);
32829  return;
32830  }
32831 
32832  /*
32833  * save results
32834  */
32835  ae_v_move(&ensemble->weights.ptr.p_double[k*wcount], 1, &ensemble->network.weights.ptr.p_double[0], 1, ae_v_len(k*wcount,(k+1)*wcount-1));
32836  ae_v_move(&ensemble->columnmeans.ptr.p_double[k*pcount], 1, &ensemble->network.columnmeans.ptr.p_double[0], 1, ae_v_len(k*pcount,(k+1)*pcount-1));
32837  ae_v_move(&ensemble->columnsigmas.ptr.p_double[k*pcount], 1, &ensemble->network.columnsigmas.ptr.p_double[0], 1, ae_v_len(k*pcount,(k+1)*pcount-1));
32838  rep->ngrad = rep->ngrad+tmprep.ngrad;
32839  rep->nhess = rep->nhess+tmprep.nhess;
32840  rep->ncholesky = rep->ncholesky+tmprep.ncholesky;
32841  }
32842  mlpeallerrorsx(ensemble, xy, &ensemble->network.dummysxy, npoints, 0, &ensemble->network.dummyidx, 0, npoints, 0, &ensemble->network.buf, &moderr, _state);
32843  rep->relclserror = moderr.relclserror;
32844  rep->avgce = moderr.avgce;
32845  rep->rmserror = moderr.rmserror;
32846  rep->avgerror = moderr.avgerror;
32847  rep->avgrelerror = moderr.avgrelerror;
32848  ae_frame_leave(_state);
32849 }
32850 
32851 
32852 /*************************************************************************
32853 This function trains neural network ensemble passed to this function using
32854 current dataset and early stopping training algorithm. Each early stopping
32855 round performs NRestarts random restarts (thus, EnsembleSize*NRestarts
32856 training rounds is performed in total).
32857 
32858 FOR USERS OF COMMERCIAL EDITION:
32859 
32860  ! Commercial version of ALGLIB includes two important improvements of
32861  ! this function:
32862  ! * multicore support (C++ and C# computational cores)
32863  ! * SSE support (C++ computational core)
32864  !
32865  ! Second improvement gives constant speedup (2-3X). First improvement
32866  ! gives close-to-linear speedup on multicore systems. Following
32867  ! operations can be executed in parallel:
32868  ! * EnsembleSize training sessions performed for each of ensemble
32869  ! members (always parallelized)
32870  ! * NRestarts training sessions performed within each of training
32871  ! sessions (if NRestarts>1)
32872  ! * gradient calculation over large dataset (if dataset is large enough)
32873  !
32874  ! In order to use multicore features you have to:
32875  ! * use commercial version of ALGLIB
32876  ! * call this function with "smp_" prefix, which indicates that
32877  ! multicore code will be used (for multicore support)
32878  !
32879  ! In order to use SSE features you have to:
32880  ! * use commercial version of ALGLIB on Intel processors
32881  ! * use C++ computational core
32882  !
32883  ! This note is given for users of commercial edition; if you use GPL
32884  ! edition, you still will be able to call smp-version of this function,
32885  ! but all computations will be done serially.
32886  !
32887  ! We recommend you to carefully read ALGLIB Reference Manual, section
32888  ! called 'SMP support', before using parallel version of this function.
32889 
32890 INPUT PARAMETERS:
32891  S - trainer object;
32892  Ensemble - neural network ensemble. It must have same number of
32893  inputs and outputs/classes as was specified during
32894  creation of the trainer object.
32895  NRestarts - number of restarts, >=0:
32896  * NRestarts>0 means that specified number of random
32897  restarts are performed during each ES round;
32898  * NRestarts=0 is silently replaced by 1.
32899 
32900 OUTPUT PARAMETERS:
32901  Ensemble - trained ensemble;
32902  Rep - it contains all type of errors.
32903 
32904 NOTE: this training method uses BOTH early stopping and weight decay! So,
32905  you should select weight decay before starting training just as you
32906  select it before training "conventional" networks.
32907 
32908 NOTE: when no dataset was specified with MLPSetDataset/SetSparseDataset(),
32909  or single-point dataset was passed, ensemble is filled by zero
32910  values.
32911 
32912 NOTE: this method uses sum-of-squares error function for training.
32913 
32914  -- ALGLIB --
32915  Copyright 22.08.2012 by Bochkanov Sergey
32916 *************************************************************************/
32917 void mlptrainensemblees(mlptrainer* s,
32918  mlpensemble* ensemble,
32919  ae_int_t nrestarts,
32920  mlpreport* rep,
32921  ae_state *_state)
32922 {
32923  ae_frame _frame_block;
32924  ae_int_t nin;
32925  ae_int_t nout;
32926  ae_int_t ntype;
32927  ae_int_t ttype;
32928  ae_shared_pool esessions;
32929  sinteger sgrad;
32930  modelerrors tmprep;
32931 
32932  ae_frame_make(_state, &_frame_block);
32933  _mlpreport_clear(rep);
32934  ae_shared_pool_init(&esessions, _state, ae_true);
32935  _sinteger_init(&sgrad, _state, ae_true);
32936  _modelerrors_init(&tmprep, _state, ae_true);
32937 
32938  ae_assert(s->npoints>=0, "MLPTrainEnsembleES: parameter S is not initialized or is spoiled(S.NPoints<0)", _state);
32939  if( !mlpeissoftmax(ensemble, _state) )
32940  {
32941  ntype = 0;
32942  }
32943  else
32944  {
32945  ntype = 1;
32946  }
32947  if( s->rcpar )
32948  {
32949  ttype = 0;
32950  }
32951  else
32952  {
32953  ttype = 1;
32954  }
32955  ae_assert(ntype==ttype, "MLPTrainEnsembleES: internal error - type of input network is not similar to network type in trainer object", _state);
32956  nin = mlpgetinputscount(&ensemble->network, _state);
32957  ae_assert(s->nin==nin, "MLPTrainEnsembleES: number of inputs in trainer is not equal to number of inputs in ensemble network", _state);
32958  nout = mlpgetoutputscount(&ensemble->network, _state);
32959  ae_assert(s->nout==nout, "MLPTrainEnsembleES: number of outputs in trainer is not equal to number of outputs in ensemble network", _state);
32960  ae_assert(nrestarts>=0, "MLPTrainEnsembleES: NRestarts<0.", _state);
32961 
32962  /*
32963  * Initialize parameter Rep
32964  */
32965  rep->relclserror = 0;
32966  rep->avgce = 0;
32967  rep->rmserror = 0;
32968  rep->avgerror = 0;
32969  rep->avgrelerror = 0;
32970  rep->ngrad = 0;
32971  rep->nhess = 0;
32972  rep->ncholesky = 0;
32973 
32974  /*
32975  * Allocate
32976  */
32977  ivectorsetlengthatleast(&s->subset, s->npoints, _state);
32978  ivectorsetlengthatleast(&s->valsubset, s->npoints, _state);
32979 
32980  /*
32981  * Start training
32982  *
32983  * NOTE: ESessions is not initialized because MLPTrainEnsembleX
32984  * needs uninitialized pool.
32985  */
32986  sgrad.val = 0;
32987  mlptrain_mlptrainensemblex(s, ensemble, 0, ensemble->ensemblesize, nrestarts, 0, &sgrad, ae_true, &esessions, _state);
32988  rep->ngrad = sgrad.val;
32989 
32990  /*
32991  * Calculate errors.
32992  */
32993  if( s->datatype==0 )
32994  {
32995  mlpeallerrorsx(ensemble, &s->densexy, &s->sparsexy, s->npoints, 0, &ensemble->network.dummyidx, 0, s->npoints, 0, &ensemble->network.buf, &tmprep, _state);
32996  }
32997  if( s->datatype==1 )
32998  {
32999  mlpeallerrorsx(ensemble, &s->densexy, &s->sparsexy, s->npoints, 1, &ensemble->network.dummyidx, 0, s->npoints, 0, &ensemble->network.buf, &tmprep, _state);
33000  }
33001  rep->relclserror = tmprep.relclserror;
33002  rep->avgce = tmprep.avgce;
33003  rep->rmserror = tmprep.rmserror;
33004  rep->avgerror = tmprep.avgerror;
33005  rep->avgrelerror = tmprep.avgrelerror;
33006  ae_frame_leave(_state);
33007 }
33008 
33009 
33010 /*************************************************************************
33011 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
33012 *************************************************************************/
33013 void _pexec_mlptrainensemblees(mlptrainer* s,
33014  mlpensemble* ensemble,
33015  ae_int_t nrestarts,
33016  mlpreport* rep, ae_state *_state)
33017 {
33018  mlptrainensemblees(s,ensemble,nrestarts,rep, _state);
33019 }
33020 
33021 
33022 /*************************************************************************
33023 Internal cross-validation subroutine
33024 *************************************************************************/
33025 static void mlptrain_mlpkfoldcvgeneral(multilayerperceptron* n,
33026  /* Real */ ae_matrix* xy,
33027  ae_int_t npoints,
33028  double decay,
33029  ae_int_t restarts,
33030  ae_int_t foldscount,
33031  ae_bool lmalgorithm,
33032  double wstep,
33033  ae_int_t maxits,
33034  ae_int_t* info,
33035  mlpreport* rep,
33036  mlpcvreport* cvrep,
33037  ae_state *_state)
33038 {
33039  ae_frame _frame_block;
33040  ae_int_t i;
33041  ae_int_t fold;
33042  ae_int_t j;
33043  ae_int_t k;
33044  multilayerperceptron network;
33045  ae_int_t nin;
33046  ae_int_t nout;
33047  ae_int_t rowlen;
33048  ae_int_t wcount;
33049  ae_int_t nclasses;
33050  ae_int_t tssize;
33051  ae_int_t cvssize;
33052  ae_matrix cvset;
33053  ae_matrix testset;
33054  ae_vector folds;
33055  ae_int_t relcnt;
33056  mlpreport internalrep;
33057  ae_vector x;
33058  ae_vector y;
33059 
33060  ae_frame_make(_state, &_frame_block);
33061  *info = 0;
33062  _mlpreport_clear(rep);
33063  _mlpcvreport_clear(cvrep);
33064  _multilayerperceptron_init(&network, _state, ae_true);
33065  ae_matrix_init(&cvset, 0, 0, DT_REAL, _state, ae_true);
33066  ae_matrix_init(&testset, 0, 0, DT_REAL, _state, ae_true);
33067  ae_vector_init(&folds, 0, DT_INT, _state, ae_true);
33068  _mlpreport_init(&internalrep, _state, ae_true);
33069  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
33070  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
33071 
33072 
33073  /*
33074  * Read network geometry, test parameters
33075  */
33076  mlpproperties(n, &nin, &nout, &wcount, _state);
33077  if( mlpissoftmax(n, _state) )
33078  {
33079  nclasses = nout;
33080  rowlen = nin+1;
33081  }
33082  else
33083  {
33084  nclasses = -nout;
33085  rowlen = nin+nout;
33086  }
33087  if( (npoints<=0||foldscount<2)||foldscount>npoints )
33088  {
33089  *info = -1;
33090  ae_frame_leave(_state);
33091  return;
33092  }
33093  mlpcopy(n, &network, _state);
33094 
33095  /*
33096  * K-fold out cross-validation.
33097  * First, estimate generalization error
33098  */
33099  ae_matrix_set_length(&testset, npoints-1+1, rowlen-1+1, _state);
33100  ae_matrix_set_length(&cvset, npoints-1+1, rowlen-1+1, _state);
33101  ae_vector_set_length(&x, nin-1+1, _state);
33102  ae_vector_set_length(&y, nout-1+1, _state);
33103  mlptrain_mlpkfoldsplit(xy, npoints, nclasses, foldscount, ae_false, &folds, _state);
33104  cvrep->relclserror = 0;
33105  cvrep->avgce = 0;
33106  cvrep->rmserror = 0;
33107  cvrep->avgerror = 0;
33108  cvrep->avgrelerror = 0;
33109  rep->ngrad = 0;
33110  rep->nhess = 0;
33111  rep->ncholesky = 0;
33112  relcnt = 0;
33113  for(fold=0; fold<=foldscount-1; fold++)
33114  {
33115 
33116  /*
33117  * Separate set
33118  */
33119  tssize = 0;
33120  cvssize = 0;
33121  for(i=0; i<=npoints-1; i++)
33122  {
33123  if( folds.ptr.p_int[i]==fold )
33124  {
33125  ae_v_move(&testset.ptr.pp_double[tssize][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,rowlen-1));
33126  tssize = tssize+1;
33127  }
33128  else
33129  {
33130  ae_v_move(&cvset.ptr.pp_double[cvssize][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,rowlen-1));
33131  cvssize = cvssize+1;
33132  }
33133  }
33134 
33135  /*
33136  * Train on CV training set
33137  */
33138  if( lmalgorithm )
33139  {
33140  mlptrainlm(&network, &cvset, cvssize, decay, restarts, info, &internalrep, _state);
33141  }
33142  else
33143  {
33144  mlptrainlbfgs(&network, &cvset, cvssize, decay, restarts, wstep, maxits, info, &internalrep, _state);
33145  }
33146  if( *info<0 )
33147  {
33148  cvrep->relclserror = 0;
33149  cvrep->avgce = 0;
33150  cvrep->rmserror = 0;
33151  cvrep->avgerror = 0;
33152  cvrep->avgrelerror = 0;
33153  ae_frame_leave(_state);
33154  return;
33155  }
33156  rep->ngrad = rep->ngrad+internalrep.ngrad;
33157  rep->nhess = rep->nhess+internalrep.nhess;
33158  rep->ncholesky = rep->ncholesky+internalrep.ncholesky;
33159 
33160  /*
33161  * Estimate error using CV test set
33162  */
33163  if( mlpissoftmax(&network, _state) )
33164  {
33165 
33166  /*
33167  * classification-only code
33168  */
33169  cvrep->relclserror = cvrep->relclserror+mlpclserror(&network, &testset, tssize, _state);
33170  cvrep->avgce = cvrep->avgce+mlperrorn(&network, &testset, tssize, _state);
33171  }
33172  for(i=0; i<=tssize-1; i++)
33173  {
33174  ae_v_move(&x.ptr.p_double[0], 1, &testset.ptr.pp_double[i][0], 1, ae_v_len(0,nin-1));
33175  mlpprocess(&network, &x, &y, _state);
33176  if( mlpissoftmax(&network, _state) )
33177  {
33178 
33179  /*
33180  * Classification-specific code
33181  */
33182  k = ae_round(testset.ptr.pp_double[i][nin], _state);
33183  for(j=0; j<=nout-1; j++)
33184  {
33185  if( j==k )
33186  {
33187  cvrep->rmserror = cvrep->rmserror+ae_sqr(y.ptr.p_double[j]-1, _state);
33188  cvrep->avgerror = cvrep->avgerror+ae_fabs(y.ptr.p_double[j]-1, _state);
33189  cvrep->avgrelerror = cvrep->avgrelerror+ae_fabs(y.ptr.p_double[j]-1, _state);
33190  relcnt = relcnt+1;
33191  }
33192  else
33193  {
33194  cvrep->rmserror = cvrep->rmserror+ae_sqr(y.ptr.p_double[j], _state);
33195  cvrep->avgerror = cvrep->avgerror+ae_fabs(y.ptr.p_double[j], _state);
33196  }
33197  }
33198  }
33199  else
33200  {
33201 
33202  /*
33203  * Regression-specific code
33204  */
33205  for(j=0; j<=nout-1; j++)
33206  {
33207  cvrep->rmserror = cvrep->rmserror+ae_sqr(y.ptr.p_double[j]-testset.ptr.pp_double[i][nin+j], _state);
33208  cvrep->avgerror = cvrep->avgerror+ae_fabs(y.ptr.p_double[j]-testset.ptr.pp_double[i][nin+j], _state);
33209  if( ae_fp_neq(testset.ptr.pp_double[i][nin+j],0) )
33210  {
33211  cvrep->avgrelerror = cvrep->avgrelerror+ae_fabs((y.ptr.p_double[j]-testset.ptr.pp_double[i][nin+j])/testset.ptr.pp_double[i][nin+j], _state);
33212  relcnt = relcnt+1;
33213  }
33214  }
33215  }
33216  }
33217  }
33218  if( mlpissoftmax(&network, _state) )
33219  {
33220  cvrep->relclserror = cvrep->relclserror/npoints;
33221  cvrep->avgce = cvrep->avgce/(ae_log(2, _state)*npoints);
33222  }
33223  cvrep->rmserror = ae_sqrt(cvrep->rmserror/(npoints*nout), _state);
33224  cvrep->avgerror = cvrep->avgerror/(npoints*nout);
33225  if( relcnt>0 )
33226  {
33227  cvrep->avgrelerror = cvrep->avgrelerror/relcnt;
33228  }
33229  *info = 1;
33230  ae_frame_leave(_state);
33231 }
33232 
33233 
33234 /*************************************************************************
33235 Subroutine prepares K-fold split of the training set.
33236 
33237 NOTES:
33238  "NClasses>0" means that we have classification task.
33239  "NClasses<0" means regression task with -NClasses real outputs.
33240 *************************************************************************/
33241 static void mlptrain_mlpkfoldsplit(/* Real */ ae_matrix* xy,
33242  ae_int_t npoints,
33243  ae_int_t nclasses,
33244  ae_int_t foldscount,
33245  ae_bool stratifiedsplits,
33246  /* Integer */ ae_vector* folds,
33247  ae_state *_state)
33248 {
33249  ae_frame _frame_block;
33250  ae_int_t i;
33251  ae_int_t j;
33252  ae_int_t k;
33253  hqrndstate rs;
33254 
33255  ae_frame_make(_state, &_frame_block);
33256  ae_vector_clear(folds);
33257  _hqrndstate_init(&rs, _state, ae_true);
33258 
33259 
33260  /*
33261  * test parameters
33262  */
33263  ae_assert(npoints>0, "MLPKFoldSplit: wrong NPoints!", _state);
33264  ae_assert(nclasses>1||nclasses<0, "MLPKFoldSplit: wrong NClasses!", _state);
33265  ae_assert(foldscount>=2&&foldscount<=npoints, "MLPKFoldSplit: wrong FoldsCount!", _state);
33266  ae_assert(!stratifiedsplits, "MLPKFoldSplit: stratified splits are not supported!", _state);
33267 
33268  /*
33269  * Folds
33270  */
33271  hqrndrandomize(&rs, _state);
33272  ae_vector_set_length(folds, npoints-1+1, _state);
33273  for(i=0; i<=npoints-1; i++)
33274  {
33275  folds->ptr.p_int[i] = i*foldscount/npoints;
33276  }
33277  for(i=0; i<=npoints-2; i++)
33278  {
33279  j = i+hqrnduniformi(&rs, npoints-i, _state);
33280  if( j!=i )
33281  {
33282  k = folds->ptr.p_int[i];
33283  folds->ptr.p_int[i] = folds->ptr.p_int[j];
33284  folds->ptr.p_int[j] = k;
33285  }
33286  }
33287  ae_frame_leave(_state);
33288 }
33289 
33290 
33291 static void mlptrain_mthreadcv(mlptrainer* s,
33292  ae_int_t rowsize,
33293  ae_int_t nrestarts,
33294  /* Integer */ ae_vector* folds,
33295  ae_int_t fold,
33296  ae_int_t dfold,
33297  /* Real */ ae_matrix* cvy,
33298  ae_shared_pool* pooldatacv,
33299  ae_state *_state)
33300 {
33301  ae_frame _frame_block;
33302  mlpparallelizationcv *datacv;
33303  ae_smart_ptr _datacv;
33304  ae_int_t i;
33305 
33306  ae_frame_make(_state, &_frame_block);
33307  ae_smart_ptr_init(&_datacv, (void**)&datacv, _state, ae_true);
33308 
33309  if( fold==dfold-1 )
33310  {
33311 
33312  /*
33313  * Separate set
33314  */
33315  ae_shared_pool_retrieve(pooldatacv, &_datacv, _state);
33316  datacv->subsetsize = 0;
33317  for(i=0; i<=s->npoints-1; i++)
33318  {
33319  if( folds->ptr.p_int[i]!=fold )
33320  {
33321  datacv->subset.ptr.p_int[datacv->subsetsize] = i;
33322  datacv->subsetsize = datacv->subsetsize+1;
33323  }
33324  }
33325 
33326  /*
33327  * Train on CV training set
33328  */
33329  mlptrain_mlptrainnetworkx(s, nrestarts, -1, &datacv->subset, datacv->subsetsize, &datacv->subset, 0, &datacv->network, &datacv->rep, ae_true, &datacv->trnpool, _state);
33330  datacv->ngrad = datacv->ngrad+datacv->rep.ngrad;
33331 
33332  /*
33333  * Estimate error using CV test set
33334  */
33335  for(i=0; i<=s->npoints-1; i++)
33336  {
33337  if( folds->ptr.p_int[i]==fold )
33338  {
33339  if( s->datatype==0 )
33340  {
33341  ae_v_move(&datacv->xyrow.ptr.p_double[0], 1, &s->densexy.ptr.pp_double[i][0], 1, ae_v_len(0,rowsize-1));
33342  }
33343  if( s->datatype==1 )
33344  {
33345  sparsegetrow(&s->sparsexy, i, &datacv->xyrow, _state);
33346  }
33347  mlpprocess(&datacv->network, &datacv->xyrow, &datacv->y, _state);
33348  ae_v_move(&cvy->ptr.pp_double[i][0], 1, &datacv->y.ptr.p_double[0], 1, ae_v_len(0,s->nout-1));
33349  }
33350  }
33351  ae_shared_pool_recycle(pooldatacv, &_datacv, _state);
33352  }
33353  else
33354  {
33355  ae_assert(fold<dfold-1, "MThreadCV: internal error(Fold>DFold-1).", _state);
33356  mlptrain_mthreadcv(s, rowsize, nrestarts, folds, fold, (fold+dfold)/2, cvy, pooldatacv, _state);
33357  mlptrain_mthreadcv(s, rowsize, nrestarts, folds, (fold+dfold)/2, dfold, cvy, pooldatacv, _state);
33358  }
33359  ae_frame_leave(_state);
33360 }
33361 
33362 
33363 static void mlptrain_mlptrainnetworkx(mlptrainer* s,
33364  ae_int_t nrestarts,
33365  ae_int_t algokind,
33366  /* Integer */ ae_vector* trnsubset,
33367  ae_int_t trnsubsetsize,
33368  /* Integer */ ae_vector* valsubset,
33369  ae_int_t valsubsetsize,
33370  multilayerperceptron* network,
33371  mlpreport* rep,
33372  ae_bool isrootcall,
33373  ae_shared_pool* sessions,
33374  ae_state *_state)
33375 {
33376  ae_frame _frame_block;
33377  modelerrors modrep;
33378  double eval;
33379  double ebest;
33380  ae_int_t ngradbatch;
33381  ae_int_t nin;
33382  ae_int_t nout;
33383  ae_int_t wcount;
33384  ae_int_t pcount;
33385  ae_int_t itbest;
33386  ae_int_t itcnt;
33387  ae_int_t ntype;
33388  ae_int_t ttype;
33389  ae_bool rndstart;
33390  ae_int_t i;
33391  ae_int_t nr0;
33392  ae_int_t nr1;
33393  mlpreport rep0;
33394  mlpreport rep1;
33395  ae_bool randomizenetwork;
33396  double bestrmserror;
33397  smlptrnsession *psession;
33398  ae_smart_ptr _psession;
33399 
33400  ae_frame_make(_state, &_frame_block);
33401  _modelerrors_init(&modrep, _state, ae_true);
33402  _mlpreport_init(&rep0, _state, ae_true);
33403  _mlpreport_init(&rep1, _state, ae_true);
33404  ae_smart_ptr_init(&_psession, (void**)&psession, _state, ae_true);
33405 
33406  mlpproperties(network, &nin, &nout, &wcount, _state);
33407 
33408  /*
33409  * Process root call
33410  */
33411  if( isrootcall )
33412  {
33413 
33414  /*
33415  * Check correctness of parameters
33416  */
33417  ae_assert(algokind==0||algokind==-1, "MLPTrainNetworkX: unexpected AlgoKind", _state);
33418  ae_assert(s->npoints>=0, "MLPTrainNetworkX: internal error - parameter S is not initialized or is spoiled(S.NPoints<0)", _state);
33419  if( s->rcpar )
33420  {
33421  ttype = 0;
33422  }
33423  else
33424  {
33425  ttype = 1;
33426  }
33427  if( !mlpissoftmax(network, _state) )
33428  {
33429  ntype = 0;
33430  }
33431  else
33432  {
33433  ntype = 1;
33434  }
33435  ae_assert(ntype==ttype, "MLPTrainNetworkX: internal error - type of the training network is not similar to network type in trainer object", _state);
33436  ae_assert(s->nin==nin, "MLPTrainNetworkX: internal error - number of inputs in trainer is not equal to number of inputs in the training network.", _state);
33437  ae_assert(s->nout==nout, "MLPTrainNetworkX: internal error - number of outputs in trainer is not equal to number of outputs in the training network.", _state);
33438  ae_assert(nrestarts>=0, "MLPTrainNetworkX: internal error - NRestarts<0.", _state);
33439  ae_assert(trnsubset->cnt>=trnsubsetsize, "MLPTrainNetworkX: internal error - parameter TrnSubsetSize more than input subset size(Length(TrnSubset)<TrnSubsetSize)", _state);
33440  for(i=0; i<=trnsubsetsize-1; i++)
33441  {
33442  ae_assert(trnsubset->ptr.p_int[i]>=0&&trnsubset->ptr.p_int[i]<=s->npoints-1, "MLPTrainNetworkX: internal error - parameter TrnSubset contains incorrect index(TrnSubset[I]<0 or TrnSubset[I]>S.NPoints-1)", _state);
33443  }
33444  ae_assert(valsubset->cnt>=valsubsetsize, "MLPTrainNetworkX: internal error - parameter ValSubsetSize more than input subset size(Length(ValSubset)<ValSubsetSize)", _state);
33445  for(i=0; i<=valsubsetsize-1; i++)
33446  {
33447  ae_assert(valsubset->ptr.p_int[i]>=0&&valsubset->ptr.p_int[i]<=s->npoints-1, "MLPTrainNetworkX: internal error - parameter ValSubset contains incorrect index(ValSubset[I]<0 or ValSubset[I]>S.NPoints-1)", _state);
33448  }
33449 
33450  /*
33451  * Train
33452  */
33453  randomizenetwork = nrestarts>0;
33454  mlptrain_initmlptrnsessions(network, randomizenetwork, s, sessions, _state);
33455  mlptrain_mlptrainnetworkx(s, nrestarts, algokind, trnsubset, trnsubsetsize, valsubset, valsubsetsize, network, rep, ae_false, sessions, _state);
33456 
33457  /*
33458  * Choose best network
33459  */
33460  bestrmserror = ae_maxrealnumber;
33461  ae_shared_pool_first_recycled(sessions, &_psession, _state);
33462  while(psession!=NULL)
33463  {
33464  if( ae_fp_less(psession->bestrmserror,bestrmserror) )
33465  {
33466  mlpimporttunableparameters(network, &psession->bestparameters, _state);
33467  bestrmserror = psession->bestrmserror;
33468  }
33469  ae_shared_pool_next_recycled(sessions, &_psession, _state);
33470  }
33471 
33472  /*
33473  * Calculate errors
33474  */
33475  if( s->datatype==0 )
33476  {
33477  mlpallerrorssubset(network, &s->densexy, s->npoints, trnsubset, trnsubsetsize, &modrep, _state);
33478  }
33479  if( s->datatype==1 )
33480  {
33481  mlpallerrorssparsesubset(network, &s->sparsexy, s->npoints, trnsubset, trnsubsetsize, &modrep, _state);
33482  }
33483  rep->relclserror = modrep.relclserror;
33484  rep->avgce = modrep.avgce;
33485  rep->rmserror = modrep.rmserror;
33486  rep->avgerror = modrep.avgerror;
33487  rep->avgrelerror = modrep.avgrelerror;
33488 
33489  /*
33490  * Done
33491  */
33492  ae_frame_leave(_state);
33493  return;
33494  }
33495 
33496  /*
33497  * Split problem, if we have more than 1 restart
33498  */
33499  if( nrestarts>=2 )
33500  {
33501 
33502  /*
33503  * Divide problem with NRestarts into two: NR0 and NR1.
33504  */
33505  nr0 = nrestarts/2;
33506  nr1 = nrestarts-nr0;
33507  mlptrain_mlptrainnetworkx(s, nr0, algokind, trnsubset, trnsubsetsize, valsubset, valsubsetsize, network, &rep0, ae_false, sessions, _state);
33508  mlptrain_mlptrainnetworkx(s, nr1, algokind, trnsubset, trnsubsetsize, valsubset, valsubsetsize, network, &rep1, ae_false, sessions, _state);
33509 
33510  /*
33511  * Aggregate results
33512  */
33513  rep->ngrad = rep0.ngrad+rep1.ngrad;
33514  rep->nhess = rep0.nhess+rep1.nhess;
33515  rep->ncholesky = rep0.ncholesky+rep1.ncholesky;
33516 
33517  /*
33518  * Done :)
33519  */
33520  ae_frame_leave(_state);
33521  return;
33522  }
33523 
33524  /*
33525  * Execution with NRestarts=1 or NRestarts=0:
33526  * * NRestarts=1 means that network is restarted from random position
33527  * * NRestarts=0 means that network is not randomized
33528  */
33529  ae_assert(nrestarts==0||nrestarts==1, "MLPTrainNetworkX: internal error", _state);
33530  rep->ngrad = 0;
33531  rep->nhess = 0;
33532  rep->ncholesky = 0;
33533  ae_shared_pool_retrieve(sessions, &_psession, _state);
33534  if( ((s->datatype==0||s->datatype==1)&&s->npoints>0)&&trnsubsetsize!=0 )
33535  {
33536 
33537  /*
33538  * Train network using combination of early stopping and step-size
33539  * and step-count based criteria. Network state with best value of
33540  * validation set error is stored in WBuf0. When validation set is
33541  * zero, most recent state of network is stored.
33542  */
33543  rndstart = nrestarts!=0;
33544  ngradbatch = 0;
33545  eval = 0;
33546  ebest = 0;
33547  itbest = 0;
33548  itcnt = 0;
33549  mlptrain_mlpstarttrainingx(s, rndstart, algokind, trnsubset, trnsubsetsize, psession, _state);
33550  if( s->datatype==0 )
33551  {
33552  ebest = mlperrorsubset(&psession->network, &s->densexy, s->npoints, valsubset, valsubsetsize, _state);
33553  }
33554  if( s->datatype==1 )
33555  {
33556  ebest = mlperrorsparsesubset(&psession->network, &s->sparsexy, s->npoints, valsubset, valsubsetsize, _state);
33557  }
33558  ae_v_move(&psession->wbuf0.ptr.p_double[0], 1, &psession->network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
33559  while(mlptrain_mlpcontinuetrainingx(s, trnsubset, trnsubsetsize, &ngradbatch, psession, _state))
33560  {
33561  if( s->datatype==0 )
33562  {
33563  eval = mlperrorsubset(&psession->network, &s->densexy, s->npoints, valsubset, valsubsetsize, _state);
33564  }
33565  if( s->datatype==1 )
33566  {
33567  eval = mlperrorsparsesubset(&psession->network, &s->sparsexy, s->npoints, valsubset, valsubsetsize, _state);
33568  }
33569  if( ae_fp_less_eq(eval,ebest)||valsubsetsize==0 )
33570  {
33571  ae_v_move(&psession->wbuf0.ptr.p_double[0], 1, &psession->network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
33572  ebest = eval;
33573  itbest = itcnt;
33574  }
33575  if( itcnt>30&&ae_fp_greater(itcnt,1.5*itbest) )
33576  {
33577  break;
33578  }
33579  itcnt = itcnt+1;
33580  }
33581  ae_v_move(&psession->network.weights.ptr.p_double[0], 1, &psession->wbuf0.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
33582  rep->ngrad = ngradbatch;
33583  }
33584  else
33585  {
33586  for(i=0; i<=wcount-1; i++)
33587  {
33588  psession->network.weights.ptr.p_double[i] = 0;
33589  }
33590  }
33591 
33592  /*
33593  * Evaluate network performance and update PSession.BestParameters/BestRMSError
33594  * (if needed).
33595  */
33596  if( s->datatype==0 )
33597  {
33598  mlpallerrorssubset(&psession->network, &s->densexy, s->npoints, trnsubset, trnsubsetsize, &modrep, _state);
33599  }
33600  if( s->datatype==1 )
33601  {
33602  mlpallerrorssparsesubset(&psession->network, &s->sparsexy, s->npoints, trnsubset, trnsubsetsize, &modrep, _state);
33603  }
33604  if( ae_fp_less(modrep.rmserror,psession->bestrmserror) )
33605  {
33606  mlpexporttunableparameters(&psession->network, &psession->bestparameters, &pcount, _state);
33607  psession->bestrmserror = modrep.rmserror;
33608  }
33609 
33610  /*
33611  * Move session back to pool
33612  */
33613  ae_shared_pool_recycle(sessions, &_psession, _state);
33614  ae_frame_leave(_state);
33615 }
33616 
33617 
33618 static void mlptrain_mlptrainensemblex(mlptrainer* s,
33619  mlpensemble* ensemble,
33620  ae_int_t idx0,
33621  ae_int_t idx1,
33622  ae_int_t nrestarts,
33623  ae_int_t trainingmethod,
33624  sinteger* ngrad,
33625  ae_bool isrootcall,
33626  ae_shared_pool* esessions,
33627  ae_state *_state)
33628 {
33629  ae_frame _frame_block;
33630  ae_int_t pcount;
33631  ae_int_t nin;
33632  ae_int_t nout;
33633  ae_int_t wcount;
33634  ae_int_t i;
33635  ae_int_t j;
33636  ae_int_t k;
33637  ae_int_t trnsubsetsize;
33638  ae_int_t valsubsetsize;
33639  ae_int_t k0;
33640  sinteger ngrad0;
33641  sinteger ngrad1;
33642  mlpetrnsession *psession;
33643  ae_smart_ptr _psession;
33644  hqrndstate rs;
33645 
33646  ae_frame_make(_state, &_frame_block);
33647  _sinteger_init(&ngrad0, _state, ae_true);
33648  _sinteger_init(&ngrad1, _state, ae_true);
33649  ae_smart_ptr_init(&_psession, (void**)&psession, _state, ae_true);
33650  _hqrndstate_init(&rs, _state, ae_true);
33651 
33652  nin = mlpgetinputscount(&ensemble->network, _state);
33653  nout = mlpgetoutputscount(&ensemble->network, _state);
33654  wcount = mlpgetweightscount(&ensemble->network, _state);
33655  if( mlpissoftmax(&ensemble->network, _state) )
33656  {
33657  pcount = nin;
33658  }
33659  else
33660  {
33661  pcount = nin+nout;
33662  }
33663  if( nrestarts<=0 )
33664  {
33665  nrestarts = 1;
33666  }
33667 
33668  /*
33669  * Handle degenerate case
33670  */
33671  if( s->npoints<2 )
33672  {
33673  for(i=idx0; i<=idx1-1; i++)
33674  {
33675  for(j=0; j<=wcount-1; j++)
33676  {
33677  ensemble->weights.ptr.p_double[i*wcount+j] = 0.0;
33678  }
33679  for(j=0; j<=pcount-1; j++)
33680  {
33681  ensemble->columnmeans.ptr.p_double[i*pcount+j] = 0.0;
33682  ensemble->columnsigmas.ptr.p_double[i*pcount+j] = 1.0;
33683  }
33684  }
33685  ae_frame_leave(_state);
33686  return;
33687  }
33688 
33689  /*
33690  * Process root call
33691  */
33692  if( isrootcall )
33693  {
33694 
33695  /*
33696  * Prepare:
33697  * * prepare MLPETrnSessions
33698  * * fill ensemble by zeros (helps to detect errors)
33699  */
33700  mlptrain_initmlpetrnsessions(&ensemble->network, s, esessions, _state);
33701  for(i=idx0; i<=idx1-1; i++)
33702  {
33703  for(j=0; j<=wcount-1; j++)
33704  {
33705  ensemble->weights.ptr.p_double[i*wcount+j] = 0.0;
33706  }
33707  for(j=0; j<=pcount-1; j++)
33708  {
33709  ensemble->columnmeans.ptr.p_double[i*pcount+j] = 0.0;
33710  ensemble->columnsigmas.ptr.p_double[i*pcount+j] = 0.0;
33711  }
33712  }
33713 
33714  /*
33715  * Train in non-root mode and exit
33716  */
33717  mlptrain_mlptrainensemblex(s, ensemble, idx0, idx1, nrestarts, trainingmethod, ngrad, ae_false, esessions, _state);
33718  ae_frame_leave(_state);
33719  return;
33720  }
33721 
33722  /*
33723  * Split problem
33724  */
33725  if( idx1-idx0>=2 )
33726  {
33727  k0 = (idx1-idx0)/2;
33728  ngrad0.val = 0;
33729  ngrad1.val = 0;
33730  mlptrain_mlptrainensemblex(s, ensemble, idx0, idx0+k0, nrestarts, trainingmethod, &ngrad0, ae_false, esessions, _state);
33731  mlptrain_mlptrainensemblex(s, ensemble, idx0+k0, idx1, nrestarts, trainingmethod, &ngrad1, ae_false, esessions, _state);
33732  ngrad->val = ngrad0.val+ngrad1.val;
33733  ae_frame_leave(_state);
33734  return;
33735  }
33736 
33737  /*
33738  * Retrieve and prepare session
33739  */
33740  ae_shared_pool_retrieve(esessions, &_psession, _state);
33741 
33742  /*
33743  * Train
33744  */
33745  hqrndrandomize(&rs, _state);
33746  for(k=idx0; k<=idx1-1; k++)
33747  {
33748 
33749  /*
33750  * Split set
33751  */
33752  trnsubsetsize = 0;
33753  valsubsetsize = 0;
33754  if( trainingmethod==0 )
33755  {
33756  do
33757  {
33758  trnsubsetsize = 0;
33759  valsubsetsize = 0;
33760  for(i=0; i<=s->npoints-1; i++)
33761  {
33762  if( ae_fp_less(ae_randomreal(_state),0.66) )
33763  {
33764 
33765  /*
33766  * Assign sample to training set
33767  */
33768  psession->trnsubset.ptr.p_int[trnsubsetsize] = i;
33769  trnsubsetsize = trnsubsetsize+1;
33770  }
33771  else
33772  {
33773 
33774  /*
33775  * Assign sample to validation set
33776  */
33777  psession->valsubset.ptr.p_int[valsubsetsize] = i;
33778  valsubsetsize = valsubsetsize+1;
33779  }
33780  }
33781  }
33782  while(!(trnsubsetsize!=0&&valsubsetsize!=0));
33783  }
33784  if( trainingmethod==1 )
33785  {
33786  valsubsetsize = 0;
33787  trnsubsetsize = s->npoints;
33788  for(i=0; i<=s->npoints-1; i++)
33789  {
33790  psession->trnsubset.ptr.p_int[i] = hqrnduniformi(&rs, s->npoints, _state);
33791  }
33792  }
33793 
33794  /*
33795  * Train
33796  */
33797  mlptrain_mlptrainnetworkx(s, nrestarts, -1, &psession->trnsubset, trnsubsetsize, &psession->valsubset, valsubsetsize, &psession->network, &psession->mlprep, ae_true, &psession->mlpsessions, _state);
33798  ngrad->val = ngrad->val+psession->mlprep.ngrad;
33799 
33800  /*
33801  * Save results
33802  */
33803  ae_v_move(&ensemble->weights.ptr.p_double[k*wcount], 1, &psession->network.weights.ptr.p_double[0], 1, ae_v_len(k*wcount,(k+1)*wcount-1));
33804  ae_v_move(&ensemble->columnmeans.ptr.p_double[k*pcount], 1, &psession->network.columnmeans.ptr.p_double[0], 1, ae_v_len(k*pcount,(k+1)*pcount-1));
33805  ae_v_move(&ensemble->columnsigmas.ptr.p_double[k*pcount], 1, &psession->network.columnsigmas.ptr.p_double[0], 1, ae_v_len(k*pcount,(k+1)*pcount-1));
33806  }
33807 
33808  /*
33809  * Recycle session
33810  */
33811  ae_shared_pool_recycle(esessions, &_psession, _state);
33812  ae_frame_leave(_state);
33813 }
33814 
33815 
33816 /*************************************************************************
33817 This function performs step-by-step training of the neural network. Here
33818 "step-by-step" means that training starts with MLPStartTrainingX call,
33819 and then user subsequently calls MLPContinueTrainingX to perform one more
33820 iteration of the training.
33821 
33822 After call to this function trainer object remembers network and is ready
33823 to train it. However, no training is performed until first call to
33824 MLPContinueTraining() function. Subsequent calls to MLPContinueTraining()
33825 will advance traing progress one iteration further.
33826 
33827 
33828  -- ALGLIB --
33829  Copyright 13.08.2012 by Bochkanov Sergey
33830 *************************************************************************/
33831 static void mlptrain_mlpstarttrainingx(mlptrainer* s,
33832  ae_bool randomstart,
33833  ae_int_t algokind,
33834  /* Integer */ ae_vector* subset,
33835  ae_int_t subsetsize,
33836  smlptrnsession* session,
33837  ae_state *_state)
33838 {
33839  ae_int_t nin;
33840  ae_int_t nout;
33841  ae_int_t wcount;
33842  ae_int_t ntype;
33843  ae_int_t ttype;
33844  ae_int_t i;
33845 
33846 
33847 
33848  /*
33849  * Check parameters
33850  */
33851  ae_assert(s->npoints>=0, "MLPStartTrainingX: internal error - parameter S is not initialized or is spoiled(S.NPoints<0)", _state);
33852  ae_assert(algokind==0||algokind==-1, "MLPStartTrainingX: unexpected AlgoKind", _state);
33853  if( s->rcpar )
33854  {
33855  ttype = 0;
33856  }
33857  else
33858  {
33859  ttype = 1;
33860  }
33861  if( !mlpissoftmax(&session->network, _state) )
33862  {
33863  ntype = 0;
33864  }
33865  else
33866  {
33867  ntype = 1;
33868  }
33869  ae_assert(ntype==ttype, "MLPStartTrainingX: internal error - type of the resulting network is not similar to network type in trainer object", _state);
33870  mlpproperties(&session->network, &nin, &nout, &wcount, _state);
33871  ae_assert(s->nin==nin, "MLPStartTrainingX: number of inputs in trainer is not equal to number of inputs in the network.", _state);
33872  ae_assert(s->nout==nout, "MLPStartTrainingX: number of outputs in trainer is not equal to number of outputs in the network.", _state);
33873  ae_assert(subset->cnt>=subsetsize, "MLPStartTrainingX: internal error - parameter SubsetSize more than input subset size(Length(Subset)<SubsetSize)", _state);
33874  for(i=0; i<=subsetsize-1; i++)
33875  {
33876  ae_assert(subset->ptr.p_int[i]>=0&&subset->ptr.p_int[i]<=s->npoints-1, "MLPStartTrainingX: internal error - parameter Subset contains incorrect index(Subset[I]<0 or Subset[I]>S.NPoints-1)", _state);
33877  }
33878 
33879  /*
33880  * Prepare session
33881  */
33882  minlbfgssetcond(&session->optimizer, 0.0, 0.0, s->wstep, s->maxits, _state);
33883  if( s->npoints>0&&subsetsize!=0 )
33884  {
33885  if( randomstart )
33886  {
33887  mlprandomize(&session->network, _state);
33888  }
33889  minlbfgsrestartfrom(&session->optimizer, &session->network.weights, _state);
33890  }
33891  else
33892  {
33893  for(i=0; i<=wcount-1; i++)
33894  {
33895  session->network.weights.ptr.p_double[i] = 0;
33896  }
33897  }
33898  if( algokind==-1 )
33899  {
33900  session->algoused = s->algokind;
33901  if( s->algokind==1 )
33902  {
33903  session->minibatchsize = s->minibatchsize;
33904  }
33905  }
33906  else
33907  {
33908  session->algoused = 0;
33909  }
33910  hqrndrandomize(&session->generator, _state);
33911  ae_vector_set_length(&session->rstate.ia, 15+1, _state);
33912  ae_vector_set_length(&session->rstate.ra, 1+1, _state);
33913  session->rstate.stage = -1;
33914 }
33915 
33916 
33917 /*************************************************************************
33918 This function performs step-by-step training of the neural network. Here
33919 "step-by-step" means that training starts with MLPStartTrainingX call,
33920 and then user subsequently calls MLPContinueTrainingX to perform one more
33921 iteration of the training.
33922 
33923 This function performs one more iteration of the training and returns
33924 either True (training continues) or False (training stopped). In case True
33925 was returned, Network weights are updated according to the current state
33926 of the optimization progress. In case False was returned, no additional
33927 updates is performed (previous update of the network weights moved us to
33928 the final point, and no additional updates is needed).
33929 
33930 EXAMPLE:
33931  >
33932  > [initialize network and trainer object]
33933  >
33934  > MLPStartTraining(Trainer, Network, True)
33935  > while MLPContinueTraining(Trainer, Network) do
33936  > [visualize training progress]
33937  >
33938 
33939 
33940  -- ALGLIB --
33941  Copyright 13.08.2012 by Bochkanov Sergey
33942 *************************************************************************/
33943 static ae_bool mlptrain_mlpcontinuetrainingx(mlptrainer* s,
33944  /* Integer */ ae_vector* subset,
33945  ae_int_t subsetsize,
33946  ae_int_t* ngradbatch,
33947  smlptrnsession* session,
33948  ae_state *_state)
33949 {
33950  ae_int_t nin;
33951  ae_int_t nout;
33952  ae_int_t wcount;
33953  ae_int_t twcount;
33954  ae_int_t ntype;
33955  ae_int_t ttype;
33956  double decay;
33957  double v;
33958  ae_int_t i;
33959  ae_int_t j;
33960  ae_int_t k;
33961  ae_int_t trnsetsize;
33962  ae_int_t epoch;
33963  ae_int_t minibatchcount;
33964  ae_int_t minibatchidx;
33965  ae_int_t cursize;
33966  ae_int_t idx0;
33967  ae_int_t idx1;
33968  ae_bool result;
33969 
33970 
33971 
33972  /*
33973  * Reverse communication preparations
33974  * I know it looks ugly, but it works the same way
33975  * anywhere from C++ to Python.
33976  *
33977  * This code initializes locals by:
33978  * * random values determined during code
33979  * generation - on first subroutine call
33980  * * values from previous call - on subsequent calls
33981  */
33982  if( session->rstate.stage>=0 )
33983  {
33984  nin = session->rstate.ia.ptr.p_int[0];
33985  nout = session->rstate.ia.ptr.p_int[1];
33986  wcount = session->rstate.ia.ptr.p_int[2];
33987  twcount = session->rstate.ia.ptr.p_int[3];
33988  ntype = session->rstate.ia.ptr.p_int[4];
33989  ttype = session->rstate.ia.ptr.p_int[5];
33990  i = session->rstate.ia.ptr.p_int[6];
33991  j = session->rstate.ia.ptr.p_int[7];
33992  k = session->rstate.ia.ptr.p_int[8];
33993  trnsetsize = session->rstate.ia.ptr.p_int[9];
33994  epoch = session->rstate.ia.ptr.p_int[10];
33995  minibatchcount = session->rstate.ia.ptr.p_int[11];
33996  minibatchidx = session->rstate.ia.ptr.p_int[12];
33997  cursize = session->rstate.ia.ptr.p_int[13];
33998  idx0 = session->rstate.ia.ptr.p_int[14];
33999  idx1 = session->rstate.ia.ptr.p_int[15];
34000  decay = session->rstate.ra.ptr.p_double[0];
34001  v = session->rstate.ra.ptr.p_double[1];
34002  }
34003  else
34004  {
34005  nin = -983;
34006  nout = -989;
34007  wcount = -834;
34008  twcount = 900;
34009  ntype = -287;
34010  ttype = 364;
34011  i = 214;
34012  j = -338;
34013  k = -686;
34014  trnsetsize = 912;
34015  epoch = 585;
34016  minibatchcount = 497;
34017  minibatchidx = -271;
34018  cursize = -581;
34019  idx0 = 745;
34020  idx1 = -533;
34021  decay = -77;
34022  v = 678;
34023  }
34024  if( session->rstate.stage==0 )
34025  {
34026  goto lbl_0;
34027  }
34028 
34029  /*
34030  * Routine body
34031  */
34032 
34033  /*
34034  * Check correctness of inputs
34035  */
34036  ae_assert(s->npoints>=0, "MLPContinueTrainingX: internal error - parameter S is not initialized or is spoiled(S.NPoints<0).", _state);
34037  if( s->rcpar )
34038  {
34039  ttype = 0;
34040  }
34041  else
34042  {
34043  ttype = 1;
34044  }
34045  if( !mlpissoftmax(&session->network, _state) )
34046  {
34047  ntype = 0;
34048  }
34049  else
34050  {
34051  ntype = 1;
34052  }
34053  ae_assert(ntype==ttype, "MLPContinueTrainingX: internal error - type of the resulting network is not similar to network type in trainer object.", _state);
34054  mlpproperties(&session->network, &nin, &nout, &wcount, _state);
34055  ae_assert(s->nin==nin, "MLPContinueTrainingX: internal error - number of inputs in trainer is not equal to number of inputs in the network.", _state);
34056  ae_assert(s->nout==nout, "MLPContinueTrainingX: internal error - number of outputs in trainer is not equal to number of outputs in the network.", _state);
34057  ae_assert(subset->cnt>=subsetsize, "MLPContinueTrainingX: internal error - parameter SubsetSize more than input subset size(Length(Subset)<SubsetSize).", _state);
34058  for(i=0; i<=subsetsize-1; i++)
34059  {
34060  ae_assert(subset->ptr.p_int[i]>=0&&subset->ptr.p_int[i]<=s->npoints-1, "MLPContinueTrainingX: internal error - parameter Subset contains incorrect index(Subset[I]<0 or Subset[I]>S.NPoints-1).", _state);
34061  }
34062 
34063  /*
34064  * Quick exit on empty training set
34065  */
34066  if( s->npoints==0||subsetsize==0 )
34067  {
34068  result = ae_false;
34069  return result;
34070  }
34071 
34072  /*
34073  * Minibatch training
34074  */
34075  if( session->algoused==1 )
34076  {
34077  ae_assert(ae_false, "MINIBATCH TRAINING IS NOT IMPLEMENTED YET", _state);
34078  }
34079 
34080  /*
34081  * Last option: full batch training
34082  */
34083  decay = s->decay;
34084 lbl_1:
34085  if( !minlbfgsiteration(&session->optimizer, _state) )
34086  {
34087  goto lbl_2;
34088  }
34089  if( !session->optimizer.xupdated )
34090  {
34091  goto lbl_3;
34092  }
34093  ae_v_move(&session->network.weights.ptr.p_double[0], 1, &session->optimizer.x.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
34094  session->rstate.stage = 0;
34095  goto lbl_rcomm;
34096 lbl_0:
34097 lbl_3:
34098  ae_v_move(&session->network.weights.ptr.p_double[0], 1, &session->optimizer.x.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
34099  if( s->datatype==0 )
34100  {
34101  mlpgradbatchsubset(&session->network, &s->densexy, s->npoints, subset, subsetsize, &session->optimizer.f, &session->optimizer.g, _state);
34102  }
34103  if( s->datatype==1 )
34104  {
34105  mlpgradbatchsparsesubset(&session->network, &s->sparsexy, s->npoints, subset, subsetsize, &session->optimizer.f, &session->optimizer.g, _state);
34106  }
34107 
34108  /*
34109  * Increment number of operations performed on batch gradient
34110  */
34111  *ngradbatch = *ngradbatch+1;
34112  v = ae_v_dotproduct(&session->network.weights.ptr.p_double[0], 1, &session->network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
34113  session->optimizer.f = session->optimizer.f+0.5*decay*v;
34114  ae_v_addd(&session->optimizer.g.ptr.p_double[0], 1, &session->network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1), decay);
34115  goto lbl_1;
34116 lbl_2:
34117  minlbfgsresultsbuf(&session->optimizer, &session->network.weights, &session->optimizerrep, _state);
34118  result = ae_false;
34119  return result;
34120 
34121  /*
34122  * Saving state
34123  */
34124 lbl_rcomm:
34125  result = ae_true;
34126  session->rstate.ia.ptr.p_int[0] = nin;
34127  session->rstate.ia.ptr.p_int[1] = nout;
34128  session->rstate.ia.ptr.p_int[2] = wcount;
34129  session->rstate.ia.ptr.p_int[3] = twcount;
34130  session->rstate.ia.ptr.p_int[4] = ntype;
34131  session->rstate.ia.ptr.p_int[5] = ttype;
34132  session->rstate.ia.ptr.p_int[6] = i;
34133  session->rstate.ia.ptr.p_int[7] = j;
34134  session->rstate.ia.ptr.p_int[8] = k;
34135  session->rstate.ia.ptr.p_int[9] = trnsetsize;
34136  session->rstate.ia.ptr.p_int[10] = epoch;
34137  session->rstate.ia.ptr.p_int[11] = minibatchcount;
34138  session->rstate.ia.ptr.p_int[12] = minibatchidx;
34139  session->rstate.ia.ptr.p_int[13] = cursize;
34140  session->rstate.ia.ptr.p_int[14] = idx0;
34141  session->rstate.ia.ptr.p_int[15] = idx1;
34142  session->rstate.ra.ptr.p_double[0] = decay;
34143  session->rstate.ra.ptr.p_double[1] = v;
34144  return result;
34145 }
34146 
34147 
34148 /*************************************************************************
34149 Internal bagging subroutine.
34150 
34151  -- ALGLIB --
34152  Copyright 19.02.2009 by Bochkanov Sergey
34153 *************************************************************************/
34154 static void mlptrain_mlpebagginginternal(mlpensemble* ensemble,
34155  /* Real */ ae_matrix* xy,
34156  ae_int_t npoints,
34157  double decay,
34158  ae_int_t restarts,
34159  double wstep,
34160  ae_int_t maxits,
34161  ae_bool lmalgorithm,
34162  ae_int_t* info,
34163  mlpreport* rep,
34164  mlpcvreport* ooberrors,
34165  ae_state *_state)
34166 {
34167  ae_frame _frame_block;
34168  ae_matrix xys;
34169  ae_vector s;
34170  ae_matrix oobbuf;
34171  ae_vector oobcntbuf;
34172  ae_vector x;
34173  ae_vector y;
34174  ae_vector dy;
34175  ae_vector dsbuf;
34176  ae_int_t ccnt;
34177  ae_int_t pcnt;
34178  ae_int_t i;
34179  ae_int_t j;
34180  ae_int_t k;
34181  double v;
34182  mlpreport tmprep;
34183  ae_int_t nin;
34184  ae_int_t nout;
34185  ae_int_t wcount;
34186  hqrndstate rs;
34187 
34188  ae_frame_make(_state, &_frame_block);
34189  *info = 0;
34190  _mlpreport_clear(rep);
34191  _mlpcvreport_clear(ooberrors);
34192  ae_matrix_init(&xys, 0, 0, DT_REAL, _state, ae_true);
34193  ae_vector_init(&s, 0, DT_BOOL, _state, ae_true);
34194  ae_matrix_init(&oobbuf, 0, 0, DT_REAL, _state, ae_true);
34195  ae_vector_init(&oobcntbuf, 0, DT_INT, _state, ae_true);
34196  ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
34197  ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
34198  ae_vector_init(&dy, 0, DT_REAL, _state, ae_true);
34199  ae_vector_init(&dsbuf, 0, DT_REAL, _state, ae_true);
34200  _mlpreport_init(&tmprep, _state, ae_true);
34201  _hqrndstate_init(&rs, _state, ae_true);
34202 
34203  nin = mlpgetinputscount(&ensemble->network, _state);
34204  nout = mlpgetoutputscount(&ensemble->network, _state);
34205  wcount = mlpgetweightscount(&ensemble->network, _state);
34206 
34207  /*
34208  * Test for inputs
34209  */
34210  if( (!lmalgorithm&&ae_fp_eq(wstep,0))&&maxits==0 )
34211  {
34212  *info = -8;
34213  ae_frame_leave(_state);
34214  return;
34215  }
34216  if( ((npoints<=0||restarts<1)||ae_fp_less(wstep,0))||maxits<0 )
34217  {
34218  *info = -1;
34219  ae_frame_leave(_state);
34220  return;
34221  }
34222  if( mlpissoftmax(&ensemble->network, _state) )
34223  {
34224  for(i=0; i<=npoints-1; i++)
34225  {
34226  if( ae_round(xy->ptr.pp_double[i][nin], _state)<0||ae_round(xy->ptr.pp_double[i][nin], _state)>=nout )
34227  {
34228  *info = -2;
34229  ae_frame_leave(_state);
34230  return;
34231  }
34232  }
34233  }
34234 
34235  /*
34236  * allocate temporaries
34237  */
34238  *info = 2;
34239  rep->ngrad = 0;
34240  rep->nhess = 0;
34241  rep->ncholesky = 0;
34242  ooberrors->relclserror = 0;
34243  ooberrors->avgce = 0;
34244  ooberrors->rmserror = 0;
34245  ooberrors->avgerror = 0;
34246  ooberrors->avgrelerror = 0;
34247  if( mlpissoftmax(&ensemble->network, _state) )
34248  {
34249  ccnt = nin+1;
34250  pcnt = nin;
34251  }
34252  else
34253  {
34254  ccnt = nin+nout;
34255  pcnt = nin+nout;
34256  }
34257  ae_matrix_set_length(&xys, npoints, ccnt, _state);
34258  ae_vector_set_length(&s, npoints, _state);
34259  ae_matrix_set_length(&oobbuf, npoints, nout, _state);
34260  ae_vector_set_length(&oobcntbuf, npoints, _state);
34261  ae_vector_set_length(&x, nin, _state);
34262  ae_vector_set_length(&y, nout, _state);
34263  if( mlpissoftmax(&ensemble->network, _state) )
34264  {
34265  ae_vector_set_length(&dy, 1, _state);
34266  }
34267  else
34268  {
34269  ae_vector_set_length(&dy, nout, _state);
34270  }
34271  for(i=0; i<=npoints-1; i++)
34272  {
34273  for(j=0; j<=nout-1; j++)
34274  {
34275  oobbuf.ptr.pp_double[i][j] = 0;
34276  }
34277  }
34278  for(i=0; i<=npoints-1; i++)
34279  {
34280  oobcntbuf.ptr.p_int[i] = 0;
34281  }
34282 
34283  /*
34284  * main bagging cycle
34285  */
34286  hqrndrandomize(&rs, _state);
34287  for(k=0; k<=ensemble->ensemblesize-1; k++)
34288  {
34289 
34290  /*
34291  * prepare dataset
34292  */
34293  for(i=0; i<=npoints-1; i++)
34294  {
34295  s.ptr.p_bool[i] = ae_false;
34296  }
34297  for(i=0; i<=npoints-1; i++)
34298  {
34299  j = hqrnduniformi(&rs, npoints, _state);
34300  s.ptr.p_bool[j] = ae_true;
34301  ae_v_move(&xys.ptr.pp_double[i][0], 1, &xy->ptr.pp_double[j][0], 1, ae_v_len(0,ccnt-1));
34302  }
34303 
34304  /*
34305  * train
34306  */
34307  if( lmalgorithm )
34308  {
34309  mlptrainlm(&ensemble->network, &xys, npoints, decay, restarts, info, &tmprep, _state);
34310  }
34311  else
34312  {
34313  mlptrainlbfgs(&ensemble->network, &xys, npoints, decay, restarts, wstep, maxits, info, &tmprep, _state);
34314  }
34315  if( *info<0 )
34316  {
34317  ae_frame_leave(_state);
34318  return;
34319  }
34320 
34321  /*
34322  * save results
34323  */
34324  rep->ngrad = rep->ngrad+tmprep.ngrad;
34325  rep->nhess = rep->nhess+tmprep.nhess;
34326  rep->ncholesky = rep->ncholesky+tmprep.ncholesky;
34327  ae_v_move(&ensemble->weights.ptr.p_double[k*wcount], 1, &ensemble->network.weights.ptr.p_double[0], 1, ae_v_len(k*wcount,(k+1)*wcount-1));
34328  ae_v_move(&ensemble->columnmeans.ptr.p_double[k*pcnt], 1, &ensemble->network.columnmeans.ptr.p_double[0], 1, ae_v_len(k*pcnt,(k+1)*pcnt-1));
34329  ae_v_move(&ensemble->columnsigmas.ptr.p_double[k*pcnt], 1, &ensemble->network.columnsigmas.ptr.p_double[0], 1, ae_v_len(k*pcnt,(k+1)*pcnt-1));
34330 
34331  /*
34332  * OOB estimates
34333  */
34334  for(i=0; i<=npoints-1; i++)
34335  {
34336  if( !s.ptr.p_bool[i] )
34337  {
34338  ae_v_move(&x.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nin-1));
34339  mlpprocess(&ensemble->network, &x, &y, _state);
34340  ae_v_add(&oobbuf.ptr.pp_double[i][0], 1, &y.ptr.p_double[0], 1, ae_v_len(0,nout-1));
34341  oobcntbuf.ptr.p_int[i] = oobcntbuf.ptr.p_int[i]+1;
34342  }
34343  }
34344  }
34345 
34346  /*
34347  * OOB estimates
34348  */
34349  if( mlpissoftmax(&ensemble->network, _state) )
34350  {
34351  dserrallocate(nout, &dsbuf, _state);
34352  }
34353  else
34354  {
34355  dserrallocate(-nout, &dsbuf, _state);
34356  }
34357  for(i=0; i<=npoints-1; i++)
34358  {
34359  if( oobcntbuf.ptr.p_int[i]!=0 )
34360  {
34361  v = (double)1/(double)oobcntbuf.ptr.p_int[i];
34362  ae_v_moved(&y.ptr.p_double[0], 1, &oobbuf.ptr.pp_double[i][0], 1, ae_v_len(0,nout-1), v);
34363  if( mlpissoftmax(&ensemble->network, _state) )
34364  {
34365  dy.ptr.p_double[0] = xy->ptr.pp_double[i][nin];
34366  }
34367  else
34368  {
34369  ae_v_moved(&dy.ptr.p_double[0], 1, &xy->ptr.pp_double[i][nin], 1, ae_v_len(0,nout-1), v);
34370  }
34371  dserraccumulate(&dsbuf, &y, &dy, _state);
34372  }
34373  }
34374  dserrfinish(&dsbuf, _state);
34375  ooberrors->relclserror = dsbuf.ptr.p_double[0];
34376  ooberrors->avgce = dsbuf.ptr.p_double[1];
34377  ooberrors->rmserror = dsbuf.ptr.p_double[2];
34378  ooberrors->avgerror = dsbuf.ptr.p_double[3];
34379  ooberrors->avgrelerror = dsbuf.ptr.p_double[4];
34380  ae_frame_leave(_state);
34381 }
34382 
34383 
34384 /*************************************************************************
34385 This function initializes temporaries needed for training session.
34386 
34387 
34388  -- ALGLIB --
34389  Copyright 01.07.2013 by Bochkanov Sergey
34390 *************************************************************************/
34391 static void mlptrain_initmlptrnsession(multilayerperceptron* networktrained,
34392  ae_bool randomizenetwork,
34393  mlptrainer* trainer,
34394  smlptrnsession* session,
34395  ae_state *_state)
34396 {
34397  ae_frame _frame_block;
34398  ae_int_t nin;
34399  ae_int_t nout;
34400  ae_int_t wcount;
34401  ae_int_t pcount;
34402  ae_vector dummysubset;
34403 
34404  ae_frame_make(_state, &_frame_block);
34405  ae_vector_init(&dummysubset, 0, DT_INT, _state, ae_true);
34406 
34407 
34408  /*
34409  * Prepare network:
34410  * * copy input network to Session.Network
34411  * * re-initialize preprocessor and weights if RandomizeNetwork=True
34412  */
34413  mlpcopy(networktrained, &session->network, _state);
34414  if( randomizenetwork )
34415  {
34416  ae_assert(trainer->datatype==0||trainer->datatype==1, "InitTemporaries: unexpected Trainer.DataType", _state);
34417  if( trainer->datatype==0 )
34418  {
34419  mlpinitpreprocessorsubset(&session->network, &trainer->densexy, trainer->npoints, &dummysubset, -1, _state);
34420  }
34421  if( trainer->datatype==1 )
34422  {
34423  mlpinitpreprocessorsparsesubset(&session->network, &trainer->sparsexy, trainer->npoints, &dummysubset, -1, _state);
34424  }
34425  mlprandomize(&session->network, _state);
34426  session->randomizenetwork = ae_true;
34427  }
34428  else
34429  {
34430  session->randomizenetwork = ae_false;
34431  }
34432 
34433  /*
34434  * Determine network geometry and initialize optimizer
34435  */
34436  mlpproperties(&session->network, &nin, &nout, &wcount, _state);
34437  minlbfgscreate(wcount, ae_minint(wcount, trainer->lbfgsfactor, _state), &session->network.weights, &session->optimizer, _state);
34438  minlbfgssetxrep(&session->optimizer, ae_true, _state);
34439 
34440  /*
34441  * Create buffers
34442  */
34443  ae_vector_set_length(&session->wbuf0, wcount, _state);
34444  ae_vector_set_length(&session->wbuf1, wcount, _state);
34445 
34446  /*
34447  * Initialize session result
34448  */
34449  mlpexporttunableparameters(&session->network, &session->bestparameters, &pcount, _state);
34450  session->bestrmserror = ae_maxrealnumber;
34451  ae_frame_leave(_state);
34452 }
34453 
34454 
34455 /*************************************************************************
34456 This function initializes temporaries needed for training session.
34457 
34458 *************************************************************************/
34459 static void mlptrain_initmlptrnsessions(multilayerperceptron* networktrained,
34460  ae_bool randomizenetwork,
34461  mlptrainer* trainer,
34462  ae_shared_pool* sessions,
34463  ae_state *_state)
34464 {
34465  ae_frame _frame_block;
34466  ae_vector dummysubset;
34467  smlptrnsession t;
34468  smlptrnsession *p;
34469  ae_smart_ptr _p;
34470 
34471  ae_frame_make(_state, &_frame_block);
34472  ae_vector_init(&dummysubset, 0, DT_INT, _state, ae_true);
34473  _smlptrnsession_init(&t, _state, ae_true);
34474  ae_smart_ptr_init(&_p, (void**)&p, _state, ae_true);
34475 
34476  if( ae_shared_pool_is_initialized(sessions) )
34477  {
34478 
34479  /*
34480  * Pool was already initialized.
34481  * Clear sessions stored in the pool.
34482  */
34483  ae_shared_pool_first_recycled(sessions, &_p, _state);
34484  while(p!=NULL)
34485  {
34486  ae_assert(mlpsamearchitecture(&p->network, networktrained, _state), "InitMLPTrnSessions: internal consistency error", _state);
34487  p->bestrmserror = ae_maxrealnumber;
34488  ae_shared_pool_next_recycled(sessions, &_p, _state);
34489  }
34490  }
34491  else
34492  {
34493 
34494  /*
34495  * Prepare session and seed pool
34496  */
34497  mlptrain_initmlptrnsession(networktrained, randomizenetwork, trainer, &t, _state);
34498  ae_shared_pool_set_seed(sessions, &t, sizeof(t), _smlptrnsession_init, _smlptrnsession_init_copy, _smlptrnsession_destroy, _state);
34499  }
34500  ae_frame_leave(_state);
34501 }
34502 
34503 
34504 /*************************************************************************
34505 This function initializes temporaries needed for ensemble training.
34506 
34507 *************************************************************************/
34508 static void mlptrain_initmlpetrnsession(multilayerperceptron* individualnetwork,
34509  mlptrainer* trainer,
34510  mlpetrnsession* session,
34511  ae_state *_state)
34512 {
34513  ae_frame _frame_block;
34514  ae_vector dummysubset;
34515 
34516  ae_frame_make(_state, &_frame_block);
34517  ae_vector_init(&dummysubset, 0, DT_INT, _state, ae_true);
34518 
34519 
34520  /*
34521  * Prepare network:
34522  * * copy input network to Session.Network
34523  * * re-initialize preprocessor and weights if RandomizeNetwork=True
34524  */
34525  mlpcopy(individualnetwork, &session->network, _state);
34526  mlptrain_initmlptrnsessions(individualnetwork, ae_true, trainer, &session->mlpsessions, _state);
34527  ivectorsetlengthatleast(&session->trnsubset, trainer->npoints, _state);
34528  ivectorsetlengthatleast(&session->valsubset, trainer->npoints, _state);
34529  ae_frame_leave(_state);
34530 }
34531 
34532 
34533 /*************************************************************************
34534 This function initializes temporaries needed for training session.
34535 
34536 *************************************************************************/
34537 static void mlptrain_initmlpetrnsessions(multilayerperceptron* individualnetwork,
34538  mlptrainer* trainer,
34539  ae_shared_pool* sessions,
34540  ae_state *_state)
34541 {
34542  ae_frame _frame_block;
34543  mlpetrnsession t;
34544 
34545  ae_frame_make(_state, &_frame_block);
34546  _mlpetrnsession_init(&t, _state, ae_true);
34547 
34548  if( !ae_shared_pool_is_initialized(sessions) )
34549  {
34550  mlptrain_initmlpetrnsession(individualnetwork, trainer, &t, _state);
34551  ae_shared_pool_set_seed(sessions, &t, sizeof(t), _mlpetrnsession_init, _mlpetrnsession_init_copy, _mlpetrnsession_destroy, _state);
34552  }
34553  ae_frame_leave(_state);
34554 }
34555 
34556 
34557 ae_bool _mlpreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
34558 {
34559  mlpreport *p = (mlpreport*)_p;
34560  ae_touch_ptr((void*)p);
34561  return ae_true;
34562 }
34563 
34564 
34565 ae_bool _mlpreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
34566 {
34567  mlpreport *dst = (mlpreport*)_dst;
34568  mlpreport *src = (mlpreport*)_src;
34569  dst->relclserror = src->relclserror;
34570  dst->avgce = src->avgce;
34571  dst->rmserror = src->rmserror;
34572  dst->avgerror = src->avgerror;
34573  dst->avgrelerror = src->avgrelerror;
34574  dst->ngrad = src->ngrad;
34575  dst->nhess = src->nhess;
34576  dst->ncholesky = src->ncholesky;
34577  return ae_true;
34578 }
34579 
34580 
34581 void _mlpreport_clear(void* _p)
34582 {
34583  mlpreport *p = (mlpreport*)_p;
34584  ae_touch_ptr((void*)p);
34585 }
34586 
34587 
34588 void _mlpreport_destroy(void* _p)
34589 {
34590  mlpreport *p = (mlpreport*)_p;
34591  ae_touch_ptr((void*)p);
34592 }
34593 
34594 
34595 ae_bool _mlpcvreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
34596 {
34597  mlpcvreport *p = (mlpcvreport*)_p;
34598  ae_touch_ptr((void*)p);
34599  return ae_true;
34600 }
34601 
34602 
34603 ae_bool _mlpcvreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
34604 {
34605  mlpcvreport *dst = (mlpcvreport*)_dst;
34606  mlpcvreport *src = (mlpcvreport*)_src;
34607  dst->relclserror = src->relclserror;
34608  dst->avgce = src->avgce;
34609  dst->rmserror = src->rmserror;
34610  dst->avgerror = src->avgerror;
34611  dst->avgrelerror = src->avgrelerror;
34612  return ae_true;
34613 }
34614 
34615 
34616 void _mlpcvreport_clear(void* _p)
34617 {
34618  mlpcvreport *p = (mlpcvreport*)_p;
34619  ae_touch_ptr((void*)p);
34620 }
34621 
34622 
34623 void _mlpcvreport_destroy(void* _p)
34624 {
34625  mlpcvreport *p = (mlpcvreport*)_p;
34626  ae_touch_ptr((void*)p);
34627 }
34628 
34629 
34630 ae_bool _smlptrnsession_init(void* _p, ae_state *_state, ae_bool make_automatic)
34631 {
34632  smlptrnsession *p = (smlptrnsession*)_p;
34633  ae_touch_ptr((void*)p);
34634  if( !ae_vector_init(&p->bestparameters, 0, DT_REAL, _state, make_automatic) )
34635  return ae_false;
34636  if( !_multilayerperceptron_init(&p->network, _state, make_automatic) )
34637  return ae_false;
34638  if( !_minlbfgsstate_init(&p->optimizer, _state, make_automatic) )
34639  return ae_false;
34640  if( !_minlbfgsreport_init(&p->optimizerrep, _state, make_automatic) )
34641  return ae_false;
34642  if( !ae_vector_init(&p->wbuf0, 0, DT_REAL, _state, make_automatic) )
34643  return ae_false;
34644  if( !ae_vector_init(&p->wbuf1, 0, DT_REAL, _state, make_automatic) )
34645  return ae_false;
34646  if( !ae_vector_init(&p->allminibatches, 0, DT_INT, _state, make_automatic) )
34647  return ae_false;
34648  if( !ae_vector_init(&p->currentminibatch, 0, DT_INT, _state, make_automatic) )
34649  return ae_false;
34650  if( !_rcommstate_init(&p->rstate, _state, make_automatic) )
34651  return ae_false;
34652  if( !_hqrndstate_init(&p->generator, _state, make_automatic) )
34653  return ae_false;
34654  return ae_true;
34655 }
34656 
34657 
34658 ae_bool _smlptrnsession_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
34659 {
34660  smlptrnsession *dst = (smlptrnsession*)_dst;
34661  smlptrnsession *src = (smlptrnsession*)_src;
34662  if( !ae_vector_init_copy(&dst->bestparameters, &src->bestparameters, _state, make_automatic) )
34663  return ae_false;
34664  dst->bestrmserror = src->bestrmserror;
34665  dst->randomizenetwork = src->randomizenetwork;
34666  if( !_multilayerperceptron_init_copy(&dst->network, &src->network, _state, make_automatic) )
34667  return ae_false;
34668  if( !_minlbfgsstate_init_copy(&dst->optimizer, &src->optimizer, _state, make_automatic) )
34669  return ae_false;
34670  if( !_minlbfgsreport_init_copy(&dst->optimizerrep, &src->optimizerrep, _state, make_automatic) )
34671  return ae_false;
34672  if( !ae_vector_init_copy(&dst->wbuf0, &src->wbuf0, _state, make_automatic) )
34673  return ae_false;
34674  if( !ae_vector_init_copy(&dst->wbuf1, &src->wbuf1, _state, make_automatic) )
34675  return ae_false;
34676  if( !ae_vector_init_copy(&dst->allminibatches, &src->allminibatches, _state, make_automatic) )
34677  return ae_false;
34678  if( !ae_vector_init_copy(&dst->currentminibatch, &src->currentminibatch, _state, make_automatic) )
34679  return ae_false;
34680  if( !_rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic) )
34681  return ae_false;
34682  dst->algoused = src->algoused;
34683  dst->minibatchsize = src->minibatchsize;
34684  if( !_hqrndstate_init_copy(&dst->generator, &src->generator, _state, make_automatic) )
34685  return ae_false;
34686  return ae_true;
34687 }
34688 
34689 
34690 void _smlptrnsession_clear(void* _p)
34691 {
34692  smlptrnsession *p = (smlptrnsession*)_p;
34693  ae_touch_ptr((void*)p);
34694  ae_vector_clear(&p->bestparameters);
34695  _multilayerperceptron_clear(&p->network);
34696  _minlbfgsstate_clear(&p->optimizer);
34697  _minlbfgsreport_clear(&p->optimizerrep);
34698  ae_vector_clear(&p->wbuf0);
34699  ae_vector_clear(&p->wbuf1);
34700  ae_vector_clear(&p->allminibatches);
34701  ae_vector_clear(&p->currentminibatch);
34702  _rcommstate_clear(&p->rstate);
34703  _hqrndstate_clear(&p->generator);
34704 }
34705 
34706 
34707 void _smlptrnsession_destroy(void* _p)
34708 {
34709  smlptrnsession *p = (smlptrnsession*)_p;
34710  ae_touch_ptr((void*)p);
34711  ae_vector_destroy(&p->bestparameters);
34712  _multilayerperceptron_destroy(&p->network);
34713  _minlbfgsstate_destroy(&p->optimizer);
34714  _minlbfgsreport_destroy(&p->optimizerrep);
34715  ae_vector_destroy(&p->wbuf0);
34716  ae_vector_destroy(&p->wbuf1);
34717  ae_vector_destroy(&p->allminibatches);
34718  ae_vector_destroy(&p->currentminibatch);
34719  _rcommstate_destroy(&p->rstate);
34720  _hqrndstate_destroy(&p->generator);
34721 }
34722 
34723 
34724 ae_bool _mlpetrnsession_init(void* _p, ae_state *_state, ae_bool make_automatic)
34725 {
34726  mlpetrnsession *p = (mlpetrnsession*)_p;
34727  ae_touch_ptr((void*)p);
34728  if( !ae_vector_init(&p->trnsubset, 0, DT_INT, _state, make_automatic) )
34729  return ae_false;
34730  if( !ae_vector_init(&p->valsubset, 0, DT_INT, _state, make_automatic) )
34731  return ae_false;
34732  if( !ae_shared_pool_init(&p->mlpsessions, _state, make_automatic) )
34733  return ae_false;
34734  if( !_mlpreport_init(&p->mlprep, _state, make_automatic) )
34735  return ae_false;
34736  if( !_multilayerperceptron_init(&p->network, _state, make_automatic) )
34737  return ae_false;
34738  return ae_true;
34739 }
34740 
34741 
34742 ae_bool _mlpetrnsession_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
34743 {
34744  mlpetrnsession *dst = (mlpetrnsession*)_dst;
34745  mlpetrnsession *src = (mlpetrnsession*)_src;
34746  if( !ae_vector_init_copy(&dst->trnsubset, &src->trnsubset, _state, make_automatic) )
34747  return ae_false;
34748  if( !ae_vector_init_copy(&dst->valsubset, &src->valsubset, _state, make_automatic) )
34749  return ae_false;
34750  if( !ae_shared_pool_init_copy(&dst->mlpsessions, &src->mlpsessions, _state, make_automatic) )
34751  return ae_false;
34752  if( !_mlpreport_init_copy(&dst->mlprep, &src->mlprep, _state, make_automatic) )
34753  return ae_false;
34754  if( !_multilayerperceptron_init_copy(&dst->network, &src->network, _state, make_automatic) )
34755  return ae_false;
34756  return ae_true;
34757 }
34758 
34759 
34760 void _mlpetrnsession_clear(void* _p)
34761 {
34762  mlpetrnsession *p = (mlpetrnsession*)_p;
34763  ae_touch_ptr((void*)p);
34764  ae_vector_clear(&p->trnsubset);
34765  ae_vector_clear(&p->valsubset);
34766  ae_shared_pool_clear(&p->mlpsessions);
34767  _mlpreport_clear(&p->mlprep);
34768  _multilayerperceptron_clear(&p->network);
34769 }
34770 
34771 
34772 void _mlpetrnsession_destroy(void* _p)
34773 {
34774  mlpetrnsession *p = (mlpetrnsession*)_p;
34775  ae_touch_ptr((void*)p);
34776  ae_vector_destroy(&p->trnsubset);
34777  ae_vector_destroy(&p->valsubset);
34778  ae_shared_pool_destroy(&p->mlpsessions);
34779  _mlpreport_destroy(&p->mlprep);
34780  _multilayerperceptron_destroy(&p->network);
34781 }
34782 
34783 
34784 ae_bool _mlptrainer_init(void* _p, ae_state *_state, ae_bool make_automatic)
34785 {
34786  mlptrainer *p = (mlptrainer*)_p;
34787  ae_touch_ptr((void*)p);
34788  if( !ae_matrix_init(&p->densexy, 0, 0, DT_REAL, _state, make_automatic) )
34789  return ae_false;
34790  if( !_sparsematrix_init(&p->sparsexy, _state, make_automatic) )
34791  return ae_false;
34792  if( !_smlptrnsession_init(&p->session, _state, make_automatic) )
34793  return ae_false;
34794  if( !ae_vector_init(&p->subset, 0, DT_INT, _state, make_automatic) )
34795  return ae_false;
34796  if( !ae_vector_init(&p->valsubset, 0, DT_INT, _state, make_automatic) )
34797  return ae_false;
34798  return ae_true;
34799 }
34800 
34801 
34802 ae_bool _mlptrainer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
34803 {
34804  mlptrainer *dst = (mlptrainer*)_dst;
34805  mlptrainer *src = (mlptrainer*)_src;
34806  dst->nin = src->nin;
34807  dst->nout = src->nout;
34808  dst->rcpar = src->rcpar;
34809  dst->lbfgsfactor = src->lbfgsfactor;
34810  dst->decay = src->decay;
34811  dst->wstep = src->wstep;
34812  dst->maxits = src->maxits;
34813  dst->datatype = src->datatype;
34814  dst->npoints = src->npoints;
34815  if( !ae_matrix_init_copy(&dst->densexy, &src->densexy, _state, make_automatic) )
34816  return ae_false;
34817  if( !_sparsematrix_init_copy(&dst->sparsexy, &src->sparsexy, _state, make_automatic) )
34818  return ae_false;
34819  if( !_smlptrnsession_init_copy(&dst->session, &src->session, _state, make_automatic) )
34820  return ae_false;
34821  dst->ngradbatch = src->ngradbatch;
34822  if( !ae_vector_init_copy(&dst->subset, &src->subset, _state, make_automatic) )
34823  return ae_false;
34824  dst->subsetsize = src->subsetsize;
34825  if( !ae_vector_init_copy(&dst->valsubset, &src->valsubset, _state, make_automatic) )
34826  return ae_false;
34827  dst->valsubsetsize = src->valsubsetsize;
34828  dst->algokind = src->algokind;
34829  dst->minibatchsize = src->minibatchsize;
34830  return ae_true;
34831 }
34832 
34833 
34834 void _mlptrainer_clear(void* _p)
34835 {
34836  mlptrainer *p = (mlptrainer*)_p;
34837  ae_touch_ptr((void*)p);
34838  ae_matrix_clear(&p->densexy);
34839  _sparsematrix_clear(&p->sparsexy);
34840  _smlptrnsession_clear(&p->session);
34841  ae_vector_clear(&p->subset);
34842  ae_vector_clear(&p->valsubset);
34843 }
34844 
34845 
34846 void _mlptrainer_destroy(void* _p)
34847 {
34848  mlptrainer *p = (mlptrainer*)_p;
34849  ae_touch_ptr((void*)p);
34850  ae_matrix_destroy(&p->densexy);
34851  _sparsematrix_destroy(&p->sparsexy);
34852  _smlptrnsession_destroy(&p->session);
34853  ae_vector_destroy(&p->subset);
34854  ae_vector_destroy(&p->valsubset);
34855 }
34856 
34857 
34858 ae_bool _mlpparallelizationcv_init(void* _p, ae_state *_state, ae_bool make_automatic)
34859 {
34860  mlpparallelizationcv *p = (mlpparallelizationcv*)_p;
34861  ae_touch_ptr((void*)p);
34862  if( !_multilayerperceptron_init(&p->network, _state, make_automatic) )
34863  return ae_false;
34864  if( !_mlpreport_init(&p->rep, _state, make_automatic) )
34865  return ae_false;
34866  if( !ae_vector_init(&p->subset, 0, DT_INT, _state, make_automatic) )
34867  return ae_false;
34868  if( !ae_vector_init(&p->xyrow, 0, DT_REAL, _state, make_automatic) )
34869  return ae_false;
34870  if( !ae_vector_init(&p->y, 0, DT_REAL, _state, make_automatic) )
34871  return ae_false;
34872  if( !ae_shared_pool_init(&p->trnpool, _state, make_automatic) )
34873  return ae_false;
34874  return ae_true;
34875 }
34876 
34877 
34878 ae_bool _mlpparallelizationcv_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
34879 {
34880  mlpparallelizationcv *dst = (mlpparallelizationcv*)_dst;
34881  mlpparallelizationcv *src = (mlpparallelizationcv*)_src;
34882  if( !_multilayerperceptron_init_copy(&dst->network, &src->network, _state, make_automatic) )
34883  return ae_false;
34884  if( !_mlpreport_init_copy(&dst->rep, &src->rep, _state, make_automatic) )
34885  return ae_false;
34886  if( !ae_vector_init_copy(&dst->subset, &src->subset, _state, make_automatic) )
34887  return ae_false;
34888  dst->subsetsize = src->subsetsize;
34889  if( !ae_vector_init_copy(&dst->xyrow, &src->xyrow, _state, make_automatic) )
34890  return ae_false;
34891  if( !ae_vector_init_copy(&dst->y, &src->y, _state, make_automatic) )
34892  return ae_false;
34893  dst->ngrad = src->ngrad;
34894  if( !ae_shared_pool_init_copy(&dst->trnpool, &src->trnpool, _state, make_automatic) )
34895  return ae_false;
34896  return ae_true;
34897 }
34898 
34899 
34900 void _mlpparallelizationcv_clear(void* _p)
34901 {
34902  mlpparallelizationcv *p = (mlpparallelizationcv*)_p;
34903  ae_touch_ptr((void*)p);
34904  _multilayerperceptron_clear(&p->network);
34905  _mlpreport_clear(&p->rep);
34906  ae_vector_clear(&p->subset);
34907  ae_vector_clear(&p->xyrow);
34908  ae_vector_clear(&p->y);
34909  ae_shared_pool_clear(&p->trnpool);
34910 }
34911 
34912 
34913 void _mlpparallelizationcv_destroy(void* _p)
34914 {
34915  mlpparallelizationcv *p = (mlpparallelizationcv*)_p;
34916  ae_touch_ptr((void*)p);
34917  _multilayerperceptron_destroy(&p->network);
34918  _mlpreport_destroy(&p->rep);
34919  ae_vector_destroy(&p->subset);
34920  ae_vector_destroy(&p->xyrow);
34921  ae_vector_destroy(&p->y);
34922  ae_shared_pool_destroy(&p->trnpool);
34923 }
34924 
34925 
34926 
34927 
34928 /*************************************************************************
34929 Principal components analysis
34930 
34931 Subroutine builds orthogonal basis where first axis corresponds to
34932 direction with maximum variance, second axis maximizes variance in subspace
34933 orthogonal to first axis and so on.
34934 
34935 It should be noted that, unlike LDA, PCA does not use class labels.
34936 
34937 INPUT PARAMETERS:
34938  X - dataset, array[0..NPoints-1,0..NVars-1].
34939  matrix contains ONLY INDEPENDENT VARIABLES.
34940  NPoints - dataset size, NPoints>=0
34941  NVars - number of independent variables, NVars>=1
34942 
34943 ÂÛÕÎÄÍÛÅ ÏÀÐÀÌÅÒÐÛ:
34944  Info - return code:
34945  * -4, if SVD subroutine haven't converged
34946  * -1, if wrong parameters has been passed (NPoints<0,
34947  NVars<1)
34948  * 1, if task is solved
34949  S2 - array[0..NVars-1]. variance values corresponding
34950  to basis vectors.
34951  V - array[0..NVars-1,0..NVars-1]
34952  matrix, whose columns store basis vectors.
34953 
34954  -- ALGLIB --
34955  Copyright 25.08.2008 by Bochkanov Sergey
34956 *************************************************************************/
34957 void pcabuildbasis(/* Real */ ae_matrix* x,
34958  ae_int_t npoints,
34959  ae_int_t nvars,
34960  ae_int_t* info,
34961  /* Real */ ae_vector* s2,
34962  /* Real */ ae_matrix* v,
34963  ae_state *_state)
34964 {
34965  ae_frame _frame_block;
34966  ae_matrix a;
34967  ae_matrix u;
34968  ae_matrix vt;
34969  ae_vector m;
34970  ae_vector t;
34971  ae_int_t i;
34972  ae_int_t j;
34973  double mean;
34974  double variance;
34975  double skewness;
34976  double kurtosis;
34977 
34978  ae_frame_make(_state, &_frame_block);
34979  *info = 0;
34980  ae_vector_clear(s2);
34981  ae_matrix_clear(v);
34982  ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
34983  ae_matrix_init(&u, 0, 0, DT_REAL, _state, ae_true);
34984  ae_matrix_init(&vt, 0, 0, DT_REAL, _state, ae_true);
34985  ae_vector_init(&m, 0, DT_REAL, _state, ae_true);
34986  ae_vector_init(&t, 0, DT_REAL, _state, ae_true);
34987 
34988 
34989  /*
34990  * Check input data
34991  */
34992  if( npoints<0||nvars<1 )
34993  {
34994  *info = -1;
34995  ae_frame_leave(_state);
34996  return;
34997  }
34998  *info = 1;
34999 
35000  /*
35001  * Special case: NPoints=0
35002  */
35003  if( npoints==0 )
35004  {
35005  ae_vector_set_length(s2, nvars-1+1, _state);
35006  ae_matrix_set_length(v, nvars-1+1, nvars-1+1, _state);
35007  for(i=0; i<=nvars-1; i++)
35008  {
35009  s2->ptr.p_double[i] = 0;
35010  }
35011  for(i=0; i<=nvars-1; i++)
35012  {
35013  for(j=0; j<=nvars-1; j++)
35014  {
35015  if( i==j )
35016  {
35017  v->ptr.pp_double[i][j] = 1;
35018  }
35019  else
35020  {
35021  v->ptr.pp_double[i][j] = 0;
35022  }
35023  }
35024  }
35025  ae_frame_leave(_state);
35026  return;
35027  }
35028 
35029  /*
35030  * Calculate means
35031  */
35032  ae_vector_set_length(&m, nvars-1+1, _state);
35033  ae_vector_set_length(&t, npoints-1+1, _state);
35034  for(j=0; j<=nvars-1; j++)
35035  {
35036  ae_v_move(&t.ptr.p_double[0], 1, &x->ptr.pp_double[0][j], x->stride, ae_v_len(0,npoints-1));
35037  samplemoments(&t, npoints, &mean, &variance, &skewness, &kurtosis, _state);
35038  m.ptr.p_double[j] = mean;
35039  }
35040 
35041  /*
35042  * Center, apply SVD, prepare output
35043  */
35044  ae_matrix_set_length(&a, ae_maxint(npoints, nvars, _state)-1+1, nvars-1+1, _state);
35045  for(i=0; i<=npoints-1; i++)
35046  {
35047  ae_v_move(&a.ptr.pp_double[i][0], 1, &x->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
35048  ae_v_sub(&a.ptr.pp_double[i][0], 1, &m.ptr.p_double[0], 1, ae_v_len(0,nvars-1));
35049  }
35050  for(i=npoints; i<=nvars-1; i++)
35051  {
35052  for(j=0; j<=nvars-1; j++)
35053  {
35054  a.ptr.pp_double[i][j] = 0;
35055  }
35056  }
35057  if( !rmatrixsvd(&a, ae_maxint(npoints, nvars, _state), nvars, 0, 1, 2, s2, &u, &vt, _state) )
35058  {
35059  *info = -4;
35060  ae_frame_leave(_state);
35061  return;
35062  }
35063  if( npoints!=1 )
35064  {
35065  for(i=0; i<=nvars-1; i++)
35066  {
35067  s2->ptr.p_double[i] = ae_sqr(s2->ptr.p_double[i], _state)/(npoints-1);
35068  }
35069  }
35070  ae_matrix_set_length(v, nvars-1+1, nvars-1+1, _state);
35071  copyandtranspose(&vt, 0, nvars-1, 0, nvars-1, v, 0, nvars-1, 0, nvars-1, _state);
35072  ae_frame_leave(_state);
35073 }
35074 
35075 
35076 
35077 }
35078 
void mlprandomize(multilayerperceptron *network, ae_state *_state)
void mlpgradnbatch(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize, double &e, real_1d_array &grad)
real_1d_array mergedist
Definition: dataanalysis.h:484
alglib_impl::multilayerperceptron * c_ptr()
void _mlpcvreport_clear(void *_p)
ae_int_t & ngrad
Definition: dataanalysis.h:947
struct alglib_impl::ae_state ae_state
void mcpdcreateentryexit(const ae_int_t n, const ae_int_t entrystate, const ae_int_t exitstate, mcpdstate &s)
ae_int_t mlpgetlayerscount(const multilayerperceptron &network)
void mlpcreatetrainer(const ae_int_t nin, const ae_int_t nout, mlptrainer &s)
void mlpecreatec2(ae_int_t nin, ae_int_t nhid1, ae_int_t nhid2, ae_int_t nout, ae_int_t ensemblesize, mlpensemble *ensemble, ae_state *_state)
void mlpsetdataset(const mlptrainer &s, const real_2d_array &xy, const ae_int_t npoints)
void mlpcreatetrainercls(const ae_int_t nin, const ae_int_t nclasses, mlptrainer &s)
void dserrfinish(ae_vector *buf, ae_state *_state)
void mlpeunserialize(std::string &s_in, mlpensemble &obj)
void _pexec_clusterizerrunahc(clusterizerstate *s, ahcreport *rep, ae_state *_state)
ae_bool ae_fp_greater_eq(double v1, double v2)
Definition: ap.cpp:1351
double smp_mlprmserrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
ae_bool _mlpreport_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
double mnlrmserror(const logitmodel &lm, const real_2d_array &xy, const ae_int_t npoints)
double & avgrelerror
Definition: dataanalysis.h:946
double mlperrorsparsesubset(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize)
void mlpkfoldcvlm(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, const ae_int_t foldscount, ae_int_t &info, mlpreport &rep, mlpcvreport &cvrep)
alglib_impl::logitmodel * c_ptr()
void ae_serializer_init(ae_serializer *serializer)
Definition: ap.cpp:3393
alglib_impl::multilayerperceptron * p_struct
Definition: dataanalysis.h:743
void mlpecreate1(ae_int_t nin, ae_int_t nhid, ae_int_t nout, ae_int_t ensemblesize, mlpensemble *ensemble, ae_state *_state)
void _cvreport_clear(void *_p)
void mlpecreate0(const ae_int_t nin, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble)
double mlperrorsubset(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize)
void mlpcreateb0(const ae_int_t nin, const ae_int_t nout, const double b, const double d, multilayerperceptron &network)
void smp_mlptrainnetwork(const mlptrainer &s, const multilayerperceptron &network, const ae_int_t nrestarts, mlpreport &rep)
void rmatrixsyrk(const ae_int_t n, const ae_int_t k, const double alpha, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t optypea, const double beta, const real_2d_array &c, const ae_int_t ic, const ae_int_t jc, const bool isupper)
Definition: linalg.cpp:518
void mlpeproperties(const mlpensemble &ensemble, ae_int_t &nin, ae_int_t &nout)
void dfprocessi(decisionforest *df, ae_vector *x, ae_vector *y, ae_state *_state)
alglib_impl::mlpcvreport * p_struct
Definition: dataanalysis.h:967
double mlpavgrelerror(multilayerperceptron *network, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
ae_bool _linearmodel_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void mlpserialize(ae_serializer *s, multilayerperceptron *network, ae_state *_state)
double mlperror(multilayerperceptron *network, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
void mlpecreateb1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const double b, const double d, const ae_int_t ensemblesize, mlpensemble &ensemble)
void mlpecreatefromnetwork(const multilayerperceptron &network, const ae_int_t ensemblesize, mlpensemble &ensemble)
void mlpcreatec1(ae_int_t nin, ae_int_t nhid, ae_int_t nout, multilayerperceptron *network, ae_state *_state)
ae_int_t cols
Definition: ap.h:445
void mlpealloc(ae_serializer *s, mlpensemble *ensemble, ae_state *_state)
alglib_impl::mcpdreport * p_struct
Definition: dataanalysis.h:866
void mcpdcreate(ae_int_t n, mcpdstate *s, ae_state *_state)
void rankdatacentered(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nfeatures)
ae_int_t _pexec_mlpclserror(multilayerperceptron *network, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
void dsoptimalsplit2fast(real_1d_array &a, integer_1d_array &c, integer_1d_array &tiesbuf, integer_1d_array &cntbuf, real_1d_array &bufr, integer_1d_array &bufi, const ae_int_t n, const ae_int_t nc, const double alpha, ae_int_t &info, double &threshold, double &rms, double &cvrms)
void mnltrainh(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nclasses, ae_int_t &info, logitmodel &lm, mnlreport &rep)
ae_int_t & ncholesky
Definition: dataanalysis.h:949
ae_bool _lrreport_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void smp_mlpgradbatchsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t ssize, double &e, real_1d_array &grad)
double rms(const MultidimArray< T > &x, const MultidimArray< T > &y, const MultidimArray< int > *mask=nullptr, MultidimArray< double > *Contributions=nullptr)
Definition: filters.h:725
void mlpecreatec0(ae_int_t nin, ae_int_t nout, ae_int_t ensemblesize, mlpensemble *ensemble, ae_state *_state)
void lrbuildzs(ae_matrix *xy, ae_vector *s, ae_int_t npoints, ae_int_t nvars, ae_int_t *info, linearmodel *lm, lrreport *ar, ae_state *_state)
ae_bool _logitmodel_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
double smp_mlpavgerror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
void mlpeserialize(mlpensemble &obj, std::string &s_out)
_mlptrainer_owner & operator=(const _mlptrainer_owner &rhs)
double & cvavgerror
Definition: dataanalysis.h:678
double _pexec_mlpavgrelerrorsparse(multilayerperceptron *network, sparsematrix *xy, ae_int_t npoints, ae_state *_state)
void mlpstarttraining(mlptrainer *s, multilayerperceptron *network, ae_bool randomstart, ae_state *_state)
ae_int_t ae_serializer_get_alloc_size(ae_serializer *serializer)
Definition: ap.cpp:3416
void smp_clusterizergetdistances(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nfeatures, const ae_int_t disttype, real_2d_array &d)
void ae_serializer_sstart_str(ae_serializer *serializer, std::string *buf)
Definition: ap.cpp:3447
void smp_mlpkfoldcv(const mlptrainer &s, const multilayerperceptron &network, const ae_int_t nrestarts, const ae_int_t foldscount, mlpreport &rep)
ae_bool _mcpdreport_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
int * mmax
void lrpack(ae_vector *v, ae_int_t nvars, linearmodel *lm, ae_state *_state)
_decisionforest_owner & operator=(const _decisionforest_owner &rhs)
double lravgrelerror(const linearmodel &lm, const real_2d_array &xy, const ae_int_t npoints)
double dfavgerror(const decisionforest &df, const real_2d_array &xy, const ae_int_t npoints)
void mnlprocess(const logitmodel &lm, const real_1d_array &x, real_1d_array &y)
bool mlpeissoftmax(const mlpensemble &ensemble)
void mlpcreatec2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, multilayerperceptron &network)
integer_1d_array cvdefects
Definition: dataanalysis.h:681
double _pexec_mlpavgerrorsparse(multilayerperceptron *network, sparsematrix *xy, ae_int_t npoints, ae_state *_state)
alglib_impl::mlpensemble * c_ptr()
void _pexec_mlpgradbatchsparse(multilayerperceptron *network, sparsematrix *xy, ae_int_t ssize, double *e, ae_vector *grad, ae_state *_state)
ae_bool _dfreport_init(void *_p, ae_state *_state, ae_bool make_automatic)
alglib_impl::logitmodel * p_struct
Definition: dataanalysis.h:768
void mlptrainlbfgs(multilayerperceptron *network, ae_matrix *xy, ae_int_t npoints, double decay, ae_int_t restarts, double wstep, ae_int_t maxits, ae_int_t *info, mlpreport *rep, ae_state *_state)
void mlpeprocessi(const mlpensemble &ensemble, const real_1d_array &x, real_1d_array &y)
void filterlrma(ae_vector *x, ae_int_t n, ae_int_t k, ae_state *_state)
double ae_fabs(double x, ae_state *state)
Definition: ap.cpp:1520
double smp_mlprmserror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
_clusterizerstate_owner & operator=(const _clusterizerstate_owner &rhs)
integer_2d_array pz
Definition: dataanalysis.h:482
double dsgetmeanmindistance(ae_matrix *xy, ae_int_t npoints, ae_int_t nvars, ae_state *_state)
void mlpgradbatchsubset(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t setsize, const integer_1d_array &idx, const ae_int_t subsetsize, double &e, real_1d_array &grad)
void dssplitk(ae_vector *a, ae_vector *c, ae_int_t n, ae_int_t nc, ae_int_t kmax, ae_int_t *info, ae_vector *thresholds, ae_int_t *ni, double *cve, ae_state *_state)
void mlpgradnbatch(multilayerperceptron *network, ae_matrix *xy, ae_int_t ssize, double *e, ae_vector *grad, ae_state *_state)
doublereal * c
doublereal * g
double mlpavgrelerror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
void dstie(ae_vector *a, ae_int_t n, ae_vector *ties, ae_int_t *tiecount, ae_vector *p1, ae_vector *p2, ae_state *_state)
#define ae_false
Definition: ap.h:196
void clusterizerrunahc(clusterizerstate *s, ahcreport *rep, ae_state *_state)
alglib_impl::ahcreport * p_struct
Definition: dataanalysis.h:470
void * ae_malloc(size_t size, ae_state *state)
Definition: ap.cpp:222
ae_int_t stride
Definition: ap.h:446
void kmeansgenerate(ae_matrix *xy, ae_int_t npoints, ae_int_t nvars, ae_int_t k, ae_int_t restarts, ae_int_t *info, ae_matrix *c, ae_vector *xyc, ae_state *_state)
ae_int_t & terminationtype
Definition: dataanalysis.h:878
ae_bool _mlpcvreport_init(void *_p, ae_state *_state, ae_bool make_automatic)
#define pp(s, x)
Definition: ml2d.cpp:473
double lrprocess(const linearmodel &lm, const real_1d_array &x)
double mlpavgerrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
alglib_impl::modelerrors * c_ptr()
DatasetType
Definition: dimred_tools.h:42
ae_int_t & nhess
Definition: dataanalysis.h:806
doublereal * grad
void filterema(real_1d_array &x, const ae_int_t n, const double alpha)
void _pexec_mlpkfoldcv(mlptrainer *s, multilayerperceptron *network, ae_int_t nrestarts, ae_int_t foldscount, mlpreport *rep, ae_state *_state)
real_2d_array c
Definition: dataanalysis.h:673
union alglib_impl::ae_matrix::@12 ptr
alglib_impl::mlptrainer * p_struct
double smp_mlperror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
void mlpecreateb1(ae_int_t nin, ae_int_t nhid, ae_int_t nout, double b, double d, ae_int_t ensemblesize, mlpensemble *ensemble, ae_state *_state)
double _pexec_mlperrorsparsesubset(multilayerperceptron *network, sparsematrix *xy, ae_int_t setsize, ae_vector *subset, ae_int_t subsetsize, ae_state *_state)
alglib_impl::lrreport * c_ptr()
void dserraccumulate(ae_vector *buf, ae_vector *y, ae_vector *desiredy, ae_state *_state)
void mlpactivationfunction(double net, ae_int_t k, double *f, double *df, double *d2f, ae_state *_state)
void clusterizersetpoints(clusterizerstate *s, ae_matrix *xy, ae_int_t npoints, ae_int_t nfeatures, ae_int_t disttype, ae_state *_state)
void mlpproperties(multilayerperceptron *network, ae_int_t *nin, ae_int_t *nout, ae_int_t *wcount, ae_state *_state)
void dfserialize(decisionforest &obj, std::string &s_out)
ae_bool _mlpcvreport_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void ae_frame_make(ae_state *state, ae_frame *tmp)
Definition: ap.cpp:402
void _pexec_clusterizergetdistances(ae_matrix *xy, ae_int_t npoints, ae_int_t nfeatures, ae_int_t disttype, ae_matrix *d, ae_state *_state)
ae_int_t & nhess
Definition: dataanalysis.h:948
static double * y
void _logitmodel_clear(void *_p)
double mlprelclserrorsparse(multilayerperceptron *network, sparsematrix *xy, ae_int_t npoints, ae_state *_state)
void lrbuild(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, ae_int_t &info, linearmodel &lm, lrreport &ar)
double mnlavgrelerror(const logitmodel &lm, const real_2d_array &xy, const ae_int_t ssize)
void dfbuildrandomdecisionforestx1(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nclasses, const ae_int_t ntrees, const ae_int_t nrndvars, const double r, ae_int_t &info, decisionforest &df, dfreport &rep)
void mlpcreate1(ae_int_t nin, ae_int_t nhid, ae_int_t nout, multilayerperceptron *network, ae_state *_state)
void _linearmodel_clear(void *_p)
void clusterizersetkmeanslimits(const clusterizerstate &s, const ae_int_t restarts, const ae_int_t maxits)
void _pexec_mlpallerrorssubset(multilayerperceptron *network, ae_matrix *xy, ae_int_t setsize, ae_vector *subset, ae_int_t subsetsize, modelerrors *rep, ae_state *_state)
ae_int_t mlpgetoutputscount(const multilayerperceptron &network)
double mnlavgce(const logitmodel &lm, const real_2d_array &xy, const ae_int_t npoints)
double mlpgetweight(const multilayerperceptron &network, const ae_int_t k0, const ae_int_t i0, const ae_int_t k1, const ae_int_t i1)
void mlpcreate2(ae_int_t nin, ae_int_t nhid1, ae_int_t nhid2, ae_int_t nout, multilayerperceptron *network, ae_state *_state)
_mcpdstate_owner & operator=(const _mcpdstate_owner &rhs)
void filterema(ae_vector *x, ae_int_t n, double alpha, ae_state *_state)
void lrbuildzs(const real_2d_array &xy, const real_1d_array &s, const ae_int_t npoints, const ae_int_t nvars, ae_int_t &info, linearmodel &lm, lrreport &ar)
void _mlptrainer_clear(void *_p)
void mlpecreateb0(ae_int_t nin, ae_int_t nout, double b, double d, ae_int_t ensemblesize, mlpensemble *ensemble, ae_state *_state)
void mlpsetdecay(mlptrainer *s, double decay, ae_state *_state)
alglib_impl::mlpcvreport * c_ptr()
bool mlpissoftmax(const multilayerperceptron &network)
void mlpserialize(multilayerperceptron &obj, std::string &s_out)
bool mlpcontinuetraining(const mlptrainer &s, const multilayerperceptron &network)
void _pexec_mlpallerrorssparsesubset(multilayerperceptron *network, sparsematrix *xy, ae_int_t setsize, ae_vector *subset, ae_int_t subsetsize, modelerrors *rep, ae_state *_state)
void _mlpreport_clear(void *_p)
void _mnlreport_clear(void *_p)
void mlpallerrorssubset(multilayerperceptron *network, ae_matrix *xy, ae_int_t setsize, ae_vector *subset, ae_int_t subsetsize, modelerrors *rep, ae_state *_state)
void mlphessiannbatch(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize, double &e, real_1d_array &grad, real_2d_array &h)
ae_bool _mcpdstate_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void mlptrainensemblees(mlptrainer *s, mlpensemble *ensemble, ae_int_t nrestarts, mlpreport *rep, ae_state *_state)
void mlpkfoldcv(mlptrainer *s, multilayerperceptron *network, ae_int_t nrestarts, ae_int_t foldscount, mlpreport *rep, ae_state *_state)
double _pexec_mlperror(multilayerperceptron *network, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
void mlpgradbatchsparsesubset(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t setsize, const integer_1d_array &idx, const ae_int_t subsetsize, double &e, real_1d_array &grad)
void mlpcreatec2(ae_int_t nin, ae_int_t nhid1, ae_int_t nhid2, ae_int_t nout, multilayerperceptron *network, ae_state *_state)
double smp_mlprelclserrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
double mlpavgcesparse(multilayerperceptron *network, sparsematrix *xy, ae_int_t npoints, ae_state *_state)
void dfprocess(decisionforest *df, ae_vector *x, ae_vector *y, ae_state *_state)
ae_bool apservisfinitematrix(ae_matrix *x, ae_int_t m, ae_int_t n, ae_state *_state)
double lravgrelerror(linearmodel *lm, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
void _ahcreport_clear(void *_p)
void mlpunserialize(std::string &s_in, multilayerperceptron &obj)
double smp_mlprelclserror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
double & oobavgerror
Definition: dataanalysis.h:606
ae_int_t mlpgetinputscount(multilayerperceptron *network, ae_state *_state)
void ae_serializer_ustart_str(ae_serializer *serializer, const std::string *buf)
Definition: ap.cpp:3457
void mlpsetcond(const mlptrainer &s, const double wstep, const ae_int_t maxits)
void mlpsetalgobatch(const mlptrainer &s)
void mlperandomize(const mlpensemble &ensemble)
void mlpgrad(const multilayerperceptron &network, const real_1d_array &x, const real_1d_array &desiredy, double &e, real_1d_array &grad)
void mcpdaddtrack(mcpdstate *s, ae_matrix *xy, ae_int_t k, ae_state *_state)
void mlpecreatec0(const ae_int_t nin, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble)
alglib_impl::decisionforest * p_struct
Definition: dataanalysis.h:563
double _pexec_mlprmserror(multilayerperceptron *network, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
_multilayerperceptron_owner & operator=(const _multilayerperceptron_owner &rhs)
doublereal * w
void mlptrainensemblees(const mlptrainer &s, const mlpensemble &ensemble, const ae_int_t nrestarts, mlpreport &rep)
void clusterizerseparatedbycorr(const ahcreport &rep, const double r, ae_int_t &k, integer_1d_array &cidx, integer_1d_array &cz)
double * p_double
Definition: ap.h:437
void mlpebagginglm(mlpensemble *ensemble, ae_matrix *xy, ae_int_t npoints, double decay, ae_int_t restarts, ae_int_t *info, mlpreport *rep, mlpcvreport *ooberrors, ae_state *_state)
ae_bool _cvreport_init(void *_p, ae_state *_state, ae_bool make_automatic)
ae_int_t mlpgetlayersize(const multilayerperceptron &network, const ae_int_t k)
double mnlrelclserror(const logitmodel &lm, const real_2d_array &xy, const ae_int_t npoints)
void mlpeprocessi(mlpensemble *ensemble, ae_vector *x, ae_vector *y, ae_state *_state)
void dfbuildrandomdecisionforestx1(ae_matrix *xy, ae_int_t npoints, ae_int_t nvars, ae_int_t nclasses, ae_int_t ntrees, ae_int_t nrndvars, double r, ae_int_t *info, decisionforest *df, dfreport *rep, ae_state *_state)
void mlpcreater0(ae_int_t nin, ae_int_t nout, double a, double b, multilayerperceptron *network, ae_state *_state)
ae_int_t mlpgetweightscount(const multilayerperceptron &network)
double & oobavgrelerror
Definition: dataanalysis.h:607
double _pexec_mlprmserrorsparse(multilayerperceptron *network, sparsematrix *xy, ae_int_t npoints, ae_state *_state)
double mnlavgerror(const logitmodel &lm, const real_2d_array &xy, const ae_int_t npoints)
void ae_serializer_stop(ae_serializer *serializer)
Definition: ap.cpp:3599
mlpcvreport & operator=(const mlpcvreport &rhs)
void mlperandomize(mlpensemble *ensemble, ae_state *_state)
void ae_state_clear(ae_state *state)
Definition: ap.cpp:373
const alglib_impl::ae_matrix * c_ptr() const
Definition: ap.cpp:6463
ae_bool _modelerrors_init(void *_p, ae_state *_state, ae_bool make_automatic)
void mlprandomize(const multilayerperceptron &network)
void clusterizergetkclusters(const ahcreport &rep, const ae_int_t k, integer_1d_array &cidx, integer_1d_array &cz)
ae_bool ae_fp_eq(double v1, double v2)
Definition: ap.cpp:1313
void mcpdsetbc(mcpdstate *s, ae_matrix *bndl, ae_matrix *bndu, ae_state *_state)
double mlprmserror(multilayerperceptron *network, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
void mcpdaddtrack(const mcpdstate &s, const real_2d_array &xy, const ae_int_t k)
alglib_impl::dfreport * c_ptr()
void dfserialize(ae_serializer *s, decisionforest *forest, ae_state *_state)
alglib_impl::dfreport * p_struct
Definition: dataanalysis.h:589
void mlpsetoutputscaling(multilayerperceptron *network, ae_int_t i, double mean, double sigma, ae_state *_state)
void mlptraines(const multilayerperceptron &network, const real_2d_array &trnxy, const ae_int_t trnsize, const real_2d_array &valxy, const ae_int_t valsize, const double decay, const ae_int_t restarts, ae_int_t &info, mlpreport &rep)
void mlpkfoldcv(const mlptrainer &s, const multilayerperceptron &network, const ae_int_t nrestarts, const ae_int_t foldscount, mlpreport &rep)
void mcpdsolve(mcpdstate *s, ae_state *_state)
ae_int_t mnlclserror(const logitmodel &lm, const real_2d_array &xy, const ae_int_t npoints)
void mlprandomizefull(const multilayerperceptron &network)
lrreport & operator=(const lrreport &rhs)
double mlprelclserrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
void mlpecreater1(ae_int_t nin, ae_int_t nhid, ae_int_t nout, double a, double b, ae_int_t ensemblesize, mlpensemble *ensemble, ae_state *_state)
_mcpdreport_owner & operator=(const _mcpdreport_owner &rhs)
void mlpgetinputscaling(const multilayerperceptron &network, const ae_int_t i, double &mean, double &sigma)
alglib_impl::mcpdreport * c_ptr()
ae_bool _mnlreport_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void mlpsetcond(mlptrainer *s, double wstep, ae_int_t maxits, ae_state *_state)
void lrbuildz(ae_matrix *xy, ae_int_t npoints, ae_int_t nvars, ae_int_t *info, linearmodel *lm, lrreport *ar, ae_state *_state)
void mlphessianbatch(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize, double &e, real_1d_array &grad, real_2d_array &h)
alglib_impl::modelerrors * p_struct
Definition: dataanalysis.h:712
void _multilayerperceptron_clear(void *_p)
void mlpecreate2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble)
ae_bool ae_matrix_init(ae_matrix *dst, ae_int_t rows, ae_int_t cols, ae_datatype datatype, ae_state *state, ae_bool make_automatic)
Definition: ap.cpp:756
void mcpdcreateentryexit(ae_int_t n, ae_int_t entrystate, ae_int_t exitstate, mcpdstate *s, ae_state *_state)
double dfavgrelerror(const decisionforest &df, const real_2d_array &xy, const ae_int_t npoints)
void dsoptimalsplit2(const real_1d_array &a, const integer_1d_array &c, const ae_int_t n, ae_int_t &info, double &threshold, double &pal, double &pbl, double &par, double &pbr, double &cve)
void mcpdcreateexit(const ae_int_t n, const ae_int_t exitstate, mcpdstate &s)
void dfalloc(ae_serializer *s, decisionforest *forest, ae_state *_state)
alglib_impl::mlpreport * p_struct
Definition: dataanalysis.h:933
mnlreport & operator=(const mnlreport &rhs)
doublereal * x
void clusterizerrunkmeans(clusterizerstate *s, ae_int_t k, kmeansreport *rep, ae_state *_state)
alglib_impl::mlpensemble * p_struct
Definition: dataanalysis.h:895
double mlpavgerrorsparse(multilayerperceptron *network, sparsematrix *xy, ae_int_t npoints, ae_state *_state)
#define i
double mnlavgerror(logitmodel *lm, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
double mlperrorn(multilayerperceptron *network, ae_matrix *xy, ae_int_t ssize, ae_state *_state)
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
void pcabuildbasis(const real_2d_array &x, const ae_int_t npoints, const ae_int_t nvars, ae_int_t &info, real_1d_array &s2, real_2d_array &v)
ae_bool _clusterizerstate_init(void *_p, ae_state *_state, ae_bool make_automatic)
void _mcpdreport_clear(void *_p)
void dstiefasti(ae_vector *a, ae_vector *b, ae_int_t n, ae_vector *ties, ae_int_t *tiecount, ae_vector *bufr, ae_vector *bufi, ae_state *_state)
void mcpdcreate(const ae_int_t n, mcpdstate &s)
logitmodel & operator=(const logitmodel &rhs)
void mcpdaddec(const mcpdstate &s, const ae_int_t i, const ae_int_t j, const double c)
_mlpensemble_owner & operator=(const _mlpensemble_owner &rhs)
integer_2d_array pm
Definition: dataanalysis.h:483
void mcpdsetpredictionweights(mcpdstate *s, ae_vector *pw, ae_state *_state)
doublereal * d
void mlpecreatec1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble)
linearmodel & operator=(const linearmodel &rhs)
void mlpgradn(multilayerperceptron *network, ae_vector *x, ae_vector *desiredy, double *e, ae_vector *grad, ae_state *_state)
void mlpgrad(multilayerperceptron *network, ae_vector *x, ae_vector *desiredy, double *e, ae_vector *grad, ae_state *_state)
void ae_serializer_clear(ae_serializer *serializer)
Definition: ap.cpp:3400
void mlpecreater0(ae_int_t nin, ae_int_t nout, double a, double b, ae_int_t ensemblesize, mlpensemble *ensemble, ae_state *_state)
void mcpdsetbc(const mcpdstate &s, const real_2d_array &bndl, const real_2d_array &bndu)
ae_bool _lrreport_init(void *_p, ae_state *_state, ae_bool make_automatic)
void mlpsetdataset(mlptrainer *s, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
alglib_impl::mlptrainer * c_ptr()
void mlpgetoutputscaling(multilayerperceptron *network, ae_int_t i, double *mean, double *sigma, ae_state *_state)
void _pexec_mlptrainensemblees(mlptrainer *s, mlpensemble *ensemble, ae_int_t nrestarts, mlpreport *rep, ae_state *_state)
void mlpallerrorssparsesubset(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize, modelerrors &rep)
alglib_impl::clusterizerstate * c_ptr()
void mlpecreater2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const double a, const double b, const ae_int_t ensemblesize, mlpensemble &ensemble)
void mlpecreate2(ae_int_t nin, ae_int_t nhid1, ae_int_t nhid2, ae_int_t nout, ae_int_t ensemblesize, mlpensemble *ensemble, ae_state *_state)
void fisherldan(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nclasses, ae_int_t &info, real_2d_array &w)
void dsnormalize(ae_matrix *xy, ae_int_t npoints, ae_int_t nvars, ae_int_t *info, ae_vector *means, ae_vector *sigmas, ae_state *_state)
void clusterizersetahcalgo(const clusterizerstate &s, const ae_int_t algo)
void threshold(double *phi, unsigned long nvox, double limit)
Definition: lib_vwk.cpp:524
mlptrainer & operator=(const mlptrainer &rhs)
double mlperelclserror(mlpensemble *ensemble, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
ae_bool _linearmodel_init(void *_p, ae_state *_state, ae_bool make_automatic)
void mlpsetdecay(const mlptrainer &s, const double decay)
void dsnormalizec(ae_matrix *xy, ae_int_t npoints, ae_int_t nvars, ae_int_t *info, ae_vector *means, ae_vector *sigmas, ae_state *_state)
ae_bool _kmeansreport_init(void *_p, ae_state *_state, ae_bool make_automatic)
double vv
double mlprelclserror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
mcpdstate & operator=(const mcpdstate &rhs)
#define cl(i, j)
void mcpdcreateentry(ae_int_t n, ae_int_t entrystate, mcpdstate *s, ae_state *_state)
double mnlavgrelerror(logitmodel *lm, ae_matrix *xy, ae_int_t ssize, ae_state *_state)
ae_int_t ae_v_len(ae_int_t a, ae_int_t b)
Definition: ap.cpp:4562
void mlptrainnetwork(mlptrainer *s, multilayerperceptron *network, ae_int_t nrestarts, mlpreport *rep, ae_state *_state)
void mnlprocessi(logitmodel *lm, ae_vector *x, ae_vector *y, ae_state *_state)
ae_bool _dfreport_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void mcpdaddbc(const mcpdstate &s, const ae_int_t i, const ae_int_t j, const double bndl, const double bndu)
doublereal * b
multilayerperceptron & operator=(const multilayerperceptron &rhs)
void mlpactivationfunction(const double net, const ae_int_t k, double &f, double &df, double &d2f)
double mlpeavgrelerror(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints)
ae_int_t mlpclserror(multilayerperceptron *network, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
void dsoptimalsplit2fast(ae_vector *a, ae_vector *c, ae_vector *tiesbuf, ae_vector *cntbuf, ae_vector *bufr, ae_vector *bufi, ae_int_t n, ae_int_t nc, double alpha, ae_int_t *info, double *threshold, double *rms, double *cvrms, ae_state *_state)
void mlpetraines(mlpensemble *ensemble, ae_matrix *xy, ae_int_t npoints, double decay, ae_int_t restarts, ae_int_t *info, mlpreport *rep, ae_state *_state)
ae_int_t ** pp_int
Definition: ap.h:454
double dfavgrelerror(decisionforest *df, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
double smp_mlperrorsubset(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize)
void tagsort(ae_vector *a, ae_int_t n, ae_vector *p1, ae_vector *p2, ae_state *_state)
void mlpkfoldcvlm(multilayerperceptron *network, ae_matrix *xy, ae_int_t npoints, double decay, ae_int_t restarts, ae_int_t foldscount, ae_int_t *info, mlpreport *rep, mlpcvreport *cvrep, ae_state *_state)
double mlpeavgerror(mlpensemble *ensemble, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
void mcpdsetprior(mcpdstate *s, ae_matrix *pp, ae_state *_state)
void smp_mlpgradbatchsparsesubset(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t setsize, const integer_1d_array &idx, const ae_int_t subsetsize, double &e, real_1d_array &grad)
integer_1d_array cidx
Definition: dataanalysis.h:544
double mlperror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
void kmeansgenerateinternal(ae_matrix *xy, ae_int_t npoints, ae_int_t nvars, ae_int_t k, ae_int_t maxits, ae_int_t restarts, ae_int_t *info, ae_matrix *ccol, ae_bool needccol, ae_matrix *crow, ae_bool needcrow, ae_vector *xyc, ae_state *_state)
double mlpavgerror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
double mlprelclserror(multilayerperceptron *network, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
ae_bool _ahcreport_init(void *_p, ae_state *_state, ae_bool make_automatic)
void mlpecreate0(ae_int_t nin, ae_int_t nout, ae_int_t ensemblesize, mlpensemble *ensemble, ae_state *_state)
void _clusterizerstate_clear(void *_p)
void lrbuildz(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, ae_int_t &info, linearmodel &lm, lrreport &ar)
void mlpgradbatch(multilayerperceptron *network, ae_matrix *xy, ae_int_t ssize, double *e, ae_vector *grad, ae_state *_state)
double dfrelclserror(decisionforest *df, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
double mlperrorsubset(multilayerperceptron *network, ae_matrix *xy, ae_int_t setsize, ae_vector *subset, ae_int_t subsetsize, ae_state *_state)
ae_bool _mnlreport_init(void *_p, ae_state *_state, ae_bool make_automatic)
void mlpcreate1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, multilayerperceptron &network)
double mlpgetweight(multilayerperceptron *network, ae_int_t k0, ae_int_t i0, ae_int_t k1, ae_int_t i1, ae_state *_state)
void ae_v_move(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n)
Definition: ap.cpp:4371
ae_int_t mlpgetlayerscount(multilayerperceptron *network, ae_state *_state)
void mlpgetinputscaling(multilayerperceptron *network, ae_int_t i, double *mean, double *sigma, ae_state *_state)
void mlpallerrorssubset(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize, modelerrors &rep)
viol index
viol type
ae_int_t rows
Definition: ap.h:444
void mlpecreateb2(ae_int_t nin, ae_int_t nhid1, ae_int_t nhid2, ae_int_t nout, double b, double d, ae_int_t ensemblesize, mlpensemble *ensemble, ae_state *_state)
void fisherlda(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nclasses, ae_int_t &info, real_1d_array &w)
ae_int_t & terminationtype
Definition: dataanalysis.h:541
void mlpeproperties(mlpensemble *ensemble, ae_int_t *nin, ae_int_t *nout, ae_state *_state)
alglib_impl::mcpdstate * c_ptr()
void clusterizercreate(clusterizerstate *s, ae_state *_state)
int in
double * f
double smp_mlpavgrelerrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
void ae_vector_clear(ae_vector *dst)
Definition: ap.cpp:692
void mlpgetneuroninfo(const multilayerperceptron &network, const ae_int_t k, const ae_int_t i, ae_int_t &fkind, double &threshold)
void mlphessianbatch(multilayerperceptron *network, ae_matrix *xy, ae_int_t ssize, double *e, ae_vector *grad, ae_matrix *h, ae_state *_state)
void mlphessiannbatch(multilayerperceptron *network, ae_matrix *xy, ae_int_t ssize, double *e, ae_vector *grad, ae_matrix *h, ae_state *_state)
double dfrmserror(decisionforest *df, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
ae_int_t length() const
Definition: ap.cpp:5882
_lrreport_owner & operator=(const _lrreport_owner &rhs)
void rmatrixcopy(const ae_int_t m, const ae_int_t n, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, real_2d_array &b, const ae_int_t ib, const ae_int_t jb)
Definition: linalg.cpp:166
double & cvavgrelerror
Definition: dataanalysis.h:679
double mlpeavgrelerror(mlpensemble *ensemble, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
void dsoptimalsplit2(ae_vector *a, ae_vector *c, ae_int_t n, ae_int_t *info, double *threshold, double *pal, double *pbl, double *par, double *pbr, double *cve, ae_state *_state)
ae_bool mlpeissoftmax(mlpensemble *ensemble, ae_state *_state)
void clusterizergetkclusters(ahcreport *rep, ae_int_t k, ae_vector *cidx, ae_vector *cz, ae_state *_state)
void _lrreport_clear(void *_p)
ae_bool ae_fp_less(double v1, double v2)
Definition: ap.cpp:1327
void mlpunserialize(ae_serializer *s, multilayerperceptron *network, ae_state *_state)
double _pexec_mlperrorsparse(multilayerperceptron *network, sparsematrix *xy, ae_int_t npoints, ae_state *_state)
void mlpprocessi(const multilayerperceptron &network, const real_1d_array &x, real_1d_array &y)
void mlpcreate2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, multilayerperceptron &network)
double & oobrelclserror
Definition: dataanalysis.h:603
mlpensemble & operator=(const mlpensemble &rhs)
ae_bool _multilayerperceptron_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void lrbuild(ae_matrix *xy, ae_int_t npoints, ae_int_t nvars, ae_int_t *info, linearmodel *lm, lrreport *ar, ae_state *_state)
double dfavgce(const decisionforest &df, const real_2d_array &xy, const ae_int_t npoints)
double mlpeavgce(mlpensemble *ensemble, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
void mcpdcreateentry(const ae_int_t n, const ae_int_t entrystate, mcpdstate &s)
double smp_mlperrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
void mlpgradbatchsparsesubset(multilayerperceptron *network, sparsematrix *xy, ae_int_t setsize, ae_vector *idx, ae_int_t subsetsize, double *e, ae_vector *grad, ae_state *_state)
void mlpcreater1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const double a, const double b, multilayerperceptron &network)
double mlpermserror(mlpensemble *ensemble, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
void mlpsetweight(multilayerperceptron *network, ae_int_t k0, ae_int_t i0, ae_int_t k1, ae_int_t i1, double w, ae_state *_state)
void mlpkfoldcvlbfgs(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, const double wstep, const ae_int_t maxits, const ae_int_t foldscount, ae_int_t &info, mlpreport &rep, mlpcvreport &cvrep)
void _kmeansreport_clear(void *_p)
ae_bool _modelerrors_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void filtersma(real_1d_array &x, const ae_int_t n, const ae_int_t k)
alglib_impl::mcpdstate * p_struct
Definition: dataanalysis.h:828
double dx
void mcpdresults(mcpdstate *s, ae_matrix *p, mcpdreport *rep, ae_state *_state)
void mcpdsetec(mcpdstate *s, ae_matrix *ec, ae_state *_state)
void mcpdsettikhonovregularizer(mcpdstate *s, double v, ae_state *_state)
void mlpsetalgobatch(mlptrainer *s, ae_state *_state)
void mlpgetoutputscaling(const multilayerperceptron &network, const ae_int_t i, double &mean, double &sigma)
void mlpcreatec0(ae_int_t nin, ae_int_t nout, multilayerperceptron *network, ae_state *_state)
alglib_impl::mnlreport * c_ptr()
void clusterizercreate(clusterizerstate &s)
#define ae_bool
Definition: ap.h:194
void mlpstarttraining(const mlptrainer &s, const multilayerperceptron &network, const bool randomstart)
_dfreport_owner & operator=(const _dfreport_owner &rhs)
void mlpcreateb2(ae_int_t nin, ae_int_t nhid1, ae_int_t nhid2, ae_int_t nout, double b, double d, multilayerperceptron *network, ae_state *_state)
ae_bool ae_fp_neq(double v1, double v2)
Definition: ap.cpp:1321
void mnlpack(const real_2d_array &a, const ae_int_t nvars, const ae_int_t nclasses, logitmodel &lm)
double mlpavgerror(multilayerperceptron *network, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
void mcpdaddbc(mcpdstate *s, ae_int_t i, ae_int_t j, double bndl, double bndu, ae_state *_state)
double z
ae_bool mlpissoftmax(multilayerperceptron *network, ae_state *_state)
void mnlprocess(logitmodel *lm, ae_vector *x, ae_vector *y, ae_state *_state)
void ae_touch_ptr(void *p)
Definition: ap.cpp:294
decisionforest & operator=(const decisionforest &rhs)
void smp_mlpallerrorssparsesubset(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize, modelerrors &rep)
void mlpcreateb2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const double b, const double d, multilayerperceptron &network)
void mlpcreatetrainercls(ae_int_t nin, ae_int_t nclasses, mlptrainer *s, ae_state *_state)
ae_bool _mlpensemble_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void mlpecreatec2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble)
ae_bool _multilayerperceptron_init(void *_p, ae_state *_state, ae_bool make_automatic)
void mnltrainh(ae_matrix *xy, ae_int_t npoints, ae_int_t nvars, ae_int_t nclasses, ae_int_t *info, logitmodel *lm, mnlreport *rep, ae_state *_state)
double ae_maxreal(double m1, double m2, ae_state *state)
Definition: ap.cpp:1577
ae_error_type
Definition: ap.h:201
void lrpack(const real_1d_array &v, const ae_int_t nvars, linearmodel &lm)
ae_bool _kmeansreport_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
double smp_mlpavgce(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
alglib_impl::linearmodel * c_ptr()
void mlpcreateb0(ae_int_t nin, ae_int_t nout, double b, double d, multilayerperceptron *network, ae_state *_state)
void mcpdaddec(mcpdstate *s, ae_int_t i, ae_int_t j, double c, ae_state *_state)
void clusterizersetdistances(clusterizerstate *s, ae_matrix *d, ae_int_t npoints, ae_bool isupper, ae_state *_state)
double dummy
void mlpetraines(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, ae_int_t &info, mlpreport &rep)
void mlpebagginglbfgs(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, const double wstep, const ae_int_t maxits, ae_int_t &info, mlpreport &rep, mlpcvreport &ooberrors)
void lrbuilds(ae_matrix *xy, ae_vector *s, ae_int_t npoints, ae_int_t nvars, ae_int_t *info, linearmodel *lm, lrreport *ar, ae_state *_state)
ae_bool ae_vector_set_length(ae_vector *dst, ae_int_t newsize, ae_state *state)
Definition: ap.cpp:658
void mlpcreateb1(ae_int_t nin, ae_int_t nhid, ae_int_t nout, double b, double d, multilayerperceptron *network, ae_state *_state)
void mlpsetneuroninfo(multilayerperceptron *network, ae_int_t k, ae_int_t i, ae_int_t fkind, double threshold, ae_state *_state)
void mlpcreateb1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const double b, const double d, multilayerperceptron &network)
double _pexec_mlpavgerror(multilayerperceptron *network, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
void ae_v_sub(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n)
Definition: ap.cpp:4506
void mlpsetinputscaling(const multilayerperceptron &network, const ae_int_t i, const double mean, const double sigma)
void mlpkfoldcvlbfgs(multilayerperceptron *network, ae_matrix *xy, ae_int_t npoints, double decay, ae_int_t restarts, double wstep, ae_int_t maxits, ae_int_t foldscount, ae_int_t *info, mlpreport *rep, mlpcvreport *cvrep, ae_state *_state)
integer_1d_array p
Definition: dataanalysis.h:480
double mlperrorsparsesubset(multilayerperceptron *network, sparsematrix *xy, ae_int_t setsize, ae_vector *subset, ae_int_t subsetsize, ae_state *_state)
void dfbuildrandomdecisionforest(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t nclasses, const ae_int_t ntrees, const double r, ae_int_t &info, decisionforest &df, dfreport &rep)
ae_bool _mcpdreport_init(void *_p, ae_state *_state, ae_bool make_automatic)
alglib_impl::clusterizerstate * p_struct
Definition: dataanalysis.h:360
double mlpeavgce(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints)
void lrbuilds(const real_2d_array &xy, const real_1d_array &s, const ae_int_t npoints, const ae_int_t nvars, ae_int_t &info, linearmodel &lm, lrreport &ar)
int ni
void mlpgradbatch(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize, double &e, real_1d_array &grad)
void mlpgradbatchsubset(multilayerperceptron *network, ae_matrix *xy, ae_int_t setsize, ae_vector *idx, ae_int_t subsetsize, double *e, ae_vector *grad, ae_state *_state)
void _mlpensemble_clear(void *_p)
void _pexec_mlpgradbatchsubset(multilayerperceptron *network, ae_matrix *xy, ae_int_t setsize, ae_vector *idx, ae_int_t subsetsize, double *e, ae_vector *grad, ae_state *_state)
double smp_mlpavgrelerror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
void smp_mlpgradbatchsubset(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t setsize, const integer_1d_array &idx, const ae_int_t subsetsize, double &e, real_1d_array &grad)
double ae_log(double x, ae_state *state)
Definition: ap.cpp:1679
double mlpavgcesparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
struct alglib_impl::ae_vector ae_vector
ae_bool _apbuffers_init(void *_p, ae_state *_state, ae_bool make_automatic)
void mnlunpack(logitmodel *lm, ae_matrix *a, ae_int_t *nvars, ae_int_t *nclasses, ae_state *_state)
void mlpgetneuroninfo(multilayerperceptron *network, ae_int_t k, ae_int_t i, ae_int_t *fkind, double *threshold, ae_state *_state)
double mlpavgrelerrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
const alglib_impl::ae_vector * c_ptr() const
Definition: ap.cpp:5907
void mlpecreater0(const ae_int_t nin, const ae_int_t nout, const double a, const double b, const ae_int_t ensemblesize, mlpensemble &ensemble)
double mlperrorn(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize)
double mnlavgce(logitmodel *lm, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
#define j
double ae_minreal(double m1, double m2, ae_state *state)
Definition: ap.cpp:1582
void mlpprocessi(multilayerperceptron *network, ae_vector *x, ae_vector *y, ae_state *_state)
struct alglib_impl::ae_shared_pool ae_shared_pool
void mcpdcreateexit(ae_int_t n, ae_int_t exitstate, mcpdstate *s, ae_state *_state)
void mlpecreateb0(const ae_int_t nin, const ae_int_t nout, const double b, const double d, const ae_int_t ensemblesize, mlpensemble &ensemble)
ae_bool _mcpdstate_init(void *_p, ae_state *_state, ae_bool make_automatic)
double mlperrorsparse(multilayerperceptron *network, sparsematrix *xy, ae_int_t npoints, ae_state *_state)
void fisherldan(ae_matrix *xy, ae_int_t npoints, ae_int_t nvars, ae_int_t nclasses, ae_int_t *info, ae_matrix *w, ae_state *_state)
alglib_impl::linearmodel * p_struct
Definition: dataanalysis.h:624
ae_bool mlpcontinuetraining(mlptrainer *s, multilayerperceptron *network, ae_state *_state)
double mlprmserrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
ae_int_t smp_mlpclserror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
double mnlrmserror(logitmodel *lm, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
void lrunpack(const linearmodel &lm, real_1d_array &v, ae_int_t &nvars)
alglib_impl::kmeansreport * p_struct
Definition: dataanalysis.h:530
ae_bool _pexec_mlpcontinuetraining(mlptrainer *s, multilayerperceptron *network, ae_state *_state)
void mlpprocess(const multilayerperceptron &network, const real_1d_array &x, real_1d_array &y)
void mlptrainlm(multilayerperceptron *network, ae_matrix *xy, ae_int_t npoints, double decay, ae_int_t restarts, ae_int_t *info, mlpreport *rep, ae_state *_state)
dfreport & operator=(const dfreport &rhs)
double dfrelclserror(const decisionforest &df, const real_2d_array &xy, const ae_int_t npoints)
_mnlreport_owner & operator=(const _mnlreport_owner &rhs)
struct alglib_impl::ae_matrix ae_matrix
void mlpeserialize(ae_serializer *s, mlpensemble *ensemble, ae_state *_state)
void mlprandomizefull(multilayerperceptron *network, ae_state *_state)
void _pexec_mlpgradbatchsparsesubset(multilayerperceptron *network, sparsematrix *xy, ae_int_t setsize, ae_vector *idx, ae_int_t subsetsize, double *e, ae_vector *grad, ae_state *_state)
ae_int_t ae_iabs(ae_int_t x, ae_state *state)
Definition: ap.cpp:1525
double ** pp_double
Definition: ap.h:455
void dfprocessi(const decisionforest &df, const real_1d_array &x, real_1d_array &y)
void _pexec_mlpgradbatch(multilayerperceptron *network, ae_matrix *xy, ae_int_t ssize, double *e, ae_vector *grad, ae_state *_state)
void mlpeprocess(mlpensemble *ensemble, ae_vector *x, ae_vector *y, ae_state *_state)
void ae_state_init(ae_state *state)
Definition: ap.cpp:309
void mcpdsetlc(const mcpdstate &s, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k)
double lrrmserror(const linearmodel &lm, const real_2d_array &xy, const ae_int_t npoints)
double lrprocess(linearmodel *lm, ae_vector *x, ae_state *_state)
void touchint(ae_int_t *a, ae_state *_state)
double mlperelclserror(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints)
void rmatrixsetlengthatleast(ae_matrix *x, ae_int_t m, ae_int_t n, ae_state *_state)
double ae_sqrt(double x, ae_state *state)
Definition: ap.cpp:1535
alglib_impl::mlpreport * c_ptr()
void ae_assert(ae_bool cond, const char *msg, ae_state *state)
Definition: ap.cpp:1227
union alglib_impl::ae_vector::@11 ptr
void mlpallerrorssparsesubset(multilayerperceptron *network, sparsematrix *xy, ae_int_t setsize, ae_vector *subset, ae_int_t subsetsize, modelerrors *rep, ae_state *_state)
ae_int_t & npoints
Definition: dataanalysis.h:479
void _dfreport_clear(void *_p)
ae_int_t rows() const
Definition: ap.cpp:6419
void kmeansgenerate(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nvars, const ae_int_t k, const ae_int_t restarts, ae_int_t &info, real_2d_array &c, integer_1d_array &xyc)
double _pexec_mlprelclserrorsparse(multilayerperceptron *network, sparsematrix *xy, ae_int_t npoints, ae_state *_state)
void mlpcreater2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const double a, const double b, multilayerperceptron &network)
ae_int_t & ncvdefects
Definition: dataanalysis.h:680
double _pexec_mlpavgrelerror(multilayerperceptron *network, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
ae_bool _mlpreport_init(void *_p, ae_state *_state, ae_bool make_automatic)
double _pexec_mlprelclserror(multilayerperceptron *network, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
void ae_serializer_alloc_start(ae_serializer *serializer)
Definition: ap.cpp:3404
void mlpgradbatchsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t ssize, double &e, real_1d_array &grad)
const char *volatile error_msg
Definition: ap.h:389
double mlpavgce(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
void mlpprocess(multilayerperceptron *network, ae_vector *x, ae_vector *y, ae_state *_state)
void _decisionforest_clear(void *_p)
_linearmodel_owner & operator=(const _linearmodel_owner &rhs)
alglib_impl::kmeansreport * c_ptr()
clusterizerstate & operator=(const clusterizerstate &rhs)
void mlptrainlbfgs(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, const double wstep, const ae_int_t maxits, ae_int_t &info, mlpreport &rep)
ae_int_t mlpgetinputscount(const multilayerperceptron &network)
mcpdreport & operator=(const mcpdreport &rhs)
integer_2d_array z
Definition: dataanalysis.h:481
void dserrallocate(ae_int_t nclasses, ae_vector *buf, ae_state *_state)
void samplemoments(const real_1d_array &x, const ae_int_t n, double &mean, double &variance, double &skewness, double &kurtosis)
Definition: statistics.cpp:59
void mlpecreateb2(const ae_int_t nin, const ae_int_t nhid1, const ae_int_t nhid2, const ae_int_t nout, const double b, const double d, const ae_int_t ensemblesize, mlpensemble &ensemble)
void smp_clusterizerrunahc(const clusterizerstate &s, ahcreport &rep)
void fisherlda(ae_matrix *xy, ae_int_t npoints, ae_int_t nvars, ae_int_t nclasses, ae_int_t *info, ae_vector *w, ae_state *_state)
double smp_mlpavgerrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
ae_bool _cvreport_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void _mcpdstate_clear(void *_p)
ae_bool _decisionforest_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void mlpcreater2(ae_int_t nin, ae_int_t nhid1, ae_int_t nhid2, ae_int_t nout, double a, double b, multilayerperceptron *network, ae_state *_state)
void rmatrixenforcesymmetricity(const real_2d_array &a, const ae_int_t n, const bool isupper)
Definition: linalg.cpp:108
#define ae_machineepsilon
Definition: ap.h:825
void mlpcreatec0(const ae_int_t nin, const ae_int_t nout, multilayerperceptron &network)
double mlpermserror(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints)
void clusterizersetpoints(const clusterizerstate &s, const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nfeatures, const ae_int_t disttype)
void pcabuildbasis(ae_matrix *x, ae_int_t npoints, ae_int_t nvars, ae_int_t *info, ae_vector *s2, ae_matrix *v, ae_state *_state)
ae_bool _mlpensemble_init(void *_p, ae_state *_state, ae_bool make_automatic)
void mlpproperties(const multilayerperceptron &network, ae_int_t &nin, ae_int_t &nout, ae_int_t &wcount)
double & avgrelerror
Definition: dataanalysis.h:676
void mlpeprocess(const mlpensemble &ensemble, const real_1d_array &x, real_1d_array &y)
void mcpdsetec(const mcpdstate &s, const real_2d_array &ec)
modelerrors & operator=(const modelerrors &rhs)
ae_bool _clusterizerstate_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void mcpdsetprior(const mcpdstate &s, const real_2d_array &pp)
void clusterizerrunkmeans(const clusterizerstate &s, const ae_int_t k, kmeansreport &rep)
ae_int_t mlpclserror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
void mnlunpack(const logitmodel &lm, real_2d_array &a, ae_int_t &nvars, ae_int_t &nclasses)
void mlpecreatec1(ae_int_t nin, ae_int_t nhid, ae_int_t nout, ae_int_t ensemblesize, mlpensemble *ensemble, ae_state *_state)
void clusterizerseparatedbydist(const ahcreport &rep, const double r, ae_int_t &k, integer_1d_array &cidx, integer_1d_array &cz)
void mlptrainnetwork(const mlptrainer &s, const multilayerperceptron &network, const ae_int_t nrestarts, mlpreport &rep)
void clusterizergetdistances(ae_matrix *xy, ae_int_t npoints, ae_int_t nfeatures, ae_int_t disttype, ae_matrix *d, ae_state *_state)
ptrdiff_t ae_int_t
Definition: ap.h:186
double lravgerror(linearmodel *lm, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
void mlpeunserialize(ae_serializer *s, mlpensemble *ensemble, ae_state *_state)
void lrunpack(linearmodel *lm, ae_vector *v, ae_int_t *nvars, ae_state *_state)
void dsoptimalsplitk(ae_vector *a, ae_vector *c, ae_int_t n, ae_int_t nc, ae_int_t kmax, ae_int_t *info, ae_vector *thresholds, ae_int_t *ni, double *cve, ae_state *_state)
ae_bool ae_vector_init(ae_vector *dst, ae_int_t size, ae_datatype datatype, ae_state *state, ae_bool make_automatic)
Definition: ap.cpp:580
void mlpcreate0(ae_int_t nin, ae_int_t nout, multilayerperceptron *network, ae_state *_state)
void smp_mlpallerrorssubset(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize, modelerrors &rep)
void mlpcreatetrainer(ae_int_t nin, ae_int_t nout, mlptrainer *s, ae_state *_state)
ae_bool ae_isfinite(double x, ae_state *state)
Definition: ap.cpp:1495
double ae_sqr(double x, ae_state *state)
Definition: ap.cpp:1530
alglib_impl::decisionforest * c_ptr()
void clusterizerseparatedbydist(ahcreport *rep, double r, ae_int_t *k, ae_vector *cidx, ae_vector *cz, ae_state *_state)
double mlpavgce(multilayerperceptron *network, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
void clusterizerrunahc(const clusterizerstate &s, ahcreport &rep)
#define INF
Definition: svm.cpp:43
void(* obj)()
double & relclserror
Definition: dataanalysis.h:942
double lravgerror(const linearmodel &lm, const real_2d_array &xy, const ae_int_t npoints)
double dfavgce(decisionforest *df, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
_mlpreport_owner & operator=(const _mlpreport_owner &rhs)
constexpr int K
void clusterizergetdistances(const real_2d_array &xy, const ae_int_t npoints, const ae_int_t nfeatures, const ae_int_t disttype, real_2d_array &d)
double mlperrorsparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
ae_bool _mlptrainer_init(void *_p, ae_state *_state, ae_bool make_automatic)
double dfavgerror(decisionforest *df, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
alglib_impl::ahcreport * c_ptr()
void mcpdsetpredictionweights(const mcpdstate &s, const real_1d_array &pw)
void dfunserialize(ae_serializer *s, decisionforest *forest, ae_state *_state)
void mlpcreater0(const ae_int_t nin, const ae_int_t nout, const double a, const double b, multilayerperceptron &network)
double smp_mlpavgcesparse(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t npoints)
_modelerrors_owner & operator=(const _modelerrors_owner &rhs)
ae_int_t mlpgetlayersize(multilayerperceptron *network, ae_int_t k, ae_state *_state)
ae_int_t * p_int
Definition: ap.h:436
ae_int_t & inneriterationscount
Definition: dataanalysis.h:875
mlpreport & operator=(const mlpreport &rhs)
ae_int_t & ngrad
Definition: dataanalysis.h:805
void clusterizerseparatedbycorr(ahcreport *rep, double r, ae_int_t *k, ae_vector *cidx, ae_vector *cz, ae_state *_state)
ae_bool _ahcreport_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
ae_int_t mlpgetoutputscount(multilayerperceptron *network, ae_state *_state)
void mnlprocessi(const logitmodel &lm, const real_1d_array &x, real_1d_array &y)
void tagsortfasti(ae_vector *a, ae_vector *b, ae_vector *bufa, ae_vector *bufb, ae_int_t n, ae_state *_state)
void mcpdsetlc(mcpdstate *s, ae_matrix *c, ae_vector *ct, ae_int_t k, ae_state *_state)
double mlprmserrorsparse(multilayerperceptron *network, sparsematrix *xy, ae_int_t npoints, ae_state *_state)
ae_int_t & outeriterationscount
Definition: dataanalysis.h:876
void ae_v_addd(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n, double alpha)
Definition: ap.cpp:4479
ae_bool ae_vector_init_copy(ae_vector *dst, ae_vector *src, ae_state *state, ae_bool make_automatic)
Definition: ap.cpp:614
ae_bool _mlptrainer_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void smp_mlpgradbatch(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t ssize, double &e, real_1d_array &grad)
void mlpecreater1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const double a, const double b, const ae_int_t ensemblesize, mlpensemble &ensemble)
void mcpdsolve(const mcpdstate &s)
void mlpsetneuroninfo(const multilayerperceptron &network, const ae_int_t k, const ae_int_t i, const ae_int_t fkind, const double threshold)
ae_bool ae_fp_less_eq(double v1, double v2)
Definition: ap.cpp:1335
void dfbuildrandomdecisionforest(ae_matrix *xy, ae_int_t npoints, ae_int_t nvars, ae_int_t nclasses, ae_int_t ntrees, double r, ae_int_t *info, decisionforest *df, dfreport *rep, ae_state *_state)
kmeansreport & operator=(const kmeansreport &rhs)
void dfunserialize(std::string &s_in, decisionforest &obj)
ae_int_t ae_round(double x, ae_state *state)
Definition: ap.cpp:1547
void clusterizersetkmeanslimits(clusterizerstate *s, ae_int_t restarts, ae_int_t maxits, ae_state *_state)
_ahcreport_owner & operator=(const _ahcreport_owner &rhs)
void mlpebagginglbfgs(mlpensemble *ensemble, ae_matrix *xy, ae_int_t npoints, double decay, ae_int_t restarts, double wstep, ae_int_t maxits, ae_int_t *info, mlpreport *rep, mlpcvreport *ooberrors, ae_state *_state)
void mlpsetsparsedataset(mlptrainer *s, sparsematrix *xy, ae_int_t npoints, ae_state *_state)
void mcpdresults(const mcpdstate &s, real_2d_array &p, mcpdreport &rep)
void mlpcreate0(const ae_int_t nin, const ae_int_t nout, multilayerperceptron &network)
void mnlpack(ae_matrix *a, ae_int_t nvars, ae_int_t nclasses, logitmodel *lm, ae_state *_state)
void mlpecreater2(ae_int_t nin, ae_int_t nhid1, ae_int_t nhid2, ae_int_t nout, double a, double b, ae_int_t ensemblesize, mlpensemble *ensemble, ae_state *_state)
void mlpgradbatchsparse(multilayerperceptron *network, sparsematrix *xy, ae_int_t ssize, double *e, ae_vector *grad, ae_state *_state)
alglib_impl::ae_int_t ae_int_t
Definition: ap.h:889
void mlptraines(multilayerperceptron *network, ae_matrix *trnxy, ae_int_t trnsize, ae_matrix *valxy, ae_int_t valsize, double decay, ae_int_t restarts, ae_int_t *info, mlpreport *rep, ae_state *_state)
void filtersma(ae_vector *x, ae_int_t n, ae_int_t k, ae_state *_state)
double & oobrmserror
Definition: dataanalysis.h:605
double _pexec_mlpavgcesparse(multilayerperceptron *network, sparsematrix *xy, ae_int_t npoints, ae_state *_state)
void ae_frame_leave(ae_state *state)
Definition: ap.cpp:415
alglib_impl::sparsematrix * c_ptr()
Definition: linalg.cpp:4775
void ae_matrix_clear(ae_matrix *dst)
Definition: ap.cpp:891
void filterlrma(real_1d_array &x, const ae_int_t n, const ae_int_t k)
alglib_impl::lrreport * p_struct
Definition: dataanalysis.h:664
#define ae_true
Definition: ap.h:195
void mlpgradn(const multilayerperceptron &network, const real_1d_array &x, const real_1d_array &desiredy, double &e, real_1d_array &grad)
void dfprocess(const decisionforest &df, const real_1d_array &x, real_1d_array &y)
void mlptrainlm(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, ae_int_t &info, mlpreport &rep)
double dfrmserror(const decisionforest &df, const real_2d_array &xy, const ae_int_t npoints)
int * n
ae_int_t mnlclserror(logitmodel *lm, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
double mlpavgrelerrorsparse(multilayerperceptron *network, sparsematrix *xy, ae_int_t npoints, ae_state *_state)
ae_int_t cols() const
Definition: ap.cpp:6426
void mlpsetoutputscaling(const multilayerperceptron &network, const ae_int_t i, const double mean, const double sigma)
bool smp_mlpcontinuetraining(const mlptrainer &s, const multilayerperceptron &network)
ae_bool ae_fp_greater(double v1, double v2)
Definition: ap.cpp:1343
ae_bool ae_matrix_set_length(ae_matrix *dst, ae_int_t rows, ae_int_t cols, ae_state *state)
Definition: ap.cpp:854
double mnlrelclserror(logitmodel *lm, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
ae_bool _decisionforest_init(void *_p, ae_state *_state, ae_bool make_automatic)
doublereal * a
void clusterizersetahcalgo(clusterizerstate *s, ae_int_t algo, ae_state *_state)
ae_bool _logitmodel_init(void *_p, ae_state *_state, ae_bool make_automatic)
void mlpecreate1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, const ae_int_t ensemblesize, mlpensemble &ensemble)
double lrrmserror(linearmodel *lm, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
_kmeansreport_owner & operator=(const _kmeansreport_owner &rhs)
void mcpdsettikhonovregularizer(const mcpdstate &s, const double v)
ae_int_t mlpgetweightscount(multilayerperceptron *network, ae_state *_state)
void _modelerrors_clear(void *_p)
void mlpebagginglm(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints, const double decay, const ae_int_t restarts, ae_int_t &info, mlpreport &rep, mlpcvreport &ooberrors)
void mlpcreatec1(const ae_int_t nin, const ae_int_t nhid, const ae_int_t nout, multilayerperceptron &network)
void mlpalloc(ae_serializer *s, multilayerperceptron *network, ae_state *_state)
ql0001_ & zero(ctemp+1),(cvec+1),(a+1),(b+1),(bl+1),(bu+1),(x+1),(w+1), &iout, ifail, &zero,(w+3), &lwar2,(iw+1), &leniw, &glob_grd.epsmac
void mlpsetinputscaling(multilayerperceptron *network, ae_int_t i, double mean, double sigma, ae_state *_state)
void mlpsetweight(const multilayerperceptron &network, const ae_int_t k0, const ae_int_t i0, const ae_int_t k1, const ae_int_t i1, const double w)
void smp_mlptrainensemblees(const mlptrainer &s, const mlpensemble &ensemble, const ae_int_t nrestarts, mlpreport &rep)
double & relclserror
Definition: dataanalysis.h:598
double mlpeavgerror(const mlpensemble &ensemble, const real_2d_array &xy, const ae_int_t npoints)
double smp_mlperrorsparsesubset(const multilayerperceptron &network, const sparsematrix &xy, const ae_int_t setsize, const integer_1d_array &subset, const ae_int_t subsetsize)
double & cvrmserror
Definition: dataanalysis.h:677
ae_int_t ae_minint(ae_int_t m1, ae_int_t m2, ae_state *state)
Definition: ap.cpp:1572
void mlpecreatefromnetwork(multilayerperceptron *network, ae_int_t ensemblesize, mlpensemble *ensemble, ae_state *_state)
alglib_impl::mnlreport * p_struct
Definition: dataanalysis.h:796
void ae_free(void *p)
Definition: ap.cpp:237
ahcreport & operator=(const ahcreport &rhs)
double _pexec_mlperrorsubset(multilayerperceptron *network, ae_matrix *xy, ae_int_t setsize, ae_vector *subset, ae_int_t subsetsize, ae_state *_state)
double mlprmserror(const multilayerperceptron &network, const real_2d_array &xy, const ae_int_t npoints)
double & avgrelerror
Definition: dataanalysis.h:602
void mlpcreater1(ae_int_t nin, ae_int_t nhid, ae_int_t nout, double a, double b, multilayerperceptron *network, ae_state *_state)
void clusterizersetdistances(const clusterizerstate &s, const real_2d_array &d, const ae_int_t npoints, const bool isupper)
double _pexec_mlpavgce(multilayerperceptron *network, ae_matrix *xy, ae_int_t npoints, ae_state *_state)
_logitmodel_owner & operator=(const _logitmodel_owner &rhs)
_mlpcvreport_owner & operator=(const _mlpcvreport_owner &rhs)
double ae_v_dotproduct(const double *v0, ae_int_t stride0, const double *v1, ae_int_t stride1, ae_int_t n)
Definition: ap.cpp:4344
void _cvreport_destroy(void *_p)
void _pexec_mlptrainnetwork(mlptrainer *s, multilayerperceptron *network, ae_int_t nrestarts, mlpreport *rep, ae_state *_state)
#define ae_maxrealnumber
Definition: ap.h:826
void mlpsetsparsedataset(const mlptrainer &s, const sparsematrix &xy, const ae_int_t npoints)