sympy: поиск корня параметризованной функции в диапазоне - PullRequest
0 голосов
/ 26 марта 2020

У меня проблемы с поиском root параметризованного полинома квинти c. Предпосылки: я хочу найти параметр s_f такой, чтобы для любого заданного параметра d_f кривизна многочлена была меньше порога (да ... звучит сложно, но математика довольно прямая);

# define quintic polynomial (jerk-minimized trajectory)
# see http://courses.shadmehrlab.org/Shortcourse/minimumjerk.pdf
s = symbols('s', real=True, positive=True)
s_f = symbols('s_f', real=True, positive=True, nonzero=True)
d_0 = 0
d_f = symbols('d_f', real=True, positive=True, nonzero=True)
d_of_s = d_0 + (d_f - d_0) * ( 10*(s/s_f)**3 - 15*(s/s_f)**4 + 6*(s/s_f)**5 )
display(d_of_s)


# define curvature of d_of_s
# see https://en.wikipedia.org/wiki/Curvature#In_terms_of_a_general_parametrization
y = d_of_s
dy = diff(d_of_s, s)
ddy = diff(dy, s)
x = s 
dx = diff(x, s) # evaluates to 1
ddx = diff(dx, s) # evaluates to 0

k = (dx*ddy - dy*ddx) / ((dx*dx + dy*dy)**Rational(3,2))


# the goal is to find s_f for any given d_f, such that k(s) < some_threshold
# strategy: find the roots of the derivative of k in the range of s∈[0, s_f]
dk = diff(k, s)
dk = simplify(dk)
display(dk)


# now solve
res = solveset(dk, s, Interval(0, s_f).intersection(S.Reals))
display(res)

Функция dk(s, d_f, s_f) имеет два root в интервале s∈ [0, s_f], однако solveset возвращает это:

ConditionSet(s, Eq(5400*d_f**2*s**4*(-s**2 + 2*s*s_f - s_f**2)*(2*s**2 - 3*s*s_f + s_f**2)**2 + (900*d_f**2*s**4*(s**2 - 2*s*s_f + s_f**2)**2 + s_f**10)*(6*s**2 - 6*s*s_f + s_f**2), 0), Interval(0, s_f))

.., что в действительности эквивалентно : Я не могу решить это, мы получили бесконечное количество результатов. Ну, это верно для функции в целом. limit(dk, s, -oo) и limit(dk, s, +oo) - ноль. Но так как я указал интервал домена, почему я не получаю двух ожидаемых корней? Я также ожидал бы получить более детальный результат: - множество, содержащее корни для s <0; - установить содержащий корни для s> s_f - два корня, когда s∈ [0, s_f]

Я начал с solve () и множества различных предположений о моих символах. Я получаю разные результаты для разных предположений, но ни одна комбинация не дает того, что мне нужно. Когда я не заявляю никаких предположений, я получаю набор с огромным условием и 8 корнями, которые не кажутся реальными или правильными. В общем, ограничения следующие:

- all symbols are real
- s_f > 0
- d_f > 0
- s ∈ [0, s_f] (domain range .. the polynomial is only evaluated in this interval)

Думаю, проблема в том, что я неправильно настраиваю свой набор решений:

  • как указать этот s_f и д_ф реальны? afaik Предположения символа игнорируются при использовании решает?
  • как указать интервалы и допущения для других многомерных функций, т.е. других символов, кроме доменной?

Так выглядит d_of_s для s_f = 1, d_f = 1

d_of_s

И вот как выглядит dk (s) (я нарисовал за пределами диапазона домена, чтобы визуализировать проблему).

dk(s)

1 Ответ

1 голос
/ 26 марта 2020

Замените в известных значениях d_f и s_f и используйте real_roots, чтобы найти действительные корни числителя dk. Оставьте те, которые имеют значение в интересующем диапазоне:

>>> s_fi = 3
>>> [i for i in real_roots(dk.subs(d_f,2).subs(s_f, s_fi).as_numer_denom()[0])
... if 0 <= i.n(2) <= s_fi]
[CRootOf(800*s**10 - 12000*s**9 + 74000*s**8 - 240000*s**7 + 432000*s**6 - 410400*s**5 
+ 162000*s**4 - 4374*s**2 + 13122*s - 6561, 1), CRootOf(800*s**10 - 12000*s**9 + 
74000*s**8 - 240000*s**7 + 432000*s**6 - 410400*s**5 + 162000*s**4 - 4374*s**2 + 
13122*s - 6561, 2)]

Я сохранил экземпляры CRootOf, потому что они могут быть вычислены с произвольной точностью, например, до 3 цифр:

>>> [i.n(3) for i in _]
[0.433, 2.57]
...