# 'Do' loop acting on a global variable

I need a code that will allow me to alter a matrix (a global variable) iteratively using a function update (which depends on variable var), append the value of a function func of the altered matrix to a list mypoints, and then reset the matrix to its original value. (In my code, I've already defined a matrix matrix1 by matrix=matrix to make it easier to set the value of matrix at the end of the process.) The function update was given to me and is defined to alter this particular matrix- I can't change it to return a matrix output given a general matrix input, although I believe this would be a better option if I could. I have the following code that I wish to define as a single function:

Do[update[var], 1000]
AppendTo[mypoints, {var, func[matrix]}]
Clear[matrix]
matrix = matrix1


This works for me, but I'd like to rewrite this code as a function of var so I can obtain many points. My naive/unsuccessful attempt is below, I'm not very familiar with the 'Do' loop so I don't know where to go from here, or if this can even be done. Any help is appreciated.

getpoints[var_] := Do[update[var]], 1000;
AppendTo[mypoints, {var, func[matrix]}],
Clear[matrix],
matrix = matrix1]

• Experiment with f[x_]:=(y=2*x;z=x+1);y=5;z=1;f[12] and see what the values of y and z are after that code runs. Maybe with that you can understand how to use that idea to accomplish what you want to do.
– Bill
Jan 15 at 3:49
• Check, for example, the documentation of HoldFirst (Applications section). If you want to define functions that modify other symbols, you need to hold the evaluation of those symbols. Jan 15 at 10:00

Assuming your first piece of code is working as intended, I think all you want to do is wrap it up as a function.

getpoints[var_] := (
Do[update[var], 1000];
AppendTo[mypoints, {var, func[matrix]}];
Clear[matrix];
matrix = matrix1)


A slightly cleaner method would be to use the dynamic scoping construct Block, which will allow you to modify matrix while the body of the block is evaluating, but will restore the original value afterwards (ie the same thing that you are doing manually with matrix1).

getpoints[var_] := Block[{matrix = matrix},
Do[update[var], 1000];
AppendTo[mypoints, {var, func[matrix]}]]


I explain the procedure with the help of an example: Consider the interactive calculation of a matrix invers, using several approximations. A necessary condition for this that the inverse of the diagonal is a first approximation, namely:

Norm[Identity- mat. DiagonalMatrix[1/Diagonal[mat]] < 1


We first search such a matrix:

n = 3;
id = IdentityMatrix[n];
While[mat = RandomReal[{-1, 1}, {n, n}];
Norm[id - mat.DiagonalMatrix[1/Diagonal[mat]]] >= 1]


Then we define the update function. var chooses which approximation we want to use. And we define a function fun that gives a value for the error. We only iterate 4 times because the procedures converge pretty fast.

update[var_] := Switch[var
, 1, #.(2 id - mat.#) &
, 2, #.(3 id - 3 mat.# + mat.#.mat.#) &
, 3, #.(3 id - mat.#.(3 id - mat.#)) &
, 4, (id + 1/4 (id - #.mat).(3 id - #.mat).(3 id - #.mat)).# &
];
fun[mat_, ivmat_] := Norm[Inverse[mat] - ivmat];


Finally we define getpoints, that first iterates the update and then appends the error to mypoints.

mypoints = {};
getpoints[mat_, var_] :=
AppendTo[mypoints,
fun[mat,
Nest[update[var][#] &, DiagonalMatrix[1/Diagonal[mat]], 4]] ];


Now we calculate getpoints with different for val and look at the resulting errors:

getpoints[mat, 1];
getpoints[mat, 2];
getpoints[mat, 3];
getpoints[mat, 4];

mypoints