Skip to content

Commit

Permalink
Add integrator guard to prevent infinite loops
Browse files Browse the repository at this point in the history
- Limits the number of sequential invalid states from exceeding 1000
  - Prevents "occasionally invalid" output from terminating the simulation
- Allow `tau_tol` to be properly accepted as argument
  • Loading branch information
jtcooper10 committed Jul 15, 2021
1 parent 9487a45 commit 49710b7
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 8 deletions.
2 changes: 1 addition & 1 deletion gillespy2/solvers/cpp/c_base/arg_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class ArgParser
double end = 0.0;
double increment = 0.0;
double switch_tol = 0.0;
double tau_tol = 0.0;
double tau_tol = 0.03;

ArgParser(int argc, char *argv[]);
~ArgParser();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ int random_seed = 0;
double end_time = 100.0;
bool seed_time = true;
double increment = 0;
double tau_tol = 0.05;
double tau_tol = 0.03;

class PropensityFunction : public IPropensityFunction
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,11 @@ namespace Gillespy::TauHybrid
// An invalid simulation state indicates that an unrecoverable error has occurred,
// and the trajectory should terminate early.
bool invalid_state = false;
// This is a temporary fix. Ideally, invalid state should allow for integrator options change.
// For now, a "guard" is put in place to prevent potentially infinite loops from occurring.
unsigned int integration_guard = 1000;

while (!invalid_state && simulation->current_time < simulation->end_time)
while (integration_guard > 0 && simulation->current_time < simulation->end_time)
{
// Compute current propensity values based on existing state.
for (int rxn_i = 0; rxn_i < num_reactions; ++rxn_i)
Expand Down Expand Up @@ -256,10 +259,9 @@ namespace Gillespy::TauHybrid
// Invalid state after the do-while loop implies that an unrecoverable error has occurred.
// While prior results are considered usable, the current integration results are not.
// Calling `continue` with an invalid state will discard the results and terminate the trajectory.
if (invalid_state)
{
continue;
}
integration_guard = invalid_state
? integration_guard - 1
: 1000;

// Output the results for this time step.
sol.refresh_state();
Expand All @@ -276,6 +278,14 @@ namespace Gillespy::TauHybrid
}
}

if (integration_guard == 0)
{
std::cerr
<< "[Trajectory #" << traj << "] "
<< "Integration guard triggered; problem space too stiff at t="
<< simulation->current_time << std::endl;
}

// End of trajectory
delete[] population_changes;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,10 @@ URNGenerator::URNGenerator()

URNGenerator::URNGenerator(unsigned long long seed)
: uniform(0, 1),
rng(seed) {}
rng(seed)
{
this->seed = seed;
}


/* Generate a new random floating-point number on the range [0,1).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ namespace Gillespy::TauHybrid
private:
std::uniform_real_distribution<double> uniform;
std::mt19937_64 rng;
unsigned long long seed;
public:
double next();
URNGenerator();
Expand Down

0 comments on commit 49710b7

Please sign in to comment.