libeblearn
/home/rex/ebltrunk/core/libeblearn/include/ebl_march.hpp
00001 /***************************************************************************
00002  *   Copyright (C) 2011 by Pierre Sermanet *
00003  *   pierre.sermanet@gmail.com *
00004  *   All rights reserved.
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  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Redistribution under a license not approved by the Open Source
00014  *       Initiative (http://www.opensource.org) must display the
00015  *       following acknowledgement in all advertising material:
00016  *        This product includes software developed at the Courant
00017  *        Institute of Mathematical Sciences (http://cims.nyu.edu).
00018  *     * The names of the authors may not be used to endorse or promote products
00019  *       derived from this software without specific prior written permission.
00020  *
00021  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
00022  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00023  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00024  * DISCLAIMED. IN NO EVENT SHALL ThE AUTHORS BE LIABLE FOR ANY
00025  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00026  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00028  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00029  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00030  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031  ***************************************************************************/
00032 
00033 namespace ebl {
00034 
00035   // s2m_module ////////////////////////////////////////////////////////////////
00036 
00037   template <typename T, class Tin, class Tout>
00038   s2m_module<T,Tin,Tout>::s2m_module(uint nstates_, const char *name_)
00039     : module_1_1<T,Tin,Tout>(), _nstates(nstates_) {
00040     this->_name = name_;
00041     // this module takes single-state inputs and multi-state outputs
00042     this->bmstate_input = false;
00043     this->bmstate_output = true;
00044   }
00045 
00046   template <typename T, class Tin, class Tout>
00047   s2m_module<T,Tin,Tout>::~s2m_module() {}
00048 
00049   template <typename T, class Tin, class Tout>
00050   void s2m_module<T,Tin,Tout>::fprop(Tin &in, mstate<Tout> &out) {
00051     eblerror("not implemented");
00052   }
00053 
00054   template <typename T, class Tin, class Tout>
00055   void s2m_module<T,Tin,Tout>::bprop(Tin &in, mstate<Tout> &out) {
00056     eblerror("not implemented");
00057   }
00058 
00059   template <typename T, class Tin, class Tout>
00060   void s2m_module<T,Tin,Tout>::bbprop(Tin &in, mstate<Tout> &out) {
00061     eblerror("not implemented");
00062   }
00063 
00064   template <typename T, class Tin, class Tout>
00065   mfidxdim s2m_module<T,Tin,Tout>::bprop_size(mfidxdim &osize) {
00066     return osize;
00067   }
00068 
00069   template <typename T, class Tin, class Tout>
00070   uint s2m_module<T,Tin,Tout>::nstates() {
00071     return _nstates;
00072   }
00073 
00074   template <typename T, class Tin, class Tout>
00075   void s2m_module<T,Tin,Tout>::resize_output(Tin &in, mstate<Tout> &out,
00076                                              idxdim *d_) {
00077     idxdim d;
00078     if (d_) // use passed dimension to allocate states
00079       d = *d_;
00080     else { // use in's order with minimum dimensions of 1
00081       d = in.x.get_idxdim();
00082       d.setdims(1); // reset all existing dimensions to 1
00083     }
00084     // check we have the right number of states
00085     bool reset = false;
00086     if (out.size() != _nstates)
00087       reset = true;
00088     // check that all states have the right orders
00089     for (uint i = 0; i < out.size() && !reset; ++i) {
00090       Tout &o = out[i];
00091       if (o.x.get_idxdim() != d)
00092         reset = true;
00093     }
00094     // allocate
00095     if (reset) {
00096       out.clear();
00097       for (uint i = 0; i < nstates(); ++i)
00098         out.push_back(new Tin(d));
00099     }
00100   }
00101 
00103   // m2s_module
00104 
00105   template <typename T, class Tin, class Tout>
00106   m2s_module<T,Tin,Tout>::m2s_module(uint nstates_, const char *name_)
00107     : module_1_1<T,Tin,Tout>(), _nstates(nstates_) {
00108     this->_name = name_;
00109     // this module takes multi-state inputs and single-state outputs
00110     this->bmstate_input = true;
00111     this->bmstate_output = false;
00112   }
00113 
00114   template <typename T, class Tin, class Tout>
00115   m2s_module<T,Tin,Tout>::~m2s_module() {}
00116 
00117   template <typename T, class Tin, class Tout>
00118   void m2s_module<T,Tin,Tout>::fprop(mstate<Tin> &in, Tout &out) {
00119     eblerror("not implemented");
00120   }
00121 
00122   template <typename T, class Tin, class Tout>
00123   void m2s_module<T,Tin,Tout>::bprop(mstate<Tin> &in, Tout &out) {
00124     eblerror("not implemented");
00125   }
00126 
00127   template <typename T, class Tin, class Tout>
00128   void m2s_module<T,Tin,Tout>::bbprop(mstate<Tin> &in, Tout &out) {
00129     eblerror("not implemented");
00130   }
00131 
00132   template <typename T, class Tin, class Tout>
00133   mfidxdim m2s_module<T,Tin,Tout>::bprop_size(mfidxdim &osize) {
00134     eblerror("not implemented");
00135     mfidxdim v;
00136     return v;
00137   }
00138 
00139   template <typename T, class Tin, class Tout>
00140   uint m2s_module<T,Tin,Tout>::nstates() {
00141     return _nstates;
00142   }
00143 
00144 
00145   // ms_module /////////////////////////////////////////////////////////////////
00146 
00147   template <typename T, class Tstate>
00148   ms_module<T,Tstate>::ms_module(bool rep_ins, const char *name_)
00149     : module_1_1<T,Tstate>(name_), pipes(), replicate_inputs(rep_ins) {
00150     init();
00151   }
00152 
00153   template <typename T, class Tstate>
00154   ms_module<T,Tstate>::ms_module(module_1_1<T,Tstate> *pipe, uint n,
00155                                  bool rep_ins, const char *name_)
00156     : module_1_1<T,Tstate>(name_), pipes(), replicate_inputs(rep_ins) {
00157     if (!pipe) eblerror("expected non-NULL pipe module");
00158     // replicate pipe
00159     for (uint i = 0; i < n; ++i)
00160       pipes.push_back(pipe);
00161     init();
00162   }
00163 
00164   template <typename T, class Tstate>
00165   ms_module<T,Tstate>::ms_module(std::vector<module_1_1<T,Tstate>*> &pipes_,
00166                                  bool rep_ins, const char *name_)
00167     : module_1_1<T,Tstate>(name_), pipes(pipes_), replicate_inputs(rep_ins) {
00168     if (pipes.size() == 0)
00169       eblerror("expected non-empty vector of pipe modules");
00170     init();
00171   }
00172 
00173   template <typename T, class Tstate>
00174   ms_module<T,Tstate>::~ms_module() {
00175     module_1_1<T,Tstate> *p0 = pipes[0];
00176     if (p0) delete p0;
00177     for (uint i = 1; i < pipes.size(); ++i) {
00178       module_1_1<T,Tstate> *p = pipes[i];
00179       if (p && p != p0) delete p;
00180     }
00181   }
00182 
00183   // multi-multi input/outputs /////////////////////////////////////////////////
00184 
00185   template <typename T, class Tstate>
00186   void ms_module<T,Tstate>::fprop(mstate<Tstate> &in, mstate<Tstate> &out) {
00187     init_fprop(in, out);
00188     EDEBUG(this->name() << ": in " << in << " ins " << ins
00189           << " used_pipes " << used_pipes);
00190     // fprop ins
00191     for (uint i = 0; i < used_pipes.size(); ++i) {
00192       module_1_1<T,Tstate> *p = used_pipes[i];
00193       if (!p) { // no pipe, just pass data along
00194         EDEBUG("fprop empty pipe, just passing input " << ins[i]);
00195         out.push_back(ins[i]);
00196         if (i >= pipes_noutputs.size()) pipes_noutputs.push_back(ins[i].size());
00197         else pipes_noutputs[i] = ins[i].size();
00198       } else {
00199         mstate<Tstate> b;
00200         EDEBUG("fprop " << p->name() << " with input " << ins[i]);
00201         p->fprop(ins[i], b);
00202         out.push_back_new(b);
00203         if (i >= pipes_noutputs.size()) pipes_noutputs.push_back(b.size());
00204         else pipes_noutputs[i] = b.size();
00205         EDEBUG(p->name() << " in " << ins[i] << " out " << b);
00206       }
00207       EDEBUG(this->name() << ": current outputs: " << out);
00208       // TODO: code below reuses buffers but is a problem when this module
00209       // is called multiple times, effectively erasing previous results
00210       // -> question: is code above slow? if not, remove this block.
00211       // used_pipes[i]->fprop(ins[i], mbuffers[i]);
00212       // out.push_back(mbuffers[i]);
00213       // pipes_noutputs[i] = mbuffers[i].size();
00214     }
00215     // remember number of outputs
00216     this->noutputs = out.size();
00217     EDEBUG(this->name() << ": " << in << " -> " << out);
00218   }
00219 
00220   template <typename T, class Tstate>
00221   void ms_module<T,Tstate>::bprop(mstate<Tstate> &in, mstate<Tstate> &out) {
00222     uint off = out.size();
00223     for (int i = (int) used_pipes.size() - 1; i >= 0; --i) {
00224       module_1_1<T,Tstate> *p = used_pipes[i];
00225       off -= pipes_noutputs[i];
00226       if (!p) { // no pipe, just pass data along
00227         EDEBUG("bprop empty pipe doing nothing.");
00228       } else {
00229         mstate<Tstate> b = out.narrow(pipes_noutputs[i], (uint) off);
00230         EDEBUG("bprop " << p->name() << " in " << ins[i] << " out " << b);
00231         p->bprop(ins[i], b);
00232       }
00233     }
00234       //used_pipes[i]->bprop(ins[i], out[i]);
00235     //      used_pipes[i]->bprop(ins[i], mbuffers[i]);
00236   }
00237 
00238   template <typename T, class Tstate>
00239   void ms_module<T,Tstate>::bbprop(mstate<Tstate> &in, mstate<Tstate> &out) {
00240     int off = out.size();
00241     for (int i = (int) used_pipes.size() - 1; i >= 0; --i) {
00242       module_1_1<T,Tstate> *p = used_pipes[i];
00243       off -= pipes_noutputs[i];
00244       if (!p) { // no pipe, just pass data along
00245         EDEBUG("bbprop empty pipe doing nothing.");
00246       } else {
00247         mstate<Tstate> b = out.narrow(pipes_noutputs[i], (uint) off);
00248         p->bbprop(ins[i], b);
00249       }
00250     }
00251     //used_pipes[i]->bbprop(ins[i], out[i]);
00252     //      used_pipes[i]->bbprop(ins[i], mbuffers[i]);
00253   }
00254 
00255   template <typename T, class Tstate>
00256   void ms_module<T,Tstate>::dump_fprop(mstate<Tstate> &in, mstate<Tstate> &out){
00257     // remember number of input
00258     this->ninputs = in.size();
00259     ins.clear();
00260     out.clear();
00261     // replicate input states if only 1 state but multiple pipes
00262     // or if manually requested with replicate_inputs
00263     if ((in.size() == 1 && pipes.size() > 1) || replicate_inputs)
00264       for (uint i = 0; i < pipes.size(); ++i) ins.push_back(in);
00265     else ins.push_back(in); // just feed in to pipes
00266     EDEBUG("input " << in << " -> " << ins << " in " << this->name());
00267     // allocate buffers
00268     if (pipes.size() > 0) mbuffers.resize_default(pipes.size());
00269     // fprop ins
00270     for (uint i = 0; i < pipes.size(); ++i) {
00271       pipes[i]->dump_fprop(ins[i], mbuffers[i]);
00272       out.push_back(mbuffers[i]);
00273     }
00274     // remember number of outputs
00275     this->noutputs = out.size();
00276     EDEBUG(this->name() << ": " << in << " -> " << out);
00277   }
00278 
00279   // forget methods ////////////////////////////////////////////////////////////
00280 
00281   template <typename T, class Tstate>
00282   void ms_module<T,Tstate>::forget(forget_param_linear& fp) {
00283     for (uint i = 0; i < pipes.size(); ++i)
00284       if (pipes[i]) pipes[i]->forget(fp);
00285   }
00286 
00288 
00289   template <typename T, class Tstate>
00290   fidxdim ms_module<T,Tstate>::fprop_size(fidxdim &isize) {
00291     fidxdim d = isize;
00292     // use 1st pipe as base size
00293     module_1_1<T,Tstate> *p0 = pipes[0];
00294     d = p0->fprop_size(d);
00295     return d;
00296   }
00297 
00298   template <typename T, class Tstate>
00299   mfidxdim ms_module<T,Tstate>::fprop_size(mfidxdim &isize) {
00300     this->ninputs = isize.size();
00301     mfidxdim osize;
00302     for (uint i = 0; i < pipes.size(); ++i) {
00303       mfidxdim o;
00304       if (replicate_inputs || (isize.size() == 1 && pipes.size() > 1))
00305         o = isize;
00306       else {
00307         if (isize.exists(i)) o.push_back(isize[i]);
00308         else o.push_back_empty();
00309       }
00310       if (pipes[i]) o = pipes[i]->fprop_size(o);
00311       osize.push_back_new(o);
00312     }
00313     this->noutputs = osize.size();
00314     EDEBUG(this->name() << " (" << this->noutputs << " outputs): "
00315           << isize << " f-> " << osize);
00316     return osize;
00317   }
00318 
00319   template <typename T, class Tstate>
00320   fidxdim ms_module<T,Tstate>::bprop_size(const fidxdim &osize) {
00321     fidxdim d = osize;
00322     vector<fidxdim> os;
00323     os.assign(pipes.size(), d);
00324     if (os.size() != pipes.size())
00325       eblerror("expected same size vector of idxdim as pipes but found "
00326                << os.size() << " and " << pipes.size());
00327     // bprop in all pipes
00328     for (uint i = 0; i < pipes.size(); ++i) {
00329       module_1_1<T,Tstate> *p = pipes[i];
00330       fidxdim &pi = os[i];
00331       if (p) pi = p->bprop_size(pi);
00332     }
00333     return d;
00334   }
00335 
00336   template <typename T, class Tstate>
00337   mfidxdim ms_module<T,Tstate>::bprop_size(mfidxdim &osize) {
00338     EDEBUG(this->name() << " (ms, " << this->noutputs << " outputs): "
00339           << osize << " b-> ...");
00340     mfidxdim isize;
00341     // we replicated the input for each pipe, so fuse inputs into 1
00342     if (replicate_inputs) {
00343       //uint cap = std::max((uint) pipes.size(), this->ninputs);
00344       uint sz = osize.size() / pipes.size();
00345       for (uint i = 0; i < pipes.size(); i++) {
00346         mfidxdim o1;
00347         for (uint j = 0; j < sz; ++j)
00348           if (osize.exists(j + i * sz)) o1.push_back_new(osize[j + i * sz]);
00349           else o1.push_back_empty();
00350         module_1_1<T,Tstate> *p = pipes[i];
00351         mfidxdim i1 = o1;
00352         if (p) i1 = p->bprop_size(o1);
00353         // fuse inputs from different pipes into 1
00354         //EDEBUG(this->name() << ": noutputs " << this->noutputs);
00355         //      if (i == 0 || this->noutputs != osize.size()) // first pipe, just add
00356         if (i == 0) // first pipe, just add
00357           isize.push_back(i1);
00358         else {
00359           for (uint j = 0; j < i1.size(); ++j) {
00360             if (!isize.exists(j) && i1.exists(j)) { // fuse if empty
00361               if (j >= isize.size())
00362                 isize.push_back(i1[j]);
00363               else
00364                 isize.set_new(i1[j], j);
00365             }
00366           }
00367         }
00368       }
00369     } else { // bprop in all pipes
00370       uint j = 0;
00371       for (uint i = 0; i < pipes.size(); i++) {
00372         module_1_1<T,Tstate> *p = pipes[i];
00373         mfidxdim pi = osize;
00374         if (p) {
00375           // narrow to number of outputs
00376           pi = osize.narrow_copy(p->get_noutputs(), j);
00377           pi = p->bprop_size(pi);
00378           j += p->get_noutputs();
00379         }
00380         isize.push_back(pi);
00381       }
00382     }
00383     EDEBUG(this->name() << ": " << osize << " b-> " << isize);
00384     return isize;
00385   }
00386 
00387   // printing //////////////////////////////////////////////////////////////////
00388 
00389   template <typename T, class Tstate>
00390   std::string ms_module<T,Tstate>::pretty(idxdim &isize) {
00391     std::string s;
00392     idxdim is(isize);
00393     fidxdim fis(isize);
00394     s << pipes[0]->pretty(is);
00395     fis = pipes[0]->fprop_size(fis);
00396     return s;
00397   }
00398 
00399   template <typename T, class Tstate>
00400   std::string ms_module<T,Tstate>::pretty(mfidxdim &isize) {
00401     std::string s;
00402     mfidxdim is(isize);
00403     s << "\n";
00404     for (uint i = 0; i < pipes.size(); ++i) {
00405       mfidxdim j;
00406       int id = std::min((int) i, (int) is.size() - 1);
00407       if (replicate_inputs) j.push_back(is);
00408       else if (is.exists(id)) j.push_back(is[id]);
00409       s << j << " -> " << this->name() << " pipe " << i;
00410       if (!pipes[i]) s << ": empty pipe (just passing data)\n";
00411       else s << pipes[i]->pretty(j) << "\n";
00412     }
00413     return s;
00414   }
00415 
00416   template <typename T, class Tstate>
00417   std::string ms_module<T, Tstate>::describe() {
00418     std::string desc;
00419     desc << "ms module " << this->name();
00420     desc << ", pipes ";
00421     for (uint i = 0; i < pipes.size(); ++i) {
00422       if (!pipes[i]) desc << "empty pipe";
00423       else desc << pipes[i]->name();
00424       if (i != pipes.size() - 1) desc << ", ";
00425     }
00426     if (switches.size() > 0)
00427       desc << ", switching based on input sizes: " << switches;
00428     desc << ":\n";
00429     for (uint i = 0; i < pipes.size(); ++i) {
00430       desc << this->name() << " pipe[" << i << "]: ";
00431       if (!pipes[i]) desc << "empty pipe (just passing data)\n";
00432       else desc << pipes[i]->describe(1) << "\n";
00433     }
00434     return desc;
00435   }
00436 
00437   // accessors /////////////////////////////////////////////////////////////////
00438 
00439   template <typename T, class Tstate>
00440   void ms_module<T, Tstate>::set_switch(midxdim &s) {
00441     switches = s;
00442   }
00443 
00444   template <typename T, class Tstate>
00445   void ms_module<T, Tstate>::set_switch(intg id) {
00446     EDEBUG("switching scale to " << id);
00447     bindex = true;
00448     switch_id = id;
00449   }
00450 
00451   template <typename T, class Tstate>
00452   uint ms_module<T, Tstate>::npipes() {
00453     return (uint) pipes.size();
00454   }
00455 
00456   template <typename T, class Tstate>
00457   module_1_1<T,Tstate>* ms_module<T, Tstate>::get_pipe(uint i) {
00458     if (i > pipes.size())
00459       eblerror("cannot access pipe " << i << ", only "
00460                << pipes.size() << "pipes");
00461     return pipes[i];
00462   }
00463 
00464   template <typename T, class Tstate>
00465   module_1_1<T,Tstate>* ms_module<T, Tstate>::last_module() {
00466     if (pipes.size())
00467       return pipes[0]->last_module();
00468     return this;
00469   }
00470 
00471   // protected methods /////////////////////////////////////////////////////////
00472 
00473   template <typename T, class Tstate>
00474   void ms_module<T,Tstate>::init() {
00475     // this module takes multi-state inputs and multi-state outputs
00476     this->bmstate_input = true;
00477     this->bmstate_output = true;
00478     // check that modules exist
00479     for (uint i = 0; i < pipes.size(); ++i)
00480       if (pipes[i] == NULL)
00481         eblwarn(this->name() << ": pipe " << i
00482                 << " is empty (just passing data long)");
00483     // initialize actually used pipes
00484     used_pipes = pipes;
00485     // resize
00486     if (used_pipes.size() != pipes_noutputs.size())
00487       pipes_noutputs.resize(used_pipes.size());
00488     // switching
00489     bindex = false;
00490     switch_id = -1;
00491   }
00492 
00493   template <typename T, class Tstate>
00494   void ms_module<T,Tstate>::init_fprop(mstate<Tstate> &in,mstate<Tstate> &out) {
00495     // remember number of input
00496     this->ninputs = in.size();
00497     ins.clear();
00498     out.clear();
00499     // switch used pipes if switches are defined
00500     switch_pipes(in);
00501     // replicate input states if only 1 state but multiple pipes
00502     // or if manually requested with replicate_inputs
00503     if ((in.size() == 1 && used_pipes.size() > 1) || replicate_inputs)
00504       for (uint i = 0; i < used_pipes.size(); ++i) ins.push_back_new(in);
00505     else if (in.size() == used_pipes.size())
00506       for (uint i = 0; i < used_pipes.size(); ++i) {
00507         mstate<Tstate> tin;
00508         tin.push_back_new(in[i]);
00509         ins.push_back_new(tin);
00510       }
00511     else ins.push_back_new(in); // just feed in to pipes
00512     EDEBUG("input " << in << " -> " << ins << " for used_pipes "
00513           << used_pipes << " in " << this->name());
00514     // allocate buffers
00515     if (used_pipes.size() != mbuffers.size())
00516       mbuffers.resize_default(used_pipes.size());
00517     if (used_pipes.size() != pipes_noutputs.size())
00518       pipes_noutputs.resize(used_pipes.size());
00519   }
00520 
00521   template <typename T, class Tstate>
00522   void ms_module<T,Tstate>::switch_pipes(mstate<Tstate> &in) {
00523     // if switching is on, limit to only 1 pipe
00524     intg id = -1;
00525     // determine switch id
00526     if (bindex) // switching based on given pipe index
00527       id = switch_id;
00528     else if (switches.size() > 0) {
00529       // find the switch index matching the first input size
00530       idxdim d0 = in[0].x.get_idxdim();
00531       d0.remove_dim(0);
00532       bool found = false;
00533       for (intg i = 0; i < (intg) switches.size(); ++i)
00534         if (switches[i] == d0) {
00535           id = i;
00536           found = true;
00537           break ;
00538         }
00539       if (!found)
00540         eblerror("switch with dimensions " << d0 << " not found in "<<switches);
00541     }
00542     // actual switch
00543     if (id >= 0) {
00544       used_pipes.clear();
00545       used_pipes.push_back(pipes[id]);
00546       EDEBUG("switching to pipe " << id << " (input is " << in[0].x << ")");
00547     } else used_pipes = pipes;
00548   }
00549 
00551   // msc_module
00552 
00553   template <typename T, class Tstate>
00554   msc_module<T,Tstate>::msc_module
00555   (std::vector<module_1_1<T,Tstate>*> &pipes_, uint nsize_, uint stride_,
00556    uint nsize2_, const char *name_)
00557     : ms_module<T,Tstate>(pipes_, false, name_), nsize(nsize_), stride(stride_),
00558       nsize2(nsize2_) {
00559     if (nsize2 == 0) nsize2 = nsize;
00560     if (nsize2 < nsize) eblerror("nsize2 must be greater or equal to nsize");
00561   }
00562 
00563   template <typename T, class Tstate>
00564   msc_module<T,Tstate>::~msc_module() {
00565   }
00566 
00568 
00569   template <typename T, class Tstate>
00570   fidxdim msc_module<T,Tstate>::fprop_size(fidxdim &isize) {
00571     fidxdim d = isize;
00572     // use 1st pipe as base size
00573     module_1_1<T,Tstate> *p0 = pipes[0];
00574     d = p0->fprop_size(d);
00575     return d;
00576   }
00577 
00578   template <typename T, class Tstate>
00579   fidxdim msc_module<T,Tstate>::bprop_size(const fidxdim &osize) {
00580     fidxdim d = osize;
00581     vector<fidxdim> os;
00582     os.assign(pipes.size(), d);
00583     if (os.size() != pipes.size())
00584       eblerror("expected same size vector of idxdim as pipes but found "
00585                << os.size() << " and " << pipes.size());
00586     // bprop in all pipes
00587     for (uint i = 0; i < pipes.size(); ++i) {
00588       module_1_1<T,Tstate> *p = pipes[i];
00589       fidxdim &pi = os[i];
00590       pi = p->bprop_size(pi);
00591     }
00592     return d;
00593   }
00594 
00595   template <typename T, class Tstate>
00596   mfidxdim msc_module<T,Tstate>::bprop_size(mfidxdim &osize) {
00597     EDEBUG(this->name() << " (msc): " << osize << " b-> ...");
00598     if (osize.size() != this->noutputs)
00599       eblerror("expected osize to have " << this->noutputs << " elements but"
00600                << " it has only: " << osize);
00601     mfidxdim isize(this->ninputs);
00602     uint i = 0, o = 0, off = 0;
00603     // loop on high-level groups
00604     uint n2 = this->ninputs / nsize2;
00605     for (uint j = 0; j < n2; ++j) {
00606       // loop on low-level groups
00607       for (uint k = 0; k < nsize2 - nsize + 1; ++k) {
00608         mfidxdim md;
00609         if (o >= pipes_noutputs.size())
00610           eblerror("expected at least " << o + 1 << " outputs sizes but got "
00611                    << pipes_noutputs);
00612         // loop on number of outputs for this pipe
00613         for (uint l = 0; l < pipes_noutputs[o]; ++l, ++off) {
00614           if (osize.exists(off)) md.push_back(osize[off]);
00615           else md.push_back_empty();
00616         }
00617         md = pipes[std::min(pipes.size() - 1, (size_t)o)]->bprop_size(md);
00618         // copy all inputs to size
00619         for (uint l = 0; l < md.size(); ++l)
00620           if (md.exists(l)) isize.set(md[l], l + i);
00621         o++;
00622         i++;
00623       }
00624       i += nsize - 1;
00625       // // fill remaining inputs before next group with empty elements
00626       // for (uint k = 0; k < nsize - 1; ++k)
00627       //        isize.push_back_empty();
00628     }
00629     EDEBUG(this->name() << ": " << osize << " b-> " << isize);
00630     return isize;
00631   }
00632 
00633 template <typename T, class Tstate>
00634   std::string msc_module<T, Tstate>::describe() {
00635     std::string desc;
00636     desc << "msc module " << this->name();
00637     desc << " with nsize " << nsize << ", stride " << stride << ", nsize2 "
00638          << nsize2 << ", pipes ";
00639     for (uint i = 0; i < pipes.size(); ++i)
00640       desc << pipes[i]->name() << ", ";
00641     desc << ":\n";
00642     for (uint i = 0; i < pipes.size(); ++i)
00643       desc << this->name() << " pipe[" << i << "]: "
00644            << pipes[i]->describe(1);
00645     return desc;
00646   }
00647 
00649   // protected methods
00650 
00651   template <typename T, class Tstate>
00652   void msc_module<T,Tstate>::init_fprop(mstate<Tstate> &in,mstate<Tstate> &out){
00653     // remember number of input
00654     this->ninputs = in.size();
00655     // in has to have at least nsize states
00656     if (in.size() < nsize)
00657       eblerror("input must have at least " << nsize << " states but has only "
00658                << in.size());
00659     if (in.size() % nsize2 != 0)
00660       eblerror("expected input to be multiple of " << nsize2 << " but got "
00661                << in.size() << " states instead");
00662     ins.clear();
00663     out.clear();
00664     used_pipes.clear();
00665     mstate<Tstate> mi; // buffers
00666     uint o = 0; // number of output groups
00667     // pipes
00668     for (uint i = 0; i < pipes.size(); ++i) {
00669       if (!pipes[i]->mstate_input())
00670         eblerror("expected module with multi-inputs capabilities");
00671       // loop on high-level groups
00672       uint n2 = in.size() / nsize2;
00673       for (uint j = 0; j < n2; ++j) {
00674         // loop on low-level groups
00675         for (uint k = 0; k < nsize2 - nsize + 1; ++k) {
00676           // create buffer with nsize states
00677           mi = in.narrow(nsize, k + j * nsize2);
00678           // TODO: temporarly lock elements manually
00679           // pb: operator= when returning narrow doesnt lock elements,
00680           // if defining it, then assigning to a reference gives
00681           // negative references counters (?).
00682           mi.lock_all();
00683           used_pipes.push_back(pipes[i]);
00684           ins.push_back_new(mi);
00685           o++;
00686         }
00687       }
00688     }
00689   }
00690 
00692   // arch find
00693 
00694   template <typename T, class Tstate, class Tcast>
00695   Tcast* arch_find(module_1_1<T,Tstate> *m, Tcast *c) {
00696     Tcast *ret = dynamic_cast<Tcast*>(m);
00697     if (ret) return ret;
00698     layers<T,Tstate> *l = dynamic_cast<layers<T,Tstate>*>(m);
00699     if (l) return arch_find(l, c);
00700     ms_module<T,Tstate> *ms = dynamic_cast<ms_module<T,Tstate>*>(m);
00701     if (ms) return arch_find(ms, c);
00702     return NULL;
00703   }
00704 
00705   template <typename T, class Tstate, class Tcast>
00706   Tcast* arch_find(layers<T,Tstate> *m, Tcast *c) {
00707     if (!m) return NULL;
00708     for (uint i = 0; i < m->modules.size(); ++i) {
00709       module_1_1<T, Tstate, Tstate>* mo = m->modules[i];
00710       Tcast *ret = arch_find(mo, c);
00711       if (ret) return ret;
00712     }
00713     return NULL; // not found
00714   }
00715 
00716   template <typename T, class Tstate, class Tcast>
00717   Tcast* arch_find(ms_module<T,Tstate> *m, Tcast *c) {
00718     if (!m) return NULL;
00719     Tcast *ret = NULL;
00720     for (uint i = 0; i < m->pipes.size(); ++i) {
00721       ret = arch_find(m->pipes[i], c);
00722       if (ret) return ret;
00723     }
00724     return NULL;
00725   }
00726 
00728   // arch find_all
00729 
00730   template <typename T, class Tstate, class Tcast>
00731   std::vector<Tcast*> arch_find_all(module_1_1<T,Tstate> *m, Tcast *c,
00732                                     std::vector<Tcast*> *v) {
00733     std::vector<Tcast*> v2;
00734     std::vector<Tcast*> *all = &v2;
00735     if (v) all = v;
00736     Tcast *ret = dynamic_cast<Tcast*>(m);
00737     if (ret) all->push_back(ret);
00738     layers<T,Tstate> *l = dynamic_cast<layers<T,Tstate>*>(m);
00739     if (l) return arch_find_all(l, c, all);
00740     ms_module<T,Tstate> *ms = dynamic_cast<ms_module<T,Tstate>*>(m);
00741     if (ms) return arch_find_all(ms, c, all);
00742     return *all;
00743   }
00744 
00745   template <typename T, class Tstate, class Tcast>
00746   std::vector<Tcast*> arch_find_all(layers<T,Tstate> *m, Tcast *c,
00747                                     std::vector<Tcast*> *v) {
00748     std::vector<Tcast*> v2;
00749     std::vector<Tcast*> *all = &v2;
00750     if (v) all = v;
00751     if (!m) return *all;
00752     for (uint i = 0; i < m->modules.size(); ++i) {
00753       module_1_1<T, Tstate, Tstate>* mo = m->modules[i];
00754       *all = arch_find_all(mo, c, all);
00755     }
00756     return *all;
00757   }
00758 
00759   template <typename T, class Tstate, class Tcast>
00760   std::vector<Tcast*> arch_find_all(ms_module<T,Tstate> *m, Tcast *c,
00761                                     std::vector<Tcast*> *v) {
00762     std::vector<Tcast*> v2;
00763     std::vector<Tcast*> *all = &v2;
00764     if (v) all = v;
00765     if (!m) return *all;
00766     for (uint i = 0; i < m->pipes.size(); ++i)
00767       *all = arch_find_all(m->pipes[i], c, all);
00768     return *all;
00769   }
00770 
00772   // arch narrow
00773 
00774   template <typename T, class Tstate, class Tcast>
00775   module_1_1<T,Tstate>* arch_narrow(module_1_1<T,Tstate> *m, Tcast *c,
00776                                     bool included, bool *found) {
00777     if (!m) return NULL;
00778     Tcast *ret = dynamic_cast<Tcast*>(m);
00779     if (ret == c) { // this module matches the target type Tcast*
00780       if (found) *found = true;
00781       if (included) return m->copy(); // include found module
00782       else return NULL; // do not include found module
00783     }
00784     layers<T,Tstate> *l = dynamic_cast<layers<T,Tstate>*>(m);
00785     if (l) return (module_1_1<T,Tstate>*) arch_narrow(l, c, included, found);
00786     ms_module<T,Tstate> *ms = dynamic_cast<ms_module<T,Tstate>*>(m);
00787     if (ms) return (module_1_1<T,Tstate>*) arch_narrow(ms, c, included, found);
00788     return m->copy();
00789   }
00790 
00791   template <typename T, class Tstate, class Tcast>
00792   layers<T,Tstate>* arch_narrow(layers<T,Tstate> *m, Tcast *c,
00793                                 bool included, bool *found) {
00794     if (!m) return NULL;
00795     bool lfound = false;
00796     if (!found) found = &lfound;
00797     layers<T,Tstate> *m2 = new layers<T,Tstate>(true, m->name());
00798     for (uint i = 0; i < m->modules.size(); ++i) {
00799       module_1_1<T,Tstate,Tstate>* mo = m->modules[i];
00800       mo = arch_narrow(mo, c, included, found);
00801       if (mo) m2->add_module(mo);
00802       if (*found) return m2;
00803     }
00804     return m2;
00805   }
00806 
00807   template <typename T, class Tstate, class Tcast>
00808   ms_module<T,Tstate>* arch_narrow(ms_module<T,Tstate> *m, Tcast *c,
00809                                    bool included, bool *found) {
00810     if (!m) return NULL;
00811     bool lfound = false;
00812     if (!found) found = &lfound;
00813     ms_module<T,Tstate> *m2 =
00814       new ms_module<T,Tstate>(m->replicate_inputs, m->name());
00815     for (uint i = 0; i < m->pipes.size(); ++i) {
00816       module_1_1<T,Tstate> *p2 = NULL;
00817       if (m->pipes[i]) p2 = arch_narrow(m->pipes[i], c, included, found);
00818       m2->pipes.push_back(p2);
00819       if (*found) {
00820         m2->pipes.clear();
00821         m2->pipes.push_back(p2);
00822         return m2;
00823       }
00824     }
00825     return m2;
00826   }
00827 
00828 } // end namespace ebl