Я не могу понять, как отправить массив из функции optimis.minimize - PullRequest
0 голосов
/ 16 февраля 2020

Я создаю Python приложение для использования в sientifi c. Приложение представляет собой модель Predicive Controler (MP C), и я использую функцию scipy.optimize.minimize в качестве алгоритма оптимизации.

solution_guess = minimize(objectiveFunction,
                                  U_guess,
                                  arg_guess,
                                  callback= None,
                                  method = "SLSQP")

, где целевая функция является самодельной функцией, в которой выполняется симуляция моей системы. это выглядит примерно так:

def objectiveFunction(x,*arg):
    U_test = x
    dt_test = arg[0]
    setpoint_test = arg[1]
    pred_horizion_length_test = arg[2]
    initStateValue_test = arg[3]
    # Defining Model Arrays
    NS_pred_horizion_test = int(pred_horizion_length_test/dt_test)+1
    pred_horizion_array_test = np.linspace(0, pred_horizion_length_test, NS_pred_horizion_test)
    SP_array_test = np.zeros(NS_pred_horizion_test) + setpoint_test
    Y_array_test = SP_array_test * 0

    # Defining parameters for the testing model
    timeDelay_test = 50
    initDelayValue_test = 0
    K_test = 4
    Tc1_test = 30
    Tc2_test = 60

    # Defining Model Object
    obj_model_test = model.secDegModel(dt = dt_test,
                                      K = K_test,
                                      Tc1 = Tc1_test,
                                      Tc2 = Tc2_test,
                                      timeDelay = timeDelay_test,
                                      initStateValue = initStateValue_test,
                                      initDelayValue = initDelayValue_test
                                      )


    ###########################################
    #|||||||||||||||||||||||||||||||||||||||||#
    #     Testing Values for U on Model       #
    #|||||||||||||||||||||||||||||||||||||||||#
    ###########################################


    # Running simulation of "real" model function
    for k in range(NS_pred_horizion_test):
        Y_array_test[k] = obj_model_test.run(u_k = U_test) 

    error = np.sum(abs(SP_array_test-Y_array_test))
    return error

С чем я борюсь, так это с тем, как вернуть массив Y_array_test, чтобы я мог отображать его каждый раз, когда выполняется оптимизация. Я пытался использовать глобальные переменные, но я не получил его работать, и я не думаю, что это хороший способ кодирования для использования глобальных переменных. Кто-нибудь знает хороший способ решить мою проблему? может быть, используя функцию обратного вызова? (если обратный вызов - это путь к go, я не до конца понимаю, как работает этот метод или как его правильно реализовать)

Ответы [ 2 ]

0 голосов
/ 24 февраля 2020

Основываясь на ваших комментариях к моему первому ответу и повторному использованию некоторого кода из моего другого ответа (Само это написано путем изменения @Scott (Скотт Зиверт) ответ и используя его пакет GitHub drawnow )

Примечание:

Я не установил пакет Github drawnow . Вместо этого я просто скопировал drawnow.py в свою папку. (Это потому, что я не нашел способа установить его через conda. Я не хотел использовать PyPi)

Измените ваш код следующим образом

from numpy.random import random_sample
from numpy import arange, zeros

from drawnow import drawnow
from matplotlib import use
from matplotlib.pyplot import figure, axes, ion
from matplotlib import rcParams
from matplotlib.pyplot import style
from matplotlib.pyplot import cla, close
use("TkAgg")
pgf_with_rc_fonts = {"pgf.texsystem": "pdflatex"}
rcParams.update(pgf_with_rc_fonts)
style.use('seaborn-whitegrid')

scott_fig = figure()  # call here instead!
ion()
# figure()  # call here instead!
# ion()    # enable interactivity



solution_guess = minimize(objectiveFunction,
                          U_guess,
                          arg_guess,
                          callback= None,
                          method = "SLSQP")





def objectiveFunction(x,*arg):
    .
    .
    .
    .
    .
    def draw_fig():
        # can be arbitrarily complex; just to draw a figure
        # figure() # don't call!
        scott_ax = axes()
        scott_ax.plot(x, y, '-g', label='label')
        # Need to add some pause element here
        # otherwise you won't be able to see the figure as  
        # it will change too fast
        # cla()
        # close(scott_fig)
        # show() # don't call!

    # Running simulation of "real" model function
    for k in range(NS_pred_horizion_test):
        Y_array_test[k] = obj_model_test.run(u_k = U_test)

    # Just plot Y_array_test now that you have updated it


    drawnow(draw_fig)
    # Then you could plot it outside using matplotlib
    error = np.sum(abs(SP_array_test-Y_array_test))
    return error
0 голосов
/ 19 февраля 2020

Почему бы вам просто не сделать следующее?

Измените свою целевую функцию следующим образом

from numpy import savez

def objectiveFunction(x,*arg):
.
.
.
.
.

# Running simulation of "real" model function
for k in range(NS_pred_horizion_test):
    Y_array_test[k] = obj_model_test.run(u_k = U_test) 
# Just save Y_array_test in a file
# Add some call_no if you don't want to overwrite
# then filename would be 'Y_array_test_' + str(call_no) 
# You could increment this call_no, every time by 
# call_no = call_no + 1
savez(file_name, Y_array_test)
# Then you could plot it outside using matplotlib
error = np.sum(abs(SP_array_test-Y_array_test))
return error
...