Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions pyomo/contrib/solver/common/results.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,14 +197,6 @@ def __init__(
description="A tuple representing the version of the solver in use.",
),
)
self.iteration_count: Optional[int] = self.declare(
'iteration_count',
ConfigValue(
domain=NonNegativeInt,
default=None,
description="The total number of iterations.",
),
)
self.timing_info: ConfigDict = self.declare(
'timing_info', ConfigDict(implicit=True)
)
Expand Down
2 changes: 1 addition & 1 deletion pyomo/contrib/solver/solvers/gurobi_direct.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ def _postsolve(self, timer: HierarchicalTimer, config, loader):
results.incumbent_objective = None
results.objective_bound = None

results.iteration_count = grb_model.getAttr('IterCount')
results.extra_info.iteration_count = grb_model.getAttr('IterCount')

timer.start('load solution')
if config.load_solutions:
Expand Down
2 changes: 1 addition & 1 deletion pyomo/contrib/solver/solvers/gurobi_persistent.py
Original file line number Diff line number Diff line change
Expand Up @@ -857,7 +857,7 @@ def _postsolve(self, timer: HierarchicalTimer):
):
results.incumbent_objective = None

results.iteration_count = gprob.getAttr('IterCount')
results.extra_info.iteration_count = gprob.getAttr('IterCount')

timer.start('load solution')
if config.load_solutions:
Expand Down
10 changes: 9 additions & 1 deletion pyomo/contrib/solver/solvers/highs.py
Original file line number Diff line number Diff line change
Expand Up @@ -750,7 +750,15 @@ def _postsolve(self, stream: io.StringIO):
results.objective_bound = None
else:
results.objective_bound = info.mip_dual_bound
results.iteration_count = info.simplex_iteration_count

if info.valid:
results.extra_info.iteration_counts = {
'simplex_iteration_count': info.simplex_iteration_count,
'ipm_iteration_count': info.ipm_iteration_count,
'mip_node_count': info.mip_node_count,
'pdlp_iteration_count': info.pdlp_iteration_count,
'qp_iteration_count': info.qp_iteration_count,
}

if config.load_solutions:
if has_feasible_solution:
Expand Down
8 changes: 5 additions & 3 deletions pyomo/contrib/solver/solvers/ipopt.py
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ def solve(self, model, **kwds) -> Results:
results = Results()
results.termination_condition = TerminationCondition.provenInfeasible
results.solution_loader = SolSolutionLoader(None, None)
results.iteration_count = 0
results.extra_info.iteration_count = 0
results.timing_info.total_seconds = 0
elif len(nl_info.variables) == 0:
if len(nl_info.eliminated_vars) == 0:
Expand All @@ -487,7 +487,7 @@ def solve(self, model, **kwds) -> Results:
)
results.solution_status = SolutionStatus.optimal
results.solution_loader = SolSolutionLoader(None, nl_info=nl_info)
results.iteration_count = 0
results.extra_info.iteration_count = 0
results.timing_info.total_seconds = 0
else:
if os.path.isfile(basename + '.sol'):
Expand All @@ -503,7 +503,9 @@ def solve(self, model, **kwds) -> Results:
results.solution_loader = SolSolutionLoader(None, None)
else:
try:
results.iteration_count = parsed_output_data.pop('iters')
results.extra_info.iteration_count = parsed_output_data.pop(
'iters'
)
cpu_seconds = parsed_output_data.pop('cpu_seconds')
for k, v in cpu_seconds.items():
results.timing_info[k] = v
Expand Down
2 changes: 1 addition & 1 deletion pyomo/contrib/solver/solvers/knitro/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ def _postsolve(self, config: KnitroConfig, timer: HierarchicalTimer) -> Results:
results.solution_status = self._get_solution_status(status)
results.termination_condition = self._get_termination_condition(status)
results.incumbent_objective = self._engine.get_obj_value()
results.iteration_count = self._engine.get_num_iters()
results.extra_info.iteration_count = self._engine.get_num_iters()
results.timing_info.solve_time = self._engine.get_solve_time()
results.timing_info.timer = timer

Expand Down
10 changes: 5 additions & 5 deletions pyomo/contrib/solver/tests/solvers/test_ipopt.py
Original file line number Diff line number Diff line change
Expand Up @@ -594,13 +594,13 @@ def test_ipopt_quiet_print_level(self):
result = ipopt.Ipopt().solve(model, solver_options={'print_level': 0})
# IPOPT doesn't tell us anything about the iters if the print level
# is set to 0
self.assertIsNone(result.iteration_count)
self.assertFalse(hasattr(result.extra_info, 'iteration_count'))
self.assertFalse(hasattr(result.extra_info, 'iteration_log'))
model = self.create_model()
result = ipopt.Ipopt().solve(model, solver_options={'print_level': 3})
# At a slightly higher level, we get some of the info, like
# iteration count, but NOT iteration_log
self.assertEqual(result.iteration_count, 11)
self.assertEqual(result.extra_info.iteration_count, 11)
self.assertFalse(hasattr(result.extra_info, 'iteration_log'))

def test_ipopt_loud_print_level(self):
Expand All @@ -609,13 +609,13 @@ def test_ipopt_loud_print_level(self):
result = ipopt.Ipopt().solve(model, solver_options={'print_level': 8})
# Nothing unexpected should be in the results object at this point,
# except that the solver_log is significantly longer
self.assertEqual(result.iteration_count, 11)
self.assertEqual(result.extra_info.iteration_count, 11)
self.assertEqual(result.incumbent_objective, 7.013645951336496e-25)
self.assertIn('Optimal Solution Found', result.extra_info.solver_message)
self.assertTrue(hasattr(result.extra_info, 'iteration_log'))
model = self.create_model()
result = ipopt.Ipopt().solve(model, solver_options={'print_level': 12})
self.assertEqual(result.iteration_count, 11)
self.assertEqual(result.extra_info.iteration_count, 11)
self.assertEqual(result.incumbent_objective, 7.013645951336496e-25)
self.assertIn('Optimal Solution Found', result.extra_info.solver_message)
self.assertTrue(hasattr(result.extra_info, 'iteration_log'))
Expand All @@ -624,7 +624,7 @@ def test_ipopt_results(self):
model = self.create_model()
results = ipopt.Ipopt().solve(model)
self.assertEqual(results.solver_name, 'ipopt')
self.assertEqual(results.iteration_count, 11)
self.assertEqual(results.extra_info.iteration_count, 11)
self.assertEqual(results.incumbent_objective, 7.013645951336496e-25)
self.assertIn('Optimal Solution Found', results.extra_info.solver_message)

Expand Down
3 changes: 0 additions & 3 deletions pyomo/contrib/solver/tests/solvers/test_solvers.py
Original file line number Diff line number Diff line change
Expand Up @@ -604,9 +604,6 @@ def test_results_object_populated(
for v in res.solver_version:
self.assertIsInstance(v, int)

# iteration_count is nonnegative
self.assertGreaterEqual(res.iteration_count, 0)

# timing_info should exist
self.assertIsNotNone(res.timing_info)

Expand Down
3 changes: 0 additions & 3 deletions pyomo/contrib/solver/tests/unit/test_results.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ def test_member_list(self):
expected_declared = {
'extra_info',
'incumbent_objective',
'iteration_count',
'objective_bound',
'solution_loader',
'solution_status',
Expand All @@ -182,7 +181,6 @@ def test_default_initialization(self):
self.assertEqual(res.solution_status, results.SolutionStatus.noSolution)
self.assertIsNone(res.solver_name)
self.assertIsNone(res.solver_version)
self.assertIsNone(res.iteration_count)
self.assertIsInstance(res.timing_info, ConfigDict)
self.assertIsInstance(res.extra_info, ConfigDict)
self.assertIsNone(res.timing_info.start_timestamp)
Expand All @@ -198,7 +196,6 @@ def test_display(self):
objective_bound: None
solver_name: None
solver_version: None
iteration_count: None
timing_info:
start_timestamp: None
wall_time: None
Expand Down
Loading