Search code examples
matrixrandommoodlemaximadeterminants

Random matrix with determinant not zero in Maxima


I want to generate a matrix with random entries such that the determinant of that matrix is not zero using Maxima and further down the line implement this in STACK for Moodle. I am completely new to working with Maxima (or any CAS for that matter), so I have been going through various examples I found online and have so far managed to get this:

Generating a 2x2 random matrix with 0 or 1 (for simplicity reasons) and calculating its determinant:

g[i,j]:=1-random(2);
M1:genmatrix(g,2,2);
dM1:determinant(M1);

For the next step I wanted to define a matrix M2 as follows:

M2:(if dM1#0 then M1 else ***)

If the determinant of the matrix M1 is already not zero, fine, I'll go with that, but I am struggling with the else-part. I was thinking of creating a loop that generates new random numbers g[i,j] for M1 until I get a matrix with determinant not zero, but am unsure on how to do that or if there are other options.

In addition: as I mentioned this is ultimately something I want to implement in STACK for moodle (question will be to solve a system of linear equations with the generated matrix being the matrix of this system), so I don't know if there are any limitations on using if and while loops in STACK, so if somebody is aware of known problems I would appreciate any input.


Solution

  • You can say for ... do ... return(something) to yield something from the for-loop, which can be assigned to a variable. In this case it looks like this works as intended:

    (%i9) M2: for i thru 10
                do (genmatrix (lambda ([i, j], 1 - random(2)), 2, 2),
                    if determinant(%%) # 0 then return(%%));
                                [ 1  0 ]
    (%o9)                       [      ]
                                [ 0  1 ]
    (%i10) M2: for i thru 10
                do (genmatrix (lambda ([i, j], 1 - random(2)), 2, 2),
                    if determinant(%%) # 0 then return(%%));
                                [ 1  0 ]
    (%o10)                      [      ]
                                [ 1  1 ]
    (%i11) M2: for i thru 10
                do (genmatrix (lambda ([i, j], 1 - random(2)), 2, 2),
                    if determinant(%%) # 0 then return(%%));
                                [ 1  1 ]
    (%o11)                      [      ]
                                [ 0  1 ]
    

    Note that the first argument for genmatrix is a lambda expression (i.e. unnamed function). If you put the name of an array function such as g in your example, it will not have the intended effect, because in Maxima, array functions are memoizing functions, giving a stored output for an input that has been seen before. Obviously that's not intended if the output is supposed to be random.

    Note also that M2 will be assigned done if the for-loop runs to completion without finding a non-singular matrix. I think that's useful, since you can see if M2 # 'done to ensure that you did get a result.

    Finally note that it makes a difference to use the "group of expressions without local variables" (...) as the body of the for-loop, instead of "group of expressions with local variables" block(...), because the effect of return is different in those two cases.