Source code for gillespy2.core.gillespySolver
# GillesPy2 is a modeling toolkit for biochemical simulation.
# Copyright (C) 2019-2024 GillesPy2 developers.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import copy
from .timespan import TimeSpan
from .gillespyError import SimulationError, ModelError
[docs]class GillesPySolver:
"""
Abstract class for a solver.
"""
name = "GillesPySolver"
[docs] def run(self, model, t=20, number_of_trajectories=1, increment=0.05, seed=None,
debug=False, profile=False, **kwargs):
"""
Call out and run the solver. Collect the results.
:param model: The model on which the solver will operate.
:type model: gillespy.Model
:param t: The end time of the solver
:type t: int
:param number_of_trajectories: The number of times to sample the chemical master equation. Each
trajectory will be returned at the end of the simulation.
:type number_of_trajectories: int
:param increment: The time step of the solution
:type increment: float
:param seed: The random seed for the simulation. Defaults to None.
:type seed: int
:param debug: Set to True to provide additional debug information about the simulation.
:type debug: bool
:returns: Simulation trajectories.
"""
raise SimulationError("This abstract solver class cannot be used directly.")
[docs] def get_solver_settings(self):
'''
Abstract function for getting a solvers settings.
'''
raise SimulationError("This abstract solver class cannot be used directly")
[docs] def validate_tspan(self, increment, t):
"""
Validate the models time span and set it if not provided.
:param increment: The current value of increment.
:type increment: int
:param t: The end time of the simulation.
:type t: int
:raises SimulationError: if timespan and increment are both set by the user or neither are set by the user.
"""
if self.model.tspan is None and increment is None:
raise SimulationError(
"""
Failed while preparing to run the model. Neither increment or timespan are set.
To continue either add a `timespan` definition to your Model or add the
`increment` and `t` arguments to this `solver.run()` call.
"""
)
if self.model.tspan is not None and increment is not None:
raise SimulationError(
"""
Failed while preparing to run the model. Both increment and timespan are set.
To continue either remove your `timespan` definition from your Model or remove the
`increment` argument from this `solver.run()` call.
"""
)
if self.model.tspan is None:
if t is None:
tspan = TimeSpan.arange(increment)
else:
tspan = TimeSpan.arange(increment, t=t)
self.model.timespan(tspan)
[docs] @classmethod
def get_supported_features(cls) -> "Set[Type]":
'''
Get the set of supported features.
'''
return set()
[docs] @classmethod
def get_supported_integrator_options(cls) -> "Set[str]":
'''
Get the supported integrator options
'''
return set()
[docs] @classmethod
def validate_model(cls, sol_model, model):
'''
Validate that the solvers model is the same as the model passed to solver.run.
:param sol_model: Solver model object.
:type sol_model: gillespy2.Model
:param model: Model object passed to solver.run.
:type model: gillespy2.Model
:raises SimulationError: If the models are not equal.
'''
if model is not None:
model.compile_prep()
if model.tspan is None:
model = copy.deepcopy(model)
model.tspan = sol_model.tspan
if model.get_json_hash() != sol_model.get_json_hash():
raise SimulationError("Model must equal ODECSolver.model.")
[docs] @classmethod
def validate_sbml_features(cls, model):
'''
Validate the models SBML features.
:param model: The model object to be checked.
:type model: gillespy2.Model
:raises ModelError: If the model contains unsupported SBML features.
'''
unsupported_features = model.get_model_features() - cls.get_supported_features()
if unsupported_features:
unsupported_features = [feature.__name__ for feature in unsupported_features]
raise ModelError(f"Could not run Model, "
f"SBML Features not supported by {cls.name}: " +
", ".join(unsupported_features))
[docs] @classmethod
def validate_integrator_options(cls, options: "dict[str, float]") -> "dict[str, float]":
'''
Validate the integrator options.
:param options: Integrator options to validate.
:type options: dict
:returns: Dict of supported integrator options.
:rtype: dict
'''
return {
option: value for option, value in options.items() if option in cls.get_supported_integrator_options()
}