Recover solution from dynamic programming memo table - python-3.x

My goal is to find the longest sub-list of a list of numbers such that each element is at most 1 away from each other, e.g., a list of [0,1,2,2,3,3] from the list [0,4,1,2,2,3,3,1]. I create the memo table as follows:
def memoizeLSS(a):
T = {}
n = len(a)
for j in range(-1, n):
T[(n, j)] = 0 # i = n and j
for i in range(0, n+1):
for j in range(-1, n+1):
T[(i, j)] = 0
for i in range(n-1, -1, -1):
for j in range(n-1, -1, -1):
aj = a[j] if 0 <= j < len(a) else None
if aj != None and abs(a[i] - a[j]) > 1:
T[(i, j)] = T[(i + 1, j)]
elif aj == None or abs(a[i] - a[j]) <= 1:
T[(i, j)] = max(T[(i + 1, i)] + 1, T[(i + 1, j)])
for i in range(n-2, -1, -1):
T[(i, -1)] = max(T[(i+1, -1)], T[(i+1, 0)], T[(i, 0)], 0)
return T
I can figure out the maximum length, however I'm having trouble reconstructing the subsequence from the memo table. I tried creating a list of paired indices where the numbers are <= 1 away from and building it up from there, but there are pairs of indices which are not part of the sub-sequence and I'm stumped on what to do from here or even if creating this list is useful:
def computeLSS(a):
T = {}
Y_list = []
# Now populate the entries for the base case
n = len(a)
for j in range(-1, n):
T[(n, j)] = 0 # i = n and j
for i in range(0, n+1):
for j in range(-1, n+1):
T[(i, j)] = 0
for i in range(n-1, -1, -1):
for j in range(n-1, -1, -1):
aj = a[j] if 0 <= j < len(a) else None
if aj != None and abs(a[i] - a[j]) > 1:
T[(i, j)] = T[(i + 1, j)]
elif aj == None or abs(a[i] - a[j]) <= 1:
T[(i, j)] = max(T[(i + 1, i)] + 1, T[(i + 1, j)])
if T[(i, j)] == T[(i + 1, i)] + 1 and a[i] != a[j]:
Y_list.append((i, j))
for i in range(n-2, -1, -1):
T[(i, -1)] = max(T[(i+1, -1)], T[(i+1, 0)], T[(i, 0)], 0)
Y_list_new = []
for x,y in Y_list:
if x==y:
pass
if (y,x) in Y_list_new:
pass
else:
Y_list_new.append((x,y))
print(Y_list_new)
#print(T)
return
Any help is appreciated. Thank you!

Related

Dynamic Programming, create a memo table longest stable subsequence

I have worked on a dynamic programming problem for quite some time now and am stuck, so any help is much appreciated.
Here is the first part of the problem which I was able to get the tests to pass.
def lssLength(a, i, j):
aj = a[j] if 0 <= j < len(a) else None
# Implement the recurrence below. Use recursive calls back to lssLength
assert 0 <= i <= len(a)
if i >= len(a) or j >= len(a):
return 0
if aj and abs(a[i] - a[j]) > 1:
return lssLength(a, i+1, j)
if aj is None or (abs(a[i] - a[j]) <= 1 and i != j):
return max(lssLength(a, i+1, j), lssLength(a, i+1, i) + 1)
else:
return lssLength(a, i+1, j)
Here are my test cases for the first problem:
def test_lss_length(self):
# test 1
n1 = lssLength([1, 4, 2, -2, 0, -1, 2, 3], 0, -1)
print(n1)
self.assertEqual(4, n1)
# test 2
n2 = lssLength([1, 2, 3, 4, 0, 1, -1, -2, -3, -4, 5, -5, -6], 0, -1)
print(n2)
self.assertEqual(8, n2)
# test 3
n3 = lssLength([0, 2, 4, 6, 8, 10, 12], 0, -1)
print(n3)
self.assertEqual(1, n3)
# test 4
n4 = lssLength(
[4, 8, 7, 5, 3, 2, 5, 6, 7, 1, 3, -1, 0, -2, -3, 0, 1, 2, 1, 3, 1, 0, -1, 2, 4, 5, 0, 2, -3, -9, -4, -2, -3,
-1], 0, -1)
print(n4)
self.assertEqual(14, n4)
Now I need to take the recursive solution and convert it to dynamic programming, and this is where I am stuck. I am using the same tests as before, but the tests are failing.
def memoizeLSS(a):
T = {} # Initialize the memo table to empty dictionary
# Now populate the entries for the base case
# Now fill out the table : figure out the two nested for loops
# It is important to also figure out the order in which you iterate the indices i and j
# Use the recurrence structure itself as a guide: see for instance that T[(i,j)] will depend on T[(i+1, j)]
n = len(a)
for i in range(0, n+1):
for j in range(-1, n+1):
T[(i, j)] = 0
for i in range(n-1, -1, -1):
for j in range(n-1, -1, -1):
if abs(a[i] - a[j]) > 1:
try:
T[(i, j)] = max(0, T[(i, j+1)], T[(i+1, j)])
except Exception:
T[(i, j)] = 0
elif abs(a[i] - a[j]) <= 1 and i != j:
T[(i, j)] = T[(i+1, j+1)] + 1
else:
T[(i, j)] = max(0, T[(i+1, j+1)])
for i in range(n-2, -1, -1):
T[(i, -1)] = max(T[(i+1, -1)], T[(i+1, 0)], T[(i, 0)], 0)
return T
If you've read all of this, thank you so much. I know it is a lot and really appreciate your time. Any pointers to reading materials, etc. is much appreciated.
If there are more details required, please let me know. Thanks.
Your solution only worked for the first test case. Below is a corrected version:
def memoizeLSS(a):
T = {} # Initialize the memo table to empty dictionary
n = len(a)
for j in range(-1, n):
T[(n, j)] = 0 # i = n and j
# Now populate the entries for the base case
# Now fill out the table : figure out the two nested for loops
# It is important to also figure out the order in which you iterate the indices i and j
# Use the recurrence structure itself as a guide: see for instance that T[(i,j)] will depend on T[(i+1, j)]
n = len(a)
for i in range(0, n + 1):
for j in range(-1, n + 1):
T[(i, j)] = 0
for i in range(n-1, -1, -1):
for j in range(n-1, -1, -1):
aj = a[j] if 0 <= j < len(a) else None
if aj != None and abs(a[i] - a[j]) > 1:
T[(i, j)] = T[(i+1, j)]
elif aj == None or abs(a[i] - a[j]) <= 1:
T[(i, j)] = max(T[(i+1, i)] + 1, T[(i + 1, j)])
for i in range(n-2, -1, -1):
T[(i, -1)] = max(T[(i+1, -1)], T[(i+1, 0)], T[(i, 0)], 0)
return T

Finding inverse of a matrix using Gauss-Jordan Elimination in Python

So I am trying to find inverse of a matrix (using Python lists) by Gauss-Jordan Elimination. But I am facing this peculiar problem. In the code below, I apply my code to the given matrix and it reduces to the identity matrix as intended.
M = [[0, 2, 1], [4, 0, 1], [-1, 2, 0]]
P = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
n = len(P)
def inverse(a):
for k in range(n):
if abs(a[k][k]) < 1.0e-12:
for i in range(k+1, n):
if abs(a[i][k]) > abs(a[k][k]):
for j in range(k, n):
a[k][j], a[i][j] = a[i][j], a[k][j]
break
pivot = a[k][k]
for j in range(k, n):
a[k][j] /= pivot
for i in range(n):
if i == k or a[i][k] == 0: continue
factor = a[i][k]
for j in range(k, n):
a[i][j] -= factor * a[k][j]
return a
inverse(M)
The output is
[[1.0, 0.0, 0.0], [0, 1.0, 0.0], [0.0, 0.0, 1.0]]
But when I apply the same code, after adding lines of code for my identity matrix (which is part of the augmented matrix with the given matrix), It is not giving me the correct inverse when it should (as I am applying same operation on it as I'm applying on the given matrix).
M = [[0, 2, 1], [4, 0, 1], [-1, 2, 0]]
P = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
n = len(P)
def inverse(a, b):
for k in range(n):
if abs(a[k][k]) < 1.0e-12:
for i in range(k+1, n):
if abs(a[i][k]) > abs(a[k][k]):
for j in range(k, n):
a[k][j], a[i][j] = a[i][j], a[k][j]
b[k][j], b[i][j] = b[i][j], b[k][j]
b[k], b[i] = b[i], b[k]
break
pivot = a[k][k]
for j in range(k, n):
a[k][j] /= pivot
b[k][j] /= pivot
for i in range(n):
if i == k or a[i][k] == 0: continue
factor = a[i][k]
for j in range(k, n):
a[i][j] -= factor * a[k][j]
b[i][j] -= factor * b[k][j]
return a, b
inverse(M, P)
The output is not the inverse matrix, but something else (though the last column has correct entries).
([[1.0, 0.0, 0.0], [0, 1.0, 0.0], [0.0, 0.0, 1.0]],
[[0.0, 0.25, 0.3333333333333333],
[1, 0.0, 0.6666666666666666],
[0.0, 0.25, -1.3333333333333333]])
I tried using print statements while debugging, and I think the line where I divide the rows by the pivot, has some issue. It works fine in the original matrix but doesn't work with the identity matrix. Also, note that only the last column of the identity matrix gets converted to the correct entries of the inverse matrix.
The correct inverse matrix for reference is
I = [[-1/3, 1/3, 1/3], [-1/6, 1/6, 2/3], [4/3, -1/3, -4/3]]
Any help would be much appreciated.
Thanks in advance!
I could not figure out the problem in my code though I found a workaround and I'll be instead posting that. Hope that might help someone else.
Instead of doing the same operations on the two matrices of which I formed the augmented matrix, I decided to deal it as a n x 2n matrix. Here is the fully working code:
def inverse(a):
n = len(a) #defining the range through which loops will run
#constructing the n X 2n augmented matrix
P = [[0.0 for i in range(len(a))] for j in range(len(a))]
for i in range(3):
for j in range(3):
P[j][j] = 1.0
for i in range(len(a)):
a[i].extend(P[i])
#main loop for gaussian elimination begins here
for k in range(n):
if abs(a[k][k]) < 1.0e-12:
for i in range(k+1, n):
if abs(a[i][k]) > abs(a[k][k]):
for j in range(k, 2*n):
a[k][j], a[i][j] = a[i][j], a[k][j] #swapping of rows
break
pivot = a[k][k] #defining the pivot
if pivot == 0: #checking if matrix is invertible
print("This matrix is not invertible.")
return
else:
for j in range(k, 2*n): #index of columns of the pivot row
a[k][j] /= pivot
for i in range(n): #index the subtracted rows
if i == k or a[i][k] == 0: continue
factor = a[i][k]
for j in range(k, 2*n): #index the columns for subtraction
a[i][j] -= factor * a[k][j]
for i in range(len(a)): #displaying the matrix
for j in range(n, len(a[0])):
print(a[i][j], end = " ")
print()

Finding maximal submatrix of all 1's - missing argument error

Program that finds the maximal rectangle containing only 1's of a binary matrix with the maximal histogram problem.
I am trying to do some tests on a code
def maximalRectangle(self, matrix):
if not matrix or not matrix[0]:
return 0
n = len(matrix[0])
height = [0] * (n + 1)
ans = 0
for row in matrix:
for i in range(n):
height[i] = height[i] + 1 if row[i] == '1' else 0
stack = [-1]
for i in range(n + 1):
while height[i] < height[stack[-1]]:
h = height[stack.pop()]
w = i - 1 - stack[-1]
ans = max(ans, h * w)
stack.append(i)
return ans
# Driver Code
if __name__ == '__main__':
matrix = [[0, 1, 0, 1],
[0, 1, 0, 1],
[0, 1, 1, 1],
[1, 1, 1, 1]]
print(maximalRectangle(matrix))
I get TypeError: maximalRectangle() missing 1 required positional argument: 'matrix' error
Solved by removing self and changing the print statement to:
print(maximalRectangle([
["1","0","1","0","0"],
["1","1","1","1","1"],
["1","1","1","1","1"],
["1","0","0","1","0"]]))

python performance improvement

I am trying to obtain intensity values from an RGB image based on this formula:
And my code is:
def normalize(image): #normalize values to between 0 and 1
image -= image.min()
image /= image.max()
image = np.uint8(image * 255) #convert values to uint8 between 0-255
return image
def custom_intensity(image):
h, w, c = image.shape
intensity = np.zeros((h, w))
image = image.astype(float)
for i in range(h):
for j in range(w):
divider = image[i, j, 0] + image[i, j, 1] + image[i, j, 2]
if(divider == 0):
intensity[i, j] == 0
else:
intensity[i, j] = image[i, j, 0] * (image[i, j, 0] / divider) + \
image[i, j, 1] * (image[i, j, 1] / divider) + \
image[i, j, 2] * (image[i, j, 2] / divider)
intensity = normalize(intensity)
return intensity
Which works well but slow. I am beginner in python so could not improve this further. How can I make this code more efficient?
Try this:
image += (pow(10, -6), pow(10, -6), pow(10, -6))
intensity = (pow(image[:, :, 0], 2) + pow(image[:, :, 1], 2) + pow(image[:, :, 2], 2)) \
/ (image[:, :, 0] + image[:, :, 1] + image[:, :, 2])
You don't need to be an expert in Python.
Simplify your equation:
(R**2 + G**2 + B**2) / (R+G+B)

Dynamic Programming: Tabulation of a Recursive Relation

The following recursive relation solves a variation of the coin exchange problem. Count the number of ways in which we can sum to a required value, while keeping the number of summands even:
def count_even(coins, num_coins, req_sum, parity):
if req_sum < 0:
return 0
if req_sum == 0 and not parity:
return 1
if req_sum == 0 and parity:
return 0
if num_coins == 0:
return 0
count_wout_high_coin = count_even(coins, num_coins - 1, req_sum, parity)
count_with_high_coin = count_even(coins, num_coins, req_sum - coins[num_coins - 1], not parity)
return count_wout_high_coin + count_with_high_coin
This code would yield the required solution if called with parity = False.
I am having issues implementing a tabulation technique to optimize this algorithm. On a first attempt I tried to follow the same pattern as for other DP problems, and took the parity as another parameter to the problem, so I coded this triple loop:
def count_even_tabulation(S, m, n):
if m <= 0 or n < 0:
return 0
if n == 0:
return 1
table = [[[0 for x in range(m)] for x in range(n + 1)] for x in range(2)]
for j in range(m):
table[0][0][j] = 1
table[1][0][j] = 0
for p in range(2):
for i in range(1, n + 1):
for j in range(m):
y = table[p][i][j - 1] if j >= 1 else 0
x = table[1 - p][i - S[j]][j] if i - S[j] >= 0 else 0
table[p][i][j] = x + y
return table[0][n][m - 1]
However, this approach is not creating the right tables for parity equal to 0 and equal to 1:
[1, 1, 1]
[0, 0, 0]
[0, 0, 0]
[0, 0, 0]
[0, 0, 0]
[0, 0, 0]
[1, 1, 1]
[0, 1, 1]
[0, 0, 1]
[0, 0, 0]
How can I adequately implement a tabulation approach for the given recursion relation?

Resources