PageRenderTime 84ms CodeModel.GetById 55ms RepoModel.GetById 0ms app.codeStats 0ms

/src/shogun/lib/slep/q1/epph.cpp

https://code.google.com/
C++ | 686 lines | 443 code | 132 blank | 111 comment | 96 complexity | f0cf27e741ac2f1cdc34f1999f867185 MD5 | raw file
Possible License(s): GPL-2.0, GPL-3.0, BSD-3-Clause
  1. /* This program is free software: you can redistribute it and/or modify
  2. * it under the terms of the GNU General Public License as published by
  3. * the Free Software Foundation, either version 3 of the License, or
  4. * (at your option) any later version.
  5. *
  6. * This program is distributed in the hope that it will be useful,
  7. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. * GNU General Public License for more details.
  10. *
  11. * You should have received a copy of the GNU General Public License
  12. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. *
  14. * Copyright (C) 2009 - 2012 Jun Liu and Jieping Ye
  15. */
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <time.h>
  19. #include <math.h>
  20. #include <shogun/lib/slep/q1/epph.h>
  21. #define delta 1e-8
  22. #define innerIter 1000
  23. #define outerIter 1000
  24. void eplb(double * x, double *root, int * steps, double * v,int n, double z, double lambda0)
  25. {
  26. int i, j, flag=0;
  27. int rho_1, rho_2, rho, rho_T, rho_S;
  28. int V_i_b, V_i_e, V_i;
  29. double lambda_1, lambda_2, lambda_T, lambda_S, lambda;
  30. double s_1, s_2, s, s_T, s_S, v_max, temp;
  31. double f_lambda_1, f_lambda_2, f_lambda, f_lambda_T, f_lambda_S;
  32. int iter_step=0;
  33. /* find the maximal absolute value in v
  34. * and copy the (absolute) values from v to x
  35. */
  36. if (z< 0){
  37. printf("\n z should be nonnegative!");
  38. return;
  39. }
  40. V_i=0;
  41. if (v[0] !=0){
  42. rho_1=1;
  43. s_1=x[V_i]=v_max=fabs(v[0]);
  44. V_i++;
  45. }
  46. else{
  47. rho_1=0;
  48. s_1=v_max=0;
  49. }
  50. for (i=1;i<n; i++){
  51. if (v[i]!=0){
  52. x[V_i]=fabs(v[i]); s_1+= x[V_i]; rho_1++;
  53. if (x[V_i] > v_max)
  54. v_max=x[V_i];
  55. V_i++;
  56. }
  57. }
  58. /* If ||v||_1 <= z, then v is the solution */
  59. if (s_1 <= z){
  60. flag=1; lambda=0;
  61. for(i=0;i<n;i++){
  62. x[i]=v[i];
  63. }
  64. *root=lambda;
  65. *steps=iter_step;
  66. return;
  67. }
  68. lambda_1=0; lambda_2=v_max;
  69. f_lambda_1=s_1 -z;
  70. /*f_lambda_1=s_1-rho_1* lambda_1 -z;*/
  71. rho_2=0; s_2=0; f_lambda_2=-z;
  72. V_i_b=0; V_i_e=V_i-1;
  73. lambda=lambda0;
  74. if ( (lambda<lambda_2) && (lambda> lambda_1) ){
  75. /*-------------------------------------------------------------------
  76. Initialization with the root
  77. *-------------------------------------------------------------------
  78. */
  79. i=V_i_b; j=V_i_e; rho=0; s=0;
  80. while (i <= j){
  81. while( (i <= V_i_e) && (x[i] <= lambda) ){
  82. i++;
  83. }
  84. while( (j>=V_i_b) && (x[j] > lambda) ){
  85. s+=x[j];
  86. j--;
  87. }
  88. if (i<j){
  89. s+=x[i];
  90. temp=x[i]; x[i]=x[j]; x[j]=temp;
  91. i++; j--;
  92. }
  93. }
  94. rho=V_i_e-j; rho+=rho_2; s+=s_2;
  95. f_lambda=s-rho*lambda-z;
  96. if ( fabs(f_lambda)< delta ){
  97. flag=1;
  98. }
  99. if (f_lambda <0){
  100. lambda_2=lambda; s_2=s; rho_2=rho; f_lambda_2=f_lambda;
  101. V_i_e=j; V_i=V_i_e-V_i_b+1;
  102. }
  103. else{
  104. lambda_1=lambda; rho_1=rho; s_1=s; f_lambda_1=f_lambda;
  105. V_i_b=i; V_i=V_i_e-V_i_b+1;
  106. }
  107. if (V_i==0){
  108. /*printf("\n rho=%d, rho_1=%d, rho_2=%d",rho, rho_1, rho_2);
  109. printf("\n V_i=%d",V_i);*/
  110. lambda=(s - z)/ rho;
  111. flag=1;
  112. }
  113. /*-------------------------------------------------------------------
  114. End of initialization
  115. *--------------------------------------------------------------------
  116. */
  117. }/* end of if(!flag) */
  118. while (!flag){
  119. iter_step++;
  120. /* compute lambda_T */
  121. lambda_T=lambda_1 + f_lambda_1 /rho_1;
  122. if(rho_2 !=0){
  123. if (lambda_2 + f_lambda_2 /rho_2 > lambda_T)
  124. lambda_T=lambda_2 + f_lambda_2 /rho_2;
  125. }
  126. /* compute lambda_S */
  127. lambda_S=lambda_2 - f_lambda_2 *(lambda_2-lambda_1)/(f_lambda_2-f_lambda_1);
  128. if (fabs(lambda_T-lambda_S) <= delta){
  129. lambda=lambda_T; flag=1;
  130. break;
  131. }
  132. /* set lambda as the middle point of lambda_T and lambda_S */
  133. lambda=(lambda_T+lambda_S)/2;
  134. s_T=s_S=s=0;
  135. rho_T=rho_S=rho=0;
  136. i=V_i_b; j=V_i_e;
  137. while (i <= j){
  138. while( (i <= V_i_e) && (x[i] <= lambda) ){
  139. if (x[i]> lambda_T){
  140. s_T+=x[i]; rho_T++;
  141. }
  142. i++;
  143. }
  144. while( (j>=V_i_b) && (x[j] > lambda) ){
  145. if (x[j] > lambda_S){
  146. s_S+=x[j]; rho_S++;
  147. }
  148. else{
  149. s+=x[j]; rho++;
  150. }
  151. j--;
  152. }
  153. if (i<j){
  154. if (x[i] > lambda_S){
  155. s_S+=x[i]; rho_S++;
  156. }
  157. else{
  158. s+=x[i]; rho++;
  159. }
  160. if (x[j]> lambda_T){
  161. s_T+=x[j]; rho_T++;
  162. }
  163. temp=x[i]; x[i]=x[j]; x[j]=temp;
  164. i++; j--;
  165. }
  166. }
  167. s_S+=s_2; rho_S+=rho_2;
  168. s+=s_S; rho+=rho_S;
  169. s_T+=s; rho_T+=rho;
  170. f_lambda_S=s_S-rho_S*lambda_S-z;
  171. f_lambda=s-rho*lambda-z;
  172. f_lambda_T=s_T-rho_T*lambda_T-z;
  173. /*printf("\n %d & %d & %5.6f & %5.6f & %5.6f & %5.6f & %5.6f \\\\ \n \\hline ", iter_step, V_i, lambda_1, lambda_T, lambda, lambda_S, lambda_2);*/
  174. if ( fabs(f_lambda)< delta ){
  175. /*printf("\n lambda");*/
  176. flag=1;
  177. break;
  178. }
  179. if ( fabs(f_lambda_S)< delta ){
  180. /* printf("\n lambda_S");*/
  181. lambda=lambda_S; flag=1;
  182. break;
  183. }
  184. if ( fabs(f_lambda_T)< delta ){
  185. /* printf("\n lambda_T");*/
  186. lambda=lambda_T; flag=1;
  187. break;
  188. }
  189. /*
  190. printf("\n\n f_lambda_1=%5.6f, f_lambda_2=%5.6f, f_lambda=%5.6f",f_lambda_1,f_lambda_2, f_lambda);
  191. printf("\n lambda_1=%5.6f, lambda_2=%5.6f, lambda=%5.6f",lambda_1, lambda_2, lambda);
  192. printf("\n rho_1=%d, rho_2=%d, rho=%d ",rho_1, rho_2, rho);
  193. */
  194. if (f_lambda <0){
  195. lambda_2=lambda; s_2=s; rho_2=rho;
  196. f_lambda_2=f_lambda;
  197. lambda_1=lambda_T; s_1=s_T; rho_1=rho_T;
  198. f_lambda_1=f_lambda_T;
  199. V_i_e=j; i=V_i_b;
  200. while (i <= j){
  201. while( (i <= V_i_e) && (x[i] <= lambda_T) ){
  202. i++;
  203. }
  204. while( (j>=V_i_b) && (x[j] > lambda_T) ){
  205. j--;
  206. }
  207. if (i<j){
  208. x[j]=x[i];
  209. i++; j--;
  210. }
  211. }
  212. V_i_b=i; V_i=V_i_e-V_i_b+1;
  213. }
  214. else{
  215. lambda_1=lambda; s_1=s; rho_1=rho;
  216. f_lambda_1=f_lambda;
  217. lambda_2=lambda_S; s_2=s_S; rho_2=rho_S;
  218. f_lambda_2=f_lambda_S;
  219. V_i_b=i; j=V_i_e;
  220. while (i <= j){
  221. while( (i <= V_i_e) && (x[i] <= lambda_S) ){
  222. i++;
  223. }
  224. while( (j>=V_i_b) && (x[j] > lambda_S) ){
  225. j--;
  226. }
  227. if (i<j){
  228. x[i]=x[j];
  229. i++; j--;
  230. }
  231. }
  232. V_i_e=j; V_i=V_i_e-V_i_b+1;
  233. }
  234. if (V_i==0){
  235. lambda=(s - z)/ rho; flag=1;
  236. /*printf("\n V_i=0, lambda=%5.6f",lambda);*/
  237. break;
  238. }
  239. }/* end of while */
  240. for(i=0;i<n;i++){
  241. if (v[i] > lambda)
  242. x[i]=v[i]-lambda;
  243. else
  244. if (v[i]< -lambda)
  245. x[i]=v[i]+lambda;
  246. else
  247. x[i]=0;
  248. }
  249. *root=lambda;
  250. *steps=iter_step;
  251. }
  252. void epp1(double *x, double *v, int n, double rho)
  253. {
  254. int i;
  255. /*
  256. we assume rho>=0
  257. */
  258. for(i=0;i<n;i++){
  259. if (fabs(v[i])<=rho)
  260. x[i]=0;
  261. else
  262. if (v[i]< -rho)
  263. x[i]=v[i]+rho;
  264. else
  265. x[i]=v[i]-rho;
  266. }
  267. }
  268. void epp2(double *x, double *v, int n, double rho)
  269. {
  270. int i;
  271. double v2=0, ratio;
  272. /*
  273. we assume rho>=0
  274. */
  275. for(i=0; i< n; i++){
  276. v2+=v[i]*v[i];
  277. }
  278. v2=sqrt(v2);
  279. if (rho >= v2)
  280. for(i=0;i<n;i++)
  281. x[i]=0;
  282. else{
  283. ratio= (v2-rho) /v2;
  284. for(i=0;i<n;i++)
  285. x[i]=v[i]*ratio;
  286. }
  287. }
  288. void eppInf(double *x, double * c, int * iter_step, double *v, int n, double rho, double c0)
  289. {
  290. int i, steps;
  291. /*
  292. we assume rho>=0
  293. */
  294. eplb(x, c, &steps, v, n, rho, c0);
  295. for(i=0; i< n; i++){
  296. x[i]=v[i]-x[i];
  297. }
  298. iter_step[0]=steps;
  299. iter_step[1]=0;
  300. }
  301. void zerofind(double *root, int * iterStep, double v, double p, double c, double x0)
  302. {
  303. double x, f, fprime, p1=p-1, pp;
  304. int step=0;
  305. if (v==0){
  306. *root=0; *iterStep=0; return;
  307. }
  308. if (c==0){
  309. *root=v; * iterStep=0; return;
  310. }
  311. if ( (x0 <v) && (x0>0) )
  312. x=x0;
  313. else
  314. x=v;
  315. pp=pow(x, p1);
  316. f= x + c* pp -v;
  317. /*
  318. We apply the Newton's method for solving the root
  319. */
  320. while (1){
  321. step++;
  322. fprime=1 + c* p1 * pp / x;
  323. /*
  324. The derivative at the current solution x
  325. */
  326. x = x- f/fprime; /*
  327. The new solution is computed by the Newton method
  328. */
  329. if (p>2){
  330. if (x>v){
  331. x=v;
  332. }
  333. }
  334. else{
  335. if ( (x<0) || (x>v)){
  336. x=1e-30;
  337. f= x+c* pow(x,p1)-v;
  338. if (f>0){ /*
  339. If f(x) = x + c x^{p-1} - v <0 at x=1e-30,
  340. this shows that the real root is between (0, 1e-30).
  341. For numerical reason, we just set x=0
  342. */
  343. *root=x;
  344. * iterStep=step;
  345. break;
  346. }
  347. }
  348. }
  349. /*
  350. This makes sure that x lies in the interval [0, v]
  351. */
  352. pp=pow(x, p1);
  353. f= x + c* pp -v;
  354. /*
  355. The function value at the new solution
  356. */
  357. if ( fabs(f) <= delta){
  358. *root=x;
  359. * iterStep=step;
  360. break;
  361. }
  362. if (step>=innerIter){
  363. printf("\n The number of steps exceed %d, in finding the root for f(x)= x + c x^{p-1} - v, 0< x< v.", innerIter);
  364. printf("\n If you meet with this problem, please contact Jun Liu (j.liu@asu.edu). Thanks!");
  365. return;
  366. }
  367. }
  368. /*
  369. printf("\n x=%e, f=%e, step=%d\n",x, f, step);
  370. */
  371. }
  372. double norm(double * v, double p, int n)
  373. {
  374. int i;
  375. double t=0;
  376. /*
  377. we assume that v[i]>=0
  378. p>1
  379. */
  380. for(i=0;i<n;i++)
  381. t+=pow(v[i], p);
  382. return( pow(t, 1/p) );
  383. };
  384. void eppO(double *x, double * cc, int * iter_step, double *v, int n, double rho, double p)
  385. {
  386. int i, *flag, bisStep, newtonStep=0, totoalStep=0;
  387. double vq=0, epsilon, vmax=0, vmin=1e10; /* we assume that the minimal value in |v| is less than 1e10*/
  388. double q=1/(1-1/p), c, c1, c2, root, f, xp;
  389. double x_diff=0; /* this value denotes the maximal difference of the x values computed from c1 and c2*/
  390. double temp;
  391. int p_n=1; /* p_n indicates the previous phi(c) is positive or negative*/
  392. flag=(int *)malloc(sizeof(int)*n);
  393. /*
  394. compute vq, the q-norm of v
  395. flag denotes the sign of v:
  396. flag[i]=0 denotes v[i] is non-negative
  397. flag[i]=1 denotes v[i] is negative
  398. vmin and vmax are the maximal and minimal value of |v| (excluding 0)
  399. */
  400. for(i=0; i< n; i++){
  401. x[i]=0;
  402. if (v[i]==0)
  403. flag[i]=0;
  404. else
  405. {
  406. if (v[i]>0)
  407. flag[i]=0;
  408. else
  409. {
  410. flag[i]=1;
  411. v[i]=-v[i];/*
  412. we set v[i] to its absolute value
  413. */
  414. }
  415. vq+=pow(v[i], q);
  416. if (v[i]>vmax)
  417. vmax=v[i];
  418. if (v[i]<vmin)
  419. vmin=v[i];
  420. }
  421. }
  422. vq=pow(vq, 1/q);
  423. /*
  424. zero solution
  425. */
  426. if (rho >= vq){
  427. *cc=0;
  428. iter_step[0]=iter_step[1]=0;
  429. for(i=0;i<n;i++){
  430. if (flag[i])
  431. v[i]=-v[i]; /* set the value of v[i] back*/
  432. }
  433. free(flag);
  434. return;
  435. }
  436. /*
  437. compute epsilon
  438. initialize c1 and c2, the interval where the root lies
  439. */
  440. epsilon=(vq -rho)/ vq;
  441. if (p>2){
  442. if ( log((1-epsilon) * vmin) - (p-1) * log( epsilon* vmin ) >= 709 )
  443. {
  444. /* If this contition holds, we have c2 >= 1e308, exceeding the machine precision.
  445. In this case, the reason is that p is too large
  446. and meanwhile epsilon * vmin is typically small.
  447. For numerical stablity, we just regard p=inf, and run eppInf
  448. */
  449. for(i=0;i<n;i++){
  450. if (flag[i])
  451. v[i]=-v[i]; /* set the value of v[i] back*/
  452. }
  453. eppInf(x, cc, iter_step, v, n, rho, 0);
  454. free(flag);
  455. return;
  456. }
  457. c1= (1-epsilon) * vmax / pow(epsilon* vmax, p-1);
  458. c2= (1-epsilon) * vmin / pow(epsilon* vmin, p-1);
  459. }
  460. else{ /*1 < p < 2*/
  461. c2= (1-epsilon) * vmax / pow(epsilon* vmax, p-1);
  462. c1= (1-epsilon) * vmin / pow(epsilon* vmin, p-1);
  463. }
  464. /*
  465. printf("\n c1=%e, c2=%e", c1, c2);
  466. */
  467. if (fabs(c1-c2) <= delta){
  468. c=c1;
  469. }
  470. else
  471. c=(c1+c2)/2;
  472. bisStep =0;
  473. while(1){
  474. bisStep++;
  475. /*compute the root corresponding to c*/
  476. x_diff=0;
  477. for(i=0;i<n;i++){
  478. zerofind(&root, &newtonStep, v[i], p, c, x[i]);
  479. temp=fabs(root-x[i]);
  480. if (x_diff< temp )
  481. x_diff=temp; /*x_diff denotes the largest gap to the previous solution*/
  482. x[i]=root;
  483. totoalStep+=newtonStep;
  484. }
  485. xp=norm(x, p, n);
  486. f=rho * pow(xp, 1-p) - c;
  487. if ( fabs(f)<=delta || fabs(c1-c2)<=delta )
  488. break;
  489. else{
  490. if (f>0){
  491. if ( (x_diff <=delta) && (p_n==0) )
  492. break;
  493. c1=c; p_n=1;
  494. }
  495. else{
  496. if ( (x_diff <=delta) && (p_n==1) )
  497. break;
  498. c2=c; p_n=0;
  499. }
  500. }
  501. c=(c1+c2)/2;
  502. if (bisStep>=outerIter){
  503. if ( fabs(c1-c2) <=delta * c2 )
  504. break;
  505. else{
  506. printf("\n The number of bisection steps exceed %d.", outerIter);
  507. printf("\n c1=%e, c2=%e, x_diff=%e, f=%e",c1,c2,x_diff,f);
  508. printf("\n If you meet with this problem, please contact Jun Liu (j.liu@asu.edu). Thanks!");
  509. return;
  510. }
  511. }
  512. /*
  513. printf("\n c1=%e, c2=%e, f=%e, newtonStep=%d", c1, c2, f, newtonStep);
  514. */
  515. }
  516. /*
  517. printf("\n c1=%e, c2=%e, x_diff=%e, f=%e, bisStep=%d, totoalStep=%d",c1,c2, x_diff, f,bisStep,totoalStep);
  518. */
  519. for(i=0;i<n;i++){
  520. if (flag[i]){
  521. x[i]=-x[i];
  522. v[i]=-v[i];
  523. }
  524. }
  525. free(flag);
  526. *cc=c;
  527. iter_step[0]=bisStep;
  528. iter_step[1]=totoalStep;
  529. }
  530. void epp(double *x, double * c, int * iter_step, double * v, int n, double rho, double p, double c0){
  531. if (rho <0){
  532. printf("\n rho should be non-negative!");
  533. exit(1);
  534. }
  535. if (p==1){
  536. epp1(x, v, n, rho);
  537. *c=0;
  538. iter_step[0]=iter_step[1]=0;
  539. }
  540. else
  541. if (p==2){
  542. epp2(x, v, n, rho);
  543. *c=0;
  544. iter_step[0]=iter_step[1]=0;
  545. }
  546. else
  547. if (p>=1e6) /* when p >=1e6, we treat it as infity*/
  548. eppInf(x, c, iter_step, v, n, rho, c0);
  549. else
  550. eppO(x, c, iter_step, v, n, rho, p);
  551. }