# Using ZeroTest method with RowReduce

My goal is to solve this system:

\begin{align*} x_1+2x_2+2x_3+2x_4&=a\\ 2x_1+4x_2+6x_3+8x_4&=b\\ 3x_1+6x_2+8x_3+10x_4&=c \end{align*}

Setting up the augmented matrix and using RowReduce,

mat = {{1, 2, 2, 2, a}, {2, 4, 6, 8, b}, {3, 6, 8, 10, c}};
MatrixForm[RowReduce[mat]]


produces:

\begin{bmatrix} 1 & 2 & 0 & -2 & 0\\ 0 & 0 & 1 & 2 & 0\\ 0 & 0 & 0 & 0 & 1 \end{bmatrix}

A first glance at the last row indicates there are no solutions, which is not true. There are either no solutions or an infinite number of solutions depending on the values of a, b, and c.

To let my colleagues know, I can solve this using Mathematica. I use elementary row operations to put the matrix in row echelon form, then I can see that there will be solutions if $a+b-c=0$. Then I can pick a particular solution, then find the null space of the coefficient matrix to determine all possible solutions if $a+b-c=0$.

Now, here comes the real question that I need help with. There is a very interesting answer by @ssch here. It uses RowReduce and the option ZeroTest. So I went to the documentation on RowReduce, read that RowReduce[m,ZeroTest->test] evaluates test[m[[i,j]]] to determine whether matrix elements are zero. However, there is not even a single example of its use in the RowReduce documentation page.

Now, here is @ssch possible use for this question:

MatrixForm[RowReduce[mat, ZeroTest -> (! FreeQ[#, a] &)]] // Simplify


This remarkably produces the following result:

\begin{bmatrix} 1 & 2 & 0 & -2 & 3a-b\\ 0 & 0 & 1 & 2 & \frac12(-2a+b)\\ 0 & 0 & 0 & 0 & -2(a+b-c) \end{bmatrix}

It doesn't matter if I use FreeQ[#,a], FreeQ[#,b], or FreeQ[#,c]. All three deliver the same result. Now, I did look up FreeQ and I understand its use, but I still don't understand what is going on with the ZeroTest due to the lack of examples in the documentation.

Can some of my colleagues walk me through this with some examples and quality explanation? Thanks.

If your goal is to solve the linear system, then using Reduce seems much clearer:

mat = {{1, 2, 2, 2}, {2, 4, 6, 8}, {3, 6, 8, 10}};
Reduce[mat.{x1, x2, x3, x4} == {a, b, c}, {x1, x2, x3, x4}]

a == -b + c && x3 == -((5 b)/2) + 2 c - x1 - 2 x2 &&
x4 == 2 b - (3 c)/2 + x1/2 + x2


which gives conditions under which equality can hold. Observe that your condition that a+b-c==0 is the first of these.

• Thanks for this answer. It is a good way to find the solution. However, my question does ask for an explanation of the ZeroTest, but I appreciate this answer as well. Commented Aug 14, 2017 at 20:31

As far as I understand it, this

RowReduce[mat, ZeroTest -> (! FreeQ[#, a] &)]


means: If the matrix element has an "a" in it, treat it as though it could be zero, so don't divide by it. If you replace "a" by "b" you'd get the same result whenever the expression has both an "a" and a "b" in it.

I am uncertain whether the result remains the same for any matrix; i.e. I don't know whether specifying one variable will always cover all other variables. I would probably make it foolproof and test for the presence of "a", "b", or "c":

RowReduce[mat, ZeroTest -> (! FreeQ[#, a] || !FreeQ[#,b] || !FreeQ[#,c] &)]


so you are saying, "If it has an "a", a "b", or a "c" in it, treat it as though it could be zero; i.e. don't divide by it.