Exemple #1
0
    def is_empty_intersection(self, uncertain_params, nlp_solver):
        """
        Determine if intersection is empty

        Args:
            uncertain_params: list of uncertain parameters
            nlp_solver: a Pyomo Solver object for solving NLPs
        """

        # === Non-emptiness check for the set intersection
        is_empty_intersection = True
        if any(a_set.type == "discrete" for a_set in self.all_sets):
            disc_sets = (a_set for a_set in self.all_sets if a_set.type == "discrete")
            disc_set = min(disc_sets, key=lambda x: len(x.scenarios))  # minimum set of scenarios
            # === Ensure there is at least one scenario from this discrete set which is a member of all other sets
            for scenario in disc_set.scenarios:
                if all(a_set.point_in_set(point=scenario) for a_set in self.all_sets):
                    is_empty_intersection = False
                    break
        else:
            # === Compile constraints and solve NLP
            m = ConcreteModel()
            m.obj = Objective(expr=0) # dummy objective required if using baron
            m.param_vars = Var(uncertain_params.index_set())
            for a_set in self.all_sets:
                m.add_component(a_set.type + "_constraints", a_set.set_as_constraint(uncertain_params=m.param_vars))
            try:
                res = nlp_solver.solve(m)
            except:
                raise ValueError("Solver terminated with an error while checking set intersection non-emptiness.")
            if check_optimal_termination(res):
                is_empty_intersection = False
        return is_empty_intersection
Exemple #2
0
def solve_master_feasibility_problem(model_data, config):
    """
    Solve a slack variable based feasibility model for the master problem
    """
    model = construct_master_feasibility_problem(model_data, config)

    if config.solve_master_globally:
        solver = config.global_solver
    else:
        solver = config.local_solver

    if not solver.available():
        raise RuntimeError("NLP solver %s is not available." % config.solver)

    results = solver.solve(model, tee=config.tee, load_solutions=False)

    if check_optimal_termination(results):
        model.solutions.load_from(results)

        # load solution to master model
        for v in model.component_data_objects(Var):
            master_v = model_data.master_model.find_component(v)
            if master_v is not None:
                master_v.set_value(v.value, skip_validation=True)
    else:
        results.solver.termination_condition = tc.error
        results.solver.message = ("Cannot load a SolverResults object with "
                                  "bad status: error")
    return results
Exemple #3
0
def solve_master_feasibility_problem(model_data, config):
    """
    Solve a slack variable based feasibility model for the master problem
    """
    model = model_data.master_model.clone()
    for o in model.component_data_objects(Objective):
        o.deactivate()
    TransformationFactory("core.add_slack_variables").apply_to(model)
    solver = config.global_solver

    if not solver.available():
        raise RuntimeError("NLP solver %s is not available." % config.solver)
    try:
        results = solver.solve(model, tee=config.tee)
    except ValueError as err:
        if 'Cannot load a SolverResults object with bad status: error' in str(
                err):
            results.solver.termination_condition = tc.error
            results.solver.message = str(err)
        else:
            raise

    if check_optimal_termination(results) and value(
            model._core_add_slack_variables._slack_objective) <= 0:
        # If this led to a feasible solution, continue with this model
        # Load solution into master
        for v in model.component_data_objects(Var):
            master_v = model_data.master_model.find_component(v)
            if master_v is not None:
                master_v.set_value(v.value, skip_validation=True)
    return results
Exemple #4
0
    def is_bounded(self, config):
        """
        Return True if the uncertainty set is bounded, else False.
        """
        # === Determine bounds on all uncertain params
        bounding_model = ConcreteModel()
        bounding_model.util = Block() # So that boundedness checks work for Cardinality and FactorModel sets
        bounding_model.uncertain_param_vars = IndexedVar(range(len(config.uncertain_params)), initialize=1)
        for idx, param in enumerate(config.uncertain_params):
            bounding_model.uncertain_param_vars[idx].value = param.value

        bounding_model.add_component("uncertainty_set_constraint",
                                     config.uncertainty_set.set_as_constraint(
                                         uncertain_params=bounding_model.uncertain_param_vars,
                                         model=bounding_model,
                                         config=config
                                     ))

        for idx, param in enumerate(list(bounding_model.uncertain_param_vars.values())):
            bounding_model.add_component("lb_obj_" + str(idx), Objective(expr=param, sense=minimize))
            bounding_model.add_component("ub_obj_" + str(idx), Objective(expr=param, sense=maximize))

        for o in bounding_model.component_data_objects(Objective):
            o.deactivate()

        for i in range(len(bounding_model.uncertain_param_vars)):
            for limit in ("lb", "ub"):
                getattr(bounding_model, limit + "_obj_" + str(i)).activate()
                res = config.global_solver.solve(bounding_model, tee=False)
                getattr(bounding_model, limit + "_obj_" + str(i)).deactivate()
                if not check_optimal_termination(res):
                    return False
        return True
Exemple #5
0
def generate_report(model: CVRPModel, result: SolverResults):

    # noinspection PyUnresolvedReferences
    def place_rows(ctx):
        depot = ctx.get("network").depot
        demand_sum = 0

        for i, place in enumerate(ctx.get("network").all_places):
            h = "E" if place.longitude > 0 else "W"
            v = "N" if place.latitude > 0 else "S"

            demand_sum += place.demand

            yield tr(
                td(strong(place.name) if place is depot else place.name),
                td("-" if place is depot else place.demand),
                td(f"{abs(place.longitude):.2f} {h}, {abs(place.latitude):.2f} {v}")
            )

        yield tr(
            td(strong("SUMA")),
            td(f"{demand_sum:.2f}"),
            td("-")
        )

    # noinspection PyUnresolvedReferences
    def vehicle_rows(ctx):
        max_cap_sum = 0

        for i, vehicle in enumerate(ctx.get("network").vehicles):
            max_cap_sum += vehicle.max_capacity

            yield tr(
                td(vehicle.name),
                td(vehicle.max_capacity),
            )

        yield tr(
            td(strong("SUMA")),
            td(f"{max_cap_sum:.2f}")
        )

    # noinspection PyUnresolvedReferences
    def route_vehicles(ctx):
        network = ctx.get("network")
        routes = ctx.get("routes")

        for vehicle in network.vehicles:
            place_names = ["Wyjazd z magazynu"]
            vehicle_distance = 0

            for vehicle_route in routes[vehicle.slug_name]:
                place_from = network.get_place(vehicle_route[0])
                place_dest = network.get_place(vehicle_route[1])

                route_name = place_dest.name

                if place_dest is network.depot:
                    route_name = "Powrót do magazynu"

                distance = Place.distance(place_from, place_dest)
                vehicle_distance += distance

                place_names.append(f"{route_name} (+ {distance:.2f} km)")

            yield div(
                h2(f"{vehicle.name} ({vehicle_distance:.2f} km)"),
                ol(*[li(name) for name in place_names]),
            )

    body_sections = [
        section(
            h2("Dane wejściowe"),
            div(
                h3("Miejsca"),
                table(
                    thead(td("Nazwa"), td("Zapotrzebowanie"), td("Położenie geo.")),
                    tbody(place_rows)
                )
            ),
            div(
                h3("Pojazdy"),
                table(
                    thead(td("Nazwa"), td("Maks. pojemność")),
                    tbody(vehicle_rows)
                )
            ),
        )
    ]

    if check_optimal_termination(result):
        body_sections.append(
            section(
                h2("Wybrane trasy"),
                div(route_vehicles),
                p(strong("Całkowita przebyta odległość: "), span(f"{model.obj_total_cost():.2f} km"))
            )
        )

        body_sections.append(
            section(
                h2("Wizualizacja"),
                lambda ctx: img(src=generate_network_vis(ctx.get("network"), ctx.get("routes")))
            )
        )

    body_sections.append(
        section(
            h2("Solver"),
            div(table(tbody(
                tr(td(strong("Użyty solver:")), td(get_solvers()[0])),
                tr(td(strong("Czas rozwiązywania:")), td(result.solver.time)),
                tr(td(strong("Status:")), td(str(result.solver.status))),
                tr(td(strong("Stan zakończenia:")), td(str(result.solver.termination_condition))),
                tr(td(strong("Kod zwrotny:")), td(str(result.solver.return_code))),
                tr(td(strong("Wiadomość:")), td(str(result.solver.message))),
            ))),
            h2("Problem"),
            div(table(tbody(*[
                tr(td(p(strong(k + ":")), td(v.value)))
                for k, v in result.problem[0].items()
            ])))
        )
    )

    template = html(
        head(
            title("Problem marszrutyzacji - Raport"),
            style(
                "table, th, td { border: 1px solid black; border-collapse: collapse; }" +
                "section { margin-left: 2em; }"
            ),
        ),
        body(
            header(h1("Raport marszrutyzacji")),
            *body_sections,
            footer(hr, f"Wygenerowano: {datetime.now()}"),
        ),
    )

    return template.render(
        network=model.network,
        routes=model.vehicle_routes(),
        result=result
    )