-2

I need to make calculations using two lists each with 36 elements in them. The calculation must use one value in each list using all combinations. Example:

listx = [x1 , x2 , x3 , ... , x36] listy = [y1 , y2 , y3 , ... , y36]

F(x,y) = ((y-x)*(a/b))+x

x and y in F(x,y) must assume all combinations inside listx and listy. Results should be a matrix of (36 x 36)

This is what I've tried so far:

listx = np.arange(-0.05,0.301,0.01)
listy = np.arange(-0.05,0.301,0.01)

for x in listx:
    for y in listy:

F = ((y-x)*(a/b))+x

print(F)
  • 2
    What have you tried so far? If we do your homework for you how will you learn? – TheQAGuy Sep 13 '22 at 20:28
  • This is what I've tried so far: defined the vectors containing all the values to be iterated. listx = np.arange(-0.05,0.301,0.01) listy = np.arange(-0.05,0.301,0.01) Then tried using for loops: for x in listx: for y in listy: F = ((y-x)*(a/b))+x print(F) and the result is just one value – Renan Madruga Sep 13 '22 at 20:52
  • 1
    Don't put code in a comment - edit your question. Comment code is hard to read. Have you read enough basic Python to know how to accumulate values in a simple iteration? Your `F` gets changed each time through the loop, without saving the previous values. Does a `list comprehension` mean anything to you? – hpaulj Sep 13 '22 at 22:27
  • 1
    I suspect you can do this with `numpy` arrays without iterations (in Python). Hint - `np.meshgrid` can generate all combinations. But getting it working with list and list iterations would be a good learning exercise. – hpaulj Sep 13 '22 at 22:29
  • Welcome to Stack Overflow. If you had trouble [looking for an answer yourself](https://meta.stackoverflow.com/questions/261592), it's because "combinations" is the **wrong word** for what you want. – Karl Knechtel Sep 13 '22 at 22:45
  • Thanks for the tips. I'm a beginner and I was wrong to not put more effort in pursuing the solution for me. Not quite fully familiar with Stack Overflow rules. I'll try harder next time. – Renan Madruga Sep 14 '22 at 12:04

1 Answers1

1

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.

t.o.
  • 832
  • 6
  • 20