void OptionsFunctionalityNode::addOption(const string &name, const opt_type& type, const GenericType &def_val, const string& desc, const std::vector<GenericType> &allowed_vals, bool inherit){

  // If inheriting, check if the type matches
  if (inherit && allowed_options.find(name)!=allowed_options.end()) {
     casadi_assert_message(allowed_options[name] == type,
        "The option '" << name << "' was indicated to inherit, but the type definition of the ancestor '" <<
         GenericType::get_type_description(allowed_options[name]) << "' conflicts with the type definition here '" <<
         GenericType::get_type_description(type) << "'."
     );
  }
  
  defaults_[name] = def_val;
  allowed_options[name] = type;

  std::vector<GenericType> allowed_vals_vec;
  
  // Inherit allowed_vals
  if (inherit && allowed_vals_.find(name)!=allowed_vals_.end()) {
    allowed_vals_vec.insert( allowed_vals_vec.end(), allowed_vals_[name].begin(), allowed_vals_[name].end() );
  }
  // Insert current allowed_vals
  allowed_vals_vec.insert( allowed_vals_vec.end(), allowed_vals.begin(), allowed_vals.end() );
  
  if(!def_val.isNull())
    dictionary_[name] = def_val;

  // Inherit description
  std::stringstream s;
  if (inherit && description_.find(name)!=description_.end()) {
    s << description_[name];
    if (!desc.empty())
      s << std::endl;
  }
  // Insert current description
  s << desc;
  description_[name] = s.str();

  allowed_vals_[name] = allowed_vals_vec;

}
void OptionsFunctionalityNode::setOption(const string &name, const GenericType &op) {
  assert_exists(name);

  // If we have an empty vector, than we are not strict about the type
  if (op.isEmptyVector()) {
    dictionary_[name] = GenericType::from_type(allowed_options[name]);
    return;
  }

  // Some typechecking
  if (!op.can_cast_to(allowed_options[name]) && !op.isNull()) {
    stringstream ss;
    ss << "Option '" << name << "' expects a '" <<
        GenericType::get_type_description(allowed_options[name]) << "' type." << endl;
    if (op.getType() == OT_BOOLEAN) {
      ss << "You supplied another type, possibly boolean." << endl;
      if (allowed_options[name]==OT_REAL || allowed_options[name]==OT_INTEGER) {
        ss << "(A common mistake is to use SX/MX instead of floats/DMatrix in this context)"
           << endl;
      }
    } else {
      ss << "You supplied a type '" << op.get_description() << "' instead." << endl;
    }
    if (!allowed_vals_[name].empty()) {
      ss << "(Allowed values are:";
      for (std::vector<GenericType>::const_iterator it=allowed_vals_[name].begin();
           it!=allowed_vals_[name].end();it++) {
        ss << " '" << *it << "'";
      }
      ss << ")" << endl;
    }
    casadi_error(ss.str());
  }

  // If allowed values are listed, check them.
  if (!allowed_vals_[name].empty()) {
    bool found;
    GenericType problem = op;
    if (op.isStringVector()) {
      found = true;
      const std::vector<std::string> & opv = op.toStringVector();
      for (std::vector<std::string>::const_iterator it=opv.begin();it!=opv.end();it++) {
        std::cout << "checking " << *it << std::endl;
        if (std::find(allowed_vals_[name].begin(),
                      allowed_vals_[name].end(), (*it))==allowed_vals_[name].end()) {
          problem = (*it);
          found = false;
          break;
        }
      }
    } else {
      found = false;
      for (std::vector<GenericType>::const_iterator it=allowed_vals_[name].begin();
           it!=allowed_vals_[name].end();it++) {
       found = found || (*it) == op;
      }
    }
    // If supplied op is not in allowed values, raise an error.
    if (!found) {
      stringstream ss;
      ss << "Option '" << name << "' does not allow '" << problem  << "'." << endl;
      ss << "(Allowed values options are:";
      for (std::vector<GenericType>::const_iterator it=allowed_vals_[name].begin();
           it!=allowed_vals_[name].end();it++) {
        ss << " '" << *it << "'";
      }
      ss << ")" << endl;
      casadi_error(ss.str());
    }
  }
  // Save the option
  dictionary_[name] = op;
}