I'd like to programmatically construct a function from a long expression with many duplicate terms. The objective is to programmatically create a set of compiled functions with expressions that were previously created programmatically. This is somewhat related to Stack Exchange Question: How to speed up an optimization with very long symbolic expressions?
The question may be clarified with a minimal non-working example. The example is a bit silly, but it expresses the idea.
Suppose I have a list of expressions:
exampleTerms = {(x - y)^2, x y, (x - y)^4};
exprList = Expand /@ RandomChoice[exampleTerms, 10]
(*{x^4 - 4 x^3 y + 6 x^2 y^2 - 4 x y^3 + y^4,....}*)
Here is a list of terms that I'd like to precompute for insertion into a Function, or Compile:
vars =Union[Flatten[(List @@@ exprList) /. _?IntegerQ t_ :> t]]
(*{x y, x^3 y, x^2 y^2, x y^3}*)
Here is a list of rules pointing to intermediate variables:
assigments =
Thread[vars -> (Indexed[term, #] & /@ Range[Length[vars]])]
and here is what I want as the expr in Compile:
expr = exprList /. assigments
(*{x^2 -> Indexed[term, {1}], x^4 -> Indexed[term, {2}],
x y -> Indexed[term, {3}],...}*)
local = With[{termList = Indexed[term, #] & /@ Range[Length[vars]]},
MapThread[HoldForm[#1 = #2] &, {termList, vars}]]
Here is something that looks like what I want:
tmpF = Function[{x, y},
Evaluate[Block[Evaluate[local], Evaluate[expr]]]
]
But that fails because Block objects to the local variable assignment. (Also, the evaluates seem redundant, but it doesn't work if I remove them) It also fails if I don't use Indexed:
tmpF = Function[{x, y},
Evaluate[
Block[Evaluate[local /. Indexed[term, i_] :> term[i]],
Evaluate[expr]]]
]
Or, which seems to be to be a total kludge by creating my own symbol names:
localAlt = With[{termList =
ToExpression["term" <> ToString[#]] & /@ Range[Length[vars]]},
MapThread[HoldForm[#1 = #2] &, {termList, vars}]]
exprAlt =
expr /. Indexed[p_, i_] :> ToExpression[ToString[p] <> ToString[i]]
tmpF = Function[{x, y},
Evaluate[Block[localAlt, Evaluate[exprAlt]]]
]