Skip to content
Advertisement

Values in Python lists getting overwritten

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.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement