This PR changes the Multiply and Add operations to support any number of arguments for faster evaluation and more efficient simplifications.
For operations organized in a tree such as (A + B) + (C + D) it is difficult to discover relevant structures, for instance A and D having matching sparsity. In the current form, the only way to properly discover this is if (A + B)._add(C + D) dispatches to A._add(C + D) as well as the reverse (C + D)._add(A), and from there to D._add(A). While fuctional, it is impossible to avoid redundancy (C + D)._add(A + B) will explore most of the same combinations - a problem that grows rapidly with the depth of the tree. By moving to a flat structure A + B + C + D it is trivial to find patterns with minimal effort. Moreover, most simplifications currently defined on Add and Multiply are already valid for multiple arguments, so the new structure does not add complexity.
This PR changes the Multiply and Add operations to support any number of arguments for faster evaluation and more efficient simplifications.
For operations organized in a tree such as
(A + B) + (C + D)
it is difficult to discover relevant structures, for instanceA
andD
having matching sparsity. In the current form, the only way to properly discover this is if(A + B)._add(C + D)
dispatches toA._add(C + D)
as well as the reverse(C + D)._add(A)
, and from there toD._add(A)
. While fuctional, it is impossible to avoid redundancy(C + D)._add(A + B)
will explore most of the same combinations - a problem that grows rapidly with the depth of the tree. By moving to a flat structureA + B + C + D
it is trivial to find patterns with minimal effort. Moreover, most simplifications currently defined onAdd
andMultiply
are already valid for multiple arguments, so the new structure does not add complexity.