the difference between `lower` and `upper` in LDLT decomposition - python

I have a problem in LDLT decomposition. Here is my code:
import numpy as np
from scipy.linalg import ldl
B = np.array([[2,-1,0], [-1,3,-1], [0,-1,4]]);
l0,d0, p = ldl(B, lower=0)
print('\nlower=0, L0= ')
print(l0)
print(d0)
l1,d1, p = ldl(B, lower=1)
print('\nlower=1, L1= ')
print(l1)
print(d1)
here is the output
lower=0, L0=
[[ 1. -0.36363636 0. ]
[ 0. 1. -0.25 ]
[ 0. 0. 1. ]]
[[1.63636364 0. 0. ]
[0. 2.75 0. ]
[0. 0. 4. ]]
lower=1, L1=
[[ 1. 0. 0. ]
[-0.5 1. 0. ]
[ 0. -0.4 1. ]]
[[2. 0. 0. ]
[0. 2.5 0. ]
[0. 0. 3.6]]
Well, the l1 and d1 equals the output of ldl() function in matlab.
and the l0 and d0 equals the output of gsl_linalg_ldlt_decomp() function in GSL.
But I want know the difference between the l0 and l1 matrixs.
and How to transform l0 d0 into l1 d1???
Thanks.

Related

Python returning two identical matrices

I am trying to write a small program for Markov Decision Process (inventory problem) using Python. I cannot figure out why the program outputs two identical matrices (for profit and decision matrices). The programming itself has some problems too because the last two columns are all zeros, which should not happen. Any help on the program itself would also be super helpful!
import math
import numpy as np
def salvageCost(b):
return 5 * b
def orderingCost(b):
if b == 0:
return 0
else:
return 4 + 2 * b
def holdingCost(b):
return 1.5 * b
def revenue(b):
return 8 * b
M = 10
N = 4
u = np.zeros((M+1,N))
T = np.array([4,3,2,1])
S = np.array(range(M+1))
A = np.array(range(M+1))
u[:,0] = S*5
d = np.zeros((11,4))
probs = np.array([0.05, 0.1, 0.15, 0.2, 0.2, 0.15, 0.1, 0.05, 0, 0, 0])
demands = np.array(range(11))
candidate = [0]*11
d = u
for i in T[1:N]:
for j in S:
for a in range(M-j+1):
candidate[a] = -holdingCost(j) - orderingCost(a) \
+ np.array([probs[k]for k in range(j+a)]).dot(8*np.array([demands[k]for k in range(j+a)])) \
+ np.array([probs[p] for p in range(min(j+a+1,M+1),M+1)]).dot(np.array(range(min(j+a+1,M+1),M+1)))*80\
+ probs.dot(u[:,i-1])
u[j,i] = max(candidate)
d[j,i] = candidate.index(max(candidate))
print(d)
print(u)
This is the output
[[ 0. 0. 0. 0.]
[ 5. 0. 0. 0.]
[10. 0. 0. 0.]
[15. 0. 0. 0.]
[20. 0. 0. 0.]
[25. 0. 0. 0.]
[30. 0. 0. 0.]
[35. 0. 0. 0.]
[40. 0. 0. 0.]
[45. 0. 0. 0.]
[50. 0. 0. 0.]]
[[ 0. 0. 0. 0.]
[ 5. 0. 0. 0.]
[10. 0. 0. 0.]
[15. 0. 0. 0.]
[20. 0. 0. 0.]
[25. 0. 0. 0.]
[30. 0. 0. 0.]
[35. 0. 0. 0.]
[40. 0. 0. 0.]
[45. 0. 0. 0.]
[50. 0. 0. 0.]]
This line:
d = u
points d and u to the same location in memory. As a result, any changes to d are reflected in u, and vice versa.
You are probably looking to create a copy of the contents of u, in which case you can use d = u.copy().
Because numpy.ndarrays are mutable, when you write
d = u
d and u point to the same matrix, so any change to d or to u affects both:
>>> import numpy as np
>>> x = np.array([1, 2])
>>> y = x
>>> y[0] = 10
>>> x
array([10, 2])

Create 4-dimensional NxNxMxM array using 2-dimension NxM array as diagonal

I am looking to perform the following operation: A[i,j,a,b] = δ ij δ ab B[i,a]. Where A is a NxNxMxM array and B is a NxM array and the δ symbols corresponds to the Kronecker delta.
This can be easily done using explicit looping.
A = np.zeros((N,N,M,M))
for i in range(N):
for j in range(N):
for a in range(M):
for b in range(M):
if i == j and a == b:
A[i,j,a,b] = B[i,a]
However, there must be easier and faster ways to perform such operations.
A much shorter way (but still maybe not the most optimal) is to do the following:
Try it online!
import numpy as np
np.random.seed(4)
N, M = 2, 3
B = np.random.randint(0, 100, (N, M))
print(B)
A = np.zeros((N, N, M, M))
arange_m = np.arange(M)
for i in range(N):
A[(i, i, arange_m, arange_m)] = B[i, arange_m]
print(A)
Output:
[[46 55 69]
[ 1 87 72]]
[[[[46. 0. 0.]
[ 0. 55. 0.]
[ 0. 0. 69.]]
[[ 0. 0. 0.]
[ 0. 0. 0.]
[ 0. 0. 0.]]]
[[[ 0. 0. 0.]
[ 0. 0. 0.]
[ 0. 0. 0.]]
[[ 1. 0. 0.]
[ 0. 87. 0.]
[ 0. 0. 72.]]]]
I just found even shorter way doing same thing using mesh-grid:
Try it online!
import numpy as np
np.random.seed(4)
N, M = 2, 3
B = np.random.randint(0, 100, (N, M))
print(B)
A = np.zeros((N, N, M, M))
mg = np.meshgrid(np.r_[:N], np.r_[:M], sparse = True)
A[(mg[0], mg[0], mg[1], mg[1])] = B[(mg[0], mg[1])]
print(A)
Output:
[[46 55 69]
[ 1 87 72]]
[[[[46. 0. 0.]
[ 0. 55. 0.]
[ 0. 0. 69.]]
[[ 0. 0. 0.]
[ 0. 0. 0.]
[ 0. 0. 0.]]]
[[[ 0. 0. 0.]
[ 0. 0. 0.]
[ 0. 0. 0.]]
[[ 1. 0. 0.]
[ 0. 87. 0.]
[ 0. 0. 72.]]]]

Randomizing Array Values

I have a 4x4 array.
Initially the values are all set to 0, however I want to change innermost 2x2 values to a random float.
a = np.zeros((4,4))
print(a)
a[1:3,1:3] = random.uniform(-1,1)
print(a)
Creates an output:
[[0. 0. 0. 0. ]
[0. 0.66529858 0.66529858 0. ]
[0. 0.66529858 0.66529858 0. ]
[0. 0. 0. 0. ]]
When the desired outcome would be:
[[0. 0. 0. 0. ]
[0. 0.random0 0.random1 0. ]
[0. 0.random2 0.random3 0. ]
[0. 0. 0. 0. ]]
You need to use the size argument to generate a 2 by 2 random matrix:
a[1:3,1:3] = random.uniform(-1,1,size=(2,2))

How to scatter a smaller array in to a larger array using a list as index?

I need help to obtain the following type of result in Python (that I was used to in Matlab):
M = numpy.zeros((5,5))
m = numpy.array([[1,2,3],[4,5,6],[7,8,9]])
indx = [0, 2, 3]
# in Matlab: M(indx,indx) = M(indx,indx) + m
so that the output is:
[[ 1. 0. 2. 3. 0.]
[ 0. 0. 0. 0. 0.]
[ 4. 0. 5. 6. 0.]
[ 7. 0. 8. 9. 0.]
[ 0. 0. 0. 0. 0.]]

Python: Appending dimensions to a bidimensional array

Suppose you have an array (m, m) and want to make it (n, n). For example, transforming a 2x2 matrix to a 6x6. So:
[[ 1. 2.]
[ 3. 4.]]
To:
[[ 1. 2. 0. 0. 0. 0.]
[ 3. 4. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]]
This is what I'm doing:
def array_append(old_array, new_shape):
old_shape = old_array.shape
dif = np.array(new_shape) - np.array(old_array.shape)
rows = []
for i in xrange(dif[0]):
rows.append(np.zeros((old_array.shape[0])).tolist())
new_array = np.append(old_array, rows, axis=0)
columns = []
for i in xrange(len(new_array)):
columns.append(np.zeros(dif[1]).tolist())
return np.append(new_array, columns, axis=1)
Example use:
test1 = np.ones((2,2))
test2 = np.zeros((6,6))
print array_append(test1, test2.shape)
Output:
[[ 1. 1. 0. 0. 0. 0.]
[ 1. 1. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]]
Based on this answer. But that's a lot of code for an (imho) simple operation. Is there a more concise/pythonic way to do it?
Why not use array = numpy.zeros((6,6)), see the numpy docs...
EDIT, woops, question has been edited... I guess you are trying to put ones in a section of an array filled with zeros? Then:
array = numpy.zeros((6,6))
array[0:2,0:2] = 1
If the small matrix does not all have the value of 1:
array[ystart:yend,xstart:xend] = smallermatrix
That would be then:
# test1= np.ones((2, 2))
test1= np.random.randn((2, 2))
test2= np.zeros((6, 6))
test2[0: 2, 0: 2]= test1

Categories