2015-10-12 3 views
1

Я новичок в программировании, и это мой первый вопрос. Я трачу много времени на эту проблему. Это абстракция из программы, которую я пишу для моей диссертации. Может быть, для некоторых из вас эксперты тривиальны, но мне даже не хватает математических знаний.Runtime Оптимизация символьного кода с использованием numpy или scipy

Я хочу, чтобы решить следующую систему уравнений для b1, b2 и с3:

0 = cos(b1)+ cos(b2)- 0.0166 
0 = sin(b1)+ sin(b2)+ 0.3077*c3 - 0.6278 
0 = cos(b1)- cos(b2)+ 5.4155*c3 - 4.3547 

b1 и b2 являются углы и должны, следовательно, между [0, 2 * пи] и с3 должно быть между [0, 1], но это необязательно. Я могу фильтровать результаты позже.

Я нашел решение с помощью SymPy:

import sympy as sy 
b1 = sy.Symbol('b1',real=True) 
b2 = sy.Symbol('b2',real=True) 
c3 = sy.Symbol('c3',real=True) 
a = sy.cos(b1)+sy.cos(b2)-0.0166 
b = sy.sin(b1)+sy.sin(b2)+0.3077*c3-0.6278 
c = sy.cos(b1)-sy.cos(b2)+5.4155*c3-4.3547 
Erg = sy.solve([a,b,c,],[b1,b2,c3],dict=True) 

[{с3: -0,4634, b1: 2,7245, б2: 0,3739}]

Результаты являются обоснованными, но, к сожалению, это приводит к вычислению время 6s, что приведет к полному времени вычисления более 7 часов для моей программы. Пожалуйста, помогите мне найти более быстрое решение. Я попытался SciPy

from scipy.optimize import fsolve 
import numpy as np 

def equations(p): 
    b1, b2, c3 = p 
    return (np.cos(b1)+np.cos(b2)-0.0166, np.sin(b1)+np.sin(b2)+0.3077*c3-0.6278,np.cos(b1)-np.cos(b2)+5.4155*c3-4.3547) 

b1, b2, c3 = fsolve(equations, (-0.4634, 2.7245, 0.3739)) 

В результате под 1s в (-9.8418e-14, 5.6621e-15, -7.5495e-14). Я не знаю, какое число принадлежит какой переменной, но они не имеют никакого смысла. Другим вариантом было бы оптимизировать уравнение для минимального c3. Пожалуйста, не стесняйтесь спрашивать, не ясно ли я о чем-либо.

+0

Корпус «numpy» может знать только порядок переменных из определения функции: вы передаете 'p' как' b1, b2, c3'. Но тогда вы должны ввести свои данные в следующем порядке: 'fsolve (уравнения, (2.7245, 0.3739, -0.4634))'. Но в любом случае вы правы, что '(0,0,0)' не решает ваше уравнение. Разве вам не хватает скобки в вашем 'numpy'' return'? –

+0

Да, вы правы, что он потерялся при изменении вопроса, но он есть в исходном коде. Спасибо за комментарий к правильному порядку переменных! – Fips

+0

Интересно, если я попробую ваше символическое решение, я получаю сообщение об ошибке «не могу решить» ... sympy 0.7.4.1. –

ответ

2

Если исправить недостающую скобку в вашем numpy Например, я получить другой результат:

In [40]: b1,b2,c3 
Out[40]: (0.21407625679722384, 2.8598524043642226, 0.4463029985826017) 

И в любом случае ваши входные точки не очень хорошо, так как ваши переменные перепутаны. Ваша функция определена в порядке b1,b2,c3, но отправная точка соответствует символическому решению c3,b1,b2. Изменение порядка дает мне

In [42]: b1,b2,c3 
Out[42]: (2.9450733464142882, 0.07278767695320594, 1.1693849677611501) 

Обратите внимание, что для данного b1,b2 вы будете иметь также решение с b1+2*k*pi,b2*2*l*pik,l, где целые числа.

Я не помещал эти цифры в ваши уравнения, но я уверен, что они решают их. Проблема в том, что есть множество решений. Как я уже сказал, ваши первые две переменные являются периодическими, и даже тогда может быть много других решений с c3. Если вы используете кучу разных начальных точек для fsolve, вы получите множество различных решений.

Что еще хуже: ваше решение не обеспечивает привязку 0<c3<1.


по математике: из-за разнообразие возможных решений, вы можете упростить числовую проблему на бумаге первой.

Например, первое уравнение является специальным, так как оно не содержит c3. Вы можете связать b1 с b2, хотя и нелинейным способом. Для каждого b1 вы будете знать, что

b2=+-acos(0.0166-cos(b1))+2*k*pi 

Что уже является сдерживающим фактором. Кроме того, добавив уравнение 1 до3 дает

0 = 2*cos(b1)+ 5.4155*c3 - 4.3547-0.0166 

другими словами, c3 линейно зависит от cos(b1). Это может помочь, если вы представите это в уравнении. 2, получая соединение между функциями b1 и b2. По существу у вас есть переменные как b1,b2(b1),c3(b1), с одним уравнением. 2 решить.

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

+0

У меня есть проблемы, чтобы найти отсутствующую скобку. Я думал, ты имеешь в виду тот, который был в конце возвращения. Он отсутствовал в коде, опубликованном в этом вопросе (исправлено уже), но в моем скрипте этого не было, поэтому я все еще получаю (0,0,0) решение – Fips

+0

@Fips, это именно то, что я имел в виду. Вы уверены, что ваш код такой, как указано выше? Если я начну с '(0,0,0)', это даст мне другое решение, поэтому '(0,0,0)' не кажется для меня решением. Вы пытались удалить старые переменные, а затем запустить решение «numpy»? Или, по крайней мере, изменить имена переменных, чтобы избежать путаницы с символическими. –

+0

Хорошо, я вижу, что у меня была проблема с моей командой печати. Я применил функцию «уравнения» второй раз по результату ... глупо меня. Большое спасибо за помощь мне здесь. Любая идея, как установить лимиты для переменных? если я принимаю плохие входные значения, я получаю углы до 2000 рад – Fips