diff --git a/src/sbml/conversion/ExpressionAnalyser.cpp b/src/sbml/conversion/ExpressionAnalyser.cpp index 104952900..a33c66d13 100644 --- a/src/sbml/conversion/ExpressionAnalyser.cpp +++ b/src/sbml/conversion/ExpressionAnalyser.cpp @@ -52,6 +52,13 @@ using namespace std; LIBSBML_CPP_NAMESPACE_BEGIN +bool compareExpressions(SubstitutionValues_t* values1, SubstitutionValues_t* values2) +{ + if (values1->type >= values2->type) + return true; + return false; +} + ExpressionAnalyser::ExpressionAnalyser() : mModel (NULL), mODEs (), @@ -340,6 +347,13 @@ bool ExpressionAnalyser::expressionExists(SubstitutionValues_t* current, bool ExpressionAnalyser::parentExpressionExists(SubstitutionValues_t* current, SubstitutionValues_t* mightAdd) { bool parentExists = false; + + // if the expressions are on the same level then one cannot be the child of another + if (current->levelInExpression == mightAdd->levelInExpression) + { + return false; + } + // here we want to find out if the expression is actually a child of another // and therefore need not be logged // all expressions will have K and X but the type may not be the same @@ -530,7 +544,7 @@ SubstitutionValues_t* ExpressionAnalyser::getExpression(unsigned int index) * e.g. if we have k-x-y do not need to analyse k-x */ bool -ExpressionAnalyser::shouldAddExpression(SubstitutionValues_t* value) +ExpressionAnalyser::shouldAddExpression(SubstitutionValues_t* value, ASTNodePair currentNode) { bool found = false; bool foundParent = false; @@ -559,8 +573,22 @@ bool ExpressionAnalyser::analyseNode(ASTNode* node, SubstitutionValues_t *value) { // cout << "current node: " << SBML_formulaToL3String(node) << endl; - unsigned int numChildren = node->getNumChildren(); ASTNodeType_t type = node->getType(); + + // type must be plus or minus + if (type != AST_PLUS && type != AST_MINUS) + { + return false; + } + unsigned int numChildren = node->getNumChildren(); + + // we must have two children + if (numChildren != 2) + { + return false; + } + + ASTNode* rightChild = node->getRightChild(); ASTNode* leftChild = node->getLeftChild(); //cout << "RIGHT CHILD: " << SBML_formulaToL3String(rightChild) << endl; @@ -648,11 +676,11 @@ ExpressionAnalyser::detect_minusXPlusYOnly() value->type = TYPE_MINUS_X_PLUS_Y; value->current = currentNode; value->odeIndex = odeIndex; - if (!shouldAddExpression(value)) - { - printSubstitutionValues(value); - mExpressions.push_back(value); - } + //if (shouldAddExpression(value)) + ////{ + // printSubstitutionValues(value); + // mExpressions.push_back(value); + //} } @@ -670,19 +698,20 @@ ExpressionAnalyser::analyse(bool minusXPlusYOnly) ASTNode* odeRHS = ode.second; odeRHS->decompose(); odeRHS->reduceToBinary(); - List* operators = odeRHS->getListOfNodes((ASTNodePredicate)ASTNode_isOperator); - ListIterator it = operators->begin(); + ASTNodeLevels operators = odeRHS->getListOfNodesWithLevel(); + ASTNodeLevelsIterator it = operators.begin(); - while (it != operators->end()) + while (it != operators.end()) { - ASTNode* currentNode = (ASTNode*)*it; + ASTNodePair currentNode = (ASTNodePair)*it; SubstitutionValues_t* value = createBlankSubstitutionValues(); - cout << "current node: " << SBML_formulaToL3String(currentNode) << endl; - if (analyseNode(currentNode, value)) + cout << "Level " << currentNode.first << ": " << SBML_formulaToL3String(currentNode.second) << endl; + if (analyseNode(currentNode.second, value)) { value->odeIndex = odeIndex; - if (shouldAddExpression(value)) + value->levelInExpression = currentNode.first; + if (shouldAddExpression(value, currentNode)) { //printSubstitutionValues(value); mExpressions.push_back(value); @@ -695,18 +724,7 @@ ExpressionAnalyser::analyse(bool minusXPlusYOnly) void ExpressionAnalyser::orderExpressions() { - for (unsigned int i = 0; i < mExpressions.size(); i++) - { - for (unsigned int j = i + 1; j < mExpressions.size(); j++) - { - if (mExpressions[i]->type > mExpressions[j]->type) - { - SubstitutionValues_t* temp = mExpressions[i]; - mExpressions[i] = mExpressions[j]; - mExpressions[j] = temp; - } - } - } + std::sort(mExpressions.begin(), mExpressions.end(), compareExpressions); } void @@ -1251,4 +1269,3 @@ LIBSBML_CPP_NAMESPACE_END #endif /* __cplusplus */ - diff --git a/src/sbml/conversion/ExpressionAnalyser.h b/src/sbml/conversion/ExpressionAnalyser.h index 5b5341984..3755788d2 100644 --- a/src/sbml/conversion/ExpressionAnalyser.h +++ b/src/sbml/conversion/ExpressionAnalyser.h @@ -91,8 +91,10 @@ struct SubstitutionValues_t { std::string z_value; ASTNode* z_expression; unsigned int odeIndex; + unsigned int levelInExpression; }; +bool compareExpressions(SubstitutionValues_t* values1, SubstitutionValues_t* values2); class LIBSBML_EXTERN ExpressionAnalyser @@ -236,7 +238,7 @@ class LIBSBML_EXTERN ExpressionAnalyser /* * Loops through expressions already recorded and checks for exact matches */ - bool shouldAddExpression(SubstitutionValues_t* value); + bool shouldAddExpression(SubstitutionValues_t* value, ASTNodePair currentNode); bool expressionExists(SubstitutionValues_t* current, SubstitutionValues_t* mightAdd); diff --git a/src/sbml/conversion/SBMLRateRuleConverter.cpp b/src/sbml/conversion/SBMLRateRuleConverter.cpp index 7d0a1b079..057fd9fa8 100644 --- a/src/sbml/conversion/SBMLRateRuleConverter.cpp +++ b/src/sbml/conversion/SBMLRateRuleConverter.cpp @@ -863,10 +863,10 @@ SBMLRateRuleConverter::populateInitialODEinfo() } } - for (unsigned int odeIndex = 0; odeIndex < mODEs.size(); odeIndex++) - { - cout << mODEs[odeIndex].first << ": " << SBML_formulaToL3String(mODEs[odeIndex].second) << endl; - } + //for (unsigned int odeIndex = 0; odeIndex < mODEs.size(); odeIndex++) + //{ + // cout << mODEs[odeIndex].first << ": " << SBML_formulaToL3String(mODEs[odeIndex].second) << endl; + //} } diff --git a/src/sbml/conversion/test/TestExpressionAnalyser.cpp b/src/sbml/conversion/test/TestExpressionAnalyser.cpp index 61febe50a..91da0b4dd 100644 --- a/src/sbml/conversion/test/TestExpressionAnalyser.cpp +++ b/src/sbml/conversion/test/TestExpressionAnalyser.cpp @@ -485,6 +485,38 @@ START_TEST(test_analyse_4) } END_TEST +START_TEST(test_order_expressions_1) +{ + RateRule* rr = d->getModel()->createRateRule(); + rr->setVariable("b"); + rr->setMath(SBML_parseFormula("k - x + w - y")); + + RateRule* rrr = d->getModel()->createRateRule(); + rrr->setVariable("a"); + rrr->setMath(SBML_parseFormula("k-x-y")); + converter->populateInitialODEinfo(); + ExpressionAnalyser* analyser = new ExpressionAnalyser(m, converter->getOdePairs()); + + fail_unless(analyser->getNumExpressions() == 0); + + analyser->analyse(); + + fail_unless(analyser->getNumExpressions() == 2); + SubstitutionValues_t* value = analyser->getExpression(0); + //fail_unless(value->type == TYPE_K_MINUS_X_PLUS_W_MINUS_Y); + SubstitutionValues_t* value1 = analyser->getExpression(1); + //fail_unless(value1->type == TYPE_K_MINUS_X_MINUS_Y); + + analyser->orderExpressions(); + fail_unless(analyser->getNumExpressions() == 2); + SubstitutionValues_t* value2 = analyser->getExpression(0); + fail_unless(value2->type == TYPE_K_MINUS_X_MINUS_Y); + SubstitutionValues_t* value3 = analyser->getExpression(1); + fail_unless(value3->type == TYPE_K_MINUS_X_PLUS_W_MINUS_Y); +} +END_TEST + + START_TEST(test_reorder_minusXplusYIteratively_simple) { RateRule* rr = d->getModel()->createRateRule(); @@ -495,25 +527,26 @@ START_TEST(test_reorder_minusXplusYIteratively_simple) fail_unless(analyser->getNumExpressions() == 0); - analyser->detect_minusXPlusYOnly(); + analyser->analyse(); - fail_unless(analyser->getNumExpressions() == 1); + // since we decomposed the term we no longer need to identify this type - analyser->reorderMinusXPlusYIteratively(); - SubstitutionValues_t* value = analyser->getExpression(0); - fail_unless(value->k_value.empty()); - fail_unless(value->x_value == "x"); - fail_unless(value->y_value == "y"); - fail_unless(value->z_value.empty()); - fail_unless(value->type == TYPE_MINUS_X_PLUS_Y); - fail_unless(formulas_equal("-x + y", value->current)); - fail_unless(formulas_equal("0", value->dxdt_expression)); - fail_unless(formulas_equal("0", value->dydt_expression)); - fail_unless(value->v_expression == NULL); - fail_unless(value->w_expression == NULL); - fail_unless(value->z_expression == NULL); - fail_unless(value->odeIndex == 0); - fail_unless(util_isNaN(value->k_real_value)); + fail_unless(analyser->getNumExpressions() == 0); + + //SubstitutionValues_t* value = analyser->getExpression(0); + //fail_unless(value->k_value.empty()); + //fail_unless(value->x_value == "x"); + //fail_unless(value->y_value == "y"); + //fail_unless(value->z_value.empty()); + //fail_unless(value->type == TYPE_MINUS_X_PLUS_Y); + //fail_unless(formulas_equal("-x + y", value->current)); + //fail_unless(formulas_equal("0", value->dxdt_expression)); + //fail_unless(formulas_equal("0", value->dydt_expression)); + //fail_unless(value->v_expression == NULL); + //fail_unless(value->w_expression == NULL); + //fail_unless(value->z_expression == NULL); + //fail_unless(value->odeIndex == 0); + //fail_unless(util_isNaN(value->k_real_value)); } END_TEST @@ -724,7 +757,7 @@ Suite *suite = suite_create("ExpressionAnalyser"); if (testing) { - tcase_add_test(tcase, test_analyse_1_two_terms); + tcase_add_test(tcase, test_order_expressions_1); } else { @@ -738,7 +771,7 @@ Suite *suite = suite_create("ExpressionAnalyser"); tcase_add_test(tcase, test_analyse_1_same); //k+v-x-y tcase_add_test(tcase, test_analyse_1_two_terms); //(k+v-x-y)+(k-x) tcase_add_test(tcase, test_analyse_1_different); //k+v-x-y - //tcase_add_test(tcase, test_order_of_replacements); + tcase_add_test(tcase, test_reorder_minusXplusYIteratively_simple); //tcase_add_test(tcase, test_order_of_replacements1); //tcase_add_test(tcase, test_order_of_replacements2); diff --git a/src/sbml/math/ASTNode.cpp b/src/sbml/math/ASTNode.cpp index c96fbeecb..1a28fc322 100644 --- a/src/sbml/math/ASTNode.cpp +++ b/src/sbml/math/ASTNode.cpp @@ -1183,7 +1183,7 @@ void ASTNode::fillListOfNodesWithLevel(ASTNodePredicate predicate, ASTNodeLevels if (predicate(this) != 0) { - cout << "Level " << level << ": " << SBML_formulaToL3String(this) << endl; + //cout << "Level " << level << ": " << SBML_formulaToL3String(this) << endl; vector_pairs.push_back(std::make_pair(level, (ASTNode*)this)); } diff --git a/src/sbml/math/ASTNode.h b/src/sbml/math/ASTNode.h index 2ad1497f8..592cc9863 100644 --- a/src/sbml/math/ASTNode.h +++ b/src/sbml/math/ASTNode.h @@ -212,10 +212,13 @@ LIBSBML_CPP_NAMESPACE_END #ifdef __cplusplus LIBSBML_CPP_NAMESPACE_BEGIN +#ifndef SWIG + typedef std::pair ASTNodePair; typedef std::vector ASTNodeLevels; typedef ASTNodeLevels::iterator ASTNodeLevelsIterator; +#endif // !SWIG class List; diff --git a/src/sbml/math/test/TestLevelNodeFunction.cpp b/src/sbml/math/test/TestLevelNodeFunction.cpp index ec3d7f3af..1cddbd6fa 100644 --- a/src/sbml/math/test/TestLevelNodeFunction.cpp +++ b/src/sbml/math/test/TestLevelNodeFunction.cpp @@ -140,15 +140,143 @@ START_TEST(test_level_2) } END_TEST + +START_TEST(test_level_3) +{ + ASTNode* node = SBML_parseL3Formula("k + v - x - y"); + ASTNodeLevels node_levels = node->getListOfNodesWithLevel(); + fail_unless(node_levels.size() == 7); + fail_unless(node_levels[0].first == 0); + fail_unless(formulas_equal("k + v - x - y", node_levels[0].second)); + fail_unless(node_levels[1].first == 1); + fail_unless(formulas_equal("k + v - x", node_levels[1].second)); + fail_unless(node_levels[2].first == 2); + fail_unless(formulas_equal("k + v", node_levels[2].second)); + fail_unless(node_levels[3].first == 3); + fail_unless(formulas_equal("k", node_levels[3].second)); + fail_unless(node_levels[4].first == 3); + fail_unless(formulas_equal("v", node_levels[4].second)); + fail_unless(node_levels[5].first == 2); + fail_unless(formulas_equal("x", node_levels[5].second)); + fail_unless(node_levels[6].first == 1); + fail_unless(formulas_equal("y", node_levels[6].second)); + + delete node; + node_levels.clear(); +} +END_TEST + +START_TEST(test_level_4) +{ + ASTNode* node = SBML_parseL3Formula("w + (k - x) - y"); + ASTNodeLevels node_levels = node->getListOfNodesWithLevel(); + fail_unless(node_levels.size() == 7); + fail_unless(node_levels[0].first == 0); + fail_unless(formulas_equal("w + (k - x) - y", node_levels[0].second)); + fail_unless(node_levels[1].first == 1); + fail_unless(formulas_equal("w + (k - x)", node_levels[1].second)); + fail_unless(node_levels[2].first == 2); + fail_unless(formulas_equal("k - x", node_levels[2].second)); + fail_unless(node_levels[3].first == 2); + fail_unless(formulas_equal("w", node_levels[3].second)); + fail_unless(node_levels[4].first == 3); + fail_unless(formulas_equal("k", node_levels[4].second)); + fail_unless(node_levels[5].first == 3); + fail_unless(formulas_equal("x", node_levels[5].second)); + fail_unless(node_levels[6].first == 1); + fail_unless(formulas_equal("y", node_levels[6].second)); + + delete node; + node_levels.clear(); +} +END_TEST + +START_TEST(test_level_5) +{ + ASTNode* node = SBML_parseL3Formula("k - x"); + ASTNodeLevels node_levels = node->getListOfNodesWithLevel(); + fail_unless(node_levels.size() == 3); + fail_unless(node_levels[0].first == 0); + fail_unless(formulas_equal("k - x", node_levels[0].second)); + fail_unless(node_levels[1].first == 1); + fail_unless(formulas_equal("k", node_levels[1].second)); + fail_unless(node_levels[2].first == 1); + fail_unless(formulas_equal("x", node_levels[2].second)); + + delete node; + node_levels.clear(); +} +END_TEST + +START_TEST(test_level_6) +{ + ASTNode* node = SBML_parseL3Formula("k + v - x"); + ASTNodeLevels node_levels = node->getListOfNodesWithLevel(); + fail_unless(node_levels.size() == 5); + fail_unless(node_levels[0].first == 0); + fail_unless(formulas_equal("k + v - x", node_levels[0].second)); + fail_unless(node_levels[1].first == 1); + fail_unless(formulas_equal("k + v", node_levels[1].second)); + fail_unless(node_levels[2].first == 2); + fail_unless(formulas_equal("k", node_levels[2].second)); + fail_unless(node_levels[3].first == 2); + fail_unless(formulas_equal("v", node_levels[3].second)); + fail_unless(node_levels[4].first == 1); + fail_unless(formulas_equal("x", node_levels[4].second)); + + delete node; + node_levels.clear(); +} +END_TEST + +START_TEST(test_level_7) +{ + ASTNode* node = SBML_parseL3Formula("(k + v - x - y) + (l - m)"); + ASTNodeLevels node_levels = node->getListOfNodesWithLevel(); + fail_unless(node_levels.size() == 11); + fail_unless(node_levels[0].first == 0); + fail_unless(formulas_equal("(k + v - x - y) + (l - m)", node_levels[0].second)); + fail_unless(node_levels[1].first == 1); + fail_unless(formulas_equal("k + v - x - y", node_levels[1].second)); + fail_unless(node_levels[2].first == 2); + fail_unless(formulas_equal("k + v - x", node_levels[2].second)); + fail_unless(node_levels[3].first == 3); + fail_unless(formulas_equal("k + v", node_levels[3].second)); + fail_unless(node_levels[4].first == 1); + fail_unless(formulas_equal("l - m", node_levels[4].second)); + fail_unless(node_levels[5].first == 4); + fail_unless(formulas_equal("k", node_levels[5].second)); + fail_unless(node_levels[6].first == 4); + fail_unless(formulas_equal("v", node_levels[6].second)); + fail_unless(node_levels[7].first == 3); + fail_unless(formulas_equal("x", node_levels[7].second)); + fail_unless(node_levels[8].first == 2); + fail_unless(formulas_equal("y", node_levels[8].second)); + fail_unless(node_levels[9].first == 2); + fail_unless(formulas_equal("l", node_levels[9].second)); + fail_unless(node_levels[10].first == 2); + fail_unless(formulas_equal("m", node_levels[10].second)); + + delete node; + node_levels.clear(); +} +END_TEST + + Suite * create_suite_TestLevelNodeFunction() { Suite *suite = suite_create("TestLevelNodeFunction"); TCase *tcase = tcase_create("TestLevelNodeFunction"); - tcase_add_test(tcase, test_null); - tcase_add_test(tcase, test_level_1); - tcase_add_test(tcase, test_level_2); + //tcase_add_test(tcase, test_null); + //tcase_add_test(tcase, test_level_1); + //tcase_add_test(tcase, test_level_2); + //tcase_add_test(tcase, test_level_3); + //tcase_add_test(tcase, test_level_4); + //tcase_add_test(tcase, test_level_5); + //tcase_add_test(tcase, test_level_6); + tcase_add_test(tcase, test_level_7); suite_add_tcase(suite, tcase);