1
$\begingroup$

INTRODUCTION

Hi. I feel a bit embarrased asking this question as the answer may be staring me in the face and there are at least two other stackexchange articles related to it.

MINIMAL WORKING EXAMPLE

In the minimal working example below I do the following:

  • I define a matrix familhy a[n] where n is the dimension of the matrix;
  • I define a matrix function DropM[M,r,c] which takes a matrix of size n and returns a matrix of size n-1 with row r and column c of the original matrix deleted (So it is good for studying minors in laplace expansions);
  • I then define a doubly indexed family of matrices R[m,n_] where -- the first argument simply indexes the collection of matrix families and -- the second argument (set delayed) will be the size. -- R[1,n_]:=a[n] the original matrix family. -- Then R[2,n_] and R[3,n_] come from R[1,n_] and R[2,n_] by deleting "fixed" rows and columns.

PREVIOUS STACK EXCHANGE ARTICLES

I know from previous stackexchange articles that it is dangerous to define recursively with extra parameters. One article suggests making the parameters arguments and another article suggests using global variables. I can't do either here because in the actual project i is a counter controlling a loop(and varies). So I thought I would get around this by defining associations (without set delayed) so that no parameters appear in my function definition. Only the 2nd argument in R[m,n_] is set delayed. The first is fixed (So I am not sure what I am doing wrong).

THE PROBLEM

The code below runs fine. If I now print e.g. R[2,10] I get an error of "Exceeding the recursion limit". But if I print R[1,11],R[2,10] I get no such error. R[2,10] comes from R[1,11] by dropping a specified row and column. But why do I have to print it to avoid an error (perhaps the combination of set and non set "stores" the computed value). But R[1,n] = a[n] which is well defined for any n and there is no real recursion.

As an example of what is bothering me. Using R[1,11] I can then compute R[2,10] by dropping a row and column. Using R[2,10] I can then compute R[3,9] by dropping a row and column. But I dont see why I have to print (or store) these values to avoid 1000 recursions. The first argument is fixed.

The reason I need R[m,n_] is I want a collection of matrix families and I dont know beforehand how many I will need.

CONCLUDING REMARKS

Help, explanations (and encouragement) would be greatly appreciated.

MWE

a[n_] := Table[    
   If[i == j + 1 || j == i + 1, -1,      
   If[i == 1 && j == 1  || i == n && j == n, 1,     
    If[i == j && 2  <= i <=  n - 1, 2, 0]]],        
   {i, 1, n}, {j, 1, n}];  

 DropM[M1_, r1_, c1_] :=   
  Module[{M, r, c, b}, M = M1; r = r1; c = c1;  
    b = Delete[M, r]; 
   Return[Transpose[Delete[Transpose[b], c]]]];    

Clear[R, P, Q];   
ParentCount = 1    
R[ParentCount, n_] := R[ParentCount, n] = a[n];   
Print[R["Position #1", ParentCount, 4]];    

ChildCount = 2; ParentCount = 1; i = 2;
P = Association[ChildCount -> ParentCount];   
Q =  Association[ChildCount -> i];  
 
R[ChildCount, n_] :=   
  R[ChildCount, n] =   
   DropM[R[P[[Key[ChildCount]]], n + 1], 1, Q[[Key[ChildCount]]] ];  

Print["Position #2", R[ChildCount, 4]];  < 

ChildCount++; ParentCount++; i--;  <  
 AssociateTo[P, ChildCount -> ParentCount];    
AssociateTo[Q, ChildCount -> i];   

 R[ChildCount, n_] :=   
  R[ChildCount, n] =    
   DropM[R[P[[Key[ChildCount]]], n + 1], 1, Q[[Key[ChildCount]]] ];  

Print["Position #3", R[ChildCount, 3]]; 
```
$\endgroup$

1 Answer 1

2
$\begingroup$

Your style of code is very convoluted and procedural-like, which is not the common and best way to program in Mathematica.

Here are a few tips on how to write a more Mathematica-like code:

  1. Generally, try to avoid capitalization of your symbols (functions etc.), because they may interfere with system symbols.
  2. No need to reassign local symbols (M = M1; r = r1; c = c1 ...).
  3. There is a simpler way to remove a row and a column from a matrix.
  4. No need to wrap the result in Return inside your Module.
  5. No need to use Key for accessing values inside Association; instead of Q[[Key[ChildCount]]], use Q[ChildCount].
  6. There are more elegant ways to create specially structured matrices like yours by using SparseArray.

Here is a simpler code. I am not sure it is completely correct, because your description is not very clear; please check it yourself. Leave a comment, and I can try to fix the code according to your feedback :)

Clear["Global`*"];

a[n_] := Normal[SparseArray[{{1, 1} -> 1, {n, n} -> 1, Band[{1, 1}] -> 2, 
   Band[{2, 1}] -> -1, Band[{1, 2}] -> -1}, {n, n}]]

R[1, n_] := R[1, n] = a[n]
R[2, n_] := R[2, n] = Drop[R[1, 1 + n], {1}, {2}]
R[3, n_] := R[3, n] = Drop[R[2, 1 + n], {1}, {1}]
$\endgroup$
1
  • $\begingroup$ Consider the following code equivalent in definition to the code you supplied above (and using the simpler syntax) $\endgroup$ Commented Mar 14 at 16:21

Not the answer you're looking for? Browse other questions tagged or ask your own question.