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 "SundanceProductEvaluator.hpp"
00032 #include "SundanceEvalManager.hpp"
00033 #include "SundanceProductExpr.hpp"
00034
00035 #include "PlayaTabs.hpp"
00036 #include "SundanceOut.hpp"
00037
00038 using namespace Sundance;
00039 using namespace Sundance;
00040 using namespace Sundance;
00041 using namespace Teuchos;
00042
00043
00044
00045
00046
00047 ProductEvaluator::ProductEvaluator(const ProductExpr* expr,
00048 const EvalContext& context)
00049 : BinaryEvaluator<ProductExpr>(expr, context),
00050 maxOrder_(this->sparsity()->maxOrder()),
00051 resultIndex_(maxOrder_+1),
00052 resultIsConstant_(maxOrder_+1),
00053 hasWorkspace_(maxOrder_+1),
00054 workspaceIsLeft_(maxOrder_+1),
00055 workspaceIndex_(maxOrder_+1),
00056 workspaceCoeffIndex_(maxOrder_+1),
00057 workspaceCoeffIsConstant_(maxOrder_+1),
00058 ccTerms_(maxOrder_+1),
00059 cvTerms_(maxOrder_+1),
00060 vcTerms_(maxOrder_+1),
00061 vvTerms_(maxOrder_+1),
00062 startingVectors_(maxOrder_+1),
00063 startingParities_(maxOrder_+1)
00064 {
00065 int verb = context.evalSetupVerbosity();
00066
00067 try
00068 {
00069 Tabs tabs(0);
00070 {
00071 Tabs tab;
00072 Tabs tabz;
00073 SUNDANCE_MSG1(verb,
00074 tabs << "initializing product evaluator for "
00075 << expr->toString());
00076
00077 SUNDANCE_MSG2(verb,
00078 tab << "return sparsity " << std::endl
00079 << tabz << *(this->sparsity)());
00080
00081 SUNDANCE_MSG2(verb,
00082 tab << "left sparsity " << std::endl
00083 << tabz << *(leftSparsity()) << std::endl
00084 << tabz << "right sparsity " << std::endl
00085 << tabz << *(rightSparsity()));
00086
00087 SUNDANCE_MSG3(verb,
00088 tab << "left vector index map "
00089 << leftEval()->vectorIndexMap() << std::endl
00090 << tabz << "right vector index map "
00091 << rightEval()->vectorIndexMap() << std::endl
00092 << tabz << "left constant index map "
00093 << leftEval()->constantIndexMap() << std::endl
00094 << tabz << "right constant index map "
00095 << rightEval()->constantIndexMap());
00096 }
00097 int vecResultIndex = 0;
00098 int constResultIndex = 0;
00099
00100 for (int i=0; i<this->sparsity()->numDerivs(); i++)
00101 {
00102 Tabs tab0;
00103 const MultipleDeriv& d = this->sparsity()->deriv(i);
00104
00105 SUNDANCE_MSG2(verb,
00106 tabs << std::endl
00107 << tabs << "finding rules for deriv " << d);
00108
00109 int order = d.order();
00110
00111
00112 bool resultIsConstant = this->sparsity()->state(i)==ConstantDeriv;
00113 resultIsConstant_[order].append(resultIsConstant);
00114 if (resultIsConstant)
00115 {
00116 SUNDANCE_MSG3(verb,
00117 tab0 << std::endl
00118 << tab0 << "result will be in constant index " << constResultIndex);
00119 resultIndex_[order].append(constResultIndex);
00120 addConstantIndex(i, constResultIndex);
00121 constResultIndex++;
00122 }
00123 else
00124 {
00125 SUNDANCE_MSG3(verb,
00126 tab0 << std::endl
00127 << tab0 << "result will be in constant index " << vecResultIndex);
00128 resultIndex_[order].append(vecResultIndex);
00129 addVectorIndex(i, vecResultIndex);
00130 vecResultIndex++;
00131 }
00132
00133
00134
00135
00136
00137
00138
00139 int dnLeftIndex = leftSparsity()->getIndex(d);
00140 int dnRightIndex = rightSparsity()->getIndex(d);
00141
00142
00143 bool hasVectorWorkspace = false;
00144 bool workspaceIsLeft = false;
00145 int workspaceIndex = -1;
00146 int workspaceCoeffIndex = -1;
00147 bool workspaceCoeffIsConstant = false;
00148
00149
00150 bool dnLeftIsConst = false;
00151 if (dnLeftIndex != -1)
00152 {
00153 dnLeftIsConst = leftSparsity()->state(dnLeftIndex)==ConstantDeriv;
00154 }
00155 bool dnRightIsConst = false;
00156 if (dnRightIndex != -1)
00157 {
00158 dnRightIsConst = rightSparsity()->state(dnRightIndex)==ConstantDeriv;
00159 }
00160
00161
00162 if (dnLeftIndex != -1 && !dnLeftIsConst
00163 && rightSparsity()->containsDeriv(MultipleDeriv()))
00164 {
00165
00166 hasVectorWorkspace = true;
00167 workspaceIndex = leftEval()->vectorIndexMap().get(dnLeftIndex);
00168 SUNDANCE_MSG3(verb,
00169 tab0 << "using left as workspace");
00170 workspaceIsLeft = true;
00171 int d0RightIndex = rightSparsity()->getIndex(MultipleDeriv());
00172 bool d0RightIsConst = rightSparsity()->state(d0RightIndex)==ConstantDeriv;
00173 workspaceCoeffIsConstant = d0RightIsConst;
00174 if (d0RightIsConst)
00175 {
00176 workspaceCoeffIndex
00177 = rightEval()->constantIndexMap().get(d0RightIndex);
00178 }
00179 else
00180 {
00181 workspaceCoeffIndex
00182 = rightEval()->vectorIndexMap().get(d0RightIndex);
00183 }
00184 }
00185
00186
00187 if (!hasVectorWorkspace && dnRightIndex != -1 && !dnRightIsConst
00188 && leftSparsity()->containsDeriv(MultipleDeriv()))
00189 {
00190
00191 hasVectorWorkspace = true;
00192 workspaceIndex = rightEval()->vectorIndexMap().get(dnRightIndex);
00193 workspaceIsLeft = false;
00194 SUNDANCE_MSG3(verb,
00195 tab0 << "using right as workspace");
00196 int d0LeftIndex = leftSparsity()->getIndex(MultipleDeriv());
00197 bool d0LeftIsConst = leftSparsity()->state(d0LeftIndex)==ConstantDeriv;
00198 workspaceCoeffIsConstant = d0LeftIsConst;
00199 if (d0LeftIsConst)
00200 {
00201 workspaceCoeffIndex
00202 = leftEval()->constantIndexMap().get(d0LeftIndex);
00203 }
00204 else
00205 {
00206 workspaceCoeffIndex
00207 = leftEval()->vectorIndexMap().get(d0LeftIndex);
00208 }
00209 }
00210
00211 if (hasVectorWorkspace && verb > 2)
00212 {
00213 std::string wSide = "right";
00214 MultipleDeriv wsDeriv;
00215 if (workspaceIsLeft)
00216 {
00217 wSide = "left";
00218 wsDeriv = leftSparsity()->deriv(dnLeftIndex);
00219 }
00220 else
00221 {
00222 wsDeriv = rightSparsity()->deriv(dnRightIndex);
00223 }
00224 SUNDANCE_MSG2(verb, tab0 << "has workspace vector: "
00225 << wSide << " deriv= "
00226 << wsDeriv
00227 << ", coeff index= " << workspaceCoeffIndex);
00228 }
00229 else
00230 {
00231 SUNDANCE_MSG2(verb, tab0 << "has no workspace vector");
00232 }
00233
00234 hasWorkspace_[order].append(hasVectorWorkspace);
00235 workspaceIsLeft_[order].append(workspaceIsLeft);
00236 workspaceIndex_[order].append(workspaceIndex);
00237 workspaceCoeffIndex_[order].append(workspaceCoeffIndex);
00238 workspaceCoeffIsConstant_[order].append(workspaceCoeffIsConstant);
00239
00240 ProductRulePerms perms;
00241 d.productRulePermutations(perms);
00242 SUNDANCE_MSG4(verb,
00243 tabs << "product rule permutations " << perms);
00244
00245 Array<Array<int> > ccTerms;
00246 Array<Array<int> > cvTerms;
00247 Array<Array<int> > vcTerms;
00248 Array<Array<int> > vvTerms;
00249 Array<int> startingVector;
00250 ProductParity startingParity;
00251
00252 bool hasStartingVector = false;
00253
00254 for (ProductRulePerms::const_iterator
00255 iter = perms.begin(); iter != perms.end(); iter++)
00256 {
00257 Tabs tab1;
00258 MultipleDeriv dLeft = iter->first.first();
00259 MultipleDeriv dRight = iter->first.second();
00260 int multiplicity = iter->second;
00261
00262
00263
00264 if (hasVectorWorkspace && workspaceIsLeft
00265 && dLeft.order()==order) continue;
00266 if (hasVectorWorkspace && !workspaceIsLeft
00267 && dRight.order()==order) continue;
00268
00269 if (!leftSparsity()->containsDeriv(dLeft)
00270 || !rightSparsity()->containsDeriv(dRight)) continue;
00271 int iLeft = leftSparsity()->getIndex(dLeft);
00272 int iRight = rightSparsity()->getIndex(dRight);
00273
00274 if (iLeft==-1 || iRight==-1) continue;
00275 SUNDANCE_MSG4(verb,
00276 tab1 << "left deriv=" << dLeft);
00277 SUNDANCE_MSG4(verb,
00278 tab1 << "right deriv=" << dRight);
00279
00280 bool leftIsConst = leftSparsity()->state(iLeft)==ConstantDeriv;
00281 bool rightIsConst = rightSparsity()->state(iRight)==ConstantDeriv;
00282
00283 if (leftIsConst)
00284 {
00285 Tabs tab2;
00286 SUNDANCE_MSG4(verb,
00287 tab2 << "left is const");
00288 int leftIndex = leftEval()->constantIndexMap().get(iLeft);
00289 if (rightIsConst)
00290 {
00291 SUNDANCE_MSG4(verb,
00292 tab2 << "right is const");
00293 int rightIndex = rightEval()->constantIndexMap().get(iRight);
00294 ccTerms.append(tuple(leftIndex, rightIndex, multiplicity));
00295 }
00296 else
00297 {
00298 SUNDANCE_MSG4(verb,
00299 tab2 << "right is vec");
00300 int rightIndex = rightEval()->vectorIndexMap().get(iRight);
00301 if (!hasVectorWorkspace && !hasStartingVector)
00302 {
00303 SUNDANCE_MSG4(verb,
00304 tab1 << "found c-v starting vec");
00305 startingVector = tuple(leftIndex, rightIndex,
00306 multiplicity);
00307 hasStartingVector = true;
00308 startingParity = ConstVec;
00309 }
00310 else
00311 {
00312 SUNDANCE_MSG4(verb,
00313 tab1 << "found c-v term");
00314 cvTerms.append(tuple(leftIndex, rightIndex,
00315 multiplicity));
00316 }
00317 }
00318 }
00319 else
00320 {
00321 Tabs tab2;
00322 SUNDANCE_MSG4(verb,
00323 tab2 << "left is vec");
00324 int leftIndex = leftEval()->vectorIndexMap().get(iLeft);
00325 if (rightIsConst)
00326 {
00327 SUNDANCE_MSG4(verb,
00328 tab2 << "right is const");
00329 int rightIndex = rightEval()->constantIndexMap().get(iRight);
00330 if (!hasVectorWorkspace && !hasStartingVector)
00331 {
00332 SUNDANCE_MSG4(verb,
00333 tab1 << "found v-c starting vec");
00334 startingVector = tuple(leftIndex, rightIndex,
00335 multiplicity);
00336 hasStartingVector = true;
00337 startingParity = VecConst;
00338 }
00339 else
00340 {
00341 SUNDANCE_MSG4(verb,
00342 tab1 << "found v-c term");
00343 vcTerms.append(tuple(leftIndex, rightIndex,
00344 multiplicity));
00345 }
00346 }
00347 else
00348 {
00349 SUNDANCE_MSG4(verb,
00350 tab2 << "right is vec");
00351 int rightIndex = rightEval()->vectorIndexMap().get(iRight);
00352 if (!hasVectorWorkspace && !hasStartingVector)
00353 {
00354 SUNDANCE_MSG4(verb,
00355 tab1 << "found v-v starting vec");
00356 startingVector = tuple(leftIndex, rightIndex,
00357 multiplicity);
00358 hasStartingVector = true;
00359 startingParity = VecVec;
00360 }
00361 else
00362 {
00363 SUNDANCE_MSG4(verb,
00364 tab1 << "found v-v term");
00365 vvTerms.append(tuple(leftIndex, rightIndex,
00366 multiplicity));
00367 }
00368 }
00369 }
00370 }
00371 ccTerms_[order].append(ccTerms);
00372 cvTerms_[order].append(cvTerms);
00373 vcTerms_[order].append(vcTerms);
00374 vvTerms_[order].append(vvTerms);
00375 startingVectors_[order].append(startingVector);
00376 startingParities_[order].append(startingParity);
00377
00378 if (verb > 2)
00379 {
00380 Tabs tab0;
00381 Out::os() << tab0 << "deriv " << i << " order=" << order ;
00382 if (resultIsConstant)
00383 {
00384 Out::os() << " constant result, index= ";
00385 }
00386 else
00387 {
00388 Out::os() << " vector result, index= ";
00389 }
00390 Out::os() << resultIndex_[order] << std::endl;
00391 {
00392 Tabs tab1;
00393 if (hasStartingVector)
00394 {
00395 Out::os() << tab1 << "starting vector " << startingVector << std::endl;
00396 }
00397 Out::os() << tab1 << "c-c terms " << ccTerms << std::endl;
00398 Out::os() << tab1 << "c-v terms " << cvTerms << std::endl;
00399 Out::os() << tab1 << "v-c terms " << vcTerms << std::endl;
00400 Out::os() << tab1 << "v-v terms " << vvTerms << std::endl;
00401 }
00402 }
00403 }
00404
00405 if (verb > 2)
00406 {
00407 Out::os() << tabs << "maps: " << std::endl;
00408 Out::os() << tabs << "vector index map " << vectorIndexMap() << std::endl;
00409 Out::os() << tabs << "constant index map " << constantIndexMap() << std::endl;
00410 }
00411 }
00412 catch(std::exception& e)
00413 {
00414 TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
00415 "exception detected in ProductEvaluator: expr="
00416 << expr->toString() << std::endl
00417 << "exception=" << e.what());
00418 }
00419 }
00420
00421 void ProductEvaluator
00422 ::internalEval(const EvalManager& mgr,
00423 Array<double>& constantResults,
00424 Array<RCP<EvalVector> >& vectorResults) const
00425 {
00426 Tabs tabs(0);
00427
00428 SUNDANCE_MSG1(mgr.verb(),
00429 tabs << "ProductEvaluator::eval() expr="
00430 << expr()->toString());
00431
00432
00433 Array<RCP<EvalVector> > leftVectorResults;
00434 Array<RCP<EvalVector> > rightVectorResults;
00435 Array<double> leftConstantResults;
00436 Array<double> rightConstantResults;
00437 evalChildren(mgr, leftConstantResults, leftVectorResults,
00438 rightConstantResults, rightVectorResults);
00439
00440 if (mgr.verb() > 2)
00441 {
00442 Out::os() << tabs << "left operand results" << std::endl;
00443 mgr.showResults(Out::os(), leftSparsity(), leftVectorResults,
00444 leftConstantResults);
00445 Out::os() << tabs << "right operand results" << std::endl;
00446 mgr.showResults(Out::os(), rightSparsity(), rightVectorResults,
00447 rightConstantResults);
00448 }
00449
00450 constantResults.resize(this->sparsity()->numConstantDerivs());
00451 vectorResults.resize(this->sparsity()->numVectorDerivs());
00452
00453
00454
00455
00456
00457 for (int order=maxOrder_; order>=0; order--)
00458 {
00459 for (int i=0; i<resultIndex_[order].size(); i++)
00460 {
00461 double constantVal = 0.0;
00462 const Array<Array<int> >& ccTerms = ccTerms_[order][i];
00463 for (int j=0; j<ccTerms.size(); j++)
00464 {
00465
00466 constantVal += leftConstantResults[ccTerms[j][0]]
00467 * rightConstantResults[ccTerms[j][1]] * ccTerms[j][2];
00468 }
00469
00470 if (resultIsConstant_[order][i])
00471 {
00472 constantResults[resultIndex_[order][i]] = constantVal;
00473 continue;
00474 }
00475
00476
00477
00478
00479
00480
00481 RCP<EvalVector> result;
00482 if (hasWorkspace_[order][i])
00483 {
00484 int index = workspaceIndex_[order][i];
00485 int coeffIndex = workspaceCoeffIndex_[order][i];
00486 bool coeffIsConstant = workspaceCoeffIsConstant_[order][i];
00487 if (workspaceIsLeft_[order][i])
00488 {
00489 result = leftVectorResults[index];
00490 if (coeffIsConstant)
00491 {
00492 const double& coeff = rightConstantResults[coeffIndex];
00493 if (!isOne(coeff)) result->multiply_S(coeff);
00494 }
00495 else
00496 {
00497 const RCP<EvalVector>& coeff
00498 = rightVectorResults[coeffIndex];
00499 result->multiply_V(coeff.get());
00500 }
00501 }
00502 else
00503 {
00504 result = rightVectorResults[index];
00505 if (coeffIsConstant)
00506 {
00507 const double& coeff = leftConstantResults[coeffIndex];
00508 if (!isOne(coeff)) result->multiply_S(coeff);
00509 }
00510 else
00511 {
00512 const RCP<EvalVector>& coeff
00513 = leftVectorResults[coeffIndex];
00514 result->multiply_V(coeff.get());
00515 }
00516 }
00517 SUNDANCE_MSG5(mgr.verb(), tabs << "workspace = " << result->str());
00518 }
00519 else
00520 {
00521 result = mgr.popVector();
00522 const Array<int>& sv = startingVectors_[order][i];
00523 int multiplicity = sv[2];
00524 switch(startingParities_[order][i])
00525 {
00526 case VecVec:
00527 if (!isZero(constantVal))
00528 {
00529 if (!isOne(multiplicity))
00530 {
00531 result->setTo_S_add_SVV(constantVal,
00532 multiplicity,
00533 leftVectorResults[sv[0]].get(),
00534 rightVectorResults[sv[1]].get());
00535 }
00536 else
00537 {
00538 result->setTo_S_add_VV(constantVal,
00539 leftVectorResults[sv[0]].get(),
00540 rightVectorResults[sv[1]].get());
00541 }
00542 }
00543 else
00544 {
00545 if (!isOne(multiplicity))
00546 {
00547 result->setTo_SVV(multiplicity,
00548 leftVectorResults[sv[0]].get(),
00549 rightVectorResults[sv[1]].get());
00550 }
00551 else
00552 {
00553 result->setTo_VV(leftVectorResults[sv[0]].get(),
00554 rightVectorResults[sv[1]].get());
00555 }
00556 }
00557 SUNDANCE_MSG5(mgr.verb(), tabs << "init to v-v prod, m="
00558 << multiplicity << ", left="
00559 << leftVectorResults[sv[0]]->str()
00560 << ", right="
00561 << rightVectorResults[sv[1]]->str()
00562 << ", result=" << result->str());
00563 break;
00564 case VecConst:
00565 if (!isZero(constantVal))
00566 {
00567 if (!isOne(multiplicity*rightConstantResults[sv[1]]))
00568 {
00569 result->setTo_S_add_SV(constantVal,
00570 multiplicity
00571 *rightConstantResults[sv[1]],
00572 leftVectorResults[sv[0]].get());
00573 }
00574 else
00575 {
00576 result->setTo_S_add_V(constantVal,
00577 leftVectorResults[sv[0]].get());
00578 }
00579 }
00580 else
00581 {
00582 if (!isOne(multiplicity*rightConstantResults[sv[1]]))
00583 {
00584 result->setTo_SV(multiplicity
00585 *rightConstantResults[sv[1]],
00586 leftVectorResults[sv[0]].get());
00587 }
00588 else
00589 {
00590 result->setTo_V(leftVectorResults[sv[0]].get());
00591 }
00592 }
00593 SUNDANCE_MSG5(mgr.verb(), tabs << "init to v-c prod, m="
00594 << multiplicity << ", left="
00595 << leftVectorResults[sv[0]]->str()
00596 << ", right="
00597 << rightConstantResults[sv[1]]
00598 << ", result=" << result->str());
00599 break;
00600 case ConstVec:
00601 if (!isZero(constantVal))
00602 {
00603 if (!isOne(multiplicity*leftConstantResults[sv[0]]))
00604 {
00605 result->setTo_S_add_SV(constantVal,
00606 multiplicity
00607 *leftConstantResults[sv[0]],
00608 rightVectorResults[sv[1]].get());
00609 }
00610 else
00611 {
00612 result->setTo_S_add_V(constantVal,
00613 rightVectorResults[sv[1]].get());
00614 }
00615 }
00616 else
00617 {
00618 if (!isOne(multiplicity*leftConstantResults[sv[0]]))
00619 {
00620 result->setTo_SV(multiplicity
00621 *leftConstantResults[sv[0]],
00622 rightVectorResults[sv[1]].get());
00623 }
00624 else
00625 {
00626 result->setTo_V(rightVectorResults[sv[1]].get());
00627 }
00628 }
00629 SUNDANCE_MSG5(mgr.verb(), tabs << "init to c-v prod, m="
00630 << multiplicity << ", left="
00631 << leftConstantResults[sv[0]]
00632 << ", right="
00633 << rightVectorResults[sv[1]]->str()
00634 << ", result=" << result->str());
00635
00636 }
00637 SUNDANCE_MSG4(mgr.verb(), tabs << "starting value = " << result->str());
00638 }
00639 vectorResults[resultIndex_[order][i]] = result;
00640
00641 const Array<Array<int> >& cvTerms = cvTerms_[order][i];
00642 const Array<Array<int> >& vcTerms = vcTerms_[order][i];
00643 const Array<Array<int> >& vvTerms = vvTerms_[order][i];
00644
00645 for (int j=0; j<cvTerms.size(); j++)
00646 {
00647 SUNDANCE_MSG4(mgr.verb(), tabs << "adding c-v term " << cvTerms[j]);
00648
00649 double multiplicity = cvTerms[j][2];
00650 double scalar = multiplicity*leftConstantResults[cvTerms[j][0]];
00651 const EvalVector* vec = rightVectorResults[cvTerms[j][1]].get();
00652 if (!isOne(scalar))
00653 {
00654 result->add_SV(scalar, vec);
00655 }
00656 else
00657 {
00658 result->add_V(vec);
00659 }
00660 }
00661
00662 for (int j=0; j<vcTerms.size(); j++)
00663 {
00664 SUNDANCE_MSG4(mgr.verb(), tabs << "adding v-c term " << vcTerms[j]);
00665
00666 double multiplicity = vcTerms[j][2];
00667 double scalar = multiplicity*rightConstantResults[vcTerms[j][1]];
00668 const EvalVector* vec = leftVectorResults[vcTerms[j][0]].get();
00669 if (!isOne(scalar))
00670 {
00671 result->add_SV(scalar, vec);
00672 }
00673 else
00674 {
00675 result->add_V(vec);
00676 }
00677 }
00678
00679 for (int j=0; j<vvTerms.size(); j++)
00680 {
00681 SUNDANCE_MSG4(mgr.verb(), tabs << "adding v-v term " << vvTerms[j]);
00682
00683 double multiplicity = vvTerms[j][2];
00684 const EvalVector* vec1 = leftVectorResults[vvTerms[j][0]].get();
00685 const EvalVector* vec2 = rightVectorResults[vvTerms[j][1]].get();
00686 if (!isOne(multiplicity))
00687 {
00688 result->add_SVV(multiplicity, vec1, vec2);
00689 }
00690 else
00691 {
00692 result->add_VV(vec1, vec2);
00693 }
00694 }
00695
00696
00697 }
00698 }
00699
00700 if (mgr.verb() > 1)
00701 {
00702 Out::os() << tabs << "product result " << std::endl;
00703 mgr.showResults(Out::os(), this->sparsity(), vectorResults,
00704 constantResults);
00705 }
00706 }