#### How to constrict your problem to allow a custom-defined "cool-off period"?

I am making use of CVXPY and CVXOPT to solve a problem which allows us to control the running of motors in the cheapest possible ways.

We have existing constraints which consist of, cost, volume and level which needs to be maintained (all of which work, and is only to give a further definition of the problem at hand). We use this to minimize the cost and provide an optimized approach.

Recently, we wish to add a new constraint which will allow for a cool-off period. Which we can set. So if the selection value is 1, the next two periods should be a 0 if this makes sense. Essentially, if the pump runs for a period it should be off for the next two to cool down.

Please see below for a current function which is being used. Currently no cool-off constraint has been implemented and wish to get a push in the right direction of how best to implement such a solution.

``````def optimiser(self, cost_, volume_,v_min,flow_,min_level,max_level,initial_level,period_lengths,out_flow_, errors) :
"""
This function optimises the regime possible combinations using convex optimisation. We assign and define the problem and uses `GLPK_MI` to solve our problem.

Parameters
----------
cost_
Numpy Array
volume_
Numpy Array
v_min
Float -> minimum volume
flow_
Numpy Array
min_level
Float -> minimum level
max_level
Float -> maximum level
initial_level
Float -> initial level
period_lengths
Integer -> number of period lengths
out_flow_
Numpy Array
errors
Exceptions -> error handling

Returns
----------
selection
Solved problem with the best possible combination for pumping regime.
"""
FACTOR =  0.001*1800*self.RESERVOIR_VOLUME
input_flow_matrix=np.zeros((max(period_lengths),len(period_lengths)))
for i,l in enumerate(period_lengths):
input_flow_matrix[:l,i]=1
selection = cp.Variable(shape=cost_.shape,boolean=True)
assignment_constraint = cp.sum(selection,axis=1) == 1
input_flow_= cp.sum(cp.multiply(flow_,selection),axis=1)
input_flow_vector=cp.vec(cp.multiply(input_flow_matrix,np.ones((max(period_lengths), 1)) @ cp.reshape(input_flow_,(1,len(period_lengths)))))
res_flow= (input_flow_vector-cp.vec(out_flow_))
res_level=cp.cumsum(res_flow) * FACTOR + initial_level
volume_= cp.sum(cp.multiply(volume_,selection))
volume_constraint = volume_ >= v_min
min_level_constraint = res_level >= min_level
max_level_constraint = res_level <= max_level

if errors is LevelTooLowError:
constraints = [assignment_constraint, max_level_constraint, volume_constraint]
elif errors is LevelTooHighError:
constraints = [assignment_constraint, min_level_constraint, volume_constraint]
elif errors is MaxVolumeExceededError:
constraints = [assignment_constraint, min_level_constraint, volume_constraint]
else:
constraints = [assignment_constraint, max_level_constraint, min_level_constraint, volume_constraint]

cost_ = cp.sum(cp.multiply(cost_,selection))
assign_prob = cp.Problem(cp.Minimize(cost_),constraints)
assign_prob.solve(solver=cp.GLPK_MI, verbose=False)
return selection
``````

I hope my problem has been well defined for anyone to understand what I wish to do at the moment. If anything else is needed, I can happily provide this for anyone.