I need to do the following. Suppose I have an array, c[ ]. I need to be able to specialize the elements of this array, and then later "clear" the elements, making them indeterminates again. I attempted to do this by creating a temporary holding array
i:='i': for i from 1 to 5 do d[i]:=c[i] end do;
i:='i': for i from 1 to 5 do c[i]:=i end do;
i:='i': for i from 1 to 5 do c[i]:=d[i] end do;
I expected and want the output to be
c[0] c[1] c[2] c[3] c[4] c[5] 1 2 3 4 5 c[0] c[1] c[2] c[3] c[4] c[5]
Instead, my output is
c[0] c[1] c[2] c[3] c[4] c[5] 1 2 3 4 5 1 2 3 4 5
in other words, the c[ ] remain specialized. Any suggestions how to do this?
Comments
evaln
Note that you do not need to clear variables used as loop counters, at least not for the loop.
I think the following does what you want.
[A[1], A[2], c]
Need to clear loop counters
One does indeed need to clear variables used as loop counters. I have experimented with that and proven that is necessary many times.
Thank you for the evaln function. I will try it.
There is no way I would have been able to look in the Help menu for the "evaln" function unless I already knew that it was able to clear array elements.
please give a counter-example
Please show an example where a loop counter must be cleared. Here is what I was referring:
i := 23:
for i to 3 do i end do;
1
2
3
By "loop counter" I mean the 'for' variable (i, above). At the exit of the loop i is assigned 4, but its value prior to entering the loop has no effect on the loop counter (unless that value is used in the 'from' or 'to' fields).
FYI I have requested (submitted a bug report) for evaln to be explicitly mentioned in the table help page. Currently there is a link to it there, in the See Also section, however, that does not suffice. Note that arrays (no capital) are deprecated, so do not expect to see that help page, array(deprecated), modified in the future.
"Resetting" a counter loop
# Desired output 1, 2, 3 s[i]
# Actual output: 1, 2, 3, s[4]
for i fro 1 to 3 do i end do;
s[i];
I have had more complicated examples than this,
such as when the counter loop is used again as a counter loop
in which I have had to "reset" the "i". I can't dig those up now.
(They're too long to type in.)
"Resetting" a counter loop
My errors tend to look like this...
for i from 1 to 5 do i; od;
1
2
3
4
5
sum(2,i=1..5);
Error, (in sum) summation variable previously assigned, second argument evaluates to 6 = 1 .. 5
sum(2,'i'=1..5);
10
---
G A Edgar
after, not before
Yes, however, reassigning the for-loop counter before the for-loop does not help here, which was my point. If you need to reassign the variable after the loop, then do so. Of course, in the simple example above you would be better served with the add procedure, which does not require resetting the variable, in place of the sum, which does.
local counter
Yes, ?add states:
But why the for-loop cannot be changed to use a local index also? It would be better to adapt the software to the way the users think than adapt the users to think the way the developers did it.
we don't think alike
While it could be done, it would break a lot of code. It is frequently useful to know the last counter value after exiting from a loop. Consider, for example
When (and if) the loop exits, the value of i is the value that caused the exit. If i were local to the loop, then we would have to do
or something similar.
An interesting alternative would be to have a finally clause for a loop. Then one could do
Thank you, Edgar!
THANK you for recreating the error message that I get all the time.
The "evaluates to 6=1..5" thing.
add/sum
If you get this a lot, it might be because you are using sum where you should/could be using add.
you have a table, not an array
Your initial construction of c produces a table, not an array.
for i from 1 to 5 do c[i]:=i end do;
type(c,table);
true
type(c,array);
false
Thus you can clear c by simply assigning it to be the null table:
c:=table([ ]);
There is no need for your "holding array" d.
Thanks to all for your help: next problem...
My next problem is to COLLECT all the like powers of c[0,j,0,l] and c[i,0,k,0]. Actually, there are no powers. My output (all it R) is a LINEAR combination of assorted TABLE elements c[0,j,0,l] and c[i,0,k,0] for i,j,k,l in the range 1 through 5. 5 is about the largest range I can choose before my computer completely hangs up. It has to set up storage space for 5^4 c[i,0,k,0]'s and c[0,j,0,l]'s.
R = Linear combinations of these c[ ] elements over polynomials in indeterminate table elements d[] and e[] and rational in d[0].
For example, I now need to turn R:= (1/d[0])*(c[0,1,0,2] - c[3,0,4,0]) + (5*c[0,1,0,2] - e[1]*c[3,0,4,0]) into (1/d[0] + 5)*c[0,1,0,2] + (-1/d[0] - e[1])*c[3,0,4,0].
like this?
R :=(1/d[0])*(c[0,1,0,2] - c[3,0,4,0]) + (5*c[0,1,0,2] - e[1]*c[3,0,4,0]): vars := indets(R, 'specindex(nonnegint,c)'); vars := {c[0, 1, 0, 2], c[3, 0, 4, 0]} collect(R, vars); / 1 \ / 1 \ |---- + 5| c[0, 1, 0, 2] + |- ---- - e[1]| c[3, 0, 4, 0] \d[0] / \ d[0] /Exactly! And now..
Exactly, Joe Riel! Thank you!
And now, one more level of complication: I need to make the vars list itself be of indefinite lengths. Plus, I have a lot of R's to compute, so I'll have to put your code into its own loop. More specifically, I am computing c[i,j,k,l] for all i,j,k,l in terms of (using my recursion, as linear combinations of) just those of the form c[0,j',0,l'] and c[i',0,k',0] where i',j',k',l' run from 0 to about 2*i,2*j,k,l. Hence, the number of variables c[i',0,k',0] and c[0,j',0,l'] needed increases with i,j,k,l. I need to compute a sufficient number of c[i,j,k,l], as I mentioned earlier, about 0<=i,j,k,l<=5, to visualize the pattern and hopefully guess a general formula.
I don't quite understand
I don't quite understand what you want. In the code I gave, vars is computed from R. In what sense must it be of indefinite length?
Is the following of use (not directly, but maybe it will give you a clue as to how to do what you really want, efficiently)?
AllVars := proc(i,j,k,l) local ii,jj,kk,ll; global c; {NULL , seq(seq(c[0,jj,0,ll], jj=0..j+1), ll=0..l) , seq(seq(c[ii,0,kk,0], ii=0..i+1), kk=0..k) }; end proc:Presumably you have some way of combining them to generate the linear combinations...