def __get_model__(self, relaxed=False): """Create gurobi API model. Args: relaxed (:bool:): This flag describes if logic values are relaxed. Default ``False``. Example: ``{'TimeLimit': 10}``. """ self.__create_gurobi_model__() self.__create_vars__() self.__create_objfunc__() self.__create_constraints_aux__ self.__create_constraints__() if self.list_y_init is not None: self.s[self.I[0], 1].lb = 1 self.m.update() model = solution.Solution( self.m, dict(s=self.s, tr=self.tr, r=self.r, er=self.er, e=self.e, u=self.u, w=self.w, z=self.z, cr=self.cr, y=self.y, mu=self.mu)) return model
def update_lambda1(self, lambda1, sol): """Update lambda in DPP model Args: lambda1 (:obj:`list`): Array with lambda values. """ self.solution = sol self.lambda1 = lambda1 self.__create_vars__() self.__create_objfunc__() self.__create_constraints__() self.m.update() self.model = solution.Solution( self.m, dict(s=self.s, tr=self.tr, r=self.r, er=self.er, e=self.e, u=self.u, w=self.w, z=self.z, cr=self.cr, y=self.y, mu=self.mu))
def set_model(self, model): self.model = solution.Solution( model, dict(s=self.s, tr=self.tr, r=self.r, er=self.er, e=self.e, u=self.u, w=self.w, z=self.z, cr=self.cr, y=self.y, mu=self.mu))
def gather_solution(self, DPP_sol_row, initial_solution): counter = 0 s = gurobipy.tupledict() tr = gurobipy.tupledict() r = gurobipy.tupledict() er = gurobipy.tupledict() e = gurobipy.tupledict() Tlen = self.problem_data.get_names("wildfire") Ilen = self.problem_data.get_names("resources") Glen = self.problem_data.get_names("groups") for res in Ilen: DPP = DPP_sol_row[counter] for tt in Tlen: s[res,tt] = DPP.get_variables().get_variable('s')[res,tt].X tr[res,tt] = DPP.get_variables().get_variable('tr')[res,tt].X r[res,tt] = DPP.get_variables().get_variable('r')[res,tt].X er[res,tt] = DPP.get_variables().get_variable('er')[res,tt].X e[res,tt] = DPP.get_variables().get_variable('e')[res,tt].X counter = counter + 1 vars = gurobipy.tupledict() vars["s"] = s vars["tr"] = tr vars["r"] = r vars["er"] = er vars["e"] = e modelcopy = initial_solution.get_model().copy() modelcopy.update() sol1 = _sol.Solution(modelcopy, vars) counter=0 for res in Ilen: DPP = DPP_sol_row[counter] for tt in Tlen: sol1.get_model().getVarByName("start["+res+","+str(tt)+"]").start = DPP.get_variables().get_variable('s')[res,tt].X sol1.get_model().getVarByName("travel["+str(res)+","+str(tt)+"]").start = DPP.get_variables().get_variable('tr')[res,tt].X sol1.get_model().getVarByName("rest["+str(res)+","+str(tt)+"]").start = DPP.get_variables().get_variable('r')[res,tt].X sol1.get_model().getVarByName("end_rest["+str(res)+","+str(tt)+"]").start = DPP.get_variables().get_variable('er')[res,tt].X sol1.get_model().getVarByName("end["+str(res)+","+str(tt)+"]").start = DPP.get_variables().get_variable('e')[res,tt].X counter = counter + 1 #for gro in Glen: # for tt in Tlen: # sol1.get_model().getVarByName("missing_resources["+gro+","+str(tt)+"]").start = DPP.get_variables().get_variable('mu')[gro,tt].X sol1.get_model().update() #print(sol1.get_model().getVars()) # mu[res,tt] = DPP.get_variables().get_variable('mu')[res,tt] return sol1
def model(self, data, relaxed=False, slack_containment=False, valid_constraints=None, slack_penalty=1000000000000): """Wildfire suppression model. Args: data (:obj:`firedecomp.model.InputModel`): problem data. relaxed (:obj:`bool`): if True variables will be continuous. Defaults to False. slack_containment (:obj:`bool`): if True add slack variable to wildfire containment constraints. Defaults to False. slack_penalty (:obj:`float`): slack containment penalty. """ self.m = gurobipy.Model("wildfire_supression") if relaxed is True: vtype = gurobipy.GRB.CONTINUOUS lb = 0 ub = 1 else: vtype = gurobipy.GRB.BINARY lb = 0 ub = 1 if valid_constraints is None: valid_constraints = ['contention', 'work', 'max_obj'] # Variables # ========= # Resources # --------- self.s = self.m.addVars(data.I, data.T, vtype=vtype, lb=lb, ub=ub, name="start") self.tr = self.m.addVars(data.I, data.T, vtype=vtype, lb=lb, ub=ub, name="travel") self.r = self.m.addVars(data.I, data.T, vtype=vtype, lb=lb, ub=ub, name="rest") self.er = self.m.addVars(data.I, data.T, vtype=vtype, lb=lb, ub=ub, name="end_rest") self.e = self.m.addVars(data.I, data.T, vtype=vtype, lb=lb, ub=ub, name="end") # Auxiliar variables self.u = {(i, t): self.s.sum(i, data.T_int.get_names(p_max=t)) - self.e.sum(i, data.T_int.get_names(p_max=t - 1)) for i in data.I for t in data.T} self.w = {(i, t): self.u[i, t] - self.r[i, t] - self.tr[i, t] for i in data.I for t in data.T} self.z = {i: self.e.sum(i, '*') for i in data.I} self.cr = {(i, t): sum([ (t + 1 - t1) * self.s[i, t1] - (t - t1) * self.e[i, t1] - self.r[i, t1] - data.WP[i] * self.er[i, t1] for t1 in data.T_int.get_names(p_max=t) ]) for i in data.I for t in data.T if not data.ITW[i] and not data.IOW[i]} self.cr.update({ (i, t): (t + data.CWP[i] - data.CRP[i]) * self.s[i, data.min_t] + sum([ (t + 1 - t1 + data.WP[i]) * self.s[i, t1] for t1 in data.T_int.get_names(p_min=data.min_t + 1, p_max=t) ]) - sum([(t - t1) * self.e[i, t1] + self.r[i, t1] + data.WP[i] * self.er[i, t1] for t1 in data.T_int.get_names(p_max=t)]) for i in data.I for t in data.T if data.ITW[i] or data.IOW[i] }) # Wildfire # -------- self.y = self.m.addVars(data.T + [data.min_t - 1], vtype=vtype, lb=lb, ub=ub, name="contention") self.mu = self.m.addVars(data.G, data.T, vtype=gurobipy.GRB.CONTINUOUS, lb=0, name="missing_resources") if slack_containment: slack_cont1 = self.m.addVar(vtype=gurobipy.GRB.CONTINUOUS, lb=0, name="slack_containment_1") slack_cont2 = self.m.addVars(data.T, vtype=gurobipy.GRB.CONTINUOUS, lb=0, name="slack_containment_2") # Objective # ========= self.obj_expression = \ sum([data.C[i]*self.u[i, t] for i in data.I for t in data.T]) + \ sum([data.P[i] * self.z[i] for i in data.I]) + \ sum([data.NVC[t] * self.y[t-1] for t in data.T]) + \ sum([data.Mp*self.mu[g, t] for g in data.G for t in data.T]) + \ 0.001*self.y[data.max_t] if slack_containment: self.obj_expression += \ slack_penalty * slack_cont1 + \ sum([slack_penalty * slack_cont2[t] for t in data.T]) self.m.setObjective(self.obj_expression, gurobipy.GRB.MINIMIZE) # Constraints # =========== # Valid constraints # ----------------- if 'contention' in valid_constraints: expr_lhs = {t: self.y[t] for t in data.T} expr_rhs = {t: self.y[t - 1] for t in data.T} self.m.addConstrs((expr_lhs[t] <= expr_rhs[t] for t in data.T), name='valid_constraint_contention') if 'work' in valid_constraints: expr_lhs = {(i, t): self.w[i, t] for i in data.I for t in data.T} expr_rhs = {t: self.y[t - 1] for t in data.T} self.m.addConstrs((expr_lhs[i, t] <= expr_rhs[t] for i in data.I for t in data.T), name='valid_constraint_contention') # Wildfire Containment # -------------------- self.m.addConstr(self.y[data.min_t - 1] == 1, name='start_no_contained') if slack_containment: wildfire_containment_1_expr = \ sum([data.PER[t] * self.y[t - 1] for t in data.T]) <= \ sum([data.PR[i, t] * self.w[i, t] for i in data.I for t in data.T]) + \ slack_cont1 else: wildfire_containment_1_expr = \ sum([data.PER[t] * self.y[t - 1] for t in data.T]) <= \ sum([data.PR[i, t] * self.w[i, t] for i in data.I for t in data.T]) self.m.addConstr(wildfire_containment_1_expr, name='wildfire_containment_1') if slack_containment: wildfire_containment_2_expr = ( data.M * self.y[t] + slack_cont2[t] >= sum([data.PER[t1] for t1 in data.T_int.get_names(p_max=t)]) * self.y[t - 1] - sum([ data.PR[i, t1] * self.w[i, t1] for i in data.I for t1 in data.T_int.get_names(p_max=t) ]) for t in data.T) else: wildfire_containment_2_expr = ( data.M * self.y[t] >= sum([data.PER[t1] for t1 in data.T_int.get_names(p_max=t)]) * self.y[t - 1] - sum([ data.PR[i, t1] * self.w[i, t1] for i in data.I for t1 in data.T_int.get_names(p_max=t) ]) for t in data.T) self.m.addConstrs(wildfire_containment_2_expr, name='wildfire_containment_2') # Start of activity # ----------------- self.m.addConstrs((data.A[i] * self.w[i, t] <= sum( [self.tr[i, t1] for t1 in data.T_int.get_names(p_max=t)]) for i in data.I for t in data.T), name='start_activity_1') self.m.addConstrs((self.s[i, data.min_t] + sum([ (data.max_t + 1) * self.s[i, t] for t in data.T_int.get_names(p_min=data.min_t + 1) ]) <= data.max_t * self.z[i] for i in data.I if data.ITW[i] == True), name='start_activity_2') self.m.addConstrs((sum([self.s[i, t] for t in data.T]) <= self.z[i] for i in data.I if data.ITW[i] == False), name='start_activity_3') # End of Activity # --------------- self.m.addConstrs((sum([ self.tr[i, t1] for t1 in data.T_int.get_names(p_min=t - data.TRP[i] + 1, p_max=t) ]) >= data.TRP[i] * self.e[i, t] for i in data.I for t in data.T), name='end_activity') # Breaks # ------ self.m.addConstrs((0 <= self.cr[i, t] for i in data.I for t in data.T), name='Breaks_1_lb') self.m.addConstrs( (self.cr[i, t] <= data.WP[i] for i in data.I for t in data.T), name='Breaks_1_ub') self.m.addConstrs((self.r[i, t] <= sum([ self.er[i, t1] for t1 in data.T_int.get_names(p_min=t, p_max=t + data.RP[i] - 1) ]) for i in data.I for t in data.T), name='Breaks_2') self.m.addConstrs((sum([ self.r[i, t1] for t1 in data.T_int.get_names(p_min=t - data.RP[i] + 1, p_max=t) ]) >= data.RP[i] * self.er[i, t] if t >= data.min_t - 1 + data.RP[i] else data.CRP[i] * self.s[i, data.min_t] + sum([ self.r[i, t1] for t1 in data.T_int.get_names(p_max=t) ]) >= data.RP[i] * self.er[i, t] for i in data.I for t in data.T), name='Breaks_3') self.m.addConstrs((sum([ self.r[i, t1] + self.tr[i, t1] for t1 in data.T_int.get_names(p_min=t - data.TRP[i], p_max=t + data.TRP[i]) ]) >= len( data.T_int.get_names(p_min=t - data.TRP[i], p_max=t + data.TRP[i])) * self.r[i, t] for i in data.I for t in data.T), name='Breaks_4') # Maximum Number of Usage Periods in a Day # ---------------------------------------- self.m.addConstrs((sum([self.u[i, t] for t in data.T]) <= data.UP[i] - data.CUP[i] for i in data.I), name='max_usage_periods') # Non-Negligence of Fronts # ------------------------ self.m.addConstrs((sum([self.w[i, t] for i in data.Ig[g]]) >= data.nMin[g, t] * self.y[t - 1] - self.mu[g, t] for g in data.G for t in data.T), name='non-negligence_1') self.m.addConstrs( (sum([self.w[i, t] for i in data.Ig[g]]) <= data.nMax[g, t] * self.y[t - 1] for g in data.G for t in data.T), name='non-negligence_2') # Logical constraints # ------------------------ self.m.addConstrs( (sum([t * self.e[i, t] for t in data.T]) >= sum([t * self.s[i, t] for t in data.T]) for i in data.I), name='logical_1') self.m.addConstrs( (sum([self.e[i, t] for t in data.T]) <= 1 for i in data.I), name='logical_2') self.m.addConstrs((self.r[i, t] + self.tr[i, t] <= self.u[i, t] for i in data.I for t in data.T), name='logical_3') self.m.addConstrs( (sum([self.w[i, t] for t in data.T]) >= self.z[i] for i in data.I), name='logical_4') self.m.update() return solution.Solution( self.m, dict(s=self.s, tr=self.tr, r=self.r, er=self.er, e=self.e, u=self.u, w=self.w, z=self.z, cr=self.cr, y=self.y, mu=self.mu))
def model(data, relaxed=False): """Wildfire suppression model. data (:obj:`firedecomp.model.InputModel`): problem data. """ m = scip.Model("wildfire_supression") if relaxed is True: vtype = "C" lb = 0 ub = 1 else: vtype = "B" lb = 0 ub = 1 # Variables # ========= # Resources # --------- s = {} tr = {} r = {} er = {} e = {} for i in data.I: for t in data.T: s[i, t] = m.addVar(vtype=vtype, lb=lb, ub=ub, name="start[%s,%s]" % (i, t)) tr[i, t] = m.addVar(vtype=vtype, lb=lb, ub=ub, name="travel[%s,%s]" % (i, t)) r[i, t] = m.addVar(vtype=vtype, lb=lb, ub=ub, name="rest[%s,%s]" % (i, t)) er[i, t] = m.addVar(vtype=vtype, lb=lb, ub=ub, name="end_rest[%s,%s]" % (i, t)) e[i, t] = m.addVar(vtype=vtype, lb=lb, ub=ub, name="end[%s,%s]" % (i, t)) # Auxiliar variables u = {(i, t): scip.quicksum(s[i, tind] for tind in data.T_int.get_names(p_max=t)) - scip.quicksum(e[i, tind] for tind in data.T_int.get_names(p_max=t - 1)) for i in data.I for t in data.T} w = {(i, t): u[i, t] - r[i, t] - tr[i, t] for i in data.I for t in data.T} z = {i: scip.quicksum(e[i, tind] for tind in data.T) for i in data.I} cr = {(i, t): sum([(t + 1 - t1) * s[i, t1] - (t - t1) * e[i, t1] - r[i, t1] - data.WP[i] * er[i, t1] for t1 in data.T_int.get_names(p_max=t)]) for i in data.I for t in data.T if not data.ITW[i] and not data.IOW[i]} cr.update({ (i, t): (t + data.CWP[i] - data.CRP[i]) * s[i, data.min_t] + sum([(t + 1 - t1 + data.WP[i]) * s[i, t1] for t1 in data.T_int.get_names(p_min=data.min_t + 1, p_max=t)]) - sum([(t - t1) * e[i, t1] + r[i, t1] + data.WP[i] * er[i, t1] for t1 in data.T_int.get_names(p_max=t)]) for i in data.I for t in data.T if data.ITW[i] or data.IOW[i] }) # Wildfire # -------- y = { t: m.addVar(vtype=vtype, lb=lb, ub=ub, name="contention[%s]" % t) for t in data.T + [data.min_t - 1] } mu = {(g, t): m.addVar(vtype="C", lb=0, name="missing_resources[%s,%s]" % (g, t)) for g in data.G for t in data.T} # Objective # ========= m.setObjective(sum([data.C[i] * u[i, t] for i in data.I for t in data.T]) + sum([data.P[i] * z[i] for i in data.I]) + sum([data.NVC[t] * y[t - 1] for t in data.T]) + sum([data.Mp * mu[g, t] for g in data.G for t in data.T]) + 0.001 * y[data.max_t], sense="minimize") # Constraints # =========== # Wildfire Containment # -------------------- m.addCons(y[data.min_t - 1] == 1, name='start_no_contained') m.addCons(sum([data.PER[t] * y[t - 1] for t in data.T]) <= sum( [data.PR[i, t] * w[i, t] for i in data.I for t in data.T]), name='wildfire_containment_1') for t in data.T: m.addCons( data.M * y[t] >= sum([data.PER[t1] for t1 in data.T_int.get_names(p_max=t)]) * y[t - 1] - sum([ data.PR[i, t1] * w[i, t1] for i in data.I for t1 in data.T_int.get_names(p_max=t) ]), name='wildfire_containment_2[%s]' % t) # Start of activity # ----------------- for i in data.I: for t in data.T: m.addCons(data.A[i] * w[i, t] <= sum( [tr[i, t1] for t1 in data.T_int.get_names(p_max=t)]), name='start_activity_1[%s,%s]' % (i, t)) for i in data.I: if data.ITW[i] == True: m.addCons(s[i, data.min_t] + sum([ (data.max_t + 1) * s[i, t] for t in data.T_int.get_names(p_min=data.min_t + 1) ]) <= data.max_t * z[i], name='start_activity_2[%s]' % i) for i in data.I: if data.ITW[i] == False: m.addCons(sum([s[i, t] for t in data.T]) <= z[i], name='start_activity_3[%s]' % i) # End of Activity # --------------- for i in data.I: for t in data.T: m.addCons(sum([ tr[i, t1] for t1 in data.T_int.get_names(p_min=t - data.TRP[i] + 1, p_max=t) ]) >= data.TRP[i] * e[i, t], name='end_activity[%s,%s]' % (i, t)) # Breaks # ------ for i in data.I: for t in data.T: m.addCons(0 <= cr[i, t], name='Breaks_1_lb[%s,%s]' % (i, t)) for i in data.I: for t in data.T: m.addCons(cr[i, t] <= data.WP[i], name='Breaks_1_ub[%s,%s]' % (i, t)) for i in data.I: for t in data.T: m.addCons(r[i, t] <= sum([ er[i, t1] for t1 in data.T_int.get_names(p_min=t, p_max=t + data.RP[i] - 1) ]), name='Breaks_2[%s,%s]' % (i, t)) for i in data.I: for t in data.T: m.addCons( sum([ r[i, t1] for t1 in data.T_int.get_names(p_min=t - data.RP[i] + 1, p_max=t) ]) >= data.RP[i] * er[i, t] if t >= data.min_t - 1 + data.RP[i] else data.CRP[i] * s[i, data.min_t] + sum([r[i, t1] for t1 in data.T_int.get_names(p_max=t)]) >= data.RP[i] * er[i, t], name='Breaks_3[%s,%s]' % (i, t)) for i in data.I: for t in data.T: m.addCons(sum([ r[i, t1] + tr[i, t1] for t1 in data.T_int.get_names(p_min=t - data.TRP[i], p_max=t + data.TRP[i]) ]) >= len( data.T_int.get_names(p_min=t - data.TRP[i], p_max=t + data.TRP[i])) * r[i, t], name='Breaks_4[%s,%s]' % (i, t)) # Maximum Number of Usage Periods in a Day # ---------------------------------------- for i in data.I: m.addCons(sum([u[i, t] for t in data.T]) <= data.UP[i] - data.CUP[i], name='max_usage_periods[%s]' % i) # Non-Negligence of Fronts # ------------------------ for g in data.G: for t in data.T: m.addCons(sum([w[i, t] for i in data.Ig[g]]) >= data.nMin[g, t] * y[t - 1] - mu[g, t], name='non-negligence_1[%s,%s]' % (g, t)) for g in data.G: for t in data.T: m.addCons(sum([w[i, t] for i in data.Ig[g]]) <= data.nMax[g, t] * y[t - 1], name='non-negligence_2[%s,%s]' % (g, t)) # Logical constraints # ------------------------ for i in data.I: m.addCons(sum([t * e[i, t] for t in data.T]) >= sum([t * s[i, t] for t in data.T]), name='logical_1[%s]' % i) for i in data.I: m.addCons(sum([e[i, t] for t in data.T]) <= 1, name='logical_2[%s]' % i) for i in data.I: for t in data.T: m.addCons(r[i, t] + tr[i, t] <= u[i, t], name='logical_3[%s,%s]' % (i, t)) for i in data.I: m.addCons(sum([w[i, t] for t in data.T]) >= z[i], name='logical_4[%s]' % i) return solution.Solution( m, dict(s=s, tr=tr, r=r, er=er, e=e, u=u, w=w, z=z, cr=cr, y=y, mu=mu))