#include "WeightInherit.hh" #include "Kernel.hh" using namespace cadabra; std::string WeightInherit::name() const { return "WeightInherit"; } WeightInherit::WeightException::WeightException(const std::string& str) : ConsistencyException(str) { } bool WeightInherit::parse(Kernel& k, std::shared_ptr ex, keyval_t& kv) { keyval_t::const_iterator tpit=kv.find("type"); if(tpit!=kv.end()) { if(*tpit->second->name=="multiplicative") combination_type=multiplicative; else if(*tpit->second->name=="additive") combination_type=additive; else if(*tpit->second->name=="power") combination_type=power; else throw ArgumentException("weight type must be 'multiplicative', 'additive' or 'power'."); } else combination_type=multiplicative; tpit = kv.find("self"); if(tpit!=kv.end()) { value_self=*tpit->second->multiplier; } else value_self=0; auto ret = WeightBase::parse(k, ex, kv); return ret; } multiplier_t WeightInherit::value(const Kernel& kernel, Ex::iterator it, const std::string& forcedlabel) const { const Properties& properties=kernel.properties; multiplier_t ret=0; bool first_term=true; // std::cerr << "calling inherit on " << *it->name << " " << &(*it) << " " << forcedlabel << std::endl; Ex::sibling_iterator sib=it.begin(); while(sib!=it.end()) { if(!sib->is_index()) { switch(combination_type) { case multiplicative: { const WeightBase *gnb=properties.get(sib, forcedlabel); // std::cerr << "finding weight for " << Ex(sib) << std::endl; if(gnb) { multiplier_t tmp=gnb->value(kernel, sib, forcedlabel); ret+=tmp; } } break; case additive: { multiplier_t thisone=0; const WeightBase *gnb=properties.get(sib, forcedlabel); if(gnb) thisone=gnb->value(kernel, sib, forcedlabel); else thisone=0; if(first_term) { first_term=false; ret=thisone; } else if(ret!=thisone) { // the weights in the sum are not uniform throw WeightException("Encountered sum with un-equal weight terms."); } } break; case power: { const WeightBase *gnb=properties.get(sib, forcedlabel); if(gnb) { multiplier_t tmp=gnb->value(kernel, sib, forcedlabel); ++sib; if(sib==it.end() || sib->is_rational()==false) throw RuntimeException("Can only handle numerical exponents for weight counting."); ret+=(*sib->multiplier)*tmp; sib=it.end(); continue; } } break; } } ++sib; } ret+=value_self; // Add our own weight. return ret; }