void Module::SetAssignmentFor(Model* sbmlmod, const Variable* var) { char cc = g_registry.GetCC(); formula_type ftype = var->GetFormulaType(); const Formula* formula = var->GetFormula(); if (!formula->IsEmpty()) { ASTNode* math = parseStringToASTNode(formula->ToSBMLString()); if (ftype == formulaASSIGNMENT) { AssignmentRule* ar = sbmlmod->createAssignmentRule(); ar->setVariable(var->GetNameDelimitedBy(cc)); ar->setMath(math); } else if (!formula->IsDouble() && !(IsSpecies(var->GetType()) && formula->IsAmountIn(var->GetCompartment()))) { //if it was a double or a species with an amount, we already dealt with it. Otherwise: InitialAssignment* ia = sbmlmod->createInitialAssignment(); ia->setSymbol(var->GetNameDelimitedBy(cc)); ia->setMath(math); } delete math; } if (ftype == formulaRATE) { formula = var->GetRateRule(); if (!formula->IsEmpty()) { ASTNode* math = parseStringToASTNode(var->GetRateRule()->ToSBMLString()); RateRule* rr = sbmlmod->createRateRule(); rr->setVariable(var->GetNameDelimitedBy(cc)); rr->setMath(math); delete math; } } }
void AssignmentCycles::addInitialAssignmentDependencies(const Model& m, const InitialAssignment& object) { unsigned int ns; std::string thisId = object.getSymbol(); /* loop thru the list of names in the Math * if they refer to a Reaction, an Assignment Rule * or an Initial Assignment add to the map * with the variable as key */ List* variables = object.getMath()->getListOfNodes( ASTNode_isName ); for (ns = 0; ns < variables->getSize(); ns++) { ASTNode* node = static_cast<ASTNode*>( variables->get(ns) ); string name = node->getName() ? node->getName() : ""; if (m.getReaction(name)) { mIdMap.insert(pair<const std::string, std::string>(thisId, name)); } else if (m.getRule(name) && m.getRule(name)->isAssignment()) { mIdMap.insert(pair<const std::string, std::string>(thisId, name)); } else if (m.getInitialAssignment(name)) { mIdMap.insert(pair<const std::string, std::string>(thisId, name)); } } delete variables; }
END_TEST START_TEST ( test_InitialAssignment ) { InitialAssignment* ia = new InitialAssignment(2, 4); fail_unless (!(ia->hasRequiredAttributes())); ia->setSymbol("ia"); fail_unless (ia->hasRequiredAttributes()); delete ia; }
END_TEST START_TEST ( test_InitialAssignment_parent_create ) { Model *m = new Model(2, 4); InitialAssignment *ia = m->createInitialAssignment(); ListOf *lo = m->getListOfInitialAssignments(); fail_unless(lo == m->getInitialAssignment(0)->getParentSBMLObject()); fail_unless(lo == ia->getParentSBMLObject()); fail_unless(m == lo->getParentSBMLObject()); }
END_TEST START_TEST ( test_InitialAssignment ) { InitialAssignment* ia = new InitialAssignment(2, 4); fail_unless (!(ia->hasRequiredElements())); ia->setMath(SBML_parseFormula("ia")); fail_unless (ia->hasRequiredElements()); delete ia; }
END_TEST START_TEST ( test_InitialAssignment_parent_NULL ) { SBMLDocument *d = new SBMLDocument(); Model *m = d->createModel(); InitialAssignment *c = m->createInitialAssignment(); InitialAssignment *c1 = c->clone(); delete d; fail_unless(c1->getAncestorOfType(SBML_MODEL) == NULL); fail_unless(c1->getParentSBMLObject() == NULL); fail_unless (c1->getSBMLDocument() == NULL); delete c1; }
END_TEST START_TEST ( test_InitialAssignment_parent_add ) { InitialAssignment *ia = new InitialAssignment(2, 4); Model *m = new Model(2, 4); ia->setSymbol("c"); ia->setMath(SBML_parseFormula("9")); m->addInitialAssignment(ia); delete ia; ListOf *lo = m->getListOfInitialAssignments(); fail_unless(lo == m->getInitialAssignment(0)->getParentSBMLObject()); fail_unless(m == lo->getParentSBMLObject()); }
void Submodel::createNewConversionFactor(string& cf, const ASTNode* newcf, string oldcf, Model* model) { stringstream npID; npID << oldcf << "_times_" << newcf->getName(); int i=0; while (model->getElementBySId(npID.str()) != NULL) { i++; npID.clear(); npID << oldcf << "_times_" << newcf->getName() << "_" << i; } cf = npID.str(); Parameter* newparam = model->createParameter(); newparam->setId(cf); newparam->setConstant(true); InitialAssignment* ia = model->createInitialAssignment(); ia->setSymbol(cf); string math = oldcf + " * " + newcf->getName(); ia->setMath(SBML_parseL3Formula(math.c_str())); }
int Submodel::convertTimeAndExtentWith(const ASTNode* tcf, const ASTNode* xcf, const ASTNode* klmod) { if (tcf==NULL && xcf==NULL) return LIBSBML_OPERATION_SUCCESS; Model* model = getInstantiation(); if (model==NULL) { //getInstantiation sets its own error messages. return LIBSBML_OPERATION_FAILED; } ASTNode tcftimes(AST_TIMES); ASTNode tcfdiv(AST_DIVIDE); if (tcf != NULL) { tcftimes.addChild(tcf->deepCopy()); tcfdiv.addChild(tcf->deepCopy()); } ASTNode rxndivide(AST_DIVIDE); if (klmod != NULL) { ASTNode rxnref(AST_NAME); rxndivide.addChild(rxnref.deepCopy()); rxndivide.addChild(klmod->deepCopy()); } List* allElements = model->getAllElements(); for (ListIterator iter = allElements->begin(); iter != allElements->end(); ++iter) { SBase* element = static_cast<SBase*>(*iter); assert(element != NULL); ASTNode* ast1 = NULL; ASTNode* ast2 = NULL; Constraint* constraint = NULL; Delay* delay = NULL; EventAssignment* ea = NULL; InitialAssignment* ia = NULL; KineticLaw* kl = NULL; Priority* priority = NULL; RateRule* rrule = NULL; Rule* rule = NULL; Submodel* submodel = NULL; Trigger* trigger = NULL; string cf = ""; //Reaction math will be converted below, in the bits with the kinetic law. But because of that, we need to handle references *to* the reaction: even if it has no kinetic law, the units have changed, and this needs to be reflected by the flattening routine. if (rxndivide.getNumChildren() != 0 && element->getTypeCode()==SBML_REACTION && element->isSetId()) { rxndivide.getChild(0)->setName(element->getId().c_str()); for (ListIterator iter = allElements->begin(); iter != allElements->end(); ++iter) { SBase* subelement = static_cast<SBase*>(*iter); subelement->replaceSIDWithFunction(element->getId(), &rxndivide); } } //Submodels need their timeConversionFactor and extentConversionFactor attributes converted. We're moving top-down, so all we need to do here is fix the conversion factor attributes themselves, pointing them to new parameters if need be. if ((tcf !=NULL || xcf != NULL) && element->getTypeCode()==SBML_COMP_SUBMODEL) { submodel = static_cast<Submodel*>(element); if (tcf != NULL) { if (submodel->isSetTimeConversionFactor()) { createNewConversionFactor(cf, tcf, submodel->getTimeConversionFactor(), model); submodel->setTimeConversionFactor(cf); } else { submodel->setTimeConversionFactor(tcf->getName()); } } if (xcf != NULL) { if (submodel->isSetExtentConversionFactor()) { createNewConversionFactor(cf, xcf, submodel->getExtentConversionFactor(), model); submodel->setExtentConversionFactor(cf); } else { submodel->setExtentConversionFactor(xcf->getName()); } } } if (tcf==NULL) { if (klmod !=NULL && element->getTypeCode()==SBML_KINETIC_LAW) { kl = static_cast<KineticLaw*>(element); if (kl->isSetMath()) { ast1 = new ASTNode(AST_TIMES); ast1->addChild(klmod->deepCopy()); ast1->addChild(kl->getMath()->deepCopy()); kl->setMath(ast1); delete ast1; } } } else { // All math 'time' and 'delay' csymbols must still be converted. // Also, several constructs are modified directly. switch(element->getTypeCode()) { //This would be a WHOLE LOT SIMPLER if there was a 'hasMath' class in libsbml. But even so, it would have to // handle the kinetic laws, rate rules, and delays separately. case SBML_KINETIC_LAW: //Kinetic laws are multiplied by 'klmod'. kl = static_cast<KineticLaw*>(element); ast1 = kl->getMath()->deepCopy(); convertCSymbols(ast1, &tcfdiv, &tcftimes); if (klmod !=NULL) { kl = static_cast<KineticLaw*>(element); if (kl->isSetMath()) { ast2 = new ASTNode(AST_TIMES); ast2->addChild(klmod->deepCopy()); ast2->addChild(ast1); kl->setMath(ast2); delete ast2; } } else { kl->setMath(ast1); delete ast1; } break; case SBML_DELAY: //Delays are multiplied by the time conversion factor. delay = static_cast<Delay*>(element); if (delay->isSetMath()) { ast1 = delay->getMath()->deepCopy(); convertCSymbols(ast1, &tcfdiv, &tcftimes); tcftimes.addChild(ast1); delay->setMath(&tcftimes); tcftimes.removeChild(1); delete ast1; } break; case SBML_RATE_RULE: //Rate rules are divided by the time conversion factor. rrule = static_cast<RateRule*>(element); if (rrule->isSetMath()) { ast1 = rrule->getMath()->deepCopy(); tcfdiv.insertChild(0, ast1); rrule->setMath(&tcfdiv); tcfdiv.removeChild(0); delete ast1; } //Fall through to: case SBML_ASSIGNMENT_RULE: case SBML_ALGEBRAIC_RULE: //Rules in general need csymbols converted. rule = static_cast<Rule*>(element); if (rule->isSetMath()) { ast1 = rule->getMath()->deepCopy(); convertCSymbols(ast1, &tcfdiv, &tcftimes); rule->setMath(ast1); delete ast1; } break; case SBML_EVENT_ASSIGNMENT: //Event assignments need csymbols converted. ea = static_cast<EventAssignment*>(element); if (ea->isSetMath()) { ast1 = ea->getMath()->deepCopy(); convertCSymbols(ast1, &tcfdiv, &tcftimes); ea->setMath(ast1); delete ast1; } break; case SBML_INITIAL_ASSIGNMENT: //Initial assignments need csymbols converted. ia = static_cast<InitialAssignment*>(element); if (ia->isSetMath()) { ast1 = ia->getMath()->deepCopy(); convertCSymbols(ast1, &tcfdiv, &tcftimes); ia->setMath(ast1); delete ast1; } break; case SBML_CONSTRAINT: //Constraints need csymbols converted. constraint = static_cast<Constraint*>(element); if (constraint->isSetMath()) { ast1 = constraint->getMath()->deepCopy(); convertCSymbols(ast1, &tcfdiv, &tcftimes); constraint->setMath(ast1); delete ast1; } break; case SBML_PRIORITY: //Priorities need csymbols converted. priority = static_cast<Priority*>(element); if (priority->isSetMath()) { ast1 = priority->getMath()->deepCopy(); convertCSymbols(ast1, &tcfdiv, &tcftimes); priority->setMath(ast1); delete ast1; } break; case SBML_TRIGGER: //Triggers need csymbols converted. trigger = static_cast<Trigger*>(element); if (trigger->isSetMath()) { ast1 = trigger->getMath()->deepCopy(); convertCSymbols(ast1, &tcfdiv, &tcftimes); trigger->setMath(ast1); delete ast1; } break; default: //Do nothing! If we wanted to call a plugin routine, this would be the place. The only other alternative is to #ifdef some code in here that deals with the math-containing package objects explicitly. Which might be the best option, all told. break; } } } delete allElements; return LIBSBML_OPERATION_SUCCESS; }
LIBSBML_CPP_NAMESPACE_USE int main (int argc, char* argv[]) { SBMLNamespaces sbmlns(3,1,"arrays",1); // create the document SBMLDocument *document = new SBMLDocument(&sbmlns); // set the required attribute to true ArraysSBMLDocumentPlugin * docPlug = static_cast<ArraysSBMLDocumentPlugin*>(document->getPlugin("arrays")); docPlug->setRequired(true); // create the Model Model* model=document->createModel(); // create the parameters // first parameter - for dimension m Parameter * p = model->createParameter(); p->setId("m"); p->setConstant(true); p->setValue(2); // second parameter - for dimension n p = model->createParameter(); p->setId("n"); p->setConstant(true); p->setValue(1); // third parameter - 2 x 1 matrix of parameters p = model->createParameter(); p->setId("x"); p->setConstant(false); // create the Dimensions via the Plugin ArraysSBasePlugin * arraysPlug = static_cast<ArraysSBasePlugin*>(p->getPlugin("arrays")); // first dimension Dimension * dim = arraysPlug->createDimension(); dim->setArrayDimension(0); dim->setSize("m"); // second dimension dim = arraysPlug->createDimension(); dim->setArrayDimension(1); dim->setSize("n"); // other parameters p = model->createParameter(); p->setId("y"); p->setConstant(true); p->setValue(2.3); // create the initialAssignment InitialAssignment *ia = model->createInitialAssignment(); ia->setSymbol("x"); ASTNode * row1 = new ASTNode(AST_LINEAR_ALGEBRA_VECTOR_CONSTRUCTOR); ASTNode * ci1 = new ASTNode(AST_NAME); ci1->setName("y"); row1->addChild(ci1); ASTNode * row2 = new ASTNode(AST_LINEAR_ALGEBRA_VECTOR_CONSTRUCTOR); ASTNode * ci2 = new ASTNode(AST_INTEGER); ci2->setValue(2); row2->addChild(ci2); ASTNode * math = new ASTNode(AST_LINEAR_ALGEBRA_VECTOR_CONSTRUCTOR); math->addChild(row1); math->addChild(row2); ia->setMath(math); writeSBML(document,"arrays_example3.xml"); delete document; return 0; }
void dealWithL1Stoichiometry(Model & m, bool l2) { unsigned int idCount = 0; char newid[15]; std::string id; for (unsigned int i = 0; i < m.getNumReactions(); i++) { Reaction *r = m.getReaction(i); unsigned int j; for (j = 0; j < r->getNumReactants(); j++) { SpeciesReference *sr = r->getReactant(j); if (sr->getDenominator() != 1) { long stoich = static_cast<long>(sr->getStoichiometry()); int denom = sr->getDenominator(); ASTNode *node = new ASTNode(); node->setValue(stoich, denom); if (l2 == true) { StoichiometryMath * sm = sr->createStoichiometryMath(); sm->setMath(node); } else { sprintf(newid, "speciesRefId_%u", idCount); id.assign(newid); idCount++; sr->setId(id); InitialAssignment * ar = m.createInitialAssignment(); ar->setSymbol(id); ar->setMath(node); sr->unsetStoichiometry(); } } } for (j = 0; j < r->getNumProducts(); j++) { SpeciesReference *sr = r->getProduct(j); if (sr->getDenominator() != 1) { long stoich = static_cast<long>(sr->getStoichiometry()); int denom = sr->getDenominator(); ASTNode *node = new ASTNode(); node->setValue(stoich, denom); if (l2 == true) { StoichiometryMath * sm = sr->createStoichiometryMath(); sm->setMath(node); } else { sprintf(newid, "speciesRefId_%u", idCount); id.assign(newid); idCount++; sr->setId(id); InitialAssignment * ar = m.createInitialAssignment(); ar->setSymbol(id); ar->setMath(node); sr->unsetStoichiometry(); } } } } }
void CompIdBase::checkId (const InitialAssignment& x) { if (x.isSetSymbol()) doCheckId(x.getSymbol(), x); }
void test000014::test_references_to_species() { // load the CPS file // export to SBML // check the resulting SBML model CCopasiDataModel* pDataModel = pCOPASIDATAMODEL; std::istringstream iss(test000014::MODEL_STRING); CPPUNIT_ASSERT(load_cps_model_from_stream(iss, *pDataModel) == true); CPPUNIT_ASSERT(pDataModel->getModel() != NULL); CPPUNIT_ASSERT(pDataModel->exportSBMLToString(NULL, 2, 3).empty() == false); SBMLDocument* pDocument = pDataModel->getCurrentSBMLDocument(); CPPUNIT_ASSERT(pDocument != NULL); Model* pModel = pDocument->getModel(); CPPUNIT_ASSERT(pModel != NULL); // assert that there is only one compartment and // assert the compartment is constant CPPUNIT_ASSERT(pModel->getNumCompartments() == 1); Compartment* pCompartment = pModel->getCompartment(0); CPPUNIT_ASSERT(pCompartment->getConstant() == false); CPPUNIT_ASSERT(pModel->getNumSpecies() == 2); Species* pSpecies = pModel->getSpecies(1); CPPUNIT_ASSERT(pSpecies->getHasOnlySubstanceUnits() == true); pSpecies = pModel->getSpecies(0); std::string idSpeciesA = pSpecies->getId(); CPPUNIT_ASSERT(pSpecies->getHasOnlySubstanceUnits() == true); CPPUNIT_ASSERT(pModel->getNumRules() == 1); CPPUNIT_ASSERT(pModel->getNumInitialAssignments() == 1); InitialAssignment* pAssignment = pModel->getInitialAssignment(0); CPPUNIT_ASSERT(pAssignment != NULL); CPPUNIT_ASSERT(pModel->getNumParameters() == 1); Parameter* pParameter = pModel->getParameter(0); CPPUNIT_ASSERT(pParameter != NULL); CPPUNIT_ASSERT(pAssignment->getSymbol() == pParameter->getId()); const ASTNode* pMath = pAssignment->getMath(); CPPUNIT_ASSERT(pMath != NULL); // the expression should be the species divided by the initial volume CPPUNIT_ASSERT(pMath->getType() == AST_DIVIDE); CPPUNIT_ASSERT(pMath->getNumChildren() == 2); CPPUNIT_ASSERT(pMath->getChild(0) != NULL); CPPUNIT_ASSERT(pMath->getChild(0)->getType() == AST_NAME); CPPUNIT_ASSERT(pMath->getChild(0)->getName() == pSpecies->getId()); CPPUNIT_ASSERT(pMath->getChild(1) != NULL); CPPUNIT_ASSERT(pMath->getChild(1)->getType() == AST_NAME); CPPUNIT_ASSERT(pMath->getChild(1)->getName() == pCompartment->getId()); CPPUNIT_ASSERT(pModel->getNumReactions() == 2); Reaction* pReaction = pModel->getReaction(0); // make sure this is reaction A -> CPPUNIT_ASSERT(pReaction != NULL); CPPUNIT_ASSERT(pReaction->getNumReactants() == 1); CPPUNIT_ASSERT(pReaction->getNumProducts() == 0); // check if all references in the kinetic law are unmodified // math element must be a multiplication of the mass action term by // the compartment volume // the mass action term is a multiplication of the parameter node by // the species node CPPUNIT_ASSERT(pReaction->isSetKineticLaw() == true); KineticLaw* pLaw = pReaction->getKineticLaw(); CPPUNIT_ASSERT(pLaw != NULL); CPPUNIT_ASSERT(pLaw->isSetMath() == true); pMath = pLaw->getMath(); CPPUNIT_ASSERT(pMath->getType() == AST_TIMES); CPPUNIT_ASSERT(pMath->getNumChildren() == 2); CPPUNIT_ASSERT(pMath->getChild(0) != NULL); CPPUNIT_ASSERT(pMath->getChild(0)->getType() == AST_NAME); CPPUNIT_ASSERT(pMath->getChild(0)->getName() == std::string("k1")); CPPUNIT_ASSERT(pMath->getChild(1) != NULL); CPPUNIT_ASSERT(pMath->getChild(1)->getType() == AST_NAME); CPPUNIT_ASSERT(pMath->getChild(1)->getName() == idSpeciesA); pReaction = pModel->getReaction(1); // make sure this is reaction A -> S CPPUNIT_ASSERT(pReaction != NULL); CPPUNIT_ASSERT(pReaction->getNumReactants() == 1); CPPUNIT_ASSERT(pReaction->getNumProducts() == 1); // check if all references in the kinetic law are unmodified // math element must be a multiplication of the compartments volume with // a function call with three arguments // the first argument is the reference to the species CPPUNIT_ASSERT(pReaction->isSetKineticLaw() == true); pLaw = pReaction->getKineticLaw(); CPPUNIT_ASSERT(pLaw != NULL); CPPUNIT_ASSERT(pLaw->isSetMath() == true); pMath = pLaw->getMath(); CPPUNIT_ASSERT(pMath->getType() == AST_TIMES); CPPUNIT_ASSERT(pMath->getNumChildren() == 2); CPPUNIT_ASSERT(pMath->getChild(0)->getType() == AST_NAME); CPPUNIT_ASSERT(pMath->getChild(0)->getName() == pCompartment->getId()); pMath = pMath->getChild(1); CPPUNIT_ASSERT(pMath != NULL); CPPUNIT_ASSERT(pMath->getType() == AST_FUNCTION); CPPUNIT_ASSERT(pMath->getNumChildren() == 3); pMath = pMath->getChild(0); CPPUNIT_ASSERT(pMath != NULL); CPPUNIT_ASSERT(pMath->getType() == AST_DIVIDE); CPPUNIT_ASSERT(pMath->getNumChildren() == 2); CPPUNIT_ASSERT(pMath->getChild(0) != NULL); CPPUNIT_ASSERT(pMath->getChild(0)->getType() == AST_NAME); CPPUNIT_ASSERT(pMath->getChild(0)->getName() == idSpeciesA); CPPUNIT_ASSERT(pMath->getChild(1) != NULL); CPPUNIT_ASSERT(pMath->getChild(1)->getType() == AST_NAME); CPPUNIT_ASSERT(pMath->getChild(1)->getName() == pCompartment->getId()); }
LIBSBML_CPP_NAMESPACE_USE int main (int argc, char *argv[]) { if (argc != 2) { cout << endl << "Usage: printUnits filename" << endl << endl; return 1; } const char* filename = argv[1]; SBMLDocument* document = readSBML(filename); if (document->getNumErrors() > 0) { cerr << "Encountered the following SBML errors:" << endl; document->printErrors(cerr); return 1; } Model* model = document->getModel(); if (model == 0) { cout << "No model present." << endl; return 1; } unsigned int i,j; for (i = 0; i < model->getNumSpecies(); i++) { Species* s = model->getSpecies(i); cout << "Species " << i << ": " << UnitDefinition::printUnits(s->getDerivedUnitDefinition()) << endl; } for (i = 0; i < model->getNumCompartments(); i++) { Compartment *c = model->getCompartment(i); cout << "Compartment " << i << ": " << UnitDefinition::printUnits(c->getDerivedUnitDefinition()) << endl; } for (i = 0; i < model->getNumParameters(); i++) { Parameter *p = model->getParameter(i); cout << "Parameter " << i << ": " << UnitDefinition::printUnits(p->getDerivedUnitDefinition()) << endl; } for (i = 0; i < model->getNumInitialAssignments(); i++) { InitialAssignment *ia = model->getInitialAssignment(i); cout << "InitialAssignment " << i << ": " << UnitDefinition::printUnits(ia->getDerivedUnitDefinition()) << endl; cout << " undeclared units: "; cout << (ia->containsUndeclaredUnits() ? "yes\n" : "no\n"); } for (i = 0; i < model->getNumEvents(); i++) { Event *e = model->getEvent(i); cout << "Event " << i << ": " << endl; if (e->isSetDelay()) { cout << "Delay: " << UnitDefinition::printUnits(e->getDelay()->getDerivedUnitDefinition()) << endl; cout << " undeclared units: "; cout << (e->getDelay()->containsUndeclaredUnits() ? "yes\n" : "no\n"); } for (j = 0; j < e->getNumEventAssignments(); j++) { EventAssignment *ea = e->getEventAssignment(j); cout << "EventAssignment " << j << ": " << UnitDefinition::printUnits(ea->getDerivedUnitDefinition()) << endl; cout << " undeclared units: "; cout << (ea->containsUndeclaredUnits() ? "yes\n" : "no\n"); } } for (i = 0; i < model->getNumReactions(); i++) { Reaction *r = model->getReaction(i); cout << "Reaction " << i << ": " << endl; if (r->isSetKineticLaw()) { cout << "Kinetic Law: " << UnitDefinition::printUnits(r->getKineticLaw()->getDerivedUnitDefinition()) << endl; cout << " undeclared units: "; cout << (r->getKineticLaw()->containsUndeclaredUnits() ? "yes\n" : "no\n"); } for (j = 0; j < r->getNumReactants(); j++) { SpeciesReference *sr = r->getReactant(j); if (sr->isSetStoichiometryMath()) { cout << "Reactant stoichiometryMath" << j << ": " << UnitDefinition::printUnits(sr->getStoichiometryMath()->getDerivedUnitDefinition()) << endl; cout << " undeclared units: "; cout << (sr->getStoichiometryMath()->containsUndeclaredUnits() ? "yes\n" : "no\n"); } } for (j = 0; j < r->getNumProducts(); j++) { SpeciesReference *sr = r->getProduct(j); if (sr->isSetStoichiometryMath()) { cout << "Product stoichiometryMath" << j << ": " << UnitDefinition::printUnits(sr->getStoichiometryMath()->getDerivedUnitDefinition()) << endl; cout << " undeclared units: "; cout << (sr->getStoichiometryMath()->containsUndeclaredUnits() ? "yes\n" : "no\n"); } } } for (i = 0; i < model->getNumRules(); i++) { Rule *r = model->getRule(i); cout << "Rule " << i << ": " << UnitDefinition::printUnits(r->getDerivedUnitDefinition()) << endl; cout << " undeclared units: "; cout << (r->containsUndeclaredUnits() ? "yes\n" : "no\n"); } delete document; return 0; }