Skip to content

Commit

Permalink
Merge pull request Pyomo#3335 from jsiirola/freebsd-fixes
Browse files Browse the repository at this point in the history
Omnibus testing / platform portability fixes
  • Loading branch information
blnicho authored Aug 12, 2024
2 parents 7f779ab + 658dab3 commit 404fd6d
Show file tree
Hide file tree
Showing 22 changed files with 360 additions and 121 deletions.
9 changes: 8 additions & 1 deletion pyomo/common/fileutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,10 +286,17 @@ def find_dir(
)


_exeExt = {'linux': None, 'windows': '.exe', 'cygwin': '.exe', 'darwin': None}
_exeExt = {
'linux': None,
'freebsd': None,
'windows': '.exe',
'cygwin': '.exe',
'darwin': None,
}

_libExt = {
'linux': ('.so', '.so.*'),
'freebsd': ('.so', '.so.*'),
'windows': ('.dll', '.pyd'),
'cygwin': ('.dll', '.so', '.so.*'),
'darwin': ('.dylib', '.so', '.so.*'),
Expand Down
7 changes: 4 additions & 3 deletions pyomo/common/tests/test_download.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import pyomo.common.envvar as envvar

from pyomo.common import DeveloperError
from pyomo.common.fileutils import this_file
from pyomo.common.fileutils import this_file, Executable
from pyomo.common.download import FileDownloader, distro_available
from pyomo.common.log import LoggingIntercept
from pyomo.common.tee import capture_output
Expand Down Expand Up @@ -173,7 +173,8 @@ def test_get_os_version(self):
self.assertTrue(v.replace('.', '').startswith(dist_ver))

if (
subprocess.run(
Executable('lsb_release').available()
and subprocess.run(
['lsb_release'],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
Expand Down Expand Up @@ -206,7 +207,7 @@ def test_get_os_version(self):
self.assertEqual(_os, 'win')
self.assertEqual(_norm, _os + ''.join(_ver.split('.')[:2]))
else:
self.assertEqual(ans, '')
self.assertEqual(_os, '')

self.assertEqual((_os, _ver), FileDownloader._os_version)
# Exercise the fetch from CACHE
Expand Down
2 changes: 1 addition & 1 deletion pyomo/common/unittest.py
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,7 @@ def filter_file_contents(self, lines, abstol=None):

return filtered

def compare_baseline(self, test_output, baseline, abstol=1e-6, reltol=None):
def compare_baseline(self, test_output, baseline, abstol=1e-6, reltol=1e-8):
# Filter files independently and then compare filtered contents
out_filtered = self.filter_file_contents(
test_output.strip().split('\n'), abstol
Expand Down
21 changes: 21 additions & 0 deletions pyomo/contrib/appsi/solvers/ipopt.py
Original file line number Diff line number Diff line change
Expand Up @@ -567,3 +567,24 @@ def get_reduced_costs(
return ComponentMap((k, v) for k, v in self._reduced_costs.items())
else:
return ComponentMap((v, self._reduced_costs[v]) for v in vars_to_load)

def has_linear_solver(self, linear_solver):
import pyomo.core as AML
from pyomo.common.tee import capture_output

m = AML.ConcreteModel()
m.x = AML.Var()
m.o = AML.Objective(expr=(m.x - 2) ** 2)
with capture_output() as OUT:
solver = self.__class__()
solver.config.stream_solver = True
solver.config.load_solution = False
solver.ipopt_options['linear_solver'] = linear_solver
try:
solver.solve(m)
except FileNotFoundError:
# The APPSI interface always tries to open the SOL file,
# and will generate a FileNotFoundError if ipopt didn't
# generate one
return False
return 'running with linear solver' in OUT.getvalue()
42 changes: 42 additions & 0 deletions pyomo/contrib/appsi/tests/test_ipopt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# ___________________________________________________________________________
#
# Pyomo: Python Optimization Modeling Objects
# Copyright (c) 2008-2024
# National Technology and Engineering Solutions of Sandia, LLC
# Under the terms of Contract DE-NA0003525 with National Technology and
# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________

from pyomo.common import unittest
from pyomo.contrib.appsi.solvers import ipopt


ipopt_available = ipopt.Ipopt().available()


@unittest.skipIf(not ipopt_available, "The 'ipopt' command is not available")
class TestIpoptInterface(unittest.TestCase):
def test_has_linear_solver(self):
opt = ipopt.Ipopt()
self.assertTrue(
any(
map(
opt.has_linear_solver,
[
'mumps',
'ma27',
'ma57',
'ma77',
'ma86',
'ma97',
'pardiso',
'pardisomkl',
'spral',
'wsmp',
],
)
)
)
self.assertFalse(opt.has_linear_solver('bogus_linear_solver'))
9 changes: 6 additions & 3 deletions pyomo/contrib/doe/doe.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def __init__(
A Python ``function`` that returns a Concrete Pyomo model, similar to the interface for ``parmest``
solver:
A ``solver`` object that User specified, default=None.
If not specified, default solver is IPOPT MA57.
If not specified, default solver is IPOPT (with MA57, if available).
prior_FIM:
A 2D numpy array containing Fisher information matrix (FIM) for prior experiments.
The default None means there is no prior information.
Expand Down Expand Up @@ -995,7 +995,7 @@ def run_grid_search(
)
count += 1
failed_count += 1
self.logger.warning("failed count:", failed_count)
self.logger.warning("failed count: %s", failed_count)
result_combine[tuple(design_set_iter)] = None

# For user's access
Expand Down Expand Up @@ -1387,7 +1387,10 @@ def _fix_design(self, m, design_val, fix_opt=True, optimize_option=None):
def _get_default_ipopt_solver(self):
"""Default solver"""
solver = SolverFactory("ipopt")
solver.options["linear_solver"] = "ma57"
for linear_solver in ('ma57', 'ma27', 'ma97'):
if solver.has_linear_solver(linear_solver):
solver.options["linear_solver"] = linear_solver
break
solver.options["halt_on_ampl_error"] = "yes"
solver.options["max_iter"] = 3000
return solver
Expand Down
2 changes: 2 additions & 0 deletions pyomo/contrib/doe/tests/test_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
from pyomo.opt import SolverFactory

ipopt_available = SolverFactory("ipopt").available()
k_aug_available = SolverFactory("k_aug").available(exception_flag=False)


class TestReactorExamples(unittest.TestCase):
Expand All @@ -57,6 +58,7 @@ def test_reactor_optimize_doe(self):

reactor_optimize_doe.main()

@unittest.skipIf(not k_aug_available, "The 'k_aug' command is not available")
@unittest.skipIf(not ipopt_available, "The 'ipopt' command is not available")
@unittest.skipIf(not pandas_available, "pandas is not available")
@unittest.skipIf(not numpy_available, "Numpy is not available")
Expand Down
4 changes: 4 additions & 0 deletions pyomo/contrib/doe/tests/test_fim_doe.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
VariablesWithIndices,
)
from pyomo.contrib.doe.examples.reactor_kinetics import create_model, disc_for_measure
from pyomo.environ import SolverFactory

ipopt_available = SolverFactory("ipopt").available()


class TestMeasurementError(unittest.TestCase):
Expand Down Expand Up @@ -196,6 +199,7 @@ def test(self):


@unittest.skipIf(not numpy_available, "Numpy is not available")
@unittest.skipIf(not ipopt_available, "ipopt is not available")
class TestPriorFIMError(unittest.TestCase):
def test(self):
# Control time set [h]
Expand Down
2 changes: 2 additions & 0 deletions pyomo/contrib/doe/tests/test_reactor_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from pyomo.opt import SolverFactory

ipopt_available = SolverFactory("ipopt").available()
k_aug_available = SolverFactory("k_aug").available(exception_flag=False)


class Test_Reaction_Kinetics_Example(unittest.TestCase):
Expand Down Expand Up @@ -133,6 +134,7 @@ def test_kinetics_example_sequential_finite_then_optimize(self):
# self.assertAlmostEqual(value(optimize_result.model.T[0.5]), 300, places=2)
self.assertAlmostEqual(np.log10(optimize_result.trace), 3.340, places=2)

@unittest.skipIf(not k_aug_available, "The 'k_aug' solver is not available")
@unittest.skipIf(not ipopt_available, "The 'ipopt' solver is not available")
@unittest.skipIf(not numpy_available, "Numpy is not available")
@unittest.skipIf(not pandas_available, "Pandas is not available")
Expand Down
12 changes: 8 additions & 4 deletions pyomo/contrib/parmest/tests/test_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
import pyomo.common.unittest as unittest
import pyomo.contrib.parmest.parmest as parmest
from pyomo.contrib.parmest.graphics import matplotlib_available, seaborn_available
from pyomo.contrib.pynumero.asl import AmplInterface
from pyomo.opt import SolverFactory

ipopt_available = SolverFactory("ipopt").available()
pynumero_ASL_available = AmplInterface.available()


@unittest.skipIf(
Expand Down Expand Up @@ -43,6 +45,7 @@ def test_model_with_constraint(self):

rooney_biegler_with_constraint.main()

@unittest.skipUnless(pynumero_ASL_available, "test requires libpynumero_ASL")
@unittest.skipUnless(seaborn_available, "test requires seaborn")
def test_parameter_estimation_example(self):
from pyomo.contrib.parmest.examples.rooney_biegler import (
Expand All @@ -66,11 +69,11 @@ def test_likelihood_ratio_example(self):
likelihood_ratio_example.main()


@unittest.skipIf(
not parmest.parmest_available,
"Cannot test parmest: required dependencies are missing",
@unittest.skipUnless(pynumero_ASL_available, "test requires libpynumero_ASL")
@unittest.skipUnless(ipopt_available, "The 'ipopt' solver is not available")
@unittest.skipUnless(
parmest.parmest_available, "Cannot test parmest: required dependencies are missing"
)
@unittest.skipIf(not ipopt_available, "The 'ipopt' solver is not available")
class TestReactionKineticsExamples(unittest.TestCase):
@classmethod
def setUpClass(self):
Expand Down Expand Up @@ -140,6 +143,7 @@ def test_model(self):

reactor_design.main()

@unittest.skipUnless(pynumero_ASL_available, "test requires libpynumero_ASL")
def test_parameter_estimation_example(self):
from pyomo.contrib.parmest.examples.reactor_design import (
parameter_estimation_example,
Expand Down
Loading

0 comments on commit 404fd6d

Please sign in to comment.