コード例 #1
0
void CODEExporterC::setExportNameOfFunction(const CEvaluationNode* pNode, std::set<std::string> & tmpset)
{
  if (pNode)
    {
      CFunctionDB* pFunctionDB = CCopasiRootContainer::getFunctionList();
      CCopasiTree<CEvaluationNode>::const_iterator treeIt = pNode;

      while (treeIt != NULL)
        {
          if (treeIt->mainType() == CEvaluationNode::T_CALL)
            {
              const CFunction* ifunc;
              ifunc = static_cast<CFunction*>(pFunctionDB->findFunction((*treeIt).getData()));

              setExportNameOfFunction(ifunc->getRoot(), tmpset);

              if (ifunc->getType() != CEvaluationTree::MassAction)
                if (tmpset.find(ifunc->getObjectName()) == tmpset.end())
                  {
                    NameMap[ifunc->getKey()] = translateObjectName(ifunc->getObjectName());
                    tmpset.insert(ifunc->getObjectName());
                  }
            }

          ++treeIt;
        }
    }
}
コード例 #2
0
void test_compare_utilities::test_copasi_function_expansion()
{
  CCopasiDataModel* pDataModel = pCOPASIDATAMODEL;;
  std::istringstream iss(test_compare_utilities::MODEL_STRING1);
  CPPUNIT_ASSERT(load_cps_model_from_stream(iss, *pDataModel) == true);
  CFunctionDB* pFunctionDB = CCopasiRootContainer::getFunctionList();
  // function_5
  CEvaluationTree* pTree = pFunctionDB->findFunction("function_4");
  CPPUNIT_ASSERT(pTree != NULL);
  // generate a call node
  CFunction* pFunction = dynamic_cast<CFunction*>(pTree);
  CPPUNIT_ASSERT(pFunction != NULL);
  CEvaluationNodeCall* pCallNode = new CEvaluationNodeCall(CEvaluationNode::S_FUNCTION, pFunction->getObjectName());
  CPPUNIT_ASSERT(pCallNode != NULL);
  CFunctionParameters* pFunctionParameters = &pFunction->getVariables();
  unsigned int i = 0, iMax = pFunctionParameters->size();

  while (i < iMax)
    {
      CFunctionParameter* pParameter = (*pFunctionParameters)[i];
      CPPUNIT_ASSERT(pParameter != NULL);
      CEvaluationNodeVariable* pVariableNode = new CEvaluationNodeVariable(CEvaluationNode::S_DEFAULT, pParameter->getObjectName());
      pCallNode->addChild(pVariableNode);
      ++i;
    }

  CEvaluationNode* pExpanded = expand_function_calls(pCallNode, pFunctionDB);
  delete pCallNode;
  CPPUNIT_ASSERT(pExpanded != NULL);
  CPPUNIT_ASSERT(pExpanded->mainType() == CEvaluationNode::T_OPERATOR);
  CPPUNIT_ASSERT(pExpanded->subType() == CEvaluationNode::S_DIVIDE);
  CEvaluationNode* pChild = dynamic_cast<CEvaluationNode*>(pExpanded->getChild());
  CPPUNIT_ASSERT(pChild != NULL);
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_OPERATOR);
  CPPUNIT_ASSERT(pChild->subType() == CEvaluationNode::S_PLUS);
  pChild = dynamic_cast<CEvaluationNode*>(pChild->getChild());
  CPPUNIT_ASSERT(pChild != NULL);
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_VARIABLE);
  CPPUNIT_ASSERT(pChild->getData() == std::string("y"));
  pChild = dynamic_cast<CEvaluationNode*>(pChild->getSibling());
  CPPUNIT_ASSERT(pChild != NULL);
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_VARIABLE);
  CPPUNIT_ASSERT(pChild->getData() == std::string("x"));
  CPPUNIT_ASSERT(pChild->getSibling() == NULL);
  pChild = dynamic_cast<CEvaluationNode*>(pExpanded->getChild()->getSibling());
  CPPUNIT_ASSERT(pChild != NULL);
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_NUMBER);
  CPPUNIT_ASSERT(pChild->subType() == CEvaluationNode::S_DOUBLE);
  CPPUNIT_ASSERT((fabs(pChild->getValue() - 2.0) / 2.0) < 1e-6);
  CPPUNIT_ASSERT(pChild->getSibling() == NULL);
  delete pExpanded;

  // function_5
  pTree = pFunctionDB->findFunction("function_5");
  CPPUNIT_ASSERT(pTree != NULL);
  // generate a call node
  pFunction = dynamic_cast<CFunction*>(pTree);
  CPPUNIT_ASSERT(pFunction != NULL);
  pCallNode = new CEvaluationNodeCall(CEvaluationNode::S_FUNCTION, pFunction->getObjectName());
  CPPUNIT_ASSERT(pCallNode != NULL);
  pFunctionParameters = &pFunction->getVariables();
  i = 0, iMax = pFunctionParameters->size();

  while (i < iMax)
    {
      CFunctionParameter* pParameter = (*pFunctionParameters)[i];
      CPPUNIT_ASSERT(pParameter != NULL);
      CEvaluationNodeVariable* pVariableNode = new CEvaluationNodeVariable(CEvaluationNode::S_DEFAULT, pParameter->getObjectName());
      pCallNode->addChild(pVariableNode);
      ++i;
    }

  pExpanded = expand_function_calls(pCallNode, pFunctionDB);
  delete pCallNode;
  CPPUNIT_ASSERT(pExpanded != NULL);
  CPPUNIT_ASSERT(pExpanded->mainType() == CEvaluationNode::T_OPERATOR);
  CPPUNIT_ASSERT(pExpanded->subType() == CEvaluationNode::S_PLUS);
  pChild = dynamic_cast<CEvaluationNode*>(pExpanded->getChild());
  CPPUNIT_ASSERT(pChild != NULL);
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_OPERATOR);
  CPPUNIT_ASSERT(pChild->subType() == CEvaluationNode::S_MINUS);
  pChild = dynamic_cast<CEvaluationNode*>(pChild->getChild());
  CPPUNIT_ASSERT(pChild != NULL);
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_VARIABLE);
  CPPUNIT_ASSERT(pChild->getData() == std::string("a"));
  pChild = dynamic_cast<CEvaluationNode*>(pChild->getSibling());
  CPPUNIT_ASSERT(pChild != NULL);
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_OPERATOR);
  CPPUNIT_ASSERT(pChild->subType() == CEvaluationNode::S_MULTIPLY);
  CPPUNIT_ASSERT(pChild->getSibling() == NULL);
  pChild = dynamic_cast<CEvaluationNode*>(pChild->getChild());
  CPPUNIT_ASSERT(pChild != NULL);
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_VARIABLE);
  CPPUNIT_ASSERT(pChild->getData() == std::string("c"));
  pChild = dynamic_cast<CEvaluationNode*>(pChild->getSibling());
  CPPUNIT_ASSERT(pChild != NULL);
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_NUMBER);
  CPPUNIT_ASSERT(pChild->subType() == CEvaluationNode::S_DOUBLE);
  CPPUNIT_ASSERT((fabs(pChild->getValue() - 1.3) / 1.3) < 1e-6);
  CPPUNIT_ASSERT(pChild->getSibling() == NULL);

  // (3*b)-5.23
  pChild = dynamic_cast<CEvaluationNode*>(pExpanded->getChild()->getSibling());
  CPPUNIT_ASSERT(pChild != NULL);
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_OPERATOR);
  CPPUNIT_ASSERT(pChild->subType() == CEvaluationNode::S_MINUS);
  // 3*b
  pChild = dynamic_cast<CEvaluationNode*>(pChild->getChild());
  CPPUNIT_ASSERT(pChild != NULL);
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_OPERATOR);
  CPPUNIT_ASSERT(pChild->subType() == CEvaluationNode::S_MULTIPLY);
  pChild = dynamic_cast<CEvaluationNode*>(pChild->getChild());
  CPPUNIT_ASSERT(pChild != NULL);
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_NUMBER);
  CPPUNIT_ASSERT(pChild->subType() == CEvaluationNode::S_DOUBLE);
  CPPUNIT_ASSERT((fabs(pChild->getValue() - 3.0) / 3.0) < 1e-6);
  pChild = dynamic_cast<CEvaluationNode*>(pChild->getSibling());
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_VARIABLE);
  CPPUNIT_ASSERT(pChild->getData() == std::string("b"));
  CPPUNIT_ASSERT(pChild->getSibling() == NULL);
  // 5.23
  pChild = dynamic_cast<CEvaluationNode*>(pExpanded->getChild()->getSibling()->getChild()->getSibling());
  CPPUNIT_ASSERT(pChild != NULL);
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_NUMBER);
  CPPUNIT_ASSERT(pChild->subType() == CEvaluationNode::S_DOUBLE);
  CPPUNIT_ASSERT((fabs(pChild->getValue() - 5.23) / 5.23) < 1e-6);
  CPPUNIT_ASSERT(pChild->getSibling() == NULL);

  delete pExpanded;

  // function_6
  pTree = pFunctionDB->findFunction("function_6");
  CPPUNIT_ASSERT(pTree != NULL);
  // generate a call node
  pFunction = dynamic_cast<CFunction*>(pTree);
  CPPUNIT_ASSERT(pFunction != NULL);
  pCallNode = new CEvaluationNodeCall(CEvaluationNode::S_FUNCTION, pFunction->getObjectName());
  CPPUNIT_ASSERT(pCallNode != NULL);
  pFunctionParameters = &pFunction->getVariables();
  i = 0, iMax = pFunctionParameters->size();

  while (i < iMax)
    {
      CFunctionParameter* pParameter = (*pFunctionParameters)[i];
      CPPUNIT_ASSERT(pParameter != NULL);
      CEvaluationNodeVariable* pVariableNode = new CEvaluationNodeVariable(CEvaluationNode::S_DEFAULT, pParameter->getObjectName());
      pCallNode->addChild(pVariableNode);
      ++i;
    }

  pExpanded = expand_function_calls(pCallNode, pFunctionDB);
  delete pCallNode;
  CPPUNIT_ASSERT(pExpanded != NULL);
  // (k1-k3*1.3)+((3*k2)-5.23)
  CPPUNIT_ASSERT(pExpanded->mainType() == CEvaluationNode::T_OPERATOR);
  CPPUNIT_ASSERT(pExpanded->subType() == CEvaluationNode::S_PLUS);
  pChild = dynamic_cast<CEvaluationNode*>(pExpanded->getChild());
  CPPUNIT_ASSERT(pChild != NULL);
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_OPERATOR);
  CPPUNIT_ASSERT(pChild->subType() == CEvaluationNode::S_MINUS);
  pChild = dynamic_cast<CEvaluationNode*>(pChild->getChild());
  CPPUNIT_ASSERT(pChild != NULL);
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_VARIABLE);
  CPPUNIT_ASSERT(pChild->getData() == std::string("k1"));
  pChild = dynamic_cast<CEvaluationNode*>(pChild->getSibling());
  CPPUNIT_ASSERT(pChild != NULL);
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_OPERATOR);
  CPPUNIT_ASSERT(pChild->subType() == CEvaluationNode::S_MULTIPLY);
  CPPUNIT_ASSERT(pChild->getSibling() == NULL);
  pChild = dynamic_cast<CEvaluationNode*>(pChild->getChild());
  CPPUNIT_ASSERT(pChild != NULL);
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_VARIABLE);
  CPPUNIT_ASSERT(pChild->getData() == std::string("k3"));
  pChild = dynamic_cast<CEvaluationNode*>(pChild->getSibling());
  CPPUNIT_ASSERT(pChild != NULL);
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_NUMBER);
  CPPUNIT_ASSERT(pChild->subType() == CEvaluationNode::S_DOUBLE);
  CPPUNIT_ASSERT((fabs(pChild->getValue() - 1.3) / 1.3) < 1e-6);
  CPPUNIT_ASSERT(pChild->getSibling() == NULL);

  // (3*b)-5.23
  pChild = dynamic_cast<CEvaluationNode*>(pExpanded->getChild()->getSibling());
  CPPUNIT_ASSERT(pChild != NULL);
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_OPERATOR);
  CPPUNIT_ASSERT(pChild->subType() == CEvaluationNode::S_MINUS);
  // 3*b
  pChild = dynamic_cast<CEvaluationNode*>(pChild->getChild());
  CPPUNIT_ASSERT(pChild != NULL);
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_OPERATOR);
  CPPUNIT_ASSERT(pChild->subType() == CEvaluationNode::S_MULTIPLY);
  pChild = dynamic_cast<CEvaluationNode*>(pChild->getChild());
  CPPUNIT_ASSERT(pChild != NULL);
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_NUMBER);
  CPPUNIT_ASSERT(pChild->subType() == CEvaluationNode::S_DOUBLE);
  CPPUNIT_ASSERT((fabs(pChild->getValue() - 3.0) / 3.0) < 1e-6);
  pChild = dynamic_cast<CEvaluationNode*>(pChild->getSibling());
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_VARIABLE);
  CPPUNIT_ASSERT(pChild->getData() == std::string("k2"));
  CPPUNIT_ASSERT(pChild->getSibling() == NULL);
  // 5.23
  pChild = dynamic_cast<CEvaluationNode*>(pExpanded->getChild()->getSibling()->getChild()->getSibling());
  CPPUNIT_ASSERT(pChild != NULL);
  CPPUNIT_ASSERT(pChild->mainType() == CEvaluationNode::T_NUMBER);
  CPPUNIT_ASSERT(pChild->subType() == CEvaluationNode::S_DOUBLE);
  CPPUNIT_ASSERT((fabs(pChild->getValue() - 5.23) / 5.23) < 1e-6);
  CPPUNIT_ASSERT(pChild->getSibling() == NULL);

  delete pExpanded;
}
コード例 #3
0
bool CODEExporterC::exportSingleFunction(const CFunction *func, std::set<std::string>& isExported)
{
  CFunctionDB* pFunctionDB = CCopasiRootContainer::getFunctionList();

  CFunction* tmpfunc = NULL;
  tmpfunc = new CFunction(*func, NO_PARENT);

  if (func->getType() != CEvaluationTree::MassAction)
    {

      CCopasiTree< CEvaluationNode>::iterator treeIt = tmpfunc->getRoot();
      CCopasiTree< CEvaluationNode>::iterator newIt = treeIt;

      size_t j, varbs_size = tmpfunc->getVariables().size();
      std::map< std::string, std::string > parameterNameMap;
      std::set<std::string> parameterNameSet;

      std::map< CFunctionParameter::Role, std::string > constName;
      std::map< CFunctionParameter::Role, size_t > tmpIndex;

      constName[CFunctionParameter::SUBSTRATE] = "sub_"; tmpIndex[CFunctionParameter::SUBSTRATE] = 0;
      constName[CFunctionParameter::PRODUCT] = "prod_"; tmpIndex[CFunctionParameter::PRODUCT] = 0;
      constName[CFunctionParameter::PARAMETER] = "param_"; tmpIndex[CFunctionParameter::PARAMETER] = 0;
      constName[CFunctionParameter::MODIFIER] = "modif_"; tmpIndex[CFunctionParameter::MODIFIER] = 0;
      constName[CFunctionParameter::VOLUME] = "volume_"; tmpIndex[CFunctionParameter::VOLUME] = 0;
      constName[CFunctionParameter::VARIABLE] = "varb_"; tmpIndex[CFunctionParameter::VARIABLE] = 0;
      constName[CFunctionParameter::TIME] = "time_"; tmpIndex[CFunctionParameter::VARIABLE] = 0;

      for (j = 0; j < varbs_size; ++j)
        {
          if (parameterNameSet.find(tmpfunc->getVariables()[j]->getObjectName()) == parameterNameSet.end())
            {
              std::ostringstream tmpName;
              CFunctionParameter::Role role = tmpfunc->getVariables()[j]->getUsage();

              tmpName << constName[role] << tmpIndex[role];
              parameterNameMap[ tmpfunc->getVariables()[j]->getObjectName()] = tmpName.str();
              parameterNameSet.insert(tmpfunc->getVariables()[j]->getObjectName());
              tmpIndex[role]++;
            }
        }

      CODEExporter::modifyTreeForMassAction(tmpfunc);

      while (newIt != NULL)
        {
          if (newIt->mainType() == CEvaluationNode::T_VARIABLE)
            {
              newIt->setData(parameterNameMap[ tmpfunc->getVariables()[newIt->getData()]->getObjectName()]);
            }

          if (newIt->mainType() == CEvaluationNode::T_CALL)
            {
              const CFunction* callfunc;
              callfunc = static_cast<CFunction*>(pFunctionDB->findFunction((*newIt).getData()));

              if (callfunc->getType() != CEvaluationTree::MassAction)
                newIt->setData(NameMap[callfunc->getKey()]);
            }

          ++newIt;
        }

      std::string name = func->getObjectName();

      if (isExported.find(name) == isExported.end())
        {
          size_t j, varbs_size = tmpfunc->getVariables().size();

          std::string mappedName = NameMap[func->getKey()];

          if (mappedName.empty())
            {
              NameMap[func->getKey()]  = translateObjectName(name);
              mappedName = NameMap[func->getKey()];
            }

          functions << "double " << mappedName << "(";
          headers << "double " << mappedName << "(";

          for (j = 0; j < varbs_size; ++j)
            {
              functions << "double " << parameterNameMap[ tmpfunc->getVariables()[j]->getObjectName().c_str()];

              if (j != varbs_size - 1) functions << ", ";

              headers << "double " << parameterNameMap[ tmpfunc->getVariables()[j]->getObjectName().c_str()];

              if (j != varbs_size - 1) headers << ", ";
            }

          functions << ") ";
          functions << '\t' << "//" << name << std::endl;
          functions << "{return  " << tmpfunc->getRoot()->buildCCodeString().c_str() << ";} " << std::endl;

          headers << "); " << std::endl;

          isExported.insert(name);
        }
    }

  return true;
}
コード例 #4
0
ファイル: abiochem.cpp プロジェクト: Koliham/COPASI
void MakeKinType(CFunctionDB &db, C_INT32 k, C_INT32 p, C_INT32 specific)
{
  C_INT32 i, j;
  CKinFunction *funct;
  char tmpstr[2048];
  string kiname, pname;
  string equation;

  // make name
  if (specific)
    sprintf(tmpstr, "basal %ld inh %ld spec act (indp)", k - p, p);
  else
    sprintf(tmpstr, "transcr %ld inh %ld act (indp)", k - p, p);

  kiname = tmpstr;
  if (db.findFunction(kiname) == NULL)
    {
      // not yet in the DB, so add it
      funct = new CKinFunction();
      if (funct == NULL)
        return;
      funct->setName(kiname);
      funct->setReversible(TriFalse);
      equation = "V";
      if (specific)
        {
          for (i = 0, j = 1; i < p; i++, j++)
            {
              sprintf(tmpstr, "*(A%ld/(A%ld+Ka%ld))^na%ld", j, j, j, j);
              equation += tmpstr;
            }
        }
      else
        {
          for (i = 0, j = 1; i < p; i++, j++)
            {
              sprintf(tmpstr, "*(1+A%ld/(A%ld+Ka%ld))^na%ld", j, j, j, j);
              equation += tmpstr;
            }
        }
      for (j = 1; i < k; i++, j++)
        {
          sprintf(tmpstr, "*(Ki%ld/(I%ld+Ki%ld))^ni%ld", j, j, j, j);
          equation += tmpstr;
        }
      funct->setDescription(equation);
      funct->addUsage("SUBSTRATES", 0, CRange::NoRange);
      funct->addUsage("PRODUCTS", 1, CRange::NoRange);
      pname = "V";
      funct->addParameter(pname, CFunctionParameter::FLOAT64, "PARAMETER");
      for (i = 0, j = 1; i < p; i++, j++)
        {
          sprintf(tmpstr, "Ka%ld", j);
          pname = tmpstr;
          funct->addParameter(pname, CFunctionParameter::FLOAT64, "PARAMETER");
          sprintf(tmpstr, "na%ld", j);
          pname = tmpstr;
          funct->addParameter(pname, CFunctionParameter::FLOAT64, "PARAMETER");
          sprintf(tmpstr, "A%ld", j);
          pname = tmpstr;
          funct->addParameter(pname, CFunctionParameter::FLOAT64, "MODIFIER");
        }
      for (j = 1; i < k; i++, j++)
        {
          sprintf(tmpstr, "Ki%ld", j);
          pname = tmpstr;
          funct->addParameter(pname, CFunctionParameter::FLOAT64, "PARAMETER");
          sprintf(tmpstr, "ni%ld", j);
          pname = tmpstr;
          funct->addParameter(pname, CFunctionParameter::FLOAT64, "PARAMETER");
          sprintf(tmpstr, "I%ld", j);
          pname = tmpstr;
          funct->addParameter(pname, CFunctionParameter::FLOAT64, "MODIFIER");
        }
      funct->compile();
      db.add(*funct);
    }
}
コード例 #5
0
ファイル: example7.cpp プロジェクト: ShuoLearner/COPASI
int main()
{
  // initialize the backend library
  // since we are not interested in the arguments
  // that are passed to main, we pass 0 and NULL to
  // init
  CCopasiRootContainer::init(0, NULL);
  assert(CCopasiRootContainer::getRoot() != NULL);
  // create a new datamodel
  CCopasiDataModel* pDataModel = CCopasiRootContainer::addDatamodel();
  assert(CCopasiRootContainer::getDatamodelList()->size() == 1);
  // get the model from the datamodel
  CModel* pModel = pDataModel->getModel();
  assert(pModel != NULL);
  // set the units for the model
  // we want seconds as the time unit
  // microliter as the volume units
  // and nanomole as the substance units
  pModel->setTimeUnit(CModel::s);
  pModel->setVolumeUnit(CModel::microl);
  pModel->setQuantityUnit(CModel::nMol);

  // we have to keep a set of all the initial values that are changed during
  // the model building process
  // They are needed after the model has been built to make sure all initial
  // values are set to the correct initial value
  std::set<const CCopasiObject*> changedObjects;

  // create a compartment with the name cell and an initial volume of 5.0
  // microliter
  CCompartment* pCompartment = pModel->createCompartment("cell", 5.0);
  const CCopasiObject* pObject = pCompartment->getValueReference();
  assert(pObject != NULL);
  changedObjects.insert(pObject);
  assert(pCompartment != NULL);
  assert(pModel->getCompartments().size() == 1);
  // create a new metabolite with the name S and an inital
  // concentration of 10 nanomol
  // the metabolite belongs to the compartment we created and is is to be
  // fixed
  CMetab* pS = pModel->createMetabolite("S", pCompartment->getObjectName(), 10.0, CMetab::FIXED);
  pObject = pS->getInitialConcentrationReference();
  assert(pObject != NULL);
  changedObjects.insert(pObject);
  assert(pCompartment != NULL);
  assert(pS != NULL);
  assert(pModel->getMetabolites().size() == 1);
  // create a second metabolite called P with an initial
  // concentration of 0. This metabolite is to be changed by reactions
  CMetab* pP = pModel->createMetabolite("P", pCompartment->getObjectName(), 0.0, CMetab::REACTIONS);
  assert(pP != NULL);
  pObject = pP->getInitialConcentrationReference();
  assert(pObject != NULL);
  changedObjects.insert(pObject);
  assert(pModel->getMetabolites().size() == 2);
  // now we create a reaction
  CReaction* pReaction = pModel->createReaction("reaction");
  assert(pReaction != NULL);
  assert(pModel->getReactions().size() == 1);
  // reaction converts S to P
  // we can set these on the chemical equation of the reaction
  CChemEq* pChemEq = &pReaction->getChemEq();
  // S is a substrate with stoichiometry 1
  pChemEq->addMetabolite(pS->getKey(), 1.0, CChemEq::SUBSTRATE);
  // P is a product with stoichiometry 1
  pChemEq->addMetabolite(pP->getKey(), 1.0, CChemEq::PRODUCT);
  assert(pChemEq->getSubstrates().size() == 1);
  assert(pChemEq->getProducts().size() == 1);
  // this reaction is to be irreversible
  pReaction->setReversible(false);
  assert(pReaction->isReversible() == false);

  CModelValue* pMV = pModel->createModelValue("K", 42.0);
  // set the status to FIXED
  pMV->setStatus(CModelValue::FIXED);
  assert(pMV != NULL);
  pObject = pMV->getInitialValueReference();
  assert(pObject != NULL);
  changedObjects.insert(pObject);
  assert(pModel->getModelValues().size() == 1);

  // now we ned to set a kinetic law on the reaction
  // for this we create a user defined function
  CFunctionDB* pFunDB = CCopasiRootContainer::getFunctionList();
  assert(pFunDB != NULL);

  CKinFunction* pFunction = new CKinFunction("My Rate Law");

  pFunDB->add(pFunction, true);
  CFunction* pRateLaw = dynamic_cast<CFunction*>(pFunDB->findFunction("My Rate Law"));

  assert(pRateLaw != NULL);

  // now we create the formula for the function and set it on the function
  std::string formula = "(1-0.4/(EXPONENTIALE^(temp-37)))*0.00001448471257*1.4^(temp-37)*substrate";

  bool result = pFunction->setInfix(formula);
  assert(result == true);
  // make the function irreversible
  pFunction->setReversible(TriFalse);
  // the formula string should have been parsed now
  // and COPASI should have determined that the formula string contained 2 parameters (temp and substrate)
  CFunctionParameters& variables = pFunction->getVariables();
  // per default the usage of those parameters will be set to VARIABLE
  size_t index = pFunction->getVariableIndex("temp");
  assert(index != C_INVALID_INDEX);
  CFunctionParameter* pParam = variables[index];
  assert(pParam->getUsage() == CFunctionParameter::VARIABLE);
  // This is correct for temp, but substrate should get the usage SUBSTRATE in order
  // for us to use the function with the reaction created above
  // So we need to set the usage for "substrate" manually
  index = pFunction->getVariableIndex("substrate");
  assert(index != C_INVALID_INDEX);
  pParam = variables[index];
  pParam->setUsage(CFunctionParameter::SUBSTRATE);

  // set the rate law for the reaction
  pReaction->setFunction(pFunction);
  assert(pReaction->getFunction() != NULL);

  // COPASI also needs to know what object it has to assocuiate with the individual function parameters
  // In our case we need to tell COPASI that substrate is to be replaced by the substrate of the reaction
  // and temp is to be replaced by the global parameter K
  pReaction->setParameterMapping("substrate", pS->getKey());
  pReaction->setParameterMapping("temp", pMV->getKey());

  // finally compile the model
  // compile needs to be done before updating all initial values for
  // the model with the refresh sequence
  pModel->compileIfNecessary(NULL);

  // now that we are done building the model, we have to make sure all
  // initial values are updated according to their dependencies
  std::vector<Refresh*> refreshes = pModel->buildInitialRefreshSequence(changedObjects);
  std::vector<Refresh*>::iterator it2 = refreshes.begin(), endit2 = refreshes.end();

  while (it2 != endit2)
    {
      // call each refresh
      (**it2)();
      ++it2;
    }

  // save the model to a COPASI file
  // we save to a file named example1.cps, we don't want a progress report
  // and we want to overwrite any existing file with the same name
  // Default tasks are automatically generated and will always appear in cps
  // file unless they are explicitley deleted before saving.
  pDataModel->saveModel("example7.cps", NULL, true);

  // export the model to an SBML file
  // we save to a file named example1.xml, we want to overwrite any
  // existing file with the same name and we want SBML L2V3
  pDataModel->exportSBML("example7.xml", true, 2, 3);

  // destroy the root container once we are done
  CCopasiRootContainer::destroy();
}