Skip to content

Extended Rearrangement#3

Merged
agarny merged 27 commits into
stagingfrom
extended-rearrangement
Dec 18, 2025
Merged

Extended Rearrangement#3
agarny merged 27 commits into
stagingfrom
extended-rearrangement

Conversation

@RLee64
Copy link
Copy Markdown
Owner

@RLee64 RLee64 commented Dec 15, 2025

Overview

In #1 we resolved the rearrangement example seen in cellml#1354 for the trivial x = y + z case. However, we want to expand upon this functionality in order to support more operations. As such, this pull request focuses on growing the existing level of support for equation rearrangement, expanding functionality to other use cases. That being said, this implementation does not fully cover all libcellml supported types, but we hope to expand upon this in an additional pull request.

Here we also begin to build a set of proper test cases for us to ensure SymEngine's rearrangement functionality is behaving as we intend.

Changes

  • Added test cases for equation rearrangement (originally written by GPT, but I've adjusted files to fix errors and hopefully cover more edge cases)
  • Parsing from SymEngine back to AST now supports SymEngine expressions with 3+ children
  • Rearrangement support for addition and subtraction
  • Rearrangement support for unary +/-
  • Rearrangement support for multiplication and division
  • Rearrangement support for basic trigonometric rearrangement (when the unknown variable is not inside a trig function)
  • Rearrangement support for various constants (i.e. e, pi, inf)
  • Rearrangement support for different number 'types' (i.e. doubles and scientific notation)
  • Rearrangement support for polynomials with one real solution
  • In order to achieve polynomial rearrangement support, the method isSymEngineExpressionComplex was introduced to recursively look for complex constituents. This is consequently used to remove complex equations from our solution set.

Notes

  • Since SymEngine occasionally throws exceptions when the system is unable to rearrange an equation (e.g. when needing to rearrange tan to atan or having to work with fractional polynomials), I'm guessing we'll probably want to catch these errors at some point to ensure that these errors don't terminate code execution just because rearrangement wasn't successful. With that in mind, I haven't done it yet since getting symengine errors is useful for discovering the library's limitations.
  • Similar to the previous PR, we're once again failing some existing test cases. At a quick glance, it seems that the unordered algebraic system is running into an issue with variables now being underconstrained and the hodgkin huxley model tests now have some equations interpreted as algebraic. I'll have a deeper look into these to get a better idea of what's going on.
image
  • Not all of the new test cases currently pass, but this PR is probably big enough as is, so I'm hoping to finish them off in a third branch that wraps up rearrangement (at least for the time being).
image

Mostly GPT generated test cases
Test case has been superseded by the newly added test suite to more robustly test for equation rearrangement
Previous system assumed that symengine expressions contained only 0-2 children, but in reality it could be any whole number. This adjusts the existing conversion logic to account for this.
Made it so that we also now consider mathml unary +/- operators
Can now handle unary plus, minus, unary minus, and CN types from AST (which means code now passes Analyser.rearrangeAdditiveEquations)
Had an error at equation 4

Also added brackets to equation comments to make things more clear
Now passes Analyser.rearrangeMultiplicativeEquations
Now covers a greater variety of cases
Symengine is not capable of rearranging trig functions into inverse trig functions (e.g. tan(x) = y cannot become x = atan(y))
Now has better Eq 1 test case and more consistent variable naming
Now supports
- Decimal point values (i.e. doubles)
- Constants (E, pi, and inf)
We need to ensure that there can only be one real solution for each
Some specific things had to be added to handle this
- CN representing integers must be appropriately converted since symengine requires exponentials to be whole numbers
- We need to filter out real from non-real solutions since we assume users will want to ignore the complex domain in most cases
Now assumes left child will always be the non-null component
@RLee64 RLee64 requested a review from agarny December 15, 2025 22:37
Copy link
Copy Markdown
Collaborator

@agarny agarny left a comment

Choose a reason for hiding this comment

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

  • In your tests, in addition to confirming that a model is of algebraic type, it would be good to confirm that its equation looks the way we would expect. For this, you could use Generator::equationCode().
  • No need to have our CellML files named unarranged_xxx.cellml. They can simply be named xxx.cellml since they are located under the symengine folder.
  • For the different equations you are testing, it would be nice to have a comment on why they are being tested.

Comment thread src/analyser.cpp
Comment thread src/analyser.cpp Outdated
Comment thread src/analyser.cpp Outdated
Comment thread tests/resources/analyser/symengine/unarranged_polynomials.cellml Outdated
Comment thread tests/resources/analyser/symengine/unarranged_combination.cellml Outdated
I can't believe I didn't get an error for this sooner!!!
- Added comments
- Tried to give each test case a more 'unique' purpose
Also moved initialising constants to the bottom of the mathml block so we guarantee that our tested equation range always starts at 0
Copy link
Copy Markdown
Owner Author

@RLee64 RLee64 left a comment

Choose a reason for hiding this comment

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

In your tests, in addition to confirming that a model is of algebraic type, it would be good to confirm that its equation looks the way we would expect. For this, you could use Generator::equationCode().

ec0ace2

No need to have our CellML files named unarranged_xxx.cellml. They can simply be named xxx.cellml since they are located under the symengine folder.

f8a39f5

For the different equations you are testing, it would be nice to have a comment on why they are being tested.

fc1cf1c

In addition to these changes I've also done the following

  • Cleaned up the trigonometric test case so it's only testing for functionality we know will pass in symengine's current state (i.e. no operations needed to inverse functions). d79d8fc
  • Fixed an issue where unary functions weren't being properly converted back (this wasn't picked up since we hadn't encountered symengine outputting unary functions until the proper trigonometric test case) aab7d89
  • Fixed issue where ast children weren't being assigned their parents (this one I'm just embarrased I hadn't noticed sooner) 9c1e0b8

Comment thread src/analyser.cpp Outdated
Comment thread src/analyser.cpp Outdated
Comment thread tests/resources/analyser/symengine/unarranged_combination.cellml Outdated
Comment thread tests/resources/analyser/symengine/unarranged_polynomials.cellml Outdated
Comment thread src/analyser.cpp
Copy link
Copy Markdown
Collaborator

@agarny agarny left a comment

Choose a reason for hiding this comment

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

Approving, but... at some point, we will need to ensure that ALL tests pass, incl. coverage tests, memory checks, etc.

@agarny agarny merged commit 7c34ff2 into staging Dec 18, 2025
1 check passed
@RLee64 RLee64 deleted the extended-rearrangement branch December 18, 2025 02:44
This was referenced Dec 18, 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