diff --git a/src/sbml/conversion/ExpressionAnalyser.cpp b/src/sbml/conversion/ExpressionAnalyser.cpp index 92ceade5c..e30b4a530 100644 --- a/src/sbml/conversion/ExpressionAnalyser.cpp +++ b/src/sbml/conversion/ExpressionAnalyser.cpp @@ -175,6 +175,8 @@ void ExpressionAnalyser::substituteParametersForExpressions() { if (mExpressions.empty()) return; + if (mHiddenSpecies == NULL) + mHiddenSpecies = new List(); // need to actually address the expressions in the correct order // replace k-x-y first with newParam type=TYPE_K_MINUS_X_MINUS_Y @@ -194,71 +196,147 @@ void ExpressionAnalyser::substituteParametersForExpressions() // and cannot rely on any other expression if (j == 0) { - std::string zName = getUniqueNewParameterName(); - exp->z_value = zName; - mNewVarCount++; - ASTNode* z = new ASTNode(AST_NAME); - z->setName(zName.c_str()); if (exp->type == TYPE_K_MINUS_X_MINUS_Y || exp->type == TYPE_K_MINUS_X) { // we have a value for k-x-y or k-x - exp->z_expression = z->deepCopy(); - delete z; + addSingleNewParameter(exp); } else if (exp->type == TYPE_K_PLUS_V_MINUS_X_MINUS_Y || exp->type == TYPE_K_PLUS_V_MINUS_X) { // we have a value for k+v-x-y and no value for k-x-y // we have a value for k+v-x and no value for k-x - ASTNode* replacement = new ASTNode(AST_PLUS); - ASTNode* v = exp->v_expression->deepCopy(); - replacement->addChild(z); - replacement->addChild(v); - exp->z_expression = replacement->deepCopy(); - delete replacement; + addNewParameterPlusVOrW(exp); } else if (exp->type == TYPE_K_MINUS_X_PLUS_W_MINUS_Y) { // we have a value for k-x+w-y and no value for k-x-y - ASTNode* replacement = new ASTNode(AST_PLUS); - ASTNode* w = exp->w_expression->deepCopy(); - replacement->addChild(z); - replacement->addChild(w); - exp->z_expression = replacement->deepCopy(); - delete replacement; + addNewParameterPlusVOrW(exp, "w"); } } - else + else // j > 0 so not the first expression { - std::string zName = getUniqueNewParameterName(); - exp->z_value = zName; - mNewVarCount++; - ASTNode* z = new ASTNode(AST_NAME); - z->setName(zName.c_str()); - if (exp->type == TYPE_K_MINUS_X_MINUS_Y || - exp->type == TYPE_K_MINUS_X) + if (exp->type == TYPE_K_MINUS_X_MINUS_Y) { - // we have a different value for k-x-y or k-x - exp->z_expression = z->deepCopy(); - delete z; + // we have a different value for k-x-y + // we know this because the expressions are in order and k-x-y is always first + // and the code that decides whether to add the expression well have checked that it is not identical + // so we if we have an expression of this type but is not first then it must be + // k-x-y but with a different value + addSingleNewParameter(exp); + } + else if (exp->type == TYPE_K_MINUS_X) + { + // k-x will always be replaced by a new variable + addSingleNewParameter(exp); + } + else if (exp->type == TYPE_K_PLUS_V_MINUS_X_MINUS_Y) + { + // we need to know what type of expression has come before + // deal with the case where the previous expression was the same type + if (mExpressions[j - 1]->type == TYPE_K_PLUS_V_MINUS_X_MINUS_Y) + { + // here we are dealing with the fact that we have k+v-x-y and k+v-x-a + // so we have two different expressions of the same type + // need to create a new parameter + addNewParameterPlusVOrW(exp); + } + else if (mExpressions[j - 1]->type == TYPE_K_MINUS_X_MINUS_Y) + { + // here we are dealing with the fact that we have k+v-x-y and k-x-y + // need to check whether they have the same values for k,x,y + if (matchesK(mExpressions[j - 1], exp) && + matchesXValue(mExpressions[j - 1], exp) && + matchesYValue(mExpressions[j - 1], exp)) + { + // the values are the same so we can use the same new parameter + exp->z_value = mExpressions[j - 1]->z_value; + ASTNode* z = new ASTNode(AST_NAME); + z->setName(mExpressions[j - 1]->z_value.c_str()); + ASTNode* replacement = new ASTNode(AST_PLUS); + ASTNode* v = exp->v_expression->deepCopy(); + replacement->addChild(z); + replacement->addChild(v); + exp->z_expression = replacement->deepCopy(); + delete replacement; + } + else + { + addNewParameterPlusVOrW(exp); + } + } + } + else if (exp->type == TYPE_K_MINUS_X_PLUS_W_MINUS_Y) + { + // we need to know what type of expression has come before + // deal with the case where the previous expression was the same type + if (mExpressions[j - 1]->type == TYPE_K_MINUS_X_PLUS_W_MINUS_Y) + { + // here we are dealing with the fact that we have k-x+w-y and k-x+w-a + // so we have two different expressions of the same time + // need to create a new parameter + addNewParameterPlusVOrW(exp, "w"); + } + else if (mExpressions[j - 1]->type == TYPE_K_MINUS_X_MINUS_Y) + { + // here we are dealing with the fact that we have k-x+w-y and k-x-y + // need to check whether they have the same values for k,x,y + if (matchesK(mExpressions[j - 1], exp) && + matchesXValue(mExpressions[j - 1], exp) && + matchesYValue(mExpressions[j - 1], exp)) + { + // the values are the same so we can use the same new parameter + exp->z_value = mExpressions[j - 1]->z_value; + ASTNode* z = new ASTNode(AST_NAME); + z->setName(mExpressions[j - 1]->z_value.c_str()); + ASTNode* replacement = new ASTNode(AST_PLUS); + ASTNode* w = exp->w_expression->deepCopy(); + replacement->addChild(z); + replacement->addChild(w); + exp->z_expression = replacement->deepCopy(); + delete replacement; + } + else + { + addNewParameterPlusVOrW(exp, "w"); + } + } + } + else if (exp->type == TYPE_K_PLUS_V_MINUS_X) + { + if (mExpressions[j - 1]->type == TYPE_K_MINUS_X) + { + // here we are dealing with the fact that we have k+v-x and k-x + // need to check whether they have the same values for k,x,y + if (matchesK(mExpressions[j - 1], exp) && + matchesXValue(mExpressions[j - 1], exp)) + { + // the values are the same so we can use the same new parameter + exp->z_value = mExpressions[j - 1]->z_value; + ASTNode* z = new ASTNode(AST_NAME); + z->setName(mExpressions[j - 1]->z_value.c_str()); + ASTNode* replacement = new ASTNode(AST_PLUS); + ASTNode* v = exp->v_expression->deepCopy(); + replacement->addChild(z); + replacement->addChild(v); + exp->z_expression = replacement->deepCopy(); + delete replacement; + } + else + { + // if the type before was not k-x then we need to create a new parameter + addNewParameterPlusVOrW(exp, "v"); + } + } + else + { + // if the type before was not k-x then we need to create a new parameter + // because it doesn't matter what it was. + addNewParameterPlusVOrW(exp, "v"); + } } - } - //else if (j > 0 && - // exp->type == TYPE_K_PLUS_V_MINUS_X_MINUS_Y && - // exp->z_expression == NULL) - //{ - // // we have a value for k-x-y - // ASTNode* replacement = new ASTNode(AST_PLUS); - // ASTNode* z = new ASTNode(AST_NAME); - // z->setName(mExpressions[j - 1]->z_value.c_str()); - // ASTNode* v = exp->v_expression->deepCopy(); - // replacement->addChild(z); - // replacement->addChild(v); - // exp->z_expression = replacement->deepCopy(); - - //} } } @@ -307,6 +385,43 @@ SubstitutionValues_t* ExpressionAnalyser::getSubstitutionValuesByType(Expression return NULL; } +void ExpressionAnalyser::addSingleNewParameter(SubstitutionValues_t* exp) +{ + std::string zName = getUniqueNewParameterName(); + exp->z_value = zName; + mNewVarCount++; + ASTNode* z = new ASTNode(AST_NAME); + z->setName(zName.c_str()); + exp->z_expression = z->deepCopy(); + mHiddenSpecies->add(z); + delete z; + +} + +void ExpressionAnalyser::addNewParameterPlusVOrW(SubstitutionValues_t* exp, std::string vOrW) +{ + ASTNode* var = NULL; + if (vOrW == "v") + { + var = exp->v_expression->deepCopy(); + } + else + { + var = exp->w_expression->deepCopy(); + } + std::string zName = getUniqueNewParameterName(); + exp->z_value = zName; + mNewVarCount++; + ASTNode* z = new ASTNode(AST_NAME); + z->setName(zName.c_str()); + ASTNode* replacement = new ASTNode(AST_PLUS); + replacement->addChild(z); + replacement->addChild(var); + exp->z_expression = replacement->deepCopy(); + mHiddenSpecies->add(z); + delete replacement; +} + /* * Check whether two SubstitutionValues_t are identical. */ @@ -525,38 +640,38 @@ bool ExpressionAnalyser::matchesType(SubstitutionValues_t* values1, Substitution void ExpressionAnalyser::printSubstitutionValues(const SubstitutionValues_t* values) { - cout << "k_value: " << values->k_value << endl; - cout << "k_real_value: " << values->k_real_value << endl; - cout << "x_value: " << values->x_value << endl; - cout << "y_value: " << values->y_value << endl; - cout << "z_value: " << values->z_value << endl; - if (values->dxdt_expression != NULL) - cout << "dxdt_expression: " << SBML_formulaToL3String(values->dxdt_expression) << " " << values->dxdt_expression << endl; - else - cout << "dxdt_expression: NULL" << endl; - if (values->dydt_expression != NULL) - cout << "dydt_expression: " << SBML_formulaToL3String(values->dydt_expression) << " " << values->dydt_expression << endl; - else - cout << "dydt_expression: NULL" << endl; - if (values->v_expression != NULL) - cout << "v_expression: " << SBML_formulaToL3String(values->v_expression) << " " << values->v_expression << endl; - else - cout << "v_expression: NULL" << endl; - if (values->w_expression != NULL) - cout << "w_expression: " << SBML_formulaToL3String(values->w_expression) << " " << values->w_expression << endl; - else - cout << "w_expression: NULL" << endl; - if (values->z_expression != NULL) - cout << "z_expression: " << SBML_formulaToL3String(values->z_expression) << " " << values->z_expression << endl; - else - cout << "z_expression: NULL" << endl; - cout << "type: " << values->type << endl; - if (values->current != NULL) - cout << "current: " << SBML_formulaToL3String(values->current) << " " << values->current << endl; - else - cout << "current: NULL" << endl; - cout << "odeIndex: " << values->odeIndex << endl; - cout << "levelInExpression: " << values->levelInExpression << endl; +// cout << "k_value: " << values->k_value << endl; +// cout << "k_real_value: " << values->k_real_value << endl; +// cout << "x_value: " << values->x_value << endl; +// cout << "y_value: " << values->y_value << endl; +// cout << "z_value: " << values->z_value << endl; +// if (values->dxdt_expression != NULL) +// cout << "dxdt_expression: " << SBML_formulaToL3String(values->dxdt_expression) << " " << values->dxdt_expression << endl; +// else +// cout << "dxdt_expression: NULL" << endl; +// if (values->dydt_expression != NULL) +// cout << "dydt_expression: " << SBML_formulaToL3String(values->dydt_expression) << " " << values->dydt_expression << endl; +// else +// cout << "dydt_expression: NULL" << endl; +// if (values->v_expression != NULL) +// cout << "v_expression: " << SBML_formulaToL3String(values->v_expression) << " " << values->v_expression << endl; +// else +// cout << "v_expression: NULL" << endl; +// if (values->w_expression != NULL) +// cout << "w_expression: " << SBML_formulaToL3String(values->w_expression) << " " << values->w_expression << endl; +// else +// cout << "w_expression: NULL" << endl; +// if (values->z_expression != NULL) +// cout << "z_expression: " << SBML_formulaToL3String(values->z_expression) << " " << values->z_expression << endl; +// else +// cout << "z_expression: NULL" << endl; +// cout << "type: " << values->type << endl; +// if (values->current != NULL) +// cout << "current: " << SBML_formulaToL3String(values->current) << " " << values->current << endl; +// else +// cout << "current: NULL" << endl; +// cout << "odeIndex: " << values->odeIndex << endl; +// cout << "levelInExpression: " << values->levelInExpression << endl; } List* ExpressionAnalyser::getHiddenSpecies() @@ -564,6 +679,11 @@ List* ExpressionAnalyser::getHiddenSpecies() return mHiddenSpecies; } +unsigned int ExpressionAnalyser::getNumHiddenSpecies() +{ + return mHiddenSpecies->getSize(); +} + SubstitutionValues_t* ExpressionAnalyser::createBlankSubstitutionValues() { SubstitutionValues_t* values = new SubstitutionValues_t; diff --git a/src/sbml/conversion/ExpressionAnalyser.h b/src/sbml/conversion/ExpressionAnalyser.h index fe5c5055e..f52101d3f 100644 --- a/src/sbml/conversion/ExpressionAnalyser.h +++ b/src/sbml/conversion/ExpressionAnalyser.h @@ -157,6 +157,8 @@ class LIBSBML_EXTERN ExpressionAnalyser int setModel(Model* m); List* getHiddenSpecies(); + + unsigned int getNumHiddenSpecies(); SubstitutionValues_t* createBlankSubstitutionValues(); unsigned int getNumExpressions(); SubstitutionValues_t* getExpression(unsigned int index); @@ -208,9 +210,9 @@ class LIBSBML_EXTERN ExpressionAnalyser // functions that represents steps of algo 3.1 + void addSingleNewParameter(SubstitutionValues_t* exp); - - + void addNewParameterPlusVOrW(SubstitutionValues_t* exp, std::string var = "v"); /* * Return the ODE for the given variable * or an ASTNode representing zero if there is no time derivative diff --git a/src/sbml/conversion/test/TestExpressionAnalyser.cpp b/src/sbml/conversion/test/TestExpressionAnalyser.cpp index 45f7b236e..c59e3c61d 100644 --- a/src/sbml/conversion/test/TestExpressionAnalyser.cpp +++ b/src/sbml/conversion/test/TestExpressionAnalyser.cpp @@ -81,7 +81,7 @@ extern char *TestDataDirectory; static Parameter* setupZeroParameter(Model* model, const char* name, bool is_constant) { Parameter* parameter = model->createParameter(); - parameter->setId(name); + parameter->setId(name); parameter->setConstant(is_constant); parameter->setValue(0); return parameter; @@ -695,6 +695,7 @@ START_TEST(test_analyse_replace) fail_unless(value->odeIndex == 0); fail_unless(util_isNaN(value->k_real_value)); + fail_unless(analyser->getNumHiddenSpecies() == 1); delete analyser; } END_TEST @@ -732,6 +733,7 @@ START_TEST(test_analyse_same_expression_replace) fail_unless(formulas_equal("newVar1", value->z_expression)); fail_unless(value->odeIndex == 0); fail_unless(util_isNaN(value->k_real_value)); + fail_unless(analyser->getNumHiddenSpecies() == 1); delete analyser; } @@ -786,6 +788,7 @@ START_TEST(test_analyse_different_expression_replace) fail_unless(formulas_equal("newVar2", value1->z_expression)); fail_unless(value1->odeIndex == 1); fail_unless(util_isNaN(value1->k_real_value)); + fail_unless(analyser->getNumHiddenSpecies() == 2); delete analyser; } @@ -818,6 +821,7 @@ START_TEST(test_analyse_1_replace) fail_unless(formulas_equal("newVar1 + v", value->z_expression)); fail_unless(value->odeIndex == 0); fail_unless(util_isNaN(value->k_real_value)); + fail_unless(analyser->getNumHiddenSpecies() == 1); delete analyser; } @@ -850,6 +854,7 @@ START_TEST(test_analyse_2_replace) fail_unless(formulas_equal("newVar1 + w", value->z_expression)); fail_unless(value->odeIndex == 0); fail_unless(util_isNaN(value->k_real_value)); + fail_unless(analyser->getNumHiddenSpecies() == 1); delete analyser; } @@ -882,6 +887,7 @@ START_TEST(test_analyse_3_replace) fail_unless(formulas_equal("newVar1", value->z_expression)); fail_unless(value->odeIndex == 0); fail_unless(util_isNaN(value->k_real_value)); + fail_unless(analyser->getNumHiddenSpecies() == 1); delete analyser; } @@ -914,11 +920,440 @@ START_TEST(test_analyse_4_replace) fail_unless(formulas_equal("newVar1 + v", value->z_expression)); fail_unless(value->odeIndex == 0); fail_unless(util_isNaN(value->k_real_value)); + fail_unless(analyser->getNumHiddenSpecies() == 1); delete analyser; } END_TEST +START_TEST(test_analyse_1_different_replace) +{ + RateRule* rr = d->getModel()->createRateRule(); + rr->setVariable("a"); + rr->setMath(SBML_parseFormula("k + v - x - y")); + RateRule* rr1 = d->getModel()->createRateRule(); + rr1->setVariable("b"); + rr1->setMath(SBML_parseFormula("k + v - x - a")); + converter->populateInitialODEinfo(); + ExpressionAnalyser* analyser = new ExpressionAnalyser(m, converter->getOdePairs()); + + fail_unless(analyser->getNumExpressions() == 0); + + analyser->detectHiddenSpecies(); + + fail_unless(analyser->getNumExpressions() == 2); + SubstitutionValues_t* value = analyser->getExpression(0); + fail_unless(value->k_value == "k"); + fail_unless(value->x_value == "x"); + fail_unless(value->y_value == "y"); + fail_unless(value->z_value == "newVar1"); + fail_unless(value->type == TYPE_K_PLUS_V_MINUS_X_MINUS_Y); + fail_unless(formulas_equal("k + v - x - y", value->current)); + fail_unless(formulas_equal("0", value->dxdt_expression)); + fail_unless(formulas_equal("0", value->dydt_expression)); + fail_unless(formulas_equal("v", value->v_expression)); + fail_unless(value->w_expression == NULL); + fail_unless(formulas_equal("newVar1 + v", value->z_expression)); + fail_unless(value->odeIndex == 0); + fail_unless(util_isNaN(value->k_real_value)); + + SubstitutionValues_t* value1 = analyser->getExpression(1); + fail_unless(value1->k_value == "k"); + fail_unless(value1->x_value == "x"); + fail_unless(value1->y_value == "a"); + fail_unless(value1->z_value == "newVar2"); + fail_unless(value1->type == TYPE_K_PLUS_V_MINUS_X_MINUS_Y); + fail_unless(formulas_equal("k + v - x - a", value1->current)); + fail_unless(formulas_equal("0", value1->dxdt_expression)); + fail_unless(formulas_equal("k + v - x - y", value1->dydt_expression)); + fail_unless(formulas_equal("v", value1->v_expression)); + fail_unless(value1->w_expression == NULL); + fail_unless(formulas_equal("newVar2 + v", value1->z_expression)); + fail_unless(value1->odeIndex == 1); + fail_unless(util_isNaN(value1->k_real_value)); + fail_unless(analyser->getNumHiddenSpecies() == 2); + + delete analyser; +} +END_TEST + +START_TEST(test_analyse_1_different_replace_1) +{ + RateRule* rr = d->getModel()->createRateRule(); + rr->setVariable("a"); + rr->setMath(SBML_parseFormula("k - x - y")); + RateRule* rr1 = d->getModel()->createRateRule(); + rr1->setVariable("b"); + rr1->setMath(SBML_parseFormula("k + v - x - y")); + converter->populateInitialODEinfo(); + ExpressionAnalyser* analyser = new ExpressionAnalyser(m, converter->getOdePairs()); + + fail_unless(analyser->getNumExpressions() == 0); + + analyser->detectHiddenSpecies(); + + fail_unless(analyser->getNumExpressions() == 2); + SubstitutionValues_t* value = analyser->getExpression(0); + fail_unless(value->k_value == "k"); + fail_unless(value->x_value == "x"); + fail_unless(value->y_value == "y"); + fail_unless(value->z_value == "newVar1"); + fail_unless(value->type == TYPE_K_MINUS_X_MINUS_Y); + fail_unless(formulas_equal("k - 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(formulas_equal("newVar1", value->z_expression)); + fail_unless(value->odeIndex == 0); + fail_unless(util_isNaN(value->k_real_value)); + + SubstitutionValues_t* value1 = analyser->getExpression(1); + fail_unless(value1->k_value == "k"); + fail_unless(value1->x_value == "x"); + fail_unless(value1->y_value == "y"); + fail_unless(value1->z_value == "newVar1"); + fail_unless(value1->type == TYPE_K_PLUS_V_MINUS_X_MINUS_Y); + fail_unless(formulas_equal("k + v - x - y", value1->current)); + fail_unless(formulas_equal("0", value1->dxdt_expression)); + fail_unless(formulas_equal("0", value1->dydt_expression)); + fail_unless(formulas_equal("v", value1->v_expression)); + fail_unless(value1->w_expression == NULL); + fail_unless(formulas_equal("newVar1 + v", value1->z_expression)); + fail_unless(value1->odeIndex == 1); + fail_unless(util_isNaN(value1->k_real_value)); + fail_unless(analyser->getNumHiddenSpecies() == 1); + + delete analyser; +} +END_TEST + +START_TEST(test_analyse_1_different_replace_2) +{ + RateRule* rr = d->getModel()->createRateRule(); + rr->setVariable("a"); + rr->setMath(SBML_parseFormula("k - x - y")); + RateRule* rr1 = d->getModel()->createRateRule(); + rr1->setVariable("b"); + rr1->setMath(SBML_parseFormula("k + v - x - a")); + converter->populateInitialODEinfo(); + ExpressionAnalyser* analyser = new ExpressionAnalyser(m, converter->getOdePairs()); + + fail_unless(analyser->getNumExpressions() == 0); + + analyser->detectHiddenSpecies(); + + fail_unless(analyser->getNumExpressions() == 2); + SubstitutionValues_t* value = analyser->getExpression(0); + fail_unless(value->k_value == "k"); + fail_unless(value->x_value == "x"); + fail_unless(value->y_value == "y"); + fail_unless(value->z_value == "newVar1"); + fail_unless(value->type == TYPE_K_MINUS_X_MINUS_Y); + fail_unless(formulas_equal("k - 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(formulas_equal("newVar1", value->z_expression)); + fail_unless(value->odeIndex == 0); + fail_unless(util_isNaN(value->k_real_value)); + + SubstitutionValues_t* value1 = analyser->getExpression(1); + fail_unless(value1->k_value == "k"); + fail_unless(value1->x_value == "x"); + fail_unless(value1->y_value == "a"); + fail_unless(value1->z_value == "newVar2"); + fail_unless(value1->type == TYPE_K_PLUS_V_MINUS_X_MINUS_Y); + fail_unless(formulas_equal("v", value1->v_expression)); + fail_unless(formulas_equal("newVar2 + v", value1->z_expression)); + fail_unless(value1->odeIndex == 1); + fail_unless(util_isNaN(value1->k_real_value)); + fail_unless(analyser->getNumHiddenSpecies() == 2); + + delete analyser; +} +END_TEST + +START_TEST(test_analyse_1_different_replace_3) +{ + RateRule* rr = d->getModel()->createRateRule(); + rr->setVariable("a"); + rr->setMath(SBML_parseFormula("k - x - y")); + RateRule* rr1 = d->getModel()->createRateRule(); + rr1->setVariable("b"); + rr1->setMath(SBML_parseFormula("k - x + w - y")); + converter->populateInitialODEinfo(); + ExpressionAnalyser* analyser = new ExpressionAnalyser(m, converter->getOdePairs()); + + fail_unless(analyser->getNumExpressions() == 0); + + analyser->detectHiddenSpecies(); + + fail_unless(analyser->getNumExpressions() == 2); + SubstitutionValues_t* value = analyser->getExpression(0); + fail_unless(value->k_value == "k"); + fail_unless(value->x_value == "x"); + fail_unless(value->y_value == "y"); + fail_unless(value->z_value == "newVar1"); + fail_unless(value->type == TYPE_K_MINUS_X_MINUS_Y); + fail_unless(formulas_equal("k - 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(formulas_equal("newVar1", value->z_expression)); + fail_unless(value->odeIndex == 0); + fail_unless(util_isNaN(value->k_real_value)); + + SubstitutionValues_t* value1 = analyser->getExpression(1); + fail_unless(value1->k_value == "k"); + fail_unless(value1->x_value == "x"); + fail_unless(value1->y_value == "y"); + fail_unless(value1->z_value == "newVar1"); + fail_unless(value1->type == TYPE_K_MINUS_X_PLUS_W_MINUS_Y); + fail_unless(formulas_equal("w + (k - x) - y", value1->current)); + fail_unless(formulas_equal("0", value1->dxdt_expression)); + fail_unless(formulas_equal("0", value1->dydt_expression)); + fail_unless(formulas_equal("w", value1->w_expression)); + fail_unless(formulas_equal("newVar1 + w", value1->z_expression)); + fail_unless(value1->odeIndex == 1); + fail_unless(util_isNaN(value1->k_real_value)); + fail_unless(analyser->getNumHiddenSpecies() == 1); + + delete analyser; +} +END_TEST + + +START_TEST(test_analyse_1_two_terms_replace) +{ + RateRule* rr = d->getModel()->createRateRule(); + rr->setVariable("a"); + rr->setMath(SBML_parseFormula("(k + v - x - y) + (k - x)")); + + converter->populateInitialODEinfo(); + ExpressionAnalyser* analyser = new ExpressionAnalyser(m, converter->getOdePairs()); + + fail_unless(analyser->getNumExpressions() == 0); + + analyser->detectHiddenSpecies(); + + fail_unless(analyser->getNumExpressions() == 2); + SubstitutionValues_t* value = analyser->getExpression(0); + fail_unless(value->k_value == "k"); + fail_unless(value->x_value == "x"); + fail_unless(value->y_value == "y"); + fail_unless(value->z_value == "newVar1"); + fail_unless(value->type == TYPE_K_PLUS_V_MINUS_X_MINUS_Y); + fail_unless(formulas_equal("k + v - x - y", value->current)); + fail_unless(formulas_equal("0", value->dxdt_expression)); + fail_unless(formulas_equal("0", value->dydt_expression)); + fail_unless(formulas_equal("v", value->v_expression)); + fail_unless(value->w_expression == NULL); + fail_unless(formulas_equal("newVar1 + v", value->z_expression)); + fail_unless(value->odeIndex == 0); + fail_unless(util_isNaN(value->k_real_value)); + + SubstitutionValues_t* value1 = analyser->getExpression(1); + fail_unless(value1->k_value == "k"); + fail_unless(value1->x_value == "x"); + fail_unless(value1->y_value.empty()); + fail_unless(value1->z_value == "newVar2"); + fail_unless(value1->type == TYPE_K_MINUS_X); + fail_unless(formulas_equal("k - x", value1->current)); + fail_unless(formulas_equal("0", value1->dxdt_expression)); + fail_unless(value1->dydt_expression == NULL); + fail_unless(value1->v_expression == NULL); + fail_unless(value1->w_expression == NULL); + fail_unless(formulas_equal("newVar2", value1->z_expression)); + fail_unless(value1->odeIndex == 0); + fail_unless(util_isNaN(value1->k_real_value)); + + fail_unless(analyser->getNumHiddenSpecies() == 2); + + delete analyser; +} +END_TEST + +START_TEST(test_analyse_3_replace_1) +{ + RateRule* rr = d->getModel()->createRateRule(); + rr->setVariable("a"); + rr->setMath(SBML_parseFormula("k - x")); + RateRule* rra = d->getModel()->createRateRule(); + rra->setVariable("b"); + rra->setMath(SBML_parseFormula("k - y")); + converter->populateInitialODEinfo(); + ExpressionAnalyser* analyser = new ExpressionAnalyser(m, converter->getOdePairs()); + + fail_unless(analyser->getNumExpressions() == 0); + + analyser->detectHiddenSpecies(); + + fail_unless(analyser->getNumExpressions() == 2); + SubstitutionValues_t* value = analyser->getExpression(0); + fail_unless(value->k_value == "k"); + fail_unless(value->x_value == "x"); + fail_unless(value->y_value.empty()); + fail_unless(value->z_value == "newVar1"); + fail_unless(value->type == TYPE_K_MINUS_X); + fail_unless(formulas_equal("k - x", value->current)); + fail_unless(formulas_equal("newVar1", value->z_expression)); + fail_unless(value->odeIndex == 0); + fail_unless(util_isNaN(value->k_real_value)); + + SubstitutionValues_t* value1 = analyser->getExpression(1); + fail_unless(value1->k_value == "k"); + fail_unless(value1->y_value.empty()); + fail_unless(value1->x_value == "y"); + fail_unless(value1->z_value == "newVar2"); + fail_unless(value1->type == TYPE_K_MINUS_X); + fail_unless(formulas_equal("k - y", value1->current)); + fail_unless(formulas_equal("newVar2", value1->z_expression)); + fail_unless(value1->odeIndex == 1); + fail_unless(util_isNaN(value1->k_real_value)); + + fail_unless(analyser->getNumHiddenSpecies() == 2); + + delete analyser; +} +END_TEST + +START_TEST(test_analyse_4_replace_1) +{ + RateRule* rr = d->getModel()->createRateRule(); + rr->setVariable("a"); + rr->setMath(SBML_parseFormula("k + v - x")); + RateRule* rrb = d->getModel()->createRateRule(); + rrb->setVariable("b"); + rrb->setMath(SBML_parseFormula("k - x")); + converter->populateInitialODEinfo(); + ExpressionAnalyser* analyser = new ExpressionAnalyser(m, converter->getOdePairs()); + + fail_unless(analyser->getNumExpressions() == 0); + + analyser->detectHiddenSpecies(); + + fail_unless(analyser->getNumExpressions() == 2); + SubstitutionValues_t* value = analyser->getExpression(0); + fail_unless(value->k_value == "k"); + fail_unless(value->x_value == "x"); + fail_unless(value->y_value.empty()); + fail_unless(value->z_value == "newVar1"); + fail_unless(value->type == TYPE_K_MINUS_X); + fail_unless(formulas_equal("k - x", value->current)); + fail_unless(formulas_equal("newVar1", value->z_expression)); + fail_unless(value->odeIndex == 1); + fail_unless(util_isNaN(value->k_real_value)); + + SubstitutionValues_t* value1 = analyser->getExpression(1); + fail_unless(value1->k_value == "k"); + fail_unless(value1->x_value == "x"); + fail_unless(value1->y_value.empty()); + fail_unless(value1->z_value == "newVar1"); + fail_unless(value1->type == TYPE_K_PLUS_V_MINUS_X); + fail_unless(formulas_equal("k + v - x", value1->current)); + fail_unless(formulas_equal("newVar1 + v", value1->z_expression)); + fail_unless(value1->odeIndex == 0); + fail_unless(util_isNaN(value1->k_real_value)); + + fail_unless(analyser->getNumHiddenSpecies() == 1); + + delete analyser; +} +END_TEST + + +START_TEST(test_analyse_4_replace_2) +{ + RateRule* rr = d->getModel()->createRateRule(); + rr->setVariable("a"); + rr->setMath(SBML_parseFormula("k + v - y")); + RateRule* rrb = d->getModel()->createRateRule(); + rrb->setVariable("b"); + rrb->setMath(SBML_parseFormula("k - x")); + converter->populateInitialODEinfo(); + ExpressionAnalyser* analyser = new ExpressionAnalyser(m, converter->getOdePairs()); + + fail_unless(analyser->getNumExpressions() == 0); + + analyser->detectHiddenSpecies(); + + fail_unless(analyser->getNumExpressions() == 2); + SubstitutionValues_t* value = analyser->getExpression(0); + fail_unless(value->k_value == "k"); + fail_unless(value->x_value == "x"); + fail_unless(value->y_value.empty()); + fail_unless(value->z_value == "newVar1"); + fail_unless(value->type == TYPE_K_MINUS_X); + fail_unless(formulas_equal("k - x", value->current)); + fail_unless(formulas_equal("newVar1", value->z_expression)); + fail_unless(value->odeIndex == 1); + fail_unless(util_isNaN(value->k_real_value)); + + SubstitutionValues_t* value1 = analyser->getExpression(1); + fail_unless(value1->k_value == "k"); + fail_unless(value1->x_value == "y"); + fail_unless(value1->y_value.empty()); + fail_unless(value1->z_value == "newVar2"); + fail_unless(value1->type == TYPE_K_PLUS_V_MINUS_X); + fail_unless(formulas_equal("k + v - y", value1->current)); + fail_unless(formulas_equal("newVar2 + v", value1->z_expression)); + fail_unless(value1->odeIndex == 0); + fail_unless(util_isNaN(value1->k_real_value)); + + fail_unless(analyser->getNumHiddenSpecies() == 2); + + delete analyser; +} +END_TEST + +START_TEST(test_analyse_4_replace_3) +{ + RateRule* rr = d->getModel()->createRateRule(); + rr->setVariable("a"); + rr->setMath(SBML_parseFormula("k + v - x")); + RateRule* rrb = d->getModel()->createRateRule(); + rrb->setVariable("b"); + rrb->setMath(SBML_parseFormula("k + v - y")); + converter->populateInitialODEinfo(); + ExpressionAnalyser* analyser = new ExpressionAnalyser(m, converter->getOdePairs()); + + fail_unless(analyser->getNumExpressions() == 0); + + analyser->detectHiddenSpecies(); + + fail_unless(analyser->getNumExpressions() == 2); + SubstitutionValues_t* value = analyser->getExpression(0); + fail_unless(value->k_value == "k"); + fail_unless(value->x_value == "x"); + fail_unless(value->y_value.empty()); + fail_unless(value->z_value == "newVar1"); + fail_unless(value->type == TYPE_K_PLUS_V_MINUS_X); + fail_unless(formulas_equal("k + v - x", value->current)); + fail_unless(formulas_equal("newVar1 + v", value->z_expression)); + fail_unless(value->odeIndex == 0); + fail_unless(util_isNaN(value->k_real_value)); + + SubstitutionValues_t* value1 = analyser->getExpression(1); + fail_unless(value1->k_value == "k"); + fail_unless(value1->x_value == "y"); + fail_unless(value1->y_value.empty()); + fail_unless(value1->z_value == "newVar2"); + fail_unless(value1->type == TYPE_K_PLUS_V_MINUS_X); + fail_unless(formulas_equal("k + v - y", value1->current)); + fail_unless(formulas_equal("newVar2 + v", value1->z_expression)); + fail_unless(value1->odeIndex == 1); + fail_unless(util_isNaN(value1->k_real_value)); + + fail_unless(analyser->getNumHiddenSpecies() == 2); + + delete analyser; +} +END_TEST + + Suite * create_suite_TestExpressionAnalyser (void) { @@ -930,7 +1365,7 @@ create_suite_TestExpressionAnalyser (void) if (testing) { - tcase_add_test(tcase, test_analyse_4_replace); //k-x-y + tcase_add_test(tcase, test_analyse_4_replace_2); //k+v-y & k-x } else { @@ -956,6 +1391,15 @@ create_suite_TestExpressionAnalyser (void) tcase_add_test(tcase, test_analyse_2_replace); //k-x+w-y tcase_add_test(tcase, test_analyse_3_replace); //k-x tcase_add_test(tcase, test_analyse_4_replace); //k+v-x + tcase_add_test(tcase, test_analyse_1_different_replace); //k+v-x-y + tcase_add_test(tcase, test_analyse_1_different_replace_1); //k-x-y & k+v-x-y + tcase_add_test(tcase, test_analyse_1_different_replace_2); //k-x-y & k+v-x-a + tcase_add_test(tcase, test_analyse_1_different_replace_3); //k-x-y & k-x+w-y + tcase_add_test(tcase, test_analyse_1_two_terms_replace); //(k+v-x-y)+(k-x) + tcase_add_test(tcase, test_analyse_3_replace_1); //k-x & k-y + tcase_add_test(tcase, test_analyse_4_replace_1); //k+v-x & k-x + tcase_add_test(tcase, test_analyse_4_replace_2); //k+v-y & k-x + tcase_add_test(tcase, test_analyse_4_replace_3); //k+v-x & k+v-y } suite_add_tcase(suite, tcase); @@ -964,4 +1408,4 @@ create_suite_TestExpressionAnalyser (void) } END_C_DECLS - \ No newline at end of file + \ No newline at end of file