2

I need to solve an equation AX = B using Python where A, X, B are matrices and all values of X must be non-negative.

The best solution I've found is

X = np.linalg.lstsq(A, B, rcond=None)

but as a result X contains negative values. Is it possible to get a solution without negative values? Thanks in advance!

4
  • Maybe docs.scipy.org/doc/scipy/reference/generated/… Commented May 20, 2019 at 20:45
  • @user2699 B has to be one-dimensional with scipy.optimize.lsq_linear and scipy.optimize.nnls unfortunately. Commented May 20, 2019 at 20:54
  • stackoverflow.com/questions/10697995/… Commented May 20, 2019 at 21:04
  • @user2653663 Why is that an issue? A wrapper can easily solve for each column in B, which reference solution in the question using np.linalg.lstsq already does. Commented May 21, 2019 at 12:14

2 Answers 2

6

In general, this is not mathematically possible. Given the basic requirements of A and B being invertible, X is a unique matrix. If you don't like the elements that X has, you can't simply ask for another solution: there isn't one. You'll have to change A or B to get a different result.

Sign up to request clarification or add additional context in comments.

1 Comment

A and B do not have to be invertible - that is not a constraint given in the question or even implied. The least squares solver given in the question finds the solution that gives the minimum mean squared error - but there are other definitions of error (or constraints on B) that result in unique solutions for non-invertible A.
2

You could solve it with cvxpy:

import cvxpy

def solve(A, B):
    """
    Minimizes |AX - B|**2, assuming A and B are 
    square matrices for simplicity. If this optimized 
    error is zero, this corresponds to solving AX = B.
    """
    n = A.shape[0]
    X = cvxpy.Variable((n,n))
    # Set objective
    obj_fun = cvxpy.sum_squares(A*X - B)
    objective = cvxpy.Minimize(obj_fun)
    # Set constraints
    constraints = [X >= 0]
    prob = cvxpy.Problem(objective, constraints)
    result = prob.solve(solver = "ECOS")
    return X.value

EDIT: The answer by Prune is correct I believe. You can check if the error in the numerical solver is non-zero by inspecting results.

1 Comment

Thank you for the answer, but I got "'shape' elements cannot be negative" error with A.shape=(128,1025) and B.shape=(128,146). When I tried the solution on arrays with less dimensios, it works fine.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.