00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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
00162
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
00290 int count = EvaluatableExpr::countNodes();
00291
00292
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
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
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
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
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
00542 if (order==0)
00543 {
00544 Tabs tab1;
00545 SUNDANCE_MSG3(verb, tab1 << "case: order=0");
00546
00547
00548
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
00561
00562
00563 SUNDANCE_MSG3(verb, tab1 << "getting Q");
00564 const Set<MultiSet<int> >& Q = findQ_W(0, context);
00565
00566
00567
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
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
00590
00591
00592
00593
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
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
00758
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
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
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
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
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
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163 Array<Deriv> elements = nu.elements();
01164
01165
01166
01167 int n = elements.size();
01168 int maxNumSubsets = pow2(n);
01169
01170 Set<MultipleDeriv> rtn;
01171
01172
01173
01174
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