# Can I generate matrices with a constraint?

Say I want a way to generate matrices with the following properties,

• All non-diagonal elements are either $0,1,-1$
• The diagonals are either $k$ or $k+1$ for some $k \in \mathbb{Z}^+$ for some $k$ specified before hand.

• for any diagonal element it should hold that $A_{ii} = \sum_{j \neq i} \vert A_{ij} \vert$

Is there a way to create a generator of such matrices? (as a function of the pre-specified $k$)

• A matrix of all zeroes seems to fulfill all your criteria. Nov 17, 2014 at 22:13
• There will be examples in the docs. Maybe start with SparseArray Nov 17, 2014 at 22:48
• The last condition which states the diagonal element ii must be equal to the sum of all the elements in the row i(in the summation diagonal ii is excluded) makes some difficulty. For example, if K is bigger than N-1, which N is the dimension of your matrix, then you cannot hold the first condition because even if all the other elements were 1 the summation would be less than or equal to N-1.
– MOON
Nov 18, 2014 at 19:39

It's quite involved. Here's a way:

Module[{a},
withNegs[x_List] := x /.(Thread/@ (Array[a, Count[x, _a]] -> # & /@ Tuples[{1, -1}, Count[x, _a]]));
validRows[n_, k_] /; k <= n - 2 := {withNegs@PadRight[Array[a, k], n - 1],
withNegs@PadRight[Array[a, k + 1], n - 1]};
validRows[n_, k_] /; k == n - 1 := {withNegs@PadRight[Array[a, k], n - 1]};
validRowsConcat[n_, k_] := Flatten /@ Tuples[Flatten[validRows[n, k], 1], n];
gen[n_, k_] :=
Partition[#, n] & /@
Flatten[Outer[Riffle[#1, #2, {1, -1, n + 1}] &,
validRowsConcat[n, k], Array[a &, n], 1], 1];
genMats[n_, k_] := gen[n, k] /. {x___, a, y___} :> {x, Tr@Abs@{x} + Tr@Abs@{y}, y}
]

MatrixForm /@ genMats[2, 0]


But be careful, because the number of matrices grows wildly:

Length@genMats[4, 2]
(* 82944 *)

• that is awesome. How could I modify it to generate all matrices 2 x 3 with entries 1 or -1? Sep 23, 2017 at 21:17

I think this does what you are looking for. Generate a random matrix with elements -1, 0, and 1, then subtract out the diagonal. Create the desired diagonal by summing the absolute values of the elements in each column, and add it back.

mat = RandomInteger[{-1, 1}, {5, 5}];
matZeroDiag = mat - DiagonalMatrix@Diagonal@mat;
matZeroDiag + DiagonalMatrix@Total@Abs@matZeroDiag

• Where is this value of $k$ that I would like to fix arbitrarily? I would think that any correct code should let me first choose a value of $k$ and then the matrices would be generated corresponding to that. Nov 18, 2014 at 0:41
• You specified that "The diagonals are either k or k+1 for some k" and they certainly fulfill that condition. You did not say that you wanted to be able to choose k before the matrix was defined. Nov 18, 2014 at 1:08
• @user6818 You should've stated something like "For all 0 < k < n^2-n ..." Nov 18, 2014 at 1:23
• @bills Sorry for my ambiguous language. I meant that $k$ is something chosen externally. And then the matrices have to be generated. Can you help? Nov 18, 2014 at 3:26