Solving equation with for loops python - python

I have arrays like this:
x = np.array([-1,-1,-1,1,-1,-1])
weight = np.array([[0.5,-0.5,0.5,-0.5,0.5,-0.5],
[-0.5,0.5,-0.5,0.5,-0.5,0.5],
[0.5,0.5,0.5,0.5,0.5,0.5]])
print(weight.shape)
bias=np.array([2, 2, 2])
print(bias)
weight = np.transpose(weight)
weight
You can run the above code which results to arrays bias and weight_ham and x:
bias = [2 2 2]
weight = array([[ 0.5, -0.5, 0.5],
[-0.5, 0.5, 0.5],
[ 0.5, -0.5, 0.5],
[-0.5, 0.5, 0.5],
[ 0.5, -0.5, 0.5],
[-0.5, 0.5, 0.5]])
x = array([-1, -1, -1, 1, -1, -1])
Now i want to calculate this equation:
the y_in array should be like this:
y_in = np.zeros((1, len(bias)))
What i don't understand is how can i compute that equation with for loop since i'm not really familiar with how should i write for loops.
if you didn't understand the equation you can see this example below:

I don't understand why you are required to use loops when you are already working with numpy, however the correct way would be:
>>> np.add(bias, np.dot(x[None, :], weight)).flatten()
array([1., 3., 0.])
But if you want loops:
y = []
for index_1, b in enumerate(bias):
sum_ = b
for index_2, val in enumerate(x):
sum_ += x[index_2] * weight[index_2, index_1]
y.append(sum_)
>>> y
[1.0, 3.0, 0.0]
# OR
>>> [b + sum(x_val * w for x_val, w in zip(x, weight[:,i])) for i, b in enumerate(bias)]
[1.0, 3.0, 0.0]

Posting answer for your screenshot problem. You can use the same code for your original problem:
x = np.array([1,1,-1,-1])
weight = np.array([[0.5,-0.5,-0.5,-0.5],
[-0.5,-0.5,-0.5,0.5],
])
bias=np.array([2, 2])
weight = np.transpose(weight)
One Liner:
np.add(bias, np.dot(weight.T, x))
Using Loop:
y_arr = []
for j in range(weight.shape[1]):
y = (bias[j] + np.dot(weight[:,j].T, x))
y_arr.append(y)
y_arr = np.array(y_arr)
y_arr:
array([3., 1.])

Related

Get two neighboring non-nan values in numpy array

Let's say I have a numpy array
my_array = [0.2, 0.3, nan, nan, nan, 0.1, nan, 0.5, nan]
For each nan value, I want to extract the two non-nan values to the left and right of that point (or single value if appropriate). So I would like my output to be something like
output = [[0.3,0.1], [0.3,0.1], [0.3,0.1], [0.1,0.5], [0.5]]
I was thinking of looping through all the values in my_array, then finding those that are nan, but I'm not sure how to do the next part of finding the nearest non-nan values.
Using pandas and numpy:
s = pd.Series([0.2, 0.3, nan, nan, nan, 0.1, nan, 0.5, nan])
m = s.isna()
a = np.vstack((s.ffill()[m], s.bfill()[m]))
out = a[:,~np.isnan(a).any(0)].T.tolist()
Output:
[[0.3, 0.1], [0.3, 0.1], [0.3, 0.1], [0.1, 0.5]]
NB. You can choose to keep or drop the lists containing NaNs.
With NaNs:
out = a.T.tolist()
[[0.3, 0.1], [0.3, 0.1], [0.3, 0.1], [0.1, 0.5], [0.5, nan]]
alternative to handle the single elements:
s = pd.Series([0.2, 0.3, nan, nan, nan, 0.1, nan, 0.5, nan])
m = s.isna()
(pd
.concat((s.ffill()[m], s.bfill()[m]), axis=1)
.stack()
.groupby(level=0).agg(list)
.to_list()
)
Output:
[[0.3, 0.1], [0.3, 0.1], [0.3, 0.1], [0.1, 0.5], [0.5]]
Less elegant than #mozway's answer, but the last list only has one element:
pd.DataFrame({
'left':arr.ffill(),
'right': arr.bfill()
}).loc[arr.isna()].apply(lambda row: row.dropna().to_list(), axis=1).to_list()
For the sake of education, I'll post a pretty straight-forward algorithm for achieving this result, which works by finding the closest index of a value to the left and to the right of each index of a NaN, and filters out any infs at the end:
def get_neighbors(x: np.ndarray) -> list:
mask = np.isnan(x)
nan_idxs, *_ = np.where(mask)
val_idxs, *_ = np.where(~mask)
neighbors = []
for nan_idx in nan_idxs:
L, R = -float("inf"), float("inf")
for val_idx in val_idxs:
if val_idx < nan_idx:
L = max(L, val_idx)
else:
R = min(R, val_idx)
# casting to list isn't strictly necessary, you'll just end up with a list of arrays
neighbors.append(list(x[[i for i in (L, R) if i > 0 and i < float("inf")]]))
return neighbors
Output:
>>> get_neighbors(my_array)
[[0.3, 0.1], [0.3, 0.1], [0.3, 0.1], [0.1, 0.5], [0.5]]
The nested for loop has a worst-case runtime of O((n / 2)^2) where n is the number of elements of x (worst case occurs when exactly half the elements are NaN).
I was eager to check how could use just NumPy to solve this problem as an exercise. After some hours I could reach a solution :), but as I think it will be inefficient comparing to pandas as mentioned by Mozway, I didn't optimized the code further (it can be optimized; if conditions may could be cured and merged in other sections):
my_array = np.array([np.nan, np.nan, 0.2, 0.3, np.nan, np.nan, np.nan, 0.1, 0.7, np.nan, 0.5])
nans = np.isnan(my_array).astype(np.int8) # [1 1 0 0 1 1 1 0 0 1 0]
zeros = np.where(nans == 0)[0] # [ 2 3 7 8 10]
diff_nan = np.diff(nans) # [ 0 -1 0 1 0 0 -1 0 1 -1]
start = np.where(diff_nan == 1)[0] # [3 8]
end = np.where(diff_nan == -1)[0] + 1 # [ 2 7 10]
mask_start_nan = np.isnan(my_array[0]) # True
mask_end_nan = np.isnan(my_array[-1]) # False
if mask_end_nan: start = start[:-1] # [3 8]
if mask_start_nan: end = end[1:] # [ 7 10]
inds = np.dstack([start, end]).squeeze() # [[ 3 7] [ 8 10]]
initial = my_array[inds] # [[0.3 0.1] [0.7 0.5]]
repeats = np.diff(np.where(np.concatenate(([nans[0]], nans[:-1] != nans[1:], [True])))[0])[::2] # [2 3 1]
if mask_end_nan: repeats = repeats[:-1] # [2 3 1]
if mask_start_nan: repeats = repeats[1:] # [3 1]
result = np.repeat(initial, repeats, axis=0) # [[0.3 0.1] [0.3 0.1] [0.3 0.1] [0.7 0.5]]
if mask_end_nan: result = np.array([*result, np.array(my_array[zeros[-1]])], dtype=object)
if mask_start_nan: result = np.array([np.array(my_array[zeros[0]]), *result], dtype=object)
# [array(0.2) array([0.3, 0.1]) array([0.3, 0.1]) array([0.3, 0.1]) array([0.7, 0.5])]
I don't know if there be a much easier solution by NumPy; I implemented what came to my mind. I believe that this code can be greatly improved (I will do it if I find a free time).

Finding maximum per row when condition is met

I'm having the following relatively simple problem. I have two arrays storing x and y coordinates per timestep, e.g.
x = [[0, 1, 2, 3], [0.1, 1.1, 2.1, 3.1]]
y = [[0.5, 0.5, 0.5, 0.5], [0.51, 0.52, 0.49, 0.53]]
in which 2 timesteps are represented (2 rows). What I would like is to find the maximum y coordinate per row when the condition x >= 1 and x <= 2.5 is met.
How can I define a function which returns an array of 2 columns with just the max(y) per row when the spatial x condition is met?
I've tried np.where without luck. The result the function should return is:
[0.5, 0.52]
You can use numpy's mask function. The mask function 'masks' the true values, so the conditions are flipped.
import numpy as np
x = [[0, 1, 2, 3], [0.1, 1.1, 2.1, 3.1]]
y = [[0.5, 0.5, 0.5, 0.5], [0.51, 0.52, 0.49, 0.53]]
x = np.array(x)
y = np.array(y)
y_masked = np.ma.masked_where((x>2.5) | (x<1), y)
result = np.max(y_masked, axis = 1)
print(result)
Not very pretty, but using pure Python (no numpy) you could combine zip, filter, and max:
>>> x = [[0,1,2,3],[0.1,1.1,2.1,3.1]]
>>> y = [[0.5,0.5,0.5,0.5],[0.51,0.52,0.49,0.53]]
>>> [max(filter(lambda t: 1.0 <= t[0] <= 2.5, zip(rx, ry)), key=lambda t: t[1])[1]
... for rx, ry in zip(x, y)]
...
[0.5, 0.52]
Or a bit shorter, using a list comprehension to filter and reverse order of the tuple so max can use natural ordering:
>>> [max((y, x) for (x, y) in zip(rx, ry) if 1.0 <= x <= 2.5)[0]
... for rx, ry in zip(x, y)]
...
[0.5, 0.52]
As you were suggesting a Numpy solution:
import numpy as np
x = np.array([[0, 1, 2, 3], [0.1, 1.1, 2.1, 3.1]])
y = np.array([[0.5, 0.5, 0.5, 0.5], [0.51, 0.52, 0.49, 0.53]])
print([np.max(y[i][(x[i] >= 1) & (x[i] <= 2.5)]) for i in range(len(x))])
gives
[0.5, 0.52]

PyTorch: index 2D tensor with 2D tensor of row indices

I have a torch tensor a of shape (x, n) and another tensor b of shape (y, n) where y <= x. every column of b contains a sequence of row indices for a and what I would like to be able to do is to somehow index a with b such that I obtain a tensor of shape (y, n) in which the ith column contains a[:, i][b[:, i]] (not quite sure if that's the correct way to express it).
Here's an example (where x = 5, y = 3 and n = 4):
import torch
a = torch.Tensor(
[[0.1, 0.2, 0.3, 0.4],
[0.6, 0.7, 0.8, 0.9],
[1.1, 1.2, 1.3, 1.4],
[1.6, 1.7, 1.8, 1.9],
[2.1, 2.2, 2.3, 2.4]]
)
b = torch.LongTensor(
[[0, 3, 1, 2],
[2, 2, 2, 0],
[1, 1, 0, 4]]
)
# How do I get from a and b to c
# (so that I can also assign to those elements in a)?
c = torch.Tensor(
[[0.1, 1.7, 0.8, 1.4],
[1.1, 1.2, 1.3, 0.4],
[0.6, 0.7, 0.3, 2.4]]
)
I can't get my head around this. What I'm looking for is a method that will not yield the tensor c but also let me assign a tensor of the same shape as c to the elements of a which c is made up of.
I try to use index_select but it supports only 1-dim array for index.
bt = b.transpose(0, 1)
at = a.transpose(0, 1)
ct = [torch.index_select(at[i], dim=0, index=bt[i]) for i in range(len(at))]
c = torch.stack(ct).transpose(0, 1)
print(c)
"""
tensor([[0.1000, 1.7000, 0.8000, 1.4000],
[1.1000, 1.2000, 1.3000, 0.4000],
[0.6000, 0.7000, 0.3000, 2.4000]])
"""
It might be not the best solution, but hope this helps you at least.

Piecewise function in numpy with multiple arguments

I tried to define a function (tent map) as following:
def f(r, x):
return np.piecewise([r, x], [x < 0.5, x >= 0.5], [lambda r, x: 2*r*x, lambda r, x: 2*r*(1-x)])
And r, x will be numpy arrays:
no_r = 10001
r = np.linspace(0, 4, no_r)
x = np.random.rand(no_r)
I would like the result to be a numpy array matching the shapes of r and x, calculated using each pairs of elements of arrays r and x with the same indicies. For example if r = [0, 1, 2, 3] and x = [0.1, 0.7, 0.3, 1], the result should be [0, 0.6, 1.2, 0].
An error occured: "boolean index did not match indexed array along dimension 0; dimension is 2 but corresponding boolean dimension is 10001"
So what should I do to achieve the intended purpose?
what you want to get as result can be done with np.select such as:
def f(r, x):
return np.select([x < 0.5,x >= 0.5], [2*r*x, 2*r*(1-x)])
Then with
r = np.array([0, 1, 2, 3])
x = np.array([0.1, 0.7, 0.3, 1])
print (f(r,x))
[0. 0.6 1.2 0. ]
EDIT: in this case, with only 2 conditions that are exclusive, you can also use np.where:
def f(r,x):
return np.where(x<0.5,2*r*x, 2*r*(1-x))
will give the same result.

Linear programming using scipy.optimize.linprog returns suboptimal solution

I'm trying to solve the following linear programming problem in Python 2.7 and for some reason, linprog is not returning the correct results.
Minimize: -x2 -x3
such that:
x0 + 0.33*x2 + 0.67*x3 = 0.5
x1 + 0.67*x2 + 0.33*x3 = 0.5
x0 + x1 + x2 + x3 = 1.0
Here's my code:
from scipy.optimize import linprog
a_eq = [[1.0, 0.0, 0.33, 0.67],
[0.0, 1.0, 0.67, 0.33],
[1, 1, 1, 1]]
b_eq = [0.5, 0.5, 1.0]
c = [0, 0, -1.0, -1.0]
x = linprog(c=c, A_eq=a_eq, b_eq=b_eq)
print x
Here's the output of the above:
fun: -0.0
message: 'Optimization terminated successfully.'
nit: 4
slack: array([], dtype=float64)
status: 0
success: True
x: array([ 0.5, 0.5, 0. , 0. ])
Clearly, the following solution is more optimal:
x: array([0.0, 0.0, 0.5, 0.5])
which makes the objective function value:
fun: -1.0
I did find some issues reported in github. Could this be what I'm facing or am I doing something wrong? Any help will be greatly appreciated! Thanks.
I did find some issues reported in github. Could this be what I'm facing...?
Exactly:
It turns out that A_eq in the problem is rank-deficient. After finding and removing rows that are a linear combination of others, linprog's solution agrees with the other.
The matrix a_eq is rank deficient. The last row is a linear combination of the first two rows. This makes the row redundant for the constraint so we can simply remove it and the corresponding entry in b_eq:
a_eq = [[1.0, 0.0, 0.33, 0.67],
[0.0, 1.0, 0.67, 0.33]]
b_eq = [0.5, 0.5]
This results in the optimal solution x: array([ 0. , 0. , 0.5, 0.5]).

Categories

Resources