I have a simple optimal control problem where I have to find a step function f(t) to maximize an objective functional (IMODE=6
). Now f(t) is defined for t in [0, 10) such that f takes on 10 different equi-spaced values. (i.e. f(t)=f0 for 0 ≤ t < 1, etc.). Moreover f itself takes on only integer values in between 0 and 10 inclusive.
To start, I took m.time=np.linspace(0, 10, 11)
to have [0, 1, 2, ..., 10]
be the points in my time mesh. Then I took f=m.MV(lb=0, ub=10, integer=True)
and solved with APOPT using m.options.SOLVER = 1
and just ignored the value of f(10).
This resolves fine and I am able to acquire an integer solution. The result of this, it appears, is a linear interpolant of f instead of the step-function interpolant of f that I wanted. After reading documentation, I thought that MV_TYPE was the flag that I needed. So I tried switching f to a step-function by setting m.options.MV_TYPE=0
but that gave me the same result as obtained by m.options.MV_TYPE=1
. (Telling me that I completely misunderstand what MV_TYPE is supposed to do.) So for my first question: what even is the MV_TYPE flag doing? My read was that MV_TYPE=0 interpolates all MV variables with a step-function and MV_TYPE=1 interpolates all MV variables with a linear interpolant. However, two separate runs with both options for MV_TYPE yields identical solutions with identical objective functional values.
Secondly, is there some better way to do what I want? (Force my control to take the form of a discontinuous step function). I saw in the documentation (example #17 of 18) that the appropriate way to make a step function is basically to make the time mesh fine enough to cover the seam. Indeed, something like m.time=[0, 0.999, 1, 1.999, 2, 2.999, ..., 9, 9.999]
would be a reasonable mesh for me. However, then my f=m.MV
line would result in f
having 20 independent values (instead of the 10 that I would like). Is there anyway to force the MV to take the same value at the time points t=0
and t=0.999
(and the same value at t=1
and t=1.999
etc.) in order to ensure that my function is a step-function?
I can't help but feel like I'm missing something obvious here!
Your understanding of MV_TYPE
is correct. From the document for MV_TYPE:
MV_TYPE specifies either a zero order hold (0) or a first order linear (1) interpolation between the MV endpoints. When the MV_STEP_HOR is two or greater, the MV_TYPE is applied only to each segment where adjustments are allowed. The MV segment is otherwise equal to the prior time segment. The MV_TYPE only influences the solution when the number of NODES is between 3 and 6. It is not important when NODES=2 because there are no interpolation nodes between the endpoints.
It is likely giving the same answer because m.options.NODES=2
by default. Setting m.options.NODES>=3
will likely cause problems for integer type MVs with MV_TYPE=1
because the linear interpolating points also need to be integers. If you still want to use NODES=2
but need more simulation resolution then try something like:
m.time = [0,0.5,0.9999,1,1.5,1.9999,2,2.5,2.9999,3]