TEST(FunctionFactoryTest, CreateCompositeFunctionTest) { std::string ini = "CompositeFunction(" "FunctionFactoryTestFunction(A=10,B=20)," "FunctionFactoryTestFunction(A=30,B=40)" ")"; IFunction_sptr fun = FunctionFactory::instance().createFitFunction(ini); EXPECT_TRUE( fun.get() != nullptr ); CompositeFunction_sptr cf = boost::dynamic_pointer_cast<CompositeFunction>(fun); EXPECT_TRUE( cf.get() != nullptr ); EXPECT_EQ( cf->nFunctions(), 2 ); auto f1 = cf->getFunction(0); auto f2 = cf->getFunction(1); EXPECT_EQ(f1->getParameter("A"),10); EXPECT_EQ(f1->getParameter("B"),20); EXPECT_EQ(f2->getParameter("A"),30); EXPECT_EQ(f2->getParameter("B"),40); EXPECT_EQ(cf->getParameter("f0.A"),10); EXPECT_EQ(cf->getParameter("f0.B"),20); EXPECT_EQ(cf->getParameter("f1.A"),30); EXPECT_EQ(cf->getParameter("f1.B"),40); std::cerr << '\n' << fun->asString(true) << '\n' << std::endl; IFunction_sptr fun1 = FunctionFactory::instance().createFitFunction(ini); EXPECT_TRUE( fun1.get() != nullptr ); cf = boost::dynamic_pointer_cast<CompositeFunction>(fun1); EXPECT_TRUE( cf.get() != nullptr ); EXPECT_EQ( cf->nFunctions(), 2 ); EXPECT_EQ(cf->getParameter("f0.A"),10); EXPECT_EQ(cf->getParameter("f0.B"),20); EXPECT_EQ(cf->getParameter("f1.A"),30); EXPECT_EQ(cf->getParameter("f1.B"),40); }
/** * Create a composite function from an expression. * @param expr :: The input expression * @param parentAttributes :: An output map filled with the attribute name & * values of the parent function * @return A pointer to the created function */ CompositeFunction_sptr FunctionFactoryImpl::createComposite( const Expression &expr, std::map<std::string, std::string> &parentAttributes) const { if (expr.name() != ";") inputError(expr.str()); if (expr.size() == 0) { return CompositeFunction_sptr(); } const std::vector<Expression> &terms = expr.terms(); auto it = terms.cbegin(); const Expression &term = it->bracketsRemoved(); CompositeFunction_sptr cfun; if (term.name() == "=") { if (term.terms()[0].name() == "composite") { cfun = boost::dynamic_pointer_cast<CompositeFunction>( createFunction(term.terms()[1].name())); if (!cfun) inputError(expr.str()); ++it; } else if (term.terms()[0].name() == "name") { cfun = boost::dynamic_pointer_cast<CompositeFunction>( createFunction("CompositeFunction")); if (!cfun) inputError(expr.str()); } else { inputError(expr.str()); } } else if (term.name() == ",") { auto firstTerm = term.terms().cbegin(); if (firstTerm->name() == "=") { if (firstTerm->terms()[0].name() == "composite") { cfun = boost::dynamic_pointer_cast<CompositeFunction>( createSimple(term, parentAttributes)); if (!cfun) inputError(expr.str()); ++it; } else if (firstTerm->terms()[0].name() == "name") { cfun = boost::dynamic_pointer_cast<CompositeFunction>( createFunction("CompositeFunction")); if (!cfun) inputError(expr.str()); } else { inputError(expr.str()); } } } else if (term.name() == ";") { cfun = boost::dynamic_pointer_cast<CompositeFunction>( createFunction("CompositeFunction")); if (!cfun) inputError(expr.str()); } else { inputError(expr.str()); } if (!cfun) inputError(expr.str()); for (; it != terms.end(); ++it) { const Expression &term = it->bracketsRemoved(); IFunction_sptr fun; std::map<std::string, std::string> pAttributes; if (term.name() == ";") { fun = createComposite(term, pAttributes); if (!fun) continue; } else { std::string parName = term[0].name(); if (parName.size() >= 10 && parName.substr(0, 10) == "constraint") { addConstraints(cfun, term[1]); continue; } else if (parName == "ties") { addTies(cfun, term[1]); continue; } else { fun = createSimple(term, pAttributes); } } cfun->addFunction(fun); size_t i = cfun->nFunctions() - 1; for (auto &pAttribute : pAttributes) { // Apply parent attributes of the child function to this function. If this // function doesn't have those attributes, they get passed up the chain to // this function's parent. if (cfun->hasLocalAttribute(pAttribute.first)) { cfun->setLocalAttributeValue(i, pAttribute.first, pAttribute.second); } else { parentAttributes[pAttribute.first] = pAttribute.second; } } } if (cfun) { cfun->applyTies(); } return cfun; }
/** * Create a composite function from an expression. * @param expr :: The input expression * @param parentAttributes :: An output map filled with the attribute name & values of the parent function * @return A pointer to the created function */ CompositeFunction_sptr FunctionFactoryImpl::createComposite(const Expression& expr, std::map<std::string,std::string>& parentAttributes)const { if (expr.name() != ";") inputError(expr.str()); if (expr.size() == 0) { return CompositeFunction_sptr(); } const std::vector<Expression>& terms = expr.terms(); std::vector<Expression>::const_iterator it = terms.begin(); const Expression& term = it->bracketsRemoved(); CompositeFunction_sptr cfun; if (term.name() == "=") { if (term.terms()[0].name() == "composite") { cfun = boost::dynamic_pointer_cast<CompositeFunction>(createFunction(term.terms()[1].name())); if (!cfun) inputError(expr.str()); ++it; } else if (term.terms()[0].name() == "name") { cfun = boost::dynamic_pointer_cast<CompositeFunction>(createFunction("CompositeFunction")); if (!cfun) inputError(expr.str()); } else { inputError(expr.str()); } } else if (term.name() == ",") { std::vector<Expression>::const_iterator firstTerm = term.terms().begin(); if (firstTerm->name() == "=") { if (firstTerm->terms()[0].name() == "composite") { cfun = boost::dynamic_pointer_cast<CompositeFunction>(createSimple(term,parentAttributes)); if (!cfun) inputError(expr.str()); ++it; } else if (firstTerm->terms()[0].name() == "name") { cfun = boost::dynamic_pointer_cast<CompositeFunction>(createFunction("CompositeFunction")); if (!cfun) inputError(expr.str()); } else { inputError(expr.str()); } } } else if (term.name() == ";") { cfun = boost::dynamic_pointer_cast<CompositeFunction>(createFunction("CompositeFunction")); if (!cfun) inputError(expr.str()); } else { inputError(expr.str()); } for(;it!=terms.end();++it) { const Expression& term = it->bracketsRemoved(); IFunction_sptr fun; std::map<std::string,std::string> pAttributes; if (term.name() == ";") { fun = createComposite(term,pAttributes); if (!fun) continue; } else { std::string parName = term[0].name(); if (parName.size() >= 10 && parName.substr(0,10) == "constraint") { addConstraints(cfun,term[1]); continue; } else if (parName == "ties") { addTies(cfun,term[1]); continue; } else { fun = createSimple(term,pAttributes); } } cfun->addFunction(fun); size_t i = cfun->nFunctions() - 1; for(auto att = pAttributes.begin(); att != pAttributes.end(); ++att) { cfun->setLocalAttributeValue(i,att->first,att->second); } } cfun->applyTies(); return cfun; }