I am calculating some values for a certain type of matrix A of varying sizes. Namely the backward error, forward error, condition number, and the error magnification (everything with the infinity norm). My values get calculated and then I am trying to put them into lists, looping through increasing sizes of the matrix A. The problem is that after every loop the values in my lists get overwritten by the current condition number and I don’t understand why. Here is my code.
import numpy as np import math as m from scipy import io, integrate, linalg, signal from scipy.sparse.linalg import eigs sizes = [50, 100, 200, 300, 400] forward_errors = sizes backward_errors = sizes magnification_factors = sizes cond_numbers = sizes number = 0 for n in sizes: A = np.zeros((n, n)) # fill out matrix i = 0 while(i < n): j = 0 while(j < n): A[i, j] = 1.0 / (abs(i - j)**2.0 + 1.0) j = j + 1 i = i + 1 # fill out x_exact x_exact = np.ones((n, 1)) # calculate b b = A.dot(x_exact) # calculate x_approx x_approx = linalg.solve(A, b) # calculate forward error forward_error = linalg.norm(x_approx - x_exact, ord=np.inf) print("forward_error = " + str(forward_error)) # calculate residual, backwards error r = b - A.dot(x_approx) #print("r = " + str(r)) # calculate error magnification error_mag = ((forward_error * linalg.norm(b, ord=np.inf)) / (linalg.norm(r, ord=np.inf) * linalg.norm(x_exact, ord=np.inf))) #print("error_mag = " + str(error_mag)) # calculate inf-norm condition number of A cond_number = linalg.norm(A, ord=np.inf) print("cond_number = " + str(cond_number)) forward_errors[number] = forward_error print(forward_errors) backward_errors[number] = r magnification_factors[number] = error_mag #print("magnification_factors = " + str(magnification_factors)) cond_numbers[number] = cond_number print("cond_numbers = " + str(cond_numbers)) #TODO figure out why these 4 are getting overwritten by cond_number number = number + 1 #TODO figure out why these 4 only print the condition numbers string print("forward_errors = " + str(forward_errors)) print("backward_errors = " + str(backward_errors)) print("magnification_factors = " + str(magnification_factors)) print("cond_numbers = " + str(cond_numbers))
And here is the output using the forward errors as an example since those are short.
forward_error = 3.3306690738754696e-15 cond_number = 3.0733694622250525 [3.3306690738754696e-15, 100, 200, 300, 400] cond_numbers = [3.0733694622250525, 100, 200, 300, 400] forward_error = 4.6629367034256575e-15 cond_number = 3.113350762669095 [3.0733694622250525, 4.6629367034256575e-15, 200, 300, 400] cond_numbers = [3.0733694622250525, 3.113350762669095, 200, 300, 400] forward_error = 5.995204332975845e-15 cond_number = 3.1333484283038167 [3.0733694622250525, 3.113350762669095, 5.995204332975845e-15, 300, 400] cond_numbers = [3.0733694622250525, 3.113350762669095, 3.1333484283038167, 300, 400] forward_error = 7.327471962526033e-15 cond_number = 3.1400148603736495 [3.0733694622250525, 3.113350762669095, 3.1333484283038167, 7.327471962526033e-15, 400] cond_numbers = [3.0733694622250525, 3.113350762669095, 3.1333484283038167, 3.1400148603736495, 400] forward_error = 6.8833827526759706e-15 cond_number = 3.143348136604871 [3.0733694622250525, 3.113350762669095, 3.1333484283038167, 3.1400148603736495, 6.8833827526759706e-15] cond_numbers = [3.0733694622250525, 3.113350762669095, 3.1333484283038167, 3.1400148603736495, 3.143348136604871] forward_errors = [3.0733694622250525, 3.113350762669095, 3.1333484283038167, 3.1400148603736495, 3.143348136604871] backward_errors = [3.0733694622250525, 3.113350762669095, 3.1333484283038167, 3.1400148603736495, 3.143348136604871] magnification_factors = [3.0733694622250525, 3.113350762669095, 3.1333484283038167, 3.1400148603736495, 3.143348136604871] cond_numbers = [3.0733694622250525, 3.113350762669095, 3.1333484283038167, 3.1400148603736495, 3.143348136604871]
I left all those print statements in there behind comments for testing, that was how I figured out everything was being replaced by the condition number. I suspect it must be some simple Python thing that I’m not getting. I just don’t see why or where everything is being overwritten, it is so strange to me. Thank you for reading.
Advertisement
Answer
That is happening due to the way Python handles variable references.
When you did
sizes = [50, 100, 200, 300, 400] forward_errors = sizes backward_errors = sizes magnification_factors = sizes cond_numbers = sizes
You’re basically sharing the variable sizes
reference not it’s value. That means that forward_errors
, backward_errors
, magnification_factors
and cond_numbers
are exactly the same variable to Python.
You have some options to fix that.
1- Using the Copy library
from copy import deepcopy sizes = [50, 100, 200, 300, 400] forward_errors = deepcopy(sizes) backward_errors = deepcopy(sizes) magnification_factors = deepcopy(sizes) cond_numbers = deepcopy(sizes)
2- Simply repeating the values
sizes = [50, 100, 200, 300, 400] forward_errors = [50, 100, 200, 300, 400] backward_errors = [50, 100, 200, 300, 400] magnification_factors = [50, 100, 200, 300, 400] cond_numbers = [50, 100, 200, 300, 400]
You can find more about the topic here.