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