How to make DifferenceRoot and RecurrenceTable useful for non-numeric difference equations?

In response to a question from the physics forum, today I came across really bad results DifferenceRootand RecurrenceTable, compared to calculating expressions, naively taking derivatives of an exponential generating functional. A very small amount of digging showed that DifferenceRootthey RecurrenceTabledid not simplify the expressions as they appeared.

For example, look at the following conclusion RecurrenceTableand how it is simplified only with the help of the Expandresult:

In[1]:= RecurrenceTable[f[n] == a f[n - 1] + (a - 1) f[n - 2] && 
                        f[0] == 0 && f[1] == 1, 
                        f, {n, 6}]
% // Expand

Out[1]= {0, 1, a, -1+a+a^2, -a+a^2+a (-1+a+a^2), 1-a-a^2+a (-1+a+a^2)+a (-a+a^2+a (-1+a+a^2))}
Out[2]= {0, 1, a, -1+a+a^2, -2 a+2 a^2+a^3, 1-2 a-2 a^2+3 a^3+a^4}

This quickly gets out of hand, as counting the leaves of the 20th iteration (calculated using DifferenceRoot) shows:

dr[k_] := DifferenceRoot[Function[{f, n}, 
          {f[n] == a f[n - 1] + (a - 1) f[n - 2], f[0] == 0, f[1] == 1}]][k]

In[2]:= dr20 = dr[20]; // Timing
        dr20Exp = Expand[dr20]; // Timing
Out[2]= {0.26, Null}
Out[3]= {2.39, Null}

In[4]:= {LeafCount[dr20], LeafCount[dr20Exp]}
Out[4]= {1188383, 92}

What can be compared with a memoized implementation

In[1]:= mem[n_] := a mem[n-1] + (a-1) mem[n-2] // Expand
        mem[0] = 0; mem[1] = 1;

In[3]:= mem20 = mem[20];//Timing
        LeafCount[mem20]
Out[3]= {0.48, Null}
Out[4]= 92

, : - /, DifferenceRoot RecurrenceTable () , , ?

: , RSolve . DifferenceRoot RecurrenceTable. , , f[n-2] n, .

+5
1

, , . RSolve ? :

sol = f /. RSolve[f[n] == a f[n - 1] + (a - 1) f[n - 2] && 
                  f[0] == 0 && f[1] == 1, f, n
           ][[1, 1]]

enter image description here

sol@Range[6] // Simplify

enter image description here

+1

All Articles