/**
  * Checks that the function has only one argument
  */
void NumberArgsMathCheck::checkUnary(const Model& m, 
                                     const ASTNode& node, const SBase & sb)
{
  if (node.getNumChildren() != 1)
  {
    logMathConflict(node, sb);
  }
  else
  {
    checkMath(m, *node.getLeftChild(), sb);
  }
}
/**
  * Checks that the arguments of the branches of a piecewise are consistent
  *
  * If not, an error message is logged.
  */
void 
PiecewiseValueMathCheck::checkPiecewiseArgs (const Model& m, const ASTNode& node, 
                                                  const SBase & sb)
{
  unsigned int numChildren = node.getNumChildren();

  /* arguments must return consistent types */
  for (unsigned int n = 0; n < numChildren; n += 2)
  {
    if (returnsNumeric(m, node.getChild(n)) && 
      !returnsNumeric(m, node.getLeftChild()))
    {
      logMathConflict(node, sb);
    }
    else if (node.getChild(n)->isBoolean() && 
            !node.getLeftChild()->isBoolean())
    {
      logMathConflict(node, sb);
    }  
  }
}
/**
  * Checks that the arguments to eq or neq are consistent
  * i.e. have same type both boolean or both numeric
  *
  * If an inconsistency is found, an error message is logged.
  */
void 
EqualityArgsMathCheck::checkArgs (const Model& m, 
                                        const ASTNode& node, 
                                        const SBase & sb)
{
  /* check that node has two children */
  if (node.getNumChildren() != 2)
  {
    return;
  }

  /* arguments must return consistent value types */
  if (returnsNumeric(m, node.getLeftChild()) && 
     !returnsNumeric(m, node.getRightChild()))
  {
    logMathConflict(node, sb);
  }
  else if (node.getLeftChild()->isBoolean() && 
          !node.getRightChild()->isBoolean())
  {
    logMathConflict(node, sb);
  }    
}
/*
  * Checks that the units of the delay function are consistent
  *
  * If inconsistent units are found, an error message is logged.
  */
void 
ArgumentsUnitsCheck::checkUnitsFromDelay (const Model& m, 
                                        const ASTNode& node, 
                                        const SBase & sb, bool inKL, int reactNo)
{
  /* check that node has two children */
  if (node.getNumChildren() != 2)
  {
    return;
  }

  if (!m.getSBMLNamespaces()->getNamespaces())
  {
#if 0
    cout << "[DEBUG] XMLNS IS NULL" << endl;
#endif
  }

  /* delay(x, t) 
   * no restrictions on units of x
   * but t must have units of time
   */
  UnitDefinition *time = new UnitDefinition(m.getSBMLNamespaces());
  Unit *unit = new Unit(m.getSBMLNamespaces());
  unit->setKind(UNIT_KIND_SECOND);
  unit->initDefaults();
  UnitDefinition * tempUD;
  time->addUnit(unit);
  
  UnitFormulaFormatter *unitFormat = new UnitFormulaFormatter(&m);

  tempUD = unitFormat->getUnitDefinition(node.getRightChild(), inKL, reactNo);
  
  if (!unitFormat->getContainsUndeclaredUnits())
  {
    if (!UnitDefinition::areEquivalent(time, tempUD)) 
    {
      logInconsistentDelay(node, sb);
    }
  }

  delete time;
  delete tempUD;
  delete unit;
  delete unitFormat;

  checkUnits(m, *node.getLeftChild(), sb, inKL, reactNo);
}
/**
 * @return the error message to use when logging constraint violations.
 * This method is called by logFailure.
 *
 * Returns a message that the given @p id and its corresponding object are
 * in  conflict with an object previously defined.
 */
const string
PiecewiseValueMathCheck::getMessage (const ASTNode& node, const SBase& object)
{

  ostringstream msg;

  //msg << getPreamble();

  char * left = SBML_formulaToString(node.getLeftChild());
  msg << "\nThe piecewise formula ";
  msg << "in the " << getFieldname() << " element of the " << getTypename(object);
  msg << " returns arguments" ;
  msg << " which have different value types from the first element '";
  msg << left << "'."; 
  safe_free(left);

  return msg.str();
}
/**
 *
 * Creates an SBML model represented in "7.2 Example involving units"
 * in the SBML Level 2 Version 4 Specification.
 *
 */
SBMLDocument* createExampleInvolvingUnits()
{
  const unsigned int level   = Level;
  const unsigned int version = Version;

  //---------------------------------------------------------------------------
  //
  // Creates an SBMLDocument object 
  //
  //---------------------------------------------------------------------------

  SBMLDocument* sbmlDoc = new SBMLDocument(level,version);

  // Adds the namespace for XHTML to the SBMLDocument object.  We need this
  // because we will add notes to the model.  (By default, the SBML document
  // created by SBMLDocument only declares the SBML XML namespace.)

  sbmlDoc->getNamespaces()->add("http://www.w3.org/1999/xhtml", "xhtml");

  //---------------------------------------------------------------------------
  //
  // Creates a Model object inside the SBMLDocument object. 
  //
  //---------------------------------------------------------------------------

  Model* model = sbmlDoc->createModel();
  model->setId("unitsExample");

  //---------------------------------------------------------------------------
  //
  // Creates UnitDefinition objects inside the Model object.
  //
  //---------------------------------------------------------------------------

  // Temporary pointers (reused more than once below).

  UnitDefinition* unitdef;
  Unit *unit;

  //---------------------------------------------------------------------------  
  // (UnitDefinition1) Creates an UnitDefinition object ("substance").
  //
  // This has the effect of redefining the default unit of subtance for the
  // whole model.
  //---------------------------------------------------------------------------

  unitdef = model->createUnitDefinition();
  unitdef->setId("substance");

  //  Creates an Unit inside the UnitDefinition object 

  unit = unitdef->createUnit();
  unit->setKind(UNIT_KIND_MOLE);
  unit->setScale(-3);

  //--------------------------------------------------------------------------------
  // (UnitDefinition2) Creates an UnitDefinition object ("mmls") 
  //--------------------------------------------------------------------------------
    
  // Note that we can reuse the pointers 'unitdef' and 'unit' because the
  // actual UnitDefinition object (along with the Unit objects within it)
  // is already attached to the Model object.

  unitdef = model->createUnitDefinition();
  unitdef->setId("mmls");
    
  //  Creates an Unit inside the UnitDefinition object ("mmls")

  unit = unitdef->createUnit();
  unit->setKind(UNIT_KIND_MOLE);
  unit->setScale(-3);

  //  Creates an Unit inside the UnitDefinition object ("mmls")

  unit = unitdef->createUnit();
  unit->setKind(UNIT_KIND_LITRE);
  unit->setExponent(-1);

  //  Creates an Unit inside the UnitDefinition object ("mmls")

  unit = unitdef->createUnit();
  unit->setKind(UNIT_KIND_SECOND);
  unit->setExponent(-1);

  //--------------------------------------------------------------------------------
  // (UnitDefinition3) Creates an UnitDefinition object ("mml") 
  //--------------------------------------------------------------------------------
    
  unitdef = model->createUnitDefinition();
  unitdef->setId("mml");
    
  //  Creates an Unit inside the UnitDefinition object ("mml")

  unit = unitdef->createUnit();
  unit->setKind(UNIT_KIND_MOLE);
  unit->setScale(-3);

  //  Creates an Unit inside the UnitDefinition object ("mml")

  unit = unitdef->createUnit();
  unit->setKind(UNIT_KIND_LITRE);
  unit->setExponent(-1);


  //---------------------------------------------------------------------------
  //
  // Creates a Compartment object inside the Model object. 
  //
  //---------------------------------------------------------------------------

  Compartment* comp;
  const string compName = "cell";

  // Creates a Compartment object ("cell")

  comp = model->createCompartment();
  comp->setId(compName);
 
  // Sets the "size" attribute of the Compartment object.
  //
  //   The units of this Compartment object is the default SBML 
  //   units of volume (litre), and thus we don't have to explicitly invoke 
  //   setUnits("litre") function to set the default units.
  //
  comp->setSize(1);


  //---------------------------------------------------------------------------
  //
  // Creates Species objects inside the Model object. 
  //
  //---------------------------------------------------------------------------
  
  // Temporary pointer (reused more than once below).
  
  Species *sp;

  //---------------------------------------------------------------------------
  // (Species1) Creates a Species object ("x0")
  //---------------------------------------------------------------------------

  sp = model->createSpecies();
  sp->setId("x0");

  // Sets the "compartment" attribute of the Species object to identify the 
  // compartnet in which the Species object located.

  sp->setCompartment(compName);

  // Sets the "initialConcentration" attribute of the Species object.
  //
  //  The units of this Species object is determined by two attributes of this 
  //  Species object ("substanceUnits" and "hasOnlySubstanceUnits") and the
  //  "spatialDimensions" attribute of the Compartment object ("cytosol") in which 
  //  this species object is located.
  //  Since the default values are used for "substanceUnits" (substance (mole)) 
  //  and "hasOnlySubstanceUnits" (false) and the value of "spatialDimension" (3) 
  //  is greater than 0, the units of this Species object is  moles/liters . 
  //
  sp->setInitialConcentration(1);

  //---------------------------------------------------------------------------
  // (Species2) Creates a Species object ("x1")
  //---------------------------------------------------------------------------

  sp = model->createSpecies();
  sp->setId("x1");
  sp->setCompartment(compName);
  sp->setInitialConcentration(1);

  //---------------------------------------------------------------------------
  // (Species3) Creates a Species object ("s1")
  //---------------------------------------------------------------------------

  sp = model->createSpecies();
  sp->setCompartment(compName);
  sp->setId("s1");
  sp->setInitialConcentration(1);

  //---------------------------------------------------------------------------
  // (Species4) Creates a Species object ("s2")
  //---------------------------------------------------------------------------

  sp = model->createSpecies();
  sp->setCompartment(compName);
  sp->setId("s2");
  sp->setInitialConcentration(1);

  //---------------------------------------------------------------------------
  //
  // Creates global Parameter objects inside the Model object. 
  //
  //---------------------------------------------------------------------------

  Parameter* para;

  // Creates a Parameter ("vm")  

  para = model->createParameter();
  para->setId("vm");
  para->setValue(2);
  para->setUnits("mmls");

  // Creates a Parameter ("km")  

  para = model->createParameter();
  para->setId("km");
  para->setValue(2);
  para->setUnits("mml");


  //---------------------------------------------------------------------------
  //
  // Creates Reaction objects inside the Model object. 
  //
  //---------------------------------------------------------------------------
  
  // Temporary pointers.

  Reaction* reaction;
  SpeciesReference* spr;
  KineticLaw* kl;

  //---------------------------------------------------------------------------
  // (Reaction1) Creates a Reaction object ("v1").
  //---------------------------------------------------------------------------

  reaction = model->createReaction();
  reaction->setId("v1");

  //---------------------------------------------------------------------------
  // Creates Reactant objects inside the Reaction object ("v1"). 
  //---------------------------------------------------------------------------

  // (Reactant1) Creates a Reactant object that references Species "x0"
  // in the model.

  spr = reaction->createReactant();
  spr->setSpecies("x0");

  //---------------------------------------------------------------------------
  // Creates a Product object inside the Reaction object ("v1"). 
  //---------------------------------------------------------------------------

  // Creates a Product object that references Species "s1" in the model. 

  spr = reaction->createProduct();
  spr->setSpecies("s1");

  //---------------------------------------------------------------------------
  // Creates a KineticLaw object inside the Reaction object ("v1"). 
  //---------------------------------------------------------------------------
  
  kl = reaction->createKineticLaw();

  // Creates a <notes> element in the KineticLaw object.
  // Here we illustrate how to do it using a literal string.  This requires
  // known the required syntax of XHTML and the requirements for SBML <notes>
  // elements.  Later below, we show how to create notes using objects instead
  // of strings.

  string notesString = "<xhtml:p> ((vm * s1)/(km + s1)) * cell </xhtml:p>";
  kl->setNotes(notesString);

  //---------------------------------------------------------------------------
  // Creates an ASTNode object which represents the following KineticLaw object.
  //
  //  <math xmlns=\"http://www.w3.org/1998/Math/MathML\">
  //   <apply>
  //     <times/>
  //     <apply>
  //       <divide/>
  //       <apply>
  //         <times/>
  //           <ci> vm </ci>
  //           <ci> s1 </ci>
  //       </apply>
  //       <apply>
  //         <plus/>
  //           <ci> km </ci>
  //           <ci> s1 </ci>
  //       </apply>
  //     </apply>
  //     <ci> cell </ci>
  //    </apply>
  //  </math>
  //---------------------------------------------------------------------------

  //
  // In the following code, ASTNode objects, which construct an ASTNode tree 
  // of the above math, are created and added in the order of preorder traversal 
  // of the tree (i.e. the order corresponds to the nested structure of the above 
  // MathML elements), and thus the following code maybe a bit more efficient but 
  // maybe a bit difficult to read.
  //

  ASTNode* astMath = new ASTNode(AST_TIMES);

  astMath->addChild(new ASTNode(AST_DIVIDE));
  ASTNode* astDivide = astMath->getLeftChild();

  astDivide->addChild(new ASTNode(AST_TIMES));
  ASTNode* astTimes = astDivide->getLeftChild();

  astTimes->addChild(new ASTNode(AST_NAME));
  astTimes->getLeftChild()->setName("vm");

  astTimes->addChild(new ASTNode(AST_NAME));
  astTimes->getRightChild()->setName("s1");

  astDivide->addChild(new ASTNode(AST_PLUS));
  ASTNode* astPlus = astDivide->getRightChild();

  astPlus->addChild(new ASTNode(AST_NAME));
  astPlus->getLeftChild()->setName("km");

  astPlus->addChild(new ASTNode(AST_NAME));
  astPlus->getRightChild()->setName("s1");


  astMath->addChild(new ASTNode(AST_NAME));
  astMath->getRightChild()->setName("cell");

  //---------------------------------------------
  //
  // set the Math element
  //
  //------------------------------------------------

  kl->setMath(astMath);
  delete astMath;


  //---------------------------------------------------------------------------
  // (Reaction2) Creates a Reaction object ("v2").
  //---------------------------------------------------------------------------

  reaction = model->createReaction();
  reaction->setId("v2");

  //---------------------------------------------------------------------------
  // Creates Reactant objects inside the Reaction object ("v2"). 
  //---------------------------------------------------------------------------

  // (Reactant2) Creates a Reactant object that references Species "s1"
  // in the model.

  spr = reaction->createReactant();
  spr->setSpecies("s1");

  //---------------------------------------------------------------------------
  // Creates a Product object inside the Reaction object ("v2"). 
  //---------------------------------------------------------------------------

  // Creates a Product object that references Species "s2" in the model. 

  spr = reaction->createProduct();
  spr->setSpecies("s2");

  //---------------------------------------------------------------------------
  // Creates a KineticLaw object inside the Reaction object ("v2"). 
  //---------------------------------------------------------------------------
  
  kl = reaction->createKineticLaw();

  // Sets a notes (by XMLNode) to the KineticLaw object.
  //
  // The following code is an alternative to using setNotes(const string&).
  // The equivalent code would be like this:
  //   
  //     notesString = "<xhtml:p>((vm * s2)/(km + s2))*cell</xhtml:p>";
  //     kl->setNotes(notesString);

  // Creates an XMLNode of start element (<xhtml:p>) without attributes.

  XMLNode notesXMLNode(XMLTriple("p", "", "xhtml"), XMLAttributes());

  // Adds a text element to the start element.

  notesXMLNode.addChild(XMLNode(" ((vm * s2)/(km + s2)) * cell ")); 

  // Adds it to the kineticLaw object.

  kl->setNotes(&notesXMLNode);

  //---------------------------------------------------------------------------
  // Sets a math (ASTNode object) to the KineticLaw object.
  //---------------------------------------------------------------------------

  // To create mathematical expressions, one would typically construct
  // an ASTNode tree as the above example code which creates a math of another
  // KineticLaw object.  Here, to save some space and illustrate another approach 
  // of doing it, we will write out the formula in MathML form and then use a 
  // libSBML convenience function to create the ASTNode tree for us.  
  // (This is a bit dangerous; it's very easy to make mistakes when writing MathML 
  // by hand, so in a real program, we would not really want to do it this way.)

  string mathXMLString = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\">"
                         "  <apply>"
                         "    <times/>"
                         "    <apply>"
                         "      <divide/>"
                         "      <apply>"
                         "        <times/>"
                         "        <ci> vm </ci>"
                         "        <ci> s2 </ci>"
                         "      </apply>"
                         "      <apply>"
                         "        <plus/>"
                         "          <ci> km </ci>"
                         "          <ci> s2 </ci>"
                         "      </apply>"
                         "    </apply>"
                         "    <ci> cell </ci>"
                         "  </apply>"
                         "</math>";

  astMath = readMathMLFromString(mathXMLString.c_str());
  kl->setMath(astMath);
  delete astMath;


  //---------------------------------------------------------------------------
  // (Reaction3) Creates a Reaction object ("v3").
  //---------------------------------------------------------------------------

  reaction = model->createReaction();
  reaction->setId("v3");

  //---------------------------------------------------------------------------
  // Creates Reactant objects inside the Reaction object ("v3"). 
  //---------------------------------------------------------------------------

  // (Reactant2) Creates a Reactant object that references Species "s2"
  // in the model.

  spr = reaction->createReactant();
  spr->setSpecies("s2");

  //---------------------------------------------------------------------------
  // Creates a Product object inside the Reaction object ("v3"). 
  //---------------------------------------------------------------------------

  // Creates a Product object that references Species "x1" in the model. 

  spr = reaction->createProduct();
  spr->setSpecies("x1");


  //---------------------------------------------------------------------------
  // Creates a KineticLaw object inside the Reaction object ("v3"). 
  //---------------------------------------------------------------------------
  
  kl = reaction->createKineticLaw();

  // Sets a notes (by string) to the KineticLaw object.

  notesString = "<xhtml:p> ((vm * x1)/(km + x1)) * cell </xhtml:p>";
  kl->setNotes(notesString);

  //---------------------------------------------------------------------------
  // Sets a math (ASTNode object) to the KineticLaw object.
  //---------------------------------------------------------------------------

  mathXMLString = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\">"
                  "  <apply>"
                  "    <times/>"
                  "    <apply>"
                  "      <divide/>"
                  "      <apply>"
                  "        <times/>"
                  "        <ci> vm </ci>"
                  "        <ci> x1 </ci>"
                  "      </apply>"
                  "      <apply>"
                  "        <plus/>"
                  "          <ci> km </ci>"
                  "          <ci> x1 </ci>"
                  "      </apply>"
                  "    </apply>"
                  "    <ci> cell </ci>"
                  "  </apply>"
                  "</math>";

  astMath = readMathMLFromString(mathXMLString.c_str());
  kl->setMath(astMath);
  delete astMath;


  // Returns the created SBMLDocument object.
  // The returned object must be explicitly deleted by the caller,
  // otherwise memory leak will happen.

  return sbmlDoc;

}
Ejemplo n.º 7
0
/**
  * Checks that the units of the power function are consistent
  *
  * If inconsistent units are found, an error message is logged.
  * 
  * The two arguments to power, which are of the form power(a, b) 
  * with the meaning a^b, should be as follows: 
  * (1) if the second argument is an integer, 
  *     then the first argument can have any units; 
  * (2) if the second argument b is a rational number n/m, 
  * it must be possible to derive the m-th root of (a{unit})n,
  * where {unit} signifies the units associated with a; 
  * otherwise, (3) the units of the first argument must be “dimensionless”. 
  * The second argument (b) should always have units of “dimensionless”.
  *
  */
void 
PowerUnitsCheck::checkUnitsFromPower (const Model& m, 
                                        const ASTNode& node, 
                                        const SBase & sb, bool inKL, int reactNo)
{

  /* check that node has 2 children */
  if (node.getNumChildren() != 2)
  {
    return;
  }

  double value;
  UnitDefinition dim(m.getSBMLNamespaces());
  Unit unit(m.getSBMLNamespaces());
  unit.setKind(UNIT_KIND_DIMENSIONLESS);
  unit.initDefaults();
  dim.addUnit(&unit);

  UnitFormulaFormatter *unitFormat = new UnitFormulaFormatter(&m);

  UnitDefinition *tempUD = NULL;
  UnitDefinition *unitsArg1, *unitsArgPower;
  unitsArg1 = unitFormat->getUnitDefinition(node.getLeftChild(), inKL, reactNo);
  unsigned int undeclaredUnits = 
    unitFormat->getContainsUndeclaredUnits();

  ASTNode *child = node.getRightChild();
  unitFormat->resetFlags();
  unitsArgPower = unitFormat->getUnitDefinition(child, inKL, reactNo);

  unsigned int undeclaredUnitsPower = 
    unitFormat->getContainsUndeclaredUnits();

  // The second argument (b) should always have units of “dimensionless”.
  // or it has undeclared units that we assume are correct

  if (undeclaredUnitsPower == 0 && !UnitDefinition::areEquivalent(&dim, unitsArgPower))
  {
    logNonDimensionlessPowerConflict(node, sb);
  }

  // The first argument is dimensionless then it doesnt matter 
  // what the power is

  if (undeclaredUnits == 0 && !UnitDefinition::areEquivalent(&dim, unitsArg1))
  {
    // if not argument needs to be an integer or a rational 
    unsigned int isInteger = 0;
    unsigned int isRational = 0;
    unsigned int isExpression = 0;
    /* power must be an integer
     * but need to check that it is not a real
     * number that is integral
     * i.e. mathml <cn> 2 </cn> will record a "real"
     */
    if (child->isRational())
    {
      isRational = 1;
    }
    else if (child->isInteger())
    {
      isInteger = 1;
    }
    else if (child->isReal())
    {
      if (ceil(child->getReal()) == child->getReal())
      {
        isInteger = 1;
      }
    }
    else if (child->getNumChildren() > 0)

    {
      // power might itself be an expression
      tempUD = unitFormat->getUnitDefinition(child, inKL, reactNo);
      UnitDefinition::simplify(tempUD);

      if (tempUD->isVariantOfDimensionless())
      {
        SBMLTransforms::mapComponentValues(&m);
        double value = SBMLTransforms::evaluateASTNode(child);
        SBMLTransforms::clearComponentValues();

#if defined(__linux) 
        if (!std::isnan(value))
#else
        if (!isnan(value))	
#endif   
        {
          if (floor(value) != value)
            isExpression = 1;
          else
            isInteger = 1;
        }
        else
        {
          isExpression = 1;
        }
      }
      else
      {
        /* here the child is an expression with units
        * flag the expression as not checked
        */
        isExpression = 1;
      }
    }
    else 
    {
      // power could be a parameter or a speciesReference in l3
      const Parameter *param = NULL;
      const SpeciesReference *sr = NULL;

      if (child->isName())
      {
        /* Parameters may be declared in two places (the model and the
        * kinetic law's local parameter list), so we have to check both.
        */

        if (sb.getTypeCode() == SBML_KINETIC_LAW)
        {
	        const KineticLaw* kl = dynamic_cast<const KineticLaw*>(&sb);

	        /* First try local parameters and if null is returned, try
	        * the global parameters */
	        if (kl != NULL)
	        {
	          param = kl->getParameter(child->getName());
	        }
        }

	      if (param == NULL)
	      {
	        param = m.getParameter(child->getName());
	      }

        if (param == NULL && m.getLevel() > 2)
        {
          // could be a species reference
          sr = m.getSpeciesReference(child->getName());
        }
        
      }

      if (param != NULL)
      {
        /* We found a parameter with this identifier. */

        if (UnitDefinition::areEquivalent(&dim, unitsArgPower) || undeclaredUnitsPower)
        {
          value = param->getValue();
          if (value != 0)
          {
            if (ceil(value) == value)
            {
              isInteger = 1;
            }
          }

        }
        else
        {
	  /* No parameter definition found for child->getName() */
          logUnitConflict(node, sb);
        }
      }
      else if (sr != NULL)
      {
        // technically here there is an issue
        // stoichiometry is dimensionless
        SBMLTransforms::mapComponentValues(&m);
        double value = SBMLTransforms::evaluateASTNode(child, &m);
        SBMLTransforms::clearComponentValues();
        // but it may not be an integer
	
#if defined(__linux) 
        if (!std::isnan(value))
#else
        if (!isnan(value))	
#endif   
          // we cant check
        {
          isExpression = 1;
        }
        else
        {
          if (ceil(value) == value)
          {
            isInteger = 1;
          }
        }
      }
    }

    if (isRational == 1)
    {
      //FIX-ME will need sorting for double exponents

      //* (2) if the second argument b is a rational number n/m, 
      //* it must be possible to derive the m-th root of (a{unit})n,
      //* where {unit} signifies the units associated with a; 
      unsigned int impossible = 0;
      for (unsigned int n = 0; impossible == 0 && n < unitsArg1->getNumUnits(); n++)
      {
        if ((int)(unitsArg1->getUnit(n)->getExponent()) * child->getInteger() %
          child->getDenominator() != 0)
          impossible = 1;
      }

      if (impossible)
        logRationalPowerConflict(node, sb);

    }
    else if (isExpression == 1)
    {
      logExpressionPowerConflict(node, sb);
    }
    else if (isInteger == 0)
    {
      logNonIntegerPowerConflict(node, sb);
    }

  }




 // if (!areEquivalent(dim, unitsPower)) 
 // {
 //   /* 'v' does not have units of dimensionless. */

 //   /* If the power 'n' is a parameter, check if its units are either
 //    * undeclared or declared as dimensionless.  If either is the case,
 //    * the value of 'n' must be an integer.
 //    */

 //   const Parameter *param = NULL;

 //   if (child->isName())
 //   {
 //     /* Parameters may be declared in two places (the model and the
 //      * kinetic law's local parameter list), so we have to check both.
 //      */

 //     if (sb.getTypeCode() == SBML_KINETIC_LAW)
 //     {
	//      const KineticLaw* kl = dynamic_cast<const KineticLaw*>(&sb);

	//      /* First try local parameters and if null is returned, try
	//      * the global parameters */
	//      if (kl != NULL)
	//      {
	//        param = kl->getParameter(child->getName());
	//      }
 //     }

	//    if (param == NULL)
	//    {
	//      param = m.getParameter(child->getName());
	//    }
 //     
 //   }

 //   if (param != NULL)
 //   {
 //     /* We found a parameter with this identifier. */

 //     if (areEquivalent(dim, unitsArgPower) || unitFormat->hasUndeclaredUnits(child))
 //     {
 //       value = param->getValue();
 //       if (value != 0)
 //       {
 //         if (ceil(value) != value)
 //         {
 //           logUnitConflict(node, sb);
 //         }
 //       }

 //     }
 //     else
 //     {
	///* No parameter definition found for child->getName() */
 //       logUnitConflict(node, sb);
 //     }
 //   }
 //   else if (child->isFunction() || child->isOperator())
 //   {
 //     /* cannot test whether the value will be appropriate */
 //     if (!areEquivalent(dim, unitsArgPower))
 //     {
 //       logUnitConflict(node, sb);
 //     }
 //   }
 //   /* power must be an integer
 //    * but need to check that it is not a real
 //    * number that is integral
 //    * i.e. mathml <cn> 2 </cn> will record a "real"
 //    */
 //   else if (!child->isInteger())
 //   {
 //     if (!child->isReal()) 
 //     {
 //       logUnitConflict(node, sb);
 //     }
 //     else if (ceil(child->getReal()) != child->getReal())
 //     {
 //       logUnitConflict(node, sb);
 //     }
 //   }
 // }
 // else if (!areEquivalent(dim, unitsArgPower)) 
 // {
 //   /* power (3, k) */
 //   logUnitConflict(node, sb);
 // }

  checkUnits(m, *node.getLeftChild(), sb, inKL, reactNo);

  delete unitFormat;
  delete unitsArg1;
  delete unitsArgPower;
}