Skip to content

-bscb appears to be required for reactant-side molecularity enforcement; -cb / complex=>1 is insufficient #51

Description

@wshlavacek

I ran into what appears to be an important gap between NFsim flag semantics and the behavior one would expect for reactant-side molecularity in bimolecular BNGL rules.

In short:

  • complex=>1 in BNGL maps to NFsim -cb
  • -cb turns on complex bookkeeping
  • but the actual reactant-side distinct-complex molecularity check appears to require -bscb, not plain -cb

This matters for models where a top-level + on the LHS is intended to mean "these reactant patterns must come from distinct complexes", as in cyclic crosslinking models.

Why this is surprising

For a bimolecular rule such as

A(a) + B(b) -> A(a!1).B(b!1) k

or, more importantly, for cyclic crosslinking rules where an LHS has separate reactant patterns that should not be matched within the same pre-existing connected complex, I would expect reactant-side molecularity to be enforced when complex bookkeeping is enabled.

However, in current NFsim source, plain -cb appears to be insufficient for that.

Source-level evidence

1. complex=>1 maps to -cb

In BioNetGen 2.9.3:

  • simulate_nf(..., complex=>1) maps to NFsim -cb
  • complex=>1 is already the default for simulate_nf

2. NFsim distinguishes -cb from -bscb

In src/NFsim.cpp, -bscb sets blockSameComplexBinding = true, while -cb separately sets turnOnComplexBookkeeping = true.

3. The actual transformation-set molecularity gate is wired to blockSameComplexBinding

In src/NFinput/NFinput.cpp, when reaction rules are initialized, NFsim does:

ts->setComplexBookkeeping( blockSameComplexBinding );

not

ts->setComplexBookkeeping( system_is_using_complex_bookkeeping );

4. ReactionClass::fire() checks molecularity through TransformationSet::checkMolecularity()

and in TransformationSet::checkMolecularity(), the full distinct-complex check is only taken when that transformation-set complex_bookkeeping flag is true.

Otherwise NFsim falls back to a weaker collision / overlap-style check rather than a full "distinct reactant complexes" check.

Practical consequence

For BNGL/NFsim users, this means:

  • complex=>1 / -cb is not enough if correctness depends on reactant-side distinct-complex enforcement
  • param=>"-bscb" is required

This is not obvious from the BNGL side, because complex=>1 sounds like it should be the relevant switch.

Minimal reproducer pattern

The problem is especially visible in cyclic crosslinking models, e.g. bivalent ligand / bivalent receptor models where a rule like

L(r!+,r) + R(l) -> L(r!+,r!1).R(l!1) kpx

must not match the R(l) from the same pre-existing complex when the intended chemistry is intermolecular crosslinking rather than an intracomplex closure via a bimolecular reactant match.

Without -bscb, NFsim appears able to admit matches that violate that intended reactant-side molecularity restriction. With -bscb, the resulting dynamics match the corresponding analytical theory much better.

Request

Could you clarify what the intended behavior is?

If the intended behavior is:

  • -cb = bookkeeping only
  • -bscb = bookkeeping + reactant-side distinct-complex enforcement

then I think this needs much clearer documentation, because it is very easy for BNGL users to assume that complex=>1 is the molecularity-relevant setting.

If instead the intended behavior is that ordinary reactant-side molecularity should already be enforced under -cb, then this may be a bug in how TransformationSet::setComplexBookkeeping() is wired during rule initialization.

I would be happy to provide a small BNGL reproducer if that would be useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions