Search code examples
cplexconstraint-programmingdocplex

Is it possible to evaluate a cumul function at a specific moment in time in CPLEX?


I'm trying to add a minimization criterion of accumulated capacity usage throughout time. The capacity usage is modeled using a cumul function, consisting of a summation of pulse() functions, where each scheduled interval would contribute to the used capacity. The max/min-capacity boundaries also vary over time, so i figured i'd model these with cumul functions as well (summation of step() functions on specified times).

I want to incorporate a fraction of a penalty (also varying over time) proportional to the fraction by which the usage exceeds the maximum capacity. My problem is that the evaluation of these cumul functions happens using height_at_start(interval, function) or height_at_end(interval, function) calls, but these min/max-boundaries, or penalty values can effectively change, independent of intervals, as well. I saw in the documentation that there is a function provided called 'get_value()', however, it seems that this is only callable on CpoStepFunctions, where the stepheight cannot be defined by a decision variable. Is there a possibility to evaluate such cumul functions at specific times?

CPLEX python documentation

Kind regards, Jasper


Solution

  • The max/min-capacity boundaries also vary over time, so i figured i'd model these with cumul functions as well (summation of step() functions on specified times).

    For min-max capacity profiles, you should use some always_in constraints. They are of the form:


    always_in(F, StartTime, EndTime, LevelMin, LevelMax) 
    

    where F is your cumul function.

    It says that on (known) time window [StartTime,EndTime), the level of the function must always be between LevelMin (can of course be 0) and LevelMax. So you can post one of such constraint for each time-window where the LevelMin/LevelMax is the same.

    Is there a possibility to evaluate such cumul functions at specific times?

    There is no direct expression for evaluating this type of value. The usual way to model it is by using a secondary (technical) cumul function.

    Let:

    F = sum([pulse(A[i],Q[i]) for i in …])
    

    be your original cumul function (on which you post min and max levels).

    If you want to get the level of F at some times t_j (j=0,1,2,…,n-1), you can create some fixed interval variables TIME[j] (start=t_i, end=t_i+1).

    And you would create a technical cumul function :

    G = F - sum([pulse(TIME[j],0,M) for j in range(n)])
    

    Where M is a large number (larger than the max level of F).

    The idea is that if you post a constraint that G=0 on interval TIME[j], then necessarily, the height of the contribution of TIME[j] in G is equal to the value of F at TIME[j]. So you add constraints:


    [ always_in(G,TIME[j],0,0) for j in range(n) ]
    

    And the value of F at time t_j is given by:


    -height_at_start(TIME[j],G)