Skip to content

Commit

Permalink
SAVE STATE: part 2 - ipopt interface cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
mrmundt committed Feb 21, 2024
1 parent 40ad333 commit a1c9aff
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 41 deletions.
92 changes: 51 additions & 41 deletions pyomo/contrib/solver/ipopt.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import subprocess
import datetime
import io
import sys
from typing import Mapping, Optional, Sequence

from pyomo.common import Executable
Expand Down Expand Up @@ -324,6 +323,54 @@ def _create_command_line(self, basename: str, config: IpoptConfig, opt_file: boo
cmd.append(str(k) + '=' + str(val))
return cmd

def _run_subprocess(
self,
basename: str,
timer: HierarchicalTimer,
ostreams: list,
config: IpoptConfig,
nl_info: NLWriterInfo,
):
# Get a copy of the environment to pass to the subprocess
env = os.environ.copy()
if nl_info.external_function_libraries:
if env.get('AMPLFUNC'):
nl_info.external_function_libraries.append(env.get('AMPLFUNC'))
env['AMPLFUNC'] = "\n".join(nl_info.external_function_libraries)
# Write the opt_file, if there should be one; return a bool to say
# whether or not we have one (so we can correctly build the command line)
opt_file = self._write_options_file(
filename=basename, options=config.solver_options
)
# Call ipopt - passing the files via the subprocess
cmd = self._create_command_line(
basename=basename, config=config, opt_file=opt_file
)
# this seems silly, but we have to give the subprocess slightly longer to finish than
# ipopt
if config.time_limit is not None:
timeout = config.time_limit + min(max(1.0, 0.01 * config.time_limit), 100)
else:
timeout = None

with TeeStream(*ostreams) as t:
timer.start('subprocess')
process = subprocess.run(
cmd,
timeout=timeout,
env=env,
universal_newlines=True,
stdout=t.STDOUT,
stderr=t.STDERR,
)
timer.stop('subprocess')
# This is the stuff we need to parse to get the iterations
# and time
iters, ipopt_time_nofunc, ipopt_time_func, ipopt_total_time = (
self._parse_ipopt_output(ostreams[0])
)
return process, iters, ipopt_time_nofunc, ipopt_time_func, ipopt_total_time

@document_kwargs_from_configdict(CONFIG)
def solve(self, model, **kwds):
# Begin time tracking
Expand Down Expand Up @@ -371,48 +418,11 @@ def solve(self, model, **kwds):
symbolic_solver_labels=config.symbolic_solver_labels,
)
timer.stop('write_nl_file')
ostreams = [io.StringIO()] + config.tee
if len(nl_info.variables) > 0:
# Get a copy of the environment to pass to the subprocess
env = os.environ.copy()
if nl_info.external_function_libraries:
if env.get('AMPLFUNC'):
nl_info.external_function_libraries.append(env.get('AMPLFUNC'))
env['AMPLFUNC'] = "\n".join(nl_info.external_function_libraries)
# Write the opt_file, if there should be one; return a bool to say
# whether or not we have one (so we can correctly build the command line)
opt_file = self._write_options_file(
filename=basename, options=config.solver_options
)
# Call ipopt - passing the files via the subprocess
cmd = self._create_command_line(
basename=basename, config=config, opt_file=opt_file
process, iters, ipopt_time_nofunc, ipopt_time_func, ipopt_total_time = (
self._run_subprocess(basename, timer, ostreams, config, nl_info)
)
# this seems silly, but we have to give the subprocess slightly longer to finish than
# ipopt
if config.time_limit is not None:
timeout = config.time_limit + min(
max(1.0, 0.01 * config.time_limit), 100
)
else:
timeout = None

ostreams = [io.StringIO()] + config.tee
with TeeStream(*ostreams) as t:
timer.start('subprocess')
process = subprocess.run(
cmd,
timeout=timeout,
env=env,
universal_newlines=True,
stdout=t.STDOUT,
stderr=t.STDERR,
)
timer.stop('subprocess')
# This is the stuff we need to parse to get the iterations
# and time
iters, ipopt_time_nofunc, ipopt_time_func, ipopt_total_time = (
self._parse_ipopt_output(ostreams[0])
)

if len(nl_info.variables) == 0:
if len(nl_info.eliminated_vars) == 0:
Expand Down
4 changes: 4 additions & 0 deletions pyomo/contrib/solver/tests/unit/test_ipopt.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,3 +241,7 @@ def test_create_command_line(self):
)
with self.assertRaises(ValueError):
result = opt._create_command_line('myfile', opt.config, False)

def test_run_subprocess(self):
# TODO: Left off here!
pass

0 comments on commit a1c9aff

Please sign in to comment.