Ejemplo n.º 1
0
/** Replace a function with a new one. The old function is deleted.
 * @param i :: The index of the function to replace
 * @param f :: A pointer to the new function
 */
void CompositeFunction::replaceFunction(size_t i, IFunction_sptr f) {
  if (i >= nFunctions())
    throw std::out_of_range("Function index out of range.");

  IFunction_sptr fun = getFunction(i);
  size_t np_old = fun->nParams();

  size_t np_new = f->nParams();

  // Modify function indeces: The new function may have different number of
  // parameters
  {
    auto itFun = std::find(m_IFunction.begin(), m_IFunction.end(), i);
    if (itFun != m_IFunction.end()) // functions must have at least 1 parameter
    {
      if (np_old > np_new) {
        m_IFunction.erase(itFun, itFun + np_old - np_new);
      } else if (np_old < np_new) {
        m_IFunction.insert(itFun, np_new - np_old, i);
      }
    } else if (np_new > 0) // it could happen if the old function is an empty
                           // CompositeFunction
    {
      itFun = std::find_if(m_IFunction.begin(), m_IFunction.end(),
                           std::bind2nd(std::greater<size_t>(), i));
      m_IFunction.insert(itFun, np_new, i);
    }
  }

  size_t dnp = np_new - np_old;
  m_nParams += dnp;
  // Shift the parameter offsets down by the total number of i-th function's
  // params
  for (size_t j = i + 1; j < nFunctions(); j++) {
    m_paramOffsets[j] += dnp;
  }

  m_functions[i] = f;
}
Ejemplo n.º 2
0
/// Get number of domains required by this function
size_t CompositeFunction::getNumberDomains() const {
  auto n = nFunctions();
  if (n == 0) {
    return 1;
  }
  size_t nd = getFunction(0)->getNumberDomains();
  for (size_t iFun = 1; iFun < n; ++iFun) {
    if (getFunction(0)->getNumberDomains() != nd) {
      throw std::runtime_error("CompositeFunction has members with "
                               "inconsistent domain numbers.");
    }
  }
  return nd;
}
Ejemplo n.º 3
0
/**
 * Returns the index of parameter if the ref points to one of the member
 * function
 * @param ref :: A reference to a parameter
 * @return Parameter index or number of nParams() if parameter not found
 */
size_t
CompositeFunction::getParameterIndex(const ParameterReference &ref) const {
  if (ref.getLocalFunction() == this && ref.getLocalIndex() < nParams()) {
    return ref.getLocalIndex();
  }
  for (size_t iFun = 0; iFun < nFunctions(); iFun++) {
    IFunction_sptr fun = getFunction(iFun);
    size_t iLocalIndex = fun->getParameterIndex(ref);
    if (iLocalIndex < fun->nParams()) {
      return m_paramOffsets[iFun] + iLocalIndex;
    }
  }
  return nParams();
}
Ejemplo n.º 4
0
/// Function you want to fit to. 
/// @param domain :: The domain
void FunctionComposition::function(const FunctionDomain& domain, FunctionValues& values)const
{
  FunctionValues tmp(domain);
  values.setCalculated(1.0);
  for(size_t iFun = 0; iFun < nFunctions(); ++iFun)
  {
    FunctionDomain1DView view(tmp.getPointerToCalculated(0),domain.size());
    if ( iFun == 0 )
    {
      m_functions[ iFun ]->function(domain,tmp);
    }
    else
    {
    }
  }
}
Ejemplo n.º 5
0
  /**
   * 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);
  }
Ejemplo n.º 6
0
  /// Function you want to fit to. 
  /// @param domain :: The buffer for writing the calculated values. Must be big enough to accept dataSize() values
  void MultiDomainFunction::function(const FunctionDomain& domain, FunctionValues& values)const
  {
    // works only on CompositeDomain
    if (!dynamic_cast<const CompositeDomain*>(&domain))
    {
      throw std::invalid_argument("Non-CompositeDomain passed to MultiDomainFunction.");
    }
    const CompositeDomain& cd = dynamic_cast<const CompositeDomain&>(domain);
    // domain must not have less parts than m_maxIndex
    if (cd.getNParts() <= m_maxIndex)
    {
      throw std::invalid_argument("CompositeDomain has too few parts (" 
        + boost::lexical_cast<std::string>(cd.getNParts()) +
        ") for MultiDomainFunction (max index " + boost::lexical_cast<std::string>(m_maxIndex) + ").");
    }
    // domain and values must be consistent
    if (cd.size() != values.size())
    {
      throw std::invalid_argument("MultiDomainFunction: domain and values have different sizes.");
    }

    countValueOffsets(cd);
    // evaluate member functions
    values.zeroCalculated();
    for(size_t iFun = 0; iFun < nFunctions(); ++iFun)
    {
      // find the domains member function must be applied to
      std::vector<size_t> domains;
      getFunctionDomains(iFun, cd, domains);

      for(auto i = domains.begin(); i != domains.end(); ++i)
      {
        const FunctionDomain& d = cd.getDomain(*i);
        FunctionValues tmp(d);
        getFunction(iFun)->function( d, tmp );
        values.addToCalculated(m_valueOffsets[*i],tmp);
      }
    }
  }
Ejemplo n.º 7
0
 /**
  * Initialize the function with the workspace(s).
  * @param function :: A function to initialize.
  */
 void MultiDomainCreator::initFunction(API::IFunction_sptr function)
 {
   auto mdFunction = boost::dynamic_pointer_cast<API::MultiDomainFunction>(function);
   if ( mdFunction )
   {
     // loop over member functions and init them
     for(size_t iFun = 0; iFun < mdFunction->nFunctions(); ++iFun)
     {
       std::vector<size_t> domainIndices;
       // get domain indices for this function
       mdFunction->getDomainIndices(iFun,m_creators.size(),domainIndices);
       if ( !domainIndices.empty() )
       {
         if ( domainIndices.size() != 1 )
         {
           g_log.warning() << "Function #" << iFun << " applies to multiple domains." << std::endl;
           g_log.warning() << "Only one of the domains is used to set workspace." << std::endl;
         }
         size_t index = domainIndices[0];
         if ( index >= m_creators.size() )
         {
           std::stringstream msg;
           msg << "Domain index is out of range. (Function #" << iFun << ")";
           throw std::runtime_error(msg.str());
         }
         m_creators[index]->initFunction( mdFunction->getFunction(iFun) );
       }
       else
       {
         g_log.warning() << "Function #" << iFun << " doesn't apply to any domain" << std::endl;
       }
     }
   }
   else
   {
     IDomainCreator::initFunction(function);
   }
 }
Ejemplo n.º 8
0
/// Return a value of attribute attName
IFunction::Attribute
MultiDomainFunction::getLocalAttribute(size_t i,
                                       const std::string &attName) const {
  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.");
  }
  auto it = m_domains.find(i);
  if (it == m_domains.end()) {
    return IFunction::Attribute("All");
  } else if (it->second.size() == 1 && it->second.front() == i) {
    return IFunction::Attribute("i");
  } else if (!it->second.empty()) {
    std::string out(boost::lexical_cast<std::string>(it->second.front()));
    for (auto i = it->second.begin() + 1; i != it->second.end(); ++it) {
      out += "," + boost::lexical_cast<std::string>(*i);
    }
    return IFunction::Attribute(out);
  }
  return IFunction::Attribute("");
}
Ejemplo n.º 9
0
/// Derivatives of function with respect to active parameters
void MultiDomainFunction::functionDeriv(const FunctionDomain &domain,
                                        Jacobian &jacobian) {
  // works only on CompositeDomain
  if (!dynamic_cast<const CompositeDomain *>(&domain)) {
    throw std::invalid_argument(
        "Non-CompositeDomain passed to MultiDomainFunction.");
  }

  if (getAttribute("NumDeriv").asBool()) {
    calNumericalDeriv(domain, jacobian);
  } else {
    const CompositeDomain &cd = dynamic_cast<const CompositeDomain &>(domain);
    // domain must not have less parts than m_maxIndex
    if (cd.getNParts() < m_maxIndex) {
      throw std::invalid_argument(
          "CompositeDomain has too few parts (" +
          boost::lexical_cast<std::string>(cd.getNParts()) +
          ") for MultiDomainFunction (max index " +
          boost::lexical_cast<std::string>(m_maxIndex) + ").");
    }

    countValueOffsets(cd);
    // evaluate member functions derivatives
    for (size_t iFun = 0; iFun < nFunctions(); ++iFun) {
      // find the domains member function must be applied to
      std::vector<size_t> domains;
      getDomainIndices(iFun, cd.getNParts(), domains);

      for (auto i = domains.begin(); i != domains.end(); ++i) {
        const FunctionDomain &d = cd.getDomain(*i);
        PartialJacobian J(&jacobian, m_valueOffsets[*i], paramOffset(iFun));
        getFunction(iFun)->functionDeriv(d, J);
      }
    }
  }
}
Ejemplo n.º 10
0
/**
 * Clear the ties.
 */
void CompositeFunction::clearTies() {
  IFunction::clearTies();
  for (size_t i = 0; i < nFunctions(); i++) {
    getFunction(i)->clearTies();
  }
}
Ejemplo n.º 11
0
/**
 * Called at the end of an iteration. Call iterationFinished() of the members.
 */
void MultiDomainFunction::iterationFinished() {
  for (size_t iFun = 0; iFun < nFunctions(); ++iFun) {
    getFunction(iFun)->iterationFinished();
  }
}
Ejemplo n.º 12
0
/**
 * Called at the start of each iteration. Call iterationStarting() of the
 * members.
 */
void MultiDomainFunction::iterationStarting() {
  for (size_t iFun = 0; iFun < nFunctions(); ++iFun) {
    getFunction(iFun)->iterationStarting();
  }
}
Ejemplo n.º 13
0
/**
 * Apply the ties.
 */
void CompositeFunction::applyTies() {
  for (size_t i = 0; i < nFunctions(); i++) {
    getFunction(i)->applyTies();
  }
}
Ejemplo n.º 14
0
/**
 * @param i :: The index of the function
 * @return function at the requested index
 */
IFunction_sptr CompositeFunction::getFunction(std::size_t i) const {
  if (i >= nFunctions()) {
    throw std::out_of_range("Function index out of range.");
  }
  return m_functions[i];
}