PLearn 0.1
MatlabInterface.cc
Go to the documentation of this file.
00001 // PLearn (A C++ Machine Learning Library)
00002 // Copyright (C) 1998 Pascal Vincent
00003 // Copyright (C) 1999-2002 Pascal Vincent, Yoshua Bengio and University of Montreal
00004 //
00005 
00006 // Redistribution and use in source and binary forms, with or without
00007 // modification, are permitted provided that the following conditions are met:
00008 // 
00009 //  1. Redistributions of source code must retain the above copyright
00010 //     notice, this list of conditions and the following disclaimer.
00011 // 
00012 //  2. Redistributions in binary form must reproduce the above copyright
00013 //     notice, this list of conditions and the following disclaimer in the
00014 //     documentation and/or other materials provided with the distribution.
00015 // 
00016 //  3. The name of the authors may not be used to endorse or promote
00017 //     products derived from this software without specific prior written
00018 //     permission.
00019 // 
00020 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
00021 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00022 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
00023 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00024 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00025 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00026 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00027 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00028 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00029 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030 // 
00031 // This file is part of the PLearn library. For more information on the PLearn
00032 // library, go to the PLearn Web site at www.plearn.org
00033 
00034 
00035 
00036 
00037 /* *******************************************************
00038    * $Id: MatlabInterface.cc 5176 2006-03-13 22:40:51Z lamblin $
00039    * AUTHORS: Christian Jauvin
00040    * This file is part of the PLearn library.
00041    ******************************************************* */
00042 
00043 #include "MatlabInterface.h"
00044 #include <plearn/io/TypesNumeriques.h> 
00045 #include <plearn/io/TmpFilenames.h>
00046 
00047 namespace PLearn {
00048 using namespace std;
00049 
00050 
00051 /*
00052 MatlabInterface::MatlabInterface(string the_matlab_file, string the_id, 
00053                                  bool the_launch_in_background, bool the_erase_tmp_files)
00054 {
00055   matlab_file_header = "";
00056   matlab_file = the_matlab_file;
00057   id = the_id;
00058   launch_in_background = the_launch_in_background;
00059   erase_tmp_files = the_erase_tmp_files;
00060 }
00061 */
00062 
00063 MatlabInterface::MatlabInterface(string the_matlab_file_header, string the_matlab_file, string the_id,
00064                                  bool the_launch_in_background, bool the_erase_tmp_files)
00065 {
00066   matlab_file_header = the_matlab_file_header;
00067   matlab_file = the_matlab_file;
00068   id = the_id;
00069   launch_in_background = the_launch_in_background;
00070   erase_tmp_files = the_erase_tmp_files;
00071 }
00072 
00073 MatlabInterface::MatlabInterface(vector<string> the_matlab_file_header, string the_matlab_file, string the_id,
00074                                  bool the_launch_in_background, bool the_erase_tmp_files)
00075 {
00076   for (unsigned int i = 0; i < the_matlab_file_header.size(); i++)
00077     matlab_file_header += (the_matlab_file_header[i] + "\n");
00078   id = the_id;
00079   matlab_file = the_matlab_file;
00080   launch_in_background = the_launch_in_background;
00081   erase_tmp_files = the_erase_tmp_files;
00082 }
00083 
00084 Popen* MatlabInterface::launch()
00085 {
00086   if (id == "")
00087   {
00088     id = newFilename("", "");
00089     unlink(id.c_str());
00090   }
00091   string tmp_matlab_file = id + ".m";
00092   ofstream tmp_out(tmp_matlab_file.c_str());
00093   tmp_out << matlab_file_header << endl;
00094   if (matlab_file != "")
00095   {
00096     string cat_command = "cat " + matlab_file + " >> " + tmp_matlab_file;
00097     system(cat_command.c_str());
00098   }
00099   string matlab_command = "matlab -nodisplay -nojvm < " + tmp_matlab_file + "";
00100   if (launch_in_background)
00101     matlab_command += " &";
00102   // Launch Matlab
00103   matlab = new Popen(matlab_command);
00104   return matlab;  
00105 }
00106 
00107 bool MatlabInterface::launchAndWaitFor(string matlab_end_answer)
00108 {
00109   if (id == "")
00110   {
00111     id = newFilename("", "");
00112     unlink(id.c_str());
00113   }
00114   string tmp_matlab_file = id + ".m";
00115   ofstream tmp_out(tmp_matlab_file.c_str());
00116   tmp_out << matlab_file_header << endl;
00117   if (matlab_file != "")
00118   {
00119     string cat_command = "cat " + matlab_file + " >> " + tmp_matlab_file;
00120     system(cat_command.c_str());
00121   }
00122   string matlab_command = "matlab -nodisplay -nojvm < " + tmp_matlab_file + "";
00123   if (launch_in_background)
00124     matlab_command += " &";
00125   // Launch Matlab
00126   matlab = new Popen(matlab_command);
00127 
00128   // Wait until Matlab outputs 'matlab_end_answer'
00129   string matlab_answer;
00130   do
00131   {
00132     matlab->in >> matlab_answer;
00133     if (0)
00134       cout << matlab_answer << endl;
00135   } while (!matlab->in.eof() && matlab_answer != matlab_end_answer 
00136            && matlab_answer.find("???",0)==string::npos);
00137   if (matlab_answer != matlab_end_answer)
00138     return false;
00139   if (erase_tmp_files)
00140     unlink(tmp_matlab_file.c_str());
00141   return true;
00142 }
00143 
00144 void matlabR11eigs(RowMapSparseMatrix<real>& A, Mat eigen_vectors, 
00145                    Vec eigen_values, string which_eigenvalues)
00146 {
00147   bool get_evectors = eigen_vectors.length()>0;
00148   TmpFilenames tmpfilename(1);
00149   //string Afile = tmpfilename.addFilename("/tmp/","A",".ijv");
00150 
00151   //Temporary workaround!
00152   string Afile = tmpfilename.addFilename("/tmp/","A");
00153   unlink(Afile.c_str());
00154   Afile += ".ijv";
00155 
00156   A.exportToMatlabReadableFormat(Afile);
00157   string Afile_noext = remove_extension(Afile);
00158   string evec_file = Afile_noext + "_evec.dat";
00159   string eval_file = Afile_noext + "_eval.dat";
00160   string Aname = extract_filename(Afile_noext);
00161   vector<string> header;
00162   // that's where we expect to find eigs_r11.m
00163   header.push_back("path(path,'"+MatlabInterface::path()+"')");
00164   header.push_back("load " + Afile + ";");
00165   // convert to matlab sparse format
00166   header.push_back("M = spconvert(" + Aname + ");");
00167   header.push_back("options.disp=0; options.isreal=1; options.issym = 1;");
00168   header.push_back("d = " + tostring(eigen_values.length()) + ";");
00169   if (!looksNumeric(which_eigenvalues.c_str()))
00170     which_eigenvalues = "'" + which_eigenvalues + "'";
00171   // call eigs_r11
00172   if (get_evectors)
00173   {
00174     header.push_back("[Evec, Eval] = eigs_r11(M,d,"+which_eigenvalues+",options);");
00175     header.push_back("Evec = Evec';");
00176     header.push_back("save " + evec_file + " Evec -ascii -double;");
00177   }
00178   else
00179     header.push_back("Eval = eigs_r11(M, d, "+which_eigenvalues+", options);");
00180   header.push_back("Eval = diag(Eval);");
00181   header.push_back("save " + eval_file + " Eval -ascii -double;");
00182   header.push_back("fprintf(1, 'done ');");
00183   header.push_back("fprintf(1, '%d ',size(Eval));");
00184   header.push_back("quit");
00185   
00186   MatlabInterface matlab(header,"",Afile_noext,false,false);
00187   bool successful = matlab.launchAndWaitFor("done");
00188   if (!successful)
00189     PLERROR("matlabR11eigs: call to matlab was not successful, executing: %s",
00190           matlab.matlab_file_header.c_str());
00191   // get actual number of e-values found
00192   int actual_n_eval;
00193   string answer;
00194   // matlab.matlab->in >> actual_n_eval;
00195   matlab.matlab->in >> answer;
00196   if (answer==">>")
00197     matlab.matlab->in >> answer;
00198   if (!looksNumeric(answer.c_str()))
00199     PLERROR("matlabR11eigs: expected nb of eigenvalues, got %s",answer.c_str());
00200   actual_n_eval=toint(answer);
00201   if (actual_n_eval<eigen_values.length())
00202   {
00203     PLWARNING("matlabR11eigs: found %d e-values out of %d required",
00204             actual_n_eval,eigen_values.length());
00205     eigen_values.resize(actual_n_eval);
00206     if (get_evectors)
00207       eigen_vectors.resize(actual_n_eval,A.length());
00208   }
00209   // get results
00210   loadAsciiWithoutSize(eval_file, eigen_values);
00211   if (get_evectors)
00212     loadAsciiWithoutSize(evec_file, eigen_vectors);
00213   unlink(Afile.c_str());
00214   unlink(eval_file.c_str());
00215   unlink(evec_file.c_str());
00216 }
00217 
00218 void MatlabInterface::eigs_r11(RowMapSparseMatrix<real>& A, Mat& evectors, Vec& evalues, 
00219                                int d, string which_eigenvalues, bool erase_tmp_files)
00220 {
00221   string id = newFilename("", "");
00222   unlink(id.c_str());
00223   string A_file = "A_" + id + ".ijv";
00224   A.exportToMatlabReadableFormat(A_file);
00225   string A_file_noext = remove_extension(A_file);
00226   string evec_file = A_file_noext + "_evec.dat";
00227   string eval_file = A_file_noext + "_eval.dat";
00228   vector<string> header;
00229   // that's where we expect to find eigs_r11.m
00230   header.push_back("path(path, '"+MatlabInterface::path()+"')");
00231   header.push_back("load " + A_file + ";");
00232   // convert to matlab sparse format
00233   header.push_back("M = spconvert(" + A_file_noext + ");");
00234   header.push_back("options.disp = 0; options.isreal = 1; options.issym = 1;");
00235   header.push_back("d = " + tostring(d) + ";");
00236   if (!looksNumeric(which_eigenvalues.c_str()))
00237     which_eigenvalues = "'" + which_eigenvalues + "'";
00238   header.push_back("[Evec, Eval] = eigs_r11(M, d, "+which_eigenvalues+", options);");
00239   header.push_back("Evec = Evec';");
00240   header.push_back("save " + evec_file + " Evec -ascii -double;");
00241   header.push_back("Eval = diag(Eval);");
00242   header.push_back("save " + eval_file + " Eval -ascii -double;");
00243   header.push_back("fprintf(1, 'done ');");
00244   header.push_back("fprintf(1, '%d ',size(Eval));");
00245   header.push_back("quit");
00246   
00247   MatlabInterface matlab(header, "", id, false, erase_tmp_files);
00248   bool successful = matlab.launchAndWaitFor("done");
00249   if (!successful)
00250     PLERROR("eigs_r11: call to matlab was not successful, executing: %s",
00251           matlab.matlab_file_header.c_str());
00252   // get actual number of e-values found
00253   int actual_n_eval;
00254   string answer;
00255   // matlab.matlab->in >> actual_n_eval;
00256   matlab.matlab->in >> answer;
00257   if (answer==">>")
00258     matlab.matlab->in >> answer;
00259   if (!looksNumeric(answer.c_str()))
00260     PLERROR("eigs_r11: expected nb of eigenvalues, got %s",answer.c_str());
00261   actual_n_eval=toint(answer);
00262   evalues.resize(actual_n_eval);
00263   evectors.resize(actual_n_eval, A.length());
00264   //evectors.resize(A.length(), actual_n_eval);
00265   if (actual_n_eval < d)
00266     PLWARNING("matlabR11eigs: found %d e-values out of %d required",
00267             actual_n_eval, d);
00268   // get results
00269   loadAsciiWithoutSize(eval_file, evalues);
00270   loadAsciiWithoutSize(evec_file, evectors);
00271   if (erase_tmp_files)
00272   {
00273     unlink(A_file.c_str());
00274     unlink(eval_file.c_str());
00275     unlink(evec_file.c_str());
00276   }
00277 }
00278 
00279 void MatlabInterface::eigs_r11(RowMapSparseMatrix<real>& A, Mat& evectors, 
00280                                int d, string which_eigenvalues, bool erase_tmp_files)
00281 {
00282   string id = newFilename("", "");
00283   unlink(id.c_str());
00284   string A_file = "A_" + id + ".ijv";
00285   A.exportToMatlabReadableFormat(A_file);
00286   string A_file_noext = remove_extension(A_file);
00287   string evec_file = A_file_noext + "_evec.dat";
00288   vector<string> header;
00289   // that's where we expect to find eigs_r11.m
00290   header.push_back("path(path, '"+MatlabInterface::path()+"')");
00291   header.push_back("load " + A_file + ";");
00292   // convert to matlab sparse format
00293   header.push_back("M = spconvert(" + A_file_noext + ");");
00294   header.push_back("options.disp = 0; options.isreal = 1; options.issym = 1;");
00295   header.push_back("d = " + tostring(d) + ";");
00296   if (!looksNumeric(which_eigenvalues.c_str()))
00297     which_eigenvalues = "'" + which_eigenvalues + "'";
00298   header.push_back("[Evec, Eval] = eigs_r11(M, d, "+which_eigenvalues+", options);");
00299   //header.push_back("Evec = Evec';");
00300   header.push_back("save " + evec_file + " Evec -ascii -double;");
00301   header.push_back("fprintf(1, 'done ');");
00302   header.push_back("fprintf(1, '%d ', size(Eval));");
00303   header.push_back("quit");
00304   
00305   MatlabInterface matlab(header, "", id, false, erase_tmp_files);
00306   bool successful = matlab.launchAndWaitFor("done");
00307   if (!successful)
00308     PLERROR("eigs_r11: call to matlab was not successful, executing: %s",
00309           matlab.matlab_file_header.c_str());
00310   // get actual number of e-values found
00311   int actual_n_eval;
00312   string answer;
00313   // matlab.matlab->in >> actual_n_eval;
00314   matlab.matlab->in >> answer;
00315   if (answer==">>")
00316     matlab.matlab->in >> answer;
00317   if (!looksNumeric(answer.c_str()))
00318     PLERROR("eigs_r11: expected nb of eigenvalues, got %s",answer.c_str());
00319   actual_n_eval=toint(answer);
00320   evectors.resize(A.length(), actual_n_eval);
00321   //evectors.resize(actual_n_eval, A.length());
00322   if (actual_n_eval < d)
00323     PLWARNING("matlabR11eigs: found %d e-values out of %d required",
00324             actual_n_eval, d);
00325   // get results
00326   loadAsciiWithoutSize(evec_file, evectors);
00327   if (erase_tmp_files)
00328   {
00329     unlink(A_file.c_str());
00330     unlink(evec_file.c_str());
00331   }
00332 }
00333 
00334 void MatlabInterface::eigs_r11(RowMapSparseMatrix<real>& A, Vec& evalues, 
00335                                int d, string which_eigenvalues, bool erase_tmp_files)
00336 {
00337   string id = newFilename("", "");
00338   unlink(id.c_str());
00339   string A_file = "A_" + id + ".ijv";
00340   A.exportToMatlabReadableFormat(A_file);
00341   string A_file_noext = remove_extension(A_file);
00342   string eval_file = A_file_noext + "_eval.dat";
00343   vector<string> header;
00344   // that's where we expect to find eigs_r11.m
00345   header.push_back("path(path, '"+MatlabInterface::path()+"')");
00346   header.push_back("load " + A_file + ";");
00347   // convert to matlab sparse format
00348   header.push_back("M = spconvert(" + A_file_noext + ");");
00349   header.push_back("options.disp = 0; options.isreal = 1; options.issym = 1;");
00350   header.push_back("d = " + tostring(d) + ";");
00351   if (!looksNumeric(which_eigenvalues.c_str()))
00352     which_eigenvalues = "'" + which_eigenvalues + "'";
00353   header.push_back("Eval = eigs_r11(M, d, "+which_eigenvalues+", options);");
00354   header.push_back("Eval = diag(Eval);");
00355   header.push_back("save " + eval_file + " Eval -ascii -double;");
00356   header.push_back("fprintf(1, 'done ');");
00357   header.push_back("fprintf(1, '%d ', size(Eval));");
00358   header.push_back("quit");
00359   
00360   MatlabInterface matlab(header, "", id, false, erase_tmp_files);
00361   bool successful = matlab.launchAndWaitFor("done");
00362   if (!successful)
00363     PLERROR("eigs_r11: call to matlab was not successful, executing: %s",
00364           matlab.matlab_file_header.c_str());
00365   // get actual number of e-values found
00366   int actual_n_eval;
00367   string answer;
00368   // matlab.matlab->in >> actual_n_eval;
00369   matlab.matlab->in >> answer;
00370   if (answer==">>")
00371     matlab.matlab->in >> answer;
00372   if (!looksNumeric(answer.c_str()))
00373     PLERROR("eigs_r11: expected nb of eigenvalues, got %s",answer.c_str());
00374   actual_n_eval=toint(answer);
00375   evalues.resize(actual_n_eval);
00376   if (actual_n_eval < d)
00377     PLWARNING("matlabR11eigs: found %d e-values out of %d required",
00378             actual_n_eval, d);
00379   // get results
00380   loadAsciiWithoutSize(eval_file, evalues);
00381   if (erase_tmp_files)
00382   {
00383     unlink(A_file.c_str());
00384     unlink(eval_file.c_str());
00385   }
00386 }
00387 
00388 
00389 
00390 } // end of namespace PLearn
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines