Exemplo n.º 1
0
 def _testParameters(self, modelType):
     mdl = Model(modelType, "parameters")
     mdl.set_parameters(MIP_Gap=0.01)
Exemplo n.º 2
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