How to write this function jax.jit-able> - jax

def factory(points):
points.sort()
#jax.jit
def fwd(x):
for i in range(1, len(points)):
if x < points[i][0]:
return (points[i][1] - points[i - 1][1]) / (points[i][0] - points[i - 1][0]) * x + (points[i][1] - (points[i][1] - points[i - 1][1]) / (points[i][0] - points[i - 1][0]) * points[i][0])
i = len(points) - 1
return (points[i][1] - points[i - 1][1]) / (points[i][0] - points[i - 1][0]) * x + (points[i][1] - (points[i][1] - points[i - 1][1]) / (points[i][0] - points[i - 1][0]) * points[i][0])
return fwd
I want to write a function that creates jitted function, given argument: points, a list contain pairs of numbers.
I aware that if/else statement can't be jitted and jax.lax.cond() allow conditions but I want something like a break as you can see in the above code.
Is there any way to work with conditions?

The challenge in converting this to JAX-compatible is that your function relies on control flow triggered by values in the array; to make this compatible with JAX you should convert it to a vector-based operation. Here's how you might express your operation in terms of np.where rather than for loops:
def factory_v2(points):
points.sort()
def fwd(x):
matches = np.where(x < points[1:, 0])[0]
i = matches[0] + 1 if len(matches) else len(points) - 1
return (points[i, 1] - points[i - 1, 1]) / (points[i, 0] - points[i - 1, 0]) * x + (points[i, 1] - (points[i, 1] - points[i - 1, 1]) / (points[i, 0] - points[i - 1, 0]) * points[i, 0])
return fwd
x = 2
points = np.array([[4, 0], [2, 1], [6, 5], [4, 6], [5, 7]])
print(factory(points)(x))
# 3.0
print(factory_v2(points)(x))
# 3.0
This is closer to a JAX-compatible operation, but unfortunately it relies on creating dynamically-shaped arrays. You can get around this by using the size argument to jnp.where. Here's a JAX-compatible version that uses the JAX-only size and fill_value arguments to jnp.where to work around this dynamic size issue:
import jax
import jax.numpy as jnp
def factory_jax(points):
points = jnp.sort(points)
#jax.jit
def fwd(x):
i = 1 + jnp.where(x < points[1:, 0], size=1, fill_value=len(points) - 2)[0][0]
return (points[i, 1] - points[i - 1, 1]) / (points[i, 0] - points[i - 1, 0]) * x + (points[i, 1] - (points[i, 1] - points[i - 1, 1]) / (points[i, 0] - points[i - 1, 0]) * points[i, 0])
return fwd
print(factory_jax(points)(x))
# 3.0
If I've understood the intended input shapes for your code, I believe this should compute the same results as your orginal function.

Related

How do I store factors of polynomials in a list in sympy?

Suppose I have x^6-1 that I would like to factor, using .factor I get my irreducible factors, but I want those factors in a list. I tried using .factor_list() But it doesn't give me my desired result instead stores them in a tuple and there is always a 1 beside the factors. I want each factored polynomial in a list on its own, how can I do that if possible?
Like for example,
from sympy import Symbol, factor, Poly
x = Symbol('x')
p = x**6 - 1
factors = factor(p)
factors
that gives me these factors 4 irreducible factors, how do I store them in a list not as a tuple?
You can break a product into a list of factors by forcing the factored result to be treated like a product (whether it is or not); this will give you a tuple of factors. You can use list to change this to a list if needed:
>>> from sympy import Mul
>>> list(Mul.make_args(factor(x**6-1)))
[x + 1, x - 1, x**2 + x + 1, x**2 - x + 1]
You said "I want each factored polynomial in a list on its own, how can I do that if possible"; is this what you mean:
>>> [[i] for i in Mul.make_args(factor(x**6-1))]
[[x + 1], [x - 1], [x**2 + x + 1], [x**2 - x + 1]]
What do you want to do with arguments that are repeated?
>>> [b for b,e in factor_list((x+1)*(x**6-1))[1] for i in range(e)]
[x - 1, x + 1, x + 1, x**2 - x + 1, x**2 + x + 1]
>>> [b for b,e in factor_list((x+1)*(x**6-1))[1]]
[x - 1, x + 1, x + 1, x**2 - x + 1, x**2 + x + 1]
>>> from collections import Counter
>>> [b**(e*c) for (b,e),c in Counter(factor_list((x+1)*(x**6-1))[1]).items()]
[x - 1, (x + 1)**2, x**2 - x + 1, x**2 + x + 1]
I don't think that last step should be necessary to combine like factors. I will report that as a bug since the docstring shows another example in which a factor with multiplicity of 2 appears once in a tuple.
The output of factor_list is the leading coefficient and then a list of tuples of monic irreducible factors along with their multiplicity:
In [13]: factor_list(x**6 - 1)
Out[13]:
⎛ ⎡ ⎛ 2 ⎞ ⎛ 2 ⎞⎤⎞
⎝1, ⎣(x - 1, 1), (x + 1, 1), ⎝x - x + 1, 1⎠, ⎝x + x + 1, 1⎠⎦⎠
You can just extract the part of the return value that you want from the factor_list output:
In [12]: [f for f, m in factor_list(x**6 - 1)[1]]
Out[12]:
⎡ 2 2 ⎤
⎣x - 1, x + 1, x - x + 1, x + x + 1⎦
I guess you could use as_terms() method
factors.as_terms()[1]
This would produce the following list:
[x - 1, x + 1, x**2 - x + 1, x**2 + x + 1]

"No loop matching the specified signature and casting was found for ufunc solve" when trying to use GEKKO OPTIMIZER

I am trying to optimize my FEA truss solution using GEKKO. So I defined all the FEA solution as one function and tried making the forces as variables.SO the goal is to mimimize the forces with one constraint (sum of all forces=-100000).But after i run my code i get an error that I could not fix it googling also did not help(I am new to python).I will be grateful if someone could tell me where the problem is.Thanks in advance.
try:
from gekko import GEKKO
except:
# pip install gekko
import pip
pip.main(['install','gekko'])
from gekko import GEKKO
# from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
# numElem=11
# numNodes=6
def calculate_truss_force(force):
# defined coordinate system
x_axis = np.array([1, 0])
y_axis = np.array([0, 1])
# elements coordinates
elemNodes = np.array([[0, 1], [0, 2], [1, 2], [1, 3],
[0, 3], [2, 3], [2, 5], [3, 4], [3, 5], [2, 4], [4, 5]])
# nodes coordinates
nodeCords = np.array([
[0.0, 0.0], [0.0, 100.0],
[100.0, 0.0], [100.0, 100.0],
[200.0, 0.0], [200.0, 100.0]])
modE = 200000
Area = 200
# assembling the model
numElem = elemNodes.shape[0]
numNodes = nodeCords.shape[0]
xx = nodeCords[:, 0]
yy = nodeCords[:, 1]
EA = modE * Area
tdof = 2 * numNodes # total number of degrees of freedom
disps = np.zeros((tdof, 1))
# force = np.zeros((tdof, 1))
sigma = np.zeros((numElem, 1))
stiffness = np.zeros((tdof, tdof))
np.set_printoptions(precision=3)
# applying the load
# force[3] = -20000.0
# force[7] = -50000.0
# force[11] = -30000.0
# defined boundary
presDof = np.array([0, 1, 9])
for e in range(numElem):
indice = elemNodes[e, :]
elemDof = np.array([indice[0] * 2, indice[0] * 2 + 1, indice[1] * 2, indice[1] * 2 + 1]) #dof corresponding to the global stifnessmatrix
xa = xx[indice[1]] - xx[indice[0]] #length of the elemnts in x dir
ya = yy[indice[1]] - yy[indice[0]] #lenth of the elemnt in y dir
len_elem = np.sqrt(xa * xa + ya * ya)
c = xa / len_elem
s = ya / len_elem
k1 = (EA / len_elem) * np.array([[c * c, c * s, -c * c, -c * s],
[c * s, s * s, -c * s, -s * s],
[-c * c, -c * s, c * c, c * s],
[-c * s, -s * s, c * s, s * s]])
stiffness[np.ix_(elemDof, elemDof)] += k1 # add elem K to the global K
actDof = np.setdiff1d(np.arange(tdof), presDof)
disp1 = np.linalg.solve(stiffness[np.ix_(actDof, actDof)], force[np.ix_(actDof)])
disps[np.ix_(actDof)] = disp1
# stresses at elements
for e in range(numElem):
indice = elemNodes[e, :]
elemDof = np.array([indice[0] * 2, indice[0] * 2 + 1, indice[1] * 2, indice[1] * 2 + 1])
xa = xx[indice[1]] - xx[indice[0]]
ya = yy[indice[1]] - yy[indice[0]]
len_elem = np.sqrt(xa * xa + ya * ya)
c = xa / len_elem
s = ya / len_elem
sigma[e] = (modE / len_elem) * np.dot(np.array([-c, -s, c, s]), disps[np.ix_(elemDof)])
#print (disps)
#print (sigma)
return np.max(np.abs(sigma))
m = GEKKO()
# Define variables
A = m.Array(m.Var, (12))
# initial guess
ig = [0, 0, 0, -20000, 0, 0, 0, -50000, 0, 0, 0, -30000]
# bounds
for i, Ai in enumerate(A):
Ai.value = ig[i]
Ai.lower = ig[i] * 0.95
Ai.upper = ig[i] * 1.05
m.Equation(np.sum(A) == -100000)
m.Obj(calculate_truss_force(A.reshape(12, 1)))
m.solve()
print(A.reshape(12, 1))
print(calculate_truss_force(np.array(ig).reshape(12, 1)))
I switched to SCipy and the code is below
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize
# numElem=11
# numNodes=6
def calculate_truss_force(Area_elem):
# print("calc_truss")
# defined coordinate system
x_axis = np.array([1, 0])
y_axis = np.array([0, 1])
# elements coordinates
elemNodes = np.array([[0, 1], [0, 2], [1, 2], [1, 3],
[0, 3], [2, 3], [2, 5], [3, 4], [3, 5], [2, 4], [4, 5]])
# nodes coordinates
nodeCords = np.array([
[0.0, 0.0], [0.0, 100.0],
[100.0, 0.0], [100.0, 100.0],
[200.0, 0.0], [200.0, 100.0]])
modE = 200000
Area = 200
# assembling the model
numElem = elemNodes.shape[0]
numNodes = nodeCords.shape[0]
xx = nodeCords[:, 0]
yy = nodeCords[:, 1]
EA = modE * Area
tdof = 2 * numNodes # total number of degrees of freedom
disps = np.zeros((tdof, 1))
force = np.zeros((tdof, 1))
sigma = np.zeros((numElem, 1))
stiffness = np.zeros((tdof, tdof))
np.set_printoptions(precision=3)
# applying the load
force[3] = -20000.0
force[7] = -50000.0
force[11] = -30000.0
# defined boundary
presDof = np.array([0, 1, 9])
for e in range(numElem):
indice = elemNodes[e, :]
elemDof = np.array([indice[0] * 2, indice[0] * 2 + 1, indice[1] * 2,
indice[1] * 2 + 1]) # dof corresponding to the global stifnessmatrix
xa = xx[indice[1]] - xx[indice[0]] # length of the elemnts in x dir
ya = yy[indice[1]] - yy[indice[0]] # lenth of the elemnt in y dir
len_elem = np.sqrt(xa * xa + ya * ya)
c = xa / len_elem
s = ya / len_elem
k1 = (modE * Area_elem[e] / len_elem) * np.array([[c * c, c * s, -c * c, -c * s],
[c * s, s * s, -c * s, -s * s],
[-c * c, -c * s, c * c, c * s],
[-c * s, -s * s, c * s, s * s]])
stiffness[np.ix_(elemDof, elemDof)] += k1 # add elem K to the global K
actDof = np.setdiff1d(np.arange(tdof), presDof)
# Correct way
disp1 = np.linalg.solve(stiffness[np.ix_(actDof, actDof)], force[np.ix_(actDof)])
disps[np.ix_(actDof)] = disp1.reshape([9,1])
# stresses at elements
for e in range(numElem):
indice = elemNodes[e, :]
elemDof = np.array([indice[0] * 2, indice[0] * 2 + 1, indice[1] * 2, indice[1] * 2 + 1])
xa = xx[indice[1]] - xx[indice[0]]
ya = yy[indice[1]] - yy[indice[0]]
len_elem = np.sqrt(xa * xa + ya * ya)
c = xa / len_elem
s = ya / len_elem
sigma[e] = (modE / len_elem) * np.dot(np.array([-c, -s, c, s]), disps[np.ix_(elemDof)])
# print (disps)
#print (sigma)
# computing internal reactions
# react = np.dot(stiffness, disps)
# print (react.reshape((numNodes, 2)))
for i,sig in enumerate(sigma):
print("Elem: ",i, "\t Force: \t",sig*Area_elem[i],sig,sigma[i],Area_elem[i])
# input("break")
return np.max(np.abs(sigma))
def constraint1(A):
sum = 100000
for i in range(num_elem):
sum = sum - A[i]
return sum
con1 = {'type': 'eq', 'fun': constraint1}
for i in range(200):
print("Number iteration: ",i)
sol = minimize(calculate_truss_force, x0, method='SLSQP', bounds=bnds,tol=0.0000000000001, constraints=con1)
x0 = sol.x
print(x0)
print(calculate_truss_force(x0))
Gekko uses automatic differentiation to provide derivatives to the gradient-based solvers. Instead of using a linear solver inside of your function:
disp1 = np.linalg.solve(stiffness[np.ix_(actDof, actDof)],\
force[np.ix_(actDof)])
this needs to be given to Gekko as an implicit A x = b, not x= A^-1 b.
A = stiffness[np.ix_(actDof, actDof)]
b = np.array(force[np.ix_(actDof)])
disp1 = np.dot(A,b)
Gekko simultaneously solves the equation, not sequentially like with an inner loop. Also, Gekko only evaluates the objective function once to build symbolic expressions that it then compiles into byte-code for the solver. It does not have a callback to calculate_truss_force to evaluate it multiple times.
One other change is the use of np.max and np.abs to the Gekko versions of m.max2 or m.max3 and also with m.min2 or m.min3. These are versions of max and abs that have continuous first and second derivatives. The ...2 version is an MPCC while the ...3 version is a mixed integer problem.
for e in range(numElem):
indice = elemNodes[e, :]
elemDof = np.array([indice[0] * 2, indice[0] * 2 + 1, \
indice[1] * 2, indice[1] * 2 + 1])
xa = xx[indice[1]] - xx[indice[0]]
ya = yy[indice[1]] - yy[indice[0]]
len_elem = np.sqrt(xa * xa + ya * ya)
c = xa / len_elem
s = ya / len_elem
sigma[e] = m.abs2(m.Intermediate((modE / len_elem) * \
np.dot(np.array([-c, -s, c, s]), \
disps[np.ix_(elemDof)])))
return m.max2(sigma)
If you don't want to use the objective function as a "black-box" then I recommend scipy.optimize.minimize instead of Gekko. Here is a tutorial on Gekko and Scipy for optimization.

Finding maximal submatrix of all 1's - missing argument error

Program that finds the maximal rectangle containing only 1's of a binary matrix with the maximal histogram problem.
I am trying to do some tests on a code
def maximalRectangle(self, matrix):
if not matrix or not matrix[0]:
return 0
n = len(matrix[0])
height = [0] * (n + 1)
ans = 0
for row in matrix:
for i in range(n):
height[i] = height[i] + 1 if row[i] == '1' else 0
stack = [-1]
for i in range(n + 1):
while height[i] < height[stack[-1]]:
h = height[stack.pop()]
w = i - 1 - stack[-1]
ans = max(ans, h * w)
stack.append(i)
return ans
# Driver Code
if __name__ == '__main__':
matrix = [[0, 1, 0, 1],
[0, 1, 0, 1],
[0, 1, 1, 1],
[1, 1, 1, 1]]
print(maximalRectangle(matrix))
I get TypeError: maximalRectangle() missing 1 required positional argument: 'matrix' error
Solved by removing self and changing the print statement to:
print(maximalRectangle([
["1","0","1","0","0"],
["1","1","1","1","1"],
["1","1","1","1","1"],
["1","0","0","1","0"]]))

Optimization of loops - How to implement list-comprehensions

I am writing a function, get_moduli,
that takes an arbitrary number of lists of Cartesian coordinates as input,
and returns the radii as a list. The function behaves correctly but is a bit too long,
and could perhaps be optimized using list comprehensions. Any suggestions?
# Sample input:
x = [1, 2, 3]
y = [1, 3, 5]
z = [1, 4, 7]
def get_moduli(*args):
"""Moduli of arbitrary number of vectors."""
moduli = []
for container in args:
for i in range(len(container)):
container[i - 1] = container[i - 1] ** 2
for i in range(len(args)):
sum_of_squares = 0
for j in range(len(args[i])):
sum_of_squares += args[j][i]
moduli.append(sum_of_squares ** .5)
return moduli
# Run function on sample input:
get_moduli(x, y, z)
# Desired outcome should be as follows:
# [(1 ** 2 + 1 ** 2 + 1 ** 2) ** .5,
# (2 ** 2 + 3 ** 2 + 4 ** 2) ** .5,
# (3 ** 2 + 5 ** 2 + 7 ** 2) ** .5]
Returns correct answer:
[1.7320508075688772, 5.385164807134504, 9.1104335791443]
But how could this function be simplified?
These two functions do what you want:
def modulus(v):
return sum(vi*vi for vi in v)**0.5
def zipped_modulus(*args):
return [modulus(t) for t in list(zip(*args))]
zipped_modulus(x,y,z)
Took me some time to figure out that your matrix is transposed of what i thought
you can use this
def modulus(*args)
return [sum([v**2 for v in vector])**.5 for vector in zip(*args)]
# Sample input:
x = [1, 2, 3]
y = [1, 3, 5]
z = [1, 4, 7]
def get_moduli1(*args):
return list(map(lambda x: sum(y**2 for y in x)**0.5 , zip(*args)))
print(get_moduli1(x, y, z))
output
[1.7320508075688772, 5.385164807134504, 9.1104335791443]

python performance improvement

I am trying to obtain intensity values from an RGB image based on this formula:
And my code is:
def normalize(image): #normalize values to between 0 and 1
image -= image.min()
image /= image.max()
image = np.uint8(image * 255) #convert values to uint8 between 0-255
return image
def custom_intensity(image):
h, w, c = image.shape
intensity = np.zeros((h, w))
image = image.astype(float)
for i in range(h):
for j in range(w):
divider = image[i, j, 0] + image[i, j, 1] + image[i, j, 2]
if(divider == 0):
intensity[i, j] == 0
else:
intensity[i, j] = image[i, j, 0] * (image[i, j, 0] / divider) + \
image[i, j, 1] * (image[i, j, 1] / divider) + \
image[i, j, 2] * (image[i, j, 2] / divider)
intensity = normalize(intensity)
return intensity
Which works well but slow. I am beginner in python so could not improve this further. How can I make this code more efficient?
Try this:
image += (pow(10, -6), pow(10, -6), pow(10, -6))
intensity = (pow(image[:, :, 0], 2) + pow(image[:, :, 1], 2) + pow(image[:, :, 2], 2)) \
/ (image[:, :, 0] + image[:, :, 1] + image[:, :, 2])
You don't need to be an expert in Python.
Simplify your equation:
(R**2 + G**2 + B**2) / (R+G+B)

Resources