我正在尝试将一段python代码转换为Julia 1.1.0。 python代码:
import numpy as np
import sympy as sp
x, y = sp.symbols('x y')
data = np.random.randn(1000, 2)
a,b = data[:,0], data[:,1]
M = len(data[:,0])
m = 5
n = round(m*(m+1)/2)
L = np.zeros((M,n))
l = sp.zeros(1,n)
k = 0
for i in range(1,m+1):
for j in range(1,i+1):
l[0,k]=((i-j)*(i-j-1)*x**(i-j-2)*y**(j-1))
f = sp.lambdify([x,y], l[0,k], "numpy")
L[:,k] = np.squeeze(f(a,b))
k=k+1
和我尝试输入的Julia代码:
using SymPy
data = rand(1000,2)
a = data[:,1];
b = data[:,2];
M = length(data[:,1])
x = symbols("x");
y = symbols("y");
m = 5;
n = Int(m*(m+1)/2)
L = zeros(M,n)
l = zeros(1,n)
k = 1;
for i in 1:m
for j in 1:i
l[1,k] = ((i-j)*(i-j-1)*x^(i-j-2)*y^(j-1))
f = l[1,k]
L[:,k] = f.subs([(x, a), (y, b)])
k=k+1
end
end
当我运行Julia代码时,l[1,k]
出现以下错误
DomainError with -2:
Cannot raise an integer x to a negative power -2.
Convert input to float.
Stacktrace:
[1] throw_domerr_powbysq(::Sym, ::Int64) at ./intfuncs.jl:173
[2] power_by_squaring(::Sym, ::Int64) at ./intfuncs.jl:196
[3] ^(::Sym, ::Int64) at ./intfuncs.jl:221
[4] top-level scope at ./In[80]:14
此外,我不确定以下代码
f = l[1,k]
L[:,k] = f.subs([(x, a), (y, b)])
如果有人可以帮助我将python代码转换为julia代码,我将不胜感激。
更新:
基于@jverzani的帖子,我现在可以使用以下代码将sym值转换为float
using SymPy
data = rand(1000,2)
a = data[:,1];
b = data[:,2];
M = length(data[:,1])
x = symbols("x");
y = symbols("y");
m = 5;
n = Int(m*(m+1)/2)
LL = zeros(M,n)
L = zeros(Sym, M,n)
l = zeros(Sym, 1,n)
k = 1;
for i in 1:m
for j in 1:i
l[1,k] = ((i-j)*(i-j-1)*x^Sym(i-j-2)*y^Sym(j-1))
f = l[1,k]
L[:,k] .= f.subs([(x, a), (y, b)])
global k=k+1
end
end
for s in 1:M
for r in 1:n
LL[s,r] = float(subs(L[s,r],(x,a[s]),(y,b[s])))
end
end
但是这次代码非常慢。如何优化代码。
答案 0 :(得分:0)
SymPy刚刚进行了一项重大更改,继承自PyCall
,这使得subs
的最后一位像键入的一样工作。
对于第一个,您遇到了具有整数基数和非文字的负整数幂的Julia问题。您可以修改该行以使其成为符号,例如x^Sym(i-j-2)
代替x^(i-j-2)
。 (最好绕过它。)
下面的编辑试图反映Python代码的精神。它包装成一个函数,可以测试N
大小的速度,并避免在global
分配上需要k
。
using SymPy
import PyCall
np = PyCall.pyimport("numpy") #import numpy as np
const sp = sympy
function fill_L(N=1000)
x, y = sp.symbols("x y")
offset = 1
data = np.random.randn(N, 2)
a,b = data[:,0+offset], data[:,1+offset]
M = length(data[:,0+offset])
m = 5
n = round(Int, m*(m+1)/2)
L = np.zeros((M,n))
l = sp.zeros(1,n)
k = 0
for i in 1:m
for j in 1:i
l[1,k+offset]=((i-j)*Sym(i-j-1)*x^Sym(i-j-2)*y^Sym(j-1))
f = lambdify(l[1,k+offset], (x, y))
#f = sp.lambdify([x,y], l[0,k], "numpy")
L[:,k+offset] = f.(a,b)
k=k+1
end
end
L
end
由于上面f
的广播,现在的性能是合理的。