I have an issue when using CVXPY that I wish to calculate the input flow for a calculation for an additional constraint within my program, I have a selection boolean variable that I am using to determine the flow rate which in turn is used to reshape a vector to fit what I need.
In this sense I am calculating estimated reservoir flows over a 24 hour period, so the selected flows are set across 7 periods of varying time periods (split into 30 minute intervals), the problem I am trying to sort is that often, it could take maybe 4 30 minute periods to go from say 15 l/s to the desired 17 l/s flow rate which can ultimate have a large effect on my calculation for smaller surface areas which is what I wish to eliminate here.
Example output currently for 1 period out of 7 (00:00 - 08:00):
[120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120]
# Imagine our ramp rate is actually 0.5l/s per 30 minutes and currently at 118l/s
Expected output:
[118 118.5 119 119.5 120 120 120 120 120 120 120 120 120 120 120 120]
I hope above example makes sense to what I wish to achieve
See below my current solution that I have implemented without a ramp rate developed in to the current problem.
FACTOR = 1/self.SURFACE_AREA
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_))
net_volume = res_flow * 1.8
res_level=cp.cumsum(net_volume) * 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
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.CPLEX, verbose=False)
My assumption here would be to include a boolean variable that would indicate if the flow rate is changing across my 7 periods which is from the input_flow_
variable. However I am just unsure how to actually develop a good solution, would this be needed over a matrix or something similar? Any help would be much appreciated.
I can provide figures if it helps with reproducibility.
If I have understand your question correctly, you should re-implement the flow_
considering the ramp rate. I didn't model the general case, but the following should work for your situation.
# delta flow, models the 1-hop influence of certain selection (next )
delta_flow_ = [5, 5, 5, 5, 4.5, 5, 4.5]
selection_of_previous_period = cp.hstack([selection[0:-1, :], np.zeros((1, num_of_pumps))]) # assume selection is flase at the beginning of the day
existence_of_delta_flow = cp.multiply(1-selection_of_previous_period, selection) # delta flow exist when previous period is close and now is open
input_flow_ = input_flow_ - cp.sum(cp.multiply(delta_flow_, existence_of_delta_flow), axis=1)
# delta delta flow, models the 2-hop influence of certain selection
delta_delta_flow_ = [0, 0, 0, 0, 0, 0.5, 0]
selection_of_previous_period2 = cp.hstack([selection[0:-2, :], np.zeros((2, num_of_pumps))]) # assume selection is flase at the beginning of the day
# delta_delta_flow[i] exist if selection[i-2] is False, and selection[i-1] is True, and selection[i] is True
# the delta_delta_flow_[6] is 0.5, which means if selection[4]=False (pump not selected in period[4], indexing from 0)
# and selection[5]=True (pump selected in period[5]) and and selection[6]=True
# delta_delta_flow[i] is non_zero when the length period[i-1]<4*30min
existence_of_delta_delta_flow = existence_of_delta_flow = cp.multiply(cp.multiply(1-selection_of_previous_period2, selection_of_previous_period), selection)
input_flow_ = input_flow_ - cp.sum(cp.multiply(delta_delta_flow_, existence_of_delta_delta_flow), axis=1)
# For general case, you may need "delta_delta_delta_flow_", which model the 3-hop influence of certain selection
In addition, I think volume_
may also need to be re-implemented considering the ramp rate. You can imitate my codes and do it yourself.