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

Add and Mul are associative. Let's make them canonical #413

Merged
merged 3 commits into from
Oct 27, 2023

Conversation

msooseth
Copy link
Collaborator

Description

As per @zoep 's idea, Mul is associative. So we should make Mul+Mul canonical. This fixes #408 . That issue also mentions Add. Doing that too.

I added an automated test for the Mul associativity, as that's not obvious I think. Anyway, now it's proven correct.

Checklist

  • tested locally
  • added automated tests
  • updated the docs
  • updated the changelog

src/EVM/Expr.hs Outdated
@@ -880,6 +880,9 @@ simplify e = if (mapExpr go e == e)
| b == c = a
| otherwise = sub (add a b) c

-- Add is associative
go (Add (Add a b) c) = add a (add b c)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I am wondering if there is a way to do this only if it is beneficial.

For instance if the initial expression is (Lit 17 + Lit 42) + x then rearranging the expression will miss an opportunity for further simplification.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oh wow, good point! I think we should be canonical, so it should eventually always be done. But you are right that here we are very much missing an opportunity. What about this (for both Add and Mul):

    -- Add is associative
    go (Add (Add a b) c) = add a (add b c)
    go (Add (Lit a) (Add (Lit b) x) = add (Lit (a+b) x

Notice that the second Add will always have Lit as 1st argument thanks to canonicalization done by add (in case any of its arguments are a Lit). The above ensures that if eventually somehow, the second Add's any argument becomes a Lit and the 1st Add's 1st argument becomes a Lit then we simplify.

This should work for Mul as well. The only special case there is Mul by Lit 0 and Lit 1, but that work with and 2nd argument, so the 2nd argument can be another Mul.

What do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes! I think adding this rule would be great!

Copy link
Collaborator

@d-xo d-xo left a comment

Choose a reason for hiding this comment

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

looks good!

@msooseth msooseth force-pushed the associative-add-mul branch from 153a4ce to 85301db Compare October 27, 2023 09:55
Copy link
Collaborator

@zoep zoep left a comment

Choose a reason for hiding this comment

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

Looks great!

@msooseth msooseth merged commit 26875ad into main Oct 27, 2023
7 checks passed
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.

Use associativity both Mul and Add to make it easier to compare equivalent Expr-s
3 participants