Ejemplo n.º 1
0
// static
CEvaluationNode * CEvaluationNodeDelay::fromAST(const ASTNode * pASTNode, const std::vector< CEvaluationNode * > & children)
{
  assert(pASTNode->getNumChildren() == children.size());

  size_t i = 0, iMax = children.size();

  SubType subType = SubType::DELAY;
  std::string data = "delay";

  CEvaluationNode * pConvertedNode = new CEvaluationNodeDelay(subType, data);

  for (i = 0; i < iMax; ++i)
    {
      pConvertedNode->addChild(children[i]);
    }

  pConvertedNode->compile(NULL);
  return pConvertedNode;
}
Ejemplo n.º 2
0
//TODO remove pModel
CEvaluationNode* CDerive::deriveBranch(const CEvaluationNode* node, const CCopasiObject * pObject,
                                       std::vector<const CEvaluationNode*>& env,
                                       //std::vector<const CCopasiObject*>& objenv,
                                       const CEvaluationTree* pTree,
                                       bool simplify)
{
  CEvaluationNode * newNode = NULL;

  const CEvaluationNodeOperator * pENO = dynamic_cast<const CEvaluationNodeOperator*>(node);

  if (pENO)
    {
      if (!pENO->getLeft() || !pENO->getRight()) return NULL;

      CEvaluationNode * pLeftDeriv = deriveBranch(pENO->getLeft(), pObject, env, pTree, simplify);

      if (!pLeftDeriv) return NULL;

      CEvaluationNode * pRightDeriv = deriveBranch(pENO->getRight(), pObject, env, pTree, simplify);

      if (!pRightDeriv) {delete pLeftDeriv; return NULL;}

      // we now know that derivations of the left and right branch exist

      switch ((CEvaluationNodeOperator::SubType) CEvaluationNode::subType(pENO->getType()))
        {
          case CEvaluationNodeOperator::MULTIPLY:
          {
            CEvaluationNode * pLeftCopy = copyBranch_var2obj(pENO->getLeft(), env);
            CEvaluationNode * pRightCopy = copyBranch_var2obj(pENO->getRight(), env);

            CEvaluationNode * tmpNode1 = multiply(pRightCopy, pLeftDeriv, simplify);
            CEvaluationNode * tmpNode2 = multiply(pRightDeriv, pLeftCopy, simplify);

            return add(tmpNode1, tmpNode2, simplify);
          }
          break;

          case CEvaluationNodeOperator::DIVIDE:
          {
            CEvaluationNode * pLeftCopy = copyBranch_var2obj(pENO->getLeft(), env);
            CEvaluationNode * pRightCopy = copyBranch_var2obj(pENO->getRight(), env);

            //numerator
            CEvaluationNode * tmpNode1 = multiply(pRightCopy, pLeftDeriv, simplify);
            CEvaluationNode * tmpNode2 = multiply(pRightDeriv, pLeftCopy, simplify);

            CEvaluationNode * minusNode = subtract(tmpNode1, tmpNode2, simplify);

            minusNode->compile(NULL);

            //denominator
            CEvaluationNode * powerNode = power(copyBranch_var2obj(pENO->getRight(), env),
                                                new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "2"),
                                                simplify);

            return divide(minusNode, powerNode, simplify);
          }
          break;

          case CEvaluationNodeOperator::PLUS:

            return add(pLeftDeriv, pRightDeriv, simplify);
            break;

          case CEvaluationNodeOperator::MINUS:

            return subtract(pLeftDeriv, pRightDeriv, simplify);
            break;

          case CEvaluationNodeOperator::POWER:
          {
            // b-1
            CEvaluationNode * tmpNode = subtract(copyBranch_var2obj(pENO->getRight(), env),
                                                 new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "1"),
                                                 simplify);

            // a^(b-1)
            CEvaluationNode * powerNode = power(copyBranch_var2obj(pENO->getLeft(), env), tmpNode, simplify);

            // b*a'
            tmpNode = multiply(copyBranch_var2obj(pENO->getRight(), env),
                               pLeftDeriv, simplify);

            // ln a
            CEvaluationNodeFunction * funcNode = new CEvaluationNodeFunction(CEvaluationNodeFunction::LOG, "ln");
            funcNode->addChild(copyBranch_var2obj(pENO->getLeft(), env)); // add a

            // a * b' * ln a
            CEvaluationNode * tmpNode2 = multiply(copyBranch_var2obj(pENO->getLeft(), env),
                                                  multiply(pRightDeriv, funcNode, simplify),
                                                  simplify);

            // b*a + a*b * ln a
            CEvaluationNode * plusNode = add(tmpNode, tmpNode2, simplify);

            // a^(b-1)*(b*a + a*b * ln a)
            return multiply(powerNode, plusNode, simplify);
          }
          break;

          default:
            break;
        }
    }

  const CEvaluationNodeVariable * pENV = dynamic_cast<const CEvaluationNodeVariable*>(node);

  if (pENV)
    {
      if (!env[pENV->getIndex()])
        return NULL;

      //basically just expand the tree.
      return deriveBranch(env[pENV->getIndex()], pObject, env, pTree, simplify);
    }

  const CEvaluationNodeNumber * pENN = dynamic_cast<const CEvaluationNodeNumber*>(node);

  if (pENN)
    {
      newNode = new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "0");
      return newNode;
    }

  const CEvaluationNodeObject *pENObj = dynamic_cast<const CEvaluationNodeObject*>(node);

  if (pENObj)
    {
      //first check whether the object is the derivation variable
      if (pObject->getCN() == pENObj->getObjectCN())
        {
          //std::cout << "*";
          return new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "1");
        }

      //now we need to check if we know something about the object so that it needs to be expanded
      const CCopasiObject * tmpObj = (const CCopasiObject *)pENObj->getObjectInterfacePtr();

      if (!tmpObj)
        return NULL;

      //object is a concentration?
      if (tmpObj->getObjectName() == "Concentration")
        {
          //std::cout << "Concentration found" << std::endl;
          //In this context, the concentration is expanded as "amount of substance/volume"
          std::string tmpstr = tmpObj->getObjectParent() ? "<" + tmpObj->getObjectParent()->getCN() + ",Reference=ParticleNumber>" : "<>";
          CEvaluationNodeObject* amount = new CEvaluationNodeObject(CEvaluationNodeObject::CN, tmpstr);
          amount->compile(pTree);

          tmpstr = tmpObj->getObjectAncestor("Compartment") ? "<" + tmpObj->getObjectAncestor("Compartment")->getCN() + ",Reference=Volume>"  : "<>";
          CEvaluationNodeObject* volume = new CEvaluationNodeObject(CEvaluationNodeObject::CN, tmpstr);
          volume->compile(pTree);
          CEvaluationNodeObject* volume2 = new CEvaluationNodeObject(CEvaluationNodeObject::CN, tmpstr); //we need this node twice
          volume2->compile(pTree);

          CEvaluationNode* damount = deriveBranch(amount, pObject, env, pTree, simplify);
          CEvaluationNode* dvolume = deriveBranch(volume, pObject, env, pTree, simplify);

          // A / V - A*V /V^2
          return
            subtract(divide(damount, volume, simplify),
                     divide(multiply(amount, dvolume, simplify),
                            power(volume2, new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "2"), simplify),
                            simplify),
                     simplify);
        }

      //TODO:
      //object is an object with an assignment
      //object is dependent species
      //object is a reaction rate

      // otherwise return 0.
      return new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "0");
    }

  const CEvaluationNodeCall  *pENCall = dynamic_cast<const CEvaluationNodeCall*>(node);

  if (pENCall)
    {

      //is it a function?
      const CFunction * tmpFunction = dynamic_cast<const CFunction*>(pENCall->getCalledTree());

//     const std::vector<CEvaluationNode *> getListOfChildNodes() const {return mCallNodes;}

      //create call environment for the called function
      std::vector<const CEvaluationNode*> subenv;
      size_t i, imax = pENCall->getListOfChildNodes().size();
      subenv.resize(imax);

      for (i = 0; i < imax; ++i)
        {
          CEvaluationNode* tmpnode = copyBranch_var2obj(pENCall->getListOfChildNodes()[i], env);
          compileTree(tmpnode, pTree);
          subenv[i] = tmpnode;
        }

      return deriveBranch(pENCall->getCalledTree()->getRoot(), pObject,
                          subenv,
                          pTree, simplify);
    }

  return newNode;
}