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

Interesting behavior when modifying init species steady state #1241

Open
ledwmp opened this issue Jan 10, 2025 · 3 comments
Open

Interesting behavior when modifying init species steady state #1241

ledwmp opened this issue Jan 10, 2025 · 3 comments

Comments

@ledwmp
Copy link

ledwmp commented Jan 10, 2025

Hi all,

I'm unsure if this is unexpected behavior, or if I'm not understanding how to properly set init variables for a species when solving for steady states.

What I'd like to do is modify species init and solve for a bunch of steady states of a pre-specified model that is loaded from sbml:

import roadrunner

sbml = """
<?xml version="1.0" encoding="UTF-8"?>
<sbml xmlns="http://www.sbml.org/sbml/level3/version2/core" level="3" version="2">
  <model name="_interactive_">
    <listOfCompartments>
      <compartment id="default" spatialDimensions="3" size="1" constant="true"/>
    </listOfCompartments>
    <listOfSpecies>
      <species id="__s0" name="A(bind=None)" compartment="default" hasOnlySubstanceUnits="true" boundaryCondition="false" constant="false"/>
      <species id="__s1" name="B(bind=None)" compartment="default" hasOnlySubstanceUnits="true" boundaryCondition="false" constant="false"/>
      <species id="__s2" name="A(bind=1) ._br_B(bind=1)" compartment="default" initialAmount="0" hasOnlySubstanceUnits="true" boundaryCondition="false" constant="false"/>
    </listOfSpecies>
    <listOfParameters>
      <parameter id="kf" name="kf" value="0.001" constant="true"/>
      <parameter id="kr" name="kr" value="0.01" constant="true"/>
      <parameter id="A_0" name="A_0" value="100" constant="true"/>
      <parameter id="B_0" name="B_0" value="50" constant="true"/>
      <parameter id="__obs0" name="A_free" constant="false"/>
      <parameter id="__obs1" name="B_free" constant="false"/>
      <parameter id="__obs2" name="AB_complex" constant="false"/>
    </listOfParameters>
    <listOfInitialAssignments>
      <initialAssignment symbol="__s0">
        <math xmlns="http://www.w3.org/1998/Math/MathML">
          <ci> A_0 </ci>
        </math>
      </initialAssignment>
      <initialAssignment symbol="__s1">
        <math xmlns="http://www.w3.org/1998/Math/MathML">
          <ci> B_0 </ci>
        </math>
      </initialAssignment>
    </listOfInitialAssignments>
    <listOfRules>
      <assignmentRule variable="__obs0">
        <math xmlns="http://www.w3.org/1998/Math/MathML">
          <ci> __s0 </ci>
        </math>
      </assignmentRule>
      <assignmentRule variable="__obs1">
        <math xmlns="http://www.w3.org/1998/Math/MathML">
          <ci> __s1 </ci>
        </math>
      </assignmentRule>
      <assignmentRule variable="__obs2">
        <math xmlns="http://www.w3.org/1998/Math/MathML">
          <ci> __s2 </ci>
        </math>
      </assignmentRule>
    </listOfRules>
    <listOfReactions>
      <reaction id="r0" name="A_binds_B" reversible="true">
        <listOfReactants>
          <speciesReference species="__s0" constant="true"/>
          <speciesReference species="__s1" constant="true"/>
        </listOfReactants>
        <listOfProducts>
          <speciesReference species="__s2" constant="true"/>
        </listOfProducts>
        <kineticLaw>
          <math xmlns="http://www.w3.org/1998/Math/MathML">
            <apply>
              <minus/>
              <apply>
                <times/>
                <ci> kf </ci>
                <ci> __s0 </ci>
                <ci> __s1 </ci>
              </apply>
              <apply>
                <times/>
                <ci> kr </ci>
                <ci> __s2 </ci>
              </apply>
            </apply>
          </math>
        </kineticLaw>
      </reaction>
    </listOfReactions>
  </model>
</sbml>
""".strip()


def main() -> None:
    rr = roadrunner.RoadRunner(sbml)
    print(rr.steadyState())
    print(rr['__s0'], rr['__s1'], rr['__s2'])
    print(rr['init(__s0)'], rr['init(__s1)'])
    print()

    rr = roadrunner.RoadRunner(sbml)
    rr['init(__s0)'] = 200
    print(rr.steadyState())
    print(rr['__s0'], rr['__s1'], rr['__s2'])
    print(rr['init(__s0)'], rr['init(__s1)'])
    print()

    rr = roadrunner.RoadRunner(sbml)
    rr['init(__s1)'] = 200
    print(rr.steadyState())
    print(rr['__s0'], rr['__s1'], rr['__s2'])
    print(rr['init(__s0)'], rr['init(__s1)'])
    print()
    
    rr = roadrunner.RoadRunner(sbml)
    s = rr.simulate(0,100,1001)
    print(s['[__s0]'][-1], s['[__s1]'][-1], s['[__s2]'][-1])

    rr = roadrunner.RoadRunner(sbml)
    rr['init(__s0)'] = 200
    s = rr.simulate(0,100,1001)
    print(s['[__s0]'][-1], s['[__s1]'][-1], s['[__s2]'][-1])

    rr = roadrunner.RoadRunner(sbml)
    rr['init(__s1)'] = 200
    s = rr.simulate(0,100,1001)
    print(s['[__s0]'][-1], s['[__s1]'][-1], s['[__s2]'][-1])

if __name__ == '__main__':
    main()

Running this script on my machine results in this output:

4.0023540037736893e-14
57.41657386773995 7.416573867739949 42.58342613226005
100.0 50.0

7.947343599049524e-15
1.324557266508251e-13 50.000000000000135 -1.324557266508251e-13
200.0 50.0

0.0
100.0 0.0 0.0
100.0 0.0

57.431853646474515 7.431853646474576 42.56814635352546
153.0662453134638 3.0662453134638703 46.93375468653606
12.268216200038605 112.26821620003845 137.73178379996145

It appears something is going on in the steady state solver, perhaps an underflow or overflow where the species concentration is set to 0 or very close to zero during steady state computation.

If I'm abusing the usage of libroadrunner or misunderstanding the usage in any way, please let me know, just trying to get to the bottom of this.

libroadrunner==2.7.0 installed via pypi on python3.9

**edited to change call to getSteadyStateValues to just outputing species from first steadystatecomputation

@ledwmp
Copy link
Author

ledwmp commented Jan 10, 2025

I'll also add that removing the initialassignment and re-adding with updated parameter seems to get around this issue, where the steady state values mimic final concentrations of a simulation:

rr.removeInitialAssignment('__s0', False)
rr.addInitialAssignment('__s0', str(200), True)

@luciansmith
Copy link

Often in cases like this, the culprit turns out to be the conservedMoietyAnalysis flag, which will notice that (say) S1+S2 is constant, so if one is changed, it'll change the other to compensate. But that doesn't seem to be the case here! I would say that this is simply a bug in roadrunner somewhere. I'm glad you found a workaround for now; I'll look into seeing how we can fix it on our end. @adelhpour , do you have time to investigate? You worked on the conserved moieties in the past, and I think this is related.

@adelhpour
Copy link
Member

@luciansmith I’ll look into it and update you on what I find.

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

No branches or pull requests

3 participants