@@ -334,7 +334,7 @@ def has_linear_solver(self, linear_solver: str) -> bool:
334334 def _verify_ipopt_options (self , config : IpoptConfig ) -> None :
335335 for key , msg in unallowed_ipopt_options .items ():
336336 if key in config .solver_options :
337- raise ValueError (f"unallowed ipopt option '{ key } ': { msg } " )
337+ raise ValueError (f"unallowed Ipopt option '{ key } ': { msg } " )
338338 # Map standard Pyomo solver options to Ipopt options: standard
339339 # options override ipopt-specific options.
340340 if config .time_limit is not None :
@@ -548,11 +548,7 @@ def solve(self, model, **kwds) -> Results:
548548 results .extra_info = parsed_output_data
549549 iter_log = results .extra_info .get ("iteration_log" , None )
550550 if iter_log is not None :
551- # Only set if object supports the attribute
552- try :
553- iter_log ._visibility = ADVANCED_OPTION
554- except Exception :
555- pass
551+ iter_log ._visibility = ADVANCED_OPTION
556552 except Exception as e :
557553 logger .log (
558554 logging .WARNING ,
@@ -659,28 +655,26 @@ def _parse_ipopt_output(self, output: Union[str, io.StringIO]) -> Dict[str, Any]
659655 tokens = line .strip ().split ()
660656 # IPOPT sometimes mashes the first two column values together
661657 # (e.g., "2r-4.93e-03"). We need to split them.
662- if tokens and (('-' in tokens [0 ][1 :]) or ('+' in tokens [0 ][1 :])):
663- m = re .match (
664- r'^(\d+r?)([+-](?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?)$' ,
665- tokens [0 ],
666- )
667- if m :
668- tokens = [m .group (1 ), m .group (2 )] + tokens [1 :]
658+ try :
659+ idx = tokens [0 ].index ('-' )
660+ tokens [:1 ] = (tokens [0 ][:idx ], tokens [0 ][idx :])
661+ except ValueError :
662+ # No '-' found, leave as-is
663+ pass
669664
670665 iter_data = dict (zip (columns , tokens ))
671666 extra_tokens = tokens [n_expected_columns :]
672667
673668 # Extract restoration flag from 'iter'
674- iter_str = iter_data .pop ("iter" )
675- restoration = iter_str .endswith ("r" )
669+ iter_num = iter_data .pop ("iter" )
670+ restoration = iter_num .endswith ("r" )
676671 if restoration :
677- iter_str = iter_str [:- 1 ]
678-
672+ iter_num = iter_num [:- 1 ]
679673 try :
680- iter_num = int (iter_str )
674+ iter_num = int (iter_num )
681675 except ValueError :
682- logger . error (
683- "Could not parse IPOPT iteration number from line: \n \t %s" , line
676+ raise ValueError (
677+ f "Could not parse Ipopt iteration number: { iter_num } "
684678 )
685679
686680 iter_data ["restoration" ] = restoration
@@ -704,10 +698,14 @@ def _parse_ipopt_output(self, output: Union[str, io.StringIO]) -> Dict[str, Any]
704698 )
705699
706700 # Attempt to cast all values to float where possible
707- for key in columns :
708- if key == 'iter' :
701+ for key , val in iter_data .items ():
702+ if key in {
703+ 'iter' ,
704+ 'restoration' ,
705+ 'step_acceptance' ,
706+ 'diagnostic_tags' ,
707+ }:
709708 continue
710- val = iter_data [key ]
711709 if val == '-' :
712710 iter_data [key ] = None
713711 else :
@@ -720,8 +718,8 @@ def _parse_ipopt_output(self, output: Union[str, io.StringIO]) -> Dict[str, Any]
720718 )
721719
722720 assert len (iterations ) == iter_num , (
723- f"Parsed row in the iterations table \n \t { line } \n "
724- f"does not match the next expected iteration number ({ len ( iterations ) } ) "
721+ f"Total number of iterations logged ( { iterations } ) does "
722+ f"not match the parsed number of iterations ({ iter_num } ). "
725723 )
726724 iterations .append (iter_data )
727725
0 commit comments