Problem with np.vectorize function in Python - python

I have created this code as below:
def scalar_function(x, y):
if x <= y:
z = x*y
else:
z = x/y
return z
And
def vector_function(x, y):
vfunc = np.vectorize(scalar_function)
return vfunc
But when I try to put: vector_function([1, 2, 3, 4], 2), the output is <numpy.vectorize at 0x226a1d9aeb8> instead of resulting array of numbers.
Can anyone point out my mistake? Thanks.

You have return return vfunc which return Vectorized function That you got. you may want return vfunc(x,y)
>>> def vector_function(x, y):
vfunc = np.vectorize(scalar_function)
return vfunc(x, y)
>>> vector_function([1, 2, 3, 4], 2)
array([2, 4, 1, 2])

There is no need for np.vectorize:
x = np.asarray(x)
y = np.asarray(y)
np.where(x <= y, x*y, x/y)
does the same and is actually vectorized.

Related

Differentiating a multivariable function w.r.t different dimensions, using *args in python

Following is my attempt to create a function to differentiate multivariable functions, but as you see it only seems to be able to differentiate with respect to the first positional argument (namely x). How can I extend this to be able to take partial derivatives with respect to y and z?
def firstderivative(func,x,*args):
return((func(x+0.001,*args)-func(x-0.001,*args))/0.002)
def afunc(x,y,z):
return(x*y+x*z+y*z)
print(firstderivative(afunc,2,4,5))
You can treat args as a list, after converting it from tuple.
def firstderivative(func, n, *args):
# args[0] is x, args[1] is y and args[2] is z
args_0 = list(args)
args_0[n] -= 0.001
args_1 = list(args)
args_1[n] += 0.001
return ((func(*args_1) - func(*args_0)) / 0.002)
def afunc(x, y, z):
return (x * y + x * z + y * z)
print(firstderivative(afunc, 0, 2, 4, 5)) # x
print(firstderivative(afunc, 1, 2, 4, 5)) # y
print(firstderivative(afunc, 2, 2, 4, 5)) # z

z3 giving a surprising answer

I tried this:
import z3
n,x,y,z = z3.Ints('n x y z')
s = z3.Solver()
s.add(4/n==1/x+1/y+1/z)
s.add(x>0)
s.add(n>0)
s.add(y>0)
s.add(z>0)
s.check()
s.model()
and I get:
[x = 1, n = 2, z = 3, y = 1, div0 = [(1, 1) → 1, (4, 2) → 2, else → 0], mod0 = [(1, 3) → 1, else → 0]]
But 4/2 does not equal 1/1+1/1+1/3.
What am I doing wrong?
You've declared n, x, y, z as integers. So division is done as an integer, giving you 1/1 = 1 and 1/3 = 0; hence satisfying the equality 2=2.
The obvious thing to do is to use Real values for this problem.
Changing the declaration to:
n,x,y,z = z3.Reals('n x y z')
produces:
[z = 1, y = 1, n = 4/3, x = 1]
which does satisfy the equation you posed trivially.
In case you actually do want n, x, y, z to be integers; then you should convert them to reals before you divide, like this:
import z3
n,x,y,z = z3.Ints('n x y z')
s = z3.Solver()
s.add(4/z3.ToReal(n)==1/z3.ToReal(x)+1/z3.ToReal(y)+1/z3.ToReal(z))
s.add(x>0)
s.add(n>0)
s.add(y>0)
s.add(z>0)
print(s.check())
print(s.model())
This prints:
sat
[n = 4, x = 3, z = 3, y = 3]
again satisfying your constraints.

sympy collect undefined functions

I have an expression in sympy that is a linear combination of an evaluated function, f. Schematically
expr = Sum_{m,n} c_{m,n} f(x+a_m,y+a_n)
where c_{m,n} is a coefficient depending on the variables x,y. A very simple example is
import sympy as sp
x, y = sp.symbols("x, y")
f = sp.Function("f")(x,y)
expr = 0
for i in range(0,3):
expr += (x-i)* f.subs({x: x+2*i, y: y+3*i})
In my actual code expr is the result of a long succession of sums and the function g not simplify like here. Is there an efficient way of grouping functions with different argument together, like collect(expr) does for polynomials? What I am after is to obtain a structured list:
In: someFunction(...)
Out: [..., [c_{m,n}, x+a_m, y+a_n ], ...]
in the example above
In: someFunction(expr)
Out: [[x, x, y], [x - 1, x + 2, y + 3], [x - 2, x + 4, y + 6]]
I'm not sure if this does exactly what you want but you can use pattern matching:
In [27]: expr
Out[27]: x⋅f(x, y) + (x - 2)⋅f(x + 4, y + 6) + (x - 1)⋅f(x + 2, y + 3)
In [28]: a, b, c = symbols('a, b, c', cls=Wild)
In [29]: pattern = a*f(b, c)
In [30]: for term in Add.make_args(expr):
...: print(term.match(pattern))
...:
{b_: x, c_: y, a_: x}
{b_: x + 2, c_: y + 3, a_: x - 1}
{b_: x + 4, c_: y + 6, a_: x - 2}

Normalize function

To normalize, would this work?:
def normalize(arr, axis):
x = [i for i in range(len(arr.shape))]
a = x[0]
x[0] = x[axis]
x[axis] = a
arr = arr.transpose(x)
return (arr/np.sum(arr**2, axis=0)**0.5).transpose(tuple(x))
You can just do x = x / sum(x) if you want to normalize. This works on numpy arrays:
import numpy
x = [1, 2, 3]
x = numpy.array(x)
x = x / sum(x)

Create a new numpy array with values based on coordinates and external variables

Suppose I have a function that receive 3 parameters:
def foo(x, y, fac):
return x * y * fac
How do I create a 2D numpy array, who's values will be the result of the above function when the parameters are the new array own x, y values?
Numpy already has a function called meshgrid. You would say:
x = np.array([1,2,3])
y = np.array([4,5,6])
X, Y = np.meshgrid(x, y)
result = foo(X, Y, 0.03)
I guess this is what you want to accomplish. I don't know if you can speed it up by getting rid of the loop though.
import numpy as np
def foo(x, y, fac):
return x * y * fac
def make2dmatrix(a, b):
C = np.zeros(shape=[a.size, b.size])
for i in range(a.size):
C[i, :] = foo(a[i], b, fac=0.5)
return C
if __name__ == '__main__':
a = np.array([1, 2, 3])
b = np.array([2, 3, 4])
print (make2dmatrix(a, b))
Outcome
[[ 1. 1.5 2. ]
[ 2. 3. 4. ]
[ 3. 4.5 6. ]]

Categories

Resources