Simplify.jl icon indicating copy to clipboard operation
Simplify.jl copied to clipboard

Distributivity not assumed

Open timziebart opened this issue 6 years ago • 3 comments

Hi, I was just playing around and realized, that distributivity is semingly not assumed (by standard). How can I switch it on? For Example in

julia> @term((x+y)*(x+y) - x^2)
@term((x + y) * (x + y) - x ^ 2)

I would actually expect something like

@term(y ^ 2 + 2 * x * y)

timziebart avatar Aug 15 '18 21:08 timziebart

TL;DR: Distributivity is hard, and applying it well in practice is somewhat unclear. It's a difficult problem to tackle, but a medium-term #TODO.


Dealing with distributivity is a tough philosophical question, even before you get to the code. :slightly_smiling_face: It's hard to agree whether factored or expanded form is simpler, from a generic standpoint.

  • It's easier to visually parse the information given by 8x^3 + 12x^2 + 6x + 1 by factoring to (2x + 1)^3. (It could be argued that the expanded form is easier to mentally differentiate, though?)
  • It's easier to visually parse the information given by (x-1) * (x+1) * (x^2 + 1) by expanding to x^4 - 1.

In this case, "simplicity" isn't immediately clear, at least without examining each expression on a case-by-case basis (or by both factoring and expanding and using some metric to determine which one is better).

However, let's say we decide that one form is simpler:

  • If expanded form is simpler, we can simply register a couple more rules, namely x * (a + b) => x*a + x*b and (a + b) * x => a*x + b*x. The existing rules should take care of cleaning up the remaining expression.
  • If factored form is simpler, things become a bit trickier. We could try adding the inverse of the previous rules, but that only works when constants haven't been "squashed" already. (For example, if the expanded form of (x+1) * (x+2) is derived to be x^2 + x*2 + 1x + 1*2, we have no issues. But once the result is simplified to x^2 + 3x + 2, reversing the process becomes challenging.)

One of the best known ways for dealing with polynomial factoring problems is the use of a Gröbner Basis, which would ideally have logic contained in a separate package but be able to operate on an existing Term object (or an optimized data translation). Then, the user could explicitly call factor or expand on their expressions, or we could attempt to automatically determine a simpler form. This type of capability is planned and is significantly influencing the upcoming specializations/strategy API.

HarrisonGrodin avatar Aug 15 '18 22:08 HarrisonGrodin

From my perspective, you showed more how simplifying a term could be a subjective matter. If one cares about normalization only, that should not be important as long as there is a strict normalization rule, right? I want to use this mostly for comparison of terms so, e.g. the expanded form would be okai as long as I can make sure two differently written but equal terms normalize to the same.

timziebart avatar Aug 19 '18 19:08 timziebart

The subjectivity is only the reason why we don't (currently) include any mention of the distributive law in the standard rule set. If the expanded form is okay, though, I think adding the left- and right-distributive rules I mentioned should solve the problem. If factored form is preferred, though, some more complex logic is required (likely in the form of a custom FactorRule <: Rule).

HarrisonGrodin avatar Aug 20 '18 12:08 HarrisonGrodin