PageRenderTime 50ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/src/shogun/lib/slep/q1/epsp.h

https://code.google.com/
C Header | 300 lines | 192 code | 49 blank | 59 comment | 41 complexity | 0057b41f994d9ef9289ea2d6f4808789 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. #ifndef EPSP_SLEP
  17. #define EPSP_SLEP
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <time.h>
  21. #include <math.h>
  22. #define delta 1e-12
  23. /*
  24. Euclidean Projection onto the simplex (epsp)
  25. min 1/2 ||x- y||_2^2
  26. s.t. ||x||_1 = z, x >=0
  27. which is converted to the following zero finding problem
  28. f(lambda)= sum( max( x-lambda,0) )-z=0
  29. Usage:
  30. [x, lambda, iter_step]=epsp(y, n, z, lambda0);
  31. */
  32. void epsp(double * x, double *root, int * stepsp, double * v,
  33. int n, double z, double lambda0)
  34. {
  35. int i, j, flag=0;
  36. int rho_1, rho_2, rho, rho_T, rho_S;
  37. int V_i_b, V_i_e, V_i;
  38. double lambda_1, lambda_2, lambda_T, lambda_S, lambda;
  39. double s_1, s_2, s, s_T, s_S, v_max, temp;
  40. double f_lambda_1, f_lambda_2, f_lambda, f_lambda_T, f_lambda_S;
  41. int iter_step=0;
  42. if (z< 0){
  43. printf("\n z should be nonnegative!");
  44. exit(-1);
  45. }
  46. /*
  47. * find the maximal value in v
  48. */
  49. v_max=v[0];
  50. for (i=1;i<n; i++){
  51. if (v[i] > v_max)
  52. v_max=v[i];
  53. }
  54. lambda_1=v_max - z; lambda_2=v_max;
  55. /*
  56. * copy v to x
  57. * compute f_lambda_1, rho_1, s_1
  58. */
  59. V_i=0;s_1=0; rho_1=0;
  60. for (i=0;i<n;i++){
  61. if (v[i] > lambda_1){
  62. x[V_i]=v[i];
  63. s_1+=x[V_i]; rho_1++;
  64. V_i++;
  65. }
  66. }
  67. f_lambda_1=s_1-rho_1* lambda_1 -z;
  68. rho_2=0; s_2=0; f_lambda_2=-z;
  69. V_i_b=0; V_i_e=V_i-1;
  70. lambda=lambda0;
  71. if ( (lambda<lambda_2) && (lambda> lambda_1) ){
  72. /*-------------------------------------------------------------------
  73. Initialization with the root
  74. *-------------------------------------------------------------------
  75. */
  76. i=V_i_b; j=V_i_e; rho=0; s=0;
  77. while (i <= j){
  78. while( (i <= V_i_e) && (x[i] <= lambda) ){
  79. i++;
  80. }
  81. while( (j>=V_i_b) && (x[j] > lambda) ){
  82. s+=x[j];
  83. j--;
  84. }
  85. if (i<j){
  86. s+=x[i];
  87. temp=x[i]; x[i]=x[j]; x[j]=temp;
  88. i++; j--;
  89. }
  90. }
  91. rho=V_i_e-j; rho+=rho_2; s+=s_2;
  92. f_lambda=s-rho*lambda-z;
  93. if ( fabs(f_lambda)< delta ){
  94. flag=1;
  95. }
  96. if (f_lambda <0){
  97. lambda_2=lambda; s_2=s; rho_2=rho; f_lambda_2=f_lambda;
  98. V_i_e=j; V_i=V_i_e-V_i_b+1;
  99. }
  100. else{
  101. lambda_1=lambda; rho_1=rho; s_1=s; f_lambda_1=f_lambda;
  102. V_i_b=i; V_i=V_i_e-V_i_b+1;
  103. }
  104. if (V_i==0){
  105. /*printf("\n rho=%d, rho_1=%d, rho_2=%d",rho, rho_1, rho_2);*/
  106. /*printf("\n V_i=%d",V_i);*/
  107. lambda=(s - z)/ rho;
  108. flag=1;
  109. }
  110. /*-------------------------------------------------------------------
  111. End of initialization
  112. *--------------------------------------------------------------------
  113. */
  114. }/* end of if(!flag) */
  115. while (!flag){
  116. iter_step++;
  117. /* compute lambda_T */
  118. lambda_T=lambda_1 + f_lambda_1 /rho_1;
  119. if(rho_2 !=0){
  120. if (lambda_2 + f_lambda_2 /rho_2 > lambda_T)
  121. lambda_T=lambda_2 + f_lambda_2 /rho_2;
  122. }
  123. /* compute lambda_S */
  124. lambda_S=lambda_2 - f_lambda_2 *(lambda_2-lambda_1)/(f_lambda_2-f_lambda_1);
  125. if (fabs(lambda_T-lambda_S) <= delta){
  126. lambda=lambda_T; flag=1;
  127. break;
  128. }
  129. /* set lambda as the middle point of lambda_T and lambda_S */
  130. lambda=(lambda_T+lambda_S)/2;
  131. s_T=s_S=s=0;
  132. rho_T=rho_S=rho=0;
  133. i=V_i_b; j=V_i_e;
  134. while (i <= j){
  135. while( (i <= V_i_e) && (x[i] <= lambda) ){
  136. if (x[i]> lambda_T){
  137. s_T+=x[i]; rho_T++;
  138. }
  139. i++;
  140. }
  141. while( (j>=V_i_b) && (x[j] > lambda) ){
  142. if (x[j] > lambda_S){
  143. s_S+=x[j]; rho_S++;
  144. }
  145. else{
  146. s+=x[j]; rho++;
  147. }
  148. j--;
  149. }
  150. if (i<j){
  151. if (x[i] > lambda_S){
  152. s_S+=x[i]; rho_S++;
  153. }
  154. else{
  155. s+=x[i]; rho++;
  156. }
  157. if (x[j]> lambda_T){
  158. s_T+=x[j]; rho_T++;
  159. }
  160. temp=x[i]; x[i]=x[j]; x[j]=temp;
  161. i++; j--;
  162. }
  163. }
  164. s_S+=s_2; rho_S+=rho_2;
  165. s+=s_S; rho+=rho_S;
  166. s_T+=s; rho_T+=rho;
  167. f_lambda_S=s_S-rho_S*lambda_S-z;
  168. f_lambda=s-rho*lambda-z;
  169. f_lambda_T=s_T-rho_T*lambda_T-z;
  170. /*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);*/
  171. if ( fabs(f_lambda)< delta ){
  172. /*printf("\n lambda");*/
  173. flag=1;
  174. break;
  175. }
  176. if ( fabs(f_lambda_S)< delta ){
  177. /* printf("\n lambda_S");*/
  178. lambda=lambda_S; flag=1;
  179. break;
  180. }
  181. if ( fabs(f_lambda_T)< delta ){
  182. /* printf("\n lambda_T");*/
  183. lambda=lambda_T; flag=1;
  184. break;
  185. }
  186. /*
  187. 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);
  188. printf("\n lambda_1=%5.6f, lambda_2=%5.6f, lambda=%5.6f",lambda_1, lambda_2, lambda);
  189. printf("\n rho_1=%d, rho_2=%d, rho=%d ",rho_1, rho_2, rho);
  190. */
  191. if (f_lambda <0){
  192. lambda_2=lambda; s_2=s; rho_2=rho;
  193. f_lambda_2=f_lambda;
  194. lambda_1=lambda_T; s_1=s_T; rho_1=rho_T;
  195. f_lambda_1=f_lambda_T;
  196. V_i_e=j; i=V_i_b;
  197. while (i <= j){
  198. while( (i <= V_i_e) && (x[i] <= lambda_T) ){
  199. i++;
  200. }
  201. while( (j>=V_i_b) && (x[j] > lambda_T) ){
  202. j--;
  203. }
  204. if (i<j){
  205. x[j]=x[i];
  206. i++; j--;
  207. }
  208. }
  209. V_i_b=i; V_i=V_i_e-V_i_b+1;
  210. }
  211. else{
  212. lambda_1=lambda; s_1=s; rho_1=rho;
  213. f_lambda_1=f_lambda;
  214. lambda_2=lambda_S; s_2=s_S; rho_2=rho_S;
  215. f_lambda_2=f_lambda_S;
  216. V_i_b=i; j=V_i_e;
  217. while (i <= j){
  218. while( (i <= V_i_e) && (x[i] <= lambda_S) ){
  219. i++;
  220. }
  221. while( (j>=V_i_b) && (x[j] > lambda_S) ){
  222. j--;
  223. }
  224. if (i<j){
  225. x[i]=x[j];
  226. i++; j--;
  227. }
  228. }
  229. V_i_e=j; V_i=V_i_e-V_i_b+1;
  230. }
  231. if (V_i==0){
  232. lambda=(s - z)/ rho; flag=1;
  233. /*printf("\n V_i=0, lambda=%5.6f",lambda);*/
  234. break;
  235. }
  236. }/* end of while */
  237. for(i=0;i<n;i++){
  238. if (v[i] > lambda)
  239. x[i]=v[i]-lambda;
  240. else
  241. x[i]=0;
  242. }
  243. *root=lambda;
  244. *stepsp=iter_step;
  245. }
  246. #endif /* ----- #ifndef EPSP_SLEP ----- */