So I think the issue is that you are having trouble conceptualizing the grid that these solutions are supposed to be stored in. This calculation is good because it is an introduction to certain optimizations and additionally there are a few ways to do it. I'll show you the three I threw together.
First, you could do it with lists and loops, which is very inefficient (numpy
is just to show the shape):
import numpy as np
x, y = [], []
length = 35
for i in range(length+1):
x.append(i/length) # Normalizing over the range of the grid
y.append(i/length) # to compare to later example
def func(x, y, a, b):
return ((y-x)*(a/b))+x
a=b=1 # Set a value for a and b
row = []
for i in x:
column = []
for j in y:
column.append(func(i,j,a,b))
row.append(column)
print(row)
print(np.shape(row))
This will output a solution assuming a
and b
are known, and it is a 36x36 matrix. To make the matrix, we have to create a large memory space which I called row
and smaller memory spaces that are recreated each iteration of the loop I called column
. The inner-most loop appends the values to the column
list, while the evaluated column
lists are appended to the top level row
list. It will then have a matrix-esque appearance even if it is just a list of lists.
A more efficient way to do this is to use numpy
. First, we can keep the loops if you wish and do the calculation with numpy
arrays:
import numpy as np
x = y = np.linspace(0,1,36)
result = np.zeros((len(x), len(y)))
F = lambda x,y,a,b: ((y-x)*(a/b))+x
a=b=1
for idx, i in enumerate(x):
for jdx, j in enumerate(y):
result[idx, jdx] = F(i,j,a,b) # plug in value at idx, jdx grip point
print(result)
print(result.shape)
So here we create the grid using linspace
and I just chose values from 0 to 1 in 36 steps. After this, I create the grid we will store the solutions in by making a numpy
array with dimensions given by the length of the x
and y
arrays. Finally The function is created with a lambda
function, which serves the same purpose of the def
previously, just in one line. The loop is kept for now, which iterates over the values i, j
and indexes of each idx, jdx
. The results are added into the allocated storage at each index with result[idx, jdx] = F(i,j,a,b)
.
We can do better, because numpy
exists to help remove loops in calculations. Instead, we can utilize the meshgrid
function to create a matrix and evaluate the function with it, as so:
import numpy as np
x = y = np.linspace(0,1,36)
X, Y = np.meshgrid(x,y)
F = lambda x,y,a,b: ((y-x)*(a/b))+x
a=b=1
result = F(X,Y,a,b) # Plug in grid directly
print(result.T)
print(result.shape)
Here we use the numpy
arrays and tell meshgrid
that we want a 36x36 array with these values at each grid point. Then we define the lambda
function as before and pass the new X
and Y
to the function. The output does not require additional storage or loops, so then we get the result.
It is good to practice using numpy
for any calculation you want to do, because they can usually be done without loops.