我有以下问题:
我想使用autowrap生成一个sympy矩阵的编译版本,其中包含包含sympy表达式的单元格。根据我的问题的规范,参数的数量会变得非常大。
我遇到了以下两个问题:
即,这有效:
import sympy
from sympy.utilities.autowrap import autowrap
x = sympy.symbols("x:509")
exp = sum(x)
cyt = autowrap(exp, backend="cython", args=x)
这无法编译:
x = sympy.symbols("x:510")
exp = sum(x)
cyt = autowrap(exp, backend="cython", args=x)
我收到的消息似乎不太明白:
[...] (Full output upon request)
Generating code
c:\users\[classified]\appdata\local\temp\tmp2zer8vfe_sympy_compile\wrapper_module_17.c(6293) : fatal error C1001: An internal error has occurred in the compiler.
(compiler file 'f:\dd\vctools\compiler\utc\src\p2\hash.c', line 884)
To work around this problem, try simplifying or changing the program near the locations listed above.
Please choose the Technical Support command on the Visual C++
Help menu, or open the Technical Support help file for more information
LINK : fatal error LNK1257: code generation failed
error: command 'C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\BIN\\x86_amd64\\link.exe' failed with exit status 1257
这有什么办法吗?我想使用我的程序版本,需要~1000个输入变量。 (我对C / cython一无所知。这是一个自动限制,一个C限制......?)
部分与上述有关:
有没有办法生成接受numpy数组作为输入的代码?我特意指的是所有参数的一个数组,而不是将参数作为列表提供。 (类似于使用DeferredVector的lambdify)。 ufuncify支持数组输入,但据我所知只是广播/矢量化函数。
我希望作为参数的数组可以绕过上面的第一个问题,这对我来说是最紧迫的。除此之外,我更喜欢数组输入,因为它看起来更快(不需要解压缩我作为输入到列表中的numpy数组),而且更直接和自然。
有没有人有什么建议我可以做什么? 还有,谁能告诉我f2py是否有类似的限制?如果可行的话,这对我来说也是一个选择,但我目前还没有把它设置为工作,并且在投入时间之前更愿意知道它是否有帮助。 谢谢!
编辑:
我和不同的候选人谈了一下,告诉autowrap
输入参数是数组形式的东西,而不是数字列表。我将在此处记录我的步骤,以便为后人记录,并增加获得一些意见的机会:
sympy.DeferredVector
我使用lambdify是出于同样的目的,所以我想试一试。但是,警告:
A = sympy.DeferredVector("A")
expression = A[0]+A[1]
cyt = autowrap(expression, backend="cython", args=A)
刚刚完全崩溃了我的操作系统 - 最后一个语句开始执行,(没有反馈),一切都变得很慢,然后没有更多的反应。 (只能推测,也许它与A没有形状信息这一事实有关,这似乎不会打扰lambdify,但这可能是一个问题。无论如何,似乎不是正确的方法。)
e.g。
x0 ,x1 = sympy.symbols("x:2")
expression = x0 + x1
cyt = autowrap(expression, backend="cython", args=np.array([x0,x1]))
仍然需要解压缩的参数。用
替换最后一行cyt = autowrap(expression, backend="cython", args=[np.array([x0,x1])])
给出消息
CodeGenArgumentListError: ("Argument list didn't specify: x0, x1 ", [InputArgument(x0), InputArgument(x1)])
这种方法的反复出现主题:在参数列表中使用sympy矩阵,元组等时也会发生。
sympy.IndexedBase
这实际上是在autowrap示例中使用的;然而,在(对我而言)直观的方式中,使用等式作为要包装的表达式。此外,它的使用方式对我来说似乎并不可行:我想要cythonize的表达式是一个矩阵,但它的单元格本身就是长表达式,我无法通过索引操作获得。
好处是我得到了一个最小的例子:
X = sympy.IndexedBase("X",shape=(1,1))
expression = 2*X[0,0]
cyt = autowrap(expression, backend="cython", args=[X])
实际编译,结果函数正确评估 - 传递2d-np.array时。
所以这似乎是最有希望的途径,尽管这种方法的进一步扩展我一直在尝试失败。
例如这个
X = sympy.IndexedBase("X",shape=(1,))
expression = 2*X[0]
cyt = autowrap(expression, backend="cython", args=[X])
让我
[...]\site-packages\sympy\printing\codeprinter.py", line 258, in _get_expression_indices " rhs indices in %s" % expr)
ValueError: lhs indices must match non-dummy rhs indices in 2*X[0]
即使我不知道它与上面的工作方式有什么不同。
粘贴到两个维度时会出现相同的错误消息,但会增加X
的大小:
X = sympy.IndexedBase("X",shape=(2,2))
expression = 2*X[0,0]+X[0,1]+X[1,0]+X[1,1]
cyt = autowrap(expression, backend="cython", args=[X])
ValueError: lhs indices must match non-dummy rhs indices in 2*X[0, 0] + X[0, 1] + X[1, 0] + X[1, 1]
我试着窥探autowrap
的代码,但我觉得有点迷失......
所以我仍然在寻找解决方案并为任何输入感到高兴。
答案 0 :(得分:2)
将参数作为数组传递似乎可以正常工作
x = sympy.MatrixSymbol('x', 520, 1)
exp = 0
for i in range(x.shape[0]):
exp += x[i]
cyt = autowrap(exp, backend='cython')
arr = np.random.randn(520, 1)
cyt(arr)
Out[48]: -42.59735861021934
arr.sum()
Out[49]: -42.597358610219345