Ejemplo n.º 1
0
    def test_diet_amplpy(self):
        dat = _diet_input_tdf.copy_to_ampl(
            _diet_dat,
            field_renamings={
                ("foods", "Cost"): "cost",
                ("categories", "Min Nutrition"): "n_min",
                ("categories", "Max Nutrition"): "n_max",
                ("nutrition_quantities", "Quantity"): "amt",
                ("nutrition_quantities", "Other Quantity"): "other_amt"
            })
        self.assertTrue({"n_min",
                         "n_max"}.issubset(dat.categories.toPandas().columns))
        ampl = amplpy.AMPL()
        ampl.setOption('solver', 'gurobi')
        ampl.eval(_diet_mod)
        _diet_input_tdf.set_ampl_data(dat, ampl, {
            "categories": "CAT",
            "foods": "FOOD"
        })
        ampl.solve()

        sln = _diet_sln_tdf.copy_from_ampl_variables({
            ("buy_food", "Quantity"):
            ampl.getVariable("Buy"),
            ("consume_nutrition", "Quantity"):
            ampl.getVariable("Consume")
        })
        sln.parameters['Total Cost'] = ampl.getObjective('Total_Cost').value()

        diet_dat_two = _diet_input_tdf.copy_tic_dat(_diet_dat)
        for r in diet_dat_two.nutrition_quantities.values():
            r["Quantity"], r["Other Quantity"] = [0.5 * r["Quantity"]] * 2

        dat = _diet_input_tdf.copy_to_ampl(
            diet_dat_two,
            field_renamings={
                ("foods", "Cost"): "cost",
                ("categories", "Min Nutrition"): "n_min",
                ("categories", "Max Nutrition"): "n_max",
                ("nutrition_quantities", "Quantity"): "amt",
                ("nutrition_quantities", "Other Quantity"): "other_amt"
            })
        ampl = amplpy.AMPL()
        ampl.setOption('solver', 'gurobi')
        ampl.eval(_diet_mod)
        _diet_input_tdf.set_ampl_data(dat, ampl, {
            "categories": "CAT",
            "foods": "FOOD"
        })
        ampl.solve()
        self.assertTrue("solved" == ampl.getValue("solve_result"))

        sln = _diet_sln_tdf.copy_from_ampl_variables({
            ("buy_food", "Quantity"):
            ampl.getVariable("Buy"),
            ("consume_nutrition", "Quantity"):
            ampl.getVariable("Consume")
        })
        sln.parameters['Total Cost'] = ampl.getObjective('Total_Cost').value()

        self.assertTrue(_nearly_same_dat(_diet_sln_tdf, sln, _diet_sln_ticdat))

        dat = _diet_input_tdf.copy_to_ampl(
            _diet_dat, {
                ("foods", "Cost"): "cost",
                ("categories", "Min Nutrition"): "",
                ("categories", "Max Nutrition"): "n_max"
            }, ["nutrition_quantities"])
        self.assertFalse(hasattr(dat, "nutrition_quantities"))
        self.assertTrue({"n_min", "n_max"}.intersection(
            dat.categories.toPandas().columns) == {"n_max"})

        sln_tdf_2 = TicDatFactory(buy_food=[["Food"], ["Quantity"]],
                                  consume_nutrition=[["Category"], []])
        sln_tdf_2.set_default_value("buy_food", "Quantity", 1)
        sln_2 = sln_tdf_2.copy_from_ampl_variables({
            ("buy_food", False):
            ampl.getVariable("Buy"),
            ("consume_nutrition", False):
            (ampl.getVariable("Consume"), lambda x: x < 100)
        })
        self.assertTrue(
            set(sln_2.buy_food) == set(sln.buy_food)
            and all(v["Quantity"] == 1 for v in sln_2.buy_food.values()))
        self.assertTrue(sln_2.consume_nutrition
                        and set(sln_2.consume_nutrition) == {
                            k
                            for k, v in sln.consume_nutrition.items()
                            if v["Quantity"] < 100
                        })

        diet_dat_two = _diet_input_tdf.copy_tic_dat(_diet_dat)
        diet_dat_two.categories["calories"] = [0, 200]
        dat = _diet_input_tdf.copy_to_ampl(
            diet_dat_two,
            field_renamings={
                ("foods", "Cost"): "cost",
                ("categories", "Min Nutrition"): "n_min",
                ("categories", "Max Nutrition"): "n_max",
                ("nutrition_quantities", "Quantity"): "amt",
                ("nutrition_quantities", "Other Quantity"): "other_amt"
            })
        ampl = amplpy.AMPL()
        ampl.setOption('solver', 'gurobi')
        ampl.eval(_diet_mod)
        _diet_input_tdf.set_ampl_data(dat, ampl, {
            "categories": "CAT",
            "foods": "FOOD"
        })
        ampl.solve()
        self.assertTrue("infeasible" == ampl.getValue("solve_result"))

        diet_dat_two = _diet_input_tdf.copy_tic_dat(_diet_dat)
        for v in diet_dat_two.categories.values():
            v["Max Nutrition"] = float("inf")
        diet_dat_two.foods["hamburger"] = -1
        dat = _diet_input_tdf.copy_to_ampl(
            diet_dat_two,
            field_renamings={
                ("foods", "Cost"): "cost",
                ("categories", "Min Nutrition"): "n_min",
                ("categories", "Max Nutrition"): "n_max",
                ("nutrition_quantities", "Quantity"): "amt",
                ("nutrition_quantities", "Other Quantity"): "other_amt"
            })
        ampl = amplpy.AMPL()
        ampl.setOption('solver', 'gurobi')
        ampl.eval(_diet_mod)
        _diet_input_tdf.set_ampl_data(dat, ampl, {
            "categories": "CAT",
            "foods": "FOOD"
        })
        ampl.solve()
        self.assertTrue("unbounded" == ampl.getValue("solve_result"))
Ejemplo n.º 2
0
def _metro_solve(dat,
                 sln_read_method="amplToDict",
                 excluded_tables=frozenset(
                     _metro_input_tdf.all_tables).difference({"load_amounts"
                                                              })):
    assert sln_read_method in ["amplToDict", "ticdat"]
    input_schema = _metro_input_tdf
    ampl_format = utils.ampl_format
    AMPL = amplpy.AMPL
    default_parameters = {
        "One Way Price": 2.25,
        "Amount Leftover Constraint": "Upper Bound"
    }
    assert input_schema.good_tic_dat_object(dat)
    full_parameters = dict(
        default_parameters,
        **{k: v["Value"]
           for k, v in dat.parameters.items()})

    sln = _metro_solution_tdf.TicDat()  # create an empty solution

    ampl_dat = input_schema.copy_to_ampl(dat, excluded_tables=excluded_tables)
    # solve a distinct MIP for each pair of (# of one-way-trips, amount leftover)
    for number_trips, amount_leftover in product(dat.number_of_one_way_trips,
                                                 dat.amount_leftover):

        ampl = AMPL()
        ampl.setOption('solver', 'gurobi')
        # use the ampl_format function for AMPL friendly key-named text substitutions
        ampl.eval(
            ampl_format("""
        set LOAD_AMTS;
        var Num_Visits {LOAD_AMTS} integer >= 0;
        var Amt_Leftover >= {{amount_leftover_lb}}, <= {{amount_leftover_ub}};
        minimize Total_Visits:
           sum {la in LOAD_AMTS} Num_Visits[la];
        subj to Set_Amt_Leftover:
           Amt_Leftover = sum {la in LOAD_AMTS} la * Num_Visits[la] - {{one_way_price}} * {{number_trips}};""",
                        number_trips=number_trips,
                        one_way_price=full_parameters["One Way Price"],
                        amount_leftover_lb=amount_leftover
                        if full_parameters["Amount Leftover Constraint"]
                        == "Equality" else 0,
                        amount_leftover_ub=amount_leftover))

        input_schema.set_ampl_data(ampl_dat, ampl,
                                   {"load_amounts": "LOAD_AMTS"})
        ampl.solve()

        if ampl.getValue("solve_result") != "infeasible":
            # store the results if and only if the model is feasible
            if sln_read_method == "ticdat":
                temp_tdf = TicDatFactory(
                    num_visits=[["Load Amount"], ["Number Of Visits"]])
                temp_sln = temp_tdf.copy_from_ampl_variables({
                    ("num_visits", "Number Of Visits"):
                    (ampl.getVariable("Num_Visits"), lambda _: round(_) > 0)
                })
                for la, r in temp_sln.num_visits.items():
                    x = round(r["Number Of Visits"])
                    sln.load_amount_details[number_trips, amount_leftover,
                                            la] = round(x)
                    sln.load_amount_summary[
                        number_trips, amount_leftover]["Number Of Visits"] += x
            else:
                for la, x in ampl.getVariable(
                        "Num_Visits").getValues().toDict().items():
                    if round(x) > 0:
                        sln.load_amount_details[number_trips, amount_leftover,
                                                la] = round(x)
                        sln.load_amount_summary[number_trips, amount_leftover]["Number Of Visits"]\
                           += round(x)
    return sln