Пример #1
0
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
Пример #2
0
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())
Пример #3
0
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())
Пример #4
0
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
Пример #5
0
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