Using output of a function as an input in a different function - python

I'm trying to create a function in python (without numpy) that would imitate matrix multiplication in numpy. The program contains 2 functions. First function takes in 2 lists (l1 and l2) as input and creates a dummy list (dummy). The second function does the matrix multiplication of the lists l1 and l2 and inputs the values in the dummy list (dummy). The issue is that in the final output, the column values are being added and repeated in each row. However, if I hard code the dummy list in the program, it is giving correct output. If I run the first function to create dummy list separately, I'm getting correct output. Not sure where I'm going wrong. Providing both the codes below. Please help.
#Following code is giving me erroneous result:
l1 = [[1,2],[3,4],[5,6]]
l2 = [[7,8,0],[9,10,5]]
def dummy_matrix(l1,l2):
g = len(l1)
h = len(l2[0])
m = []
p = []
for j in range(h):
p.append(0)
for i in range(g):
m.append(p)
dummy = m
return(dummy)
def mat_mul(l1,l2):
f = dummy_matrix(l1,l2)
for a in range(len(l1)):
for b in range(len(l2[0])):
for c in range(len(l2)):
f[a][b] += l1[a][c]*l2[c][b]
return(f)
mat_mul(l1,l2)
#Following code has hard coded dummy list and is giving correct output
l1 = [[1,2],[3,4],[5,6]]
l2 = [[7,8,0],[9,10,5]]
def dummy_matrix(l1,l2):
g = len(l1)
h = len(l2[0])
m = []
p = []
for j in range(h):
p.append(0)
for i in range(g):
m.append(p)
dummy = m
return(dummy)
def matrix_multi(l1,l2):
f = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
for a in range(len(l1)):
for b in range(len(l2[0])):
for c in range(len(l2)):
f[a][b] += l1[a][c]*l2[c][b]
return(f)
matrix_multi(l1,l2)

You create your dummy_matrix wrong. You first create a row called p, append some zeros to it and then you append the same row multiple times.
dm = dummy_matrix(l1, l2)
dm[1][2] = 1
print(dm)
You can notice that this will modify multiple rows, showing that they are in fact the same reference.
You need to create fresh list for each row:
m = []
for i in range(g):
p = []
for j in range(h):
p.append(0)
m.append(p)

Related

Row not adding to matrix in while loop in sympy

The aim of this program is to build a 3x3 matrix which then reduces additional rows, but, for some reason, after the second row is added to M in the while loop, it replaces it with the new row, rather than adding a third row, and, then, reducing additional (most likely 3) vectors after that. Here's the code:
from sympy import *
init_printing(use_unicode= True)
A = []
def reduceOneRow(M):
k = 0
for i in range(k,min(M.shape)-1):
if M[i,i]!=0 or i ==2:
for j in range(k,min(M.shape)-1):
T = Matrix([M.row(j+1)-(M[j+1,i]/M[i,i])*M.row(i)])
A.append(M[j+1]/M[i,i])
M.row_del(j+1)
M = M.row_insert(j+1,T)
k = k+1
else:
i = i+1
return M
# M = Matrix([[1,1,1],[1,4,7],[3,2,5]])
# reduceOneRow(M)
# A
#The following block of code generates a list of monomials, but not in reverse
#lexicagraphical order. This can be fixed later. Ultimately, I'd like to
#make it it's own function
sigma = symbols('x1:4')
D = [1]
for d in D:
for s in sigma:
if s*d not in D:
D.append(s*d)
if len(D) > 20:
break
# print(D)
# print(D[9].subs([('x1',4),('x2',2),('x3',3)]))
#We begin with the set up described in C1
P = [(1,2,3),(4,5,6),(7,8,9)]
G = []
Q = []
S = []
L = [1]
M = Matrix([])
#Here we being step C2.
while L != []:#what follows this while statement is the loop C2-C5 and back
t = L[0]
L.remove(L[0])
K = Matrix([]) #K is a kind of bucket matrix
if t==1: #this block generates the firs line in M. It had to be separate
for j in range(len(P)):#because of the way sympy works. 1 is int, rather
K = K.col_insert(j,Matrix([1])) #than a symbol
else: #here we generate all other rows of M, using K for the name of the rows
for p in P:
K = K.col_insert(0,Matrix([t.subs([(sigma[0],p[0]),(sigma[1],p[1]),(sigma[2],p[2])])]))
# K = K.col_insert(i,Matrix([t.subs([(sigma[0],p[0]),(sigma[1],p[1]),(sigma[2],p[2])]))
M = M.row_insert(min(M.shape)+1,K) #K gets added to M
M
A = []
reduceOneRow(M)#row reduces M and produces the ai in C3
sum = 0
for n in range(len(A)):
sum = sum + A[n]*S[n]
V = M.row(-1)
if V == zeros(1,len(V)):
G.append(t - sum)
M.row_del(-1)
else:
S.append(t-sum)
Q.append(t)
for i in range(1,4):
#if not t*D[i] == Q[0]:
L.append(t*D[i])
L
print('G =',' ',G,' ','Q =',Q)
I figure it out. I changed 'reduceRowOne(M)' to 'M = reduceRowOne'. Ugh.
Thank you all who took a look at this!

IndexError: list index out of range on python dynamic variable length

While I was creating a basic for-loop in Python within a function in order to work with a dynamic variable length (z) I've just come across the following error:
Rs = []
z = []
N = 120
m = 1
for i in range(1, N):
Rs[i] = z[m]
m = m + 1
Rs[i] = z[m]
IndexError: list index out of range
For the sake of clarity, I will explain better what I'm trying to do.
I would like to solve an equation system which is composed by a dynamical number of unknowns.
I've started to use the "static" method and It works perfectly. Basically, the code is more or less as follows:
from scipy.optimize import fsolve
def fixEqSyst(z):
v1 = z[0]
v2 = z[1]
v3 = z[2]
v4 = z[3]
f=np.zeros(4)
f[0] = 2*v1-3*v2+7*v3**2
f[1] = v1+3*v2**2-9*v3
f[2] = -3v1**2+12*v2+7*v3
f[3] = 4*v1+5*V2*v3
return f
z = fsolve(fixEqSyst, [0, 0, 0, 0])
Basing on the fact that now I will face with a dynamic number of unknowns and functions, is there any alternative solution than of what I've already put in place? (with a for-loop strategy)
Just in the first iteration of your loop you get
Rs[1] = z[1]
but z[1] don't exists, because z = [].
(The same for Rs[1].)
I haven't any idea how to fix it because I'm unable to guess what you wanted perform with you code.
Maybe you wanted to copy the contain of your - supposed nonempty - list z to Rs. Then they are 2 different simple solutions:
Rs = z
Attention! This is not a copy operation, this only associates other name to the same object, so every change in z will produce the same change in Rs and vice versa.
Rs = z[:]
This is the true (but shallow) copy. For simple lists this is the same as a deep copy.
When you assign a value to an array in python, the element must already exist. When you are assigning Rs[i] = z[m], you are assigning values out of the range of the list. You can use the += operator on a list in order to make it large enough, like this:
Rs = []
z = []
N = 120
m = 1
for i in range(m+N):
z += [m+i]
for i in range(N):
Rs += [z[m]]
m = m + 1
Note that += can only concatenate a list to another list. So this will work:
mylist = [1, 2, 3]
mylist += [4]
But this will not:
mylist = [1, 2, 3]
mylist += 4
Here is more on the += operator on lists.

Transposing a list of lists in python

Why does this code doesn't transpose the list of list
import sys
t = input()
for k in range(t):
n,m = [int(i) for i in raw_input().strip().split()]
A = [[None]*m]*n
B = [[None]*n]*m
for l in range(n):
A[l] = raw_input().strip().split()
for j in range(m):
for i in range(n):
B[j][i] = A[i][j]
print B
I know there are better methods to transpose a matrix but why does this doesn't work?
Replace
A = [[None]*m]*n
B = [[None]*n]*m
with
A = [[None for x in range(m)] for x in range(n)]
B = [[None for x in range(n)] for x in range(m)]
Why?
>>> l = [2]*5
>>> l
[2,2,2,2,2]
>>> [id(value) for value in l]
[26089400, 26089400, 26089400, 26089400, 26089400]
Can you see what happened there?
There's just one copy in memory holding a value '2'. All list elements are pointing to that same memory location holding the value '2'.
So, when you do:
A = [[None]*m]*n
you are creating a 2d array with elements pointing to the same memory location. Changing one of them, changes the value stored at that common memory location, hence changes value stored by all the elements!
That is why the program didn't work.
Read more about how all this works in Python, in detail, here:
http://foobarnbaz.com/2012/07/08/understanding-python-variables/

python function making unrequested changes

I have a function (crout) defined in a file called LU.py and another function defined in a different file (invert.py). The contents of the files are:
LU.py
def crout(A,L,U):
N = len(A)
add = 0
#print(L,U)
for i in range(N):
print('b',L[i][i])
U[i][i] = 1
print('a',L[i][i])
#print(L,U)
and invert.py
import LU
def inverse(A):
n = len(A)
B = []
L = []
U = []
for i in range(n):
row = [0 for j in range(n)]
B.append(row)
L.append(row)
U.append(row)
LU.crout(A,L,U)
return B
M = [[1,2,3],[1,0,1],[2,2,0]]
Mi = inverse(M)
A = [[1,2,3],[1,0,1],[2,2,0]]
L = [[0,0,0],[0,0,0],[0,0,0]]
U = [[0,0,0],[0,0,0],[0,0,0]]
print('bla')
LU.crout(A,L,U)
Notice that I run the function crout two times from the invert file, once from the inverse function and once from outside the function.
Next, I run the invert.py file using python 2.7.6 on an ubuntu linux machine and I get the following output:
('b',0)
('a',1)
('b',0)
('a',1)
('b',0)
('a',1)
bla
('b',0)
('a',0)
('b',0)
('a',0)
('b',0)
('a',0)
The numbers before the 'bla' which is the call of crout from within inverse, represent the elements of the diagonal in array L. Notice that these values change from 0 ('b') to 1 ('a') as I change the values in U (which off course should not happen!). On the other hand, when I call crout from outside the function inverse the values in L remain unchanged after changing U, which off course is what should happen.
Any ideas about why this is happening would be very much appreciated!
Carlos
In inverse, you append the row variable to each of B, L, and U.
for i in range(n):
row = [0 for j in range(n)]
B.append(row)
L.append(row)
U.append(row)
Now each list contains a reference to the same row value. changing a value in one of the lists will change the accompanying value in each other one. If this is not the desired behavior, create a new row for each list.
for i in range(n):
B.append([0 for j in range(n)])
L.append([0 for j in range(n)])
U.append([0 for j in range(n)])
If this looks a bit inelegant to you, it may be useful to make an independent function for matrix creation logic.
def make_square_matrix(size):
return [[0]*size for b in range(size)]
def inverse(A):
n = len(A)
B = make_square_matrix(n)
L = make_square_matrix(n)
U = make_square_matrix(n)
LU.crout(A,L,U)
return B

Knapsack algorithm dynamic programming .(incorrect output) here is what I have so far

I wrote this code for dynamic programming implementation of the knapsack problem.
#B = maximum weight
#n = number of items
#p = list of weights
#a = list of values
#p[i] = weight with value a[i]
def maximum_attractiveness(n, B, p, a):
f = [i for i in range(n+1)]
m = [f for i in range(B+1)]
m[0] = [0 for i in range(len(m[0]))]
for i in m:
i[0] = 0
print(m)
for j in range(n):
for w in range(B):
if (p[j]) > (w):
m[w][j] = m[w][j-1]
else:
m[w][j] = max(m[w][j-1],m[w-p[j]][j-1]+a[j])
return m[B][n]
I get an incorrect output for this algorithm. where did I go wrong?
f = [i for i in range(n+1)]
m = [f for i in range(B+1)]
This uses the same array f for every position m, so for example if you change m[1][k], you also change m[i][k] for every i. You probably meant to do
m = [[i for i in range(n+1)] for i in range(B+1)]
There might be some other bugs I think, so maybe you should print out the intermediate arrays at some points to check out where the results are not what you'd expect them to be.
UPDATE:
Your initialization seems strange to me. I think it should be just m = [[0]*n for i in range(B+1)] because you need a matrix of zeroes.
it should be for w in range(B+1)
you should not return m[B][n], but max(m[j][n] for j in range(B+1)).
My attempt, which avoids the the matrix altogether and only uses a single array:
m = [0]*(B+1)
for j in range(n):
for w in range(B,p[j]-1,-1):
m[w] = max(m[w], m[w-p[j]] + a[j])
return max(m)

Categories