Pyomo / pyomo

An object-oriented algebraic modeling language in Python for structured optimization problems.
https://www.pyomo.org
Other
2.03k stars 519 forks source link

BUG: stopping the default log of appsi_highs #2845

Open ZedongPeng opened 1 year ago

ZedongPeng commented 1 year ago

Summary

I am using appsi_highs in MindtPy. However, there are two lines of default logs when calling appsi_highs. I think it is inherent from highs itself, not appsi_highs interface. How can we stop the default logs?

-----------------------------------------------------------------------------------------------
               Mixed-Integer Nonlinear Decomposition Toolbox in Pyomo (MindtPy)                
-----------------------------------------------------------------------------------------------
For more information, please visit 
https://pyomo.readthedocs.io/en/stable/contributed_packages/mindtpy.html
If you use this software, please cite the following:
Bernal, David E., et al. Mixed-integer nonlinear decomposition toolbox for Pyomo (MindtPy).
Computer Aided Chemical Engineering. Vol. 44. Elsevier, 2018. 895-900.

Original model has 7 constraints (3 nonlinear) and 0 disjunctions, with 7 variables, of which 3 are binary, 0 are integer, and 4 are continuous.
rNLP is the initial strategy being used.

 ===============================================================================================
 Iteration | Subproblem Type | Objective Value | Primal Bound |   Dual Bound |   Gap   | Time(s)

         -       Relaxed NLP           2.29517            inf        2.29517      nan%      0.03
Running HiGHS 1.5.3 [date: 2023-05-16, git hash: 594fa5a9d]
Copyright (c) 2023 HiGHS under MIT licence terms
         1              MILP                 5            inf              5      nan%      0.04
*        1         Fixed NLP           7.09273        7.09273              5    29.51%      0.08
Running HiGHS 1.5.3 [date: 2023-05-16, git hash: 594fa5a9d]
Copyright (c) 2023 HiGHS under MIT licence terms
         2              MILP                 6        7.09273              6    15.41%      0.09
*        2         Fixed NLP           6.00976        6.00976              6     0.16%      0.12
Running HiGHS 1.5.3 [date: 2023-05-16, git hash: 594fa5a9d]
Copyright (c) 2023 HiGHS under MIT licence terms
         3              MILP           6.00976        6.00976        6.00976    -0.00%      0.13
MindtPy exiting on bound convergence. Absolute gap: -1.8969108595001671e-07 <= absolute tolerance: 0.0001 

 ===============================================================================================
 Primal integral          :    0.0858 
 Dual integral            :    0.1382 
 Primal-dual gap integral :    0.2241 
.
----------------------------------------------------------------------
michaelbynum commented 1 year ago

@ZedongPeng, Can you pinpoint exactly when HiGHS outputs this? I don't think it is during run. Maybe when the HiGHS model is constructed?

ZedongPeng commented 1 year ago

Yes. HiGHS outputs this when HiGHS model is constructed, more exactly this line https://github.com/Pyomo/pyomo/blob/main/pyomo/contrib/appsi/solvers/highs.py#L354.

ZedongPeng commented 1 year ago

Any thoughts on this? @michaelbynum @mrmundt

ZedongPeng commented 1 year ago

Any suggestions to stop the default log? @michaelbynum

jsiirola commented 1 year ago

Can you try wrapping with capture_output() (either by wrapping the call to set_instance(), or by putting it into that method)?

I am thinking something like


 def set_instance(self, model):
     if self._last_results_object is not None:
         self._last_results_object.solution_loader.invalidate()
     if not self.available():
         c = self.__class__
         raise PyomoException(
             f'Solver {c.__module__}.{c.__qualname__} is not available '
             f'({self.available()}).'
         )
     self._reinit()
     self._model = model
     if self.use_extensions and cmodel_available:
         self._expr_types = cmodel.PyomoExprTypes()

-    self._solver_model = highspy.Highs()
-    self.add_block(model)
+    with capture_output(capture_output=True):
+        self._solver_model = highspy.Highs()
+        self.add_block(model)
     if self._objective is None:
         self.set_objective(None)
michaelbynum commented 1 year ago

I only think we should hide the output after it is displayed at least once.

jsiirola commented 1 year ago

I only think we should hide the output after it is displayed at least once.

Why would the APPSI interface be different from the Ipopt, Gurobi, Cplex, CBC interfaces? We don't display any output from any of them unless tee=True. Maybe the better implementation here would be to duplicate the logic from _solve() and check the tee value / redirect the output to the solver log.

tarskul commented 1 year ago

It would be nice if that problem could be resolved.

I would like to use the HiGHS solver but with this bug i'm reluctant to switch.

I used to have output like this:

time 0 sample 0
time 5 sample 1
time 7 sample 2
time 9 sample 3
time 11 sample 4
...

But with the HiGHS solver it becomes this:

time 0 sample 0
Running HiGHS 1.5.3 [date: 2023-05-16, git hash: 594fa5a9d]
Copyright (c) 2023 HiGHS under MIT licence terms
time 5 sample 1
Running HiGHS 1.5.3 [date: 2023-05-16, git hash: 594fa5a9d]
Copyright (c) 2023 HiGHS under MIT licence terms
time 7 sample 2
Running HiGHS 1.5.3 [date: 2023-05-16, git hash: 594fa5a9d]
Copyright (c) 2023 HiGHS under MIT licence terms
time 9 sample 3
Running HiGHS 1.5.3 [date: 2023-05-16, git hash: 594fa5a9d]
Copyright (c) 2023 HiGHS under MIT licence terms
time 11 sample 4
...

Which is obviously quite annoying.

I've tried to suppress the output in a number of ways (including stuff related to sys.stdout) but it seems to be quite presistent.