【问题标题】:SymPy: Interval MathSymPy:区间数学
【发布时间】:2019-12-04 07:31:18
【问题描述】:

简介

我们一直在从事最近的一个项目,并一直在寻找合适的系统来计算一些值。 SymPy 被推荐为一个丰富的数学库。但是,我们无法让它与我们的项目“工作”。

我们一直在努力解决的问题是,我们将使用的许多值已经被四舍五入多次,并且很可能容易出现浮点错误。为了在之前的项目中解决这个问题,我们使用Interval Arithmetic 来相当有效地使用 JavaScript。 Python 的 mpmath 似乎很相似,但 SymPy 不仅使用 mpmath,还提供了我们将来可能需要的其他潜在有用的功能。

问题

我们最近一直在研究的一个示例方程是a = b * (1 + c * d * e),我们希望在所有其他变量已知的情况下求解e。但是,有些变量需要表示为一个值范围,因为我们不知道确切的值,而是一个很小的范围。

代码

from sympy import *
from sympy.sets.setexpr import SetExpr

a, b, c, d, e = symbols('a b c d e')

b = 40
c = 1
d = 0.1
a = SetExpr(Interval(45.995, 46.005))
equ = Eq(b * (1 + c * d * e), a)
solveset(equ, e)
ValueError: The argument '45.995*I' is not comparable.

这只是最新的尝试,但我尝试过设置域、设置符号的不等式、使用AccumBounds 以及许多其他解决方案,但我不禁认为我们完全忽略了一些简单的事情。


解决方案

使用一个区间似乎可以使用所选答案提供的代码,但它不会扩展到需要区间或值范围的多个符号。看来我们将扩展 mpmath 库以支持额外的区间函数。

【问题讨论】:

    标签: sympy intervals


    【解决方案1】:

    出于某种原因,绘图模块中的 SymPy 中有一个区间数学模块。它不是 Basic 的子类,但不能直接在表达式中使用。然而,我们可以使用lambdify 将其替换为表达式

    from sympy import *
    from sympy.plotting.intervalmath import interval
    
    b = 40
    c = 1
    d = 0.1
    a, e = symbols('a, e', real=True)
    equ = Eq(b * (1 + c * d * e), a)
    sol_e, = solveset(equ, e)
    
    f_e = lambdify(a, sol_e)
    int_a = interval(45.995, 46.005)
    int_e = f_e(a=int_a)
    
    print(int_e)
    

    这给了

    [1.498750, 1.501250]
    

    我认为 intervalmath 模块的使用并不多,因此它很有可能无法完全解决您的实际问题。

    使用集合可能是更好的方法,似乎imageset 可以做到这一点:

    In [16]: set_e = imageset(Lambda(a, sol_e), Interval(45.995, 46.005))                                                             
    
    In [17]: set_e                                                                                                                    
    Out[17]: [1.49875, 1.50125]
    

    我不确定这对多个符号/间隔的效果如何。

    编辑:为了完整起见,我将展示您如何在多个间隔中使用 intervalmath

    from sympy import *
    from sympy.plotting.intervalmath import interval
    
    b = 40
    d = 0.1
    a, c, e = symbols('a, c, e', real=True)
    equ = Eq(b * (1 + c * d * e), a)
    sol_e, = solveset(equ, e)
    
    f_e = lambdify((a, c), sol_e)
    int_a = interval(45.995, 46.005)
    int_c = interval(0.95, 1.05)
    int_e = f_e(a=int_a, c=int_c)
    
    print(int_e)
    

    这给了

    [1.427381, 1.580263]
    

    【讨论】:

    • 这适用于一个符号,我的代码可能有点误导。我希望如果我能解决一个符号间隔,我就能解决多个。我们预计在约 30 个变量方程中最多有 3 个区间(或范围)。我还不能强制图像集适用于多个符号。对阅读材料还有其他建议吗?
    • 理想情况下imageset((x, y), 1+x+y, Interval(2, 3), Interval(3, 4)) 可以在这里工作,但它似乎无法评估。
    • 我看到了,这太可惜了。我非常感谢您的帮助。我相信我们会为我们的项目选择一个不同的库。
    • 是的,很公平。为了完整起见,我添加了一个使用带有两个间隔的区间数学的示例
    猜你喜欢
    • 1970-01-01
    • 2017-08-24
    • 2016-09-03
    • 1970-01-01
    • 2013-11-02
    • 1970-01-01
    • 1970-01-01
    • 2015-07-21
    • 2015-09-15
    相关资源
    最近更新 更多