SHOGUN  v2.0.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
invCov.cpp
Go to the documentation of this file.
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 
18 
19 void m_Ax(double *Ax, double *A, double *x, int n, int ith)
20 {
21  int i, j;
22  double t;
23  for(i=0;i<n;i++){
24  if (i==ith)
25  continue;
26  t=0;
27  for(j=0;j<n;j++){
28  if (j==ith)
29  continue;
30  t+=A[i*n+j]* x[j];
31  Ax[i]=t;
32  }
33  }
34 }
35 
36 
37 int lassoCD(double *Theta, double *W, double *S, double lambda, int n, int ith, int flag, int maxIter, double fGap, double xGap)
38 {
39  int iter_step, i,j;
40  double * Ax, * x;
41  double u, v, s_v, t=0, x_new;
42  double fun_new,fun_old=-100;
43  double x_change;
44 
45  Ax= (double *)malloc(sizeof(double)*n);
46  x= (double *)malloc(sizeof(double)*n);
47 
48 
49  if ( (Ax==NULL) || (x==NULL) ){
50  printf("\n Memory allocation failure!");
51  return (-1);
52  }
53 
54  /* give x an intialized value, from previously Theta*/
55  for(i=0;i<n;i++){
56  if (i==ith)
57  continue;
58  x[i]=Theta[i*n+ith];
59  }
60 
61  /* Ax contains the derivative*/
62  m_Ax(Ax, W, x, n, ith);
63 
64  for (iter_step=0;iter_step<maxIter; iter_step++){
65 
66  /*printf("\n Iter: %d",iter_step);*/
67 
68  x_change=0;
69 
70  for (i=0;i<n;i++){
71  if(i==ith)
72  continue;
73 
74  u=W[i*n + i];
75 
76  v=Ax[i]-x[i]*u;
77 
78  s_v=S[i*n+ ith]-v;
79 
80  if(s_v > lambda)
81  x_new= (s_v-lambda) / u;
82  else{
83  if(s_v < -lambda)
84  x_new= (s_v + lambda) / u;
85  else
86  x_new=0;
87  }
88  if (x[i]!=x_new){
89  for(j=0;j<n;j++){
90  if (j==ith)
91  continue;
92  Ax[j]+= W[j*n+ i]*(x_new - x[i]);
93  }
94  x_change+=fabs(x[i]-x_new);
95 
96  x[i]=x_new;
97  }
98  }
99 
100  fun_new=0;
101  t=0;
102  for(i=0;i<n;i++){
103  if (i==ith)
104  continue;
105  t+= Ax[i]*x[i] ;
106  fun_new+=- S[i*n+ith]*x[i]+ lambda* fabs(x[i]);
107  }
108  fun_new+=0.5*t;
109 
110 
111  /*
112  the Lasso terminates either
113  the change of the function value is less than fGap
114  or the change of the solution in terms of L1 norm is less than xGap
115  or the maximal iteration maxIter has achieved
116  */
117  if ( (fabs(fun_new-fun_old) <=fGap) || x_change <=xGap){
118  /*printf("\n %d, Fun value: %2.5f",iter_step, fun_new);
119  printf("\n The objective gap between adjacent solutions is less than %e",1e-6);
120  */
121  break;
122  }
123  else{
124  /*
125  if(iter_step%10 ==0)
126  printf("\n %d, Fun value: %2.5f",iter_step, fun_new);
127  */
128  fun_old=fun_new;
129  }
130  }
131 
132  /*printf("\n %d, Fun value: %2.5f",iter_step, fun_new);*/
133 
134  if (flag){
135  t=1/(W[ith*n+ith]-t);
136  Theta[ith*n + ith]=t;
137 
138  for(i=0;i<n;i++){
139  if (i==ith)
140  continue;
141  W[i*n+ ith]=W[ith*n +i]=Ax[i];
142  Theta[i*n+ ith]=Theta[ith*n +i]=-x[i]*t;
143  }
144  }
145  else{
146  for(i=0;i<n;i++){
147  if (i==ith)
148  continue;
149  W[i*n+ ith]=W[ith*n +i]=Ax[i];
150  Theta[i*n+ ith]=Theta[ith*n +i]=x[i];
151  }
152  }
153 
154 
155  free(Ax); free(x);
156 
157  return(iter_step);
158 }
159 
160 
161 void invCov(double *Theta, double *W, double *S, double lambda, double sum_S, int n,
162  int LassoMaxIter, double fGap, double xGap, /*for the Lasso (inner iteration)*/
163  int maxIter, double xtol) /*for the outer iteration*/
164 {
165  int iter_step, i,j, ith;
166  double * W_old;
167  double gap;
168  int flag=0;
169 
170  W_old= (double *)malloc(sizeof(double)*n*n);
171 
172 
173  if ( W_old==NULL ){
174  printf("\n Memory allocation failure!");
175  exit (-1);
176  }
177 
178  for(i=0;i<n;i++)
179  for(j=0;j<n;j++){
180  if (i==j)
181  W_old[i*n+j]=W[i*n+j]=S[i*n+j]+lambda;
182  else
183  W_old[i*n+j]=W[i*n+j]=S[i*n+j];
184 
185  Theta[i*n+j]=0;
186  }
187 
188  for (iter_step=0;iter_step<=maxIter; iter_step++){
189  for(ith=0;ith<n;ith++)
190  lassoCD(Theta, W, S, lambda, n, ith, flag, LassoMaxIter,fGap, xGap);
191 
192  if (flag)
193  break;
194 
195  gap=0;
196  for(i=0;i<n;i++)
197  for(j=0;j<n;j++){
198  gap+=fabs(W[i*n+j]-W_old[i*n+j]);
199  W_old[i*n+j]=W[i*n+j];
200  }
201 
202  /* printf("\n Outer Loop: %d, gap %e\n",iter_step,gap); */
203 
204 
205  if ( (gap <= xtol) || (iter_step==maxIter-1) ){
206  flag=1;
207  }
208  /*
209  The outer loop terminates either the difference between ajacent solution in terms of L1 norm is less than xtol,
210  or the maximal iterations has achieved
211  */
212  }
213 
214  free(W_old);
215 
216  /*return (iter_step);*/
217 }
218 

SHOGUN Machine Learning Toolbox - Documentation