Уравнения с учетом угловых ограничений - PullRequest
0 голосов
/ 26 мая 2019

Я пытаюсь решить систему уравнений, используя sympy.

from sympy import *
def get_angles(a, b, c, d):
    theta, phi, lamb = symbols('\\theta \\phi \\lambda', real=True)
    a_eq = Eq(cos(theta / 2), a)
    b_eq = Eq(exp(I * phi) * sin(theta / 2), b)
    c_eq = Eq(-exp(I * lamb) * sin(theta / 2), c)
    d_eq = Eq(exp(I * (phi + lamb)) * cos(theta / 2), d)
    # theta_constr1 = Eq(theta >= 0)
    # theta_constr2 = Eq(theta <= pi)
    # phi_constr1 = Eq(phi >= 0)
    # phi_constr2 = Eq(phi < 2 * pi)
    res = solve([
        a_eq, b_eq, c_eq, d_eq,
        #theta_constr1, theta_constr2, phi_constr1, phi_constr2,
    ],
        theta,
        phi,
        lamb,
        check=False,
        dict=True)
    return res

Функция возвращает правильные результаты, как есть, но она не работает, если я пытаюсь установить ограничение на углы внутри системы уравнений (закомментированные части). Есть ли способ получить их?

В настоящее время я использую простое решение для преодоления этого ограничения: я передаю результат предыдущей функции следующей, чтобы отфильтровать нежелательные результаты

def _final_constraint(result):
    res = []
    for sol in result:
        to_add = True
        for k, v in sol.items():
            if str(k) == '\\theta' and (v < 0 or v > pi):
                to_add = False
                break
            elif str(k) == '\\phi' and (v < 0 or v >= 2 * pi):
                to_add = False
                break
        if to_add:
            res.append(simplify(sol))
    return res

1 Ответ

1 голос
/ 28 мая 2019

Eq означает Equality и не является уравнением (хотя обсуждается добавление такого объекта в SymPy). Таким образом, ваши некомментированные Eq интерпретируются так, как вы хотели, а комментированные - нет. Вы можете попробовать заменить theta_constr1 = Eq(theta >= 0) на theta_constr1 = theta >= 0, но тогда у вас возникнут проблемы с решателем неравенств - он жалуется, что среди неравенств есть более одного символа интереса. Так что насчет переписывания неравенств типа x >= 0 как Eq(x + eps, 0), где eps является неотрицательным Symbol:

def get_angles(a, b, c, d):
    theta, phi, lamb = symbols('\\theta \\phi \\lambda', real=True)
    eps = Symbol('eps', nonnegative=True)
    a_eq = Eq(cos(theta / 2), a)
    b_eq = Eq(exp(I * phi) * sin(theta / 2), b)
    c_eq = Eq(-exp(I * lamb) * sin(theta / 2), c)
    d_eq = Eq(exp(I * (phi + lamb)) * cos(theta / 2), d)
    theta_constr1 = theta + eps
    theta_constr2 = pi - theta + eps
    phi_constr1 = phi  + eps
    phi_constr2 = 2 * pi - phi + eps
    res = solve([
        a_eq, b_eq, c_eq, d_eq,
        theta_constr1, theta_constr2, phi_constr1, phi_constr2,
        ],
        theta,
        phi,
        lamb,
        check=False,
        set=True)
    return res

>>> print(filldedent(get_angles(11,2,3,4)))

([\lambda, \phi, \theta], {(pi, 0, 4*pi - 2*acos(11)), (0, pi,
2*acos(11)), (0, pi, 4*pi - 2*acos(11)), (0, 0, 4*pi - 2*acos(11)),
(0, 0, 2*acos(11)), (pi, pi, 4*pi - 2*acos(11)), (pi, pi, 2*acos(11)),
(pi, 0, 2*acos(11))})

Вы должны выяснить, какая сторона theta и phi - если таковая имеется - удовлетворяет вашим уравнениям.

...