/** * Set a value to a "local" attribute, ie an attribute related to a member *function. * * The only attribute that can be set here is "domains" which defines the * indices of domains a particular function is applied to. Possible values are *(strings): * * 1) "All" : the function is applied to all domains defined for this *MultiDomainFunction. * 2) "i" : the function is applied to a single domain which index is *equal to the * function's index in this MultiDomainFunction. * 3) "non-negative integer" : a domain index. * 4) "a,b,c,..." : a list of domain indices (a,b,c,.. are non-negative *integers). * 5) "a - b" : a range of domain indices (a,b are non-negative integers a *<= b). * * To be used with Fit algorithm at least one of the member functions must have *"domains" value * of type 2), 3), 4) or 5) because these values can tell Fit how many domains *need to be created. * * @param i :: Index of a function for which the attribute is being set. * @param attName :: Name of an attribute. * @param att :: Value of the attribute to set. */ void MultiDomainFunction::setLocalAttribute(size_t i, const std::string &attName, const IFunction::Attribute &att) { if (attName != "domains") { throw std::invalid_argument("MultiDomainFunction does not have attribute " + attName); } if (i >= nFunctions()) { throw std::out_of_range("Function index is out of range."); } std::string value = att.asString(); auto it = m_domains.find(i); if (value == "All") { // fit to all domains if (it != m_domains.end()) { m_domains.erase(it); } return; } else if (value == "i") { // fit to domain with the same index as the function setDomainIndex(i, i); return; } else if (value.empty()) { // do not fit to any domain setDomainIndices(i, std::vector<size_t>()); return; } // fit to a selection of domains std::vector<size_t> indx; Expression list; list.parse(value); if (list.name() == "+") { if (list.size() != 2 || list.terms()[1].operator_name() != "-") { throw std::runtime_error("MultiDomainFunction: attribute \"domains\" " "expects two integers separated by a \"-\""); } // value looks like "a - b". a and b must be ints and define a range of // domain indices size_t start = boost::lexical_cast<size_t>(list.terms()[0].str()); size_t end = boost::lexical_cast<size_t>(list.terms()[1].str()) + 1; if (start >= end) { throw std::runtime_error( "MultiDomainFunction: attribute \"domains\": wrong range limits."); } indx.resize(end - start); for (size_t i = start; i < end; ++i) { indx[i - start] = i; } } else { // value must be either an int or a list of ints: "a,b,c,..." list.toList(); for (size_t k = 0; k < list.size(); ++k) { indx.push_back(boost::lexical_cast<size_t>(list[k].name())); } } setDomainIndices(i, indx); }
/** * Set a value to attribute attName */ void MultiDomainFunction::setLocalAttribute(size_t i, const std::string& attName,const IFunction::Attribute& att) { if (attName != "domains") { throw std::invalid_argument("MultiDomainFunction does not have attribute " + attName); } if (i >= nFunctions()) { throw std::out_of_range("Function index is out of range."); } std::string value = att.asString(); auto it = m_domains.find(i); if (value == "All") {// fit to all domains if (it != m_domains.end()) { m_domains.erase(it); } return; } else if (value == "i") {// fit to domain with the same index as the function setDomainIndex(i,i); return; } else if (value.empty()) {// do not fit to any domain setDomainIndices(i,std::vector<size_t>()); } // fit to a selection of domains std::vector<size_t> indx; Expression list; list.parse(value); list.toList(); for(size_t k = 0; k < list.size(); ++k) { indx.push_back(boost::lexical_cast<size_t>(list[k].name())); } setDomainIndices(i,indx); }