Skip to content

feat: add pass which removes equations incident on a single variable#4454

Draft
AayushSabharwal wants to merge 1 commit intomasterfrom
as/remove-constant-eqs
Draft

feat: add pass which removes equations incident on a single variable#4454
AayushSabharwal wants to merge 1 commit intomasterfrom
as/remove-constant-eqs

Conversation

@AayushSabharwal
Copy link
Copy Markdown
Member

This avoids cases where pantelides ends up choosing a bad matching and unnecessarily differentiates the kind of equations removed by this pass.

Comment thread src/systems/alias_elimination.jl Outdated
union!(eqs_to_substitute, 𝑑neighbors(graph, ivar))

v = var_to_diff[ivar]
while v isa Int
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

would this be more readable if it was while !isnothing(v)?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I was hoping isa Int would help type inference better. And iirc since v::Union{Int, Nothing}, codegen will union-split the call to isnothing whereas isa is a builtin, so there's only ever one thing to call.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Also this is just personal preference but I like reading var === nothing over isnothing(var).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'd also be fine with !(isa Nothing). isa Int just feels kind of fragile (e.g. it would break if we changed incidence to Int32)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ah, I see your point.

Comment thread src/systems/alias_elimination.jl
for ieq in 𝑠vertices(graph)
empty!(snbors)
append!(snbors, 𝑠neighbors(graph, ieq))
setdiff!(snbors, vars_to_rm_set)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

is this needed to prevent needing to recompute the neighbors after each variable removal? IMO it could use a comment if so.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Will add a comment (and just spam some more in general)

@AayushSabharwal
Copy link
Copy Markdown
Member Author

I also just realized that this pass doesn't need to substitute, since if the eliminated variable is removed from fullvars we'll end up treating it like a parameter. The perfect aliases pass needs to substitute because we change incidence for the eliminated variable to its alias, so the alias needs to be symbolically present in the equation.

@oscardssmith
Copy link
Copy Markdown
Member

That's a very nice simplification!

@AayushSabharwal AayushSabharwal force-pushed the as/remove-constant-eqs branch from b3183de to cca4564 Compare April 15, 2026 15:36
@AayushSabharwal
Copy link
Copy Markdown
Member Author

Addressed the comments

@AayushSabharwal AayushSabharwal marked this pull request as draft April 15, 2026 15:38
@AayushSabharwal
Copy link
Copy Markdown
Member Author

AayushSabharwal commented Apr 15, 2026

A multibody model is now simplifying to 25 variables instead of 17 because of the latest changes on this PR.

@oscardssmith
Copy link
Copy Markdown
Member

any idea what the difference is?

@AayushSabharwal
Copy link
Copy Markdown
Member Author

A bunch of algebraic equations that should have been torn but weren't.

@oscardssmith
Copy link
Copy Markdown
Member

We also need to make sure to deal with #4458 for this (and add a test)

@AayushSabharwal
Copy link
Copy Markdown
Member Author

Okay, we do need to substitute. If we eliminate a variable v, and var_to_diff[v] !== nothing, that means the symbolic expression D(fullvars[v]) is present in some equation. Observed equations can't have D(...) on the LHS, so we need to substitute to handle this case. Substitution time complexity doesn't scale with the number of entries in the Dict, so if we need to substitute derivatives we might as well substitute the entire thing.

@AayushSabharwal
Copy link
Copy Markdown
Member Author

AayushSabharwal commented Apr 17, 2026

The problematic multibody system is handled by changing the tearing algorithm to the old ModiaTearing. It's possible I implemented the new tearing algorithm wrong? Will double check, but I don't think I did.

@AayushSabharwal
Copy link
Copy Markdown
Member Author

Weirdly either CarpanzanoTearing without this pass, or ModiaTearing with this pass works.

@AayushSabharwal
Copy link
Copy Markdown
Member Author

I'm certain though, there was a point where this pass + CarpanzanoTearing was perfectly fine.

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