Вложенные функции. Как правильно учесть уравнение равное нулю

Al Frolov

Новичок
Пользователь
Фев 20, 2022
20
3
3
Привет! Ниже блок с кодом (вложенные функции), он работает, но результаты представляет в виде списка формул. До того, как я добавил строки 18-22 (добавление уравнения, равного нулю), вычисление занимало около 20-30 минут, и результат был отличным - по итогу были представлены варианты значений переменных. Но когда я добавил строки 18-22, вычисления стали бесконечными, и я вижу, что строка 21 выполняется часами. Результат выглядит так, как будто переменные из уравнения остаются символами, и вычисление не выполняется. Как я могу решить эту проблему? Помогите, пожалуйста

О моей цели: Для каждой из переменных с подчеркиванием установлен диапазон возможных значений, в пределах которого значения перебираются с заданным шагом. В этом блоке кода я пытаюсь учесть уравнения, содержащие неизвестные переменные, чтобы уменьшить исходные диапазоны возможных значений. После последней функции должны быть выведены окончательные комбинации значений (конкретные числа) для переменных (y00, y10, y20... y90_).

Python:
step = -0.01
for y30_ in np.arange(y30[0], y30[1], step):
    y00_ = function_vr(ph0b, et0, y30_)
    y10_ = function_vn(ph0b, et0, y30_)
    y20_ = function_o(ph0, et0, y30_)
    #print(f"y00_ = {y00_}, y10_ = {y10_}, y20_ = {y20_}, y30_ = {y30_}")
    
    for y50_ in np.arange(y50[0], y50[1], step):
      #print(y50_)
      
      for y60_ in np.arange(y60[1], y60[0], step):
        tn0_ = funct_tn(y50_, y60_)
        #print(y60_)
        
        for y70_ in np.arange(y70[1], y70[0], step):
          y80_ = funct_labt(y30_, y60_, y70_, y50_)
          function_gam(et0, y30_, ph0b, y50_, y60_, y70_, y80_)
          ht0, et0, y30_, ph0b, y50_, y60_, y70_, y80_  = symbols('ht0 et0 y30_ ph0b y50_ y60_ y70_ y80_')
          equation = Eq(ht0, (y50_ * et0 * cos(y30_) / sqrt(ph0b) + y60_ * -et0 * sin(y30_) / sqrt(ph0b) + y70_ * sqrt(1 / ph0b) * et0 * sin(y30_) + y80_ * (sqrt(1 / ph0b) * (1 + et0 * cos(y30_)) * (1 + et0 * cos(y30_))**2) / ph0b**2))
          #Use sympy.subs() method
          ham0 = solve(equation.subs(ht0, 0))
          #print(ham0)
          
          for y90_ in np.arange(y90[1], y90[0], step):
            function_propulsion(y40, y50_, y60_, y90_, ptb, mqb)
            function_deo(y40, y50_, y60_, y90_, ptb, mqb, pes)
 
    print(f"y00_ = {y00_}, y10_ = {y10_}, y20_ = {y20_}, y30_ = {y30_}, y50_ = {y50_}, y60_ = {y60_}, y70_ = {y70_}, y80_ = {y80_}, y90_ = {y90_}")
 

Al Frolov

Новичок
Пользователь
Фев 20, 2022
20
3
3
Я пытаюсь поймать эту ошибку, например такой код не работает, потому что sympy.subs не существует:
Python:
import sympy
a, b, c, d = sympy.symbols('a b c d')
eq = sympy.Eq(d, (a + b * c))
ha = sympy.subs(eq.subs(d, 0))
# Тут у тебя solve вместо sympy.subs, но что такое solve я не понял
print(ha)
Я шёл таким путём:

Python:
from sympy import *
from sympy import symbols

z, x, y = symbols('z x y')
equation = Eq(z, (2 * x + 2 * y))
zo = solve(equation.subs(z, 0))
print(zo)

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

Сейчас вопрос решил, применив fsolve из scipy.optimize. Это сработало, на выходе получил векторы значений искомых переменных. Спасибо за отзывчивость!

Python:
from scipy.optimize import fsolve

def function_gam(et0, y30_, ph0b, y50_, y60_, y70_, y80_):
    return function_gam
    root = fsolve(function_gam(et0, y30_, ph0b, y50_, y60_, y70_, y80_))
    root
    np.isclose(function_gam(root), [0.0, 0.0]) 
    array([ True,  True])
 
  • Мне нравится
Реакции: Vershitel_sudeb

Vershitel_sudeb

Vershitel sudeb
Команда форума
Модератор
Мар 17, 2021
973
220
43
21
Москва
Ну попробуй для начала проверить типы этих переменных, что это не строки
 

Al Frolov

Новичок
Пользователь
Фев 20, 2022
20
3
3
Ну попробуй для начала проверить типы этих переменных, что это не строки
Я новичок в питоне, как это сделать?
 

Vershitel_sudeb

Vershitel sudeb
Команда форума
Модератор
Мар 17, 2021
973
220
43
21
Москва
Например так:
Python:
for num, i in enumerate((var1, var2, var3)):
    if isinstance(i, str):
        print(f"Error: {num}")
напишет индекс неправильной переменной
 

Al Frolov

Новичок
Пользователь
Фев 20, 2022
20
3
3
Например так:
Python:
for num, i in enumerate((var1, var2, var3)):
    if isinstance(i, str):
        print(f"Error: {num}")
напишет индекс неправильной переменной
вставляю в блок, ошибки нет, но и не выводит ничего
 

Vershitel_sudeb

Vershitel sudeb
Команда форума
Модератор
Мар 17, 2021
973
220
43
21
Москва
ну да, она и должна написать только если ошибка, напиши так:
Python:
for num, i in enumerate((var1, var2, var3)):
    if isinstance(i, str):
        print(f"Error: {num}")
    else:
        print(f"{num}: {type(i)}")

Тогда выведутся все типы переменных
 
  • Мне нравится
Реакции: Al Frolov

Al Frolov

Новичок
Пользователь
Фев 20, 2022
20
3
3
ну да, она и должна написать только если ошибка, напиши так:
Python:
for num, i in enumerate((var1, var2, var3)):
    if isinstance(i, str):
        print(f"Error: {num}")
    else:
        print(f"{num}: {type(i)}")

Тогда выведутся все типы переменных
Проверил 5 переменных, участвующих в уравнении, у всех символьный тип, как и назначил. Как быть в таком случае? Я вижу, что программа не подставляет в эти переменные значения из области значений и не производит расчёт. На выходе я получаю не числа, а формулы, в которых вижу эти же переменные

0: <class 'sympy.core.symbol.Symbol>
1: <class 'sympy.core.symbol.Symbol'>
2: <class 'sympy.core.symbol.Symbol'>
3: <class 'sympy.core.symbol.Symbol'>
4: <class 'sympy.core.symbol.Symbol'>
 

Vershitel_sudeb

Vershitel sudeb
Команда форума
Модератор
Мар 17, 2021
973
220
43
21
Москва
Странно, а в какой это строке? а то я не увидел строку где используется 5 переменных
 

Al Frolov

Новичок
Пользователь
Фев 20, 2022
20
3
3
Странно, а в какой это строке? а то я не увидел строку где используется 5 переменных
Меня заинтересовали переменные строки 19 (все переменные с y - y30_, y50_, y60_, y70_, y80_), так как именно после добавления уравнения равного нулю (= строк 18-22) возникла проблема с выводом результатов. Думаю, что проблема именно в том, что пришлось перевести переменные, входящие в уравнение, в символьный тип.

Прогнал остальные переменные, которые не фигурировали в уравнении (т.е. в строках 18-22) - y00_, y10_. У них иной тип - <class 'sympy.core.mul.Mul'>.
 

Al Frolov

Новичок
Пользователь
Фев 20, 2022
20
3
3
Что-то не так с используемым символьным типом? В переменных, которые приобрели этот тип в строке 18, больше не происходит перебор числовых значений. Может нужно вернуть прежний тип переменным после того, как уравнение было учтено в блоке (например, после строки 21)?
 

Al Frolov

Новичок
Пользователь
Фев 20, 2022
20
3
3
Странно, а в какой это строке? а то я не увидел строку где используется 5 переменных
Подскажите, пожалуйста, как изменить строки 18-22, чтобы не нужно было изменять класс переменных на символьные?
 

Vershitel_sudeb

Vershitel sudeb
Команда форума
Модератор
Мар 17, 2021
973
220
43
21
Москва
Так, я только проснулся, пока не знаю как заменить. Почитаю доки, как разберусь - напишу.
 
  • Мне нравится
Реакции: Al Frolov

Vershitel_sudeb

Vershitel sudeb
Команда форума
Модератор
Мар 17, 2021
973
220
43
21
Москва
solve это
numpy.linalg.solve?
 

Al Frolov

Новичок
Пользователь
Фев 20, 2022
20
3
3
solve это
numpy.linalg.solve?
Это sympy.subs()
 

Al Frolov

Новичок
Пользователь
Фев 20, 2022
20
3
3
solve это
numpy.linalg.solve?
Есть ли у Вас предположение, как можно решить мою проблему?
 

Vershitel_sudeb

Vershitel sudeb
Команда форума
Модератор
Мар 17, 2021
973
220
43
21
Москва
Я пытаюсь поймать эту ошибку, например такой код не работает, потому что sympy.subs не существует:
Python:
import sympy
a, b, c, d = sympy.symbols('a b c d')
eq = sympy.Eq(d, (a + b * c))
ha = sympy.subs(eq.subs(d, 0))
# Тут у тебя solve вместо sympy.subs, но что такое solve я не понял
print(ha)
 
  • Мне нравится
Реакции: Al Frolov

Форум IT Специалистов