Find positive solutions to underdetermined linear system of equations

13,420

Solution 1

The easy answer, since you just need non-negativity constraints on the parameters, is to use lsqnonneg. lsqlin is not needed at all for this problem and since lsqnonneg is part of MATLAB, the optimization TB is not needed.

A = [60 90 120; 30 120 90];
b = [67.5; 60];

x = lsqnonneg(A,b)
x =
                         0
         0.178571428571428
         0.428571428571429

We can test the result to see if it solved the original problem.

A*x - b
ans =
     0
     0

Of course you COULD have used lsqlin, but why bother?

In fact, there is an issue we must consider since an underdetermined system has infinitely many solutions. We can add any amount of the null-space of the array A to our solution. In this case that null-space has rank 1. It is characterized by the vector N here:

N = null(A)
N =
        -0.792593923901216
         -0.22645540682892
         0.566138517072299

An easy way to understand it is to recognize what the nullspace of A means. N is a vector (or a set of basis vectors that span a subspace in case the null-space has dimension higher than 1) such that

A*N = 0

Essentially, N is a vector that is orthogonal to all of the rows of A. If the null-space has dimension higher than 1, then N can be any linear combination of basis vectors of the null-space. Therefore, if X is ANY solution of the under-detemined system

A*x = b

then it must be true that x+c*N is also a solution, for any arbitrary constant c. (Remember that A*N will be zero.)

So for example, I'll pick an arbitrary coefficient for N:

x2 = x + N*(-.1)
x2 =
        0.0792593923901216
          0.20121696925432
         0.371957576864199

Again, x2 is also a solution. It too has entirely positive coefficients. (You can trivially find that range of values for the coefficient on N such that the solution is entirely positive.)

A*x2 - b
ans =
      -1.4210854715202e-14
       -7.105427357601e-15

(Note that these are effectively zeros, to within the double precision trash found in floating point arithmetic.)

So, IF we wanted to do so, it is easy enough to start with the lsqnonneg or backslash or pinv solution, and find the complete set of solutions to your system such that the coefficients are entirely positive. Hint: all you need do is consider the vectors x and N, then look for solutions to the problem

(x + c*N) > 0

where c is some scalar constant. Clearly, C cannot be positive, else the first element of the sum will be negative.

C = -x./N
C =
            0
      0.78855
     -0.75701

x + C(1)*N
ans =
            0
      0.17857
      0.42857

x + C(3)*N
ans =
          0.6
         0.35
            0

As we can see, when c is any value in the closed interval [-.75701,0], we get an entirely positive solution to the problem, in the form of (x+c*N). Go any further than those limits though, and one or more of the elements in the solution will be negative.

On some problems there will be no solution at all that yields an exact solution with all positive elements of the solution vector. This is entirely possible. For example, suppose we changed the original problem into:

A = [60 90 120; 30 120 90];
b = [-67.5; -60];

Now what happens when we apply lsqnonneg?

lsqnonneg(A,b)
ans =
     0
     0
     0

An all-zero solution results. Since that solution clearly can not exactly solve the original problem, it must be true that no such positive solution exists.

Solution 2

A = [60 90 120; 30 120 90];
b = [67.5; 60];

You can get a solution x for Ax = b using

x = A\b;

or

x = pinv(A)*b;

but if you want constraints on x you will have to use something like lsqlin:

lsqlin(A,b,[],[],[],[],[0; 0; 0],[])

(which in this case gives the same result as the pinv solution)

Share:
13,420

Related videos on Youtube

htd
Author by

htd

student

Updated on June 04, 2022

Comments

  • htd
    htd almost 2 years

    I'm a bit new to matlab so sorry if this is horribly simple.

    Consider a problem of the following:

    Find x_1, x_2, x_3 > 0 such that

    67.5 = 60*x_1 +  90*x_2 + 120*x_3 and
    60   = 30*x_1 + 120*x_2 +  90*x_3
    

    In this case I want the solution

    0 < x_3 < 3/7,
    x_2 = 7/20 - 4/10*x_3, and
    x_1 = 2/5  -  7/5*x_3
    

    Is there a easy way to make Matlab solve such a problem for me?

  • htd
    htd almost 11 years
    Thanks for your reply. I kind of need the inequalities - the solution part I already knew. Can what I am seeking be found by lsqlin?
  • ioums
    ioums almost 11 years
    Assuming you have the optimization toolbox, I don't see why not
  • htd
    htd almost 11 years
    It seems like an absolutely awesome answer this, but I will have to take a while to look at it. Thank you for now I will return :)