2
$\begingroup$

I am completely new to programming, so I apologize in advance for a stupid question.

I want to program an algorithm for computing invariant factors of a finitely generated abelian group, so in essence I want to feed the algorithm a matrix of relations and get the reduced form of this matrix.

I have compiled a cumbersome code which makes the first step of the procedure, namely it takes a matrix and produces a matrix, in which the upper-left element divides all the elements in first row and in a first columm:

M = {{120, 51, 72, 33}, {30, 15, 18, 9}, {60, 30, 36, 18}};
If[FreeQ[M, 0], ## &[], Print [First[Dimensions[M]]]];
L = SparseArray[M]["NonzeroPositions"];
i = First[First[L]];
j = Part[First[L], 2];
M2 = M;
M2[[{1, i}]] = M2[[{i, 1}]];
M2[[All, {1, j}]] = M2[[All, {j, 1}]];
If[M2[[1, 1]] > 0, ## &[], 
  M2 = M2*Normal[
     SparseArray[{1 -> -1, i_ -> 1}, First[Dimensions[M2]]]]];
A = Table[0, {First[Dimensions[M2]] - 1}];

For[i = 2, i <= First[Dimensions[M2]], i++, 
  A[[i - 1]] = Boole[Divisible[M2[[i, 1]], M2[[1, 1]]]]];

While[A != Table[1, {First[Dimensions[M2]] - 1}], 
  For[i = 2, i <= First[Dimensions[M2]], i++,
   If[Divisible[M2[[i, 1]], M2[[1, 1]]], ## &[], 
    M3 = M2*Normal[
       SparseArray[{1 -> Quotient[M2[[i, 1]], M2[[1, 1]]]}, 
        First[Dimensions[M2]]]] ; M3[[{1, i}]] = M3[[{i, 1}]]; 
    M2 = M2 - M3; M2[[{1, i}]] = M2[[{i, 1}]]]]; 
  For[i = 2, i <= First[Dimensions[M2]], i++, 
   A[[i - 1]] = Boole[Divisible[M2[[i, 1]], M2[[1, 1]]]]]];

So on the matrix M = {{120, 51, 72, 33}, {30, 15, 18, 9}, {60, 30, 36, 18}} it gives {{30, 15, 18, 9}, {120, 51, 72, 33}, {60, 30, 36, 18}}.

Now I want to iterate this procedure, so I want to feed an arbitrary matrix into this code as a function. I got stuck on this problem for several hours, so I hope you could help me solve this.

$\endgroup$
3
$\begingroup$

Put everything in a Module to localize your Symbols:

fn[m_?MatrixQ] :=
 Module[{M = m, L, i, j, M2, M3, A},
  If[FreeQ[M, 0], ## &[], Print[First[Dimensions[M]]]];
  L = SparseArray[M]["NonzeroPositions"];
  i = First[First[L]];
  j = Part[First[L], 2];
  M2 = M;
  M2[[{1, i}]] = M2[[{i, 1}]];
  M2[[All, {1, j}]] = M2[[All, {j, 1}]];
  If[M2[[1, 1]] > 0, ## &[], 
   M2 = M2*Normal[SparseArray[{1 -> -1, i_ -> 1}, First[Dimensions[M2]]]]];
  A = Table[0, {First[Dimensions[M2]] - 1}];
  For[i = 2, i <= First[Dimensions[M2]], i++, 
   A[[i - 1]] = Boole[Divisible[M2[[i, 1]], M2[[1, 1]]]]];
  While[A != Table[1, {First[Dimensions[M2]] - 1}], 
   For[i = 2, i <= First[Dimensions[M2]], i++, 
    If[Divisible[M2[[i, 1]], M2[[1, 1]]], ## &[], 
     M3 = M2*Normal[
        SparseArray[{1 -> Quotient[M2[[i, 1]], M2[[1, 1]]]}, First[Dimensions[M2]]]]; 
     M3[[{1, i}]] = M3[[{i, 1}]];
     M2 = M2 - M3; M2[[{1, i}]] = M2[[{i, 1}]]]];
   For[i = 2, i <= First[Dimensions[M2]], i++, 
    A[[i - 1]] = Boole[Divisible[M2[[i, 1]], M2[[1, 1]]]]]];
  {A, M2}
 ]

Now:

fn[
 {{120, 51, 72, 33}, {30, 15, 18, 9}, {60, 30, 36, 18}}
]
{{1, 1}, {{30, 15, 18, 9}, {120, 51, 72, 33}, {60, 30, 36, 18}}}

I didn't attempt to understand your operation; I assumed that you wanted both A and M2 for output.

$\endgroup$
2
$\begingroup$

A very crude way to do this would be:

func[mat_] := With[{M = mat},
  If[FreeQ[M, 0], ## &[], Print[First[Dimensions[M]]]];
  L = SparseArray[M]["NonzeroPositions"];
  i = First[First[L]];
  j = Part[First[L], 2];
  M2 = M;
  M2[[{1, i}]] = M2[[{i, 1}]];
  M2[[All, {1, j}]] = M2[[All, {j, 1}]];
  If[M2[[1, 1]] > 0, ## &[], 
   M2 = M2*Normal[
      SparseArray[{1 -> -1, i_ -> 1}, First[Dimensions[M2]]]]];
  A = Table[0, {First[Dimensions[M2]] - 1}];

  For[i = 2, i <= First[Dimensions[M2]], i++, 
   A[[i - 1]] = Boole[Divisible[M2[[i, 1]], M2[[1, 1]]]]];

  While[A != Table[1, {First[Dimensions[M2]] - 1}], 
   For[i = 2, i <= First[Dimensions[M2]], i++, 
    If[Divisible[M2[[i, 1]], M2[[1, 1]]], ## &[], 
     M3 = M2*Normal[
        SparseArray[{1 -> Quotient[M2[[i, 1]], M2[[1, 1]]]}, 
         First[Dimensions[M2]]]]; M3[[{1, i}]] = M3[[{i, 1}]];
     M2 = M2 - M3; M2[[{1, i}]] = M2[[{i, 1}]]]];
   For[i = 2, i <= First[Dimensions[M2]], i++, 
    A[[i - 1]] = Boole[Divisible[M2[[i, 1]], M2[[1, 1]]]]]];
  M2]

so that:

func[{{120, 51, 72, 33}, {30, 15, 18, 9}, {60, 30, 36, 18}}]
(*{{30, 15, 18, 9}, {120, 51, 72, 33}, {60, 30, 36, 18}} *)

There is no attempt here to localize the variables (which can be done within a Module, for example) and you should consider reading the documentation and examples as you refactor your code.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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