Reputation: 15
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.
Upvotes: 0
Views: 45
Reputation: 944
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.
Upvotes: 1