Reputation: 391
I have generated this function and I am passing through some input parameters (i,j,t) and I do some things with it. Now if you look at the output you'll see that I have some print functions labelled as Test1 and Test2, and what I am confused about is why there is a discrepancy between the two tests since from my perspective they ought to print the same exact thing for the input (1,1,1).
The first round of testing the two results are similar, which is great. However after that test it seems like the input parameters that I put in get updated from (1,1,1) to (2,2,1). This strange update also appears to happen right in the beginning of the first for-loop, and I am hoping to try and understand why this update is happening.
I don't really need the code fixed persay because introducing the x_coord and y_coord variables at the start of the function seems to alleviate the issue that I am having and does what I want it to. But if someone could help me to understand why this update of the 'i' and 'j' input is happening and why the test print statements are not identical that would be great!
model = ConcreteModel()
Imax = 3
Jmax = 3
Tmax = 1
model.Iset = RangeSet(1,Imax) #e.g. i = {1, 2, 3}
model.Jset = RangeSet(1,Jmax)
model.Tset = RangeSet(1,Tmax)
model.immigration = Var(model.Iset, model.Jset, model.Tset, initialize = 1)
model.inf_b4treat = Var(model.Iset, model.Jset, model.Tset, initialize=1)
model.foo = Var(model.Iset, model.Jset, model.Tset, initialize=1)
def get_neighbours(i,j,t):
x_coord = i
y_coord = j
rowbound = Imax + 1
colbound = Jmax + 1
neighbours = [
(i - 1, j - 1, t), (i - 1, j, t), (i - 1, j + 1, t),
(i, j - 1, t), (i, j + 1, t),
(i + 1, j - 1, t), (i + 1, j, t), (i + 1, j + 1, t),
]
print(f"Neighbours of cell ({i},{j},{t}): {neighbours}")
print("")
valid_tuples = []
invalid_tuples = []
# for each tuple in neighbours, we will print out the good and bad coordinates.
print(f"First.Test1 = ({i},{j},{t})")
print(f"First.Test2 = ({x_coord},{y_coord},{t})")
print("")
for (i,j,t) in neighbours:
if not 0 < i < rowbound or not 0 < j < colbound:
#print(f"Invalid Tuple --> ({i},{j},{t})")
invalid_tuples.append((i,j,t))
else:
#print(f"Valid Tuple --> ({i},{j},{t})")
valid_tuples.append((i,j,t))
print(f"Second.Test1 = ({i},{j},{t}) ")
print(f"Second.Test2 = ({x_coord},{y_coord},{t})")
print("")
print(f"Invalid Tuples: {invalid_tuples}")
print(f"Valid Tuples: {valid_tuples}")
print("")
immigration_value_ijt = 0
for (i,j,t) in valid_tuples:
immigration_value_ijt += value(model.inf_b4treat[i,j,t])
print(f"Quantity Immigrating to cell.Test1 ({i},{j},{t}): {immigration_value_ijt}")
print(f"Quantity Immigrating to cell.Test2 ({x_coord},{y_coord},{t}): {immigration_value_ijt}")
print("")
print(f"Third.Test1 = ({i},{j},{t})")
print(f"Third.Test2 = ({x_coord},{y_coord},{t})")
print("")
get_neighbours(1,1,1)
Output:
Neighbours of cell (1,1,1): [(0, 0, 1), (0, 1, 1), (0, 2, 1), (1, 0, 1), (1, 2, 1), (2, 0, 1), (2, 1, 1), (2, 2, 1)]
First.Test1 = (1,1,1)
First.Test2 = (1,1,1)
Second.Test1 = (2,2,1)
Second.Test2 = (1,1,1)
Invalid Tuples: [(0, 0, 1), (0, 1, 1), (0, 2, 1), (1, 0, 1), (2, 0, 1)]
Valid Tuples: [(1, 2, 1), (2, 1, 1), (2, 2, 1)]
Quantity Immigrating to cell.Test1 (2,2,1): 3
Quantity Immigrating to cell.Test2 (1,1,1): 3
Third.Test1 = (2,2,1)
Third.Test2 = (1,1,1)
Upvotes: 0
Views: 58
Reputation: 2540
You are shadowing i,j,t with the for loop and the loop sets the new value with each iteration. So the final result is the last entry of the neighbors list.
Here's some print statements show what is happening:
def test_func(a, b, c):
l1 = [(0, 0, 1), (0, 1, 2), (2, 2, 1)]
print(f'Before a {a} id {id(a)}, b {b} id {id(b)}, c {c} id {id(c)}\n')
# since three variable are specified, each tuple entry is unpacked
# into the variables, which are a, b and c
for (a, b, c) in l1: # The parenthesis don't do anything and aren't needed
print(f'Inside a {a} id {id(a)}, b {b} id {id(b)}, c {c} id {id(c)}')
print(f'Inside a is type {type(a)}')
print(f'\nAfter a {a} id {id(a)}, b {b} id {id(b)}, c {c} id {id(c)}')
# just a single variable name would be the entire tuple
for entry_tuple in l1: # The parenthesis don't do anything and aren't needed
print(f'Entry tuple is {entry_tuple} and the type is {type(entry_tuple)}')
print(f'At end a is type {type(a)}')
test_func(1, 1, 1)
Output:
Before a 1 id 94439557494624, b 1 id 94439557494624, c 1 id 94439557494624
Inside a 0 id 94439557494592, b 0 id 94439557494592, c 1 id 94439557494624
Inside a is type <class 'int'>
Inside a 0 id 94439557494592, b 1 id 94439557494624, c 2 id 94439557494656
Inside a is type <class 'int'>
Inside a 2 id 94439557494656, b 2 id 94439557494656, c 1 id 94439557494624
Inside a is type <class 'int'>
After a 2 id 94439557494656, b 2 id 94439557494656, c 1 id 94439557494624
Entry tuple is (0, 0, 1) and the type is <class 'tuple'>
Entry tuple is (0, 1, 2) and the type is <class 'tuple'>
Entry tuple is (2, 2, 1) and the type is <class 'tuple'>
At end a is type <class 'int'>
Is that what you were wondering?
Upvotes: 1