From c8a80ec36386bdc69340be8e4d121ec13a0a6d14 Mon Sep 17 00:00:00 2001
From: Christian Beckmann <c.beckmann@donders.ru.nl>
Date: Tue, 12 Aug 2003 17:39:13 +0000
Subject: [PATCH] defl approach modified

---
 melica.cc     | 101 +++++++++++++++++++++++++++++++++++++++++++++-----
 meloptions.cc |   4 +-
 2 files changed, 95 insertions(+), 10 deletions(-)

diff --git a/melica.cc b/melica.cc
index 981e76e..1d5f87d 100644
--- a/melica.cc
+++ b/melica.cc
@@ -121,18 +121,21 @@ namespace Melodic{
      //redUMM = zeros(dim); // got to start somewhere
      redUMM = melodat.get_white()*
        unifrnd(melodat.get_white().Ncols(),opts.numICs.value());
+
+
+     redUMM = zeros(melodat.get_white().Nrows(),opts.numICs.value());
+     Matrix guess;
+
      int guesses=0;
      if(opts.guessfname.value().size()>1){
        message("  Use columns in " << opts.guessfname.value() << " as initial values for the mixing matrix " <<endl);
-       Matrix guess;
        guess  = melodat.get_white()*read_ascii_matrix(opts.guessfname.value());
        guesses = guess.Ncols();
-       redUMM.Columns(1,guesses) = guess;
      }
 
      int ctrIC = 1;
      int numRestart = 0;
-     
+
      while(ctrIC<=opts.numICs.value()){
        
        message("  Extracting IC " << ctrIC << "  ... ");
@@ -140,15 +143,19 @@ namespace Melodic{
        ColumnVector w_old;   
        ColumnVector tmpU;
        if(ctrIC <= guesses){
-	 w = redUMM.Column(ctrIC);}
+	 w = guess.Column(ctrIC);}
        else{
 	 w = unifrnd(dim,1);}
-       
+
        w = w - redUMM * redUMM.t() * w;
        w = w / norm2(w);  
+
+       w_old = zeros(w.Nrows(),1);
+
        int itt_ctr = 1; 
 
        do{
+
 	 w_old = w;
  
 	 tmpU = Data.t() * w;
@@ -185,8 +192,10 @@ namespace Melodic{
 	w = w / norm2(w);  
 
 	//termination condition : angle between old and new < epsilon
-	if(norm2(w-w_old) < opts.epsilon.value() || 
-	   norm2(w+w_old) < opts.epsilon.value()){break;}
+	if((norm2(w-w_old) < 0.001*opts.epsilon.value())&&(itt_ctr>10) || 
+	   (norm2(w+w_old) < 0.001*opts.epsilon.value())&&(itt_ctr>10)){
+	 break;
+	}
         //cout << norm2(w-w_old) << "   " << norm2(w+w_old) << endl;
 	itt_ctr++;
       } while(itt_ctr <= opts.maxNumItt.value());
@@ -223,9 +232,83 @@ namespace Melodic{
 
   void MelodicICA::ica_maxent(const Matrix &Data)
   {
-    cerr << "  Not fully implemented yet " << endl;
-    //     cout << "maxent" <<endl;
+    // based on Aapo Hyvärinen's fastica method
+    // see www.cis.hut.fi/projects/ica/fastica/
+    
+    message(" MAXENT " << endl);
+
+
+    //initialize matrices
+    Matrix redUMM_old;
+    Matrix tmpU;    
+    Matrix gtmpU;
+    double lambda = 0.015/std::log((double)melodat.get_white().Ncols());
+    
+     //srand((unsigned int)timer(NULL));
+    
+    redUMM = melodat.get_white()*
+       unifrnd(melodat.get_white().Ncols(),dim); // got to start somewhere
+    
+    if(opts.guessfname.value().size()>1){
+      message("  Use columns in " << opts.guessfname.value() 
+	      << " as initial values for the mixing matrix " <<endl);
+      Matrix guess ;
+      guess  = melodat.get_white()*read_ascii_matrix(opts.guessfname.value());
+      redUMM.Columns(1,guess.Ncols()) = guess;
+    }
+    
+    //    symm_orth(redUMM);
+
+    int itt_ctr=1; 
+    double minAbsSin = 1.0;
+
+    Matrix Id;
+    Id = Identity(redUMM.Ncols());
+
+    cerr << " nonlinearity : " <<    opts.nonlinearity.value() << endl;
+
+    do{ // da loop!!!
+
+      redUMM_old = redUMM;
+      
+      //calculate IC estimates
+      tmpU = Data.t() * redUMM;
+      
+      if(opts.nonlinearity.value()=="tanh"){
+	//Matrix hyptanh;
+	//hyptanh = tanh(opts.nlconst1.value()*tmpU);
+	//redUMM = (Data * hyptanh - opts.nlconst1.value()*SP(ones(dim,1)*
+	//sum(1-pow(hyptanh,2),1),redUMM))/samples;
+	gtmpU = tanh(opts.nlconst1.value()*tmpU);
+	redUMM = redUMM + lambda*(Id+(1-2*gtmpU.t()*tmpU))*redUMM;
+      }
+      if(opts.nonlinearity.value()=="gauss"){
+	gtmpU = pow(1+exp(-(opts.nlconst2.value()/2) * tmpU),-1);
+	redUMM = redUMM + lambda*(Id - (gtmpU.t()-tmpU.t())*tmpU)*redUMM;
+      }
+      
+      //      redUMM = redUMM +  ( tmpU *tmpU.t()) * redUMM;
+
+      //termination condition : angle between old and new < epsilon
+      minAbsSin = abs(1 - diag(abs(redUMM.t()*redUMM_old)).Minimum());
+      message("  Step no. " << itt_ctr << " change : " << minAbsSin << endl);
+      if(abs(minAbsSin) < opts.epsilon.value()){ break;}
+      
+      itt_ctr++;
+    } while(itt_ctr < opts.maxNumItt.value());
+    
+    if(itt_ctr>=opts.maxNumItt.value()){
+      cerr << "  No convergence after " << itt_ctr <<" steps "<<endl;
+    } else {
+      message("  Convergence after " << itt_ctr <<" steps " << endl << endl);
+      no_convergence = false;
+      {Matrix temp(melodat.get_dewhite() * redUMM);
+       melodat.set_mix(temp);}
+      {Matrix temp(redUMM.t()*melodat.get_white());
+      melodat.set_unmix(temp);}
+    } 
   }
+  
 
 
   void MelodicICA::ica_jade(const Matrix &Data)
diff --git a/meloptions.cc b/meloptions.cc
index 743aa23..cb8719a 100644
--- a/meloptions.cc
+++ b/meloptions.cc
@@ -193,7 +193,7 @@ void MelodicOptions::print_usage(int argc, char *argv[])
 {
   print_version();
   options.usage();
-  /* cout << "Usage: " << argv[0] << " "; 
+  /* cout << "Usage: " << argv[0] << " ";
 
     Have own usage output here
   */
@@ -202,12 +202,14 @@ void MelodicOptions::print_usage(int argc, char *argv[])
 void MelodicOptions::print_version()
 {
   cout << "MELODIC Version " << version;
+  cout.flush();
 }
 
 void MelodicOptions::print_copyright()
 {
   print_version();
   cout << endl << "Copyright (C) 1999-2002 University of Oxford " << endl;
+  cout.flush();
 }
 
 void MelodicOptions::status()
-- 
GitLab