0

I am building a Python application for use in sientific computing. The application is a Model Predicive Controler (MPC) and I am using scipy.optimize.minimize function as the optimization algorithm.

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

where the objective function is a self made function where a simulation of my system is executed. it looks some like this:

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

What i struggle with no is how to get back the Y_array_test array so I can plot it every time the optimization is done. I tryed using global variables but i did not get it to work nor do I think its good coding manner to use global variables. does any one know a nice way to solv my problem? maybe using callback function? (if callback is the way to go, I do not fully understand how this method works or how to implement it in a nice way)

  • the signature of callback is 'callback(xk) ' where xk is the current parameter vector. – Tejas Shetty Mar 06 '20 at 11:20
  • x0 is the starting guess vector. x1 is the first vector. x2 second, xk the kth vector and so on. – Tejas Shetty Mar 06 '20 at 11:20
  • To use callback your requirements would need to deal only with U (as in U_guess, U_test). But you want Y_array_test array. Hence it seems unlikely that callback could be used, without some gymnastics. – Tejas Shetty Mar 06 '20 at 11:30

2 Answers2

0

Why don't you just do the following?

Modify your objectiveFunction as follows

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
Tejas Shetty
  • 685
  • 6
  • 30
  • 1
    Thank you that is acctual a good solution to my problem. but it would be nice to have a way for sending data from the objective function back to the code without saving/loading it to a file... – user2929502 Feb 21 '20 at 13:07
  • You just want a plot of the array right? @user2929502 Maybe this could help https://stackoverflow.com/a/57305659/7952027 – Tejas Shetty Feb 24 '20 at 06:11
0

Based on your comments on my first answer and reusing some code from my other answer (This itself is written by modifying @Scott (Scott Sievert) answer and using his drawnow Github package)

Imp note:

I didn't install drawnow Github package . Instead I just copied drawnow.py into my folder. (This is because I didn't find any way to install it via conda. I didn't wan't to use PyPi)

Modify your code as follows

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
Tejas Shetty
  • 685
  • 6
  • 30