PageRenderTime 54ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/src/shogun/lib/external/gpdtsolve.cpp

https://github.com/mikelfer/shogun
C++ | 1576 lines | 1232 code | 173 blank | 171 comment | 298 complexity | 88a9d9965d3837311ef9f151d8332442 MD5 | raw file
Possible License(s): GPL-2.0, GPL-3.0, BSD-3-Clause
  1. /******************************************************************************
  2. *** GPDT - Gradient Projection Decomposition Technique ***
  3. ******************************************************************************
  4. *** ***
  5. *** GPDT is a C++ software designed to train large-scale Support Vector ***
  6. *** Machines for binary classification in both scalar and distributed ***
  7. *** memory parallel environments. It uses the Joachims' problem ***
  8. *** decomposition technique to split the whole quadratic programming (QP) ***
  9. *** problem into a sequence of smaller QP subproblems, each one being ***
  10. *** solved by a suitable gradient projection method (GPM). The presently ***
  11. *** implemented GPMs are the Generalized Variable Projection Method ***
  12. *** GVPM (T. Serafini, G. Zanghirati, L. Zanni, "Gradient Projection ***
  13. *** Methods for Quadratic Programs and Applications in Training Support ***
  14. *** Vector Machines"; Optim. Meth. Soft. 20, 2005, 353-378) and the ***
  15. *** Dai-Fletcher Method DFGPM (Y. Dai and R. Fletcher,"New Algorithms for ***
  16. *** Singly Linear Constrained Quadratic Programs Subject to Lower and ***
  17. *** Upper Bounds"; Math. Prog. to appear). ***
  18. *** ***
  19. *** Authors: ***
  20. *** Thomas Serafini, Luca Zanni ***
  21. *** Dept. of Mathematics, University of Modena and Reggio Emilia - ITALY ***
  22. *** serafini.thomas@unimo.it, zanni.luca@unimo.it ***
  23. *** Gaetano Zanghirati ***
  24. *** Dept. of Mathematics, University of Ferrara - ITALY ***
  25. *** g.zanghirati@unife.it ***
  26. *** ***
  27. *** Software homepage: http://dm.unife.it/gpdt ***
  28. *** ***
  29. *** This work is supported by the Italian FIRB Projects ***
  30. *** 'Statistical Learning: Theory, Algorithms and Applications' ***
  31. *** (grant RBAU01877P), http://slipguru.disi.unige.it/ASTA ***
  32. *** and ***
  33. *** 'Parallel Algorithms and Numerical Nonlinear Optimization' ***
  34. *** (grant RBAU01JYPN), http://dm.unife.it/pn2o ***
  35. *** ***
  36. *** Copyright (C) 2004-2008 by T. Serafini, G. Zanghirati, L. Zanni. ***
  37. *** ***
  38. *** COPYRIGHT NOTIFICATION ***
  39. *** ***
  40. *** Permission to copy and modify this software and its documentation ***
  41. *** for internal research use is granted, provided that this notice is ***
  42. *** retained thereon and on all copies or modifications. The authors and ***
  43. *** their respective Universities makes no representations as to the ***
  44. *** suitability and operability of this software for any purpose. It is ***
  45. *** provided "as is" without express or implied warranty. ***
  46. *** Use of this software for commercial purposes is expressly prohibited ***
  47. *** without contacting the authors. ***
  48. *** ***
  49. *** This program is free software; you can redistribute it and/or modify ***
  50. *** it under the terms of the GNU General Public License as published by ***
  51. *** the Free Software Foundation; either version 3 of the License, or ***
  52. *** (at your option) any later version. ***
  53. *** ***
  54. *** This program is distributed in the hope that it will be useful, ***
  55. *** but WITHOUT ANY WARRANTY; without even the implied warranty of ***
  56. *** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ***
  57. *** GNU General Public License for more details. ***
  58. *** ***
  59. *** You should have received a copy of the GNU General Public License ***
  60. *** along with this program; if not, write to the Free Software ***
  61. *** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ***
  62. *** ***
  63. *** File: gpdtsolve.cpp ***
  64. *** Type: scalar ***
  65. *** Version: 1.0 ***
  66. *** Date: November, 2006 ***
  67. *** Revision: 2 ***
  68. *** ***
  69. *** SHOGUN adaptions Written (W) 2006-2009 Soeren Sonnenburg ***
  70. ******************************************************************************/
  71. #include <math.h>
  72. #include <stdio.h>
  73. #include <stdlib.h>
  74. #include <string.h>
  75. #include <time.h>
  76. #include <shogun/lib/external/gpm.h>
  77. #include <shogun/lib/external/gpdt.h>
  78. #include <shogun/lib/external/gpdtsolve.h>
  79. #include <shogun/lib/Signal.h>
  80. #include <shogun/io/SGIO.h>
  81. using namespace shogun;
  82. #ifndef DOXYGEN_SHOULD_SKIP_THIS
  83. namespace shogun
  84. {
  85. #define y_in(i) y[index_in[(i)]]
  86. #define y_out(i) y[index_out[(i)]]
  87. #define alpha_in(i) alpha[index_in[(i)]]
  88. #define alpha_out(i) alpha[index_out[(i)]]
  89. #define minfty (-1.0e+30) // minus infinity
  90. uint32_t Randnext = 1;
  91. #define ThRand (Randnext = Randnext * 1103515245L + 12345L)
  92. #define ThRandPos ((Randnext = Randnext * 1103515245L + 12345L) & 0x7fffffff)
  93. FILE *fp;
  94. /* utility routines prototyping */
  95. void quick_si (int32_t a[], int32_t k);
  96. void quick_s3 (int32_t a[], int32_t k, int32_t ia[]);
  97. void quick_s2 (float64_t a[], int32_t k, int32_t ia[]);
  98. /******************************************************************************/
  99. /*** Class for caching strategy implementation ***/
  100. /******************************************************************************/
  101. class sCache
  102. {
  103. public:
  104. sCache (sKernel* sk, int32_t Mbyte, int32_t ell);
  105. ~sCache ();
  106. cachetype *FillRow (int32_t row, int32_t IsC = 0);
  107. cachetype *GetRow (int32_t row);
  108. int32_t DivideMP (int32_t *out, int32_t *in, int32_t n);
  109. /*** Itarations counter ***/
  110. void Iteration() { nit++; }
  111. /*** Cache size control ***/
  112. int32_t CheckCycle()
  113. {
  114. int32_t us;
  115. cache_entry *pt = first_free->next;
  116. for (us = 0; pt != first_free; us++, pt = pt->next);
  117. if (us != maxmw-1)
  118. return 1;
  119. else
  120. return 0;
  121. }
  122. private:
  123. struct cache_entry
  124. {
  125. int32_t row; // unused row
  126. int32_t last_access_it;
  127. cache_entry *prev, *next;
  128. cachetype *data;
  129. };
  130. sKernel* KER;
  131. int32_t maxmw, ell;
  132. int32_t nit;
  133. cache_entry *mw;
  134. cache_entry *first_free;
  135. cache_entry **pindmw; // 0 if unused row
  136. cachetype *onerow;
  137. cachetype *FindFree(int32_t row, int32_t IsC);
  138. };
  139. /******************************************************************************/
  140. /*** Cache class constructor ***/
  141. /******************************************************************************/
  142. sCache::sCache(sKernel* sk, int32_t Mbyte, int32_t _ell) : KER(sk), ell(_ell)
  143. {
  144. int32_t i;
  145. // size in dwords of one cache row
  146. maxmw = (sizeof(cache_entry) + sizeof(cache_entry *)
  147. + ell*sizeof(cachetype)) / 4;
  148. // number of cache rows
  149. maxmw = Mbyte*1024*(1024/4) / maxmw;
  150. /* arrays allocation */
  151. mw = SG_MALLOC(cache_entry, maxmw);
  152. pindmw = SG_MALLOC(cache_entry*, ell);
  153. onerow = SG_MALLOC(cachetype, ell);
  154. /* arrays initialization */
  155. for (i = 0; i < maxmw; i++)
  156. {
  157. mw[i].prev = (i == 0 ? &mw[maxmw-1] : &mw[i-1]);
  158. mw[i].next = (i == maxmw-1 ? &mw[0] : &mw[i+1]);
  159. mw[i].data = SG_MALLOC(cachetype, ell);
  160. mw[i].row = -1; // unused row
  161. mw[i].last_access_it = -1;
  162. }
  163. for (i = 0; i < ell; i++)
  164. pindmw[i] = 0;
  165. first_free = &mw[0];
  166. nit = 0;
  167. }
  168. /******************************************************************************/
  169. /*** Cache class destructor ***/
  170. /******************************************************************************/
  171. sCache::~sCache()
  172. {
  173. int32_t i;
  174. for (i = maxmw-1; i >= 0; i--)
  175. SG_FREE(mw[i].data);
  176. SG_FREE(onerow);
  177. SG_FREE(pindmw);
  178. SG_FREE(mw);
  179. }
  180. /******************************************************************************/
  181. /*** Retrieve a cached row ***/
  182. /******************************************************************************/
  183. cachetype *sCache::GetRow(int32_t row)
  184. {
  185. cache_entry *c;
  186. c = pindmw[row];
  187. if (c == NULL)
  188. return NULL;
  189. c->last_access_it = nit;
  190. if (c == first_free)
  191. {
  192. first_free = first_free->next;
  193. }
  194. else
  195. {
  196. // move "row" as the most recently used.
  197. c->prev->next = c->next;
  198. c->next->prev = c->prev;
  199. c->next = first_free;
  200. c->prev = first_free->prev;
  201. first_free->prev = c;
  202. c->prev->next = c;
  203. }
  204. return c->data;
  205. }
  206. /******************************************************************************
  207. *** Look for a free cache row ***
  208. *** IMPORTANT: call this method only if you are sure that "row" ***
  209. *** is not already in the cache ( i.e. after calling GetRow() ) ***
  210. ******************************************************************************/
  211. cachetype *sCache::FindFree(int32_t row, int32_t IsC)
  212. {
  213. cachetype *pt;
  214. if (first_free->row != -1) // cache row already contains data
  215. {
  216. if (first_free->last_access_it == nit || IsC)
  217. return 0;
  218. else
  219. pindmw[first_free->row] = 0;
  220. }
  221. first_free->row = row;
  222. first_free->last_access_it = nit;
  223. pindmw[row] = first_free;
  224. pt = first_free->data;
  225. first_free = first_free->next;
  226. return pt;
  227. }
  228. /******************************************************************************/
  229. /*** Enter data in a cache row ***/
  230. /******************************************************************************/
  231. cachetype *sCache::FillRow(int32_t row, int32_t IsC)
  232. {
  233. int32_t j;
  234. cachetype *pt;
  235. pt = GetRow(row);
  236. if (pt != NULL)
  237. return pt;
  238. pt = FindFree(row, IsC);
  239. if (pt == 0)
  240. pt = onerow;
  241. // Compute all the row elements
  242. for (j = 0; j < ell; j++)
  243. pt[j] = (cachetype)KER->Get(row, j);
  244. return pt;
  245. }
  246. /******************************************************************************/
  247. /*** Expand a sparse row in a full cache row ***/
  248. /******************************************************************************/
  249. int32_t sCache::DivideMP(int32_t *out, int32_t *in, int32_t n)
  250. {
  251. /********************************************************************
  252. * Input meaning: *
  253. * in = vector containing row to be extracted in the cache *
  254. * n = size of in *
  255. * out = the indexes of "in" of the components to be computed *
  256. * by this processor (first those in the cache, then the *
  257. * ones not yet computed) *
  258. * Returns: the number of components of this processor *
  259. ********************************************************************/
  260. int32_t *remained, nremained, k;
  261. int32_t i;
  262. remained = SG_MALLOC(int32_t, n);
  263. nremained = 0;
  264. k = 0;
  265. for (i = 0; i < n; i++)
  266. {
  267. if (pindmw[in[i]] != NULL)
  268. out[k++] = i;
  269. else
  270. remained[nremained++] = i;
  271. }
  272. for (i = 0; i < nremained; i++)
  273. out[k++] = remained[i];
  274. SG_FREE(remained);
  275. return n;
  276. }
  277. /******************************************************************************/
  278. /*** Check solution optimality ***/
  279. /******************************************************************************/
  280. int32_t QPproblem::optimal()
  281. {
  282. /***********************************************************************
  283. * Returns 1 if the computed solution is optimal, otherwise returns 0. *
  284. * To verify the optimality it checks the KKT optimality conditions. *
  285. ***********************************************************************/
  286. register int32_t i, j, margin_sv_number, z, k, s, kin, z1, znew=0, nnew;
  287. float64_t gx_i, aux, s1, s2;
  288. /* sort -y*grad and store in ing the swaps done */
  289. for (j = 0; j < ell; j++)
  290. {
  291. grad[j] = y[j] - st[j];
  292. ing[j] = j;
  293. }
  294. quick_s2(grad,ell,ing);
  295. /* compute bee */
  296. margin_sv_number = 0;
  297. for (i = chunk_size - 1; i >= 0; i--)
  298. if (is_free(index_in[i]))
  299. {
  300. margin_sv_number++;
  301. bee = y_in(i) - st[index_in[i]];
  302. break;
  303. }
  304. if (margin_sv_number > 0)
  305. {
  306. aux=-1.0;
  307. for (i = nb-1; i >= 0; i--)
  308. {
  309. gx_i = bee + st[index_out[i]];
  310. if ((is_zero(index_out[i]) && (gx_i*y_out(i) < (1.0-delta))) ||
  311. (is_bound(index_out[i]) && (gx_i*y_out(i) > (1.0+delta))) ||
  312. (is_free(index_out[i]) &&
  313. ((gx_i*y_out(i) < 1.0-delta) || (gx_i*y_out(i) > 1.0+delta))))
  314. {
  315. if (fabs(gx_i*y_out(i) - 1.0) > aux)
  316. aux = fabs(gx_i*y_out(i) - 1.0);
  317. }
  318. }
  319. }
  320. else
  321. {
  322. for (i = ell - 1; i >= 0; i--)
  323. if (is_free(i))
  324. {
  325. margin_sv_number++;
  326. bee = y[i] - st[i];
  327. break;
  328. }
  329. if (margin_sv_number == 0)
  330. {
  331. s1 = -minfty;
  332. s2 = -minfty;
  333. for (j = 0; j < ell; j++)
  334. if ( (alpha[ing[j]] > DELTAsv) && (y[ing[j]] >= 0) )
  335. {
  336. s1 = grad[j];
  337. break;
  338. }
  339. for (j = 0; j < ell; j++)
  340. if ( (alpha[ing[j]] < c_const-DELTAsv) && (y[ing[j]] <= 0) )
  341. {
  342. s2 = grad[j];
  343. break;
  344. }
  345. if (s1 < s2)
  346. aux = s1;
  347. else
  348. aux = s2;
  349. s1 = minfty;
  350. s2 = minfty;
  351. for (j = ell-1; j >=0; j--)
  352. if ( (alpha[ing[j]] > DELTAsv) && (y[ing[j]] <= 0) )
  353. {
  354. s1 = grad[j];
  355. break;
  356. }
  357. for (j = ell-1; j >=0; j--)
  358. if ( (alpha[ing[j]] < c_const-DELTAsv) && (y[ing[j]] >= 0) )
  359. {
  360. s2 = grad[j];
  361. break;
  362. }
  363. if (s2 > s1) s1 = s2;
  364. bee = 0.5 * (s1+aux);
  365. }
  366. aux = -1.0;
  367. for (i = ell-1; i >= 0; i--)
  368. {
  369. gx_i = bee + st[i];
  370. if ((is_zero(i) && (gx_i*y[i] < (1.0-delta))) ||
  371. (is_bound(i) && (gx_i*y[i] > (1.0+delta))) ||
  372. (is_free(i) &&
  373. ((gx_i*y[i] < 1.0-delta) || (gx_i*y[i] > 1.0+delta))))
  374. {
  375. if (fabs(gx_i*y[i] - 1.0) > aux)
  376. aux = fabs(gx_i*y[i] - 1.0);
  377. }
  378. }
  379. }
  380. if (aux < 0.0)
  381. return 1;
  382. else
  383. {
  384. if (verbosity > 1)
  385. SG_SINFO(" Max KKT violation: %lf\n", aux)
  386. else if (verbosity > 0)
  387. SG_SINFO(" %lf\n", aux)
  388. if (fabs(kktold-aux) < delta*0.01 && aux < delta*2.0)
  389. {
  390. if (DELTAvpm > InitialDELTAvpm*0.1)
  391. {
  392. DELTAvpm = (DELTAvpm*0.5 > InitialDELTAvpm*0.1 ?
  393. DELTAvpm*0.5 : InitialDELTAvpm*0.1);
  394. SG_SINFO("Inner tolerance changed to: %lf\n", DELTAvpm)
  395. }
  396. }
  397. kktold = aux;
  398. /*****************************************************************************
  399. *** Update the working set (T. Serafini, L. Zanni, "On the Working Set ***
  400. *** Selection in Gradient Projection-based Decomposition Techniques for ***
  401. *** Support Vector Machines"; Optim. Meth. Soft. 20, 2005). ***
  402. *****************************************************************************/
  403. for (j = 0; j < chunk_size; j++)
  404. inold[j] = index_in[j];
  405. z = -1; /* index of the last entered component from the top */
  406. z1 = ell; /* index of the last entered component from the bottom */
  407. k = 0;
  408. j = 0;
  409. while (k < q)
  410. {
  411. i = z + 1; /* index of the candidate components from the top */
  412. while (i < z1)
  413. {
  414. if ( is_free(ing[i]) ||
  415. (-y[ing[i]]>=0 && is_zero(ing[i])) ||
  416. (-y[ing[i]]<=0 && is_bound(ing[i]))
  417. )
  418. {
  419. znew = i; /* index of the component to select from the top */
  420. break;
  421. }
  422. i++;
  423. }
  424. if (i == z1) break;
  425. s = z1 - 1;
  426. while (znew < s)
  427. {
  428. if ( is_free(ing[s]) ||
  429. (y[ing[s]]>=0 && is_zero(ing[s])) ||
  430. (y[ing[s]]<=0 && is_bound(ing[s]))
  431. )
  432. {
  433. z1 = s;
  434. z = znew;
  435. break;
  436. }
  437. s--;
  438. }
  439. if (znew == s) break;
  440. index_in[k++] = ing[z];
  441. index_in[k++] = ing[z1];
  442. }
  443. if (k < q)
  444. {
  445. if (verbosity > 1)
  446. SG_SINFO(" New q: %i\n", k)
  447. q = k;
  448. }
  449. quick_si(index_in, q);
  450. s = 0;
  451. j = 0;
  452. for (k = 0; k < chunk_size; k++)
  453. {
  454. z = inold[k];
  455. for (i = j; i < q; i++)
  456. if (z <= index_in[i])
  457. break;
  458. if (i == q)
  459. {
  460. for (i = k; i < chunk_size; i++)
  461. {
  462. ing[s] = inold[i]; /* older components not in the new basis */
  463. s = s+1;
  464. }
  465. break;
  466. }
  467. if (z == index_in[i])
  468. j = i + 1; /* the component is still in the basis */
  469. else
  470. {
  471. ing[s] = z; /* older component not in the new basis */
  472. s = s + 1;
  473. j = i;
  474. }
  475. }
  476. for (i = 0; i < s; i++)
  477. {
  478. bmemrid[i] = bmem[ing[i]];
  479. pbmr[i] = i;
  480. }
  481. quick_s3(bmemrid, s, pbmr);
  482. /* check if support vectors not at bound enter the basis */
  483. j = q;
  484. i = 0;
  485. while (j < chunk_size && i < s)
  486. {
  487. if (is_free(ing[pbmr[i]]))
  488. {
  489. index_in[j] = ing[pbmr[i]];
  490. j++;
  491. }
  492. i++;
  493. }
  494. /* choose which bound variables keep in basis (alpha = 0 or alpha = C) */
  495. if (j < chunk_size)
  496. {
  497. i = 0;
  498. while (j < chunk_size && i < s)
  499. {
  500. if (is_zero(ing[pbmr[i]]))
  501. {
  502. index_in[j] = ing[pbmr[i]];
  503. j++;
  504. }
  505. i++;
  506. }
  507. if (j < chunk_size)
  508. {
  509. i = 0;
  510. while (j < chunk_size && i < s)
  511. {
  512. if (is_bound(ing[pbmr[i]]))
  513. {
  514. index_in[j] = ing[pbmr[i]];
  515. j++;
  516. }
  517. i++;
  518. }
  519. }
  520. }
  521. quick_si(index_in, chunk_size);
  522. for (i = 0; i < chunk_size; i++)
  523. bmem[index_in[i]]++;
  524. j = 0;
  525. k = 0;
  526. for (i = 0; i < chunk_size; i++)
  527. {
  528. for (z = j; z < index_in[i]; z++)
  529. {
  530. index_out[k] = z;
  531. k++;
  532. }
  533. j = index_in[i]+1;
  534. }
  535. for (z = j; z < ell; z++)
  536. {
  537. index_out[k] = z;
  538. k++;
  539. }
  540. for (i = 0; i < nb; i++)
  541. bmem[index_out[i]] = 0;
  542. kin = 0;
  543. j = 0;
  544. for (k = 0; k < chunk_size; k++)
  545. {
  546. z = index_in[k];
  547. for (i = j; i < chunk_size; i++)
  548. if (z <= inold[i])
  549. break;
  550. if (i == chunk_size)
  551. {
  552. for (s = k; s < chunk_size; s++)
  553. {
  554. incom[s] = -1;
  555. cec[index_in[s]]++;
  556. }
  557. kin = kin + chunk_size - k ;
  558. break;
  559. }
  560. if (z == inold[i])
  561. {
  562. incom[k] = i;
  563. j = i+1;
  564. }
  565. else
  566. {
  567. incom[k] = -1;
  568. j = i;
  569. kin = kin + 1;
  570. cec[index_in[k]]++;
  571. }
  572. }
  573. nnew = kin & (~1);
  574. if (nnew < 10)
  575. nnew = 10;
  576. if (nnew < chunk_size/10)
  577. nnew = chunk_size/10;
  578. if (nnew < q)
  579. {
  580. q = nnew;
  581. q = q & (~1);
  582. }
  583. if (kin == 0)
  584. {
  585. DELTAkin *= 0.1;
  586. if (DELTAkin < 1.0e-6)
  587. {
  588. SG_SINFO("\n***ERROR***: GPDT stops with tolerance")
  589. SG_SINFO(
  590. " %lf because it is unable to change the working set.\n", kktold);
  591. return 1;
  592. }
  593. else
  594. {
  595. SG_SINFO("Inner tolerance temporary changed to:")
  596. SG_SINFO(" %e\n", DELTAvpm*DELTAkin)
  597. }
  598. }
  599. else
  600. DELTAkin = 1.0;
  601. if (verbosity > 1)
  602. {
  603. SG_SINFO(" Working set: new components: %i", kin)
  604. SG_SINFO(", new parameter n: %i\n", q)
  605. }
  606. return 0;
  607. }
  608. }
  609. /******************************************************************************/
  610. /*** Optional preprocessing: random distribution ***/
  611. /******************************************************************************/
  612. int32_t QPproblem::Preprocess0(int32_t *aux, int32_t *sv)
  613. {
  614. int32_t i, j;
  615. Randnext = 1;
  616. memset(sv, 0, ell*sizeof(int32_t));
  617. for (i = 0; i < chunk_size; i++)
  618. {
  619. do
  620. {
  621. j = ThRandPos % ell;
  622. } while (sv[j] != 0);
  623. sv[j] = 1;
  624. }
  625. return(chunk_size);
  626. }
  627. /******************************************************************************/
  628. /*** Optional preprocessing: block parallel distribution ***/
  629. /******************************************************************************/
  630. int32_t QPproblem::Preprocess1(sKernel* kernel, int32_t *aux, int32_t *sv)
  631. {
  632. int32_t s; // elements owned by the processor
  633. int32_t sl; // elements of the n-1 subproblems
  634. int32_t n, i, off, j, k, ll;
  635. int32_t nsv, nbsv;
  636. int32_t *sv_loc, *bsv_loc, *sp_y;
  637. float32_t *sp_D=NULL;
  638. float64_t *sp_alpha, *sp_h;
  639. s = ell;
  640. /* divide the s elements into n blocks smaller than preprocess_size */
  641. n = (s + preprocess_size - 1) / preprocess_size;
  642. sl = 1 + s / n;
  643. if (verbosity > 0)
  644. {
  645. SG_SINFO(" Preprocessing: examples = %d", s)
  646. SG_SINFO(", subp. = %d", n)
  647. SG_SINFO(", size = %d\n",sl)
  648. }
  649. sv_loc = SG_MALLOC(int32_t, s);
  650. bsv_loc = SG_MALLOC(int32_t, s);
  651. sp_alpha = SG_MALLOC(float64_t, sl);
  652. sp_h = SG_MALLOC(float64_t, sl);
  653. sp_y = SG_MALLOC(int32_t, sl);
  654. if (sl < 500)
  655. sp_D = SG_MALLOC(float32_t, sl*sl);
  656. for (i = 0; i < sl; i++)
  657. sp_h[i] = -1.0;
  658. memset(alpha, 0, ell*sizeof(float64_t));
  659. /* randomly reorder the component to select */
  660. for (i = 0; i < ell; i++)
  661. aux[i] = i;
  662. Randnext = 1;
  663. for (i = 0; i < ell; i++)
  664. {
  665. j = ThRandPos % ell;
  666. k = ThRandPos % ell;
  667. ll = aux[j]; aux[j] = aux[k]; aux[k] = ll;
  668. }
  669. nbsv = nsv = 0;
  670. for (i = 0; i < n; i++)
  671. {
  672. if (verbosity > 0)
  673. SG_SINFO("%d...", i)
  674. SplitParts(s, i, n, &ll, &off);
  675. if (sl < 500)
  676. {
  677. for (j = 0; j < ll; j++)
  678. {
  679. sp_y[j] = y[aux[j+off]];
  680. for (k = j; k < ll; k++)
  681. sp_D[k*sl + j] = sp_D[j*sl + k]
  682. = y[aux[j+off]] * y[aux[k+off]]
  683. * (float32_t)kernel->Get(aux[j+off], aux[k+off]);
  684. }
  685. memset(sp_alpha, 0, sl*sizeof(float64_t));
  686. /* call the gradient projection QP solver */
  687. gpm_solver(projection_solver, projection_projector, ll, sp_D, sp_h,
  688. c_const, 0.0, sp_y, sp_alpha, delta*10, NULL);
  689. }
  690. else
  691. {
  692. QPproblem p2;
  693. QPproblem::copy_subproblem(&p2, this, ll, aux + off);
  694. p2.chunk_size = (int32_t) ((float64_t)chunk_size / sqrt((float64_t)n));
  695. p2.q = (int32_t) ((float64_t)q / sqrt((float64_t)n));
  696. p2.maxmw = ll*ll*4 / (1024 * 1024);
  697. if (p2.maxmw > maxmw / 2)
  698. p2.maxmw = maxmw / 2;
  699. p2.verbosity = 0;
  700. p2.delta = delta * 10.0;
  701. p2.PreprocessMode = 0;
  702. kernel->KernelEvaluations += p2.gpdtsolve(sp_alpha);
  703. }
  704. for (j = 0; j < ll; j++)
  705. {
  706. /* modify bound support vector approximation */
  707. if (sp_alpha[j] < (c_const-DELTAsv))
  708. sp_alpha[j] = 0.0;
  709. else
  710. sp_alpha[j] = c_const;
  711. if (sp_alpha[j] > DELTAsv)
  712. {
  713. if (sp_alpha[j] < (c_const-DELTAsv))
  714. sv_loc[nsv++] = aux[j+off];
  715. else
  716. bsv_loc[nbsv++] = aux[j+off];
  717. alpha[aux[j+off]] = sp_alpha[j];
  718. }
  719. }
  720. }
  721. Randnext = 1;
  722. /* add the known support vectors to the working set */
  723. memset(sv, 0, ell*sizeof(int32_t));
  724. ll = (nsv < chunk_size ? nsv : chunk_size);
  725. for (i = 0; i < ll; i++)
  726. {
  727. do {
  728. j = sv_loc[ThRandPos % nsv];
  729. } while (sv[j] != 0);
  730. sv[j] = 1;
  731. }
  732. /* add the known bound support vectors to the working set */
  733. ll = ((nsv+nbsv) < chunk_size ? (nsv+nbsv) : chunk_size);
  734. for (; i < ll; i++)
  735. {
  736. do {
  737. j = bsv_loc[ThRandPos % nbsv];
  738. } while (sv[j] != 0);
  739. sv[j] = 1;
  740. }
  741. /* eventually fill up the working set with other components
  742. randomly chosen */
  743. for (; i < chunk_size; i++)
  744. {
  745. do {
  746. j = ThRandPos % ell;
  747. } while (sv[j] != 0);
  748. sv[j] = 1;
  749. }
  750. /* dealloc temporary arrays */
  751. if (sl < 500) SG_FREE(sp_D);
  752. SG_FREE(sp_y );
  753. SG_FREE(sp_h );
  754. SG_FREE(sv_loc );
  755. SG_FREE(bsv_loc );
  756. SG_FREE(sp_alpha);
  757. if (verbosity > 0)
  758. {
  759. SG_SINFO("\n Preprocessing: SV = %d", nsv)
  760. SG_SINFO(", BSV = %d\n", nbsv)
  761. }
  762. return(nsv);
  763. }
  764. /******************************************************************************/
  765. /*** Compute the QP problem solution ***/
  766. /******************************************************************************/
  767. float64_t QPproblem::gpdtsolve(float64_t *solution)
  768. {
  769. int32_t i, j, k, z, iin, jin, nit, tot_vpm_iter, lsCount;
  770. int32_t tot_vpm_secant, projCount, proximal_count;
  771. int32_t vpmWarningThreshold;
  772. int32_t nzin, nzout;
  773. int32_t *sp_y; /* labels vector */
  774. int32_t *indnzin, *indnzout; /* nonzero components indices vectors */
  775. float32_t *sp_D; /* quadratic part of the objective function */
  776. float64_t *sp_h, *sp_hloc, /* linear part of the objective function */
  777. *sp_alpha,*stloc; /* variables and gradient updating vectors */
  778. float64_t sp_e, aux, fval, tau_proximal_this, dfval;
  779. float64_t *vau;
  780. float64_t *weight;
  781. float64_t tot_prep_time, tot_vpm_time, tot_st_time, total_time;
  782. sCache *Cache;
  783. cachetype *ptmw;
  784. clock_t t, ti;
  785. Cache = new sCache(KER, maxmw, ell);
  786. if (chunk_size > ell) chunk_size = ell;
  787. if (chunk_size <= 20)
  788. vpmWarningThreshold = 30*chunk_size;
  789. else if (chunk_size <= 200)
  790. vpmWarningThreshold = 20*chunk_size + 200;
  791. else
  792. vpmWarningThreshold = 10*chunk_size + 2200;
  793. kktold = 10000.0;
  794. if (delta <= 5e-3)
  795. {
  796. if ( (chunk_size <= 20) | ((float64_t)chunk_size/ell <= 0.001) )
  797. DELTAvpm = delta * 0.1;
  798. else if ( (chunk_size <= 200) | ((float64_t)chunk_size/ell <= 0.005) )
  799. DELTAvpm = delta * 0.5;
  800. else
  801. DELTAvpm = delta;
  802. }
  803. else
  804. {
  805. if ( (chunk_size <= 200) | ((float64_t)chunk_size/ell <= 0.005) )
  806. DELTAvpm = (1e-3 < delta*0.1) ? 1e-3 : delta*0.1;
  807. else
  808. DELTAvpm = 5e-3;
  809. }
  810. InitialDELTAvpm = DELTAvpm;
  811. DELTAsv = EPS_SV * c_const;
  812. DELTAkin = 1.0;
  813. q = q & (~1);
  814. nb = ell - chunk_size;
  815. tot_vpm_iter = 0;
  816. tot_vpm_secant = 0;
  817. tot_prep_time = tot_vpm_time = tot_st_time = total_time = 0.0;
  818. ti = clock();
  819. /* arrays allocation */
  820. SG_SDEBUG("ell:%d, chunk_size:%d, nb:%d dim:%d\n", ell, chunk_size,nb, dim)
  821. ing = SG_MALLOC(int32_t, ell);
  822. inaux = SG_MALLOC(int32_t, ell);
  823. index_in = SG_MALLOC(int32_t, chunk_size);
  824. index_out = SG_MALLOC(int32_t, ell);
  825. indnzout = SG_MALLOC(int32_t, nb);
  826. alpha = SG_MALLOC(float64_t, ell);
  827. memset(alpha, 0, ell*sizeof(float64_t));
  828. memset(ing, 0, ell*sizeof(int32_t));
  829. if (verbosity > 0 && PreprocessMode != 0)
  830. SG_SINFO("\n*********** Begin setup step...\n")
  831. t = clock();
  832. switch(PreprocessMode)
  833. {
  834. case 1: Preprocess1(KER, inaux, ing); break;
  835. case 0:
  836. default:
  837. Preprocess0(inaux, ing); break;
  838. }
  839. for (j = k = i = 0; i < ell; i++)
  840. if (ing[i] == 0)
  841. index_out[j++] = i;
  842. else
  843. index_in[k++] = i;
  844. t = clock() - t;
  845. if (verbosity > 0 && PreprocessMode != 0)
  846. {
  847. SG_SINFO(" Time for setup: %.2lf\n", (float64_t)t/CLOCKS_PER_SEC)
  848. SG_SINFO(
  849. "\n\n*********** Begin decomposition technique...\n");
  850. }
  851. /* arrays allocation */
  852. bmem = SG_MALLOC(int32_t, ell);
  853. bmemrid = SG_MALLOC(int32_t, chunk_size);
  854. pbmr = SG_MALLOC(int32_t, chunk_size);
  855. cec = SG_MALLOC(int32_t, ell);
  856. indnzin = SG_MALLOC(int32_t, chunk_size);
  857. inold = SG_MALLOC(int32_t, chunk_size);
  858. incom = SG_MALLOC(int32_t, chunk_size);
  859. vau = SG_MALLOC(float64_t, ell);
  860. grad = SG_MALLOC(float64_t, ell);
  861. weight = SG_MALLOC(float64_t, dim);
  862. st = SG_MALLOC(float64_t, ell);
  863. stloc = SG_MALLOC(float64_t, ell);
  864. for (i = 0; i < ell; i++)
  865. {
  866. bmem[i] = 0;
  867. cec[i] = 0;
  868. st[i] = 0;
  869. }
  870. sp_y = SG_MALLOC(int32_t, chunk_size);
  871. sp_D = SG_MALLOC(float32_t, chunk_size*chunk_size);
  872. sp_alpha = SG_MALLOC(float64_t, chunk_size);
  873. sp_h = SG_MALLOC(float64_t, chunk_size);
  874. sp_hloc = SG_MALLOC(float64_t, chunk_size);
  875. for (i = 0; i < chunk_size; i++)
  876. cec[index_in[i]] = cec[index_in[i]]+1;
  877. for (i = chunk_size-1; i >= 0; i--)
  878. {
  879. incom[i] = -1;
  880. sp_alpha[i] = 0.0;
  881. bmem[index_in[i]] = 1;
  882. }
  883. if (verbosity == 1)
  884. {
  885. SG_SINFO(" IT | Prep Time | Solver IT | Solver Time |")
  886. SG_SINFO(" Grad Time | KKT violation\n")
  887. SG_SINFO("------+-----------+-----------+-------------+")
  888. SG_SINFO("-----------+--------------\n")
  889. }
  890. /***************************************************************************/
  891. /* Begin the problem resolution loop */
  892. nit = 0;
  893. do
  894. {
  895. t = clock();
  896. if ((nit % 10) == 9)
  897. {
  898. if ((t-ti) > 0)
  899. total_time += (float64_t)(t-ti) / CLOCKS_PER_SEC;
  900. else
  901. total_time += (float64_t)(ti-t) / CLOCKS_PER_SEC;
  902. ti = t;
  903. }
  904. if (verbosity > 1)
  905. SG_SINFO("\n*********** ITERATION: %d\n", nit + 1)
  906. else if (verbosity > 0)
  907. SG_SINFO("%5d |", nit + 1)
  908. else
  909. SG_SINFO(".")
  910. fflush(stdout);
  911. nzout = 0;
  912. for (k = 0; k < nb; k++)
  913. if (alpha_out(k)>DELTAsv)
  914. {
  915. indnzout[nzout] = index_out[k];
  916. nzout++;
  917. }
  918. sp_e = 0.;
  919. for (j = 0; j < nzout; j++)
  920. {
  921. vau[j] = y[indnzout[j]]*alpha[indnzout[j]];
  922. sp_e += vau[j];
  923. }
  924. if (verbosity > 1)
  925. SG_SINFO(" spe: %e ", sp_e)
  926. for (i = 0; i < chunk_size; i++)
  927. sp_y[i] = y_in(i);
  928. /* Construct the objective function Hessian */
  929. for (i = 0; i < chunk_size; i++)
  930. {
  931. iin = index_in[i];
  932. ptmw = Cache->GetRow(iin);
  933. if (ptmw != 0)
  934. {
  935. for (j = 0; j <= i; j++)
  936. sp_D[i*chunk_size + j] = sp_y[i]*sp_y[j] * ptmw[index_in[j]];
  937. }
  938. else if (incom[i] == -1)
  939. for (j = 0; j <= i; j++)
  940. sp_D[i*chunk_size + j] = sp_y[i]*sp_y[j]
  941. * (float32_t)KER->Get(iin, index_in[j]);
  942. else
  943. {
  944. for (j = 0; j < i; j++)
  945. if (incom[j] == -1)
  946. sp_D[i*chunk_size + j]
  947. = sp_y[i]*sp_y[j] * (float32_t)KER->Get(iin, index_in[j]);
  948. else
  949. sp_D[i*chunk_size + j]
  950. = sp_D[incom[j]*chunk_size + incom[i]];
  951. sp_D[i*chunk_size + i]
  952. = sp_y[i]*sp_y[i] * (float32_t)KER->Get(iin, index_in[i]);
  953. }
  954. }
  955. for (i = 0; i < chunk_size; i++)
  956. {
  957. for (j = 0; j < i; j++)
  958. sp_D[j*chunk_size + i] = sp_D[i*chunk_size + j];
  959. }
  960. if (nit == 0 && PreprocessMode > 0)
  961. {
  962. for (i = 0; i < chunk_size; i++)
  963. {
  964. iin = index_in[i];
  965. aux = 0.;
  966. ptmw = Cache->GetRow(iin);
  967. if (ptmw == NULL)
  968. for (j = 0; j < nzout; j++)
  969. aux += vau[j] * KER->Get(iin, indnzout[j]);
  970. else
  971. for (j = 0; j < nzout; j++)
  972. aux += vau[j] * ptmw[indnzout[j]];
  973. sp_h[i] = y_in(i) * aux - 1.0;
  974. }
  975. }
  976. else
  977. {
  978. for (i = 0; i < chunk_size; i++)
  979. vau[i] = alpha_in(i);
  980. for (i = 0; i < chunk_size; i++)
  981. {
  982. aux = 0.0;
  983. for (j = 0; j < chunk_size; j++)
  984. aux += sp_D[i*chunk_size + j] * vau[j];
  985. sp_h[i] = st[index_in[i]] * y_in(i) - 1.0 - aux;
  986. }
  987. }
  988. t = clock() - t;
  989. if (verbosity > 1)
  990. SG_SINFO(" Preparation Time: %.2lf\n", (float64_t)t/CLOCKS_PER_SEC)
  991. else if (verbosity > 0)
  992. SG_SINFO(" %8.2lf |", (float64_t)t/CLOCKS_PER_SEC)
  993. tot_prep_time += (float64_t)t/CLOCKS_PER_SEC;
  994. /*** Proximal point modification: first type ***/
  995. if (tau_proximal < 0.0)
  996. tau_proximal_this = 0.0;
  997. else
  998. tau_proximal_this = tau_proximal;
  999. proximal_count = 0;
  1000. do {
  1001. t = clock();
  1002. for (i = 0; i < chunk_size; i++)
  1003. {
  1004. vau[i] = sp_D[i*chunk_size + i];
  1005. sp_h[i] -= tau_proximal_this * alpha_in(i);
  1006. sp_D[i*chunk_size + i] += (float32_t)tau_proximal_this;
  1007. }
  1008. if (kktold < delta*100)
  1009. for (i = 0; i < chunk_size; i++)
  1010. sp_alpha[i] = alpha_in(i);
  1011. else
  1012. for (i = 0; i < chunk_size; i++)
  1013. sp_alpha[i] = 0.0;
  1014. /*** call the chosen inner gradient projection QP solver ***/
  1015. i = gpm_solver(projection_solver, projection_projector, chunk_size,
  1016. sp_D, sp_h, c_const, sp_e, sp_y, sp_alpha,
  1017. DELTAvpm*DELTAkin, &lsCount, &projCount);
  1018. if (i > vpmWarningThreshold)
  1019. {
  1020. if (ker_type == 2)
  1021. {
  1022. SG_SINFO("\n WARNING: inner subproblem hard to solve;")
  1023. SG_SINFO(" setting a smaller -q or")
  1024. SG_SINFO(" tuning -c and -g options might help.\n")
  1025. }
  1026. else
  1027. {
  1028. SG_SINFO("\n WARNING: inner subproblem hard to solve;")
  1029. SG_SINFO(" set a smaller -q or")
  1030. SG_SINFO(" try a better data scaling.\n")
  1031. }
  1032. }
  1033. t = clock() - t;
  1034. tot_vpm_iter += i;
  1035. tot_vpm_secant += projCount;
  1036. tot_vpm_time += (float64_t)t/CLOCKS_PER_SEC;
  1037. if (verbosity > 1)
  1038. {
  1039. SG_SINFO(" Solver it: %d", i)
  1040. SG_SINFO(", ls: %d", lsCount)
  1041. SG_SINFO(", time: %.2lf\n", (float64_t)t/CLOCKS_PER_SEC)
  1042. }
  1043. else if (verbosity > 0)
  1044. {
  1045. SG_SINFO(" %6d", i)
  1046. SG_SINFO(" | %8.2lf |", (float64_t)t/CLOCKS_PER_SEC)
  1047. }
  1048. /*** Proximal point modification: second type ***/
  1049. for (i = 0; i < chunk_size; i++)
  1050. sp_D[i*chunk_size + i] = (float32_t)vau[i];
  1051. tau_proximal_this = 0.0;
  1052. if (tau_proximal < 0.0)
  1053. {
  1054. dfval = 0.0;
  1055. for (i = 0; i < chunk_size; i++)
  1056. {
  1057. aux = 0.0;
  1058. for (j = 0; j < chunk_size; j++)
  1059. aux += sp_D[i*chunk_size + j]*(alpha_in(j) - sp_alpha[j]);
  1060. dfval += (0.5*aux - st[index_in[i]]*y_in(i) + 1.0) * (alpha_in(i) - sp_alpha[i]);
  1061. }
  1062. aux=0.0;
  1063. for (i = 0; i < chunk_size; i++)
  1064. aux += (alpha_in(i) - sp_alpha[i])*(alpha_in(i) - sp_alpha[i]);
  1065. if ((-dfval/aux) < -0.5*tau_proximal)
  1066. {
  1067. tau_proximal_this = -tau_proximal;
  1068. if (verbosity > 0)
  1069. SG_SDEBUG("tau threshold: %lf ", -dfval/aux)
  1070. }
  1071. }
  1072. proximal_count++;
  1073. } while (tau_proximal_this != 0.0 && proximal_count < 2); // Proximal point loop
  1074. t = clock();
  1075. nzin = 0;
  1076. for (j = 0; j < chunk_size; j++)
  1077. {
  1078. if (nit == 0)
  1079. aux = sp_alpha[j];
  1080. else
  1081. aux = sp_alpha[j] - alpha_in(j);
  1082. if (fabs(aux) > DELTAsv)
  1083. {
  1084. indnzin[nzin] = index_in[j];
  1085. grad[nzin] = aux * y_in(j);
  1086. nzin++;
  1087. }
  1088. }
  1089. // in case of LINADD enabled use faster linadd variant
  1090. if (KER->get_kernel()->has_property(KP_LINADD) && get_linadd_enabled())
  1091. {
  1092. KER->get_kernel()->clear_normal() ;
  1093. for (j = 0; j < nzin; j++)
  1094. KER->get_kernel()->add_to_normal(indnzin[j], grad[j]);
  1095. if (nit == 0 && PreprocessMode > 0)
  1096. {
  1097. for (j = 0; j < nzout; j++)
  1098. {
  1099. jin = indnzout[j];
  1100. KER->get_kernel()->add_to_normal(jin, alpha[jin] * y[jin]);
  1101. }
  1102. }
  1103. for (i = 0; i < ell; i++)
  1104. st[i] += KER->get_kernel()->compute_optimized(i);
  1105. }
  1106. else // nonlinear kernel
  1107. {
  1108. k = Cache->DivideMP(ing, indnzin, nzin);
  1109. for (j = 0; j < k; j++)
  1110. {
  1111. ptmw = Cache->FillRow(indnzin[ing[j]]);
  1112. for (i = 0; i < ell; i++)
  1113. st[i] += grad[ing[j]] * ptmw[i];
  1114. }
  1115. if (PreprocessMode > 0 && nit == 0)
  1116. {
  1117. clock_t ti2;
  1118. ti2 = clock();
  1119. for (j = 0; j < nzout; j++)
  1120. {
  1121. jin = indnzout[j];
  1122. ptmw = Cache->FillRow(jin);
  1123. for (i = 0; i < ell; i++)
  1124. st[i] += alpha[jin] * y[jin] * ptmw[i];
  1125. }
  1126. if (verbosity > 1)
  1127. SG_SINFO(
  1128. " G*x0 time: %.2lf\n", (float64_t)(clock()-ti2)/CLOCKS_PER_SEC);
  1129. }
  1130. }
  1131. /*** sort the vectors for cache managing ***/
  1132. t = clock() - t;
  1133. if (verbosity > 1)
  1134. SG_SINFO(" Gradient updating time: %.2lf\n", (float64_t)t/CLOCKS_PER_SEC)
  1135. else if (verbosity > 0)
  1136. SG_SINFO(" %8.2lf |", (float64_t)t/CLOCKS_PER_SEC)
  1137. tot_st_time += (float64_t)t/CLOCKS_PER_SEC;
  1138. /*** global updating of the solution vector ***/
  1139. for (i = 0; i < chunk_size; i++)
  1140. alpha_in(i) = sp_alpha[i];
  1141. if (verbosity > 1)
  1142. {
  1143. j = k = 0;
  1144. for (i = 0; i < ell; i++)
  1145. {
  1146. if (is_free(i)) j++;
  1147. if (is_bound(i)) k++;
  1148. }
  1149. SG_SINFO(" SV: %d", j+k)
  1150. SG_SINFO(", BSV: %d\n", k)
  1151. }
  1152. Cache->Iteration();
  1153. nit = nit+1;
  1154. } while (!optimal() && !(CSignal::cancel_computations()));
  1155. /* End of the problem resolution loop */
  1156. /***************************************************************************/
  1157. t = clock();
  1158. if ((t-ti) > 0)
  1159. total_time += (float64_t)(t-ti) / CLOCKS_PER_SEC;
  1160. else
  1161. total_time += (float64_t)(ti-t) / CLOCKS_PER_SEC;
  1162. ti = t;
  1163. memcpy(solution, alpha, ell * sizeof(float64_t));
  1164. /* objective function evaluation */
  1165. fval = 0.0;
  1166. for (i = 0; i < ell; i++)
  1167. fval += alpha[i]*(y[i]*st[i]*0.5 - 1.0);
  1168. SG_SINFO("\n------+-----------+-----------+-------------+")
  1169. SG_SINFO("-----------+--------------\n")
  1170. SG_SINFO(
  1171. "\n- TOTAL ITERATIONS: %i\n", nit);
  1172. if (verbosity > 1)
  1173. {
  1174. j = 0;
  1175. k = 0;
  1176. z = 0;
  1177. for (i = ell - 1; i >= 0; i--)
  1178. {
  1179. if (cec[i] > 0) j++;
  1180. if (cec[i] > 1) k++;
  1181. if (cec[i] > 2) z++;
  1182. }
  1183. SG_SINFO(
  1184. "- Variables entering the working set at least one time: %i\n", j);
  1185. SG_SINFO(
  1186. "- Variables entering the working set at least two times: %i\n", k);
  1187. SG_SINFO(
  1188. "- Variables entering the working set at least three times: %i\n", z);
  1189. }
  1190. SG_FREE(bmem);
  1191. SG_FREE(bmemrid);
  1192. SG_FREE(pbmr);
  1193. SG_FREE(cec);
  1194. SG_FREE(ing);
  1195. SG_FREE(inaux);
  1196. SG_FREE(indnzin);
  1197. SG_FREE(index_in);
  1198. SG_FREE(inold);
  1199. SG_FREE(incom);
  1200. SG_FREE(indnzout);
  1201. SG_FREE(index_out);
  1202. SG_FREE(vau);
  1203. SG_FREE(alpha);
  1204. SG_FREE(weight);
  1205. SG_FREE(grad);
  1206. SG_FREE(stloc);
  1207. SG_FREE(st);
  1208. SG_FREE(sp_h);
  1209. SG_FREE(sp_hloc);
  1210. SG_FREE(sp_y);
  1211. SG_FREE(sp_D);
  1212. SG_FREE(sp_alpha);
  1213. delete Cache;
  1214. aux = KER->KernelEvaluations;
  1215. SG_SINFO("- Total CPU time: %lf\n", total_time)
  1216. if (verbosity > 0)
  1217. {
  1218. SG_SINFO(
  1219. "- Total kernel evaluations: %.0lf\n", aux);
  1220. SG_SINFO(
  1221. "- Total inner solver iterations: %i\n", tot_vpm_iter);
  1222. if (projection_projector == 1)
  1223. SG_SINFO(
  1224. "- Total projector iterations: %i\n", tot_vpm_secant);
  1225. SG_SINFO(
  1226. "- Total preparation time: %lf\n", tot_prep_time);
  1227. SG_SINFO(
  1228. "- Total inner solver time: %lf\n", tot_vpm_time);
  1229. SG_SINFO(
  1230. "- Total gradient updating time: %lf\n", tot_st_time);
  1231. }
  1232. SG_SINFO("- Objective function value: %lf\n", fval)
  1233. objective_value=fval;
  1234. return aux;
  1235. }
  1236. /******************************************************************************/
  1237. /*** Quick sort for integer vectors ***/
  1238. /******************************************************************************/
  1239. void quick_si(int32_t a[], int32_t n)
  1240. {
  1241. int32_t i, j, s, d, l, x, w, ps[20], pd[20];
  1242. l = 0;
  1243. ps[0] = 0;
  1244. pd[0] = n-1;
  1245. do
  1246. {
  1247. s = ps[l];
  1248. d = pd[l];
  1249. l--;
  1250. do
  1251. {
  1252. i = s;
  1253. j = d;
  1254. x = a[(s+d)/2];
  1255. do
  1256. {
  1257. while (a[i] < x) i++;
  1258. while (a[j] > x) j--;
  1259. if (i <= j)
  1260. {
  1261. w = a[i];
  1262. a[i] = a[j];
  1263. i++;
  1264. a[j] = w;
  1265. j--;
  1266. }
  1267. } while(i<=j);
  1268. if (j-s > d-i)
  1269. {
  1270. l++;
  1271. ps[l] = s;
  1272. pd[l] = j;
  1273. s = i;
  1274. }
  1275. else
  1276. {
  1277. if (i < d)
  1278. {
  1279. l++;
  1280. ps[l] = i;
  1281. pd[l] = d;
  1282. }
  1283. d = j;
  1284. }
  1285. } while (s < d);
  1286. } while (l >= 0);
  1287. }
  1288. /******************************************************************************/
  1289. /*** Quick sort for real vectors returning also the exchanges ***/
  1290. /******************************************************************************/
  1291. void quick_s2(float64_t a[], int32_t n, int32_t ia[])
  1292. {
  1293. int32_t i, j, s, d, l, iw, ps[20], pd[20];
  1294. float64_t x, w;
  1295. l = 0;
  1296. ps[0] = 0;
  1297. pd[0] = n-1;
  1298. do
  1299. {
  1300. s = ps[l];
  1301. d = pd[l];
  1302. l--;
  1303. do
  1304. {
  1305. i = s;
  1306. j = d;
  1307. x = a[(s+d)/2];
  1308. do
  1309. {
  1310. while (a[i] < x) i++;
  1311. while (a[j] > x) j--;
  1312. if (i <= j)
  1313. {
  1314. iw = ia[i];
  1315. w = a[i];
  1316. ia[i] = ia[j];
  1317. a[i] = a[j];
  1318. i++;
  1319. ia[j] = iw;
  1320. a[j] = w;
  1321. j--;
  1322. }
  1323. } while (i <= j);
  1324. if (j-s > d-i)
  1325. {
  1326. l++;
  1327. ps[l] = s;
  1328. pd[l] = j;
  1329. s = i;
  1330. }
  1331. else
  1332. {
  1333. if (i < d)
  1334. {
  1335. l++;
  1336. ps[l] = i;
  1337. pd[l] = d;
  1338. }
  1339. d = j;
  1340. }
  1341. } while (s < d);
  1342. } while(l>=0);
  1343. }
  1344. /******************************************************************************/
  1345. /*** Quick sort for integer vectors returning also the exchanges ***/
  1346. /******************************************************************************/
  1347. void quick_s3(int32_t a[], int32_t n, int32_t ia[])
  1348. {
  1349. int32_t i, j, s, d, l, iw, w, x, ps[20], pd[20];
  1350. l = 0;
  1351. ps[0] = 0;
  1352. pd[0] = n-1;
  1353. do
  1354. {
  1355. s = ps[l];
  1356. d = pd[l];
  1357. l--;
  1358. do
  1359. {
  1360. i = s;
  1361. j = d;
  1362. x = a[(s+d)/2];
  1363. do
  1364. {
  1365. while (a[i] < x) i++;
  1366. while (a[j] > x) j--;
  1367. if (i <= j)
  1368. {
  1369. iw = ia[i];
  1370. w = a[i];
  1371. ia[i] = ia[j];
  1372. a[i] = a[j];
  1373. i++;
  1374. ia[j] = iw;
  1375. a[j] = w;
  1376. j--;
  1377. }
  1378. } while (i <= j);
  1379. if (j-s > d-i)
  1380. {
  1381. l++;
  1382. ps[l] = s;
  1383. pd[l] = j;
  1384. s = i;
  1385. }
  1386. else
  1387. {
  1388. if (i < d)
  1389. {
  1390. l++;
  1391. ps[l] = i;
  1392. pd[l] = d;
  1393. }
  1394. d = j;
  1395. }
  1396. } while (s < d);
  1397. } while (l >= 0);
  1398. }
  1399. }
  1400. #endif // DOXYGEN_SHOULD_SKIP_THIS
  1401. /******************************************************************************/
  1402. /*** End of gpdtsolve.cpp file ***/
  1403. /******************************************************************************/