From bc29a649a7676234755d3cf39c8deff9115b6c4a Mon Sep 17 00:00:00 2001 From: Eslick Date: Wed, 25 Jun 2025 15:27:03 -0400 Subject: [PATCH 01/34] Add external fuction library --- pyomo/contrib/external_functions/__init__.py | 10 ++ pyomo/contrib/external_functions/build.py | 32 ++++ pyomo/contrib/external_functions/plugins.py | 16 ++ .../external_functions/src/CMakeLists.txt | 43 +++++ .../external_functions/src/functions.cpp | 147 ++++++++++++++++++ .../external_functions/tests/__init__.py | 10 ++ .../tests/test_functions.py | 104 +++++++++++++ pyomo/environ/__init__.py | 1 + pyomo/environ/tests/test_package_layout.py | 1 + 9 files changed, 364 insertions(+) create mode 100644 pyomo/contrib/external_functions/__init__.py create mode 100644 pyomo/contrib/external_functions/build.py create mode 100644 pyomo/contrib/external_functions/plugins.py create mode 100644 pyomo/contrib/external_functions/src/CMakeLists.txt create mode 100644 pyomo/contrib/external_functions/src/functions.cpp create mode 100644 pyomo/contrib/external_functions/tests/__init__.py create mode 100644 pyomo/contrib/external_functions/tests/test_functions.py diff --git a/pyomo/contrib/external_functions/__init__.py b/pyomo/contrib/external_functions/__init__.py new file mode 100644 index 00000000000..6eb9ea8b81d --- /dev/null +++ b/pyomo/contrib/external_functions/__init__.py @@ -0,0 +1,10 @@ +# ___________________________________________________________________________ +# +# Pyomo: Python Optimization Modeling Objects +# Copyright (c) 2008-2025 +# 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. +# ___________________________________________________________________________ diff --git a/pyomo/contrib/external_functions/build.py b/pyomo/contrib/external_functions/build.py new file mode 100644 index 00000000000..6c1a724fd94 --- /dev/null +++ b/pyomo/contrib/external_functions/build.py @@ -0,0 +1,32 @@ +# ___________________________________________________________________________ +# +# Pyomo: Python Optimization Modeling Objects +# Copyright (c) 2008-2025 +# 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. +# ___________________________________________________________________________ + +import sys +from pyomo.common.cmake_builder import build_cmake_project + + +def build_external_functions(user_args=[], parallel=None): + return build_cmake_project( + targets=['src'], + package_name='external_functions', + description='Useful external function', + user_args=['-DBUILD_AMPLASL_IF_NEEDED=ON'] + user_args, + parallel=parallel, + ) + + +class ExternalFunctionBuilder(object): + def __call__(self, parallel): + return build_external_functions(parallel=parallel) + + +if __name__ == "__main__": + build_external_functions(sys.argv[1:]) diff --git a/pyomo/contrib/external_functions/plugins.py b/pyomo/contrib/external_functions/plugins.py new file mode 100644 index 00000000000..6b76d56c51f --- /dev/null +++ b/pyomo/contrib/external_functions/plugins.py @@ -0,0 +1,16 @@ +# ___________________________________________________________________________ +# +# Pyomo: Python Optimization Modeling Objects +# Copyright (c) 2008-2025 +# 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.extensions import ExtensionBuilderFactory +from pyomo.contrib.external_functions.build import ExternalFunctionBuilder + +def load(): + ExtensionBuilderFactory.register('external_functions')(ExternalFunctionBuilder) diff --git a/pyomo/contrib/external_functions/src/CMakeLists.txt b/pyomo/contrib/external_functions/src/CMakeLists.txt new file mode 100644 index 00000000000..42f570cb71c --- /dev/null +++ b/pyomo/contrib/external_functions/src/CMakeLists.txt @@ -0,0 +1,43 @@ +# ___________________________________________________________________________ +# +# Pyomo: Python Optimization Modeling Objects +# Copyright (c) 2008-2025 +# 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. +# ___________________________________________________________________________ + +cmake_minimum_required(VERSION 3.0...3.31) +# This was developed against CMake 3.0, and appears to comply with 3.5 + +PROJECT( external_functions ) + +INCLUDE( + "${CMAKE_CURRENT_SOURCE_DIR}/../../ampl_function_demo/src/FindASL.cmake") + +# Targets in this project +OPTION(BUILD_EXTERNAL_FCN_LIBRARY + "Build the ASL external function example library" ON) + +IF( BUILD_EXTERNAL_FCN_LIBRARY ) + ADD_LIBRARY( external_functions SHARED "functions.cpp" ) + TARGET_LINK_LIBRARIES( external_functions + PUBLIC ${ASL_LIBRARY} ${CMAKE_DL_LIBS}) + TARGET_INCLUDE_DIRECTORIES( external_functions + PUBLIC ${ASL_INCLUDE_DIR} + INTERFACE . ) + # If you need a CPP directive defined when building the library (e.g., + # for managing __declspec(dllimport) under Windows) uncomment the + # following: + #TARGET_COMPILE_DEFINITIONS( external_functions PRIVATE BUILDING_ASL_DEMO ) + #SET_TARGET_PROPERTIES( external_functions PROPERTIES ENABLE_EXPORTS 1 ) + INSTALL( TARGETS external_functions LIBRARY DESTINATION lib + RUNTIME DESTINATION lib ) + IF( BUILD_AMPLASL ) + # If we are building AMPL/asl (from FindASL), it is possible that we + # are linking against it, so we will add the appropriate dependency + add_dependencies(external_functions ampl_asl) + ENDIF() +ENDIF() diff --git a/pyomo/contrib/external_functions/src/functions.cpp b/pyomo/contrib/external_functions/src/functions.cpp new file mode 100644 index 00000000000..35ce7dbb2ec --- /dev/null +++ b/pyomo/contrib/external_functions/src/functions.cpp @@ -0,0 +1,147 @@ +/* ___________________________________________________________________________ + * Pyomo: Python Optimization Modeling Objects + * Copyright (c) 2008-2025 + * 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. + * ___________________________________________________________________________ +*/ +#include +#include "funcadd.h" + +extern real sinc(arglist *al) { + real x = al->ra[al->at[0]]; + real y = 0; + real r = 1e-4; + if(fabs(x) < r){ // use taylor series near 0 + y = 1 + - x * x / 3.0 / 2.0 + + pow(x, 4) / 5.0 / 4.0 / 3.0 / 2.0 + - pow(x, 6) / 7.0 / 6.0 / 5.0 / 4.0 / 3.0 / 2.0 + + pow(x, 8) / 9.0 / 8.0 / 7.0 / 6.0 / 5.0 / 4.0 / 3.0 / 2.0; + if (al->derivs!=NULL) { + al->derivs[0] = - x / 3.0 + + pow(x, 3) / 5.0 / 3.0 / 2.0 + - pow(x, 5) / 7.0 / 5.0 / 4.0 / 3.0 / 2.0 + + pow(x, 7) / 9.0 / 7.0 / 6.0 / 5.0 / 4.0 / 3.0 / 2.0; + } + if (al->hes!=NULL) { + al->hes[0] = - 1 / 3.0 + + pow(x, 2) / 5.0 / 2.0 + - pow(x, 4) / 7.0 / 4.0 / 3.0 / 2.0 + + pow(x, 6) / 9.0 / 6.0 / 5.0 / 4.0 / 3.0 / 2.0; + } + } + else{ // away from 0 use sin(x) / x + y = sin(x) / x; + if (al->derivs!=NULL) { + al->derivs[0] = cos(x) / x - sin(x) / x / x; + } + if (al->hes!=NULL) { + al->hes[0] = -sin(x) / x - 2 * cos(x) / x / x + + 2 * sin(x) / x / x / x; + } + } + return y; +} + +extern real sgnsqr(arglist *al) { + real x = al->ra[al->at[0]]; + real y = copysign(x * x, x); + + // Compute the first derivative, if requested. + if (al->derivs!=NULL) { + al->derivs[0] = 2 * fabs(x); + } + + // Compute the second derivative, if requested. + if (al->hes!=NULL) { + al->hes[0] = copysign(2, x); + } + return y; +} + +extern real sgnsqr_c4(arglist *al) { + real x = al->ra[al->at[0]]; + const real c[] = { + 0.0, + 0.0273437500000006, + 3.1086244689504383e-15, + 10.937499999999813, + 6.821210263296962e-13, + -546.8749999999808, + -1.2114878257930237e-10, + 21874.99999999906, + 7.251377026937331e-09, + -390624.99999998155, + -1.582935171828823e-07, + }; + const real r = 0.1; + real y = 0; + unsigned char i = 0; + + if(fabs(x) < r){ + for(i=0; i<11; ++i){ + y += c[i] * pow(x, i); + } + if (al->derivs!=NULL) { + al->derivs[0] = 0; + for(i=1; i<11; ++i){ + al->derivs[0] += c[i] * i * pow(x, i - 1); + } + } + if (al->hes!=NULL) { + al->hes[0] = 0; + for(i=2; i<11; ++i){ + al->hes[0] += c[i] * i * (i - 1) * pow(x, i - 2); + } + } + } + else{ + y = copysign(x * x, x); + if (al->derivs!=NULL) { + al->derivs[0] = 2 * fabs(x); + } + if (al->hes!=NULL) { + al->hes[0] = copysign(2, x); + } + } + + return y; +} + +// Register external functions defined in this library with the ASL +void funcadd(AmplExports *ae){ + // Arguments for addfunc (this is not fully detailed; see funcadd.h) + // 1) Name of function in AMPL + // 2) Function pointer to C function + // 3) see FUNCADD_TYPE enum in funcadd.h + // 4) Number of arguments + // >=0 indicates a fixed number of arguments + // < 0 indicates a variable length list (requiring at least -(n+1) + // arguments) + // 5) Void pointer to function info + addfunc( + "sinc", + (rfunc)sinc, + FUNCADD_REAL_VALUED, + 1, + NULL + ); + addfunc( + "sgnsqr", + (rfunc)sgnsqr, + FUNCADD_REAL_VALUED, + 1, + NULL + ); + addfunc( + "sgnsqr_c4", + (rfunc)sgnsqr_c4, + FUNCADD_REAL_VALUED, + 1, + NULL + ); +} diff --git a/pyomo/contrib/external_functions/tests/__init__.py b/pyomo/contrib/external_functions/tests/__init__.py new file mode 100644 index 00000000000..6eb9ea8b81d --- /dev/null +++ b/pyomo/contrib/external_functions/tests/__init__.py @@ -0,0 +1,10 @@ +# ___________________________________________________________________________ +# +# Pyomo: Python Optimization Modeling Objects +# Copyright (c) 2008-2025 +# 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. +# ___________________________________________________________________________ diff --git a/pyomo/contrib/external_functions/tests/test_functions.py b/pyomo/contrib/external_functions/tests/test_functions.py new file mode 100644 index 00000000000..fd392264fb9 --- /dev/null +++ b/pyomo/contrib/external_functions/tests/test_functions.py @@ -0,0 +1,104 @@ +# ___________________________________________________________________________ +# +# Pyomo: Python Optimization Modeling Objects +# Copyright (c) 2008-2025 +# 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. +# ___________________________________________________________________________ + +import platform +import math +import pyomo.environ as pyo +import pyomo.common.unittest as unittest +from pyomo.common.fileutils import find_library + +flib = find_library("external_functions") +is_pypy = platform.python_implementation().lower().startswith("pypy") + +@unittest.skipUnless(flib, 'Could not find the "external" library') +class TestAMPLExternalFunction(unittest.TestCase): + + @unittest.skipIf(is_pypy, "Cannot evaluate external functions under pypy") + def test_eval_sqnsqr_function_fgh(self): + m = pyo.ConcreteModel() + m.tf = pyo.ExternalFunction(library=flib, function="sgnsqr") + + f, g, h = m.tf.evaluate_fgh((2,)) + self.assertEqual(f, 4) + self.assertEqual(g, [4]) + self.assertEqual(h, [2]) + + f, g, h = m.tf.evaluate_fgh((-2,)) + self.assertAlmostEqual(f, -4) + self.assertStructuredAlmostEqual(g, [4]) + self.assertStructuredAlmostEqual(h, [-2]) + + @unittest.skipIf(is_pypy, "Cannot evaluate external functions under pypy") + def test_eval_sqnsqr_c4_function_fgh(self): + m = pyo.ConcreteModel() + m.tf = pyo.ExternalFunction(library=flib, function="sgnsqr_c4") + + f, g, h = m.tf.evaluate_fgh((2,)) + self.assertEqual(f, 4) + self.assertEqual(g, [4]) + self.assertEqual(h, [2]) + + f, g, h = m.tf.evaluate_fgh((-2,)) + self.assertAlmostEqual(f, -4) + self.assertStructuredAlmostEqual(g, [4]) + self.assertStructuredAlmostEqual(h, [-2]) + + dx = 1e-9 + x = 0.1 + + f1, g1, h1 = m.tf.evaluate_fgh((x + dx,)) + f2, g2, h2 = m.tf.evaluate_fgh((x - dx,)) + self.assertAlmostEqual(f1, f2) + self.assertStructuredAlmostEqual(g1, g2) + self.assertStructuredAlmostEqual(h1, h2) + + dx = 1e-9 + x = -0.1 + + f1, g1, h1 = m.tf.evaluate_fgh((x + dx,)) + f2, g2, h2 = m.tf.evaluate_fgh((x - dx,)) + self.assertAlmostEqual(f1, f2) + self.assertStructuredAlmostEqual(g1, g2) + self.assertStructuredAlmostEqual(h1, h2) + + + @unittest.skipIf(is_pypy, "Cannot evaluate external functions under pypy") + def test_eval_sinc_function_fgh(self): + m = pyo.ConcreteModel() + m.tf = pyo.ExternalFunction(library=flib, function="sinc") + + f, g, h = m.tf.evaluate_fgh((0,)) + self.assertAlmostEqual(f, 1.0) + self.assertAlmostEqual(g, [0]) + self.assertAlmostEqual(h, [-1/3.0]) + + dx = 1e-10 + f, g, h = m.tf.evaluate_fgh((2,)) + self.assertAlmostEqual(f, math.sin(2) / 2) + self.assertStructuredAlmostEqual(g, [(math.sin(2 + dx) / (2 + dx) - f)/dx], 5) + + dx = 1e-12 + x = 1e-4 + + f1, g1, h1 = m.tf.evaluate_fgh((x + dx,)) + f2, g2, h2 = m.tf.evaluate_fgh((x - dx,)) + self.assertAlmostEqual(f1, f2) + self.assertStructuredAlmostEqual(g1, g2) + self.assertStructuredAlmostEqual(h1, h2) + + dx = 1e-12 + x = 1e-4 + + f1, g1, h1 = m.tf.evaluate_fgh((x + dx,)) + f2, g2, h2 = m.tf.evaluate_fgh((x - dx,)) + self.assertAlmostEqual(f1, f2) + self.assertStructuredAlmostEqual(g1, g2) + self.assertStructuredAlmostEqual(h1, h2) diff --git a/pyomo/environ/__init__.py b/pyomo/environ/__init__.py index 7e2e4caaab1..e11fb313ace 100644 --- a/pyomo/environ/__init__.py +++ b/pyomo/environ/__init__.py @@ -41,6 +41,7 @@ def _do_import(pkg_name): 'pyomo.contrib.cp', 'pyomo.contrib.cspline_external', 'pyomo.contrib.example', + 'pyomo.contrib.external_functions', 'pyomo.contrib.fme', 'pyomo.contrib.gdp_bounds', 'pyomo.contrib.gdpopt', diff --git a/pyomo/environ/tests/test_package_layout.py b/pyomo/environ/tests/test_package_layout.py index cd6ca156c46..5c828844163 100644 --- a/pyomo/environ/tests/test_package_layout.py +++ b/pyomo/environ/tests/test_package_layout.py @@ -39,6 +39,7 @@ join('contrib', 'ampl_function_demo', 'src'), join('contrib', 'appsi', 'cmodel', 'src'), join('contrib', 'cspline_external', 'src'), + join('contrib', 'external_functions', 'src'), join('contrib', 'simplification', 'ginac', 'src'), join('contrib', 'pynumero', 'src'), join('core', 'tests', 'data', 'baselines'), From 427ae1065784b6309101a36f905ba0b76d91b845 Mon Sep 17 00:00:00 2001 From: Eslick Date: Thu, 26 Jun 2025 11:46:59 -0400 Subject: [PATCH 02/34] Add external funcion docs --- .../external_functions/figs/sgnsqr_f.png | Bin 0 -> 33641 bytes .../external_functions/figs/sgnsqr_fx.png | Bin 0 -> 40628 bytes .../external_functions/figs/sgnsqr_fxx.png | Bin 0 -> 24694 bytes .../external_functions/index.rst | 72 ++++++++++++++++++ .../explanation/modeling_utils/index.rst | 2 +- .../external_functions/src/functions.cpp | 8 +- .../tests/test_functions.py | 8 +- 7 files changed, 82 insertions(+), 8 deletions(-) create mode 100644 doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqr_f.png create mode 100644 doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqr_fx.png create mode 100644 doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqr_fxx.png create mode 100644 doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqr_f.png b/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqr_f.png new file mode 100644 index 0000000000000000000000000000000000000000..99a11de0c28731ce78301a53cf8997079cc10d17 GIT binary patch literal 33641 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 NhH9LOIiY#)zW|g?d7%IR literal 0 HcmV?d00001 diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqr_fx.png b/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqr_fx.png new file mode 100644 index 0000000000000000000000000000000000000000..933d4f15d9e6016c11342db325e7b502d5cd8e62 GIT binary patch literal 40628 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 K7`-Rp)|0=#B!pi8 literal 0 HcmV?d00001 diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqr_fxx.png b/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqr_fxx.png new file mode 100644 index 0000000000000000000000000000000000000000..35b4590975ecaa17621352549940f41dd7d89d1f GIT binary patch literal 24694 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�TS!;~@zV7?F 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 Mr^${C1G~U~1D*iFa{vGU literal 0 HcmV?d00001 diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst new file mode 100644 index 00000000000..5a1fff62d8f --- /dev/null +++ b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst @@ -0,0 +1,72 @@ +External Functions +================== + +Pyomo provides a set of AMPL user-defined functions that commonly occur but cannot be easily written as Pyomo expressions. + +Using These External Functions +------------------------------ + +You must build the Pyomo extensions to use these functions. Run ``pyomo build-extensions`` in the terminal and make sure the ``external_functions`` build status is "ok." + +.. doctest:: + + >>> import pyomo.environ as pyo + >>> from pyomo.common.fileutils import find_library + >>> flib = find_library("external_functions") + >>> m = pyo.ConcreteModel(name = 'ExternalFunctions') + >>> m.sinc = pyo.ExternalFunction(library=flib, function="sinc") + >>> m.x = pyo.Var() + >>> m.z = pyo.Var() + >>> m.constraint = pyo.Constraint(expr = m.z == m.sinc(m.x)) + +Functions +--------- + +sinc(x) +~~~~~~~ + +This function is defined as: + +.. math:: + + \text{sinc}(x) = \cases{ + \sin(x) / x & if $x \neq 0$ \\ + 1 & if $x = 0$ + } + +In this implementation, the region :math:`-0.1 < x < 0.1` is replaced by a Taylor series with enough terms that the function should be at least :math:`C^2` smooth. The difference between the function and the Tayor series is near the limits of machine precision, about :math:`1 \times 10^{-16}` for the function value, :math:`1 \times 10^{-16}` for the first derivative, and :math:`1 \times 10^{-14}` for the second derivative. + +sgnsqr(x) +~~~~~~~~~ + +This function is defined as: + +.. math:: + + \text{sgnsqr}(x) = \text{sgn}(x)x^2 + +This function is only $C^1$ smooth because at 0 the second derivative is undefined and the jumps from -2 to 2. + +sgnsqr_c4(x) +~~~~~~~~~~~~ + + +This function is defined as: + +.. math:: + + \text{sgnsqr}(x) = \cases{ + \text{sgn}(x)x^2 & if $|x| \ge 0.1$ \\ + \sum_{i=0}^{11} c_i x^i & if $|x| < 0.1$ + } + +This function is $C^4$ smooth. The region :math:`-0.1 < x < 0.1` is replaced by an 11th order polynomial approximates that :math:`\text{sgn}(x)x^2`. The approximate function has a well behaved derivatives at :math:`x=0`. If you need to use this function with very small numbers and high accuracy is important, you can scale the argument up (e.g. :math:`\text{sgnsqr_c4}(sx)/s^2`). + +These figures show the sgnsqr(x) function compared to the smooth approximation sgnsqr_c4(x). + +.. image:: figs/sgnsqr_f.png + +.. image:: figs/sgnsqr_fx.png + +.. image:: figs/sgnsqr_fxx.png + diff --git a/doc/OnlineDocs/explanation/modeling_utils/index.rst b/doc/OnlineDocs/explanation/modeling_utils/index.rst index 16560899ebd..dd12b1ec53e 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/index.rst @@ -8,7 +8,7 @@ Modeling Utilities latex_printer preprocessing scaling - + external_functions/index .. diff --git a/pyomo/contrib/external_functions/src/functions.cpp b/pyomo/contrib/external_functions/src/functions.cpp index 35ce7dbb2ec..3f151a7f2e0 100644 --- a/pyomo/contrib/external_functions/src/functions.cpp +++ b/pyomo/contrib/external_functions/src/functions.cpp @@ -14,7 +14,7 @@ extern real sinc(arglist *al) { real x = al->ra[al->at[0]]; real y = 0; - real r = 1e-4; + real r = 0.1; if(fabs(x) < r){ // use taylor series near 0 y = 1 - x * x / 3.0 / 2.0 @@ -25,13 +25,15 @@ extern real sinc(arglist *al) { al->derivs[0] = - x / 3.0 + pow(x, 3) / 5.0 / 3.0 / 2.0 - pow(x, 5) / 7.0 / 5.0 / 4.0 / 3.0 / 2.0 - + pow(x, 7) / 9.0 / 7.0 / 6.0 / 5.0 / 4.0 / 3.0 / 2.0; + + pow(x, 7) / 9.0 / 7.0 / 6.0 / 5.0 / 4.0 / 3.0 / 2.0 + - pow(x, 9) /11.0 / 9.0 / 8.0 / 7.0 / 6.0 / 5.0 / 4.0 / 3.0 / 2.0; } if (al->hes!=NULL) { al->hes[0] = - 1 / 3.0 + pow(x, 2) / 5.0 / 2.0 - pow(x, 4) / 7.0 / 4.0 / 3.0 / 2.0 - + pow(x, 6) / 9.0 / 6.0 / 5.0 / 4.0 / 3.0 / 2.0; + + pow(x, 6) / 9.0 / 6.0 / 5.0 / 4.0 / 3.0 / 2.0 + - pow(x, 8) /11.0 / 8.0 / 7.0 / 6.0 / 5.0 / 4.0 / 3.0 / 2.0; } } else{ // away from 0 use sin(x) / x diff --git a/pyomo/contrib/external_functions/tests/test_functions.py b/pyomo/contrib/external_functions/tests/test_functions.py index fd392264fb9..1e2acbdf0d5 100644 --- a/pyomo/contrib/external_functions/tests/test_functions.py +++ b/pyomo/contrib/external_functions/tests/test_functions.py @@ -85,8 +85,8 @@ def test_eval_sinc_function_fgh(self): self.assertAlmostEqual(f, math.sin(2) / 2) self.assertStructuredAlmostEqual(g, [(math.sin(2 + dx) / (2 + dx) - f)/dx], 5) - dx = 1e-12 - x = 1e-4 + dx = 1e-10 + x = 0.1 f1, g1, h1 = m.tf.evaluate_fgh((x + dx,)) f2, g2, h2 = m.tf.evaluate_fgh((x - dx,)) @@ -94,8 +94,8 @@ def test_eval_sinc_function_fgh(self): self.assertStructuredAlmostEqual(g1, g2) self.assertStructuredAlmostEqual(h1, h2) - dx = 1e-12 - x = 1e-4 + dx = 1e-10 + x = 0.1 f1, g1, h1 = m.tf.evaluate_fgh((x + dx,)) f2, g2, h2 = m.tf.evaluate_fgh((x - dx,)) From 93a95cf431c16dd7134ee6213743f7875843953f Mon Sep 17 00:00:00 2001 From: Eslick Date: Thu, 26 Jun 2025 11:48:26 -0400 Subject: [PATCH 03/34] Run black --- pyomo/contrib/external_functions/build.py | 8 ++++---- pyomo/contrib/external_functions/plugins.py | 3 ++- pyomo/contrib/external_functions/tests/test_functions.py | 6 +++--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/pyomo/contrib/external_functions/build.py b/pyomo/contrib/external_functions/build.py index 6c1a724fd94..b0ac309c428 100644 --- a/pyomo/contrib/external_functions/build.py +++ b/pyomo/contrib/external_functions/build.py @@ -15,10 +15,10 @@ def build_external_functions(user_args=[], parallel=None): return build_cmake_project( - targets=['src'], - package_name='external_functions', - description='Useful external function', - user_args=['-DBUILD_AMPLASL_IF_NEEDED=ON'] + user_args, + targets=["src"], + package_name="external_functions", + description="Useful external function", + user_args=["-DBUILD_AMPLASL_IF_NEEDED=ON"] + user_args, parallel=parallel, ) diff --git a/pyomo/contrib/external_functions/plugins.py b/pyomo/contrib/external_functions/plugins.py index 6b76d56c51f..7481bb8d597 100644 --- a/pyomo/contrib/external_functions/plugins.py +++ b/pyomo/contrib/external_functions/plugins.py @@ -12,5 +12,6 @@ from pyomo.common.extensions import ExtensionBuilderFactory from pyomo.contrib.external_functions.build import ExternalFunctionBuilder + def load(): - ExtensionBuilderFactory.register('external_functions')(ExternalFunctionBuilder) + ExtensionBuilderFactory.register("external_functions")(ExternalFunctionBuilder) diff --git a/pyomo/contrib/external_functions/tests/test_functions.py b/pyomo/contrib/external_functions/tests/test_functions.py index 1e2acbdf0d5..acb5c395aa8 100644 --- a/pyomo/contrib/external_functions/tests/test_functions.py +++ b/pyomo/contrib/external_functions/tests/test_functions.py @@ -18,6 +18,7 @@ flib = find_library("external_functions") is_pypy = platform.python_implementation().lower().startswith("pypy") + @unittest.skipUnless(flib, 'Could not find the "external" library') class TestAMPLExternalFunction(unittest.TestCase): @@ -69,7 +70,6 @@ def test_eval_sqnsqr_c4_function_fgh(self): self.assertStructuredAlmostEqual(g1, g2) self.assertStructuredAlmostEqual(h1, h2) - @unittest.skipIf(is_pypy, "Cannot evaluate external functions under pypy") def test_eval_sinc_function_fgh(self): m = pyo.ConcreteModel() @@ -78,12 +78,12 @@ def test_eval_sinc_function_fgh(self): f, g, h = m.tf.evaluate_fgh((0,)) self.assertAlmostEqual(f, 1.0) self.assertAlmostEqual(g, [0]) - self.assertAlmostEqual(h, [-1/3.0]) + self.assertAlmostEqual(h, [-1 / 3.0]) dx = 1e-10 f, g, h = m.tf.evaluate_fgh((2,)) self.assertAlmostEqual(f, math.sin(2) / 2) - self.assertStructuredAlmostEqual(g, [(math.sin(2 + dx) / (2 + dx) - f)/dx], 5) + self.assertStructuredAlmostEqual(g, [(math.sin(2 + dx) / (2 + dx) - f) / dx], 5) dx = 1e-10 x = 0.1 From 4a146b09f062250a47d3344f895a7615f1523933 Mon Sep 17 00:00:00 2001 From: Eslick Date: Thu, 26 Jun 2025 12:48:28 -0400 Subject: [PATCH 04/34] Fix doc math cases --- .../modeling_utils/external_functions/index.rst | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst index 5a1fff62d8f..34bd027c640 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst @@ -6,8 +6,14 @@ Pyomo provides a set of AMPL user-defined functions that commonly occur but cann Using These External Functions ------------------------------ +Build +~~~~~ + You must build the Pyomo extensions to use these functions. Run ``pyomo build-extensions`` in the terminal and make sure the ``external_functions`` build status is "ok." +Example +~~~~~~~ + .. doctest:: >>> import pyomo.environ as pyo @@ -29,10 +35,10 @@ This function is defined as: .. math:: - \text{sinc}(x) = \cases{ + \text{sinc}(x) = \begin{cases} \sin(x) / x & if $x \neq 0$ \\ 1 & if $x = 0$ - } + \end{cases} In this implementation, the region :math:`-0.1 < x < 0.1` is replaced by a Taylor series with enough terms that the function should be at least :math:`C^2` smooth. The difference between the function and the Tayor series is near the limits of machine precision, about :math:`1 \times 10^{-16}` for the function value, :math:`1 \times 10^{-16}` for the first derivative, and :math:`1 \times 10^{-14}` for the second derivative. @@ -55,10 +61,10 @@ This function is defined as: .. math:: - \text{sgnsqr}(x) = \cases{ + \text{sgnsqr}(x) = \begin{cases} \text{sgn}(x)x^2 & if $|x| \ge 0.1$ \\ \sum_{i=0}^{11} c_i x^i & if $|x| < 0.1$ - } + \end{cases} This function is $C^4$ smooth. The region :math:`-0.1 < x < 0.1` is replaced by an 11th order polynomial approximates that :math:`\text{sgn}(x)x^2`. The approximate function has a well behaved derivatives at :math:`x=0`. If you need to use this function with very small numbers and high accuracy is important, you can scale the argument up (e.g. :math:`\text{sgnsqr_c4}(sx)/s^2`). From fa0a9ca84652b2675de08661f327fa547aa2c41f Mon Sep 17 00:00:00 2001 From: Eslick Date: Thu, 26 Jun 2025 12:58:45 -0400 Subject: [PATCH 05/34] Fix cases more --- .../modeling_utils/external_functions/index.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst index 34bd027c640..761981cbcaa 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst @@ -36,8 +36,8 @@ This function is defined as: .. math:: \text{sinc}(x) = \begin{cases} - \sin(x) / x & if $x \neq 0$ \\ - 1 & if $x = 0$ + \sin(x) / x & \text{if } x \neq 0 \\ + 1 & \text{if } x = 0 \end{cases} In this implementation, the region :math:`-0.1 < x < 0.1` is replaced by a Taylor series with enough terms that the function should be at least :math:`C^2` smooth. The difference between the function and the Tayor series is near the limits of machine precision, about :math:`1 \times 10^{-16}` for the function value, :math:`1 \times 10^{-16}` for the first derivative, and :math:`1 \times 10^{-14}` for the second derivative. @@ -62,8 +62,8 @@ This function is defined as: .. math:: \text{sgnsqr}(x) = \begin{cases} - \text{sgn}(x)x^2 & if $|x| \ge 0.1$ \\ - \sum_{i=0}^{11} c_i x^i & if $|x| < 0.1$ + \text{sgn}(x)x^2 & \text{if } |x| \ge 0.1 \\ + \sum_{i=0}^{11} c_i x^i & \text{if } |x| < 0.1 \end{cases} This function is $C^4$ smooth. The region :math:`-0.1 < x < 0.1` is replaced by an 11th order polynomial approximates that :math:`\text{sgn}(x)x^2`. The approximate function has a well behaved derivatives at :math:`x=0`. If you need to use this function with very small numbers and high accuracy is important, you can scale the argument up (e.g. :math:`\text{sgnsqr_c4}(sx)/s^2`). From 533ddb177ae965d494f7a414e3b3992d1fc6a52a Mon Sep 17 00:00:00 2001 From: Miranda Mundt <55767766+mrmundt@users.noreply.github.com> Date: Thu, 26 Jun 2025 12:41:46 -0600 Subject: [PATCH 06/34] Fix wonky underscore --- .../explanation/modeling_utils/external_functions/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst index 761981cbcaa..b1bf02ce908 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst @@ -66,7 +66,7 @@ This function is defined as: \sum_{i=0}^{11} c_i x^i & \text{if } |x| < 0.1 \end{cases} -This function is $C^4$ smooth. The region :math:`-0.1 < x < 0.1` is replaced by an 11th order polynomial approximates that :math:`\text{sgn}(x)x^2`. The approximate function has a well behaved derivatives at :math:`x=0`. If you need to use this function with very small numbers and high accuracy is important, you can scale the argument up (e.g. :math:`\text{sgnsqr_c4}(sx)/s^2`). +This function is $C^4$ smooth. The region :math:`-0.1 < x < 0.1` is replaced by an 11th order polynomial approximates that :math:`\text{sgn}(x)x^2`. The approximate function has a well behaved derivatives at :math:`x=0`. If you need to use this function with very small numbers and high accuracy is important, you can scale the argument up (e.g. :math:`\text{sgnsqr\_c4}(sx)/s^2`). These figures show the sgnsqr(x) function compared to the smooth approximation sgnsqr_c4(x). From 967a1116c9e4f4d7127204a82c978daa7f1e9bed Mon Sep 17 00:00:00 2001 From: Eslick Date: Mon, 30 Jun 2025 10:34:52 -0400 Subject: [PATCH 07/34] Add figs for sinc --- .../external_functions/figs/sinc_f.png | Bin 0 -> 32360 bytes .../external_functions/figs/sinc_fx.png | Bin 0 -> 32851 bytes .../external_functions/figs/sinc_fxx.png | Bin 0 -> 34359 bytes .../modeling_utils/external_functions/index.rst | 9 +++++++++ 4 files changed, 9 insertions(+) create mode 100644 doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sinc_f.png create mode 100644 doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sinc_fx.png create mode 100644 doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sinc_fxx.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sinc_f.png b/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sinc_f.png new file mode 100644 index 0000000000000000000000000000000000000000..89f65c1c635d46b5f9e16a172ecefef6571321c1 GIT binary patch literal 32360 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 z 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 literal 0 HcmV?d00001 diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sinc_fx.png b/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sinc_fx.png new file mode 100644 index 0000000000000000000000000000000000000000..29b9a61bb1cbfa9a3a043836da841af3ea6aac4b GIT binary patch literal 32851 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 CT`uzg literal 0 HcmV?d00001 diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sinc_fxx.png b/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sinc_fxx.png new file mode 100644 index 0000000000000000000000000000000000000000..2d44e546ea2e19c2ee3b08ff11a504bd6c2fb212 GIT binary patch literal 34359 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 LRHqQ{_|N|W-q;w> literal 0 HcmV?d00001 diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst index 761981cbcaa..e340f87d15c 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst @@ -42,6 +42,15 @@ This function is defined as: In this implementation, the region :math:`-0.1 < x < 0.1` is replaced by a Taylor series with enough terms that the function should be at least :math:`C^2` smooth. The difference between the function and the Tayor series is near the limits of machine precision, about :math:`1 \times 10^{-16}` for the function value, :math:`1 \times 10^{-16}` for the first derivative, and :math:`1 \times 10^{-14}` for the second derivative. +These figures show the sinc(x) function, the Taylor series and where the Taylor series is used. + +.. image:: figs/sinc_f.png + +.. image:: figs/sinc_fx.png + +.. image:: figs/sinc_fxx.png + + sgnsqr(x) ~~~~~~~~~ From d76ea88cff60f708cd420f5f9a43ca745f74a218 Mon Sep 17 00:00:00 2001 From: Eslick Date: Mon, 7 Jul 2025 12:27:52 -0400 Subject: [PATCH 08/34] Add signed square root approximation --- .../figs/sgnsqrt_c4_err.png | Bin 0 -> 21611 bytes .../external_functions/figs/sgnsqrt_c4_f.png | Bin 0 -> 28635 bytes .../external_functions/figs/sgnsqrt_c4_fx.png | Bin 0 -> 28129 bytes .../figs/sgnsqrt_c4_fxx.png | Bin 0 -> 33319 bytes .../external_functions/index.rst | 25 ++++++++ .../external_functions/src/functions.cpp | 58 ++++++++++++++++++ 6 files changed, 83 insertions(+) create mode 100644 doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqrt_c4_err.png create mode 100644 doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqrt_c4_f.png create mode 100644 doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqrt_c4_fx.png create mode 100644 doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqrt_c4_fxx.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqrt_c4_err.png b/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqrt_c4_err.png new file mode 100644 index 0000000000000000000000000000000000000000..1664a0f5ae762c6103a44dfe52794e53a770e00f GIT binary patch literal 21611 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 OL`SavT=MCL{J#L;#!k2Z literal 0 HcmV?d00001 diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqrt_c4_f.png b/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqrt_c4_f.png new file mode 100644 index 0000000000000000000000000000000000000000..63964459e5ee052c198a330744b35403fa13ad09 GIT binary patch literal 28635 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 literal 0 HcmV?d00001 diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqrt_c4_fx.png b/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqrt_c4_fx.png new file mode 100644 index 0000000000000000000000000000000000000000..705240880a5c55acd762d541560974d742243c6a GIT binary patch literal 28129 zcmdSBbyQaE7cKe%0xBh$SbTwVePPo5lb90IQX)F`*8oJ>&-?RW!u}g|d);D)I1zbL`5f zlk*G1vBr(Ha_!{)&B=+4+}Km+s%+SAWUue>u=h>pDh- z?n4zx$q(JGYjk24FJW}MMsJ;R7(IZK!=er5PBr^Ax$NfJ_-pusqhrwgop!RmdgT7d zpH^!-dkk9mqpx$>3;8eWV~l4K5)uu+8BrhLcquuy7%}`IOF}Wi(JB3FC`mZ18HAaL zoF4cbbq$W%aQy%OWYgvOuB0eg`nmQP^t|G7OIO0M0p~`J=Sl1BBht`AIoKA~*JG6~ zQL;a!t(1PsriHtU?2Xtls~4uKFGb+yZN{XeFicKPZm*8UNYS`|nQjW{m;SiBKI$}n zZzjOMJsQ8Bol@()f3L;XT>JFyu$A#pp-Dqy<4fl(aX&))#omDL-)V(}g>9UiN}5Hm zFfmIv8YwdVl{;?FKi7Zt>IRn)e!r$2fl)zpP!K+k<;Wj09k;j52KpVb{6W;hL-a-A zT=?~K2}dETWoT+`*A?#jM@m|%s{Vd{xYX3tMfq05Hrj_7w`u?JIIruLJ1o6iFcT3G zA#?N8)}}r^JuPN!UCeJ~osQ73Ov_y!$a{rP&hC}>s;Rr!LPNk|@x}DXmxu^`o|uiz z&GbHWHcRkGiGQ!vA|`3*&5UKuQk&^U;wx8bC+q#n=DwO;#K)hRi?PC)nE2%#M9%Rp zHI>oL&Fyt}@}(rH5PBviyxiE~h{(vMf`!uFxr5~u&ZJ`7BgflSXrfeERTU5rFqv?6%z%xJeLZ;6ET_sy zn0~gzwnh|py`WR19^Uv?r)WaK+S%z|4FrSZ%8;Q}vDLVUW#z`>y1Kgcjg4;_C6;a{ zJN;xX_L9lfig=0sFEn1hBsK1cP0M8#5<0G2ij0Whw4M;luH2N?ezQP#e0&TKWi(Oy z_S*I9HfvRTSFc}}w6*0NciSR}j*h;7i@SAtv}T8nbLvi#B07Z|WBtuHY?aBbP|49Q zG#~s-CljF>Ig3X3q$tpQ4ht(=%C2}lRCv#)^H!V3inca1F`SNg-pcAW)kI(VR znrGASa7=D)?&XKXx-)-5g^t(jnN@SW{HWig)|ugvGV9iQVZ8VC#mu#ye6+c>70s@P zNpSOlZoMx-wYaKo6VW05zK0JM{6}Yv&NOXLuQvQUex{d4tsl{ zC#B9T!Q=4W%5X^v1TboOtSW{nyYyY-M+z>(mTSi+Cu+I67;w#L*iqyC^~rytrL>Bo zH)v_e*qv52u~N5<$bCbjqF$pKN6PH7)@}$oW@3;diItm`rBQOzE6;ke?*87w+L~1m zm0+>@PWal{Z!#UBH37IAH|h=(Q!6`uz4PHh3W2Am=XC8`tm}O-oQ5AJS63}5MLjC( zioM^x3o0xul-@f!>Kx5bVM{XW&%WL_oU7-JK@P7W-a*a7K(Z}v?#ijf&U#``+x3@>}SbTLD{HLO0arf?Ba@g@c zL!*Mh`O%6JVlpz7g=&e0vQ#`(iS(7Ce(hJypXsh!l5y(Qy}#V)?d^@RKj}yFr?WFB zT!4w>$`zEDygZ?<$=jozgj0#vuNfhT^2QGL))ds#Zqyua%J}SsK=uI6;;kC@ram_x ztBkJqBhrX;ho^?5;If~8w#2EUqq8(!St$fSAig$M#ewe)+o#=aOv!C}&BVkcQ#G%y zd>ILDa~>|!UPe@RPmfx$`HeeL!FL%Lnhwi4D<#lFSD-5fH@QR_U*U@0prLtVhZ z!Hn3tQge3d3dQ37NQHkf92&tj5M-Z_-SY~IeUSdg5`%T=B9pAf&#`8F~^K>Rm z;pO3=WW&Kcr5JG<_t@B2X<6LST3a-iF(+KF`f!oS<9I`AwPH==r$RypKwihCpyGV9 zepYy+S-0EFdA1^Jj(z-SJW9KFTCtSM#!Cj2=>!D6ik>VeAo+rzxWiJP&GEhsK#!hQ zN@iwI&G9T-a!Sh9pF1Icf67rnls}c1HySCmLC0#SYQY-tDR_d|YK}km>v+Z~rO4;K z*)ffGUFBaAm>rH6a^b|nCCs!J%u+8ZPd*8Ja`FwTDq-lSPhyWAVTK6rl0!~UeqhR; zXy+ZDi8hYMNM#=?`q`JQ)e6AMBum_rZzyAHXU8`1!R6lLk2ile1dt5Yc#0ys>fzym ze}l8(@USCJkl%U&wT13P7Y|z&u;ygSoal$tr#?@L67>|3iDWf|AR+hFTRFvk-Sr(C z6(1j8v^gl5?D32&*MC6S(UIrJj~~|~=wZ1$ z6edXF`>U0$#;v2cWn5+SRacFtC%p9i?H+{#_*v*mlJZ$y`t#?>;qFSS=h=~tqM~Al z%NYPoMiC8h+ITM}BdueR`5-4!;4I4*=piKJOib>r)trf}uC79zsVmp+&(=CvNJ)s| zHY4ro>VopxU0~dKzog2rl~iPZ0;|o43!cP$q%^cs^o%mBxdDJpp(&UuYe{7LuQ&qh znogq*K@_~f*;*B!p+doK9zgQ&z1e;pt~Bz3j+67V$H^gwSs$~lt?m87T8u)I9$%z=`*RXDdK5&JRjtOW-5Zrv zv<&wT4{wTvE7g5jt2v&VoYZ^o<8wpUb@#zf`8ahw_3-i5=4KA~yJ?~6zn1mQP0qUd z`j2B(t`tyLKR?&h)YKaem*Y?xM6>PzccJhiCMSP=?b@~2twSikL8m826c`v7kDZ-M zIXsS?UmfkPpv`j%3wulV##}%8`(K30svLFIS5y{D$r3OTM;D6goqPAvx;s7g*Y&0$ zQn|i=|BeqElmt|w(V<_<*ll;vI6Rw;wnMTXlk}Wq3gG^Kp{C_mpAbZ~8_CBDJ=N7s zl*`e$57<=H#EuVd&_6i1vAvypxb7OtY+|N4tf8TSuN)t4R(9d()29zix*NI-`QBsd z5}YF&+cN+x?+iE`y7;G~gPxwg@lbH}1Du;!In2w*_ynQO$?-O`Jtdk2(;5hk_PO_e zq0x50pBuj6*C!She#y`0l!~O4uNxhuA|fJ+6lq#}gwX2-y$^wbaQoY$qT^jZ{KGc3 zwvwJFJ$80+;V=Ip@D#ZTWt}-sSX7jMMTH=QIUGs*{n)gP9Uo5QcRzdpET`f3@3Lis zPUUlg?gs><(VT~bgv2``At9-im|<#ZDG>N7gnm+KDLF)qROAaZ@lLJoeH4D6^_1)ls7=iK76RF7oUDc z)og;L3rsdnz+nm!D#Nx40bxLIVk#<&lopBP4(Tz>gcE|7ZMm#(UL8>g9dFeyixdpM z^?9oGB_^gdCBdWR{Uwr8U^q;LsadLdn6R*taSs{Tp^c4=Nmzw3U`w9^$OEY-Pc8rD4o zFi#KA2>`CRP@Eo^_WIvb`uR*9}xPzdoZ zb2og6XgtOo5XuQze6U_mw6VQi_{xD+k-?DeS9a&*AKRtxMGXD<`}6vWn~IdGQA<#r zkEayEc`=4(4Z13 zjot#B-Grw{N+u^4*A3w}_C6Mr0`~p@)v;{V`|lv)^mt-!2-q_&EG!%!Z*?-O<-Z3S z!;Y{T5L5LsY*h_V68Sxj`55G5C!q2hH3r=%H0xijOfWt@K6vlvSD;sqvs$&MO)nc& z3!Fp(YT;nMAs!YE{zRXKRgwIV1y76#=oCCMRs(n`LK_VvLWlE7KnGA>&0!2&wlhy~ z2yRM9OJBZs?;c3Kqu3LA1_rx!?*6}3u1=s7Iw-6vf5r0KInPBKccgWWk05YT zv9VhWJpd|gOMLcwW>2&DzmbT&c*MgHLR6*Vm90nLYRT{ z#noNdb%%Tdwu#aOh+ZBk12~k>*Vjim!>?bDR|`|{S|+>ht;)vog|1Z}1#4KAVY9KZ zl{>9bx7E@nWrKwdDs0hgIjDd(vG zhRmKa`{jX9h6J~(UZtgc+U`5b5v*FK!qv7mvBlWyj}Wm4(sysvNvCL>%l**)owqma z_SuF+!_zOgVteDPRI>|43sj68kuP=$ZJr$@3A(|Bg90!{*cEK-{mgz44olOJ zBU97UgB4CW4$*Mc(F&&$5v!h`1h;SBzTRijml@4{jIlgg5g8Q~b-CstJdz;V9kz&7 z&~aH8%5qx_@7g;RwS|Gaq@6r~Nl;t2Zr}b@o~c*wi%S0SLoKojfX9AiC>%;9z=bme z1|QVX@S}sID%ZX443(VAJ6blsug}cQ*-kYCNH1Z%20h@TJ~LHnfHwh{_@34z=y zspa?@M4`}nEmj|TaB%SQTiT9fp_#HXM`?d`)JkiAPn>WMj)3|2KW^g=N@*DxrdUx+ zavZ=0WSe=iTF1xFK97~SA2|X+v9`0jLr3QWd!bx*N~7Sz87+G~BK%DIYr7E&;V|?H zK>MP(7XD?By?y((a(^l?Q>W(i^J3MfmPMuTHyBW=#dWQ!3GQ%%U02Mf zAL6tTxW6o53QD!aGH$1Y{>~k5VAOw$Eru@-Lx6-8RXBlSF)%WEsfrGP*p^XLyb6`H z@3B8nolnuxCc;f@!oqPtF*ZEU_B=s5TW_`V763bRb9c9JqDlrdteSmU&hjHk%QDuPQHsE$ArF z6czOcHXUM=4`P`Q?WqpT4XOxWy_5MQ?G)c4W`t=JmoXt+n}LsSKeqpI5c#j4axq{m z;i3T0h0gYyMCXT!n9|bHj@LZT>RXpeJazXE4mLnptwSveN4x|tFOF4bNJt878I+*hH#>`V#XY4qub?6d@|X{ZrO3yXLUAmc z4i?PBQcQM?3JRp!(^dc>{SLT)T!9;GT6l*Cc!74SHD@01b85PFM^G?kVnR1RKObs+ z`okh9l9{pCG70ZGN^03#DZhtgy$Q-8^!$AiIoe5e$%(I246UfD`UK$B=U^pP^1$lZ zKi)mT66|MMwX{<~ zvBlsu%zRhw!!}n00mnxJer>32-}71^%cego$(XiFMgRr5WVyifQYFarGppMlSNFXcJhk@oy} z_;rod(N1C9^F{pUl<<} zx(1O?4NEi1}D0X2zO-j`dEHwtpZWTcb> z6be4IP!!k)c`tX_b^?*dD@%WjL1BvV<*N(G4TM{?$MEKauZZpryb?NEE-)}OREvxg za`_CROCy2TawKYIX2x#Jj5B(^Cxr;=02<_PX82*U<#X8mC;Vn)xseW`4%e)s)lswE zVA=uKq4WUPM}1hzkC5v1U_Kp<+d2lADdnkq+3H0f;JRU-KR*K0divx^BDj}DFVcFk zO)+4*je)zZj5osHHTHqatncp5A!K;Q!tHpY3FO@8&!6?R93j?w@?J@qWsHBiExr$? zNM??dl$6Tr4H z06T1MZ#M)|iciUxTj#j7x%sEL8RHf&Z=_*s1j1}?{=4sx0HKBi)xd`I=46?jM(XlZ zSJ=d?4pWSX`i(_~asayB*`fD;eQ`tTvi zjXGkV)_9z-$Fw8HW*>2FoS>7@aIpoD>kk0gSkGR*Y=jJ70P*_KG`w5^33W|6t=c{l zU5I^8b}%P_96X;D04noCE`|qG?8Nl6Qj!G<(f+^|gH3vVZcK-W#`h?qmzMBUJNTKM zz!|WEpM-)@V4)a)L8JrM(>5fSa{F((3~UIUFtgYM5A8`JHSPwlrDpgNfE1?J`nokI zC#Pv4ffqOx@j&sPzkK-^s79w6udpzc7vk={V9S>O&oW6Kno)}haz&eFQS|kJPEDsO zEVo~%!=-V1mSkZ*nC}BTi4#H!N`4b8v7^ohk14YN-UBeaN6ya9MaB2BWxT~CBwCa? zi3^MHR9U>(nDsSZ_jb&p6{ z)Ei*uEnb%Ju_37OMTso8_d7$p^E;#(0u!8`dwH@O31kY2i&Mv@Rn19p-By_$8jSCd zo9*0;+2XJZ7iu+ejs=J`>3V9T2)K;ugJPaiG1!`9SM913QVTr+=Nw2O&v-S+*PP1D z5A7vP9f&5r;IVXyZ7sMbeM@%%XZKKx?^>BE0I6q|#ZiagT4s?&;8vHYp`^q_$*N9j zAs%@z0W)pK`Taa7Fz~}2F}!iWY28AA?(Mh(Moew{X!*eC_VBAB0LX&#UrS4&yk`$H zzFvMT5&IFqUP)o(ze_&2^AgFpFak;-wxWta(9Gv(lkoFm$6&X7~p+sy5 za?*=I>`YQIVjCU=j-MHlS-apR!teR;kdLP3hH<6F#75%?MXooa{ zpco%9Nh_FGSP+j^_h54t4AhTE9coVPU%4+_xWJbvZSxX=n78Q_UUJaG z8Ag}{V&nrcg5&I<{}Ag`Dw6KJQd~%1#dK65%N-a40uDf$x8nkI1dLA+W8tu7i3Ab% z`LQZN8jt;N!ZOzwezNKk6YsC6*TRJ<7Dvjse*8dtSh4>6Vf8Ov`2ip(_~?ko4VEVm zrb5H$sdtFAhgpLy=71r??f!oQZctTG1H~2;K#&B`qyPx^_VzxcH8V2?-;T$ThK+2{qYi+%bJw6T{8t4fj?HeFM z%-WSvV1d6>Wng0qiH)U1fj5g->#&n0Cw|0{(}h~KE-o%eZx1o(My%@zu4}h;b{c~u z5IWtTMh-wT?{p)?(;C2~z@&#BSDBfXP+6HQ7sz@eJN{*9Jj#449U>iBdZnU%-e_5* zCXF~xe*}fJ0j6QD?QF|s^p5iH`g(8hy}O~Fg2hQBdYtQU!5ZBWHwc>sbVeVFCkiYB z#G3=T=CMH|KSLDDgMxgD`sIzQa;OePRwjZOI)8{V1ab}?lvto^LrD_EX)@`Hn0*p| z9hIJ`i*<&)5il5EIxD9ZRj3Jk(+NhM6ucGaiQE*0Cz34b(DFRl(S#o~^Elib#iCxQ z3+0!rNG^2IdI;s52k#QPE$`pIk9CRzx%=V6hs@4`f`XN2(f$KI#sGNSrK zV6Xbl9IEPf-8qWQ2kSua!oCn9E!T}E8so`2pQ0CW{uX6!DCT?j^uUrK_x%Nm{rPM; zqFEtraz#4NoxPvMGS`S*a~&}fJa3XaVDyWCD(M1MVh!zB1d6ELx1WQ#APz>*Jm?>d zV)IF8pW4~G(2~s*CV6Ef2^~Xp2SM-d#o!_C#L9{sn1?NV?W&X!}Rfs$xwMkv}CW-6qs4Jo7x zuf>oA)YZ(+*3MB1K}Y7Z!~UB6!=)UIR!y0j61M|e@a4^NI3<&_Q@6Gu))itK3W$lA%t$^NOsXXL`i z*?6TNNNYKZP($i3UR?9yzVKl{8VtpqBRaI=f5Cr=Qp^>^E@GEKKSEmC-t9LJm=^yw zoz9p4tm=6!+}I2p&kB!R$>k?V!A(?$a=nBQXQwonj(?i~Rn-|Lq?IcBTtTvf(Mh)5Lbly^!)Ee_meB>ANJdZU6Ic z4VpOQ5lxn8A}=VGgY3h3?8Ko%$h9|*4o=deaIc(~x`%L1a^(?O`Z6Yt16H8F9a7Q` z+%vSVYt<$q^@tF8GkvVOB&B5uTls!ZkvFV~EZIX8bHG3VZ5Y;^Tn39uJ137Ni^|<6 z8rg2Qz*dlKxN-iwlc98#X4EHJq_h|#kEHnf?%!Di+&hpMNQM_Si}mpQ-(vs$cl>HO zHK-OMM75aOV=TP^0dX!T&YupMMQIqqUbY!iesEb;A~pbCpnnnGz*1$#>uYct33A$^ zJw^snT>atTlY=5JZsJ1!(u?O8yZ{v?(4PzOz!7?WKFkstIRBp)gN4-Fb8+*(9Vdnw zN=!Cgh_McanckmIw!75DEI}&3gE`Oj_qB)emyiUPHU2$R$dIziu#(IsGmQ7V*bt5tH0bz!DIf~J&O~D z3P7L_ya@~lNc$%s*&zR)2cg57`0-W1;XYU&eHvhIC&^qT);N!1O$SEjfAmN|`S;X4f z(P4CQxU;?Zuk~$sfWP=PwEAk*ac9Mc1V0+o0o}oF>Jy3Nm;5V?6C)#<;FK7+$N$H1 zxQK_B1oV8w^Xx=utBnh~9K;k9t-yrkp~?fPw$tpQog)A365*QTwUs@EJ}^TuE2FN3 z9(I~wO+Z0I8e=;L;Afy}!HS3mu?@wN9f~wEHo?Hf6$ZlNGw^h3q$Lv0OdG8D5jDT2 zXF~M?$z?3)T>$p}W)Iq`w&aXPsvZ#Nf>+9*_SLW^4l2CdJ%vS|A(?}(xe0CQ(94-< z)XOgHOlbQw1RzQBA_@B$f{^DynI?}qF2c@DEUcxz9^l`5A0pDmVvduM$l)J3wkDL@ z=(09y*q`2;=SOCFM6l-b&)mGvDLBCXl74N?kmtg z5j;PoCIRcOfxwz6eb_=tXzk65w6r_1kSC?ZrkXg}u|MAt6B{E)k)3t(j#sP6eR3!T zhzT&nN{c#tbNq(;3b5ZN!iXM#kEmeWOF@w0zaRPeAFK~UfTZ7%!&?l=>~oaTjCl-s zhljvv|L&0sicJjJ5@rCChN1=77Mq9XH+et=E4g*PPBIRHpg9CK&R4Ud_#epo?^YkTR1VuF?f4+tJydTIb%AnV(1@H}hlc|j@rsbw3VJ_WM3sZXO zb{N)REY8f%0&M_)MAPA)G9jc`Y{dDw%4p09sN-Ny-+>XCBGwq_B0(dKR!C?B$f5FV;{yXVX^`}|Ak9q z0K`f*P9R*n>Wxi30WUH_H)thv&-bpP z|6V;weqGi)pNZk8L^2ZdJS@nDA709_}cqG|^?WpeL?xiF-)W1jCx zY?FIz-&&>P9q3`^uW&KVCCz};u={Rqz(+h1;xu;$S`@2J^~m8qgrjUUrw=GkwG0Trob}Uf>xe8i4l)$Hf^(XM6U_c@qm)g1ZPzYRCu)Jgb z-KBMWF@`y>a&dQrBR6C`KVT4#9`D%zLXEa z5DzB$*qf!SE#HE`@Pver7>(abw?;=tIbzz;?ja>5CGF*jk`2EyG1jMY*sm?Vx^eNd z+82}hcW}*=4gySMt)t}*g2pZ-mZRnZkDP!jAo9!&963tiH(!tjG;%w)ee0MNaf!v; zW3GrJfU;dej9XRgqrTVy{sRhecwR`0>tuHr&Fl&GsQJ+7A?P}5u)#QOrX-N|9E>F( zBY()Gn?*4Zaaw&Qix(LU3ZaBMT5~ro%b?o{h7<-&%T0!>Xn#vg^n$>S2BvOV zvBD#Aw9Ey)D@v_&|6XILrTg5K{}Qp;Gx!2I3oNqb@6zfkKI|AQI%E zO*HO#CJf#$8oW*f$OuyvC1M{xq}NrYKJwMx9`>&C#$cx~vi)FZt`h0*ABQBy&70Ed z>NioIr&|flZEZrvah9Xy9MI-P+Q1OE%bMT(`NB81&fFf=j&6M)UtO4cny7LMbwhFy z2PTSBATFW7(Gg#C{7^ejADfPjPC0vR!DYiUS5hL=lpU3f)aTH{OnF(X9-x}g2$BM6 zhe0ml#s?Ev;n@{13*{O?PuuYa2ZOzV;r%p!(|P6pAwY~0g<+?;&V){wy4Z&}FoEtZ zOo#=u%1Fd26J%p)W>;dLSC}ODth>8=8T30a2H+KN8MWQId$%D^GQfW;UlLFE;KeyQ zFMfm1(SRYpGz}mHt?a_B>sTE$n~rTCisO9p>^qInpfNHkP0N}xu-KJh_=BK`(5 zF5vv5Aey|O>j~zvgMrM7*ozrg92IKOfvn~tTs5DZmeVqrx?@%i?x=Jaj* zp9vU#Kr472h9yZOf&%G2Of5D%V6Wk|o0El^K1%{m-Drk&7?jh4{uN=StVAr>su(YT zRrg9cu%e8NjqLzQ>>|LS`Wj2wUdl$x^UQk*70I-QDbFTbA_?@t5h;G_ll5hgf(KK9 zYhEjI9b)$GB9Gcxvd3OZRm=OWBV z{-Sak`4z}kJwLH1kvzu4@@{i!ZwO+qyAfl;C{6B80>knT22HPHGI z(cmOP9>6e{U@0fD&1GPDz~?Si&$M57gFR(wo6^R3r+_i+V$DU0>maF)pr$gT*Vd4+ zH7YG%f4-Ozr3lxvi|o;?E?k!MypP-;@he&T_F$)6hapbwG&_WC_NHf&L>x`fbC12a zbM_bo@Yv_9K})-vjIf5^H&GP*&PvZupQDmze)RsI2k0t

sFLO0yX2FUHbtTFFQ> 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 bdx~RgvK*~7l9mGP)=hjsLkDvc9QqLd7 literal 0 HcmV?d00001 diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqrt_c4_fxx.png b/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqrt_c4_fxx.png new file mode 100644 index 0000000000000000000000000000000000000000..220b925ca0f7fa10d0b02b059c980bb237fae6de GIT binary patch literal 33319 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 literal 0 HcmV?d00001 diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst index cf5ebfb5899..87b30390136 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst @@ -85,3 +85,28 @@ These figures show the sgnsqr(x) function compared to the smooth approximation s .. image:: figs/sgnsqr_fxx.png + +sgnsqrt_c4(x) +~~~~~~~~~~~~ + +This function is a signed square root approximation defined as: + +.. math:: + + \text{sgnsqr}(x) = \begin{cases} + \text{sgn}(x)|x|^{0.5} & \text{if } |x| \ge 0.1 \\ + \sum_{i=0}^{11} c_i x^i & \text{if } |x| < 0.1 + \end{cases} + +This function is $C^4$ smooth. The region :math:`-0.1 < x < 0.1` is replaced by an 11th order polynomial approximates that :math:`\text{sgn}(x)x^2`. The approximate function has a well behaved derivatives at :math:`x=0`. If you need to use this function with very small numbers and high accuracy is important, you can scale the argument up (e.g. :math:`\text{sgnsqr\_c4}(sx)/s^2`). + +These figures show the signed square root function compared to the smooth approximation sgnsqr_c4(x). + +.. image:: figs/sgnsqrt_err.png + +.. image:: figs/sgnsqrt_f.png + +.. image:: figs/sgnsqrt_fx.png + +.. image:: figs/sgnsqrt_fxx.png + diff --git a/pyomo/contrib/external_functions/src/functions.cpp b/pyomo/contrib/external_functions/src/functions.cpp index 3f151a7f2e0..f3754f72423 100644 --- a/pyomo/contrib/external_functions/src/functions.cpp +++ b/pyomo/contrib/external_functions/src/functions.cpp @@ -114,6 +114,57 @@ extern real sgnsqr_c4(arglist *al) { return y; } + +extern real sgnsqrt_c4(arglist *al) { + real x = al->ra[al->at[0]]; + const real c[] = { + 0.0, + 5.1186281462197964, + -5.115907697472721e-13, + -409.490251697574, + -2.4253192047278085e-12, + 34124.18764146428, + 3.827043323720301e-09, + -1574962.506529117, + -2.7353306479626024e-07, + 30109577.330703676, + 6.383782391594595e-06, + }; + const real r = 0.1; + real y = 0; + unsigned char i = 0; + + if(fabs(x) < r){ + for(i=0; i<11; ++i){ + y += c[i] * pow(x, i); + } + if (al->derivs!=NULL) { + al->derivs[0] = 0; + for(i=1; i<11; ++i){ + al->derivs[0] += c[i] * i * pow(x, i - 1); + } + } + if (al->hes!=NULL) { + al->hes[0] = 0; + for(i=2; i<11; ++i){ + al->hes[0] += c[i] * i * (i - 1) * pow(x, i - 2); + } + } + } + else{ + y = copysign(sqrt(fabs(x)), x); + if (al->derivs!=NULL) { + al->derivs[0] = 1.0 / 2.0 / sqrt(fabs(x)); + } + if (al->hes!=NULL) { + al->hes[0] = -copysign(1.0/4.0*pow(fabs(x), -1.5), x); + } + } + + return y; +} + + // Register external functions defined in this library with the ASL void funcadd(AmplExports *ae){ // Arguments for addfunc (this is not fully detailed; see funcadd.h) @@ -146,4 +197,11 @@ void funcadd(AmplExports *ae){ 1, NULL ); + addfunc( + "sgnsqrt_c4", + (rfunc)sgnsqrt_c4, + FUNCADD_REAL_VALUED, + 1, + NULL + ); } From f4fb50ac5163c52c12f94e9ead486bf17fd13739 Mon Sep 17 00:00:00 2001 From: Eslick Date: Mon, 7 Jul 2025 14:12:37 -0400 Subject: [PATCH 09/34] Minor test formatting --- pyomo/contrib/external_functions/tests/test_functions.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pyomo/contrib/external_functions/tests/test_functions.py b/pyomo/contrib/external_functions/tests/test_functions.py index acb5c395aa8..62a51d46010 100644 --- a/pyomo/contrib/external_functions/tests/test_functions.py +++ b/pyomo/contrib/external_functions/tests/test_functions.py @@ -20,9 +20,9 @@ @unittest.skipUnless(flib, 'Could not find the "external" library') +@unittest.skipIf(is_pypy, "Cannot evaluate external functions under pypy") class TestAMPLExternalFunction(unittest.TestCase): - @unittest.skipIf(is_pypy, "Cannot evaluate external functions under pypy") def test_eval_sqnsqr_function_fgh(self): m = pyo.ConcreteModel() m.tf = pyo.ExternalFunction(library=flib, function="sgnsqr") @@ -36,8 +36,7 @@ def test_eval_sqnsqr_function_fgh(self): self.assertAlmostEqual(f, -4) self.assertStructuredAlmostEqual(g, [4]) self.assertStructuredAlmostEqual(h, [-2]) - - @unittest.skipIf(is_pypy, "Cannot evaluate external functions under pypy") + def test_eval_sqnsqr_c4_function_fgh(self): m = pyo.ConcreteModel() m.tf = pyo.ExternalFunction(library=flib, function="sgnsqr_c4") @@ -70,7 +69,6 @@ def test_eval_sqnsqr_c4_function_fgh(self): self.assertStructuredAlmostEqual(g1, g2) self.assertStructuredAlmostEqual(h1, h2) - @unittest.skipIf(is_pypy, "Cannot evaluate external functions under pypy") def test_eval_sinc_function_fgh(self): m = pyo.ConcreteModel() m.tf = pyo.ExternalFunction(library=flib, function="sinc") From a74351cbbd7d94d87724ab6f89f64527c20fdf52 Mon Sep 17 00:00:00 2001 From: Eslick Date: Mon, 7 Jul 2025 14:17:33 -0400 Subject: [PATCH 10/34] Test formatting and sqrt test --- .../tests/test_functions.py | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/pyomo/contrib/external_functions/tests/test_functions.py b/pyomo/contrib/external_functions/tests/test_functions.py index 62a51d46010..5c77e815a12 100644 --- a/pyomo/contrib/external_functions/tests/test_functions.py +++ b/pyomo/contrib/external_functions/tests/test_functions.py @@ -36,7 +36,7 @@ def test_eval_sqnsqr_function_fgh(self): self.assertAlmostEqual(f, -4) self.assertStructuredAlmostEqual(g, [4]) self.assertStructuredAlmostEqual(h, [-2]) - + def test_eval_sqnsqr_c4_function_fgh(self): m = pyo.ConcreteModel() m.tf = pyo.ExternalFunction(library=flib, function="sgnsqr_c4") @@ -100,3 +100,35 @@ def test_eval_sinc_function_fgh(self): self.assertAlmostEqual(f1, f2) self.assertStructuredAlmostEqual(g1, g2) self.assertStructuredAlmostEqual(h1, h2) + + def test_eval_sqnsqrt_c4_function_fgh(self): + m = pyo.ConcreteModel() + m.tf = pyo.ExternalFunction(library=flib, function="sgnsqrt_c4") + + f, g, h = m.tf.evaluate_fgh((4,)) + self.assertEqual(f, 2) + self.assertEqual(g, [0.5 * 4 ** (-0.5)]) + self.assertEqual(h, [-0.25 * 4 ** (-3 / 2)]) + + f, g, h = m.tf.evaluate_fgh((-4,)) + self.assertAlmostEqual(f, -2) + self.assertStructuredAlmostEqual(g, [0.5 * 4 ** (-0.5)]) + self.assertStructuredAlmostEqual(h, [0.25 * 4 ** (-3 / 2)]) + + dx = 1e-9 + x = 0.1 + + f1, g1, h1 = m.tf.evaluate_fgh((x + dx,)) + f2, g2, h2 = m.tf.evaluate_fgh((x - dx,)) + self.assertAlmostEqual(f1, f2) + self.assertStructuredAlmostEqual(g1, g2) + self.assertStructuredAlmostEqual(h1, h2) + + dx = 1e-9 + x = -0.1 + + f1, g1, h1 = m.tf.evaluate_fgh((x + dx,)) + f2, g2, h2 = m.tf.evaluate_fgh((x - dx,)) + self.assertAlmostEqual(f1, f2) + self.assertStructuredAlmostEqual(g1, g2) + self.assertStructuredAlmostEqual(h1, h2) From a0f92faf7fbd0665ebab34d63abb51f4c524107f Mon Sep 17 00:00:00 2001 From: John Eslick Date: Tue, 8 Jul 2025 08:54:33 -0400 Subject: [PATCH 11/34] Update index.rst --- .../modeling_utils/external_functions/index.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst index 87b30390136..db81d4f23c8 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst @@ -102,11 +102,11 @@ This function is $C^4$ smooth. The region :math:`-0.1 < x < 0.1` is replaced by These figures show the signed square root function compared to the smooth approximation sgnsqr_c4(x). -.. image:: figs/sgnsqrt_err.png +.. image:: figs/sgnsqrt_c4_err.png -.. image:: figs/sgnsqrt_f.png +.. image:: figs/sgnsqrt_c4_f.png -.. image:: figs/sgnsqrt_fx.png +.. image:: figs/sgnsqrt_c4_fx.png -.. image:: figs/sgnsqrt_fxx.png +.. image:: figs/sgnsqrt_c4_fxx.png From 16be3370734520484cbe4911ac77804492e50ef9 Mon Sep 17 00:00:00 2001 From: John Eslick Date: Wed, 9 Jul 2025 10:02:42 -0400 Subject: [PATCH 12/34] Fix copy-paste error in doc --- .../explanation/modeling_utils/external_functions/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst index db81d4f23c8..36e01296acb 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst @@ -98,7 +98,7 @@ This function is a signed square root approximation defined as: \sum_{i=0}^{11} c_i x^i & \text{if } |x| < 0.1 \end{cases} -This function is $C^4$ smooth. The region :math:`-0.1 < x < 0.1` is replaced by an 11th order polynomial approximates that :math:`\text{sgn}(x)x^2`. The approximate function has a well behaved derivatives at :math:`x=0`. If you need to use this function with very small numbers and high accuracy is important, you can scale the argument up (e.g. :math:`\text{sgnsqr\_c4}(sx)/s^2`). +This function is $C^4$ smooth. The region :math:`-0.1 < x < 0.1` is replaced by an 11th order polynomial approximates that :math:`\text{sgn}(x)|x|^{0.5}`. The approximate function has a well behaved derivatives at :math:`x=0`. If you need to use this function with very small numbers and high accuracy is important, you can scale the argument up (e.g. :math:`\text{sgnsqrt\_c4}(sx)/s^{0.5}`). These figures show the signed square root function compared to the smooth approximation sgnsqr_c4(x). From 5b86b0ad9ea981cd197e263b71a1b67eaa33303d Mon Sep 17 00:00:00 2001 From: Eslick Date: Thu, 24 Jul 2025 08:45:42 -0400 Subject: [PATCH 13/34] Rename function library --- .../__init__.py | 0 .../build.py | 12 ++++++------ .../plugins.py | 4 ++-- .../src/CMakeLists.txt | 16 ++++++++-------- .../src/functions.cpp | 0 .../tests/__init__.py | 0 .../tests/test_functions.py | 2 +- pyomo/environ/__init__.py | 2 +- pyomo/environ/tests/test_package_layout.py | 2 +- setup.py | 2 ++ 10 files changed, 21 insertions(+), 19 deletions(-) rename pyomo/contrib/{external_functions => libaslfunctions}/__init__.py (100%) rename pyomo/contrib/{external_functions => libaslfunctions}/build.py (74%) rename pyomo/contrib/{external_functions => libaslfunctions}/plugins.py (79%) rename pyomo/contrib/{external_functions => libaslfunctions}/src/CMakeLists.txt (75%) rename pyomo/contrib/{external_functions => libaslfunctions}/src/functions.cpp (100%) rename pyomo/contrib/{external_functions => libaslfunctions}/tests/__init__.py (100%) rename pyomo/contrib/{external_functions => libaslfunctions}/tests/test_functions.py (99%) diff --git a/pyomo/contrib/external_functions/__init__.py b/pyomo/contrib/libaslfunctions/__init__.py similarity index 100% rename from pyomo/contrib/external_functions/__init__.py rename to pyomo/contrib/libaslfunctions/__init__.py diff --git a/pyomo/contrib/external_functions/build.py b/pyomo/contrib/libaslfunctions/build.py similarity index 74% rename from pyomo/contrib/external_functions/build.py rename to pyomo/contrib/libaslfunctions/build.py index b0ac309c428..4e81fd347ff 100644 --- a/pyomo/contrib/external_functions/build.py +++ b/pyomo/contrib/libaslfunctions/build.py @@ -13,20 +13,20 @@ from pyomo.common.cmake_builder import build_cmake_project -def build_external_functions(user_args=[], parallel=None): +def build_libaslfunctions(user_args=[], parallel=None): return build_cmake_project( targets=["src"], - package_name="external_functions", - description="Useful external function", + package_name="libaslfunctions", + description="Useful AMPL external functions", user_args=["-DBUILD_AMPLASL_IF_NEEDED=ON"] + user_args, parallel=parallel, ) -class ExternalFunctionBuilder(object): +class LibASLFunctionsBuilder(object): def __call__(self, parallel): - return build_external_functions(parallel=parallel) + return build_libaslfunctions(parallel=parallel) if __name__ == "__main__": - build_external_functions(sys.argv[1:]) + build_libaslfunctions(sys.argv[1:]) diff --git a/pyomo/contrib/external_functions/plugins.py b/pyomo/contrib/libaslfunctions/plugins.py similarity index 79% rename from pyomo/contrib/external_functions/plugins.py rename to pyomo/contrib/libaslfunctions/plugins.py index 7481bb8d597..9db53e70d6e 100644 --- a/pyomo/contrib/external_functions/plugins.py +++ b/pyomo/contrib/libaslfunctions/plugins.py @@ -10,8 +10,8 @@ # ___________________________________________________________________________ from pyomo.common.extensions import ExtensionBuilderFactory -from pyomo.contrib.external_functions.build import ExternalFunctionBuilder +from pyomo.contrib.libaslfunctions.build import LibASLFunctionsBuilder def load(): - ExtensionBuilderFactory.register("external_functions")(ExternalFunctionBuilder) + ExtensionBuilderFactory.register("libaslfunctions")(LibASLFunctionsBuilder) diff --git a/pyomo/contrib/external_functions/src/CMakeLists.txt b/pyomo/contrib/libaslfunctions/src/CMakeLists.txt similarity index 75% rename from pyomo/contrib/external_functions/src/CMakeLists.txt rename to pyomo/contrib/libaslfunctions/src/CMakeLists.txt index 42f570cb71c..4da3fe49bc5 100644 --- a/pyomo/contrib/external_functions/src/CMakeLists.txt +++ b/pyomo/contrib/libaslfunctions/src/CMakeLists.txt @@ -12,7 +12,7 @@ cmake_minimum_required(VERSION 3.0...3.31) # This was developed against CMake 3.0, and appears to comply with 3.5 -PROJECT( external_functions ) +PROJECT( libaslfunctions ) INCLUDE( "${CMAKE_CURRENT_SOURCE_DIR}/../../ampl_function_demo/src/FindASL.cmake") @@ -22,22 +22,22 @@ OPTION(BUILD_EXTERNAL_FCN_LIBRARY "Build the ASL external function example library" ON) IF( BUILD_EXTERNAL_FCN_LIBRARY ) - ADD_LIBRARY( external_functions SHARED "functions.cpp" ) - TARGET_LINK_LIBRARIES( external_functions + ADD_LIBRARY( libaslfunctions SHARED "functions.cpp" ) + TARGET_LINK_LIBRARIES( libaslfunctions PUBLIC ${ASL_LIBRARY} ${CMAKE_DL_LIBS}) - TARGET_INCLUDE_DIRECTORIES( external_functions + TARGET_INCLUDE_DIRECTORIES( libaslfunctions PUBLIC ${ASL_INCLUDE_DIR} INTERFACE . ) # If you need a CPP directive defined when building the library (e.g., # for managing __declspec(dllimport) under Windows) uncomment the # following: - #TARGET_COMPILE_DEFINITIONS( external_functions PRIVATE BUILDING_ASL_DEMO ) - #SET_TARGET_PROPERTIES( external_functions PROPERTIES ENABLE_EXPORTS 1 ) - INSTALL( TARGETS external_functions LIBRARY DESTINATION lib + #TARGET_COMPILE_DEFINITIONS( libaslfunctions PRIVATE BUILDING_ASL_DEMO ) + #SET_TARGET_PROPERTIES( libaslfunctions PROPERTIES ENABLE_EXPORTS 1 ) + INSTALL( TARGETS libaslfunctions LIBRARY DESTINATION lib RUNTIME DESTINATION lib ) IF( BUILD_AMPLASL ) # If we are building AMPL/asl (from FindASL), it is possible that we # are linking against it, so we will add the appropriate dependency - add_dependencies(external_functions ampl_asl) + add_dependencies(libaslfunctions ampl_asl) ENDIF() ENDIF() diff --git a/pyomo/contrib/external_functions/src/functions.cpp b/pyomo/contrib/libaslfunctions/src/functions.cpp similarity index 100% rename from pyomo/contrib/external_functions/src/functions.cpp rename to pyomo/contrib/libaslfunctions/src/functions.cpp diff --git a/pyomo/contrib/external_functions/tests/__init__.py b/pyomo/contrib/libaslfunctions/tests/__init__.py similarity index 100% rename from pyomo/contrib/external_functions/tests/__init__.py rename to pyomo/contrib/libaslfunctions/tests/__init__.py diff --git a/pyomo/contrib/external_functions/tests/test_functions.py b/pyomo/contrib/libaslfunctions/tests/test_functions.py similarity index 99% rename from pyomo/contrib/external_functions/tests/test_functions.py rename to pyomo/contrib/libaslfunctions/tests/test_functions.py index 5c77e815a12..1f0bf209e0a 100644 --- a/pyomo/contrib/external_functions/tests/test_functions.py +++ b/pyomo/contrib/libaslfunctions/tests/test_functions.py @@ -15,7 +15,7 @@ import pyomo.common.unittest as unittest from pyomo.common.fileutils import find_library -flib = find_library("external_functions") +flib = find_library("libaslfunctions") is_pypy = platform.python_implementation().lower().startswith("pypy") diff --git a/pyomo/environ/__init__.py b/pyomo/environ/__init__.py index e11fb313ace..f0d41138bb7 100644 --- a/pyomo/environ/__init__.py +++ b/pyomo/environ/__init__.py @@ -41,7 +41,7 @@ def _do_import(pkg_name): 'pyomo.contrib.cp', 'pyomo.contrib.cspline_external', 'pyomo.contrib.example', - 'pyomo.contrib.external_functions', + 'pyomo.contrib.libaslfunctions', 'pyomo.contrib.fme', 'pyomo.contrib.gdp_bounds', 'pyomo.contrib.gdpopt', diff --git a/pyomo/environ/tests/test_package_layout.py b/pyomo/environ/tests/test_package_layout.py index 5c828844163..b11359010fe 100644 --- a/pyomo/environ/tests/test_package_layout.py +++ b/pyomo/environ/tests/test_package_layout.py @@ -39,7 +39,7 @@ join('contrib', 'ampl_function_demo', 'src'), join('contrib', 'appsi', 'cmodel', 'src'), join('contrib', 'cspline_external', 'src'), - join('contrib', 'external_functions', 'src'), + join('contrib', 'libaslfunctions', 'src'), join('contrib', 'simplification', 'ginac', 'src'), join('contrib', 'pynumero', 'src'), join('core', 'tests', 'data', 'baselines'), diff --git a/setup.py b/setup.py index 043b0a637f2..0e1b3ef324f 100644 --- a/setup.py +++ b/setup.py @@ -275,6 +275,8 @@ def __ne__(self, other): package_data={ "pyomo.contrib.ampl_function_demo": ["src/*"], "pyomo.contrib.appsi.cmodel": ["src/*"], + "pyomo.contrib.cspline_external": ["src/*"], + "pyomo.contrib.libaslfunctions": ["src/*"], "pyomo.contrib.mcpp": ["*.cpp"], "pyomo.contrib.pynumero": ['src/*', 'src/tests/*'], "pyomo.contrib.viewer": ["*.ui"], From 5d63a1047c5a6c517ef7f6527c8a7c4cec70adee Mon Sep 17 00:00:00 2001 From: John Eslick Date: Thu, 24 Jul 2025 08:46:50 -0400 Subject: [PATCH 14/34] Update doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst Co-authored-by: Bethany Nicholson --- .../explanation/modeling_utils/external_functions/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst index 36e01296acb..16c743d67fd 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst @@ -75,7 +75,7 @@ This function is defined as: \sum_{i=0}^{11} c_i x^i & \text{if } |x| < 0.1 \end{cases} -This function is $C^4$ smooth. The region :math:`-0.1 < x < 0.1` is replaced by an 11th order polynomial approximates that :math:`\text{sgn}(x)x^2`. The approximate function has a well behaved derivatives at :math:`x=0`. If you need to use this function with very small numbers and high accuracy is important, you can scale the argument up (e.g. :math:`\text{sgnsqr\_c4}(sx)/s^2`). +This function is :math:`C^4` smooth. The region :math:`-0.1 < x < 0.1` is replaced by an 11th order polynomial that approximates :math:`\text{sgn}(x)x^2`. This function has well behaved derivatives at :math:`x=0`. If you need to use this function with very small numbers and high accuracy is important, you can scale the argument up (e.g. :math:`\text{sgnsqr_c4}(sx)/s^2`). These figures show the sgnsqr(x) function compared to the smooth approximation sgnsqr_c4(x). From 4db46dcea0c60c329e19c928ed578bc80b733d55 Mon Sep 17 00:00:00 2001 From: John Eslick Date: Thu, 24 Jul 2025 08:47:05 -0400 Subject: [PATCH 15/34] Update doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst Co-authored-by: Bethany Nicholson --- .../explanation/modeling_utils/external_functions/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst index 16c743d67fd..f2081f06fe6 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst @@ -70,7 +70,7 @@ This function is defined as: .. math:: - \text{sgnsqr}(x) = \begin{cases} + \text{sgnsqr_c4}(x) = \begin{cases} \text{sgn}(x)x^2 & \text{if } |x| \ge 0.1 \\ \sum_{i=0}^{11} c_i x^i & \text{if } |x| < 0.1 \end{cases} From e2302d07808bd9f39f6a8f475c9b46a8d5f1c245 Mon Sep 17 00:00:00 2001 From: John Eslick Date: Thu, 24 Jul 2025 08:47:17 -0400 Subject: [PATCH 16/34] Update doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst Co-authored-by: Bethany Nicholson --- .../explanation/modeling_utils/external_functions/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst index f2081f06fe6..36c0676f963 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst @@ -60,7 +60,7 @@ This function is defined as: \text{sgnsqr}(x) = \text{sgn}(x)x^2 -This function is only $C^1$ smooth because at 0 the second derivative is undefined and the jumps from -2 to 2. +This function is only :math:`C^1` smooth because at 0 the second derivative is undefined and the jumps from -2 to 2. sgnsqr_c4(x) ~~~~~~~~~~~~ From dcc87f22cb3249383fa9d84c702c82c5bacb2ef1 Mon Sep 17 00:00:00 2001 From: John Eslick Date: Thu, 24 Jul 2025 08:47:24 -0400 Subject: [PATCH 17/34] Update doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst Co-authored-by: Bethany Nicholson --- .../explanation/modeling_utils/external_functions/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst index 36c0676f963..4c212535c3d 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst @@ -93,7 +93,7 @@ This function is a signed square root approximation defined as: .. math:: - \text{sgnsqr}(x) = \begin{cases} + \text{sgnsqrt_c4}(x) = \begin{cases} \text{sgn}(x)|x|^{0.5} & \text{if } |x| \ge 0.1 \\ \sum_{i=0}^{11} c_i x^i & \text{if } |x| < 0.1 \end{cases} From a7f533353595c70bb1e388f1a2e0f2fd6dcbefad Mon Sep 17 00:00:00 2001 From: John Eslick Date: Thu, 24 Jul 2025 08:47:41 -0400 Subject: [PATCH 18/34] Update doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst Co-authored-by: Bethany Nicholson --- .../explanation/modeling_utils/external_functions/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst index 4c212535c3d..5d260bba4ae 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst @@ -98,7 +98,7 @@ This function is a signed square root approximation defined as: \sum_{i=0}^{11} c_i x^i & \text{if } |x| < 0.1 \end{cases} -This function is $C^4$ smooth. The region :math:`-0.1 < x < 0.1` is replaced by an 11th order polynomial approximates that :math:`\text{sgn}(x)|x|^{0.5}`. The approximate function has a well behaved derivatives at :math:`x=0`. If you need to use this function with very small numbers and high accuracy is important, you can scale the argument up (e.g. :math:`\text{sgnsqrt\_c4}(sx)/s^{0.5}`). +This function is :math:`C^4` smooth. The region :math:`-0.1 < x < 0.1` is replaced by an 11th order polynomial that approximates :math:`\text{sgn}(x)|x|^{0.5}`. This function has well behaved derivatives at :math:`x=0`. If you need to use this function with very small numbers and high accuracy is important, you can scale the argument up (e.g. :math:`\text{sgnsqrt_c4}(sx)/s^{0.5}`). These figures show the signed square root function compared to the smooth approximation sgnsqr_c4(x). From 1c3c6f285693772f263cef86170e9fd8fea94e7f Mon Sep 17 00:00:00 2001 From: John Eslick Date: Thu, 24 Jul 2025 08:47:53 -0400 Subject: [PATCH 19/34] Update doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst Co-authored-by: Bethany Nicholson --- .../explanation/modeling_utils/external_functions/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst index 5d260bba4ae..5558abab70c 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst @@ -100,7 +100,7 @@ This function is a signed square root approximation defined as: This function is :math:`C^4` smooth. The region :math:`-0.1 < x < 0.1` is replaced by an 11th order polynomial that approximates :math:`\text{sgn}(x)|x|^{0.5}`. This function has well behaved derivatives at :math:`x=0`. If you need to use this function with very small numbers and high accuracy is important, you can scale the argument up (e.g. :math:`\text{sgnsqrt_c4}(sx)/s^{0.5}`). -These figures show the signed square root function compared to the smooth approximation sgnsqr_c4(x). +These figures show the signed square root function compared to the smooth approximation sgnsqrt_c4(x). .. image:: figs/sgnsqrt_c4_err.png From 5e4cb24188509f7fce14024f3f66a302ad3523b1 Mon Sep 17 00:00:00 2001 From: Eslick Date: Thu, 24 Jul 2025 08:54:08 -0400 Subject: [PATCH 20/34] Doc update --- .../figs/sgnsqr_f.png | Bin .../figs/sgnsqr_fx.png | Bin .../figs/sgnsqr_fxx.png | Bin .../figs/sgnsqrt_c4_err.png | Bin .../figs/sgnsqrt_c4_f.png | Bin .../figs/sgnsqrt_c4_fx.png | Bin .../figs/sgnsqrt_c4_fxx.png | Bin .../figs/sinc_f.png | Bin .../figs/sinc_fx.png | Bin .../figs/sinc_fxx.png | Bin .../index.rst | 16 ++++++++-------- 11 files changed, 8 insertions(+), 8 deletions(-) rename doc/OnlineDocs/explanation/modeling_utils/{external_functions => libaslfunctions}/figs/sgnsqr_f.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{external_functions => libaslfunctions}/figs/sgnsqr_fx.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{external_functions => libaslfunctions}/figs/sgnsqr_fxx.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{external_functions => libaslfunctions}/figs/sgnsqrt_c4_err.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{external_functions => libaslfunctions}/figs/sgnsqrt_c4_f.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{external_functions => libaslfunctions}/figs/sgnsqrt_c4_fx.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{external_functions => libaslfunctions}/figs/sgnsqrt_c4_fxx.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{external_functions => libaslfunctions}/figs/sinc_f.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{external_functions => libaslfunctions}/figs/sinc_fx.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{external_functions => libaslfunctions}/figs/sinc_fxx.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{external_functions => libaslfunctions}/index.rst (91%) diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqr_f.png b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqr_f.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqr_f.png rename to doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqr_f.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqr_fx.png b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqr_fx.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqr_fx.png rename to doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqr_fx.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqr_fxx.png b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqr_fxx.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqr_fxx.png rename to doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqr_fxx.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqrt_c4_err.png b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqrt_c4_err.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqrt_c4_err.png rename to doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqrt_c4_err.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqrt_c4_f.png b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqrt_c4_f.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqrt_c4_f.png rename to doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqrt_c4_f.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqrt_c4_fx.png b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqrt_c4_fx.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqrt_c4_fx.png rename to doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqrt_c4_fx.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqrt_c4_fxx.png b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqrt_c4_fxx.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sgnsqrt_c4_fxx.png rename to doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqrt_c4_fxx.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sinc_f.png b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sinc_f.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sinc_f.png rename to doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sinc_f.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sinc_fx.png b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sinc_fx.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sinc_fx.png rename to doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sinc_fx.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sinc_fxx.png b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sinc_fxx.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/external_functions/figs/sinc_fxx.png rename to doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sinc_fxx.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst similarity index 91% rename from doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst rename to doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst index 5558abab70c..a1031c7a792 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/external_functions/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst @@ -1,15 +1,15 @@ -External Functions -================== +libaslfunctions +=============== -Pyomo provides a set of AMPL user-defined functions that commonly occur but cannot be easily written as Pyomo expressions. +Pyomo provides a set of AMPL user-defined functions that commonly occur but cannot be easily written as Pyomo expressions. -Using These External Functions ------------------------------- +Using These AMPL External Functions +----------------------------------- Build ~~~~~ -You must build the Pyomo extensions to use these functions. Run ``pyomo build-extensions`` in the terminal and make sure the ``external_functions`` build status is "ok." +You must build the Pyomo extensions to use these functions. Run ``pyomo build-extensions`` in the terminal and make sure the ``libaslfunctions`` build status is "ok." Example ~~~~~~~ @@ -18,8 +18,8 @@ Example >>> import pyomo.environ as pyo >>> from pyomo.common.fileutils import find_library - >>> flib = find_library("external_functions") - >>> m = pyo.ConcreteModel(name = 'ExternalFunctions') + >>> flib = find_library("libaslfunctions") + >>> m = pyo.ConcreteModel(name = 'AMPLExternalFunctions') >>> m.sinc = pyo.ExternalFunction(library=flib, function="sinc") >>> m.x = pyo.Var() >>> m.z = pyo.Var() From 0eac3811b11ff87608305b0dc3d78a09784f9210 Mon Sep 17 00:00:00 2001 From: Eslick Date: Thu, 24 Jul 2025 08:55:06 -0400 Subject: [PATCH 21/34] doc update 2 --- doc/OnlineDocs/explanation/modeling_utils/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/OnlineDocs/explanation/modeling_utils/index.rst b/doc/OnlineDocs/explanation/modeling_utils/index.rst index dd12b1ec53e..b9a8c47211a 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/index.rst @@ -8,7 +8,7 @@ Modeling Utilities latex_printer preprocessing scaling - external_functions/index + libaslfunctions/index .. From 1d45a863a97cbfb4a6248e86e6394061af4b525b Mon Sep 17 00:00:00 2001 From: Bethany Nicholson Date: Sat, 26 Jul 2025 09:30:54 -0600 Subject: [PATCH 22/34] Reordering to keep in alphabetical order --- pyomo/environ/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyomo/environ/__init__.py b/pyomo/environ/__init__.py index f0d41138bb7..da34c3d45a4 100644 --- a/pyomo/environ/__init__.py +++ b/pyomo/environ/__init__.py @@ -41,12 +41,12 @@ def _do_import(pkg_name): 'pyomo.contrib.cp', 'pyomo.contrib.cspline_external', 'pyomo.contrib.example', - 'pyomo.contrib.libaslfunctions', 'pyomo.contrib.fme', 'pyomo.contrib.gdp_bounds', 'pyomo.contrib.gdpopt', 'pyomo.contrib.gjh', 'pyomo.contrib.gdp_bounds', + 'pyomo.contrib.libaslfunctions', 'pyomo.contrib.mcpp', 'pyomo.contrib.mindtpy', 'pyomo.contrib.multistart', From 857b48bec19e757c08c23972f3a332fb65388033 Mon Sep 17 00:00:00 2001 From: Bethany Nicholson Date: Sat, 26 Jul 2025 22:25:52 -0600 Subject: [PATCH 23/34] Fixing section header in index.rst --- .../explanation/modeling_utils/libaslfunctions/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst index a1031c7a792..dfc7dfbfce2 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst @@ -87,7 +87,7 @@ These figures show the sgnsqr(x) function compared to the smooth approximation s sgnsqrt_c4(x) -~~~~~~~~~~~~ +~~~~~~~~~~~~~ This function is a signed square root approximation defined as: From 66161c23c051fe1b4e2f230c0b00594927339d37 Mon Sep 17 00:00:00 2001 From: John Eslick Date: Mon, 28 Jul 2025 08:47:28 -0400 Subject: [PATCH 24/34] Update index.rst fix underscore --- .../explanation/modeling_utils/libaslfunctions/index.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst index dfc7dfbfce2..13d4e296c0e 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst @@ -70,12 +70,12 @@ This function is defined as: .. math:: - \text{sgnsqr_c4}(x) = \begin{cases} + \text{sgnsqr\_c4}(x) = \begin{cases} \text{sgn}(x)x^2 & \text{if } |x| \ge 0.1 \\ \sum_{i=0}^{11} c_i x^i & \text{if } |x| < 0.1 \end{cases} -This function is :math:`C^4` smooth. The region :math:`-0.1 < x < 0.1` is replaced by an 11th order polynomial that approximates :math:`\text{sgn}(x)x^2`. This function has well behaved derivatives at :math:`x=0`. If you need to use this function with very small numbers and high accuracy is important, you can scale the argument up (e.g. :math:`\text{sgnsqr_c4}(sx)/s^2`). +This function is :math:`C^4` smooth. The region :math:`-0.1 < x < 0.1` is replaced by an 11th order polynomial that approximates :math:`\text{sgn}(x)x^2`. This function has well behaved derivatives at :math:`x=0`. If you need to use this function with very small numbers and high accuracy is important, you can scale the argument up (e.g. :math:`\text{sgnsqr\_c4}(sx)/s^2`). These figures show the sgnsqr(x) function compared to the smooth approximation sgnsqr_c4(x). @@ -93,12 +93,12 @@ This function is a signed square root approximation defined as: .. math:: - \text{sgnsqrt_c4}(x) = \begin{cases} + \text{sgnsqrt\_c4}(x) = \begin{cases} \text{sgn}(x)|x|^{0.5} & \text{if } |x| \ge 0.1 \\ \sum_{i=0}^{11} c_i x^i & \text{if } |x| < 0.1 \end{cases} -This function is :math:`C^4` smooth. The region :math:`-0.1 < x < 0.1` is replaced by an 11th order polynomial that approximates :math:`\text{sgn}(x)|x|^{0.5}`. This function has well behaved derivatives at :math:`x=0`. If you need to use this function with very small numbers and high accuracy is important, you can scale the argument up (e.g. :math:`\text{sgnsqrt_c4}(sx)/s^{0.5}`). +This function is :math:`C^4` smooth. The region :math:`-0.1 < x < 0.1` is replaced by an 11th order polynomial that approximates :math:`\text{sgn}(x)|x|^{0.5}`. This function has well behaved derivatives at :math:`x=0`. If you need to use this function with very small numbers and high accuracy is important, you can scale the argument up (e.g. :math:`\text{sgnsqrt\_c4}(sx)/s^{0.5}`). These figures show the signed square root function compared to the smooth approximation sgnsqrt_c4(x). From f8e48572544ce9aa5a98a8e9fe17a5d8c9dae06d Mon Sep 17 00:00:00 2001 From: Miranda Mundt <55767766+mrmundt@users.noreply.github.com> Date: Thu, 31 Jul 2025 11:12:47 -0600 Subject: [PATCH 25/34] Attempt to fix math in index.rst --- .../modeling_utils/libaslfunctions/index.rst | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst index 13d4e296c0e..adb61e1e939 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst @@ -35,10 +35,11 @@ This function is defined as: .. math:: - \text{sinc}(x) = \begin{cases} - \sin(x) / x & \text{if } x \neq 0 \\ - 1 & \text{if } x = 0 - \end{cases} + \operatorname{sgnsqr\_c4}(x) = + \begin{cases} + \operatorname{sgn}(x)\,x^2 & \text{if } |x| \ge 0.1, \\ + \displaystyle\sum_{i=0}^{11} c_i x^i & \text{if } |x| < 0.1 + \end{cases} In this implementation, the region :math:`-0.1 < x < 0.1` is replaced by a Taylor series with enough terms that the function should be at least :math:`C^2` smooth. The difference between the function and the Tayor series is near the limits of machine precision, about :math:`1 \times 10^{-16}` for the function value, :math:`1 \times 10^{-16}` for the first derivative, and :math:`1 \times 10^{-14}` for the second derivative. @@ -70,10 +71,11 @@ This function is defined as: .. math:: - \text{sgnsqr\_c4}(x) = \begin{cases} - \text{sgn}(x)x^2 & \text{if } |x| \ge 0.1 \\ - \sum_{i=0}^{11} c_i x^i & \text{if } |x| < 0.1 - \end{cases} + \operatorname{sgnsqrt\_c4}(x) = + \begin{cases} + \operatorname{sgn}(x)\,|x|^{0.5} & \text{if } |x| \ge 0.1, \\ + \displaystyle\sum_{i=0}^{11} c_i x^i & \text{if } |x| < 0.1 + \end{cases} This function is :math:`C^4` smooth. The region :math:`-0.1 < x < 0.1` is replaced by an 11th order polynomial that approximates :math:`\text{sgn}(x)x^2`. This function has well behaved derivatives at :math:`x=0`. If you need to use this function with very small numbers and high accuracy is important, you can scale the argument up (e.g. :math:`\text{sgnsqr\_c4}(sx)/s^2`). From fc0a021c139d2254992715ad943f4a096d6429b6 Mon Sep 17 00:00:00 2001 From: Miranda Mundt <55767766+mrmundt@users.noreply.github.com> Date: Thu, 31 Jul 2025 11:16:14 -0600 Subject: [PATCH 26/34] Edited wrong lines in index.rst --- .../modeling_utils/libaslfunctions/index.rst | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst index adb61e1e939..2df362e677e 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst @@ -35,11 +35,10 @@ This function is defined as: .. math:: - \operatorname{sgnsqr\_c4}(x) = - \begin{cases} - \operatorname{sgn}(x)\,x^2 & \text{if } |x| \ge 0.1, \\ - \displaystyle\sum_{i=0}^{11} c_i x^i & \text{if } |x| < 0.1 - \end{cases} + \text{sinc}(x) = \begin{cases} + \sin(x) / x & \text{if } x \neq 0 \\ + 1 & \text{if } x = 0 + \end{cases} In this implementation, the region :math:`-0.1 < x < 0.1` is replaced by a Taylor series with enough terms that the function should be at least :math:`C^2` smooth. The difference between the function and the Tayor series is near the limits of machine precision, about :math:`1 \times 10^{-16}` for the function value, :math:`1 \times 10^{-16}` for the first derivative, and :math:`1 \times 10^{-14}` for the second derivative. @@ -71,9 +70,9 @@ This function is defined as: .. math:: - \operatorname{sgnsqrt\_c4}(x) = + \operatorname{sgnsqr\_c4}(x) = \begin{cases} - \operatorname{sgn}(x)\,|x|^{0.5} & \text{if } |x| \ge 0.1, \\ + \operatorname{sgn}(x)\,x^2 & \text{if } |x| \ge 0.1, \\ \displaystyle\sum_{i=0}^{11} c_i x^i & \text{if } |x| < 0.1 \end{cases} @@ -95,10 +94,11 @@ This function is a signed square root approximation defined as: .. math:: - \text{sgnsqrt\_c4}(x) = \begin{cases} - \text{sgn}(x)|x|^{0.5} & \text{if } |x| \ge 0.1 \\ - \sum_{i=0}^{11} c_i x^i & \text{if } |x| < 0.1 - \end{cases} + \operatorname{sgnsqrt\_c4}(x) = + \begin{cases} + \operatorname{sgn}(x)\,|x|^{0.5} & \text{if } |x| \ge 0.1, \\ + \displaystyle\sum_{i=0}^{11} c_i x^i & \text{if } |x| < 0.1 + \end{cases} This function is :math:`C^4` smooth. The region :math:`-0.1 < x < 0.1` is replaced by an 11th order polynomial that approximates :math:`\text{sgn}(x)|x|^{0.5}`. This function has well behaved derivatives at :math:`x=0`. If you need to use this function with very small numbers and high accuracy is important, you can scale the argument up (e.g. :math:`\text{sgnsqrt\_c4}(sx)/s^{0.5}`). From f2476b26796806f11122368c0f111e3b97104139 Mon Sep 17 00:00:00 2001 From: Miranda Mundt <55767766+mrmundt@users.noreply.github.com> Date: Thu, 31 Jul 2025 11:27:36 -0600 Subject: [PATCH 27/34] Missed two instances --- .../explanation/modeling_utils/libaslfunctions/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst index 2df362e677e..535f062fe24 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst @@ -76,7 +76,7 @@ This function is defined as: \displaystyle\sum_{i=0}^{11} c_i x^i & \text{if } |x| < 0.1 \end{cases} -This function is :math:`C^4` smooth. The region :math:`-0.1 < x < 0.1` is replaced by an 11th order polynomial that approximates :math:`\text{sgn}(x)x^2`. This function has well behaved derivatives at :math:`x=0`. If you need to use this function with very small numbers and high accuracy is important, you can scale the argument up (e.g. :math:`\text{sgnsqr\_c4}(sx)/s^2`). +This function is :math:`C^4` smooth. The region :math:`-0.1 < x < 0.1` is replaced by an 11th order polynomial that approximates :math:`\text{sgn}(x)x^2`. This function has well behaved derivatives at :math:`x=0`. If you need to use this function with very small numbers and high accuracy is important, you can scale the argument up (e.g. :math:`\operatorname{sgnsqr\_c4}(sx)/s^2`). These figures show the sgnsqr(x) function compared to the smooth approximation sgnsqr_c4(x). @@ -100,7 +100,7 @@ This function is a signed square root approximation defined as: \displaystyle\sum_{i=0}^{11} c_i x^i & \text{if } |x| < 0.1 \end{cases} -This function is :math:`C^4` smooth. The region :math:`-0.1 < x < 0.1` is replaced by an 11th order polynomial that approximates :math:`\text{sgn}(x)|x|^{0.5}`. This function has well behaved derivatives at :math:`x=0`. If you need to use this function with very small numbers and high accuracy is important, you can scale the argument up (e.g. :math:`\text{sgnsqrt\_c4}(sx)/s^{0.5}`). +This function is :math:`C^4` smooth. The region :math:`-0.1 < x < 0.1` is replaced by an 11th order polynomial that approximates :math:`\text{sgn}(x)|x|^{0.5}`. This function has well behaved derivatives at :math:`x=0`. If you need to use this function with very small numbers and high accuracy is important, you can scale the argument up (e.g. :math:`\operatorname{sgnsqrt\_c4}(sx)/s^{0.5}`). These figures show the signed square root function compared to the smooth approximation sgnsqrt_c4(x). From ee7d13f943d135e5d06985f4f0433f80fc546381 Mon Sep 17 00:00:00 2001 From: Miranda Mundt Date: Thu, 31 Jul 2025 15:28:24 -0600 Subject: [PATCH 28/34] Print out skip reasons --- .github/workflows/test_branches.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_branches.yml b/.github/workflows/test_branches.yml index b5574811521..3ef8e6ffda5 100644 --- a/.github/workflows/test_branches.yml +++ b/.github/workflows/test_branches.yml @@ -723,7 +723,7 @@ jobs: if: ${{ matrix.mpi == 0 && matrix.category != 'notests' }} run: | export PATH=$PYOMO_PATH - $PYTHON_EXE -m pytest -v \ + $PYTHON_EXE -m pytest -v -rs \ -W ignore::Warning ${{matrix.category}} \ pyomo `pwd`/pyomo-model-libraries \ `pwd`/examples `pwd`/doc --junitxml="TEST-pyomo.xml" From 936ec3c82207e5dc7f2e1aede3dbab833959b370 Mon Sep 17 00:00:00 2001 From: Miranda Mundt Date: Thu, 31 Jul 2025 16:04:06 -0600 Subject: [PATCH 29/34] Flipped - should be not flib --- pyomo/contrib/libaslfunctions/tests/test_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyomo/contrib/libaslfunctions/tests/test_functions.py b/pyomo/contrib/libaslfunctions/tests/test_functions.py index 1f0bf209e0a..f7fc3bbd6a2 100644 --- a/pyomo/contrib/libaslfunctions/tests/test_functions.py +++ b/pyomo/contrib/libaslfunctions/tests/test_functions.py @@ -19,7 +19,7 @@ is_pypy = platform.python_implementation().lower().startswith("pypy") -@unittest.skipUnless(flib, 'Could not find the "external" library') +@unittest.skipUnless(not flib, 'Could not find the "external" library') @unittest.skipIf(is_pypy, "Cannot evaluate external functions under pypy") class TestAMPLExternalFunction(unittest.TestCase): From ca1b43ab0cfe5175e7c5acf6908714b58d4f4b81 Mon Sep 17 00:00:00 2001 From: Miranda Mundt Date: Thu, 31 Jul 2025 16:18:55 -0600 Subject: [PATCH 30/34] Rename the library --- .../explanation/modeling_utils/index.rst | 2 +- .../modeling_utils/libaslfunctions/index.rst | 6 +++--- .../__init__.py | 0 .../build.py | 8 ++++---- .../plugins.py | 4 ++-- .../src/CMakeLists.txt | 16 ++++++++-------- .../src/functions.cpp | 0 .../tests/__init__.py | 0 .../tests/test_functions.py | 4 ++-- pyomo/environ/__init__.py | 2 +- pyomo/environ/tests/test_package_layout.py | 2 +- setup.py | 2 +- 12 files changed, 23 insertions(+), 23 deletions(-) rename pyomo/contrib/{libaslfunctions => asl_functions_lib}/__init__.py (100%) rename pyomo/contrib/{libaslfunctions => asl_functions_lib}/build.py (82%) rename pyomo/contrib/{libaslfunctions => asl_functions_lib}/plugins.py (79%) rename pyomo/contrib/{libaslfunctions => asl_functions_lib}/src/CMakeLists.txt (75%) rename pyomo/contrib/{libaslfunctions => asl_functions_lib}/src/functions.cpp (100%) rename pyomo/contrib/{libaslfunctions => asl_functions_lib}/tests/__init__.py (100%) rename pyomo/contrib/{libaslfunctions => asl_functions_lib}/tests/test_functions.py (97%) diff --git a/doc/OnlineDocs/explanation/modeling_utils/index.rst b/doc/OnlineDocs/explanation/modeling_utils/index.rst index b9a8c47211a..2ab196ea196 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/index.rst @@ -8,7 +8,7 @@ Modeling Utilities latex_printer preprocessing scaling - libaslfunctions/index + asl_functions_lib/index .. diff --git a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst index 535f062fe24..c6546fbb828 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst @@ -1,4 +1,4 @@ -libaslfunctions +asl_functions_lib =============== Pyomo provides a set of AMPL user-defined functions that commonly occur but cannot be easily written as Pyomo expressions. @@ -9,7 +9,7 @@ Using These AMPL External Functions Build ~~~~~ -You must build the Pyomo extensions to use these functions. Run ``pyomo build-extensions`` in the terminal and make sure the ``libaslfunctions`` build status is "ok." +You must build the Pyomo extensions to use these functions. Run ``pyomo build-extensions`` in the terminal and make sure the ``asl_functions_lib`` build status is "ok." Example ~~~~~~~ @@ -18,7 +18,7 @@ Example >>> import pyomo.environ as pyo >>> from pyomo.common.fileutils import find_library - >>> flib = find_library("libaslfunctions") + >>> flib = find_library("asl_functions_lib") >>> m = pyo.ConcreteModel(name = 'AMPLExternalFunctions') >>> m.sinc = pyo.ExternalFunction(library=flib, function="sinc") >>> m.x = pyo.Var() diff --git a/pyomo/contrib/libaslfunctions/__init__.py b/pyomo/contrib/asl_functions_lib/__init__.py similarity index 100% rename from pyomo/contrib/libaslfunctions/__init__.py rename to pyomo/contrib/asl_functions_lib/__init__.py diff --git a/pyomo/contrib/libaslfunctions/build.py b/pyomo/contrib/asl_functions_lib/build.py similarity index 82% rename from pyomo/contrib/libaslfunctions/build.py rename to pyomo/contrib/asl_functions_lib/build.py index 4e81fd347ff..ebc8d5c1aef 100644 --- a/pyomo/contrib/libaslfunctions/build.py +++ b/pyomo/contrib/asl_functions_lib/build.py @@ -13,10 +13,10 @@ from pyomo.common.cmake_builder import build_cmake_project -def build_libaslfunctions(user_args=[], parallel=None): +def build_asl_functions_lib(user_args=[], parallel=None): return build_cmake_project( targets=["src"], - package_name="libaslfunctions", + package_name="asl_functions_lib", description="Useful AMPL external functions", user_args=["-DBUILD_AMPLASL_IF_NEEDED=ON"] + user_args, parallel=parallel, @@ -25,8 +25,8 @@ def build_libaslfunctions(user_args=[], parallel=None): class LibASLFunctionsBuilder(object): def __call__(self, parallel): - return build_libaslfunctions(parallel=parallel) + return build_asl_functions_lib(parallel=parallel) if __name__ == "__main__": - build_libaslfunctions(sys.argv[1:]) + build_asl_functions_lib(sys.argv[1:]) diff --git a/pyomo/contrib/libaslfunctions/plugins.py b/pyomo/contrib/asl_functions_lib/plugins.py similarity index 79% rename from pyomo/contrib/libaslfunctions/plugins.py rename to pyomo/contrib/asl_functions_lib/plugins.py index 9db53e70d6e..a29d3362e95 100644 --- a/pyomo/contrib/libaslfunctions/plugins.py +++ b/pyomo/contrib/asl_functions_lib/plugins.py @@ -10,8 +10,8 @@ # ___________________________________________________________________________ from pyomo.common.extensions import ExtensionBuilderFactory -from pyomo.contrib.libaslfunctions.build import LibASLFunctionsBuilder +from pyomo.contrib.asl_functions_lib.build import LibASLFunctionsBuilder def load(): - ExtensionBuilderFactory.register("libaslfunctions")(LibASLFunctionsBuilder) + ExtensionBuilderFactory.register("asl_functions_lib")(LibASLFunctionsBuilder) diff --git a/pyomo/contrib/libaslfunctions/src/CMakeLists.txt b/pyomo/contrib/asl_functions_lib/src/CMakeLists.txt similarity index 75% rename from pyomo/contrib/libaslfunctions/src/CMakeLists.txt rename to pyomo/contrib/asl_functions_lib/src/CMakeLists.txt index 4da3fe49bc5..822231dae99 100644 --- a/pyomo/contrib/libaslfunctions/src/CMakeLists.txt +++ b/pyomo/contrib/asl_functions_lib/src/CMakeLists.txt @@ -12,7 +12,7 @@ cmake_minimum_required(VERSION 3.0...3.31) # This was developed against CMake 3.0, and appears to comply with 3.5 -PROJECT( libaslfunctions ) +PROJECT( asl_functions_lib ) INCLUDE( "${CMAKE_CURRENT_SOURCE_DIR}/../../ampl_function_demo/src/FindASL.cmake") @@ -22,22 +22,22 @@ OPTION(BUILD_EXTERNAL_FCN_LIBRARY "Build the ASL external function example library" ON) IF( BUILD_EXTERNAL_FCN_LIBRARY ) - ADD_LIBRARY( libaslfunctions SHARED "functions.cpp" ) - TARGET_LINK_LIBRARIES( libaslfunctions + ADD_LIBRARY( asl_functions_lib SHARED "functions.cpp" ) + TARGET_LINK_LIBRARIES( asl_functions_lib PUBLIC ${ASL_LIBRARY} ${CMAKE_DL_LIBS}) - TARGET_INCLUDE_DIRECTORIES( libaslfunctions + TARGET_INCLUDE_DIRECTORIES( asl_functions_lib PUBLIC ${ASL_INCLUDE_DIR} INTERFACE . ) # If you need a CPP directive defined when building the library (e.g., # for managing __declspec(dllimport) under Windows) uncomment the # following: - #TARGET_COMPILE_DEFINITIONS( libaslfunctions PRIVATE BUILDING_ASL_DEMO ) - #SET_TARGET_PROPERTIES( libaslfunctions PROPERTIES ENABLE_EXPORTS 1 ) - INSTALL( TARGETS libaslfunctions LIBRARY DESTINATION lib + #TARGET_COMPILE_DEFINITIONS( asl_functions_lib PRIVATE BUILDING_ASL_DEMO ) + #SET_TARGET_PROPERTIES( asl_functions_lib PROPERTIES ENABLE_EXPORTS 1 ) + INSTALL( TARGETS asl_functions_lib LIBRARY DESTINATION lib RUNTIME DESTINATION lib ) IF( BUILD_AMPLASL ) # If we are building AMPL/asl (from FindASL), it is possible that we # are linking against it, so we will add the appropriate dependency - add_dependencies(libaslfunctions ampl_asl) + add_dependencies(asl_functions_lib ampl_asl) ENDIF() ENDIF() diff --git a/pyomo/contrib/libaslfunctions/src/functions.cpp b/pyomo/contrib/asl_functions_lib/src/functions.cpp similarity index 100% rename from pyomo/contrib/libaslfunctions/src/functions.cpp rename to pyomo/contrib/asl_functions_lib/src/functions.cpp diff --git a/pyomo/contrib/libaslfunctions/tests/__init__.py b/pyomo/contrib/asl_functions_lib/tests/__init__.py similarity index 100% rename from pyomo/contrib/libaslfunctions/tests/__init__.py rename to pyomo/contrib/asl_functions_lib/tests/__init__.py diff --git a/pyomo/contrib/libaslfunctions/tests/test_functions.py b/pyomo/contrib/asl_functions_lib/tests/test_functions.py similarity index 97% rename from pyomo/contrib/libaslfunctions/tests/test_functions.py rename to pyomo/contrib/asl_functions_lib/tests/test_functions.py index f7fc3bbd6a2..b5228354d15 100644 --- a/pyomo/contrib/libaslfunctions/tests/test_functions.py +++ b/pyomo/contrib/asl_functions_lib/tests/test_functions.py @@ -15,11 +15,11 @@ import pyomo.common.unittest as unittest from pyomo.common.fileutils import find_library -flib = find_library("libaslfunctions") +flib = find_library("asl_functions_lib") is_pypy = platform.python_implementation().lower().startswith("pypy") -@unittest.skipUnless(not flib, 'Could not find the "external" library') +@unittest.skipIf(not flib, 'Could not find the "asl_functions_lib" library') @unittest.skipIf(is_pypy, "Cannot evaluate external functions under pypy") class TestAMPLExternalFunction(unittest.TestCase): diff --git a/pyomo/environ/__init__.py b/pyomo/environ/__init__.py index da34c3d45a4..016e1ff708e 100644 --- a/pyomo/environ/__init__.py +++ b/pyomo/environ/__init__.py @@ -46,7 +46,7 @@ def _do_import(pkg_name): 'pyomo.contrib.gdpopt', 'pyomo.contrib.gjh', 'pyomo.contrib.gdp_bounds', - 'pyomo.contrib.libaslfunctions', + 'pyomo.contrib.asl_functions_lib', 'pyomo.contrib.mcpp', 'pyomo.contrib.mindtpy', 'pyomo.contrib.multistart', diff --git a/pyomo/environ/tests/test_package_layout.py b/pyomo/environ/tests/test_package_layout.py index b11359010fe..f11ea08df2e 100644 --- a/pyomo/environ/tests/test_package_layout.py +++ b/pyomo/environ/tests/test_package_layout.py @@ -39,7 +39,7 @@ join('contrib', 'ampl_function_demo', 'src'), join('contrib', 'appsi', 'cmodel', 'src'), join('contrib', 'cspline_external', 'src'), - join('contrib', 'libaslfunctions', 'src'), + join('contrib', 'asl_functions_lib', 'src'), join('contrib', 'simplification', 'ginac', 'src'), join('contrib', 'pynumero', 'src'), join('core', 'tests', 'data', 'baselines'), diff --git a/setup.py b/setup.py index 0e1b3ef324f..4b19d489139 100644 --- a/setup.py +++ b/setup.py @@ -276,7 +276,7 @@ def __ne__(self, other): "pyomo.contrib.ampl_function_demo": ["src/*"], "pyomo.contrib.appsi.cmodel": ["src/*"], "pyomo.contrib.cspline_external": ["src/*"], - "pyomo.contrib.libaslfunctions": ["src/*"], + "pyomo.contrib.asl_functions_lib": ["src/*"], "pyomo.contrib.mcpp": ["*.cpp"], "pyomo.contrib.pynumero": ['src/*', 'src/tests/*'], "pyomo.contrib.viewer": ["*.ui"], From ac3a579a716f33810281ef18451fa95e40075e17 Mon Sep 17 00:00:00 2001 From: Miranda Mundt Date: Thu, 31 Jul 2025 16:57:25 -0600 Subject: [PATCH 31/34] Correct docs for new name --- .github/workflows/test_branches.yml | 2 +- .../figs/sgnsqr_f.png | Bin .../figs/sgnsqr_fx.png | Bin .../figs/sgnsqr_fxx.png | Bin .../figs/sgnsqrt_c4_err.png | Bin .../figs/sgnsqrt_c4_f.png | Bin .../figs/sgnsqrt_c4_fx.png | Bin .../figs/sgnsqrt_c4_fxx.png | Bin .../figs/sinc_f.png | Bin .../figs/sinc_fx.png | Bin .../figs/sinc_fxx.png | Bin .../index.rst | 2 +- 12 files changed, 2 insertions(+), 2 deletions(-) rename doc/OnlineDocs/explanation/modeling_utils/{libaslfunctions => asl_functions_lib}/figs/sgnsqr_f.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{libaslfunctions => asl_functions_lib}/figs/sgnsqr_fx.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{libaslfunctions => asl_functions_lib}/figs/sgnsqr_fxx.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{libaslfunctions => asl_functions_lib}/figs/sgnsqrt_c4_err.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{libaslfunctions => asl_functions_lib}/figs/sgnsqrt_c4_f.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{libaslfunctions => asl_functions_lib}/figs/sgnsqrt_c4_fx.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{libaslfunctions => asl_functions_lib}/figs/sgnsqrt_c4_fxx.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{libaslfunctions => asl_functions_lib}/figs/sinc_f.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{libaslfunctions => asl_functions_lib}/figs/sinc_fx.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{libaslfunctions => asl_functions_lib}/figs/sinc_fxx.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{libaslfunctions => asl_functions_lib}/index.rst (99%) diff --git a/.github/workflows/test_branches.yml b/.github/workflows/test_branches.yml index 3ef8e6ffda5..317df363c04 100644 --- a/.github/workflows/test_branches.yml +++ b/.github/workflows/test_branches.yml @@ -723,7 +723,7 @@ jobs: if: ${{ matrix.mpi == 0 && matrix.category != 'notests' }} run: | export PATH=$PYOMO_PATH - $PYTHON_EXE -m pytest -v -rs \ + $PYTHON_EXE -m pytest -v \ -W ignore::Warning ${{matrix.category}} \ pyomo `pwd`/pyomo-model-libraries \ `pwd`/examples `pwd`/doc --junitxml="TEST-pyomo.xml" diff --git a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqr_f.png b/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqr_f.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqr_f.png rename to doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqr_f.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqr_fx.png b/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqr_fx.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqr_fx.png rename to doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqr_fx.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqr_fxx.png b/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqr_fxx.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqr_fxx.png rename to doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqr_fxx.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqrt_c4_err.png b/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqrt_c4_err.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqrt_c4_err.png rename to doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqrt_c4_err.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqrt_c4_f.png b/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqrt_c4_f.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqrt_c4_f.png rename to doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqrt_c4_f.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqrt_c4_fx.png b/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqrt_c4_fx.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqrt_c4_fx.png rename to doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqrt_c4_fx.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqrt_c4_fxx.png b/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqrt_c4_fxx.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sgnsqrt_c4_fxx.png rename to doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqrt_c4_fxx.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sinc_f.png b/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sinc_f.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sinc_f.png rename to doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sinc_f.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sinc_fx.png b/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sinc_fx.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sinc_fx.png rename to doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sinc_fx.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sinc_fxx.png b/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sinc_fxx.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/figs/sinc_fxx.png rename to doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sinc_fxx.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst b/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/index.rst similarity index 99% rename from doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst rename to doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/index.rst index c6546fbb828..c156fea7dc4 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/libaslfunctions/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/index.rst @@ -1,5 +1,5 @@ asl_functions_lib -=============== +================= Pyomo provides a set of AMPL user-defined functions that commonly occur but cannot be easily written as Pyomo expressions. From bf21a225490d248e818529fc4253e55274ff03e7 Mon Sep 17 00:00:00 2001 From: Miranda Mundt Date: Thu, 31 Jul 2025 16:59:11 -0600 Subject: [PATCH 32/34] Extra space --- .github/workflows/test_branches.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_branches.yml b/.github/workflows/test_branches.yml index 317df363c04..b5574811521 100644 --- a/.github/workflows/test_branches.yml +++ b/.github/workflows/test_branches.yml @@ -723,7 +723,7 @@ jobs: if: ${{ matrix.mpi == 0 && matrix.category != 'notests' }} run: | export PATH=$PYOMO_PATH - $PYTHON_EXE -m pytest -v \ + $PYTHON_EXE -m pytest -v \ -W ignore::Warning ${{matrix.category}} \ pyomo `pwd`/pyomo-model-libraries \ `pwd`/examples `pwd`/doc --junitxml="TEST-pyomo.xml" From 4e58993b05ebb0538db55e5f21243df740bb553f Mon Sep 17 00:00:00 2001 From: Eslick Date: Sat, 2 Aug 2025 11:41:45 -0400 Subject: [PATCH 33/34] Rerename library --- .../figs/sgnsqr_f.png | Bin .../figs/sgnsqr_fx.png | Bin .../figs/sgnsqr_fxx.png | Bin .../figs/sgnsqrt_c4_err.png | Bin .../figs/sgnsqrt_c4_f.png | Bin .../figs/sgnsqrt_c4_fx.png | Bin .../figs/sgnsqrt_c4_fxx.png | Bin .../figs/sinc_f.png | Bin .../figs/sinc_fx.png | Bin .../figs/sinc_fxx.png | Bin .../index.rst | 8 ++++---- .../explanation/modeling_utils/index.rst | 2 +- .../__init__.py | 0 .../build.py | 8 ++++---- .../plugins.py | 4 ++-- .../src/CMakeLists.txt | 16 ++++++++-------- .../src/functions.cpp | 0 .../tests/__init__.py | 0 .../tests/test_functions.py | 4 ++-- pyomo/environ/__init__.py | 2 +- pyomo/environ/tests/test_package_layout.py | 2 +- setup.py | 2 +- 22 files changed, 24 insertions(+), 24 deletions(-) rename doc/OnlineDocs/explanation/modeling_utils/{asl_functions_lib => aslfunctions}/figs/sgnsqr_f.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{asl_functions_lib => aslfunctions}/figs/sgnsqr_fx.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{asl_functions_lib => aslfunctions}/figs/sgnsqr_fxx.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{asl_functions_lib => aslfunctions}/figs/sgnsqrt_c4_err.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{asl_functions_lib => aslfunctions}/figs/sgnsqrt_c4_f.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{asl_functions_lib => aslfunctions}/figs/sgnsqrt_c4_fx.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{asl_functions_lib => aslfunctions}/figs/sgnsqrt_c4_fxx.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{asl_functions_lib => aslfunctions}/figs/sinc_f.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{asl_functions_lib => aslfunctions}/figs/sinc_fx.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{asl_functions_lib => aslfunctions}/figs/sinc_fxx.png (100%) rename doc/OnlineDocs/explanation/modeling_utils/{asl_functions_lib => aslfunctions}/index.rst (96%) rename pyomo/contrib/{asl_functions_lib => aslfunctions}/__init__.py (100%) rename pyomo/contrib/{asl_functions_lib => aslfunctions}/build.py (82%) rename pyomo/contrib/{asl_functions_lib => aslfunctions}/plugins.py (79%) rename pyomo/contrib/{asl_functions_lib => aslfunctions}/src/CMakeLists.txt (75%) rename pyomo/contrib/{asl_functions_lib => aslfunctions}/src/functions.cpp (100%) rename pyomo/contrib/{asl_functions_lib => aslfunctions}/tests/__init__.py (100%) rename pyomo/contrib/{asl_functions_lib => aslfunctions}/tests/test_functions.py (97%) diff --git a/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqr_f.png b/doc/OnlineDocs/explanation/modeling_utils/aslfunctions/figs/sgnsqr_f.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqr_f.png rename to doc/OnlineDocs/explanation/modeling_utils/aslfunctions/figs/sgnsqr_f.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqr_fx.png b/doc/OnlineDocs/explanation/modeling_utils/aslfunctions/figs/sgnsqr_fx.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqr_fx.png rename to doc/OnlineDocs/explanation/modeling_utils/aslfunctions/figs/sgnsqr_fx.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqr_fxx.png b/doc/OnlineDocs/explanation/modeling_utils/aslfunctions/figs/sgnsqr_fxx.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqr_fxx.png rename to doc/OnlineDocs/explanation/modeling_utils/aslfunctions/figs/sgnsqr_fxx.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqrt_c4_err.png b/doc/OnlineDocs/explanation/modeling_utils/aslfunctions/figs/sgnsqrt_c4_err.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqrt_c4_err.png rename to doc/OnlineDocs/explanation/modeling_utils/aslfunctions/figs/sgnsqrt_c4_err.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqrt_c4_f.png b/doc/OnlineDocs/explanation/modeling_utils/aslfunctions/figs/sgnsqrt_c4_f.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqrt_c4_f.png rename to doc/OnlineDocs/explanation/modeling_utils/aslfunctions/figs/sgnsqrt_c4_f.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqrt_c4_fx.png b/doc/OnlineDocs/explanation/modeling_utils/aslfunctions/figs/sgnsqrt_c4_fx.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqrt_c4_fx.png rename to doc/OnlineDocs/explanation/modeling_utils/aslfunctions/figs/sgnsqrt_c4_fx.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqrt_c4_fxx.png b/doc/OnlineDocs/explanation/modeling_utils/aslfunctions/figs/sgnsqrt_c4_fxx.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sgnsqrt_c4_fxx.png rename to doc/OnlineDocs/explanation/modeling_utils/aslfunctions/figs/sgnsqrt_c4_fxx.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sinc_f.png b/doc/OnlineDocs/explanation/modeling_utils/aslfunctions/figs/sinc_f.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sinc_f.png rename to doc/OnlineDocs/explanation/modeling_utils/aslfunctions/figs/sinc_f.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sinc_fx.png b/doc/OnlineDocs/explanation/modeling_utils/aslfunctions/figs/sinc_fx.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sinc_fx.png rename to doc/OnlineDocs/explanation/modeling_utils/aslfunctions/figs/sinc_fx.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sinc_fxx.png b/doc/OnlineDocs/explanation/modeling_utils/aslfunctions/figs/sinc_fxx.png similarity index 100% rename from doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/figs/sinc_fxx.png rename to doc/OnlineDocs/explanation/modeling_utils/aslfunctions/figs/sinc_fxx.png diff --git a/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/index.rst b/doc/OnlineDocs/explanation/modeling_utils/aslfunctions/index.rst similarity index 96% rename from doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/index.rst rename to doc/OnlineDocs/explanation/modeling_utils/aslfunctions/index.rst index c156fea7dc4..88adc675d3c 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/asl_functions_lib/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/aslfunctions/index.rst @@ -1,5 +1,5 @@ -asl_functions_lib -================= +aslfunctions +============ Pyomo provides a set of AMPL user-defined functions that commonly occur but cannot be easily written as Pyomo expressions. @@ -9,7 +9,7 @@ Using These AMPL External Functions Build ~~~~~ -You must build the Pyomo extensions to use these functions. Run ``pyomo build-extensions`` in the terminal and make sure the ``asl_functions_lib`` build status is "ok." +You must build the Pyomo extensions to use these functions. Run ``pyomo build-extensions`` in the terminal and make sure the ``aslfunctions`` build status is "ok." Example ~~~~~~~ @@ -18,7 +18,7 @@ Example >>> import pyomo.environ as pyo >>> from pyomo.common.fileutils import find_library - >>> flib = find_library("asl_functions_lib") + >>> flib = find_library("libaslfunctions") >>> m = pyo.ConcreteModel(name = 'AMPLExternalFunctions') >>> m.sinc = pyo.ExternalFunction(library=flib, function="sinc") >>> m.x = pyo.Var() diff --git a/doc/OnlineDocs/explanation/modeling_utils/index.rst b/doc/OnlineDocs/explanation/modeling_utils/index.rst index 2ab196ea196..c601e894279 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/index.rst @@ -8,7 +8,7 @@ Modeling Utilities latex_printer preprocessing scaling - asl_functions_lib/index + aslfunctions/index .. diff --git a/pyomo/contrib/asl_functions_lib/__init__.py b/pyomo/contrib/aslfunctions/__init__.py similarity index 100% rename from pyomo/contrib/asl_functions_lib/__init__.py rename to pyomo/contrib/aslfunctions/__init__.py diff --git a/pyomo/contrib/asl_functions_lib/build.py b/pyomo/contrib/aslfunctions/build.py similarity index 82% rename from pyomo/contrib/asl_functions_lib/build.py rename to pyomo/contrib/aslfunctions/build.py index ebc8d5c1aef..f7a99716f29 100644 --- a/pyomo/contrib/asl_functions_lib/build.py +++ b/pyomo/contrib/aslfunctions/build.py @@ -13,10 +13,10 @@ from pyomo.common.cmake_builder import build_cmake_project -def build_asl_functions_lib(user_args=[], parallel=None): +def build_aslfunctions(user_args=[], parallel=None): return build_cmake_project( targets=["src"], - package_name="asl_functions_lib", + package_name="aslfunctions", description="Useful AMPL external functions", user_args=["-DBUILD_AMPLASL_IF_NEEDED=ON"] + user_args, parallel=parallel, @@ -25,8 +25,8 @@ def build_asl_functions_lib(user_args=[], parallel=None): class LibASLFunctionsBuilder(object): def __call__(self, parallel): - return build_asl_functions_lib(parallel=parallel) + return build_aslfunctions(parallel=parallel) if __name__ == "__main__": - build_asl_functions_lib(sys.argv[1:]) + build_aslfunctions(sys.argv[1:]) diff --git a/pyomo/contrib/asl_functions_lib/plugins.py b/pyomo/contrib/aslfunctions/plugins.py similarity index 79% rename from pyomo/contrib/asl_functions_lib/plugins.py rename to pyomo/contrib/aslfunctions/plugins.py index a29d3362e95..8d464caea24 100644 --- a/pyomo/contrib/asl_functions_lib/plugins.py +++ b/pyomo/contrib/aslfunctions/plugins.py @@ -10,8 +10,8 @@ # ___________________________________________________________________________ from pyomo.common.extensions import ExtensionBuilderFactory -from pyomo.contrib.asl_functions_lib.build import LibASLFunctionsBuilder +from pyomo.contrib.aslfunctions.build import LibASLFunctionsBuilder def load(): - ExtensionBuilderFactory.register("asl_functions_lib")(LibASLFunctionsBuilder) + ExtensionBuilderFactory.register("aslfunctions")(LibASLFunctionsBuilder) diff --git a/pyomo/contrib/asl_functions_lib/src/CMakeLists.txt b/pyomo/contrib/aslfunctions/src/CMakeLists.txt similarity index 75% rename from pyomo/contrib/asl_functions_lib/src/CMakeLists.txt rename to pyomo/contrib/aslfunctions/src/CMakeLists.txt index 822231dae99..4e3e56d3f6d 100644 --- a/pyomo/contrib/asl_functions_lib/src/CMakeLists.txt +++ b/pyomo/contrib/aslfunctions/src/CMakeLists.txt @@ -12,7 +12,7 @@ cmake_minimum_required(VERSION 3.0...3.31) # This was developed against CMake 3.0, and appears to comply with 3.5 -PROJECT( asl_functions_lib ) +PROJECT( aslfunctions ) INCLUDE( "${CMAKE_CURRENT_SOURCE_DIR}/../../ampl_function_demo/src/FindASL.cmake") @@ -22,22 +22,22 @@ OPTION(BUILD_EXTERNAL_FCN_LIBRARY "Build the ASL external function example library" ON) IF( BUILD_EXTERNAL_FCN_LIBRARY ) - ADD_LIBRARY( asl_functions_lib SHARED "functions.cpp" ) - TARGET_LINK_LIBRARIES( asl_functions_lib + ADD_LIBRARY( aslfunctions SHARED "functions.cpp" ) + TARGET_LINK_LIBRARIES( aslfunctions PUBLIC ${ASL_LIBRARY} ${CMAKE_DL_LIBS}) - TARGET_INCLUDE_DIRECTORIES( asl_functions_lib + TARGET_INCLUDE_DIRECTORIES( aslfunctions PUBLIC ${ASL_INCLUDE_DIR} INTERFACE . ) # If you need a CPP directive defined when building the library (e.g., # for managing __declspec(dllimport) under Windows) uncomment the # following: - #TARGET_COMPILE_DEFINITIONS( asl_functions_lib PRIVATE BUILDING_ASL_DEMO ) - #SET_TARGET_PROPERTIES( asl_functions_lib PROPERTIES ENABLE_EXPORTS 1 ) - INSTALL( TARGETS asl_functions_lib LIBRARY DESTINATION lib + #TARGET_COMPILE_DEFINITIONS( aslfunctions PRIVATE BUILDING_ASL_DEMO ) + #SET_TARGET_PROPERTIES( aslfunctions PROPERTIES ENABLE_EXPORTS 1 ) + INSTALL( TARGETS aslfunctions LIBRARY DESTINATION lib RUNTIME DESTINATION lib ) IF( BUILD_AMPLASL ) # If we are building AMPL/asl (from FindASL), it is possible that we # are linking against it, so we will add the appropriate dependency - add_dependencies(asl_functions_lib ampl_asl) + add_dependencies(aslfunctions ampl_asl) ENDIF() ENDIF() diff --git a/pyomo/contrib/asl_functions_lib/src/functions.cpp b/pyomo/contrib/aslfunctions/src/functions.cpp similarity index 100% rename from pyomo/contrib/asl_functions_lib/src/functions.cpp rename to pyomo/contrib/aslfunctions/src/functions.cpp diff --git a/pyomo/contrib/asl_functions_lib/tests/__init__.py b/pyomo/contrib/aslfunctions/tests/__init__.py similarity index 100% rename from pyomo/contrib/asl_functions_lib/tests/__init__.py rename to pyomo/contrib/aslfunctions/tests/__init__.py diff --git a/pyomo/contrib/asl_functions_lib/tests/test_functions.py b/pyomo/contrib/aslfunctions/tests/test_functions.py similarity index 97% rename from pyomo/contrib/asl_functions_lib/tests/test_functions.py rename to pyomo/contrib/aslfunctions/tests/test_functions.py index b5228354d15..faa66a68faa 100644 --- a/pyomo/contrib/asl_functions_lib/tests/test_functions.py +++ b/pyomo/contrib/aslfunctions/tests/test_functions.py @@ -15,11 +15,11 @@ import pyomo.common.unittest as unittest from pyomo.common.fileutils import find_library -flib = find_library("asl_functions_lib") +flib = find_library("libaslfunctions") is_pypy = platform.python_implementation().lower().startswith("pypy") -@unittest.skipIf(not flib, 'Could not find the "asl_functions_lib" library') +@unittest.skipIf(not flib, 'Could not find the "aslfunctions" library') @unittest.skipIf(is_pypy, "Cannot evaluate external functions under pypy") class TestAMPLExternalFunction(unittest.TestCase): diff --git a/pyomo/environ/__init__.py b/pyomo/environ/__init__.py index 016e1ff708e..be01195b3d6 100644 --- a/pyomo/environ/__init__.py +++ b/pyomo/environ/__init__.py @@ -46,7 +46,7 @@ def _do_import(pkg_name): 'pyomo.contrib.gdpopt', 'pyomo.contrib.gjh', 'pyomo.contrib.gdp_bounds', - 'pyomo.contrib.asl_functions_lib', + 'pyomo.contrib.aslfunctions', 'pyomo.contrib.mcpp', 'pyomo.contrib.mindtpy', 'pyomo.contrib.multistart', diff --git a/pyomo/environ/tests/test_package_layout.py b/pyomo/environ/tests/test_package_layout.py index f11ea08df2e..828fa757bbe 100644 --- a/pyomo/environ/tests/test_package_layout.py +++ b/pyomo/environ/tests/test_package_layout.py @@ -39,7 +39,7 @@ join('contrib', 'ampl_function_demo', 'src'), join('contrib', 'appsi', 'cmodel', 'src'), join('contrib', 'cspline_external', 'src'), - join('contrib', 'asl_functions_lib', 'src'), + join('contrib', 'aslfunctions', 'src'), join('contrib', 'simplification', 'ginac', 'src'), join('contrib', 'pynumero', 'src'), join('core', 'tests', 'data', 'baselines'), diff --git a/setup.py b/setup.py index 4b19d489139..d91f330c028 100644 --- a/setup.py +++ b/setup.py @@ -276,7 +276,7 @@ def __ne__(self, other): "pyomo.contrib.ampl_function_demo": ["src/*"], "pyomo.contrib.appsi.cmodel": ["src/*"], "pyomo.contrib.cspline_external": ["src/*"], - "pyomo.contrib.asl_functions_lib": ["src/*"], + "pyomo.contrib.aslfunctions": ["src/*"], "pyomo.contrib.mcpp": ["*.cpp"], "pyomo.contrib.pynumero": ['src/*', 'src/tests/*'], "pyomo.contrib.viewer": ["*.ui"], From a84f9e4f64d8e83274f47a4e5f4629899d337776 Mon Sep 17 00:00:00 2001 From: Eslick Date: Mon, 4 Aug 2025 08:54:19 -0400 Subject: [PATCH 34/34] Fix library name in find_library calls --- .../explanation/modeling_utils/aslfunctions/index.rst | 2 +- pyomo/contrib/aslfunctions/tests/test_functions.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/OnlineDocs/explanation/modeling_utils/aslfunctions/index.rst b/doc/OnlineDocs/explanation/modeling_utils/aslfunctions/index.rst index 88adc675d3c..6a8f379cc6a 100644 --- a/doc/OnlineDocs/explanation/modeling_utils/aslfunctions/index.rst +++ b/doc/OnlineDocs/explanation/modeling_utils/aslfunctions/index.rst @@ -18,7 +18,7 @@ Example >>> import pyomo.environ as pyo >>> from pyomo.common.fileutils import find_library - >>> flib = find_library("libaslfunctions") + >>> flib = find_library("aslfunctions") >>> m = pyo.ConcreteModel(name = 'AMPLExternalFunctions') >>> m.sinc = pyo.ExternalFunction(library=flib, function="sinc") >>> m.x = pyo.Var() diff --git a/pyomo/contrib/aslfunctions/tests/test_functions.py b/pyomo/contrib/aslfunctions/tests/test_functions.py index faa66a68faa..919d5587ab8 100644 --- a/pyomo/contrib/aslfunctions/tests/test_functions.py +++ b/pyomo/contrib/aslfunctions/tests/test_functions.py @@ -15,7 +15,7 @@ import pyomo.common.unittest as unittest from pyomo.common.fileutils import find_library -flib = find_library("libaslfunctions") +flib = find_library("aslfunctions") is_pypy = platform.python_implementation().lower().startswith("pypy")