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

Site Contact