From f339c4c8f27854532c9fc6422f83340b6fd1096f Mon Sep 17 00:00:00 2001 From: "David L. Woodruff" Date: Thu, 15 Aug 2024 11:20:47 -0700 Subject: [PATCH] try to add mpigap (untested) --- mpisppy/agnostic/ampl_guest.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/mpisppy/agnostic/ampl_guest.py b/mpisppy/agnostic/ampl_guest.py index 5f618b0f0..e340224db 100644 --- a/mpisppy/agnostic/ampl_guest.py +++ b/mpisppy/agnostic/ampl_guest.py @@ -66,13 +66,18 @@ def scenario_creator(self, scenario_name, **kwargs): scenario_name (str): Name of the scenario to construct. """ + def _has_ints(s): + for _,v in s.getVariables(): + if "binary" in str(v) or "integer" in str(v): + return True + return False + s, prob, nonant_vardata_list, obj_fct = self.model_module.scenario_creator(scenario_name, self.ampl_file_name, **kwargs) if len(nonant_vardata_list) == 0: raise RuntimeError(f"model file {self.model_file_name} has an empty " f" nonant_vardata_list for {scenario_name =}") - ### TBD: assert that this is minimization? # In general, be sure to process variables in the same order has the guest does (so indexes match) nonant_vars = nonant_vardata_list # typing aid def _vname(v): @@ -86,7 +91,8 @@ def _vname(v): "probability": prob, "obj_fct": obj_fct, "sense": pyo.minimize, - "BFs": None + "BFs": None, + "has_ints": _has_ints(s), } ##?xxxxx ? create nonant vars and put them on the ampl model, ##?xxxxx create constraints to make them equal to the original nonants @@ -183,6 +189,7 @@ def _vname(i): gs.eval("param xbars{nonant_indices};") obj_fct = gd["obj_fct"] objstr = str(obj_fct) + assert objstr.split (' ')[0] == "minimize", "We currently assume minimization" # Dual term (weights W) (This is where indexes are an issue) phobjstr = "" @@ -274,12 +281,14 @@ def solve_one(self, Ag, s, solve_keyword_args, gripe, tee=False): # For AMPL mips, we need to use the gap option to compute bounds # https://amplmp.readthedocs.io/rst/features-guide.html + # As of Aug 2024, this is not tested... + mipgap = gs.getValue('_mipgap') if gd["has_ints"] else 0 objobj = gs.get_current_objective() # different for xhatters objval = objobj.value() if gd["sense"] == pyo.minimize: - s._mpisppy_data.outer_bound = objval + s._mpisppy_data.outer_bound = objval - mipgap else: - s._mpisppy_data.inner_bound = objval + s._mpisppy_data.inner_bound = objval + mpigap # copy the nonant x values from gs to s so mpisppy can use them in s # in general, we need more checks (see the pyomo agnostic guest example)