Scipy NNLS perform this:
Solve argmin_x || Ax - b ||_2 for x>=0.
What's the alternative way to do it if I seek
strictly non-zero solution (i.e. x > 0
) ?
Here is my LP code using Scipy's NNLS:
import numpy as np
from numpy import array
from scipy.optimize import nnls
def by_nnls(A=None, B=None):
""" Linear programming by NNLS """
#print "NOF row = ", A.shape[0]
A = np.nan_to_num(A)
B = np.nan_to_num(B)
x, rnorm = nnls(A,B)
x = x / x.sum()
# print repr(x)
return x
B1 = array([ 22.133, 197.087, 84.344, 1.466, 3.974, 0.435,
8.291, 45.059, 5.755, 0.519, 0. , 30.272,
24.92 , 10.095])
A1 = array([[ 46.35, 80.58, 48.8 , 80.31, 489.01, 40.98,
29.98, 44.3 , 5882.96],
[ 2540.73, 49.53, 26.78, 30.49, 48.51, 20.88,
19.92, 21.05, 19.39],
[ 2540.73, 49.53, 26.78, 30.49, 48.51, 20.88,
19.92, 21.05, 19.39],
[ 30.95, 1482.24, 100.48, 35.98, 35.1 , 38.65,
31.57, 87.38, 33.39],
[ 30.95, 1482.24, 100.48, 35.98, 35.1 , 38.65,
31.57, 87.38, 33.39],
[ 30.95, 1482.24, 100.48, 35.98, 35.1 , 38.65,
31.57, 87.38, 33.39],
[ 15.99, 223.27, 655.79, 1978.2 , 18.21, 20.51,
19. , 16.19, 15.91],
[ 15.99, 223.27, 655.79, 1978.2 , 18.21, 20.51,
19. , 16.19, 15.91],
[ 16.49, 20.56, 19.08, 18.65, 4568.97, 20.7 ,
17.4 , 17.62, 25.51],
[ 33.84, 26.58, 18.69, 40.88, 19.17, 5247.84,
29.39, 25.55, 18.9 ],
[ 42.66, 83.59, 99.58, 52.11, 46.84, 64.93,
43.8 , 7610.12, 47.13],
[ 42.66, 83.59, 99.58, 52.11, 46.84, 64.93,
43.8 , 7610.12, 47.13],
[ 41.63, 204.32, 4170.37, 86.95, 49.92, 87.15,
51.88, 45.38, 42.89],
[ 81.34, 60.16, 357.92, 43.48, 36.92, 39.13,
1772.07, 68.43, 38.07]])
The usage:
In [9]: by_nnls(A=A1,B=B1)
Out[9]:
array([ 0.70089761, 0. , 0.06481495, 0.14325696, 0.01218972,
0. , 0.02125942, 0.01906576, 0.03851557]
Note the zero solution above.
If you are really sure you want strictly positive solutions, you can use lsq_linear which is available in the most recent scipy version. It allows a bit more control over the bounds than
nnls
.You should question if you really want
x > 0
instead ofx >= 0
. Usually the latter constraint serves to sparsify the result, and zeros in x are desirable. Apart from that, the constraints are practically equivalent.If you constrain x to be strictly greater than zero, the 0s will simply become very very small positive numbers. If the soulution could be improved by larger values, you would get these values with the original constraint too.
Let's demonstrate this by defining the following optimization: Solve
argmin_x || Ax - b ||_2 for x>=eps
. Whileeps > 0
this also satisfiesx > 0
. Looking at the resultingx
for differenteps
, we get:What you see is that for mall
eps
there is hardly any difference in the objective function andx[1]
(one of the 0s in the original solution) gets closer and closer to 0. Thus, the infinitesimal step fromx>0
tox>=0
hardly changes anything in the solution. For practical purposes they are totally similar. However,x>=0
has the advantage that you get actual 0s rather than 1.234e-20, which helps in sparsifying the solution.Here is the code for above plot:
P.S. I have tried to implement the
x > 0
constraint in my code withlambda x: [1 if i>0 else -1 for i in x]
, but it fails to converge.