Sympy 在解决“[...] 每个候选人中都发现了不可判定的集合成员资格”期间的错误是否意味着不存在解决方案?

Does Sympy's error during solve "[...] undecidable set membership is found in every candidates" mean that no solution exists?

我正在尝试求解变量 x 的以下等式(依赖于其他符号 b, c, d):

from sympy import symbols, sin, cos, solve, solveset, S
  
b, c, d, x = symbols('b c d x', real=True)

expr = sin(x)*sin(c - 2*d - x) - sin(2*b - 2*d - x)*sin(c - x)  # find `x` such that `expr == 0`

存在适用于各种符号的附加限制,即:

0 < d < b < d+x < c

所以我尝试使用 solve 来合并这些不等式约束:

result = solve(
    [
        sin(x)*sin(c - 2*d - x) - sin(2*b - 2*d - x)*sin(c - x),
        0 < d,
        d < b,
        b < d+x,
        d+x < c,
    ],
    x,
)

但是,我收到以下错误:

Traceback (most recent call last):
  File "/path/to/venv/lib/python3.9/site-packages/sympy/polys/polyutils.py", line 211, in _parallel_dict_from_expr_if_gens
    monom[indices[base]] = exp
KeyError: sin(c - x)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/path/to/venv/lib/python3.9/site-packages/sympy/solvers/inequalities.py", line 818, in _solve_inequality
    p = Poly(expr, s)
  File "/path/to/venv/lib/python3.9/site-packages/sympy/polys/polytools.py", line 181, in __new__
    return cls._from_expr(rep, opt)
  File "/path/to/venv/lib/python3.9/site-packages/sympy/polys/polytools.py", line 310, in _from_expr
    rep, opt = _dict_from_expr(rep, opt)
  File "/path/to/venv/lib/python3.9/site-packages/sympy/polys/polyutils.py", line 368, in _dict_from_expr
    rep, gens = _dict_from_expr_if_gens(expr, opt)
  File "/path/to/venv/lib/python3.9/site-packages/sympy/polys/polyutils.py", line 307, in _dict_from_expr_if_gens
    (poly,), gens = _parallel_dict_from_expr_if_gens((expr,), opt)
  File "/path/to/venv/lib/python3.9/site-packages/sympy/polys/polyutils.py", line 216, in _parallel_dict_from_expr_if_gens
    raise PolynomialError("%s contains an element of "
sympy.polys.polyerrors.PolynomialError: sin(c - x) contains an element of the set of generators.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/path/to/venv/lib/python3.9/site-packages/sympy/polys/polyutils.py", line 211, in _parallel_dict_from_expr_if_gens
    monom[indices[base]] = exp
KeyError: sin(c - x)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/path/to/venv/lib/python3.9/site-packages/sympy/solvers/inequalities.py", line 246, in reduce_rational_inequalities
    (numer, denom), opt = parallel_poly_from_expr(
  File "/path/to/venv/lib/python3.9/site-packages/sympy/polys/polytools.py", line 4414, in parallel_poly_from_expr
    return _parallel_poly_from_expr(exprs, opt)
  File "/path/to/venv/lib/python3.9/site-packages/sympy/polys/polytools.py", line 4467, in _parallel_poly_from_expr
    reps, opt = _parallel_dict_from_expr(exprs, opt)
  File "/path/to/venv/lib/python3.9/site-packages/sympy/polys/polyutils.py", line 332, in _parallel_dict_from_expr
    reps, gens = _parallel_dict_from_expr_if_gens(exprs, opt)
  File "/path/to/venv/lib/python3.9/site-packages/sympy/polys/polyutils.py", line 216, in _parallel_dict_from_expr_if_gens
    raise PolynomialError("%s contains an element of "
sympy.polys.polyerrors.PolynomialError: sin(c - x) contains an element of the set of generators.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/path/to/venv/lib/python3.9/site-packages/sympy/solvers/inequalities.py", line 827, in _solve_inequality
    rv = reduce_rational_inequalities([[ie]], s)
  File "/path/to/venv/lib/python3.9/site-packages/sympy/solvers/inequalities.py", line 249, in reduce_rational_inequalities
    raise PolynomialError(filldedent('''
sympy.polys.polyerrors.PolynomialError: 
only polynomials and rational functions are supported in this context.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/tmp/test2.py", line 5, in <module>
    result = solve(
  File "/path/to/venv/lib/python3.9/site-packages/sympy/solvers/solvers.py", line 920, in solve
    return reduce_inequalities(f, symbols=symbols)
  File "/path/to/venv/lib/python3.9/site-packages/sympy/solvers/inequalities.py", line 996, in reduce_inequalities
    rv = _reduce_inequalities(inequalities, symbols)
  File "/path/to/venv/lib/python3.9/site-packages/sympy/solvers/inequalities.py", line 912, in _reduce_inequalities
    other.append(_solve_inequality(Relational(expr, 0, rel), gen))
  File "/path/to/venv/lib/python3.9/site-packages/sympy/solvers/inequalities.py", line 829, in _solve_inequality
    rv = solve_univariate_inequality(ie, s)
  File "/path/to/venv/lib/python3.9/site-packages/sympy/solvers/inequalities.py", line 500, in solve_univariate_inequality
    frange = function_range(e, gen, domain)
  File "/path/to/venv/lib/python3.9/site-packages/sympy/calculus/util.py", line 208, in function_range
    for critical_point in critical_points:
  File "/path/to/venv/lib/python3.9/site-packages/sympy/utilities/iterables.py", line 2881, in roundrobin
    yield nxt()
  File "/path/to/venv/lib/python3.9/site-packages/sympy/sets/sets.py", line 1439, in __iter__
    raise TypeError(
TypeError: The computation had not completed because of the undecidable set membership is found in every candidates.

我不确定这个错误是什么意思。这是否意味着对于给定的不等式约束不存在解决方案?

(sympy 版本:1.10.1)


求解集

我也试过使用solveset(但是,这里似乎不可能包含不等式约束):

result = solveset(
    sin(x)*sin(c - 2*d - x) - sin(2*b - 2*d - x)*sin(c - x),
    x,
    domain=S.Reals,
)

然而,经过长时间的计算,它只是returns原来的表达式:

ConditionSet(x, Eq(-sin(x)*sin(-c + 2*d + x) + sin(c - x)*sin(-2*b + 2*d + x), 0), Reals)

matlab

我也试过用Matlab解方程:

syms b c d x

eq1 = sin(x)*sin(c - 2*d - x) - sin(2*b - 2*d - x)*sin(c - x) == 0;
eq2 = 0 < d;
eq3 = d < b;
eq4 = b < d+x;
eq5 = d+x < c;
result = solve([eq1 eq2 eq3 eq4 eq5], x, "Real",true, "ReturnConditions",true);

然而,结果完全不同,涉及到一个我无法理解的四阶多项式:

>> result.x
 
ans =
 
2*pi*k + atan2(y, 1) - atan2(-y, 1)

>> result.conditions
 
ans =
 
d < b & b + atan2(-y, 1) < d + atan2(y, 1) + 2*pi*k & d + atan2(y, 1) + 2*pi*k < c + atan2(-y, 1) & cos(b)*sin(b) + 2*cos(b)^2*cos(d)*sin(d) ~= cos(d)*sin(d) + 2*cos(b)*cos(d)^2*sin(b) & in(k, 'integer') & ~in(c/pi, 'integer') & in(y, 'real') & 4*y^2*cos(c - 2*d) + 2*y^3*sin(c - 2*d) + sin(2*b - 2*d)*sin(c) + y^2*cos(c - 2*b + 2*d) + 3*y^2*cos(2*b + c - 2*d) + 2*y^3*sin(2*b + c - 2*d) + y^4*sin(2*b - 2*d)*sin(c) == 2*y*sin(2*b + c - 2*d) + 2*y*sin(c - 2*d) & 0 < d

以下是如何使用 SymPy 获得类似于 Matlab 解决方案的方法(请注意,我重新定义了符号以使输出更简单):

In [19]: a, b, c, d, e, x, y = symbols('a, b, c, d, e, x, y', real=True)

In [20]: expr = sin(x)*sin(a - x) - sin(e - x)*sin(c - x)

In [21]: expr.expand(trig=True)
Out[21]: 
                                        2                                                          
sin(a)⋅sin(x)⋅cos(x) - sin(c)⋅sin(e)⋅cos (x) + sin(c)⋅sin(x)⋅cos(e)⋅cos(x) + sin(e)⋅sin(x)⋅cos(c)⋅c

           2                2                 
os(x) - sin (x)⋅cos(a) - sin (x)⋅cos(c)⋅cos(e)

In [22]: expr2 = resultant(expr.expand(trig=True), cos(x)**2 + sin(x)**2 - 1, cos(x))

In [23]: expr2.collect(sin(x))
Out[23]: 
⎛     2                                                             2       2         2       2    
⎝- sin (a) - 2⋅sin(a)⋅sin(c)⋅cos(e) - 2⋅sin(a)⋅sin(e)⋅cos(c) - 2⋅sin (c)⋅sin (e) - sin (c)⋅cos (e) 

                              2       2   ⎞    2      ⎛   2                                        
+ 2⋅sin(c)⋅sin(e)⋅cos(a) - sin (e)⋅cos (c)⎠⋅sin (x) + ⎝sin (a) + 2⋅sin(a)⋅sin(c)⋅cos(e) + 2⋅sin(a)⋅

                   2       2         2       2                                  2       2         2
sin(e)⋅cos(c) + sin (c)⋅sin (e) + sin (c)⋅cos (e) - 2⋅sin(c)⋅sin(e)⋅cos(a) + sin (e)⋅cos (c) + cos 

                                  2       2   ⎞    4         2       2   
(a) + 2⋅cos(a)⋅cos(c)⋅cos(e) + cos (c)⋅cos (e)⎠⋅sin (x) + sin (c)⋅sin (e)

所以我们看到我们得到的是 sin(x) 中的 4 次多项式。这个比 Matlab 找到的那个更容易求解,因为它只有 sin(x) 的偶次幂。 sin(x) 的显式解决方案可以使用根找到,例如第一个是:

In [26]: r1, r2, r3, r4 = roots(expr2.subs(sin(x), y), y)

In [27]: r1
Out[27]: 
          _________________________________________________________________________________________
         ╱                         ________________________________________________________________
        ╱                         ╱                                                                
       ╱                         ╱                               2       2      (cos(2⋅a) + cos(2⋅c
      ╱                         ╱   - 8⋅(cos(-a + c + e) + 1)⋅sin (c)⋅sin (e) + ───────────────────
     ╱                        ╲╱                                                                   
-   ╱      - ──────────────────────────────────────────────────────────────────────────────────────
   ╱           ⎛   2                                                           2       2         2 
 ╲╱          2⋅⎝sin (a) + 2⋅sin(a)⋅sin(c)⋅cos(e) + 2⋅sin(a)⋅sin(e)⋅cos(c) + sin (c)⋅sin (e) + sin (

___________________________________________________________________________________________________
__________________________________________________________________________________________         
                                                                                        2          
) + cos(2⋅e) - 3⋅cos(-a + c + e) + cos(a - c + e) + cos(a + c - e) + cos(a + c + e) - 3)           
─────────────────────────────────────────────────────────────────────────────────────────          
                                  4                                                                
───────────────────────────────────────────────────────────────────────────────────────────────────
      2                                  2       2         2                                  2    
c)⋅cos (e) - 2⋅sin(c)⋅sin(e)⋅cos(a) + sin (e)⋅cos (c) + cos (a) + 2⋅cos(a)⋅cos(c)⋅cos(e) + cos (c)⋅

___________________________________________________________________________________________________
                                                                                                   
                                                                                                   
                                                                                                   
                                                                                                   
           -cos(2⋅a) - cos(2⋅c) - cos(2⋅e) + 3⋅cos(-a + c + e) - cos(a - c + e) - cos(a + c - e) - 
──────── + ────────────────────────────────────────────────────────────────────────────────────────
   2   ⎞                                            8⋅(cos(-a + c + e) + 1)                        
cos (e)⎠                                                                                           

___________________
                   
                   
                   
                   
cos(a + c + e) + 3 
────────────────── 
                

这是否真实或是否满足不等式将取决于符号参数的值,因此我怀疑不等式是否可用于在根的 4 个表达式中进行选择。不过,也许可以使用多项式 expr2 来回答不同的问题。