sympy.solve 对于某些系数永远不会返回

问题描述 投票:0回答:1

我试图解决的表达式的形式(对应于下面称为“表达式”的变量)的关键点在所有情况下都是相同的,因为成功和失败之间唯一变化的是指数的值每个学期。

这是一个最小的可重现示例:

from sympy import symbols, Mul, diff, solve
from decimal import Decimal


class Histogram:
    def __init__(self, bins, pdf):
        self.bins = bins
        self.pdf = pdf


histogram = Histogram(
        bins=[-1, 0, 1],
        pdf=[Decimal('0.454861111111111104943205418749130330979824066162109375'),
             Decimal('0'),
             Decimal('0.545138888888888839545643349993042647838592529296875')]
    )
]


def computation(histogram):

    A = Decimal('1')
    e = Decimal('1')
    M_factor = Decimal('1.0828567056280801')
    x = symbols('x')
    product_terms = []
    profit = lambda cp: (e * M_factor ** cp - e) * x
    commission = lambda cp: (e * M_factor ** cp + e) * Decimal('0.0005') * x

    for candles_profit, freq in zip(histogram.bins, histogram.pdf):
        profit_term = profit(candles_profit)
        commission_term = commission(candles_profit)
        term = ((A + profit_term - commission_term) / A) ** freq
        product_terms.append(term)

    expression = Mul(*product_terms)
    derivative = diff(expression, x)
    solutions = solve(derivative, x)
    print("Solutions:", solutions)

computation(histogram)

上面计算函数中的“表达式”变量在调试器中变成以下内容:

(1.0 - 0.0774785191289289x)^0.454861111111111 \* (0.0818152772752661x + 1.0)^0.545138888888889

如果您使用上面的示例创建一个 python 文件并运行它,则在尝试查找表达式的关键点时它永远不会返回。

我看到的可以解释失败的独特功能是它的指数中有重复的小数,就像 2/3 这样的有理数。为了证实我的直觉,即这是错误的根源,我重新审视了形成该交易品种直方图的交易:131 笔位于 -1 桶中,157 笔位于 +1 桶中。 131/288 = 0.454861(重复 1),157/288 = 0.545138(重复 8)。因此,即使 Decimal 值在我们传递给计算函数的直方图中保留了许多精度位置,这些值也是不准确的因为重复会在一段时间后停止,但即使这样也没关系,因为 sympy 会在该点之前切断值。由于 sympy.solve 将我的输入 python 小数强制转换为 sympy 浮点数,而不是 sympy 有理数,因此可以合理地预期这是问题的根源吗?如果是,我该如何修改我的代码以允许计算正确解析而不是永远卡住?

python sympy solver
1个回答
0
投票

使用 SymPy 时,浮点数是许多令人头痛的原因。尽可能使用准确的数字。如果您使用

nsimplify
将十进制数转换为有理数,将立即计算解决方案。

这几行代码:

expression = Mul(*product_terms)
# ...
print("Solutions:", solutions)

至:

expression = Mul(*product_terms).nsimplify()
# ...
print("Solutions:", solutions[0].n())
© www.soinside.com 2019 - 2024. All rights reserved.