SundanceExprWithChildren.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                              Sundance
00005 //                 Copyright (2005) Sandia Corporation
00006 // 
00007 // Copyright (year first published) Sandia Corporation.  Under the terms 
00008 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 
00009 // retains certain rights in this software.
00010 // 
00011 // This library is free software; you can redistribute it and/or modify
00012 // it under the terms of the GNU Lesser General Public License as
00013 // published by the Free Software Foundation; either version 2.1 of the
00014 // License, or (at your option) any later version.
00015 //  
00016 // This library is distributed in the hope that it will be useful, but
00017 // WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 // Lesser General Public License for more details.
00020 //                                                                                 
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License along with this library; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00024 // USA                                                                                
00025 // Questions? Contact Kevin Long (krlong@sandia.gov), 
00026 // Sandia National Laboratories, Livermore, California, USA
00027 // 
00028 // ************************************************************************
00029 /* @HEADER@ */
00030 
00031 #include "SundanceExprWithChildren.hpp"
00032 #include "SundanceCombinatorialUtils.hpp"
00033 #include "SundanceTabs.hpp"
00034 #include "SundanceOut.hpp"
00035 #include "SundanceExpr.hpp"
00036 #include "SundanceEvaluatorFactory.hpp"
00037 #include "SundanceEvaluator.hpp"
00038 #include "SundanceNullEvaluator.hpp"
00039 #include "SundanceUnknownFuncElement.hpp"
00040 #include "SundanceTestFuncElement.hpp"
00041 #include "SundanceUnaryExpr.hpp"
00042 
00043 using namespace Sundance;
00044 using namespace Sundance;
00045 
00046 using namespace Sundance;
00047 using namespace Teuchos;
00048 
00049 
00050 
00051 
00052 ExprWithChildren::ExprWithChildren(const Array<RCP<ScalarExpr> >& children)
00053   : EvaluatableExpr(), 
00054     children_(children),
00055     contextToQWMap_(4),
00056     contextToQVMap_(4),
00057     contextToQCMap_(4)
00058 {}
00059 
00060 bool ExprWithChildren::lessThan(const ScalarExpr* other) const
00061 {
00062   const ExprWithChildren* c = dynamic_cast<const ExprWithChildren*>(other);
00063   TEST_FOR_EXCEPTION(c==0, InternalError, "cast should never fail at this point");
00064 
00065   if (children_.size() < c->children_.size()) return true;
00066   if (children_.size() > c->children_.size()) return false;
00067   
00068   for (int i=0; i<children_.size(); i++)
00069   {
00070     Expr me = Expr::handle(children_[i]);
00071     Expr you = Expr::handle(c->children_[i]);
00072     if (me.lessThan(you)) return true;
00073     if (you.lessThan(me)) return false;
00074   }
00075   return false;
00076 }
00077 
00078 
00079 
00080 bool ExprWithChildren::isConstant() const
00081 {
00082   for (int i=0; i<children_.size(); i++) 
00083   {
00084     if (!children_[i]->isConstant()) return false;
00085   }
00086   return true;
00087 }
00088 
00089 bool ExprWithChildren::isIndependentOf(const Expr& u) const
00090 {
00091   for (int i=0; i<children_.size(); i++) 
00092   {
00093     if (!children_[i]->isIndependentOf(u)) return false;
00094   }
00095   return true;
00096 }
00097 
00098 const EvaluatableExpr* ExprWithChildren::evaluatableChild(int i) const
00099 {
00100   const EvaluatableExpr* e 
00101     = dynamic_cast<const EvaluatableExpr*>(children_[i].get());
00102 
00103   TEST_FOR_EXCEPTION(e==0, InternalError, 
00104     "ExprWithChildren: cast of child [" 
00105     << children_[i]->toString()
00106     << " to evaluatable expr failed");
00107 
00108   return e;
00109 }
00110 
00111 int ExprWithChildren::maxDiffOrderOnDiscreteFunctions() const
00112 {
00113   int biggest = -1;
00114   for (int i=0; i<numChildren(); i++)
00115   {
00116     int x = evaluatableChild(i)->maxDiffOrderOnDiscreteFunctions();
00117     if (x > biggest) biggest = x;
00118   }
00119   return biggest;
00120 }
00121 
00122 bool ExprWithChildren::hasDiscreteFunctions() const
00123 {
00124   for (int i=0; i<numChildren(); i++)
00125   {
00126     if (evaluatableChild(i)->hasDiscreteFunctions()) return true;
00127   }
00128   return false;
00129 }
00130 
00131 
00132 void ExprWithChildren::accumulateFuncSet(Set<int>& funcIDs, 
00133   const Set<int>& activeSet) const
00134 {
00135   for (int i=0; i<children_.size(); i++) 
00136   {
00137     children_[i]->accumulateFuncSet(funcIDs, activeSet);
00138   }
00139 }
00140 
00141 void ExprWithChildren::registerSpatialDerivs(const EvalContext& context, 
00142   const Set<MultiIndex>& miSet) const
00143 {
00144   for (int i=0; i<children_.size(); i++) 
00145   {
00146     evaluatableChild(i)->registerSpatialDerivs(context, miSet);
00147   }
00148   EvaluatableExpr::registerSpatialDerivs(context, miSet);
00149 }
00150 
00151 void ExprWithChildren::setupEval(const EvalContext& context) const
00152 {
00153   Tabs tabs;
00154   int verb = context.setupVerbosity();
00155   SUNDANCE_MSG3(verb, tabs << "expr " + toString() 
00156     << ": creating evaluators for children");
00157   RCP<SparsitySuperset> ss = sparsitySuperset(context);
00158   SUNDANCE_MSG3(verb, tabs << "my sparsity superset = " << *ss);
00159 
00160 
00161   /* Create the evaluators for the children first so that I can refer to
00162    * them when I create my own evaluator */
00163   if (ss->numDerivs() > 0)
00164   {
00165     for (int i=0; i<children_.size(); i++)
00166     {
00167       Tabs tabs1;
00168       SUNDANCE_MSG3(verb, tabs1 << "creating evaluator for child " 
00169         << evaluatableChild(i)->toString());
00170       evaluatableChild(i)->setupEval(context);
00171     }
00172   }
00173 
00174   if (!evaluators().containsKey(context))
00175   {
00176     RCP<Evaluator> eval;
00177     if (ss->numDerivs()>0)
00178     {
00179       eval = rcp(createEvaluator(this, context));
00180     }
00181     else
00182     {
00183       eval = rcp(new NullEvaluator());
00184     }
00185     evaluators().put(context, eval);
00186   }
00187 }
00188 
00189 void ExprWithChildren::showSparsity(std::ostream& os, 
00190   const EvalContext& context) const
00191 {
00192   Tabs tab0;
00193   os << tab0 << "Node: " << toString() << std::endl;
00194   sparsitySuperset(context)->print(os);
00195   for (int i=0; i<children_.size(); i++)
00196   {
00197     Tabs tab1;
00198     os << tab1 << "Child " << i << std::endl;
00199     evaluatableChild(i)->showSparsity(os, context);
00200   }
00201 }
00202 
00203 
00204 bool ExprWithChildren::everyTermHasTestFunctions() const
00205 {
00206   for (int i=0; i<children_.size(); i++)
00207   {
00208     if (evaluatableChild(i)->everyTermHasTestFunctions()) return true;
00209   }
00210   return false;
00211 }
00212 
00213 
00214 bool ExprWithChildren::hasTestFunctions() const
00215 {
00216   for (int i=0; i<children_.size(); i++)
00217   {
00218     if (evaluatableChild(i)->hasTestFunctions()) return true;
00219   }
00220   return false;
00221 }
00222 
00223 
00224 bool ExprWithChildren::hasUnkFunctions() const
00225 {
00226   for (int i=0; i<children_.size(); i++)
00227   {
00228     if (evaluatableChild(i)->hasUnkFunctions()) return true;
00229   }
00230   return false;
00231 }
00232 
00233 
00234 void ExprWithChildren::getUnknowns(Set<int>& unkID, Array<Expr>& unks) const
00235 {
00236   for (int i=0; i<children_.size(); i++)
00237   {
00238     const RCP<ExprBase>& e = children_[i];
00239     const UnknownFuncElement* u 
00240       = dynamic_cast<const UnknownFuncElement*>(e.get());
00241     if (u != 0)
00242     {
00243       Expr expr(e);
00244       if (!unkID.contains(u->fid().dofID())) 
00245       {
00246         unks.append(expr);
00247         unkID.put(u->fid().dofID());
00248       }
00249     }
00250     else
00251     {
00252       evaluatableChild(i)->getUnknowns(unkID, unks);
00253     }
00254   }
00255 }
00256 
00257 void ExprWithChildren::getTests(Set<int>& varID, Array<Expr>& vars) const
00258 {
00259   for (int i=0; i<children_.size(); i++)
00260   {
00261     const RCP<ExprBase>& e = children_[i];
00262     const TestFuncElement* u 
00263       = dynamic_cast<const TestFuncElement*>(e.get());
00264     if (u != 0)
00265     {
00266       Expr expr(e);
00267       if (!varID.contains(u->fid().dofID())) 
00268       {
00269         vars.append(expr);
00270         varID.put(u->fid().dofID());
00271       }
00272 
00273     }
00274     else
00275     {
00276       evaluatableChild(i)->getTests(varID, vars);
00277     }
00278   }
00279 }
00280 
00281 
00282 int ExprWithChildren::countNodes() const
00283 {
00284   if (nodesHaveBeenCounted()) 
00285   {
00286     return 0;
00287   }
00288 
00289   /* count self */
00290   int count = EvaluatableExpr::countNodes();
00291 
00292   /* count children */
00293   for (int i=0; i<children_.size(); i++)
00294   {
00295     if (!evaluatableChild(i)->nodesHaveBeenCounted())
00296     {
00297       count += evaluatableChild(i)->countNodes();
00298     }
00299   }
00300   return count;
00301 }
00302 
00303 Set<MultipleDeriv> 
00304 ExprWithChildren::product(const Array<int>& J, const Array<int>& K,
00305   DerivSubsetSpecifier dss,
00306   const EvalContext& context) const
00307 {
00308   TEST_FOR_EXCEPTION(J.size() != K.size(), InternalError,
00309     "mismatched index set sizes");
00310   TEST_FOR_EXCEPTION(J.size() == 0, InternalError,
00311     "empty index set");
00312 
00313   Set<MultipleDeriv> rtn 
00314     = evaluatableChild(J[0])->findDerivSubset(K[0], dss, context);
00315   
00316   for (int i=1; i<J.size(); i++)
00317   {
00318     const Set<MultipleDeriv>& S 
00319       = evaluatableChild(J[i])->findDerivSubset(K[i], dss, context);
00320     rtn = setProduct(rtn, S);
00321   }
00322 
00323   return rtn;
00324 }
00325 
00326 Set<MultipleDeriv> 
00327 ExprWithChildren::internalFindV(int order, const EvalContext& context) const
00328 {
00329   Tabs tab0;
00330   int verb = context.setupVerbosity();
00331   SUNDANCE_MSG3(verb, tab0 << "EWC::internalFindV(" << order 
00332     << ") for " << toString());
00333 
00334   Set<MultipleDeriv> rtn;
00335 
00336 
00337 
00338   /* we'll dealt with zero order derivatives specially */
00339   if (order==0) 
00340   {
00341     for (int i=0; i<numChildren(); i++)
00342     {
00343       if (!childIsRequired(i, order, context)) continue;
00344       const Set<MultipleDeriv>& childV0 
00345         = evaluatableChild(i)->findV(0, context);        
00346       rtn.merge(childV0);
00347     }
00348     const Set<MultipleDeriv>& R0 = findR(0, context);
00349     rtn = rtn.intersection(R0);
00350 
00351     SUNDANCE_MSG3(verb, tab0 << "V[" << order << "]=" << rtn);
00352     SUNDANCE_MSG3(verb, tab0 << "done with EWC::internalFindV(" << order
00353       << ") for " << toString());
00354     return rtn;
00355   }
00356 
00357 
00358   /* now do arbitrary order derivatives with the multivariable chain rule*/
00359   const Set<MultipleDeriv>& RM = findR(order, context);
00360   Array<Array<Array<int> > > comp = compositions(order);
00361   for (int i=1; i<=order; i++) 
00362   {
00363     Tabs tab1;
00364     SUNDANCE_MSG5(verb, tab1 << "i=" << i);
00365     const Set<MultiSet<int> >& QC = findQ_C(i, context);
00366     SUNDANCE_MSG5(verb, tab1 << "QC[" << i << "] = " << QC);
00367     for (Set<MultiSet<int> >::const_iterator j=QC.begin(); j!=QC.end(); j++)
00368     {
00369       Tabs tab2;
00370       Array<int> J = j->elements();
00371       const Array<Array<int> >& K = comp[J.size()-1];
00372       SUNDANCE_MSG5(verb, tab2 << "J=" << J);
00373       SUNDANCE_MSG5(verb, tab2 << "K=" << K);
00374 
00375       for (int k=0; k<K.size(); k++)
00376       {
00377         Tabs tab3;
00378         Set<MultipleDeriv> RProd = product(J, K[k], 
00379           RequiredNonzeros, context);
00380         Set<MultipleDeriv> CProd = product(J, K[k], 
00381           ConstantNonzeros, context);
00382         SUNDANCE_MSG5(verb, tab3 << "CProd = " << CProd);
00383         SUNDANCE_MSG5(verb, tab3 << "RProd = " << RProd);
00384         rtn.merge(RProd.setDifference(CProd));
00385       }
00386     }
00387 
00388     const Set<MultiSet<int> >& QV = findQ_V(i, context);
00389     SUNDANCE_MSG5(verb, tab1 << "QV[" << i << "] = " << QV);
00390     for (Set<MultiSet<int> >::const_iterator j=QV.begin(); j!=QV.end(); j++)
00391     {
00392       Tabs tab2;
00393       Array<int> J = j->elements();
00394       const Array<Array<int> >& K = comp[J.size()-1];
00395       SUNDANCE_MSG5(verb, tab2 << "J=" << J);
00396       SUNDANCE_MSG5(verb, tab2 << "K=" << K);
00397 
00398       for (int k=0; k<K.size(); k++)
00399       {
00400         Tabs tab3;
00401         Set<MultipleDeriv> RProd = product(J, K[k], 
00402           RequiredNonzeros, context);
00403         SUNDANCE_MSG5(verb, tab3 << "RProd = " << RProd);
00404         rtn.merge(RProd);
00405       }
00406     }
00407   }
00408 
00409   rtn = rtn.intersection(RM);
00410   SUNDANCE_MSG3(verb, tab0 << "V[" << order << "]=" << rtn);
00411   SUNDANCE_MSG3(verb, tab0 << "done with EWC::internalFindV(" << order
00412     << ") for " << toString());
00413 
00414   return rtn;
00415 }
00416 
00417 
00418 Set<MultipleDeriv> 
00419 ExprWithChildren::internalFindC(int order, const EvalContext& context) const
00420 {
00421   Tabs tab0;
00422   Set<MultipleDeriv> rtn;
00423   bool started = false;
00424   int verb = context.setupVerbosity();
00425 
00426   SUNDANCE_MSG3(verb, tab0 << "EWC::internalFindC(" << order 
00427     << ") for " << toString());
00428 
00429   /* we'll dealt with zero order derivatives specially */
00430   if (order==0) 
00431   {
00432     for (int i=0; i<numChildren(); i++)
00433     {
00434       if (!childIsRequired(i, 0, context)) continue;
00435       const Set<MultipleDeriv>& childV0 
00436         = evaluatableChild(i)->findV(0, context);        
00437       rtn.merge(childV0);
00438     }
00439     const Set<MultipleDeriv>& R0 = findR(0, context);
00440     rtn = R0.setDifference(rtn);
00441     SUNDANCE_MSG3(verb, tab0 << "C[" << order << "]=" << rtn);
00442     SUNDANCE_MSG3(verb, tab0 << "done with EWC::internalFindC(" << order
00443       << ") for " << toString());
00444     return rtn;
00445   }
00446 
00447 
00448   /* now do arbitrary order derivatives with the multivariable chain rule*/
00449   Array<Array<Array<int> > > comp = compositions(order);
00450   const Set<MultipleDeriv>& RM = findR(order, context);
00451   for (int i=1; i<=order; i++) 
00452   {
00453     Tabs tab1;
00454     SUNDANCE_MSG5(verb, tab1 << "i=" << i);
00455 
00456 
00457     const Set<MultiSet<int> >& QC = findQ_C(i, context);
00458     SUNDANCE_MSG5(verb, tab1 << "finding CProd union (R\\RProd) over QC");      
00459     SUNDANCE_MSG5(verb, tab1 << "QC = " << QC);
00460 
00461 
00462     for (Set<MultiSet<int> >::const_iterator j=QC.begin(); j!=QC.end(); j++)
00463     {
00464       Tabs tab2;
00465       Array<int> J = j->elements();
00466       const Array<Array<int> >& K = comp[J.size()-1];
00467       SUNDANCE_MSG5(verb, tab2 << "J=" << J);
00468       SUNDANCE_MSG5(verb, tab2 << "K=" << K);
00469 
00470       for (int k=0; k<K.size(); k++)
00471       {
00472         Tabs tab3;
00473         Set<MultipleDeriv> RProd = product(J, K[k], 
00474           RequiredNonzeros, context);
00475         Set<MultipleDeriv> CProd = product(J, K[k], 
00476           ConstantNonzeros, context);
00477         SUNDANCE_MSG5(verb, tab3 << "CProd = " << CProd);
00478         SUNDANCE_MSG5(verb, tab3 << "RProd = " << RProd);
00479         Set<MultipleDeriv> X = CProd.setUnion(RM.setDifference(RProd));
00480         if (!started) 
00481         {
00482           rtn = X;
00483           started = true;
00484         }
00485         else 
00486         {
00487           rtn = rtn.intersection(X);
00488         }
00489       }
00490     }
00491 
00492     const Set<MultiSet<int> >& QV = findQ_V(i, context);
00493     SUNDANCE_MSG5(verb, tab1 << "finding R\\RProd over QV");      
00494     SUNDANCE_MSG5(verb, tab1 << "QV = " << QV);
00495 
00496     for (Set<MultiSet<int> >::const_iterator j=QV.begin(); j!=QV.end(); j++)
00497     {
00498       Tabs tab2;
00499       Array<int> J = j->elements();
00500       const Array<Array<int> >& K = comp[J.size()-1];
00501       SUNDANCE_MSG5(verb, tab2 << "J=" << J);
00502       SUNDANCE_MSG5(verb, tab2 << "K=" << K);
00503 
00504       for (int k=0; k<K.size(); k++)
00505       {
00506         Tabs tab3;
00507         Set<MultipleDeriv> RProd = product(J, K[k], 
00508           RequiredNonzeros, context);
00509         Set<MultipleDeriv> X = RM.setDifference(RProd);
00510         if (!started) 
00511         {
00512           rtn = X;
00513           started = true;
00514         }
00515         else 
00516         {
00517           rtn = rtn.intersection(X);
00518         }
00519         SUNDANCE_MSG5(verb, tab3 << "RProd = " << RProd);
00520       }
00521     }
00522   }
00523 
00524   rtn = rtn.intersection(RM);
00525   SUNDANCE_MSG3(verb, tab0 << "C[" << order << "]=" << rtn);
00526   SUNDANCE_MSG3(verb, tab0 << "done with EWC::internalFindC(" << order
00527     << ") for " << toString());
00528   return rtn;
00529 }
00530 
00531 
00532 
00533 Set<MultipleDeriv> 
00534 ExprWithChildren::internalFindW(int order, const EvalContext& context) const
00535 {
00536   Tabs tab0;
00537   int verb = context.setupVerbosity();
00538   Set<MultipleDeriv> rtn;
00539   SUNDANCE_MSG3(verb, tab0 << "EWC::internalFindW("
00540     << order << ") for " << toString());  
00541   /* we'll deal with zero order derivatives specially */
00542   if (order==0) 
00543   {
00544     Tabs tab1;
00545     SUNDANCE_MSG3(verb, tab1 << "case: order=0");  
00546     /* If I am an arbitrary nonlinear expression, I cannot be known to
00547      * be zero regardless of the state of my arguments. Return the
00548      * zeroth-order derivative. */
00549     if (!(isLinear() || isProduct())) 
00550     {
00551       Tabs tab2;
00552       SUNDANCE_MSG3(verb, tab2 << "I am neither product nor linear");  
00553       rtn.put(MultipleDeriv());
00554       SUNDANCE_MSG3(verb, tab2 << "W[" << order << "]=" << rtn);
00555       SUNDANCE_MSG3(verb, tab2 << "done with EWC::internalFindW for "
00556         << toString());
00557       return rtn;
00558     }
00559 
00560     /* At this point, I've dealt with arbitrary nonlinear exprs so 
00561      * I know I'm either a product or a linear expr */
00562 
00563     SUNDANCE_MSG3(verb, tab1 << "getting Q");  
00564     const Set<MultiSet<int> >& Q = findQ_W(0, context);
00565 
00566     /* If there are no nonzero terms, a linear combination or a product
00567      * will be zero. Return the empty set. */
00568     if (Q.size()==0)
00569     {
00570       Tabs tab2;
00571       SUNDANCE_MSG3(verb, tab2 << "W[" << order << "]=" << rtn);
00572       SUNDANCE_MSG3(verb, tab2 << "done with EWC::internalFindW for "
00573         << toString());
00574       return rtn;
00575     }
00576       
00577     /* if I'm a linear combination and any term is nonzero, I am nonzero */
00578     if (isLinear())
00579     {
00580       Tabs tab2;
00581       SUNDANCE_MSG3(verb, tab2 << "I am a linear combination");  
00582       rtn.put(MultipleDeriv());      
00583       SUNDANCE_MSG3(verb, tab2 << "W[" << order << "]=" << rtn);
00584       SUNDANCE_MSG3(verb, tab2 << "done with EWC::internalFindW for "
00585         << toString());    
00586       return rtn;
00587     }
00588 
00589     /* The only possibility remaining is that I'm a product.
00590      * If any term is zero, I am zero. If a term is 
00591      * known to be zero, it's index will not appear in Q, so that 
00592      * comparing the size of Q and the number of children tells me
00593      * if I'm zero.
00594      */
00595     if (((int) Q.size()) == numChildren())
00596     {
00597       rtn.put(MultipleDeriv());
00598     }
00599     SUNDANCE_MSG3(verb, tab1 << "I am a product");  
00600     SUNDANCE_MSG3(verb, tab1 << "W[" << order << "]=" << rtn);
00601     SUNDANCE_MSG3(verb, tab0 << "done with EWC::internalFindW for "
00602       << toString());
00603     return rtn;
00604   }
00605 
00606 
00607   /* now do arbitrary order derivatives with the multivariable chain rule*/
00608   Array<Array<Array<int> > > comp = compositions(order);
00609   for (int i=1; i<=order; i++) 
00610   {
00611     Tabs tab1;
00612     SUNDANCE_MSG3(verb, tab1 << "doing order=" << i);  
00613 
00614     const Set<MultiSet<int> >& QW = findQ_W(i, context);
00615 
00616     SUNDANCE_MSG3(verb, tab1 << "QW=" << QW);  
00617       
00618     for (Set<MultiSet<int> >::const_iterator j=QW.begin(); j!=QW.end(); j++)
00619     {
00620       Array<int> J = j->elements();
00621       const Array<Array<int> >& K = comp[J.size()-1];
00622 
00623       for (int k=0; k<K.size(); k++)
00624       {
00625         Set<MultipleDeriv> WProd = product(J, K[k], AllNonzeros, context);
00626         rtn.merge(WProd);
00627       }
00628     }
00629   }
00630 
00631   SUNDANCE_MSG3(verb, tab0 << "W[" << order << "]=" << rtn);
00632   SUNDANCE_MSG3(verb, tab0 << "done with EWC::internalFindW for "
00633     << toString());
00634   return rtn;
00635 }
00636 
00637 const Set<MultiSet<int> >& 
00638 ExprWithChildren::findQ_W(int order, 
00639   const EvalContext& context) const
00640 {
00641   Tabs tab1;
00642   int verb = context.setupVerbosity();
00643   SUNDANCE_MSG3(verb, tab1 << "finding Q_W");  
00644   if (!contextToQWMap_[order].containsKey(context))
00645   {
00646     contextToQWMap_[order].put(context, internalFindQ_W(order, context));
00647   }
00648   else
00649   {
00650     SUNDANCE_MSG3(verb, tab1 << "using previously computed Q_W");  
00651   }
00652   return contextToQWMap_[order].get(context);
00653 
00654 }
00655 
00656 const Set<MultiSet<int> >& 
00657 ExprWithChildren::findQ_V(int order, 
00658   const EvalContext& context) const
00659 {
00660   if (!contextToQVMap_[order].containsKey(context))
00661   {
00662     contextToQVMap_[order].put(context, internalFindQ_V(order, context));
00663   }
00664   return contextToQVMap_[order].get(context);
00665 }
00666 
00667 const Set<MultiSet<int> >& 
00668 ExprWithChildren::findQ_C(int order, 
00669   const EvalContext& context) const
00670 {
00671   if (!contextToQCMap_[order].containsKey(context))
00672   {
00673     contextToQCMap_[order].put(context, internalFindQ_C(order, context));
00674   }
00675   return contextToQCMap_[order].get(context);
00676 }
00677 
00678 
00679 const Set<MultiSet<int> >& ExprWithChildren::getI_N() const
00680 {
00681   if (!cachedI_N().containsKey(numChildren()))
00682   {
00683     Set<MultiSet<int> > x;
00684     for (int i=0; i<numChildren(); i++)
00685     {
00686       x.put(makeMultiSet<int>(i));
00687     }
00688     cachedI_N().put(numChildren(), x);
00689   }
00690   return cachedI_N().get(numChildren());
00691 }
00692 
00693 Set<MultiSet<int> > ExprWithChildren::indexSetProduct(const Set<MultiSet<int> >& a,
00694   const Set<MultiSet<int> >& b) const
00695 {
00696   Set<MultiSet<int> > rtn;
00697   for (Set<MultiSet<int> >::const_iterator i=a.begin(); i!=a.end(); i++)
00698   {
00699     for (Set<MultiSet<int> >::const_iterator j=b.begin(); j!=b.end(); j++)
00700     {
00701       MultiSet<int> ab = (*i).merge(*j);
00702       rtn.put(ab);
00703     }
00704   }
00705   return rtn;
00706 }
00707 
00708 
00709 Set<MultiSet<int> > ExprWithChildren::internalFindQ_V(int order, 
00710   const EvalContext& context) const
00711 {
00712   Tabs tab0;
00713   int verb = context.setupVerbosity();
00714   SUNDANCE_MSG3(verb, tab0 << "EWC::internalFindQ_V(order=" << order <<")");
00715   Set<MultiSet<int> > rtn;
00716 
00717   if (!isLinear())
00718   {
00719     bool isVar = false;
00720     for (int i=0; i<numChildren(); i++)
00721     {
00722       if (childIsRequired(i,order,context) && evaluatableChild(i)->findV(0, context).size() != 0) 
00723       {
00724         isVar=true;
00725         break;
00726       }
00727     }
00728     if (isVar) rtn = findQ_W(order, context); 
00729   }
00730   SUNDANCE_MSG3(verb, tab0 << "Q_V = " << rtn);
00731   return rtn;
00732 }
00733 
00734 Set<MultiSet<int> > ExprWithChildren::internalFindQ_C(int order, 
00735   const EvalContext& context) const
00736 {
00737   if (isLinear()) return findQ_W(order,context);
00738 
00739   return findQ_W(order,context).setDifference(findQ_V(order, context));
00740 }
00741 
00742 
00743 Set<MultiSet<int> > ExprWithChildren
00744 ::internalFindQ_W(int order, 
00745   const EvalContext& context) const
00746 {
00747   Tabs tab0;
00748   int verb = context.setupVerbosity();
00749   SUNDANCE_MSG3(verb, tab0 << "in internalFindQ_W");
00750   Set<MultiSet<int> > rtn;
00751   const Set<MultiSet<int> >& I_N = getI_N();
00752   SUNDANCE_MSG3(verb, tab0 << "I_N=" << I_N);
00753 
00754   if (isLinear())
00755   {
00756     Tabs tab1;
00757     /* first derivatives of the sum wrt the arguments are 
00758      * always nonzero */
00759     if (order==1) 
00760     {
00761       SUNDANCE_MSG3(verb, tab1 << "is linear, order=1, so Q_W = I_N");
00762       return I_N;
00763     }
00764     /* zeroth derivatives are nonzero if terms are nonzero */
00765     if (order==0)
00766     {
00767       SUNDANCE_MSG3(verb, tab1 << "is linear, order=0");
00768       for (int i=0; i<numChildren(); i++)
00769       {
00770         const Set<MultipleDeriv>& W_i = evaluatableChild(i)->findW(0,context);
00771         SUNDANCE_MSG3(verb, tab1 << "is linear, order=0");
00772         if (W_i.size() > 0) 
00773         {
00774           Tabs tab2;
00775           SUNDANCE_MSG3(verb, tab2 << "child " << i << " is nonzero");
00776           rtn.put(makeMultiSet(i));
00777         }
00778         else
00779         {
00780           Tabs tab2;
00781           SUNDANCE_MSG3(verb, tab2 << "child " << i << " is zero");
00782         }
00783       }
00784     }
00785   }
00786   else
00787   {
00788     Tabs tab1;
00789     SUNDANCE_MSG3(verb, tab1 << "is nonlinear, using all index set products");
00790     rtn = I_N;
00791       
00792     for (int i=1; i<order; i++)
00793     {
00794       rtn = indexSetProduct(rtn, I_N);
00795     }
00796   }
00797   return rtn;
00798 }
00799 
00800 bool ExprWithChildren::childIsRequired(int index, int diffOrder,
00801   const EvalContext& context) const
00802 {
00803   const Set<MultiSet<int> >& Q = findQ_W(diffOrder, context);
00804   for (Set<MultiSet<int> >::const_iterator it=Q.begin(); it != Q.end(); it++)
00805   {
00806     if (it->contains(index)) return true;
00807   }
00808   return true;
00809 }
00810 
00811 RCP<Array<Set<MultipleDeriv> > > ExprWithChildren
00812 ::internalDetermineR(const EvalContext& context,
00813   const Array<Set<MultipleDeriv> >& RInput) const
00814 {
00815   Tabs tab0;
00816   int verb = context.setupVerbosity();
00817   RCP<Array<Set<MultipleDeriv> > > rtn 
00818     = rcp(new Array<Set<MultipleDeriv> >(RInput.size()));
00819 
00820   SUNDANCE_MSG3(verb, tab0 << "in internalDetermineR() for " << toString());
00821   SUNDANCE_MSG3(verb, tab0 << "RInput = " << RInput);
00822 
00823 
00824 
00825   for (int i=0; i<RInput.size(); i++)
00826   {
00827     if (RInput[i].size()==0) continue;
00828     const Set<MultipleDeriv>& Wi = findW(i, context);
00829     (*rtn)[i] = RInput[i].intersection(Wi);
00830   }
00831 
00832   int maxOrder = rtn->size()-1;
00833 
00834   const Set<MultiSet<int> >& Q1 = findQ_W(1, context);
00835   const Set<MultiSet<int> >& Q2 = findQ_W(2, context);
00836   const Set<MultiSet<int> >& Q3 = findQ_W(3, context);
00837 
00838   SUNDANCE_MSG5(verb, tab0 << "Q1 = " << Q1);
00839   SUNDANCE_MSG5(verb, tab0 << "Q2 = " << Q2);
00840   SUNDANCE_MSG5(verb, tab0 << "Q3 = " << Q3);
00841 
00842   for (int i=0; i<numChildren(); i++)
00843   {
00844     Tabs tab1;
00845     MultiSet<int> mi = makeMultiSet(i);
00846     SUNDANCE_MSG5(verb, tab1 << "i=" << i << ", Q1_i = " << mi );
00847     TEST_FOR_EXCEPTION(mi.size() != 1, InternalError, "unexpected multiset size");
00848     //      int i = *(mi.begin());
00849     Set<MultipleDeriv> R11;
00850     Set<MultipleDeriv> R12;
00851     Set<MultipleDeriv> R13;
00852     Set<MultipleDeriv> R22;
00853     Set<MultipleDeriv> R23;
00854     Set<MultipleDeriv> R33;
00855     if (maxOrder >= 1) 
00856     {
00857       R11 = (*rtn)[1];
00858       if (maxOrder >=2) R22 = (*rtn)[2];
00859       if (maxOrder >=3) R33 = (*rtn)[3];
00860     }
00861     if (maxOrder >= 2)
00862     {
00863       Tabs tab2;
00864       Set<MultiSet<int> > jSet = setDivision(Q2, i);
00865       SUNDANCE_MSG5(verb, tab2 << "Q2/i = " << jSet);
00866       for (Set<MultiSet<int> >::const_iterator 
00867              j=jSet.begin(); j!=jSet.end(); j++)
00868       {
00869         Tabs tab3;
00870         TEST_FOR_EXCEPTION(j->size()!=1, InternalError, 
00871           "unexpected set size");
00872         int jIndex = *(j->begin());
00873         SUNDANCE_MSG5(verb,  tab3 << "j=" << jIndex );
00874         const Set<MultipleDeriv>& W1j = evaluatableChild(jIndex)->findW(1, context);
00875         Set<MultipleDeriv> ROverW = setDivision((*rtn)[2], W1j);
00876         R12.merge(ROverW);
00877         SUNDANCE_MSG5(verb,  tab3 << "R2=" << (*rtn)[2] );
00878         SUNDANCE_MSG5(verb,  tab3 << "W1(j)=" << W1j );
00879         SUNDANCE_MSG5(verb,  tab3 << "R2/W1(j)=" << ROverW );
00880 
00881         if (maxOrder>=3)
00882         {
00883           const Set<MultipleDeriv>& W2j 
00884             = evaluatableChild(jIndex)->findW(2, context);             
00885           R13.merge(setDivision((*rtn)[3], W2j));
00886           R23.merge(setDivision((*rtn)[3], W1j));
00887         }
00888       }
00889     }
00890     if (maxOrder >= 3)
00891     {
00892       Set<MultiSet<int> > jkSet = setDivision(Q3, i);
00893       for (Set<MultiSet<int> >::const_iterator 
00894              jk=jkSet.begin(); jk!=jkSet.end(); jk++)
00895       {
00896         TEST_FOR_EXCEPTION(jk->size()!=2, InternalError, 
00897           "unexpected set size");
00898         Array<int> jka = jk->elements();
00899         int j = jka[0];
00900         int k = jka[1];
00901         const Set<MultipleDeriv>& W1j = evaluatableChild(j)->findW(1, context);
00902         const Set<MultipleDeriv>& W1k = evaluatableChild(k)->findW(1, context);
00903         R13.merge(setDivision((*rtn)[3], setProduct(W1j, W1k)));
00904       }
00905     }
00906     SUNDANCE_MSG5(verb,  tab1 << "R11 = " << R11 );
00907     SUNDANCE_MSG5(verb,  tab1 << "R12 = " << R12 );
00908     SUNDANCE_MSG5(verb,  tab1 << "R13 = " << R13 );
00909     SUNDANCE_MSG5(verb,  tab1 << "R22 = " << R22 );
00910     SUNDANCE_MSG5(verb,  tab1 << "R23 = " << R23 );
00911     SUNDANCE_MSG5(verb,  tab1 << "R33 = " << R33 );
00912     Set<MultipleDeriv> R1 = R11;
00913     R1.merge(R12);
00914     R1.merge(R13);
00915     Set<MultipleDeriv> R2 = R22;
00916     R2.merge(R23);
00917     Set<MultipleDeriv> R3 = R33;
00918 
00919     Set<MultipleDeriv> R0;
00920     bool childIsNeeded = (*rtn)[0].size() > 0;
00921     if (!childIsNeeded && R1.size() > 0) childIsNeeded = childIsRequired(i, 2, context);
00922     if (!childIsNeeded && R2.size() > 0) childIsNeeded = childIsRequired(i, 3, context);
00923     if (!childIsNeeded && R3.size() > 0) childIsNeeded = childIsRequired(i, 4, context);
00924     if (childIsNeeded) R0.put(MultipleDeriv());
00925       
00926     Array<Set<MultipleDeriv> > RChild;
00927       
00928     RChild.append(R0);
00929     if (maxOrder >= 1) RChild.append(R1);
00930     if (maxOrder >= 2) RChild.append(R2);
00931     if (maxOrder >= 3) RChild.append(R3);
00932     SUNDANCE_MSG5(verb,  tab1 << "RChild = " << RChild );
00933     evaluatableChild(i)->determineR(context, RChild);
00934   }
00935 
00936   SUNDANCE_MSG3(verb,  tab0 << "R = " << (*rtn) );
00937   SUNDANCE_MSG3(verb, tab0 << "done with EWC::internalDetermineR for "
00938     << toString());
00939   
00940   return rtn;
00941 }
00942 
00943 
00944 
00945 
00946 void ExprWithChildren::displayNonzeros(std::ostream& os, const EvalContext& context) const 
00947 {
00948   Tabs tabs0;
00949   os << tabs0 << "Nonzeros of " << toString() << std::endl;
00950   os << tabs0 << "Diving into children " << std::endl;
00951 
00952   for (int i=0; i<numChildren(); i++)
00953   {
00954     Tabs tab1;
00955     os << tab1 << "Child " << i << std::endl;
00956     evaluatableChild(i)->displayNonzeros(os, context);
00957   }
00958 
00959   os << tabs0 << "Printing nonzeros for parent " << toString() << std::endl;
00960   const Set<MultipleDeriv>& W = findW(context);
00961   const Set<MultipleDeriv>& R = findR(context);
00962   const Set<MultipleDeriv>& C = findC(context);
00963 
00964   
00965   for (Set<MultipleDeriv>::const_iterator i=W.begin(); i != W.end(); i++)
00966   {
00967     Tabs tab1;
00968     std::string state = "Variable";
00969     if (C.contains(*i)) state = "Constant";
00970     if (!R.contains(*i)) state = "Not Required";
00971     os << tab1 << std::setw(25) << std::left << i->toString() << ": " << state << std::endl;
00972   }
00973 }
00974 
00975 
00976 namespace Sundance {
00977  
00978 Array<Array<std::pair<int, Array<MultipleDeriv> > > >  
00979 chainRuleDerivsOfArgs(int nArgs,
00980   const MultiSet<int>& bSet,
00981   const MultipleDeriv& c)
00982 {
00983   Array<Array<std::pair<int, Array<MultipleDeriv> > > > rtn;
00984 
00985   /* convert to tuple representation of b */
00986   Array<int> b(nArgs, 0);
00987   int J = 0;
00988   for (MultiSet<int>::const_iterator i=bSet.begin(); i!=bSet.end(); i++)
00989   {
00990     b[*i]++;
00991     J++;
00992   }
00993       
00994   /* count orders of each functional deriv in c */
00995   Sundance::Map<Deriv, int> counts;
00996   Array<Deriv> d;
00997   typedef Sundance::Map<Deriv, int>::const_iterator iter;
00998   for (MultipleDeriv::const_iterator i=c.begin(); i!=c.end(); i++)
00999   {
01000     if (!counts.containsKey(*i)) counts.put(*i, 1);
01001     else counts[*i]++;
01002     d.append(*i);
01003   }
01004 
01005   Array<Array<Array<Array<int> > > > a;
01006   Array<int> s;
01007   for (iter i=counts.begin(); i!=counts.end(); i++)
01008   {
01009     Array<Array<int> > tmp = nonNegCompositions(i->second, J);
01010     Array<Array<Array<int> > > ai = bStructure(b, tmp);
01011     a.append(ai);
01012     s.append(ai.size());
01013   }
01014 
01015   Array<Array<int> > ic = indexCombinations(s);
01016 
01017 
01018 
01019   Array<Array<Array<Array<int> > > > all;
01020   for (int i=0; i<ic.size(); i++)
01021   {
01022     bool good = true;
01023     int numFuncs = ic[i].size();
01024     Array<Array<Array<int> > > tmp;
01025 
01026     Array<Array<int> > aTot(nArgs);
01027     for (int j=0; j<nArgs; j++)
01028     {
01029       if (b[j] > 0) aTot[j].resize(b[j]);
01030       for (int k=0; k<b[j]; k++) aTot[j][k] = 0;
01031     }
01032     for (int f=0; f<numFuncs; f++)
01033     {
01034       bool skip = false;
01035       const Array<Array<int> >& e = a[f][ic[i][f]];
01036       for (int j=0; j<nArgs; j++)
01037       {
01038         for (int k=0; k<b[j]; k++)
01039         {
01040           aTot[j][k] += e[j][k];
01041         }
01042       }
01043       if (!skip) tmp.append(e);
01044     }
01045 
01046     for (int j=0; j<nArgs; j++)
01047     {
01048       for (int k=0; k<b[j]; k++)
01049       {
01050         if (aTot[j][k] == 0) good = false;
01051       }
01052     }
01053     if (good) all.append(tmp);
01054   }
01055 
01056       
01057   for (int p=0; p<all.size(); p++)
01058   {
01059     Array<std::pair<int, Array<MultipleDeriv> > > terms;
01060     for (int j=0; j<nArgs; j++)
01061     {
01062       std::pair<int, Array<MultipleDeriv> > factors;
01063       factors.first = j;
01064       for (int k=0; k<b[j]; k++)
01065       {
01066         MultipleDeriv md;
01067         for (int i=0; i<all[p].size(); i++)
01068         {
01069           int order = all[p][i][j][k];
01070           if (order > 0)
01071           {
01072             md.put(d[i]);
01073           }
01074         }
01075         if (md.order() > 0) factors.second.append(md);
01076       }
01077       if (factors.second.size() > 0) terms.append(factors);
01078     }
01079     rtn.append(terms);
01080   }
01081 
01082   return rtn;
01083 }
01084 
01085 
01086 Array<Array<Array<int> > > bStructure(const Array<int>& b,
01087   const Array<Array<int> >& tmp)
01088 {
01089   Array<Array<Array<int> > > rtn(tmp.size());
01090       
01091   for (int p=0; p<tmp.size(); p++)
01092   {
01093     int count=0;
01094     rtn[p].resize(b.size());
01095     for (int j=0; j<b.size(); j++)
01096     {
01097       rtn[p][j].resize(b[j]);
01098       for (int k=0; k<b[j]; k++, count++)
01099       {
01100         rtn[p][j][k] = tmp[p][count];
01101       }
01102     }
01103   }
01104   return rtn;
01105 }
01106     
01107 Array<OrderedPair<Array<MultiSet<int> >, Array<MultipleDeriv> > >
01108 chainRuleTerms(int s, 
01109   const MultiSet<int>& lambda,
01110   const MultipleDeriv& nu)
01111 {
01112   Array<Array<MultiSet<int> > > allK = multisetCompositions(s, lambda);
01113 
01114   Array<MultipleDeriv> allL = multisetSubsets(nu).elements();
01115 
01116   Array<Array<int> > indexTuples = distinctIndexTuples(s, allL.size());
01117 
01118   Array<Array<MultipleDeriv> > allLTuples;
01119   for (int i=0; i<indexTuples.size(); i++)
01120   {
01121     Array<MultipleDeriv> t(s);
01122     for (int p=0; p<s; p++) t[p] = allL[indexTuples[i][p]];
01123     allLTuples.append(t);
01124   }
01125 
01126   Array<OrderedPair<Array<MultiSet<int> >, Array<MultipleDeriv> > > rtn;
01127   for (int i=0; i<allLTuples.size(); i++)
01128   {
01129     for (int j=0; j<allK.size(); j++)
01130     {
01131       MultipleDeriv result;
01132       for (int p=0; p<s; p++)
01133       {
01134         for (unsigned int q=0; q<allK[j][p].size(); q++)
01135         {
01136           result = result.product(allLTuples[i][p]);
01137         }
01138       }
01139       if (result==nu) 
01140       {
01141         OrderedPair<Array<MultiSet<int> >, Array<MultipleDeriv> >
01142           kl(allK[j], allLTuples[i]);
01143         rtn.append(kl);
01144       }
01145     }
01146   }
01147   return rtn;
01148 }
01149 
01150 Set<MultipleDeriv> multisetSubsets(const MultipleDeriv& nu)
01151 {
01152   /* We'll generate the subsets by traversing them in bitwise order.
01153    * For a multiset having N elements, there are up to 2^N subsets each
01154    * of which can be described by a N-bit number with the i-th
01155    * bit indicating whether the i-th element is in the subset. Note that
01156    * with a multiset, repetitions can occur so we need to record the
01157    * results in a Set object to eliminate duplicates. 
01158    */
01159 
01160   /* Make an indexable array of the elements. This will be convenient
01161    * because we'll need to access the i-th element after reading
01162    * the i-th bit. */
01163   Array<Deriv> elements = nu.elements();
01164 
01165   /* Compute the maximum number of subsets. This number will be reached
01166    * only in the case of no repetitions. */
01167   int n = elements.size();
01168   int maxNumSubsets = pow2(n);
01169     
01170   Set<MultipleDeriv> rtn;
01171     
01172     
01173   /* Loop over subsets in bitwise order. We start the count at 1 
01174      to avoid including the empty subset */
01175   for (int i=1; i<maxNumSubsets; i++)
01176   {
01177     Array<int> bits = bitsOfAnInteger(i, n);
01178     MultipleDeriv md;
01179     for (int j=0; j<n; j++) 
01180     {
01181       if (bits[j] == 1) md.put(elements[j]);
01182     }
01183     rtn.put(md);
01184   }
01185   return rtn;
01186 }
01187 
01188 
01189   
01190 int chainRuleMultiplicity(const MultipleDeriv& nu,
01191   const Array<MultiSet<int> >& K,
01192   const Array<MultipleDeriv>& L)
01193 {
01194   int rtn = factorial(nu);
01195   for (int i=0; i<K.size(); i++)
01196   {
01197     rtn = rtn/factorial(K[i]);
01198     int lFact = factorial(L[i]);
01199     int lPow = 1;
01200     int kNorm = K[i].size();
01201     for (int j=0; j<kNorm; j++) lPow *= lFact;
01202     TEST_FOR_EXCEPT(rtn % lPow != 0);
01203     rtn = rtn/lPow;
01204   }
01205   return rtn;
01206 }
01207 
01208 
01209 }
01210 
01211 
01212 

Site Contact