I believe that TransformationFunctions
are supposed to be unambiguous, i.e. they are supposed to return one and the same result each time they are called with the same argument, not AnyOfThese
.
Therefore, to ask Simplify
TryAnyOfThese
I suppose there is no other option but to introduce n
, which specifies the branch somehow. Consider the following example:
ClearAll[branch];
branch[n_Integer][multi_l] /; Length[multi] >= n := multi[[n]];
branch[_Integer][multi_l] := multi;
Here I replaced the general List
head with more specific l
in order not to confuse accidentally our toy object with some "usual" List
, like a vector. Now branch[n]
is a function which extracts n
-th branch if possible and returns a whole object untouched otherwise, so that we can ask Simplify
try many branches even if they don't exist for some of the l
objects in our expresson.
Simplify[
l[f[g[x]], g[x]] + l[f[g[x]], g[x], x],
TransformationFunctions -> Prepend[Array[branch, 10], Automatic]
]
(*Returns x + g[x]*)
EDIT
No, it doesn't work. I've chosen a good example, when the simplest expression comes last. This example
Simplify[
l[x, g[x], f[g[x]]],
TransformationFunctions -> Prepend[Array[branch, 10], Automatic]]
]
(*Returns: f[g[x]]*)
shows that Simplify
will just pickup the first "working" branch. Well, it means that one will have to track all branches manually. For this purpose:
- The branch object
l
will now have the form l[choices, var]
, where choices
is a List
of possible branches of the object and var
is a unique variable. This unique variable will prevent expressions such as l[...]+l[...]
form evaluating to 2 l[...]
.
- All possible combinations of branches are generated and the one with minimal
LeafCount
after Simplify
is selected.
Here is the code:
ClearAll[branches];
branches[expr_] := First @ MinimalBy[
Simplify /@ ReplaceAll[
ReplaceAll[
expr,
l[_, var_] :> var
],
Tuples[
Cases[
expr,
l[choices_, var_] :> Thread[var -> choices],
{0, Infinity}
]
]
],
LeafCount
]
And here is how it works:
branches[
l[{x, -x}, Unique[]] + l[{x, -x}, Unique[]]
]
branches[
l[{x, -x}, Unique[]] + l[{-x, x}, Unique[]]
]
(*Returns 0 and 0*)
Now the order of the choices doesn't matter. In order not to create unique variables each time manually (and not to leave them in memory), the following definition can be given:
l[choices_] := Module[{id}, l[choices, id]]