mirror of
https://github.com/ANL-CEEESA/MIPLearn.git
synced 2025-12-06 09:28:51 -06:00
Document LearningSolver.solve; add solver_log to solved instances
This commit is contained in:
@@ -31,9 +31,6 @@ def _parallel_solve(instance_idx):
|
|||||||
"Results": results,
|
"Results": results,
|
||||||
"Solution": instance.solution,
|
"Solution": instance.solution,
|
||||||
"LP solution": instance.lp_solution,
|
"LP solution": instance.lp_solution,
|
||||||
"LP value": instance.lp_value,
|
|
||||||
"Upper bound": instance.upper_bound,
|
|
||||||
"Lower bound": instance.lower_bound,
|
|
||||||
"Violations": instance.found_violations,
|
"Violations": instance.found_violations,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,6 +94,45 @@ class LearningSolver:
|
|||||||
model=None,
|
model=None,
|
||||||
tee=False,
|
tee=False,
|
||||||
relaxation_only=False):
|
relaxation_only=False):
|
||||||
|
"""
|
||||||
|
Solves the given instance. If trained machine-learning models are
|
||||||
|
available, they will be used to accelerate the solution process.
|
||||||
|
|
||||||
|
This method modifies the instance object. Specifically, the following
|
||||||
|
properties are set:
|
||||||
|
- instance.lp_solution
|
||||||
|
- instance.lp_value
|
||||||
|
- instance.lower_bound
|
||||||
|
- instance.upper_bound
|
||||||
|
- instance.solution
|
||||||
|
- instance.found_violations
|
||||||
|
- instance.solver_log
|
||||||
|
Additional solver components may set additional properties. Please
|
||||||
|
see their documentation for more details.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
instance: miplearn.Instance
|
||||||
|
The instance to be solved
|
||||||
|
model: pyomo.core.ConcreteModel
|
||||||
|
The corresponding Pyomo model. If not provided, it will be created.
|
||||||
|
tee: bool
|
||||||
|
If true, prints solver log to screen.
|
||||||
|
relaxation_only: bool
|
||||||
|
If true, solve only the root LP relaxation.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
dict
|
||||||
|
A dictionary of solver statistics containing at least the following
|
||||||
|
keys: "Lower bound", "Upper bound", "Wallclock time", "Nodes",
|
||||||
|
"Sense", "Log", "Warm start value" and "LP value".
|
||||||
|
|
||||||
|
Additional components may generate additional keys. For example,
|
||||||
|
ObjectiveValueComponent adds the keys "Predicted LB" and
|
||||||
|
"Predicted UB". See the documentation of each component for more
|
||||||
|
details.
|
||||||
|
"""
|
||||||
|
|
||||||
if model is None:
|
if model is None:
|
||||||
model = instance.to_model()
|
model = instance.to_model()
|
||||||
@@ -118,10 +154,12 @@ class LearningSolver:
|
|||||||
return results
|
return results
|
||||||
|
|
||||||
results = self.internal_solver.solve(tee=tee)
|
results = self.internal_solver.solve(tee=tee)
|
||||||
|
results["LP value"] = instance.lp_value
|
||||||
|
|
||||||
# Read MIP solution and bounds
|
# Read MIP solution and bounds
|
||||||
instance.lower_bound = results["Lower bound"]
|
instance.lower_bound = results["Lower bound"]
|
||||||
instance.upper_bound = results["Upper bound"]
|
instance.upper_bound = results["Upper bound"]
|
||||||
|
instance.solver_log = results["Log"]
|
||||||
instance.solution = self.internal_solver.get_solution()
|
instance.solution = self.internal_solver.get_solution()
|
||||||
|
|
||||||
logger.debug("Calling after_solve callbacks...")
|
logger.debug("Calling after_solve callbacks...")
|
||||||
@@ -147,10 +185,11 @@ class LearningSolver:
|
|||||||
for (idx, r) in enumerate(p_map_results):
|
for (idx, r) in enumerate(p_map_results):
|
||||||
instances[idx].solution = r["Solution"]
|
instances[idx].solution = r["Solution"]
|
||||||
instances[idx].lp_solution = r["LP solution"]
|
instances[idx].lp_solution = r["LP solution"]
|
||||||
instances[idx].lp_value = r["LP value"]
|
instances[idx].lp_value = r["Results"]["LP value"]
|
||||||
instances[idx].lower_bound = r["Lower bound"]
|
instances[idx].lower_bound = r["Results"]["Lower bound"]
|
||||||
instances[idx].upper_bound = r["Upper bound"]
|
instances[idx].upper_bound = r["Results"]["Upper bound"]
|
||||||
instances[idx].found_violations = r["Violations"]
|
instances[idx].found_violations = r["Violations"]
|
||||||
|
instances[idx].solver_log = r["Results"]["Log"]
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|||||||
@@ -29,12 +29,13 @@ def test_learning_solver():
|
|||||||
assert instance.solution["x"][3] == 1.0
|
assert instance.solution["x"][3] == 1.0
|
||||||
assert instance.lower_bound == 1183.0
|
assert instance.lower_bound == 1183.0
|
||||||
assert instance.upper_bound == 1183.0
|
assert instance.upper_bound == 1183.0
|
||||||
|
|
||||||
assert round(instance.lp_solution["x"][0], 3) == 1.000
|
assert round(instance.lp_solution["x"][0], 3) == 1.000
|
||||||
assert round(instance.lp_solution["x"][1], 3) == 0.923
|
assert round(instance.lp_solution["x"][1], 3) == 0.923
|
||||||
assert round(instance.lp_solution["x"][2], 3) == 1.000
|
assert round(instance.lp_solution["x"][2], 3) == 1.000
|
||||||
assert round(instance.lp_solution["x"][3], 3) == 0.000
|
assert round(instance.lp_solution["x"][3], 3) == 0.000
|
||||||
assert round(instance.lp_value, 3) == 1287.923
|
assert round(instance.lp_value, 3) == 1287.923
|
||||||
|
assert instance.found_violations == []
|
||||||
|
assert len(instance.solver_log) > 100
|
||||||
|
|
||||||
solver.fit([instance])
|
solver.fit([instance])
|
||||||
solver.solve(instance)
|
solver.solve(instance)
|
||||||
|
|||||||
Reference in New Issue
Block a user