Many numpy array manipulations in one array - python

I need to translate a matlab code to python numpy code
I have 4 2-dimension arrays (A, B, C and D) and want to create a new one "res".
the code in matlab
index1 = find(A == 2 & B > C);
index2 = find(A == 2 & B >= D & B <= C);
res = uint8(zeros(100,100));
res(index1) = 5;
res(index2) = 4;
in Python/numpy I figured out I can create new arrays like this:
res = ((A == 2) & (B > C)) * 5
res = ((A == 2) & (B >= D) & (B <= C)) * 4
but how can I combine this 2 results in only one array? Like the matlab code does.

The translation (in this case) is almost one-for-one:
index1 = ((A == 2) & (B > C))
index2 = ((A == 2) & (B >= D) & (B <= C))
res = np.zeros((100, 100), dtype='uint8')
res[index1] = 5
res[index2] = 4
Alternatively, you could define res as
res = np.where(A == 2, np.where(B > C, 5, np.where(B >= D, 4, 0)), 0)
though I don't think that helps readability :)
PS. As Mr. E suggests, mask1 might be a better variable name than index1 since index (usually) suggests integer values while mask suggest booleans, which is what we have here.

Related

A function works fine with one number, but not an array. What am I missing?

Pardon my ignorance, but I'm very new to coding in python. I have a pretty simple function; it just needs to make a calculation based on b's relative location to a and c:
a = 6
b = 3
c = 2
def function(a, b, c):
if ((a >= b) & (b >= c)):
return b - c
elif ((a <= b) & (b >= c)):
return a - c
else:
return 0
t = function(a, b, c)
print(t)
When I run it with simple numbers like above, it gives me the right answer no matter what I make b. (In this case 1)
But When I run it with a,b, and c as Numpy Arrays, it only returns b - c across the entire "t" array.
It's not too much different, but here's what I'm using for the array version:
def function(a, b, c):
if ((a >= b) & (b >= c)).any():
return b - c
elif ((a <= b) & (b >= c)).any():
return a - c
else:
return 0
t = function(a, b, c[i>1])
print(t)
(The [i>1] is there because there is a variable amount of array input, and another function will be used for when [i = 0])
I've also tried this:
t = np.where(((prev2 >= Head_ELV) & (Head_ELV >= Bottom_ELV)).any, Head_ELV - Bottom_ELV, 0)
but ran into the same result.
Would a while-loop work better?
I don't think you need looping here as the problem can be solved using array operations. You could try the below, assuming the arrays are of the same length.
# import numpy to be able to work with arrays
import numpy as np
def function(a, b, c):
# declare array t with only zeros
t = np.zeros_like(a)
# declare filters
mask_1 = (a >= b) * (b >= c)
mask_2 = (a <= b) * (b >= c)
# modifying t based on the filters above
t[mask_1] = (b - c)[mask_1]
t[mask_2] = (a - c)[mask_2]
return t
# example 2d arrays
a = np.array([[1800,5], [5,5]])
b = np.array([[3416,2], [3,4]])
c = np.array([[1714,2], [3,4]])
# run function
function(a, b, c)

Automatically simplify redundant arithmetic relations

I am looking for a way to automatically determine, e.g., that (a < 12) & (a < 3) & (c >= 4) is the same as (a < 3) & (c >= 4). I looked into Matlab's symbolic toolbox and SymPy in Python, but these are apparently only capable of simplifying purely Boolean logic (e.g., simplify(a & b | b & a) -> ans=(a & b))
Is there a way of using these symbolic math tools like described above?
Edit
As noted in the comment to #user12750353's answer, I would like to also simplify systems of relations that are concatenated with a Boolean OR, e.g., ((a < 12) & (a < 3) & (c >= 4)) | (a < 1).
SymPy sets can be used to do univariate simplification, e.g. ((x < 3) & (x < 5)).as_set() -> Interval.open(-oo, 3) and sets can be converted back to relationals. The following converts a complex expression to cnf form, separates args with respect to free symbols and simplifies those that are univariate while leaving multivariate arguments unchanged.
def f(eq):
from collections import defaultdict
from sympy import to_cnf, ordered
cnf = to_cnf(eq)
args = defaultdict(list)
for a in cnf.args:
args[tuple(ordered(a.free_symbols))].append(a)
_args = []
for k in args:
if len(k) == 1:
_args.append(cnf.func(*args[k]).as_set().as_relational(k[0]))
else:
_args.append(cnf.func(*args[k]))
return cnf.func(*_args)
For example:
>>> from sympy.abc import a, c
>>> f((a < 1) | ((c >= 4) & (a < 3) & (a < 12)))
(a < 3) & ((c >= 4) | (a < 1))
You can take a look in sympy inequality solvers for some options.
I could apply reduce_inequalities to your problem
from sympy.abc import a, c
import sympy.solvers.inequalities as neq
t = neq.reduce_inequalities([a < 12, a < 3, c >= 4])
And it results
(4 <= c) & (-oo < a) & (a < 3) & (c < oo)
It also works with some more complex examples
as long as you have one variable per inequality.

Naive Recursive Algorithm for Polynomial Multiplication in Python

I am trying to implement the divide-and-conquer algorithm for polynomial multiplication. Here is the pseudocode given in the lecture notes:
where A, B are lists of coefficients of each polynomial, n is the size of the problem (degree - 1) and a_l, b_l are indices of the coefficients of interest.
Here is my attempt at implementing it using Python3:
def poly_mult_dc_naive(A, B, n, a, b):
n = int(n)
a = int(a)
b = int(b)
C = [None] * int(2*n - 1)
if n == 1:
C[0] = A[a] * B[b]
return C[0]
C[0:n-1] = poly_mult_dc_naive(A, B, n//2, a, b)
C[n:2*n-1] = poly_mult_dc_naive(A, B, n//2, a + (n // 2), b + (n // 2))
W = poly_mult_dc_naive(A, B, n/2, a, b + (n // 2))
V = poly_mult_dc_naive(A, B, n/2, a + n/2, b)
C[n // 2:n + (n // 2) - 1] += W + V
return C
However I'm getting strange results. For example let A = [1,2,3,4] B = [4,3,2,1] I get:
[4, None, 8, 3, 6, 12, None, 16, 9, 12, 2, None, 4, 1, 2, None, 8, 3, 4, None, None]
Correct answer is [4, 11, 20, 30, 20, 11, 4]
Could someone please point out where I've gone wrong and how it could be done?
Quick update: I think I've managed to debug my code my using a numpy array for C instead of a list. Here is the updated version:
import numpy as np
def poly_mult_dc_naive(A, B, n: int, a: int, b: int):
C = np.zeros(2*n - 1, dtype=int) # here I changed it from list to np array
if n == 1:
C[0] = A[a] * B[b]
return C[0]
C[0:n-1] = poly_mult_dc_naive(A, B, n//2, a, b)
C[n:2*n-1] = poly_mult_dc_naive(A, B, n//2, a + (n // 2), b + (n // 2))
W = poly_mult_dc_naive(A, B, n//2, a, b + (n // 2))
V = poly_mult_dc_naive(A, B, n/2, a + (n//2), b)
C[(n // 2) : (3*n // 2) - 1] += W + V
return C
BONUS QUESTION: Does anyone know of a better way I could keep the arguments n, a, and b as int types?
I just feel like having to write:
n = int(n)
a = int(a)
b = int(b)
might not be the most elegant way.
There should be no need to coerce n,a,b from float to int. Just use // 2 integer division everywhere (i.e. in the W,V lines). That will "keep" ints as ints.
The line C[n // 2:n + (n // 2) - 1] badly needs parenthesizing, it misreads very easily. I'd write C[(n//2) : (3*n//2)-1]
But I seriously recommend you use numpy vectors, not Python lists. Adding, multiplying etc. are vectorized.

Strange behaviour of simple pycuda kernel

I'm quite new to cuda and pycuda.
I need a kernel that creates a matrix (of dimension n x d) out of an array (1 x d), by simply "repeating" the same array n times:
for example, suppose we have n = 4 and d = 3, then if the array is [1 2 3]
the result of my kernel should be:
[1 2 3
1 2 3
1 2 3
1 2 3]
(a matrix 4x3).
Basically, it's the same as doing numpy.tile(array, (n, 1))
I've written the code below:
kernel_code_template = """
__global__ void TileKernel(float *in, float *out)
{
// Each thread computes one element of out
int y = blockIdx.y * blockDim.y + threadIdx.y;
int x = blockIdx.x * blockDim.x + threadIdx.x;
if (y > %(n)s || x > %(d)s) return;
out[y * %(d)s + x] = in[x];
}
"""
d = 64
n = 512
blockSizex = 16
blockSizey = 16
gridSizex = (d + blockSizex - 1) / blockSizex
gridSizey = (n + blockSizey - 1) / blockSizey
# get the kernel code from the template
kernel_code = kernel_code_template % {
'd': d,
'n': n
}
mod = SourceModule(kernel_code)
TileKernel = mod.get_function("TileKernel")
vec_cpu = np.arange(d).astype(np.float32) # just as an example
vec_gpu = gpuarray.to_gpu(vec_cpu)
out_gpu = gpuarray.empty((n, d), np.float32)
TileKernel.prepare("PP")
TileKernel.prepared_call((gridSizex, gridSizey), (blockSizex, blockSizey, 1), vec_gpu.gpudata, out_gpu.gpudata)
out_cpu = out_gpu.get()
Now, if I run this code with d equals a power of 2 >= 16 I get the right result (just like numpy.tile(vec_cpu, (n, 1)) );
but if I set d equals to anything else (let's say for example 88) I get that every element of the output matrix has the
correct value, except the first column: some entries are right but others have another value, apparently random, same for every wrong element, but different every run,
and also the entries of the first column that have the wrong value are different every run.
Example:
[0 1 2
0 1 2
6 1 2
0 1 2
6 1 2
...]
I really can't figure out what is causing this problem, but maybe it's just something simple that I'm missing...
Any help will be appreciated, thanks in advance!
The bounds checking within your kernel code is incorrect. This
if (y > n || x > d) return;
out[y * d + x] = in[x];
should be:
if (y >= n || x >= d) return;
out[y * d + x] = in[x];
or better still:
if ((y < n) && (x < d))
out[y * d + x] = in[x];
All array valid indexing in the array lies on 0 < x < d and 0 < y < n. By allowing x=d you have undefined behaviour, allowing the first entry in the next row of the output array to be overwritten with an unknown value. This explains why sometimes the results were correct and other times not.

Comparing two numbers without loops or branching in Python

I have to compare two numbers and write greater, then smaller, but I don't know how to get smaller one. I currently have this code:
a = int(input())
b = int(input())
c = round(((a + b) + abs(a - b)) / 2)
x = "should be smaller one"
print("{0}\n{1}".format(c, x))
smaller is : c = round(((a + b) - abs(a - b)) / 2)
If I right understand you:
In [1]: a , b = 3, 4
In [2]: smaller = a if a < b else b
In [3]: smaller
Out[3]: 3
Here you can replace < to other operator

Categories

Resources