libeblearn
|
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