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
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include "SundanceFunctionalPolynomial.hpp"
00043 #include "PlayaTabs.hpp"
00044 #include "SundanceOut.hpp"
00045 #include "SundanceExpr.hpp"
00046 #include "SundanceEvaluatorFactory.hpp"
00047 #include "SundanceEvaluator.hpp"
00048 #include "SundanceSymbolicFuncElement.hpp"
00049 #include "SundanceDerivOfSymbFunc.hpp"
00050 #include "SundanceUnaryExpr.hpp"
00051
00052
00053 using namespace Sundance;
00054 using namespace Sundance;
00055
00056 using namespace Sundance;
00057 using namespace Teuchos;
00058
00059
00060
00061 FunctionalPolynomial::FunctionalPolynomial(const RCP<ScalarExpr>& expr)
00062 : funcs_(),
00063 funcMultiIndices_(),
00064 coeffs_(),
00065 keys_()
00066 {
00067 TEUCHOS_TEST_FOR_EXCEPTION(!isConvertibleToPoly(expr.get()), std::logic_error,
00068 "FunctionalPolynomial ctor called with an argument that "
00069 "cannot be converted to a polynomial");
00070 int funcID;
00071 MultiIndex mi;
00072 Deriv deriv;
00073
00074 const SymbolicFuncElement* s
00075 = dynamic_cast<const SymbolicFuncElement*>(expr.get());
00076 if (s != 0)
00077 {
00078 mi = MultiIndex();
00079 deriv = funcDeriv(s);
00080 }
00081
00082 const DerivOfSymbFunc* d
00083 = dynamic_cast<const DerivOfSymbFunc*>(expr.get());
00084 if (d != 0)
00085 {
00086 deriv = d->representMeAsFunctionalDeriv();
00087 }
00088
00089 MultipleDeriv mu;
00090 mu.put(deriv);
00091
00092
00093 if (d != 0 || s != 0)
00094 {
00095 funcs_.put(funcID, expr);
00096 Set<MultiIndex> miSet;
00097 miSet.put(mi);
00098 funcMultiIndices_.put(funcID, miSet);
00099
00100 Expr coeff = 1.0;
00101 RCP<ScalarExpr> cPtr = rcp_dynamic_cast<ScalarExpr>(coeff.ptr());
00102
00103 coeffs_.resize(2);
00104 keys_.resize(2);
00105 coeffs_[1].put(mu, cPtr);
00106 keys_[1].put(mu);
00107 }
00108 else
00109 {
00110 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
00111 "impossible case in FunctionalPolynomial ctor");
00112 }
00113 }
00114
00115
00116 FunctionalPolynomial::FunctionalPolynomial(const Map<int, RCP<ScalarExpr> >& funcs,
00117 const Map<int, Set<MultiIndex> >& funcMultiIndices,
00118 const Array<Map<MultipleDeriv, RCP<ScalarExpr> > > & coeffs)
00119 : funcs_(funcs),
00120 funcMultiIndices_(funcMultiIndices),
00121 coeffs_(coeffs),
00122 keys_(coeffs.size())
00123 {
00124 typedef Map<MultipleDeriv, RCP<ScalarExpr> > termMap;
00125
00126 for (int i=0; i < coeffs_.size(); i++)
00127 {
00128 for (termMap::const_iterator
00129 j = coeffs_[i].begin(); j != coeffs_[i].end(); j++)
00130 {
00131 const MultipleDeriv& key = j->first;
00132 keys_[i].put(key);
00133 }
00134 }
00135 }
00136
00137
00138 Set<MultipleDeriv>
00139 FunctionalPolynomial::internalFindW(int order, const EvalContext& context) const
00140 {
00141 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
00142 "FunctionalPolynomial not implemented");
00143 return Set<MultipleDeriv> ();
00144 }
00145
00146
00147 RCP<FunctionalPolynomial> FunctionalPolynomial::
00148 addPoly(const FunctionalPolynomial* other, int sign) const
00149 {
00150 typedef Map<MultipleDeriv, RCP<ScalarExpr> > termMap;
00151 Map<int, RCP<ScalarExpr> > newFuncs = funcs_;
00152 Map<int, Set<MultiIndex> > newFuncMultiIndices = funcMultiIndices_;
00153 Array<Map<MultipleDeriv, RCP<ScalarExpr> > > newCoeffs = coeffs_;
00154
00155 if (other->coeffs_.size() > coeffs_.size())
00156 newCoeffs.resize(other->coeffs_.size());
00157
00158
00159 for (int i=0; i < other->coeffs_.size(); i++)
00160 {
00161
00162 for (termMap::const_iterator
00163 j = other->coeffs_[i].begin(); j != other->coeffs_[i].end(); j++)
00164 {
00165 const MultipleDeriv& key = j->first;
00166 Expr right = Expr::handle(j->second);
00167 Expr sum;
00168
00169 if (newCoeffs[i].containsKey(key))
00170 {
00171 Expr left = Expr::handle(newCoeffs[i].get(key));
00172
00173 if (sign > 0) sum = left + right;
00174 else sum = left - right;
00175 }
00176 else
00177 {
00178 if (sign > 0) sum = right;
00179 else sum = -right;
00180 }
00181
00182 const ScalarExpr* se = dynamic_cast<const ScalarExpr*>(sum.ptr().get());
00183 TEUCHOS_TEST_FOR_EXCEPTION(se==0, std::logic_error,
00184 "Sum could not be cast to scalar expression");
00185 newCoeffs[i].put(key, rcp_dynamic_cast<ScalarExpr>(sum.ptr()));
00186 }
00187 }
00188
00189 for (Map<int, RCP<ScalarExpr> >::const_iterator
00190 i = other->funcs_.begin(); i != other->funcs_.end(); i++)
00191 {
00192 newFuncs.put(i->first, i->second);
00193 }
00194
00195 for (Map<int, Set<MultiIndex> >::const_iterator
00196 i = other->funcMultiIndices_.begin();
00197 i != other->funcMultiIndices_.end(); i++)
00198 {
00199 newFuncMultiIndices.put(i->first, i->second);
00200 }
00201
00202
00203
00204 return rcp(new FunctionalPolynomial(newFuncs, newFuncMultiIndices, newCoeffs));
00205 }
00206
00207 RCP<FunctionalPolynomial> FunctionalPolynomial::
00208 multiplyPoly(const FunctionalPolynomial* other) const
00209 {
00210 typedef Map<MultipleDeriv, RCP<ScalarExpr> > termMap;
00211 Map<int, RCP<ScalarExpr> > newFuncs;
00212 Map<int, Set<MultiIndex> > newFuncMultiIndices;
00213 Array<Map<MultipleDeriv, RCP<ScalarExpr> > > newCoeffs;
00214
00215 newCoeffs.resize(coeffs_.size() + other->coeffs_.size() - 1);
00216
00217 for (int i=0; i < coeffs_.size(); i++)
00218 {
00219 for (int j = 0; j<other->coeffs_.size(); j++)
00220 {
00221 for (termMap::const_iterator
00222 me = coeffs_[i].begin(); me != coeffs_[i].end(); me++)
00223 {
00224 const MultipleDeriv& myKey = me->first;
00225 Expr myExpr = Expr::handle(me->second);
00226 for (termMap::const_iterator
00227 you = other->coeffs_[j].begin();
00228 you != other->coeffs_[j].end(); you++)
00229 {
00230 const MultipleDeriv& yourKey = you->first;
00231 Expr yourExpr = Expr::handle(you->second);
00232 MultipleDeriv newKey = myKey.product(yourKey);
00233 int order = i+j;
00234 Expr newTerm = myExpr*yourExpr;
00235 if (newCoeffs[order].containsKey(newKey))
00236 {
00237 Expr old = Expr::handle(newCoeffs[i].get(newKey));
00238 newTerm = newTerm + old;
00239 }
00240 const ScalarExpr* se
00241 = dynamic_cast<const ScalarExpr*>(newTerm.ptr().get());
00242 TEUCHOS_TEST_FOR_EXCEPTION(se==0, std::logic_error,
00243 "New coeff could not be cast to scalar expression");
00244 newCoeffs[order].put(newKey,
00245 rcp_dynamic_cast<ScalarExpr>(newTerm.ptr()));
00246 }
00247 }
00248 }
00249 }
00250
00251 for (Map<int, RCP<ScalarExpr> >::const_iterator
00252 i = funcs_.begin(); i != funcs_.end(); i++)
00253 {
00254 newFuncs.put(i->first, i->second);
00255 }
00256 for (Map<int, RCP<ScalarExpr> >::const_iterator
00257 i = other->funcs_.begin(); i != other->funcs_.end(); i++)
00258 {
00259 newFuncs.put(i->first, i->second);
00260 }
00261
00262 for (Map<int, Set<MultiIndex> >::const_iterator
00263 i = funcMultiIndices_.begin();
00264 i != funcMultiIndices_.end(); i++)
00265 {
00266 newFuncMultiIndices.put(i->first, i->second);
00267 }
00268 for (Map<int, Set<MultiIndex> >::const_iterator
00269 i = other->funcMultiIndices_.begin();
00270 i != other->funcMultiIndices_.end(); i++)
00271 {
00272 Set<MultiIndex> miSet = i->second;
00273 if (newFuncMultiIndices.containsKey(i->first))
00274 {
00275 miSet.merge(newFuncMultiIndices.get(i->first));
00276 }
00277 newFuncMultiIndices.put(i->first, miSet);
00278 }
00279
00280 return rcp(new FunctionalPolynomial(newFuncs, newFuncMultiIndices, newCoeffs));
00281 }
00282
00283 RCP<FunctionalPolynomial> FunctionalPolynomial::
00284 addFunction(const RCP<ScalarExpr>& u, int sign) const
00285 {
00286 RCP<FunctionalPolynomial> other = rcp(new FunctionalPolynomial(u));
00287 return addPoly(other.get(), sign);
00288 }
00289
00290 RCP<FunctionalPolynomial> FunctionalPolynomial::
00291 multiplyScalar(const RCP<ScalarExpr>& alpha) const
00292 {
00293 typedef Map<MultipleDeriv, RCP<ScalarExpr> > termMap;
00294
00295 Array<Map<MultipleDeriv, RCP<ScalarExpr> > > newCoeffs = coeffs_;
00296
00297 Expr alphaExpr = Expr::handle(alpha);
00298
00299 for (int i=0; i < coeffs_.size(); i++)
00300 {
00301 for (termMap::const_iterator
00302 j = coeffs_[i].begin(); j != coeffs_[i].end(); j++)
00303 {
00304 const MultipleDeriv& key = j->first;
00305 Expr oldCoeff = Expr::handle(j->second);
00306 Expr newCoeff = alphaExpr*oldCoeff;
00307
00308 const ScalarExpr* se
00309 = dynamic_cast<const ScalarExpr*>(newCoeff.ptr().get());
00310 TEUCHOS_TEST_FOR_EXCEPTION(se==0, std::logic_error,
00311 "Coefficient could not be cast to "
00312 "scalar expression");
00313
00314 newCoeffs[i].put(key, rcp_dynamic_cast<ScalarExpr>(newCoeff.ptr()));
00315 }
00316 }
00317
00318 return rcp(new FunctionalPolynomial(funcs_, funcMultiIndices_, newCoeffs));
00319 }
00320
00321
00322 Evaluator* FunctionalPolynomial::createEvaluator(const EvaluatableExpr* expr,
00323 const EvalContext& context) const
00324 {
00325 TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, "poly eval not ready");
00326 return (Evaluator*) 0;
00327 }
00328
00329
00330
00331 bool FunctionalPolynomial::isConvertibleToPoly(const ScalarExpr* expr)
00332 {
00333 const SymbolicFuncElement* s
00334 = dynamic_cast<const SymbolicFuncElement*>(expr);
00335
00336 const DerivOfSymbFunc* d
00337 = dynamic_cast<const DerivOfSymbFunc*>(expr);
00338
00339 const FunctionalPolynomial* p
00340 = dynamic_cast<const FunctionalPolynomial*>(expr);
00341
00342 return (s != 0 || d != 0 || p != 0);
00343 }
00344
00345
00346 RCP<FunctionalPolynomial> FunctionalPolynomial::toPoly(const RCP<ScalarExpr>& expr)
00347 {
00348 const FunctionalPolynomial* p
00349 = dynamic_cast<const FunctionalPolynomial*>(expr.get());
00350
00351 if (p != 0) return rcp_dynamic_cast<FunctionalPolynomial>(expr);
00352
00353 Expr rtn = new FunctionalPolynomial(expr);
00354 return rcp_dynamic_cast<FunctionalPolynomial>(rtn.ptr());
00355 }
00356
00357
00358 std::ostream& FunctionalPolynomial::toText(std::ostream& os, bool paren) const
00359 {
00360 os << evalString();
00361 return os;
00362 }
00363
00364
00365 XMLObject FunctionalPolynomial::toXML() const
00366 {
00367 XMLObject rtn("Polynomial");
00368 for (int order=0; order<coeffs_.size(); order++)
00369 {
00370 for (Map<MultipleDeriv, RCP<ScalarExpr> >::const_iterator
00371 i = coeffs_[order].begin(); i != coeffs_[order].end(); i++)
00372 {
00373 const MultipleDeriv& key = i->first;
00374 Expr e = Expr::handle(i->second);
00375 XMLObject term("Term");
00376 XMLObject coeff("Coeff");
00377 coeff.addChild(e.toXML());
00378 term.addChild(coeff);
00379 for (MultipleDeriv::const_iterator
00380 j = key.begin(); j != key.end(); j++)
00381 {
00382 XMLObject f("FunctionalDeriv");
00383 f.addAttribute("mu", j->toString());
00384 term.addChild(f);
00385 }
00386 rtn.addChild(term);
00387 }
00388 }
00389 return rtn;
00390 }
00391
00392 Set<Deriv> FunctionalPolynomial
00393 ::findFuncsForSummation(const Set<MultipleDeriv>& prevSet,
00394 const MultipleDeriv& currentDeriv) const
00395 {
00396 Set<Deriv> rtn;
00397
00398 for (Set<MultipleDeriv>::const_iterator
00399 i = prevSet.begin(); i != prevSet.end(); i++)
00400 {
00401 const MultipleDeriv& mdPrev = *i;
00402 TEUCHOS_TEST_FOR_EXCEPTION(currentDeriv.size()+1 != mdPrev.size(),
00403 std::logic_error,
00404 "deriv orders must differ by 1. Found "
00405 "currentDeriv.size()=" << currentDeriv.size()
00406 << " while mdPrev.size()=" << mdPrev.size());
00407
00408
00409
00410
00411
00412
00413 Set<Deriv> tmp;
00414 set_difference(mdPrev.begin(), mdPrev.end(),
00415 currentDeriv.begin(), currentDeriv.end(),
00416 inserter(tmp, tmp.begin()));
00417 if (tmp.size()==1)
00418 {
00419 const Deriv& d = *(tmp.begin());
00420 if (currentDeriv.upper_bound(d) == currentDeriv.end()) rtn.put(d);
00421 }
00422 }
00423 return rtn;
00424 }
00425
00426
00427 MultipleDeriv FunctionalPolynomial::successorTerm(const MultipleDeriv& md) const
00428 {
00429 MultipleDeriv rtn;
00430
00431 unsigned int k = 0;
00432 for (MultipleDeriv::const_iterator i=md.begin(); i!=md.end(); i++, k++)
00433 {
00434 if (k < md.size()-1) rtn.put(*i);
00435 }
00436 return rtn;
00437 }
00438
00439 void FunctionalPolynomial
00440 ::stepRecurrence(int level, const Map<MultipleDeriv, std::string>& sPrev,
00441 Map<MultipleDeriv, std::string>& sCurr) const
00442 {
00443 Set<MultipleDeriv> allKeys;
00444 Set<MultipleDeriv> inducedKeys;
00445 Set<MultipleDeriv> prevKeys;
00446 for (Map<MultipleDeriv, std::string>::const_iterator
00447 i = sPrev.begin(); i != sPrev.end(); i++)
00448 {
00449 inducedKeys.put(successorTerm(i->first));
00450 }
00451 for (Map<MultipleDeriv, std::string>::const_iterator
00452 i = sPrev.begin(); i != sPrev.end(); i++)
00453 {
00454 prevKeys.put(i->first);
00455 }
00456
00457 Out::os() << "keys from prev level are " << prevKeys << std::endl;
00458 Out::os() << "induced keys are " << inducedKeys << std::endl;
00459 Out::os() << "natural keys are " << keys_[level] << std::endl;
00460
00461 allKeys.merge(inducedKeys);
00462 allKeys.merge(keys_[level]);
00463
00464 Out::os() << "keys active at this level are " << allKeys << std::endl;
00465
00466 for (Set<MultipleDeriv>::const_iterator
00467 i = allKeys.begin(); i != allKeys.end(); i++)
00468 {
00469 const MultipleDeriv& key = *i;
00470 Out::os() << "working on key " << key << std::endl;
00471 std::string str;
00472 if (coeffs_[level].containsKey(key))
00473 {
00474 str = coeffs_[level].get(key)->toString();
00475 }
00476
00477 Set<Deriv> funcs = findFuncsForSummation(prevKeys, key);
00478 Out::os() << "funcs to sum are " << funcs << std::endl;
00479 for (Set<Deriv>::const_iterator
00480 j = funcs.begin(); j != funcs.end(); j++)
00481 {
00482 MultipleDeriv prevKey = key;
00483 Out::os() << "prev key = " << prevKey << std::endl;
00484 Out::os() << "func = " << *j << std::endl;
00485
00486
00487
00488
00489
00490 prevKey.put(*j);
00491 TEUCHOS_TEST_FOR_EXCEPTION(!sPrev.containsKey(prevKey), std::logic_error,
00492 "inconsisent key lookup");
00493 const std::string& prevStr = sPrev.get(prevKey);
00494 std::string funcStr = (*j).toString();
00495 if (str.length() > 0) str += " + ";
00496 str += funcStr + "*(" + prevStr + ")";
00497 }
00498 if (str.length() > 0) sCurr.put(key, str);
00499 }
00500 }
00501
00502 string FunctionalPolynomial::evalString() const
00503 {
00504 int maxLevel = coeffs_.size()-1;
00505
00506 Map<MultipleDeriv, std::string> sPrev;
00507 Map<MultipleDeriv, std::string> sCurr;
00508
00509 for (int level=maxLevel; level>=0; level--)
00510 {
00511 Out::os() << "********* Recurrence level = " << level << " ***************"
00512 << std::endl;
00513 sCurr = Map<MultipleDeriv, std::string>();
00514 stepRecurrence(level, sPrev, sCurr);
00515 sPrev = sCurr;
00516
00517 for (Map<MultipleDeriv, std::string>::const_iterator
00518 j = sCurr.begin(); j != sCurr.end(); j++)
00519 {
00520 Out::os() << "key=" << j->first << std::endl;
00521 Out::os() << "value=" << j->second << std::endl;
00522 }
00523 }
00524
00525
00526
00527
00528 return sCurr.begin()->second;
00529 }
00530
00531
00532
00533 bool FunctionalPolynomial::lessThan(const ScalarExpr* other) const
00534 {
00535 const FunctionalPolynomial* f = dynamic_cast<const FunctionalPolynomial*>(other);
00536 TEUCHOS_TEST_FOR_EXCEPTION(f==0, std::logic_error, "cast should never fail at this point");
00537
00538 TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, "FunctionalPolynomial::lessThan() not "
00539 "implemented");
00540 }
00541
00542