Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor "src/dsl.jl" file #985

Open
wants to merge 44 commits into
base: master
Choose a base branch
from
Open

Conversation

TorkelE
Copy link
Member

@TorkelE TorkelE commented Jul 13, 2024

Also does the "src/expression_utils.jl" file, as that primarily support the dsl file (the other relevant file is the chemistry one).

Primarily four types of changes:

  • Added comment to code which did not have (primarily older code).
  • Rewrite some old code (a lot of stuff in the dsl file is stuff I wrote over 6 years ago, which simply can be rewritten better now).
  • Do some organisations for where the options are handled in the main function. Been meaning to do this pretty much since I introduced them, and now when we have all *for the foreseeable future) it seemed like a good time to do it. Now it should also be easier to see where to add new options in the future.
  • Rewrite so that the @reaction_network and @network_component macros reuse minimal amount of code (where as previously it the second was basically ctrl+copied versions of the first.
  • Add a bunch of error checks to handle things which previously went through but shouldn't.

I also add some tests of all the various ways to create models via the DSL, mostly stuff that was not tested before.

src/Catalyst.jl Outdated Show resolved Hide resolved
@TorkelE TorkelE changed the title Refactor "srcd/sl.jl" file [wip] Refactor "srcd/sl.jl" file Jul 13, 2024
@TorkelE TorkelE force-pushed the src___refactoring___dsl_file branch from 3f92a31 to b6ba044 Compare July 13, 2024 23:09
src/dsl.jl Show resolved Hide resolved
src/dsl.jl Outdated Show resolved Hide resolved
src/dsl.jl Show resolved Hide resolved
src/dsl.jl Outdated Show resolved Hide resolved
src/dsl.jl Show resolved Hide resolved
src/dsl.jl Outdated
variables = vcat(variables_declared, vars_extracted)

# handle independent variables
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Part of the organisations so that options are handled together (in two sets, some before and some after the reactions are considered, depending on whichever is possible for which option)

src/dsl.jl Show resolved Hide resolved
src/dsl.jl Outdated Show resolved Hide resolved
src/dsl.jl Show resolved Hide resolved
src/dsl.jl Outdated
symvec = gensym()
ex = quote
$symvec = $ex
expr = quote
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in some places we used ex and some expr, here I just made it uniform

isequivalent(rs_empty_1, rs_empty)
rs_empty_2 == rs_empty
rs_empty_3 == rs_empty
end
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WHen I remade how the macor inputs are handled at the top level (nothing, name, reactions, name + reactions) I wanted to add some tests that all of this works for all cases and both macros.

@TorkelE TorkelE changed the title [Wip] Refactor "srcd/sl.jl" file [Wip] Refactor "src/dsl.jl" file Jan 18, 2025
allunique(syms) ||
error("Reaction network independent variables, parameters, species, and variables must all have distinct names, but a duplicate has been detected. ")
nothing
end
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now only used in one place, there implemented directly.

(length(expr.args) > 3) &&
error("An option input ($expr) is misformatted. Potentially, it has multiple inputs on a single lines, and these should be split across multiple lines using a `begin ... end` block.")
return expr.args[3]
end
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Helper function for handling error checks across multiple options.

sexprs = get_sexpr([species], Dict{Symbol, Expr}())
pexprs = get_pexpr(parameters, Dict{Symbol, Expr}())
sexprs = get_usexpr([species], Dict{Symbol, Expr}())
pexprs = get_psexpr(parameters, Dict{Symbol, Expr}())
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uses new names in the DSL file

# Tests error when disallowed name is used for variable.
let
@test_throws Exception @eval @reaction_network begin
@variables π(t)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new test

probODE = ODEProblem(rn, args...; kwargs...) # Using multiple dispatch the reaction network can be used as input to create ODE, SDE and Jump problems.
probSDE = SDEProblem(rn, args...; kwargs...)
probJump = JumpProblem(prob,aggregator::Direct,rn)
"""
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first documentation of @reactio_network, but now not even a docstring and just a weird remnant. remove.

probJump = JumpProblem(prob,aggregator::Direct,rn)
"""

### Constant Declarations ###
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not removed, now just line 1 and git got confused.

(sum(length, [reaction_lines, option_lines]) != length(ex.args)) &&
error("@reaction_network input contain $(length(ex.args) - sum(length.([reaction_lines,option_lines]))) malformed lines.")
any(!in(option_keys), keys(options)) &&
error("The following unsupported options were used: $(filter(opt_in->!in(opt_in,option_keys), keys(options)))")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Step one, read the macro input and check that it is correctly formatted.

if !allunique(syms_declared)
nonunique_syms = [s for s in syms_declared if count(x -> x == s, syms_declared) > 1]
error("The following symbols $(unique(nonunique_syms)) have explicitly been declared as multiple types of components (e.g. occur in at least two of the `@species`, `@parameters`, `@variables`, `@ivs`, `@compounds`, `@differentials`). This is not allowed.")
end
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Step 2, read all options that explicitly declares symbols as stuff.

continuous_events_expr = read_events_option(options, :continuous_events)
discrete_events_expr = read_events_option(options, :discrete_events)
default_reaction_metadata = read_default_noise_scaling_option(options)
combinatoric_ratelaws = read_combinatoric_ratelaws_option(options)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Step 4, read the other options.

spsexpr, spsvar = scalarize_macro(spsexpr_init, "specs")
vsexpr, vsvar = scalarize_macro(vsexpr_init, "vars")
cmpsexpr, cmpsvar = scalarize_macro(cmpexpr_init, "comps")
rxsexprs = get_rxexprs(reactions, equations, all_syms)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Step 5, creates the various expressions to put in the macro.

end
union!(excluded_syms, species)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

union! replaces foreach(s -> push!(excluded_syms, s), species)

@test_throws Exception @eval @reaction_network begin
@combinatoric_ratelaws false false
d, 3X --> 0
end
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checks that new error checks work (don't think the one above actually errored either, but it should)

Here, `@reaction` is followed by a single line consisting of three parts:
- A rate (at which the reaction occurs).
- Any number of substrates (which are consumed by the reaction).
- Any number of products (which are produced by the reaction).
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This bit

Here, `@reaction` is followed by a single line consisting of three parts:
- A rate (at which the reaction occurs).
- Any number of substrates (which are consumed by the reaction).
- Any number of products (which are produced by the reaction).

is essentially a repeat of previous documentation. Probably unnecessary for most people and only relevant if we wish to keep this section self contained. happy to remove though.

@test_throws Exception @eval @reaction_network begin
d, X --> 0, [misc=>:misc; description="description"]
end
end
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of several new sets of tests for stuff which we previously didn't actually test

@test_throws LoadError @eval @reaction im, 0 --> B
@test_throws LoadError @eval @reaction nothing, 0 --> B
@test_throws LoadError @eval @reaction k, 0 --> im
@test_throws LoadError @eval @reaction k, 0 --> nothing
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

forbidden symbol tests now tested more extensively in a test block two blocks down ("# Check that forbidden symbols correctly generates errors"

syms_inferred = union(sps_inferred, ps_inferred, vs_inferred, diffs_inferred)
all_syms = union(syms_declared, syms_inferred)
obsexpr, obs_eqs, obs_syms = read_observed_option(options, ivs,
union(sps_declared, vs_declared), all_syms; requiredec)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Step 3: Read all reactions and equations. Finds all symbols that are inferred as something.

function escape_equation!(eqexpr::Expr, all_syms)
eqexpr.args[2] = recursive_escape_functions!(eqexpr.args[2], all_syms)
eqexpr.args[3] = recursive_escape_functions!(eqexpr.args[3], all_syms)
eqexpr
end
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

escape equations is called by get_rxexprs


# Checks for input errors.
# Checks for input errors. Needed here but not in `@reaction_network` as `ReactionSystem` perform this check but `Reaction` don't.
forbidden_symbol_check(union(species, parameters))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For @reaction_network this check is not needed as ReactionSystem does a similar one. We might consider whether Reaction should also perform this type of check (and we remove it from here entirely.

E.g. this works:

@parameters Γ
@species X(t)
Reaction(Γ, [X], [])

while this errors:

@reaction Γ, X --> 0

@TorkelE
Copy link
Member Author

TorkelE commented Jan 20, 2025

This should be ready now. However, Plots fails on precompilation, so have to wait until that is fixed.

Not high priority though, doesn't actually change anything (but should make further updates to the DSL easier).

Once this PR is merged, I will have a follow-up one which reorders the option handling functions to follow the order with which they are called.

@TorkelE TorkelE changed the title [Wip] Refactor "src/dsl.jl" file Refactor "src/dsl.jl" file Jan 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants