def solve(dat): """ core solving routine :param dat: a good ticdat for the input_schema :return: a good ticdat for the solution_schema, or None """ assert input_schema.good_tic_dat_object(dat) assert not input_schema.find_foreign_key_failures(dat) assert not input_schema.find_data_type_failures(dat) mdl = Model(_model_type, "netflow") flow = {(h, i, j): mdl.add_var(name='flow_%s_%s_%s' % (h, i, j)) for h, i, j in dat.cost if (i, j) in dat.arcs} flowslice = Slicer(flow) # Arc Capacity constraints for i_, j_ in dat.arcs: mdl.add_constraint(mdl.sum(flow[h, i, j] for h, i, j in flowslice.slice('*', i_, j_)) <= dat.arcs[i_, j_]["Capacity"], name='cap_%s_%s' % (i_, j_)) # Flow conservation constraints. Constraints are generated only for relevant pairs. # So we generate a conservation of flow constraint if there is negative or positive inflow # quantity, or at least one inbound flow variable, or at least one outbound flow variable. for h,j in set(k for k,v in dat.inflow.items() if abs(v["Quantity"]) > 0)\ .union({(h,i) for h,i,j in flow}, {(h,j) for h,i,j in flow}): mdl.add_constraint( mdl.sum(flow[h_, i_, j_] for h_, i_, j_ in flowslice.slice(h, '*', j)) + dat.inflow.get((h, j), {"Quantity": 0})["Quantity"] == mdl.sum( flow[h_, j_, i_] for h_, j_, i_ in flowslice.slice(h, j, '*')), name='node_%s_%s' % (h, j)) mdl.set_objective( mdl.sum(flow * dat.cost[h, i, j]["Cost"] for (h, i, j), flow in flow.items())) # Compute optimal solution if mdl.optimize(): rtn = solution_schema.TicDat() for (h, i, j), var in flow.items(): if mdl.get_solution_value(var) > 0: rtn.flow[h, i, j] = mdl.get_solution_value(var) rtn.parameters["Total Cost"] = sum( dat.cost[h, i, j]["Cost"] * r["Quantity"] for (h, i, j), r in rtn.flow.items()) return rtn
def netflowSolver(modelType): tdf = TicDatFactory(**netflowSchema()) addNetflowForeignKeys(tdf) addNetflowDataTypes(tdf) dat = tdf.copy_tic_dat(netflowData()) assert not tdf.find_data_type_failures( dat) and not tdf.find_foreign_key_failures(dat) mdl = Model(modelType, "netflow") flow = {} for h, i, j in dat.cost: if (i, j) in dat.arcs: flow[h, i, j] = mdl.add_var(name='flow_%s_%s_%s' % (h, i, j)) flowslice = Slicer(flow) for i_, j_ in dat.arcs: mdl.add_constraint(mdl.sum(flow[h, i, j] for h, i, j in flowslice.slice('*', i_, j_)) <= dat.arcs[i_, j_]["capacity"], name='cap_%s_%s' % (i_, j_)) for h_, j_ in set(k for k, v in dat.inflow.items() if abs(v["quantity"]) > 0).union( {(h, i) for h, i, j in flow}, {(h, j) for h, i, j in flow}): mdl.add_constraint( mdl.sum(flow[h, i, j] for h, i, j in flowslice.slice(h_, '*', j_)) + dat.inflow.get((h_, j_), {"quantity": 0})["quantity"] == mdl.sum( flow[h, i, j] for h, i, j in flowslice.slice(h_, j_, '*')), name='node_%s_%s' % (h_, j_)) mdl.set_objective( mdl.sum(flow * dat.cost[h, i, j]["cost"] for (h, i, j), flow in flow.items())) if mdl.optimize(): solutionFactory = TicDatFactory( flow=[["commodity", "source", "destination"], ["quantity"]]) if mdl.optimize(): rtn = solutionFactory.TicDat() for (h, i, j), var in flow.items(): if mdl.get_solution_value(var) > 0: rtn.flow[h, i, j] = mdl.get_solution_value(var) return rtn, sum(dat.cost[h, i, j]["cost"] * r["quantity"] for (h, i, j), r in rtn.flow.items())
def dietSolver(modelType): tdf = TicDatFactory(**dietSchema()) addDietForeignKeys(tdf) addDietDataTypes(tdf) dat = tdf.copy_tic_dat(dietData()) assert not tdf.find_data_type_failures( dat) and not tdf.find_foreign_key_failures(dat) mdl = Model(modelType, "diet") nutrition = {} for c, n in dat.categories.items(): nutrition[c] = mdl.add_var(lb=n["minNutrition"], ub=n["maxNutrition"], name=c) # Create decision variables for the foods to buy buy = {} for f in dat.foods: buy[f] = mdl.add_var(name=f) # Nutrition constraints for c in dat.categories: mdl.add_constraint(mdl.sum(dat.nutritionQuantities[f, c]["qty"] * buy[f] for f in dat.foods) == nutrition[c], name=c) mdl.set_objective(mdl.sum(buy[f] * c["cost"] for f, c in dat.foods.items())) if mdl.optimize(): solutionFactory = TicDatFactory(parameters=[[], ["totalCost"]], buyFood=[["food"], ["qty"]], consumeNutrition=[["category"], ["qty"]]) sln = solutionFactory.TicDat() for f, x in buy.items(): if mdl.get_solution_value(x) > 0.0001: sln.buyFood[f] = mdl.get_solution_value(x) for c, x in nutrition.items(): sln.consumeNutrition[c] = mdl.get_solution_value(x) return sln, sum(dat.foods[f]["cost"] * r["qty"] for f, r in sln.buyFood.items())
def solve(dat): """ core solving routine :param dat: a good ticdat for the input_schema :return: a good ticdat for the solution_schema, or None """ assert input_schema.good_tic_dat_object(dat) assert not input_schema.find_foreign_key_failures(dat) assert not input_schema.find_data_type_failures(dat) assert not input_schema.find_data_row_failures(dat) mdl = Model(_model_type, "diet") nutrition = { c: mdl.add_var(lb=n["Min Nutrition"], ub=n["Max Nutrition"], name=c) for c, n in dat.categories.items() } # Create decision variables for the foods to buy buy = {f: mdl.add_var(name=f) for f in dat.foods} # Nutrition constraints for c in dat.categories: mdl.add_constraint(mdl.sum(dat.nutrition_quantities[f, c]["Quantity"] * buy[f] for f in dat.foods) == nutrition[c], name=c) mdl.set_objective(mdl.sum(buy[f] * c["Cost"] for f, c in dat.foods.items())) if mdl.optimize(): sln = solution_schema.TicDat() for f, x in buy.items(): if mdl.get_solution_value(x) > 0: sln.buy_food[f] = mdl.get_solution_value(x) for c, x in nutrition.items(): sln.consume_nutrition[c] = mdl.get_solution_value(x) sln.parameters['Total Cost'] = sum(dat.foods[f]["Cost"] * r["Quantity"] for f, r in sln.buy_food.items()) return sln
def solve(dat, progress): assert isinstance(progress, Progress) assert input_schema.good_tic_dat_object(dat) assert not input_schema.find_foreign_key_failures(dat) assert not input_schema.find_data_type_failures(dat) full_parameters = input_schema.create_full_parameters_dict(dat) def get_distance(x, y): if (x, y) in dat.distance: return dat.distance[x, y]["Distance"] if (y, x) in dat.distance: return dat.distance[y, x]["Distance"] return float("inf") def can_assign(x, y): return dat.sites[y]["Center Status"] == "Can Be Center" \ and get_distance(x,y)<float("inf") m = Model(model_name="cog", model_type=full_parameters["Core Model Type"]) assign_vars = {(n, assigned_to): m.add_var(type="binary", name="%s_%s" % (n, assigned_to)) for n in dat.sites for assigned_to in dat.sites if can_assign(n, assigned_to)} open_vars = { n: m.add_var(type="binary", name="open_%s" % n) for n in dat.sites if dat.sites[n]["Center Status"] == "Can Be Center" } assert open_vars, "nothing can be center" assign_slicer = Slicer(assign_vars) for n, r in dat.sites.items(): if r["Demand"] > 0: m.add_constraint(m.sum( assign_vars[n, assign_to] for _, assign_to in assign_slicer.slice(n, "*")) == 1, name="must_assign_%s" % n) for assigned_to, r in dat.sites.items(): if r["Center Status"] == "Can Be Center": _assign_vars = [ assign_vars[n, assigned_to] for n, _ in assign_slicer.slice("*", assigned_to) ] # this is the weak formulation m.add_constraint(m.sum(_assign_vars) <= len(_assign_vars) * open_vars[assigned_to], name="weak_force_open%s" % assigned_to) number_of_centroids = full_parameters["Number of Centroids"] m.add_constraint(m.sum(v for v in open_vars.values()) == number_of_centroids, name="numCentroids") m.set_parameters(MIP_Gap=full_parameters["MIP Gap"]) m.set_objective(m.sum(var * get_distance(n, assigned_to) * dat.sites[n]["Demand"] for (n, assigned_to), var in assign_vars.items()), sense="minimize") if full_parameters["Core Model Type"] == "cplex": progress.add_cplex_listener("COG Optimization", m.core_model) worked = m.optimize(*( [progress.gurobi_call_back_factory("COG Optimization", m.core_model)] if full_parameters["Core Model Type"] == "gurobi" else [])) assert worked, "testing model set up only for success" sln = solution_schema.TicDat() if full_parameters["Core Model Type"] == "gurobi": sln.parameters["Lower Bound"] = getattr(m.core_model, "objBound", m.core_model.objVal) sln.parameters["Upper Bound"] = m.core_model.objVal else: lb = m.core_model.solve_details.best_bound sln.parameters["Lower Bound"] = worked.get_objective_value() if isnan( lb) else lb sln.parameters["Upper Bound"] = worked.get_objective_value() def almostone(x): return abs(x - 1) < 0.0001 for (n, assigned_to), var in assign_vars.items(): if almostone(m.get_solution_value(var)): sln.assignments[n, assigned_to] = {} for n, var in open_vars.items(): if almostone(m.get_solution_value(var)): sln.openings[n] = {} return sln