Dear all,

I am implementing a model predictive controller, which means that I have to solve as fast as possible a series of optimization problems with the same structure but with different data. I have successfully adapted the example of Python API library (transport11.py) to change a parameter in my model and solve it again using the model instance class. However, this is not a perfect solution to my problem because I cannot now in advance what will be the different values that the parameter will take.

I would like to create a function that receives a new value and solves the optimization problem without instantiating the model instance again. The best that I have achieved so far is to load a check point from a previous, offline run. In the online part of the code, I still have to call methods .add_modelinstance() and .instantiate(), which require a significant amount of time. Also, trying to pickle the model instance object was not effective because it produced an error “can’t pickle _thread.lock objects”.

Do you have any suggestions?

Thank you in advance,

Bruno

Bruno,

You might want to have a look at the transport7.py example: https://www.gams.com/latest/docs/apis/examples_python/transport7_8py_source.html

This shows how you can use the GamsModelinstance class. More information is available in the documentation: https://www.gams.com/latest/docs/apis/python/classgams_1_1execution_1_1GamsModelInstance.html

Hope that helps,

Clemens

Dear Clemens,

Thank you for your advice. From my understanding of such example, I was able to write the attached piece of code, where instead of just calling ws.add_checkpoint() to add a new checkpoint, I can reuse a previous one.

However, this does not solve my problem because the commands in lines indicated with #1 and #2, related to the creation of a model instance, require a significant amount of time to process. My objective is to avoid to call these commands at every single iteration, instead I would like to only change the modifier (not included in this minimal example) and solve the new optimization problem.

semi.txt (484 Bytes)

Bruno,

You do not have to call those methods multiple times. After you have instantiated your GamsModelinstance you have also defined the symbols that you want to change (GamsModifier). All you have to do is to change the data in your symbol (ySp) and call mi.solve().

Can you can provide a larger example with the actual loop in which you do the solve?

Best,

Clemens

Dear Clemens,

I have attached an example of a workaround that I implemented instead of the solution that I was looking for. I hope this will make my intention clearer.

The main problem is that I do not know beforehand what will be the values to be modified in the future, because they are calculated by an external code and they depend on the solution of the current optimization problem. The sequence of calculations is as follows:

x(0): provided by the user

u(0): solution of the optimization problem at time 0 (i.e., using x(0) as an input).

x(1): next state of the system, calculated by an external Matlab simulation using u(0)

u(1): solution of the optimization problem at time 1 (using x(1))

etc.

In the attached files, the Python code is in an infinite loop to keep the ModelInstance in memory. Communication between Matlab and Python is done through .mat files, with a timer in each program to force it to wait while the other program does its calculations. What bothers me in this implementation is exactly these timers, because they increase the total computational time and it is not perfectly reliable in the sense that it may occur an access to a file that is not completely finished or being written.

I would like to have a function call in Matlab to the Python API to solve these two issues, but if the definition of the model instance in Python is encapsulated within a function, it must be re-instantiated at each time or “loaded” from a previous instance.

Example.zip (1.63 KB)

Bruno,

Sorry for the delay. It seems to me that you did solve your original problem where you did the mi.instantiate call multiple times. So from a GAMS/Python perspective the code looks actually correct to me.

The new problem that arises now is that you also want to do some calculations in MatLab “on-the-fly”. Somehow you need to synchronize this and currently you are doing this by exploiting the existence of certain files that are generated by Python and MatLab. Unfortunately I have no experience with MatLab, but in principle you want to have a synchronous call from one language to the other (e.g. from Python to MatLab) in order to get rid of the file/timer approach. The following page seems to have documentation on how to do this at least from within Python: https://www.mathworks.com/help/matlab/matlab_external/call-user-script-and-function-from-python.html

If you implement it using this approach you have Python in control which makes use of MatLab functions.

If you want to have MatLab in control you indeed have the problem that you have to save the state of Python somehow in order to make use of the already instantiated GamsModelinstance. Perhaps you could encapsulate your logic in a Python class that you instantiate from within MatLab. The GamsModelinstance would be a member of the object which can be used from MatLab at any point of time. I found the following documentation that described how to do this: https://www.mathworks.com/help/matlab/matlab_external/create-object-from-python-class.html

Best,

Clemens