Skip to content

Commit

Permalink
#232: allow to store maps for each model
Browse files Browse the repository at this point in the history
  • Loading branch information
fbergmann committed Mar 14, 2023
1 parent b51d7ca commit 6f83f09
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 18 deletions.
4 changes: 4 additions & 0 deletions src/sbml/SBMLDocument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,11 @@ SBMLDocument::~SBMLDocument ()
if (mInternalValidator != NULL)
delete mInternalValidator;
if (mModel != NULL)
{
// remove from static map, since this object is being deleted
SBMLTransforms::clearComponentValues(mModel);
delete mModel;
}
clearValidators();
}

Expand Down
65 changes: 50 additions & 15 deletions src/sbml/SBMLTransforms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ LIBSBML_CPP_NAMESPACE_BEGIN
#ifdef __cplusplus

/** @cond doxygenLibsbmlInternal */
SBMLTransforms::IdValueMap SBMLTransforms::mValues;
SBMLTransforms::ModelValuesMap SBMLTransforms::mModelValues;

void
SBMLTransforms::replaceFD(ASTNode * node, const ListOfFunctionDefinitions *lofd, const IdList* idsToExclude /*= NULL*/)
Expand Down Expand Up @@ -289,7 +289,10 @@ SBMLTransforms::nodeContainsNameNotInList(const ASTNode * node, IdList& ids)
IdList
SBMLTransforms::mapComponentValues(const Model * m)
{
return getComponentValuesForModel(m, mValues);
IdValueMap values;
IdList result = getComponentValuesForModel(m, values);
mModelValues[m] = values;
return result;
}

/**
Expand Down Expand Up @@ -564,23 +567,53 @@ SBMLTransforms::getComponentValuesForModel(const Model * m, IdValueMap& values)
return ids;
}

SBMLTransforms::IdValueMap
SBMLTransforms::getComponentValues(const Model* m)
{
return mModelValues[m];
}

IdList
SBMLTransforms::getComponentIds(const Model* m)
{
IdList result;
IdValueMap values = mModelValues[m];
for (IdValueMap::iterator i = values.begin(); i != values.end(); ++i)
{
result.append(i->first);
}
return result;
}


void
SBMLTransforms::clearComponentValues()
SBMLTransforms::clearComponentValues(const Model* m)
{
mValues.clear();
if (!m)
{
// clear all maps if no model specified
mModelValues.clear();
return;
}

// otherwise remove only specific set
mModelValues.erase(m);
}



double
SBMLTransforms::evaluateASTNode(const ASTNode *node, const Model *m)
{
if (mValues.size() == 0)
if (m)
{
mapComponentValues(m);
IdValueMap values = mModelValues[m];
if (values.size() == 0)
{
mapComponentValues(m);
}
}
return evaluateASTNode(node, mValues, m);
return evaluateASTNode(node, mModelValues[m], m);
}

double
Expand Down Expand Up @@ -1217,6 +1250,7 @@ SBMLTransforms::expandInitialAssignments(Model * m)
{
IdList idsNoValues = mapComponentValues(m);
IdList idsWithValues;
IdValueMap values = mModelValues[m];

IdValueIter iter;
bool needToBail = false;
Expand All @@ -1230,7 +1264,7 @@ SBMLTransforms::expandInitialAssignments(Model * m)

/* list ids that have a calculated/assigned value */
idsWithValues.clear();
for (iter = mValues.begin(); iter != mValues.end(); ++iter)
for (iter = values.begin(); iter != values.end(); ++iter)
{
if (((*iter).second).second)
{
Expand Down Expand Up @@ -1270,7 +1304,7 @@ SBMLTransforms::expandInitialAssignments(Model * m)
while(count > 0 && needToBail == false);

// clear the internal map of values
mValues.clear();
clearComponentValues(m);

return true;
}
Expand All @@ -1280,6 +1314,7 @@ bool
SBMLTransforms::expandL3V2InitialAssignments(Model * m)
{
IdList idsNoValues = mapComponentValues(m);
IdValueMap values = mModelValues[m];
IdList idsWithValues;

IdValueIter iter;
Expand All @@ -1294,7 +1329,7 @@ SBMLTransforms::expandL3V2InitialAssignments(Model * m)

/* list ids that have a calculated/assigned value */
idsWithValues.clear();
for (iter = mValues.begin(); iter != mValues.end(); ++iter)
for (iter = values.begin(); iter != values.end(); ++iter)
{
if (((*iter).second).second)
{
Expand Down Expand Up @@ -1335,7 +1370,7 @@ SBMLTransforms::expandL3V2InitialAssignments(Model * m)
while(count > 0 && needToBail == false);

// clear the internal map of values
mValues.clear();
clearComponentValues(m);

return true;
}
Expand All @@ -1350,7 +1385,7 @@ SBMLTransforms::expandInitialAssignment(Compartment * c,
if (!util_isNaN(value))
{
c->setSize(value);
IdValueIter it = mValues.find(c->getId());
IdValueIter it = mModelValues[c->getModel()].find(c->getId());
((*it).second).first = value;
((*it).second).second = true;
success = true;
Expand All @@ -1368,7 +1403,7 @@ SBMLTransforms::expandInitialAssignment(Parameter * p,
if (!util_isNaN(value))
{
p->setValue(value);
IdValueIter it = mValues.find(p->getId());
IdValueIter it = mModelValues[p->getModel()].find(p->getId());
((*it).second).first = value;
((*it).second).second = true;
success = true;
Expand All @@ -1386,7 +1421,7 @@ SBMLTransforms::expandInitialAssignment(SpeciesReference * sr,
if (!util_isNaN(value))
{
sr->setStoichiometry(value);
IdValueIter it = mValues.find(sr->getId());
IdValueIter it = mModelValues[sr->getModel()].find(sr->getId());
((*it).second).first = value;
((*it).second).second = true;
success = true;
Expand All @@ -1412,7 +1447,7 @@ SBMLTransforms::expandInitialAssignment(Species * s,
s->setInitialConcentration(value);
}

IdValueIter it = mValues.find(s->getId());
IdValueIter it = mModelValues[s->getModel()].find(s->getId());
((*it).second).first = value;
((*it).second).second = true;
success = true;
Expand Down
102 changes: 99 additions & 3 deletions src/sbml/SBMLTransforms.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class LIBSBML_EXTERN SBMLTransforms
typedef std::pair<double, bool> ValueSet;
typedef std::map<const std::string, ValueSet> IdValueMap;
typedef IdValueMap::iterator IdValueIter;
typedef std::map<const Model*, IdValueMap> ModelValuesMap;
#endif

/**
Expand Down Expand Up @@ -136,24 +137,119 @@ class LIBSBML_EXTERN SBMLTransforms
const IdList* idsToExclude = NULL);


/**
* Expands the initial assignments in the given model
*
* @param m the model to expand the initial assignments in
*
* @return true if the model was changed, false otherwise
*/
static bool expandInitialAssignments(Model * m);


/**
* Evaluates the given AST node for the specified model
*
* @param node the AST node to evaluate
* @param m the model to evaluate the AST node for (if not NULL, all
* component values will be added to the map of values)
*
* @return the result of the evaluation
*/
static double evaluateASTNode(const ASTNode * node, const Model * m = NULL);

/**
* Expands the initial assignments in the given L3V2 model
*
* @param m the model to expand the initial assignments in
*
* @return true if the model was changed, false otherwise
*/
static bool expandL3V2InitialAssignments(Model * m);


#ifndef SWIG

/**
* Evaluates the given AST node for the specified model and values
*
* @param node the AST node to evaluate
* @param values the values to use for the evaluation of identifiers
* @param m the model to evaluate the AST node for
*
* @return the result of the evaluation
*/
static double evaluateASTNode(const ASTNode * node, const IdValueMap& values, const Model * m = NULL);

/**
* Evaluates the given AST node for the specified model and values
*
* This overload converts the map of values to an IdValueMap first
*
* @param node the AST node to evaluate
* @param values the values to use for the evaluation of identifiers
* @param m the model to evaluate the AST node for
*
* @return the result of the evaluation
*/
static double evaluateASTNode(const ASTNode * node, const std::map<std::string, double>& values, const Model * m = NULL);

/**
* creates a new component value map for the specified model (without adding it to the static map)
*
* @param m the model to create the map for
* @param values the values to fill from the model
*
* @return a list of all ids in the created map
*/
static IdList getComponentValuesForModel(const Model * m, IdValueMap& values);

/**
* Returns the component values for the specified model
*
* @param m the model to get the component values for
*
* @return the component values for the specified model (or empty if not in the static map)
*/

static IdValueMap getComponentValues(const Model* m);

/**
* Creates an IdList of the map of component values for the specified model
*
* @param m the model to get the component value ids for
*
* @return the list of ids in the map of component values for the specified model
*/
static IdList getComponentIds(const Model* m);
#endif

/**
* Creates a map of all values of the specified model.
*
* This also adds the created map to the static map of all model values. All
* identifiers that cannot be determined are returned.
*
* @param m the model to create the map for
*
* @return a list of all ids of the model that could not be determined
*/
static IdList mapComponentValues(const Model * m);

static void clearComponentValues();
/**
* Clears the component values for the specified model or all models if NULL
*
* @param m the model to clear the component values for or NULL to clear all
*/
static void clearComponentValues(const Model *m = NULL);

/**
* Checks whether the node contains any id in the specified list
*
* @param node the node to check
* @param ids the list of ids to check for
*
* @return true, if the node contains any id in the list, false otherwise
*/
static bool nodeContainsId(const ASTNode * node, IdList& ids);


Expand Down Expand Up @@ -183,7 +279,7 @@ class LIBSBML_EXTERN SBMLTransforms
const IdList* idsToExclude);


static IdValueMap mValues;
static ModelValuesMap mModelValues;

};

Expand Down
56 changes: 56 additions & 0 deletions src/sbml/test/TestSBMLTransforms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,61 @@ START_TEST(test_SBMLTransforms_evaluateAST_L2SpeciesReference)
}
END_TEST


START_TEST(test_SBMLTransforms_multipleMaps)
{
SBMLDocument d1(3, 1);
Model* m1 = d1.createModel();
Compartment* c1 = m1->createCompartment();
c1->setId("c");
c1->setConstant(true);
c1->setSize(1.0);

Species* s1 = m1->createSpecies();
s1->setId("s");
s1->setCompartment("c");
s1->setInitialConcentration(1.0);
s1->setHasOnlySubstanceUnits(false);

// at this point there shouldn't be a map for this model
fail_unless(SBMLTransforms::getComponentValues(m1).size() == 0);

// create a map for this model
IdList list1 = SBMLTransforms::mapComponentValues(m1);
fail_unless(list1.size() == 0);

SBMLDocument d2(3, 2);
Model* m2 = d2.createModel();
c1 = m2->createCompartment();
c1->setId("c");
c1->setConstant(true);
c1->setSize(2.0);

s1 = m2->createSpecies();
s1->setId("s");
s1->setCompartment("c");
s1->setInitialConcentration(2.0);
s1->setHasOnlySubstanceUnits(false);

fail_unless(SBMLTransforms::getComponentValues(m2).size() == 0);

IdList list2 = SBMLTransforms::mapComponentValues(m2);
fail_unless(list2.size() == 0);

SBMLTransforms::IdValueMap values1 = SBMLTransforms::getComponentValues(m1);
SBMLTransforms::IdValueMap values2 = SBMLTransforms::getComponentValues(m2);

fail_unless(values1["c"].first == 1);
fail_unless(values1["s"].first == 1);
fail_unless(values2["c"].first == 2);
fail_unless(values2["s"].first == 2);

SBMLTransforms::clearComponentValues(m1);
SBMLTransforms::clearComponentValues(m2);

}
END_TEST

Suite *
create_suite_SBMLTransforms (void)
{
Expand All @@ -994,6 +1049,7 @@ create_suite_SBMLTransforms (void)
tcase_add_test(tcase, test_SBMLTransforms_evaluateL3V2ASTWithModel);
tcase_add_test(tcase, test_SBMLTransforms_L3V2AssignmentNoMath);
tcase_add_test(tcase, test_SBMLTransforms_StoichiometryMath);
tcase_add_test(tcase, test_SBMLTransforms_multipleMaps);


suite_add_tcase(suite, tcase);
Expand Down

0 comments on commit 6f83f09

Please sign in to comment.