diff --git a/AUTHORS b/AUTHORS index 656141340..8af1f04da 100644 --- a/AUTHORS +++ b/AUTHORS @@ -4,7 +4,8 @@ Ghilman Brock Eliot Dixon Dalton Nickerson Sean Matthew -George Hall +Matthew Geiger +Kassidy Hall W.R. Jackson Samuel Hodges Emma Weisgerber @@ -16,3 +17,7 @@ Bryan Rumsey Mason Kidwell Jesse Reeve Fin Carter +Ethan Green +Josh Cooper +Matthew Dippel +Joshua Fisher-Caudill diff --git a/README.md b/README.md index abe4cd2d5..a8ce93853 100644 --- a/README.md +++ b/README.md @@ -176,6 +176,7 @@ Authors and history * [**Eliot Dixon**](https://github.com/edixon1) * [**Dalton Nickerson**](https://github.com/Thisisnotdalton) * [**Sean Matthew**](https://github.com/seanebum) +* [**Matthew Geiger**](https://github.com/popensesame) * [**Kassidy Hall** ](https://github.com/technodivergent) * [**W.R. Jackson** ](https://github.com/JustJackson) * [**Samuel Hodges**](https://github.com/hodgespodge) @@ -188,6 +189,11 @@ Authors and history * [**Mason Kidwell**](https://github.com/makdl) * [**Jesse Reeve**](https://github.com/jdreeve) * [**Fin Carter**](https://github.com/Fin109) +* [**Ethan Green**](https://github.com/ethangreen-dev) +* [**Josh Cooper**](https://github.com/jtcooper10) +* [**Matthew Dippel**](https://github.com/mdip226) +* [**Joshua Fisher-Caudill**](https://github.com/joshuafisherc) + Acknowledgments --------------- diff --git a/examples/Advanced_Features/Bimolecular_reactions.ipynb b/examples/Advanced_Features/Bimolecular_reactions.ipynb new file mode 100644 index 000000000..99c8c473c --- /dev/null +++ b/examples/Advanced_Features/Bimolecular_reactions.ipynb @@ -0,0 +1,248 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Quote from: \"Stochastic Simulation of Chemical Kinetics\" Daniel T. Gillespie (2007)\n", + "\n", + "\n", + "If $R_j$ is a bimolecular reaction of the form $S_1 + S_2 \\rightarrow$ product(s), kinetic theory\n", + "arguments and the well-stirred condition together imply the existence of a constant $c_j$,\n", + "such that $c_j dt$ gives the probability that a randomly chosen pair of S1 and S2 molecules\n", + "will react according to $R_j$ in the next infinitesimal time $dt$ (8–11). The probability\n", + "that some one of the $x_1x_2$ $S_1-S_2$ pairs inside will react according to $R_j$ in the next\n", + "$dt$ is therefore $x_1x_2 \\,c_j dt$, and that implies that the propensity function in Equation 2\n", + "is $a_j(x) = c_jx_1x_2$. If instead the bimolecular reaction had been $S_1 + S_1 \\rightarrow$ product(s),\n", + "we would have reckoned the number of distinct $S_1$ molecular pairs as $\\frac{1}{2} x_1(x_1 −1)$, and so obtained for the propensity function $a_j(x) = cj \\frac{1}{2}x_1(x_1 − 1)$.\n", + "\n", + "...\n", + "\n", + "unimolecular $c_j$ is independent of the system volume $\\Omega$, a bimolecular $c_j$ is inversely\n", + "proportional to $\\Omega$, reflecting the fact that two reactant molecules will have a harder\n", + "time finding each other inside a larger volume. It turns out that for a unimolecular\n", + "reaction, $c_j$ is numerically equal to the reaction-rate constant $k_j$ of conventional deterministic chemical kinetics, whereas for a bimolecular reaction, $c_j$ is equal to $k_j/\\Omega$ if the\n", + "reactants are different species, or $2k_j/\\Omega$ if they are the same species (8–11)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "-----------------------------------------------------------" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Using the above formulation for $A + B \\rightleftharpoons 2 A$, we get:\n", + "\n", + "$a_{forward} = \\dfrac{k_j}{\\Omega}\\,A\\,B $\n", + "\n", + "\n", + "$a_{reverse} = \\dfrac{2\\,k_j}{\\Omega}\\dfrac{1}{2}\\,A\\,(A-1) $" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "sys.path.insert(1, os.path.abspath(os.path.join(os.getcwd(), '../..')))" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import gillespy2" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "def create_model(A=1, B=999):\n", + " # Initialize Model\n", + " model = gillespy2.Model(name=\"Bimolecular_test\")\n", + " model.add([\n", + " #species\n", + " gillespy2.Species(name=\"A\", initial_value=A, \n", + " mode=\"discrete\"),\n", + " gillespy2.Species(name=\"B\", initial_value=B, \n", + " mode=\"discrete\"),\n", + " #parameters\n", + " gillespy2.Parameter(name=\"r_fwd\", expression=\"0.01\"),\n", + " gillespy2.Parameter(name=\"r_rev\", expression=\"0.01\"),\n", + " #reactions\n", + " gillespy2.Reaction(name='forward',\n", + " reactants={'A':1, 'B':1},\n", + " products={'A':2},\n", + " rate='r_fwd'),\n", + " gillespy2.Reaction(name='reverse',\n", + " reactants={'A':2},\n", + " products={'A':1, 'B':1},\n", + " rate='r_rev'\n", + " #propensity_function=\"((((r_rev)*A)*(A-1))/vol)\" \n", + " ),\n", + " gillespy2.TimeSpan.arange(t=10,increment=0.1)\n", + " ])\n", + " return model\n" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "model = create_model(A=999,B=1)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 1.91 ms, sys: 12 ms, total: 13.9 ms\n", + "Wall time: 2.81 s\n" + ] + } + ], + "source": [ + "%time result = model.run()" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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YodwHAAAAAAAAABQ7BCO46omTJigmjVrKiQkRG3bttW6des8PSQABWTcuHFq3bq1SpYsqYoVK6pv377as2ePp4cFoJC88cYbslgsGj16tKeHAqAAnThxQoMHD1a5cuVUokQJNW7cWBs2bPD0sAAUELvdrhdeeEG1atVSiRIldO211+qVV16R0+n09NAAuMmyZct02223qUqVKrJYLPrxxx+zfN3pdOrFF19U5cqVVaJECfXo0UP79u3zzGC9EOE4rmj27NkaM2aMXnrpJW3atElNmzZVr169FBMT4+mhASgAS5cu1ahRo7RmzRotXLhQNptNPXv2VFJSkqeHBqCArV+/Xp988omaNGni6aEAKEDnz59Xx44dFRgYqAULFmjnzp165513VKZMGU8PDUABefPNNzVx4kR99NFH2rVrl95880299dZb+vDDDz09NABukpSUpKZNm2rChAmX/fpbb72l8ePHa9KkSVq7dq3CwsLUq1cvpaSkFPJIvZPFyeFCXEHbtm3VunVrffTRR5Ikh8OhatWq6fHHH9ezzz7r4dEBKGinT59WxYoVtXTpUnXp0sXTwwFQQBITE9WiRQt9/PHHevXVV9WsWTO9//77nh4WgALw7LPPauXKlVq+fLmnhwKgkNx6662KjIzUZ599lnFev379VKJECc2YMcODIwNQECwWi3744Qf17dtXkpk1XqVKFT399NP65z//KUmKi4tTZGSkpk+frnvuuceDo/UOzBzHZVmtVm3cuFE9evTIOM/Pz089evTQ6tWrPTgyAIUlLi5OklS2bFkPjwRAQRo1apT69OmT5TkfQNH0888/q1WrVurfv78qVqyo5s2ba8qUKZ4eFoAC1KFDBy1atEh79+6VJG3ZskUrVqxQ7969PTwyAIXh0KFDioqKyvJaPyIiQm3btiXfSxfg6QHAO505c0Z2u12RkZFZzo+MjNTu3bs9NCoAhcXhcGj06NHq2LGjGjVq5OnhACggX3/9tTZt2qT169d7eigACsHBgwc1ceJEjRkzRv/5z3+0fv16PfHEEwoKCtLQoUM9PTwABeDZZ59VfHy86tevL39/f9ntdr322msaNGiQp4cGoBBERUVJ0mXzPdfXijvCcQDAJUaNGqXt27drxYoVnh4KgAJy7NgxPfnkk1q4cKFCQkI8PRwAhcDhcKhVq1Z6/fXXJUnNmzfX9u3bNWnSJMJxoIiaM2eOZs6cqVmzZun666/X5s2bNXr0aFWpUoX7PQCIWhVcQfny5eXv76/o6Ogs50dHR6tSpUoeGhWAwvDYY49p7ty5WrJkiapWrerp4QAoIBs3blRMTIxatGihgIAABQQEaOnSpRo/frwCAgJkt9s9PUQAbla5cmU1bNgwy3kNGjTQ0aNHPTQiAAXtmWee0bPPPqt77rlHjRs31pAhQ/TUU09p3Lhxnh4agELgyvDI966McByXFRQUpJYtW2rRokUZ5zkcDi1atEjt27f34MgAFBSn06nHHntMP/zwgxYvXqxatWp5ekgACtCNN96obdu2afPmzRn/WrVqpUGDBmnz5s3y9/f39BABuFnHjh21Z8+eLOft3btXNWrU8NCIABS05ORk+flljX78/f3lcDg8NCIAhalWrVqqVKlSlnwvPj5ea9euJd9LR60KrmjMmDEaOnSoWrVqpTZt2uj9999XUlKShg8f7umhASgAo0aN0qxZs/TTTz+pZMmSGf1jERERKlGihIdHB8DdSpYsecmeAmFhYSpXrhx7DQBF1FNPPaUOHTro9ddf14ABA7Ru3TpNnjxZkydP9vTQABSQ2267Ta+99pqqV6+u66+/Xn/99Zfeffdd3X///Z4eGgA3SUxM1P79+zM+P3TokDZv3qyyZcuqevXqGj16tF599VXVqVNHtWrV0gsvvKAqVaqob9++nhu0F7E4nU6npwcB7/XRRx/p7bffVlRUlJo1a6bx48erbdu2nh4WgAJgsVgue/60adM0bNiwwh0MAI/o2rWrmjVrpvfff9/TQwFQQObOnauxY8dq3759qlWrlsaMGaORI0d6elgACkhCQoJeeOEF/fDDD4qJiVGVKlU0cOBAvfjiiwoKCvL08AC4wZ9//qlu3bpdcv7QoUM1ffp0OZ1OvfTSS5o8ebJiY2PVqVMnffzxx6pbt64HRut9CMcBAAAAAAAAAMUOneMAAAAAAAAAgGKHcBwAAAAAAAAAUOwQjgMAAAAAAAAAih3CcQAAAAAAAABAsUM4DgAAAAAAAAAodgjHAQAAAAAAAADFDuE4AAAAAAAAAKDYIRwHAAAAirBhw4apb9++nh4GAAAA4HUCPD0AAAAAAHljsViu+vWXXnpJH3zwgZxOZyGNCAAAAPAdhOMAAACAjzp16lTG6dmzZ+vFF1/Unj17Ms4LDw9XeHi4J4YGAAAAeD1qVQAAAAAfValSpYx/ERERslgsWc4LDw+/pFala9euevzxxzV69GiVKVNGkZGRmjJlipKSkjR8+HCVLFlS1113nRYsWJDlurZv367evXsrPDxckZGRGjJkiM6cOVPIvzEAAADgPoTjAAAAQDHz+eefq3z58lq3bp0ef/xxPfLII+rfv786dOigTZs2qWfPnhoyZIiSk5MlSbGxserevbuaN2+uDRs26Ndff1V0dLQGDBjg4d8EAAAAyDvCcQAAAKCYadq0qZ5//nnVqVNHY8eOVUhIiMqXL6+RI0eqTp06evHFF3X27Flt3bpVkvTRRx+pefPmev3111W/fn01b95cU6dO1ZIlS7R3714P/zYAAABA3tA5DgAAABQzTZo0yTjt7++vcuXKqXHjxhnnRUZGSpJiYmIkSVu2bNGSJUsu219+4MAB1a1bt4BHDAAAALgf4TgAAABQzAQGBmb53GKxZDnPYrFIkhwOhyQpMTFRt912m958881LflblypULcKQAAABAwSEcBwAAAHBVLVq00HfffaeaNWsqIIC3EAAAACga6BwHAAAAcFWjRo3SuXPnNHDgQK1fv14HDhzQb7/9puHDh8tut3t6eAAAAECeEI4DAAAAuKoqVapo5cqVstvt6tmzpxo3bqzRo0erdOnS8vPjLQUAAAB8k8XpdDo9PQgAAAAAAAAAAAoT0zwAAAAAAAAAAMUO4TgAAAAAAAAAoNghHAcAAAAAAAAAFDuE4wAAAAAAAACAYodwHAAAAAAAAABQ7BCOAwAAAAAAAACKHcJxAAAAAAAAAECxQzgOAAAAAAAAACh2CMcBAAAAAAAAAMUO4TgAAAAAAAAAoNghHAcAAAAAAAAAFDuE4wAAAAAAAACAYuf/ATtUYuvNrgjKAAAAAElFTkSuQmCC\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "result.plot()" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Bimolecular_test\n", + "\n", + "**********\n", + "Species\n", + "**********\n", + "\n", + "A: 999\n", + "B: 1\n", + "\n", + "**********\n", + "Parameters\n", + "**********\n", + "\n", + "r_fwd: 0.01\n", + "r_rev: 0.01\n", + "\n", + "**********\n", + "Reactions\n", + "**********\n", + "\n", + "forward\n", + "\tReactants\n", + "\t\tA: 1\n", + "\t\tB: 1\n", + "\tProducts\n", + "\t\tA: 2\n", + "\tPropensity Function: (((r_fwd*A)*B)/vol)\n", + "reverse\n", + "\tReactants\n", + "\t\tA: 2\n", + "\tProducts\n", + "\t\tA: 1\n", + "\t\tB: 1\n", + "\tPropensity Function: (((r_rev*A)*(A-1))/vol)\n", + "\n", + "**********\n", + "Timespan\n", + "**********\n", + "[ 0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1. 1.1 1.2 1.3\n", + " 1.4 1.5 1.6 1.7 1.8 1.9 2. 2.1 2.2 2.3 2.4 2.5 2.6 2.7\n", + " 2.8 2.9 3. 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 4. 4.1\n", + " 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 5. 5.1 5.2 5.3 5.4 5.5\n", + " 5.6 5.7 5.8 5.9 6. 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9\n", + " 7. 7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 8. 8.1 8.2 8.3\n", + " 8.4 8.5 8.6 8.7 8.8 8.9 9. 9.1 9.2 9.3 9.4 9.5 9.6 9.7\n", + " 9.8 9.9 10. ]\n" + ] + } + ], + "source": [ + "print(model)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.10" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/gillespy2/__version__.py b/gillespy2/__version__.py index 49df09ceb..629322003 100644 --- a/gillespy2/__version__.py +++ b/gillespy2/__version__.py @@ -22,7 +22,7 @@ # ============================================================================= -__version__ = '1.7.0' +__version__ = '1.7.1' __title__ = 'GillesPy2' __description__ = 'Python interface for Gillespie-style biochemical simulations' @@ -31,4 +31,4 @@ __author__ = 'See AUTHORS' __email__ = 'bdrawert@unca.edu' __license__ = 'GPL' -__copyright__ = 'Copyright (C) 2017-2021' +__copyright__ = 'Copyright (C) 2017-2022' diff --git a/gillespy2/core/events.py b/gillespy2/core/events.py index 2cb5b4d91..a03e201ae 100644 --- a/gillespy2/core/events.py +++ b/gillespy2/core/events.py @@ -39,12 +39,15 @@ class EventAssignment(Jsonify): """ + def __init__(self, name=None, variable=None, expression=None): if name in (None, ""): - self.name = f'evn{uuid.uuid4()}'.replace('-', '_') + name = f'evn{uuid.uuid4()}'.replace('-', '_') else: - self.name = name + from gillespy2.core import log + log.warning("EventAssignment.name has been deprecated.") + self.__name_deprecated = name self.variable = variable self.expression = expression @@ -70,6 +73,14 @@ def __init__(self, name=None, variable=None, expression=None): def __str__(self): return f"{self.variable}: {self.expression}" + def __getattr__(self, key): + if key == 'name': + from gillespy2.core import log + log.warning('EventAssignment.name has been deprecated.') + return self.__name_deprecated + else: + raise AttributeError + class EventTrigger(Jsonify): """ Trigger detects changes in model/environment conditions in order to fire an diff --git a/gillespy2/core/model.py b/gillespy2/core/model.py index 9c8af418c..498cb6c65 100644 --- a/gillespy2/core/model.py +++ b/gillespy2/core/model.py @@ -1062,6 +1062,9 @@ def make_translation_table(self): assignments = self.listOfAssignmentRules.values() rates = self.listOfRateRules.values() events = self.listOfEvents.values() + for event in events: + for assignment in event.__dict__['assignments']: + del assignment.__dict__['__name_deprecated'] functions = self.listOfFunctionDefinitions.values() # A translation table is used to anonymize user-defined variable names and formulas into generic counterparts. diff --git a/gillespy2/core/reaction.py b/gillespy2/core/reaction.py index 799389b33..fb76e21e0 100644 --- a/gillespy2/core/reaction.py +++ b/gillespy2/core/reaction.py @@ -295,7 +295,7 @@ def _create_mass_action(self): reactant = reactant.name # Case 1: 2X -> Y if stoichiometry == 2: - propensity_function = f"0.5 * {propensity_function} * {reactant} * ({reactant} - 1) / vol" + propensity_function = f"{propensity_function} * {reactant} * ({reactant} - 1) / vol" ode_propensity_function += f" * {reactant} * {reactant}" else: # Case 3: X1, X2 -> Y; diff --git a/gillespy2/solvers/cpp/c_base/arg_parser.cpp b/gillespy2/solvers/cpp/c_base/arg_parser.cpp index 7ee4c5239..a1fe500cd 100644 --- a/gillespy2/solvers/cpp/c_base/arg_parser.cpp +++ b/gillespy2/solvers/cpp/c_base/arg_parser.cpp @@ -95,10 +95,12 @@ char ArgParser::match_arg(std::string &token) return 'M'; } - else + if (!token.compare("--use_root_finding")) { - return 0; + return 'u'; } + + return 0; } ArgParser::ArgParser(int argc, char *argv[]) @@ -176,6 +178,10 @@ ArgParser::ArgParser(int argc, char *argv[]) verbose = true; break; + case 'u': + use_root_finding = true; + break; + case 'R': std::stringstream(argv[i + 1]) >> rtol; break; diff --git a/gillespy2/solvers/cpp/c_base/arg_parser.h b/gillespy2/solvers/cpp/c_base/arg_parser.h index b62ad425d..1b4c72a2d 100644 --- a/gillespy2/solvers/cpp/c_base/arg_parser.h +++ b/gillespy2/solvers/cpp/c_base/arg_parser.h @@ -51,6 +51,7 @@ class ArgParser double atol = 1e-12; bool verbose = false; + bool use_root_finding = false; ArgParser(int argc, char *argv[]); ~ArgParser(); diff --git a/gillespy2/solvers/cpp/c_base/tau_hybrid_cpp_solver/TauHybridSimulation.cpp b/gillespy2/solvers/cpp/c_base/tau_hybrid_cpp_solver/TauHybridSimulation.cpp index 982d25835..f9d636b80 100644 --- a/gillespy2/solvers/cpp/c_base/tau_hybrid_cpp_solver/TauHybridSimulation.cpp +++ b/gillespy2/solvers/cpp/c_base/tau_hybrid_cpp_solver/TauHybridSimulation.cpp @@ -78,9 +78,10 @@ int main(int argc, char* argv[]) parser.rtol, parser.atol, parser.max_step, + }; - TauHybrid::TauHybridCSolver(&simulation, events, logger, tau_tol, config); + TauHybrid::TauHybridCSolver(&simulation, events, logger, tau_tol, config, parser.use_root_finding); simulation.output_buffer_final(std::cout); return simulation.get_status(); } diff --git a/gillespy2/solvers/cpp/c_base/tau_hybrid_cpp_solver/TauHybridSolver.cpp b/gillespy2/solvers/cpp/c_base/tau_hybrid_cpp_solver/TauHybridSolver.cpp index a44c636bb..735e66e92 100644 --- a/gillespy2/solvers/cpp/c_base/tau_hybrid_cpp_solver/TauHybridSolver.cpp +++ b/gillespy2/solvers/cpp/c_base/tau_hybrid_cpp_solver/TauHybridSolver.cpp @@ -84,6 +84,7 @@ namespace Gillespy // Temporary variable for the reaction's state. // Does not get updated unless the changes are deemed valid. double rxn_state = result.reactions[rxn_i]; + double old_rxn_state = rxn_state; if (simulation->reaction_state[rxn_i].mode == SimulationState::DISCRETE) { unsigned int rxn_count = 0; @@ -109,15 +110,14 @@ namespace Gillespy } } - bool TakeIntegrationStep(Integrator&sol, IntegrationResults&result, double next_time, int*population_changes, + bool TakeIntegrationStep(Integrator&sol, IntegrationResults&result, double *next_time, int*population_changes, std::vector current_state, std::set&rxn_roots, std::set&event_roots, HybridSimulation*simulation, URNGenerator&urn, int only_reaction_to_fire){ // Integration Step // For deterministic reactions, the concentrations are updated directly. // For stochastic reactions, integration updates the rxn_offsets vector. - //IntegrationResults result = sol.integrate(&next_time, event_roots, rxn_roots); - result = sol.integrate(&next_time, event_roots, rxn_roots); + result = sol.integrate(next_time, event_roots, rxn_roots); if (sol.status == IntegrationStatus::BAD_STEP_SIZE) { simulation->set_status(HybridSimulation::INTEGRATOR_FAILED); @@ -134,10 +134,11 @@ namespace Gillespy - bool IsStateNegativeCheck(int num_species, int*population_changes, std::vector current_state){ + bool IsStateNegativeCheck(int num_species, int*population_changes, std::vector current_state, std::set>tau_args_reactants){ // Explicitly check for invalid population state, now that changes have been tallied. - for (int spec_i = 0; spec_i < num_species; ++spec_i) { - if (current_state[spec_i] + population_changes[spec_i] < 0) { + // Note: this should only check species that are reactants or products + for (const auto &r : tau_args_reactants) { + if (population_changes[r.id] != 0 && current_state[r.id] + population_changes[r.id] < 0) { return true; } } @@ -150,7 +151,8 @@ namespace Gillespy std::vector &events, Logger &logger, double tau_tol, - SolverConfiguration config) + SolverConfiguration config, + bool default_use_root_finding) { if (simulation == NULL) { @@ -163,6 +165,9 @@ namespace Gillespy int num_reactions = model.number_reactions; int num_trajectories = simulation->number_trajectories; std::unique_ptr[]> &species = model.species; + bool use_root_finding = default_use_root_finding; + bool in_event_handling = false; + unsigned int neg_state_loop_cnt = 0; generator = std::mt19937_64(simulation->random_seed); URNGenerator urn(simulation->random_seed); @@ -319,101 +324,58 @@ namespace Gillespy IntegrationResults result; - if(!TauHybrid::TakeIntegrationStep(sol, result, next_time, population_changes, current_state, rxn_roots, event_roots, simulation, urn, -1)){ + if(in_event_handling){ + sol.use_events(events, simulation->reaction_state); + sol.enable_root_finder(); + }else if(use_root_finding){ + sol.use_reactions(simulation->reaction_state); + sol.enable_root_finder(); + if(neg_state_loop_cnt > 0){ + neg_state_loop_cnt--; + }else{ + use_root_finding = default_use_root_finding; + } + }else{ + sol.disable_root_finder(); + } + + + if(!TauHybrid::TakeIntegrationStep(sol, result, &next_time, population_changes, current_state, rxn_roots, event_roots, simulation, urn, -1)){ return; } // Check if we have gone negative - if (TauHybrid::IsStateNegativeCheck(num_species, population_changes, current_state)) { + if (TauHybrid::IsStateNegativeCheck(num_species, population_changes, current_state, tau_args.reactants)) { // If state is invalid, we took too agressive tau step and need to take a single SSA step forward // Restore the solver to the intial step state sol.restore_state(); - - // Calculate floor()'ed state for use in SSA step - for(int spec_i = 0; spec_i < num_species; ++spec_i){ - floored_current_state[spec_i] = floor(current_state[spec_i]); - } - // estimate the time to the first stochatic reaction by assuming constant propensities - double min_tau = 0.0; - int rxn_selected = -1; - - double *rxn_state = sol.get_reaction_state(); - - for (int rxn_k = 0; rxn_k < num_reactions; ++rxn_k) { - HybridReaction &rxn = simulation->reaction_state[rxn_k]; - double propensity_value = rxn.ssa_propensity(current_state.data()); - double floored_propensity_value = rxn.ssa_propensity(floored_current_state); - //estimate the zero crossing time - if(floored_propensity_value > 0.0){ - double est_tau = -1* rxn_state[rxn_k] / propensity_value; - - if(rxn_selected == -1 || est_tau < min_tau ){ - min_tau = est_tau; - rxn_selected = rxn_k; - } - } - } - if(rxn_selected == -1){ - simulation->set_status(HybridSimulation::NEGATIVE_STATE_NO_SSA_REACTION); - return; - } - // if min_tau < 1e-10, we can't take an ODE step that small. - if( min_tau < 1e-10 ){ - // instead we will fire the reaction - CalculateSpeciesChangeAfterStep(result, population_changes, current_state, rxn_roots, event_roots, simulation, urn, rxn_selected); - // re-attempt the step at the same time - next_time = simulation->current_time; - - }else{ - // Use the found tau-step for single SSA - next_time = simulation->current_time + min_tau; - - //*********************************** - //*********************************** - - // Integreate the system forward - if(!TauHybrid::TakeIntegrationStep(sol, result, next_time, population_changes, current_state, rxn_roots, event_roots, simulation, urn, rxn_selected)){ - return; - } - } - // check for invalid state again - if (TauHybrid::IsStateNegativeCheck(num_species, population_changes, current_state)) { - //Got an invalid state after the SSA step - simulation->set_status(HybridSimulation::INVALID_AFTER_SSA); - return; - } + use_root_finding=true; + neg_state_loop_cnt = 2; // How many single SSA events should we find before we go back to tau steping + continue; } - // "Permanently" update the rxn_state and populations. + + // Update solver object with stochastic changes for (int p_i = 0; p_i < num_species; ++p_i) { if (!simulation->species_state[p_i].boundary_condition) { - // Boundary conditions are not modified directly by reactions. - // As such, population dx in stochastic regime is not considered. - // For deterministic species, their effective dy/dt should always be 0. HybridSpecies *spec = &simulation->species_state[p_i]; if( spec->partition_mode == SimulationState::CONTINUOUS ){ - current_state[p_i] = result.concentrations[p_i] + population_changes[p_i]; + result.concentrations[p_i] = result.concentrations[p_i] + population_changes[p_i]; }else if( spec->partition_mode == SimulationState::DISCRETE ){ - current_state[p_i] += population_changes[p_i]; + result.concentrations[p_i] = current_state[p_i] + population_changes[p_i]; } - result.concentrations[p_i] = current_state[p_i]; } } - - if (interrupted){ - break; - } - // ===== ===== if (!event_list.has_active_events()) { if (event_list.evaluate_triggers(N_VGetArrayPointer(sol.y), next_time)) { sol.restore_state(); - sol.use_events(events, simulation->reaction_state); - sol.enable_root_finder(); + use_root_finding=true; + in_event_handling=true; continue; } } @@ -422,12 +384,31 @@ namespace Gillespy double *event_state = N_VGetArrayPointer(sol.y); if (!event_list.evaluate(event_state, num_species, next_time, event_roots)) { - sol.disable_root_finder(); + in_event_handling=false; + use_root_finding = default_use_root_finding; // set to default } std::copy(event_state, event_state + num_species, current_state.begin()); } // ===== ===== + // "Permanently" update species populations. + // (needs to be below event handling) + for (int p_i = 0; p_i < num_species; ++p_i) + { + if (!simulation->species_state[p_i].boundary_condition) + { + // Boundary conditions are not modified directly by reactions. + // As such, population dx in stochastic regime is not considered. + // For deterministic species, their effective dy/dt should always be 0. + current_state[p_i] = result.concentrations[p_i]; + } + } + + if (interrupted){ + break; + } + + // Output the results for this time step. sol.refresh_state(); simulation->current_time = next_time; diff --git a/gillespy2/solvers/cpp/c_base/tau_hybrid_cpp_solver/TauHybridSolver.h b/gillespy2/solvers/cpp/c_base/tau_hybrid_cpp_solver/TauHybridSolver.h index 4db5b0cf9..c3eaeeca2 100644 --- a/gillespy2/solvers/cpp/c_base/tau_hybrid_cpp_solver/TauHybridSolver.h +++ b/gillespy2/solvers/cpp/c_base/tau_hybrid_cpp_solver/TauHybridSolver.h @@ -25,6 +25,6 @@ namespace Gillespy { namespace TauHybrid { - void TauHybridCSolver(HybridSimulation* simulation, std::vector &events, Logger &logger, double tau_tol, SolverConfiguration config); + void TauHybridCSolver(HybridSimulation* simulation, std::vector &events, Logger &logger, double tau_tol, SolverConfiguration config, bool use_root_finding); } } diff --git a/gillespy2/solvers/cpp/c_base/tau_hybrid_cpp_solver/integrator.cpp b/gillespy2/solvers/cpp/c_base/tau_hybrid_cpp_solver/integrator.cpp index afb4c0a61..4e9da117f 100644 --- a/gillespy2/solvers/cpp/c_base/tau_hybrid_cpp_solver/integrator.cpp +++ b/gillespy2/solvers/cpp/c_base/tau_hybrid_cpp_solver/integrator.cpp @@ -125,15 +125,17 @@ Integrator::~Integrator() IntegrationResults Integrator::integrate(double *t) { - if (!validate(this, CVode(cvode_mem, *t, y, &this->t, CV_NORMAL))) + int retcode = CVode(cvode_mem, *t, y, &this->t, CV_NORMAL); + if (!validate(this, retcode )) { - return { nullptr, nullptr }; + return { nullptr, nullptr, 0 }; } *t = this->t; return { NV_DATA_S(y), - NV_DATA_S(y) + num_species + NV_DATA_S(y) + num_species, + retcode }; } @@ -162,32 +164,37 @@ IntegrationResults Integrator::integrate(double *t, std::set &event_roots, return results; } - unsigned long long num_triggers = data.active_triggers.size(); - unsigned long long num_rxn_roots = data.active_reaction_ids.size(); - unsigned long long root_size = data.active_triggers.size() + data.active_reaction_ids.size(); - int *root_results = new int[root_size]; + // check to see if any root we found by the solver + if( results.retcode == CV_ROOT_RETURN ){ + // find which roots were found and return them + unsigned long long num_triggers = data.active_triggers.size(); + unsigned long long num_rxn_roots = data.active_reaction_ids.size(); + unsigned long long root_size = data.active_triggers.size() + data.active_reaction_ids.size(); + int *root_results = new int[root_size]; - if (validate(this, CVodeGetRootInfo(cvode_mem, root_results))) - { - unsigned long long root_id; - for (root_id = 0; root_id < num_triggers; ++root_id) + if (validate(this, CVodeGetRootInfo(cvode_mem, root_results))) { - if (root_results[root_id] != 0) + unsigned long long root_id; + for (root_id = 0; root_id < num_triggers; ++root_id) { - event_roots.insert((int) root_id); + if (root_results[root_id] != 0) + { + event_roots.insert((int) root_id); + } } - } - for (; root_id < num_rxn_roots; ++root_id) - { - if (root_results[root_id] < 0) + for (; root_id < root_size; ++root_id) // reaction roots { - reaction_roots.insert(data.active_reaction_ids[root_id]); + if (root_results[root_id] != 0) + { + int rxn_id = root_id - num_triggers; + reaction_roots.insert(data.active_reaction_ids[rxn_id]); + } } } - } - delete[] root_results; + delete[] root_results; + } return results; } diff --git a/gillespy2/solvers/cpp/c_base/tau_hybrid_cpp_solver/integrator.h b/gillespy2/solvers/cpp/c_base/tau_hybrid_cpp_solver/integrator.h index 0b713683a..efb680bb1 100644 --- a/gillespy2/solvers/cpp/c_base/tau_hybrid_cpp_solver/integrator.h +++ b/gillespy2/solvers/cpp/c_base/tau_hybrid_cpp_solver/integrator.h @@ -79,6 +79,7 @@ namespace Gillespy realtype *concentrations; // reactions: bounded by [num_species, num_species + num_reactions) realtype *reactions; + int retcode; }; struct URNGenerator diff --git a/gillespy2/solvers/cpp/ode_c_solver.py b/gillespy2/solvers/cpp/ode_c_solver.py index a185fc8c7..bbc0fdfcb 100644 --- a/gillespy2/solvers/cpp/ode_c_solver.py +++ b/gillespy2/solvers/cpp/ode_c_solver.py @@ -40,7 +40,8 @@ def get_supported_integrator_options(): "max_step", } - def get_solver_settings(self): + @classmethod + def get_solver_settings(cls): """ Returns a list of arguments supported by odc_c_solver.run. :returns: Tuple of strings, denoting all keyword argument for this solvers run() method. @@ -136,7 +137,6 @@ def run(self=None, model: Model = None, t: int = None, number_of_trajectories: i number_timesteps = int(round(t / increment + 1)) args = { - "trajectories": number_of_trajectories, "timesteps": number_timesteps, "end": t, "increment": increment, @@ -171,7 +171,7 @@ def run(self=None, model: Model = None, t: int = None, number_of_trajectories: i display_args = None args = self._make_args(args) - decoder = IterativeSimDecoder.create_default(number_of_trajectories, number_timesteps, len(self.model.listOfSpecies)) + decoder = IterativeSimDecoder.create_default(1, number_timesteps, len(self.model.listOfSpecies)) sim_exec = self._build(self.model, self.target, self.variable, False) sim_status = self._run(sim_exec, args, decoder, timeout, display_args) @@ -190,4 +190,4 @@ def run(self=None, model: Model = None, t: int = None, number_of_trajectories: i self.result = simulation_data self.rc = int(sim_status) - return Results.build_from_solver_results(self, live_output_options) \ No newline at end of file + return sum([Results.build_from_solver_results(self, live_output_options)] * number_of_trajectories) \ No newline at end of file diff --git a/gillespy2/solvers/cpp/ssa_c_solver.py b/gillespy2/solvers/cpp/ssa_c_solver.py index 353004ad2..c41d08161 100644 --- a/gillespy2/solvers/cpp/ssa_c_solver.py +++ b/gillespy2/solvers/cpp/ssa_c_solver.py @@ -32,7 +32,8 @@ class SSACSolver(GillesPySolver, CSolver): name = "SSACSolver" target = "ssa" - def get_solver_settings(self): + @classmethod + def get_solver_settings(cls): """ Returns a list of arguments supported by ssa_c_solver.run. :returns: Tuple of strings, denoting all keyword argument for this solvers run() method. diff --git a/gillespy2/solvers/cpp/tau_hybrid_c_solver.py b/gillespy2/solvers/cpp/tau_hybrid_c_solver.py index 0bf931cf4..e2f794e9d 100644 --- a/gillespy2/solvers/cpp/tau_hybrid_c_solver.py +++ b/gillespy2/solvers/cpp/tau_hybrid_c_solver.py @@ -190,7 +190,8 @@ def _handle_return_code(self, return_code: "int") -> "int": return super()._handle_return_code(return_code) - def get_solver_settings(self): + @classmethod + def get_solver_settings(cls): """ Returns a list of arguments supported by tau_hybrid_c_solver.run. :return: Tuple of strings, denoting all keyword argument for this solvers run() method. @@ -200,7 +201,7 @@ def get_solver_settings(self): def run(self=None, model: Model = None, t: int = None, number_of_trajectories: int = 1, timeout: int = 0, increment: int = None, seed: int = None, debug: bool = False, profile: bool = False, variables={}, - resume=None, live_output: str = None, live_output_options: dict = {}, tau_step: int = .03, tau_tol=0.03, integrator_options: "dict[str, float]" = None, **kwargs): + resume=None, live_output: str = None, live_output_options: dict = {}, tau_step: int = .03, tau_tol=0.03, integrator_options: "dict[str, float]" = None, use_root_finding=False, **kwargs): """ :param model: The model on which the solver will operate. (Deprecated) @@ -326,6 +327,9 @@ def run(self=None, model: Model = None, t: int = None, number_of_trajectories: i args = self._make_args(args) if debug: args.append("--verbose") + if use_root_finding: + args.append("--use_root_finding") + decoder = IterativeSimDecoder.create_default(number_of_trajectories, number_timesteps, len(self.model.listOfSpecies)) sim_exec = self._build(self.model, self.target, self.variable, False) diff --git a/gillespy2/solvers/cpp/tau_leaping_c_solver.py b/gillespy2/solvers/cpp/tau_leaping_c_solver.py index ad12dc8d3..815bd818a 100644 --- a/gillespy2/solvers/cpp/tau_leaping_c_solver.py +++ b/gillespy2/solvers/cpp/tau_leaping_c_solver.py @@ -35,7 +35,8 @@ class TauLeapingCSolver(GillesPySolver, CSolver): name = "TauLeapingCSolver" target = "tau_leap" - def get_solver_settings(self): + @classmethod + def get_solver_settings(cls): """ Returns a list of arguments supported by tau_leaping_c_solver.run. :returns: Tuple of strings, denoting all keyword argument for this solvers run() method. diff --git a/gillespy2/solvers/numpy/CLE_solver.py b/gillespy2/solvers/numpy/CLE_solver.py index ab1444a44..6ec3515a6 100644 --- a/gillespy2/solvers/numpy/CLE_solver.py +++ b/gillespy2/solvers/numpy/CLE_solver.py @@ -99,7 +99,7 @@ def __get_reactions(self, step, curr_state, curr_time, save_time, propensities, return rxn_count, curr_state, curr_time @classmethod - def get_solver_settings(self): + def get_solver_settings(cls): """ Returns a list of arguments supported by CLE_solver.run. :returns: Tuple of strings, denoting all keyword argument for this solvers run() method. diff --git a/gillespy2/solvers/numpy/ode_solver.py b/gillespy2/solvers/numpy/ode_solver.py index c9517b5e6..6631d066c 100644 --- a/gillespy2/solvers/numpy/ode_solver.py +++ b/gillespy2/solvers/numpy/ode_solver.py @@ -81,7 +81,7 @@ def __f(t, y, curr_state, model, c_prop): return state_change @classmethod - def get_solver_settings(self): + def get_solver_settings(cls): """ Returns a list of arguments supported by ode_solver.run. :returns: Tuple of strings, denoting all keyword argument for this solvers run() method. diff --git a/gillespy2/solvers/numpy/ssa_solver.py b/gillespy2/solvers/numpy/ssa_solver.py index de166c6c9..3deefd483 100644 --- a/gillespy2/solvers/numpy/ssa_solver.py +++ b/gillespy2/solvers/numpy/ssa_solver.py @@ -53,7 +53,8 @@ def __init__(self, model=None): self.model = copy.deepcopy(model) self.is_instantiated = True - def get_solver_settings(self): + @classmethod + def get_solver_settings(cls): """ Returns a list of arguments supported by the ssa_solver.run :returns: Tuple of strings, denoting all keyword argument for this solvers run() method. diff --git a/gillespy2/solvers/numpy/tau_hybrid_solver.py b/gillespy2/solvers/numpy/tau_hybrid_solver.py index bd54f79ec..5a4722514 100644 --- a/gillespy2/solvers/numpy/tau_hybrid_solver.py +++ b/gillespy2/solvers/numpy/tau_hybrid_solver.py @@ -886,7 +886,7 @@ def __map_state(self, species, parameters, compiled_reactions, events, curr_stat return y0, y_map @classmethod - def get_solver_settings(self): + def get_solver_settings(cls): """ Returns a list of arguments supported by tau_hybrid_solver.run. :returns: Tuple of strings, denoting all keyword argument for this solvers run() method. diff --git a/gillespy2/solvers/numpy/tau_leaping_solver.py b/gillespy2/solvers/numpy/tau_leaping_solver.py index 8cda6fa12..b73e5555e 100644 --- a/gillespy2/solvers/numpy/tau_leaping_solver.py +++ b/gillespy2/solvers/numpy/tau_leaping_solver.py @@ -87,7 +87,7 @@ def __get_reactions(self, step, curr_state, curr_time, save_time, propensities, return rxn_count, curr_state, curr_time @classmethod - def get_solver_settings(self): + def get_solver_settings(cls): """ Returns a list of arguments supported by tau_leaping_solver.run. :returns: Tuple of strings, denoting all keyword argument for this solvers run() method. diff --git a/test/run_integration_tests.py b/test/run_integration_tests.py index 93a4a2a49..00b57fd36 100644 --- a/test/run_integration_tests.py +++ b/test/run_integration_tests.py @@ -30,7 +30,7 @@ if __name__ == '__main__': args = parser.parse_args() if args.mode == 'develop': - print('Running tests in develop mode. Appending repository directory to system path.') + print('Running integration tests in develop mode. Appending repository directory to system path.') sys.path.append(os.path.join(os.path.dirname(__file__), '..')) import test_empty_model diff --git a/test/run_system_tests.py b/test/run_system_tests.py index 536937730..12ba5e09a 100644 --- a/test/run_system_tests.py +++ b/test/run_system_tests.py @@ -30,7 +30,7 @@ if __name__ == '__main__': args = parser.parse_args() if args.mode == 'develop': - print('Running tests in develop mode. Appending repository directory to system path.') + print('Running system tests in develop mode. Appending repository directory to system path.') sys.path.append(os.path.join(os.path.dirname(__file__), '..')) from system_tests import test_compile_w_spaces diff --git a/test/run_unit_tests.py b/test/run_unit_tests.py index d5cbb063a..9e1b856ff 100644 --- a/test/run_unit_tests.py +++ b/test/run_unit_tests.py @@ -30,7 +30,7 @@ if __name__ == '__main__': args = parser.parse_args() if args.mode == 'develop': - print('Running tests in develop mode. Appending repository directory to system path.') + print('Running unit tests in develop mode. Appending repository directory to system path.') sys.path.append(os.path.join(os.path.dirname(__file__), '..')) from unit_tests import test_species diff --git a/test/test_check_cpp_support.py b/test/test_check_cpp_support.py index 568fa5a48..b21a1c6b2 100644 --- a/test/test_check_cpp_support.py +++ b/test/test_check_cpp_support.py @@ -32,7 +32,7 @@ def old_check_cpp_support(self): try: model = create_decay() solver = SSACSolver(model=model) - results = model.run(solver=solver, cpp_support=True) + results = model.run(solver=solver) return True except Exception as e: from gillespy2.core import log diff --git a/test/test_results.py b/test/test_results.py index e477e02e8..0543f10f0 100644 --- a/test/test_results.py +++ b/test/test_results.py @@ -43,7 +43,7 @@ def test_xscale_plot_std_dev_range(self): trajectory = Trajectory(data={'time':[0.],'foo':[1.]}, model=Model('test_model')) results = Results(data=[trajectory]) with mock.patch('matplotlib.pyplot.xscale') as mock_xscale: - results.plot_std_dev_range(xscale='log') + results.plot_mean_stdev(xscale='log') mock_xscale.assert_called_with('log') def test_yscale_plot_std_dev_range(self): @@ -73,7 +73,7 @@ def test_plotly_std_dev_range_layout_args(self): with mock.patch('plotly.offline.init_notebook_mode') as mock_notebook: with mock.patch('plotly.graph_objs.Scatter') as mock_scatter: with mock.patch('plotly.graph_objs.Layout') as mock_layout: - results.plotplotly_std_dev_range(return_plotly_figure=True, xscale='log') + results.plotplotly_mean_stdev(return_plotly_figure=True, xscale='log') mock_layout.assert_called_with(legend={'traceorder':'normal'},showlegend=True, title='Mean and Standard Deviation', xaxis_title='Time', xscale='log', yaxis_title='Value') @@ -141,7 +141,7 @@ def test_to_csv_single_result_no_stamp(self): with tempfile.TemporaryDirectory() as tempdir: result.to_csv(nametag=test_nametag, path=tempdir) - assert len(os.listdir(tempdir)) is not 0 + assert len(os.listdir(tempdir)) != 0 def test_to_csv_single_result_no_nametag(self): test_model = Model('test_model') @@ -149,7 +149,7 @@ def test_to_csv_single_result_no_nametag(self): with tempfile.TemporaryDirectory() as tempdir: result.to_csv(nametag=test_nametag, path=tempdir) - assert len(os.listdir(tempdir)) is not 0 + assert len(os.listdir(tempdir)) != 0 def test_to_csv_single_result_no_nametag(self): test_model = Model('test_model') @@ -160,7 +160,7 @@ def test_to_csv_single_result_no_nametag(self): with tempfile.TemporaryDirectory() as tempdir: result.to_csv(stamp=test_stamp, path=tempdir) - assert len(os.listdir(tempdir)) is not 0 + assert len(os.listdir(tempdir)) != 0 def test_to_csv_single_result_no_path(self): test_data = Trajectory({'time':[0]},model=Model('test_model'),solver_name='test_solver_name') diff --git a/test/test_simple_model.py b/test/test_simple_model.py index 134a03912..36a393c67 100644 --- a/test/test_simple_model.py +++ b/test/test_simple_model.py @@ -135,12 +135,6 @@ def test_getFakeParameter_ThrowsError(self): with self.assertRaises(ModelError) as ex: parameter = self.model.get_parameter(p_name) - def test_set_parameter(self): - self.model.set_parameter('k1', '100') - parameter = self.model.get_parameter('k1') - self.assertEqual('100', parameter.expression) - self.assertIsInstance(parameter, Parameter, msg='{0} has incorrect type'.format(parameter)) - def test_delete_all_parameters(self): self.model.delete_all_parameters() parameterList = self.model.get_all_parameters() diff --git a/test/unit_tests/test_reaction.py b/test/unit_tests/test_reaction.py index 265438547..ce7c8080c 100644 --- a/test/unit_tests/test_reaction.py +++ b/test/unit_tests/test_reaction.py @@ -405,7 +405,7 @@ def test__create_mass_action__2X_to_Y(self): self.valid_ma_reaction.reactants = {"X": 2} self.valid_ma_reaction.products = {"Y": 1} self.valid_ma_reaction._create_mass_action() - self.assertEqual(self.valid_ma_reaction.propensity_function, "((((0.5*k1)*X)*(X-1))/vol)") + self.assertEqual(self.valid_ma_reaction.propensity_function, "(((k1*X)*(X-1))/vol)") self.assertEqual(self.valid_ma_reaction.ode_propensity_function, "((k1*X)*X)") def test__create_mass_action__species_obj_reactant(self): @@ -536,7 +536,7 @@ def test_add_reactant__massaction_reaction_stoich_0_to_2(self): self.valid_ma_reaction.add_reactant("X", 2) self.assertIn("X", self.valid_ma_reaction.reactants) self.assertEqual(self.valid_ma_reaction.reactants["X"], 2) - self.assertEqual(self.valid_ma_reaction.propensity_function, "((((0.5*k1)*X)*(X-1))/vol)") + self.assertEqual(self.valid_ma_reaction.propensity_function, "(((k1*X)*(X-1))/vol)") self.assertEqual(self.valid_ma_reaction.ode_propensity_function, "((k1*X)*X)") def test_add_reactant__invalid_species(self):