예제 #1
0
    def test_pprint(self):
        m = ConcreteModel()
        m.h = ExternalFunction(_g)
        out = StringIO()
        m.pprint()
        m.pprint(ostream=out)
        self.assertEqual(
            out.getvalue().strip(), """
1 ExternalFunction Declarations
    h : function=_g, units=None, arg_units=None

1 Declarations: h
        """.strip())

        if not pint_available:
            return
        m.i = ExternalFunction(function=_h,
                               units=units.kg,
                               arg_units=[units.m, units.s])
        out = StringIO()
        m.pprint(ostream=out)
        self.assertEqual(
            out.getvalue().strip(), """
2 ExternalFunction Declarations
    h : function=_g, units=None, arg_units=None
    i : function=_h, units=kg, arg_units=['m', 's']

2 Declarations: h i
        """.strip())
예제 #2
0
    def test_pprint(self):
        m = ConcreteModel()
        m.f = ExternalFunction(library="junk.so", function="junk")

        out = StringIO()
        m.pprint(ostream=out)
        self.assertEqual(
            out.getvalue().strip(), """
1 ExternalFunction Declarations
    f : function=junk, library=junk.so, units=None, arg_units=None

1 Declarations: f
        """.strip())

        if not pint_available:
            return
        m.g = ExternalFunction(library="junk.so",
                               function="junk",
                               units=units.kg,
                               arg_units=[units.m, units.s])
        out = StringIO()
        m.pprint(ostream=out)
        self.assertEqual(
            out.getvalue().strip(), """
2 ExternalFunction Declarations
    f : function=junk, library=junk.so, units=None, arg_units=None
    g : function=junk, library=junk.so, units=kg, arg_units=['m', 's']

2 Declarations: f g
        """.strip())
예제 #3
0
 def test_constructor_errors(self):
     m = ConcreteModel()
     with self.assertRaisesRegex(
             ValueError, "Duplicate definition of external function "
             r"through positional and keyword \('function='\)"):
         m.f = ExternalFunction(_count, function=_count)
     with self.assertRaisesRegex(
             ValueError, "PythonCallbackFunction constructor only "
             "supports 0 - 3 positional arguments"):
         m.f = ExternalFunction(1, 2, 3, 4)
     with self.assertRaisesRegex(
             ValueError, "Cannot specify 'fgh' with any of "
             "{'function', 'gradient', hessian'}"):
         m.f = ExternalFunction(_count, fgh=_fgh)
예제 #4
0
    def test_eval_gsl_function(self):
        DLL = find_GSL()
        if not DLL:
            self.skipTest("Could not find the amplgsl.dll library")
        model = ConcreteModel()
        model.gamma = ExternalFunction(
            library=DLL, function="gsl_sf_gamma")
        model.bessel = ExternalFunction(
            library=DLL, function="gsl_sf_bessel_Jnu")
        model.x = Var(initialize=3, bounds=(1e-5,None))
        model.o = Objective(expr=model.gamma(model.x))
        self.assertAlmostEqual(value(model.o), 2.0, 7)

        f = model.bessel.evaluate((0.5, 2.0,))
        self.assertAlmostEqual(f, 0.5130161365618272, 7)
예제 #5
0
    def test_properties(self):
        m = ConcreteModel()
        m.f = ExternalFunction(_sum)
        e = m.f()
        self.assertIsInstance(e, NPV_ExternalFunctionExpression)
        self.assertFalse(e.is_constant())
        self.assertTrue(e.is_fixed())
        self.assertFalse(e.is_potentially_variable())

        # This is just a check for coverage: the expression is_constant
        # catches that the function ID is a NumericConstant and doesn't
        # call the method.
        self.assertFalse(e.arg(0).is_constant())
        self.assertTrue(e.arg(0).is_fixed())
        self.assertFalse(e.arg(0).is_potentially_variable())

        m.p = Param(initialize=1)
        e = m.f(m.p)
        self.assertIsInstance(e, NPV_ExternalFunctionExpression)
        self.assertFalse(e.is_constant())
        self.assertTrue(e.is_fixed())
        self.assertFalse(e.is_potentially_variable())

        m.x = Var(initialize=1)
        e = m.f(m.p, m.x)
        self.assertIsInstance(e, ExternalFunctionExpression)
        self.assertFalse(e.is_constant())
        self.assertFalse(e.is_fixed())
        self.assertTrue(e.is_potentially_variable())
예제 #6
0
 def test_call_countArgs(self):
     m = ConcreteModel()
     m.f = ExternalFunction(_count)
     self.assertIsInstance(m.f, PythonCallbackFunction)
     self.assertEqual(value(m.f()), 0)
     self.assertEqual(value(m.f(2)), 1)
     self.assertEqual(value(m.f(2, 3)), 2)
예제 #7
0
    def test_load_local_asl_library(self):
        DLL = find_GSL()
        if not DLL:
            self.skipTest("Could not find the amplgsl.dll library")

        LIB = 'test_pyomo_external_gsl.dll'

        model = ConcreteModel()
        model.gamma = ExternalFunction(library=LIB, function="gsl_sf_gamma")
        model.x = Var(initialize=3, bounds=(1e-5, None))
        model.o = Objective(expr=model.gamma(model.x))

        with TempfileManager.new_context() as tempfile:
            dname = tempfile.mkdtemp()
            shutil.copyfile(DLL, os.path.join(dname, LIB))
            # Without changing directories, the load should fail
            with self.assertRaises(OSError):
                value(model.o)
            # Changing directories should pick up the library
            try:
                orig_dir = os.getcwd()
                os.chdir(dname)
                self.assertAlmostEqual(value(model.o), 2.0, 7)
            finally:
                os.chdir(orig_dir)
예제 #8
0
    def test_partial_clone(self):
        m = ConcreteModel()
        m.f = ExternalFunction(_sum)
        m.x = Var(initialize=3)
        m.y = Var(initialize=5)
        m.b = Block()
        m.b.e = Expression(expr=m.f(m.x, m.y))
        self.assertIsInstance(m.f, PythonCallbackFunction)
        self.assertEqual(m.f._fcn_id, m.b.e.arg(0).arg(-1).value)
        self.assertEqual(value(m.b.e), 10)

        m.c = m.b.clone()
        self.assertIsNot(m.b.e, m.c.e)
        self.assertIsNot(m.b.e.arg(0), m.c.e.arg(0))
        self.assertEqual(m.f._fcn_id, m.b.e.arg(0).arg(-1).value)
        self.assertEqual(m.f._fcn_id, m.c.e.arg(0).arg(-1).value)
        self.assertEqual(value(m.c.e), 10)

        # save / restore should not change the fcn_id
        _fcn_id = m.f._fcn_id
        m.f.__setstate__(m.f.__getstate__())
        self.assertEqual(m.f._fcn_id, _fcn_id)

        self.assertIsNot(m.b.e, m.c.e)
        self.assertIsNot(m.b.e.arg(0), m.c.e.arg(0))
        self.assertEqual(m.f._fcn_id, m.b.e.arg(0).arg(-1).value)
        self.assertEqual(m.f._fcn_id, m.c.e.arg(0).arg(-1).value)
        self.assertEqual(value(m.c.e), 10)
예제 #9
0
 def test_call_sumfcn(self):
     m = ConcreteModel()
     m.f = ExternalFunction(_sum)
     self.assertIsInstance(m.f, PythonCallbackFunction)
     self.assertEqual(value(m.f()), 2.0)
     self.assertEqual(value(m.f(1)), 3.0)
     self.assertEqual(value(m.f(1, 2)), 5.0)
예제 #10
0
    def test_eval_fgh_gsl_function(self):
        DLL = find_GSL()
        if not DLL:
            self.skipTest("Could not find the amplgsl.dll library")
        model = ConcreteModel()
        model.gamma = ExternalFunction(
            library=DLL, function="gsl_sf_gamma")
        model.bessel = ExternalFunction(
            library=DLL, function="gsl_sf_bessel_Jnu")
        f,g,h = model.gamma.evaluate_fgh((2.0,))
        self.assertAlmostEqual(f, 1.0, 7)
        self.assertListsAlmostEqual(g, [0.422784335098467], 7)
        self.assertListsAlmostEqual(h, [0.8236806608528794], 7)

        f,g,h = model.bessel.evaluate_fgh((2.5, 2.0,), fixed=[1,0])
        self.assertAlmostEqual(f, 0.223924531469, 7)
        self.assertListsAlmostEqual(g, [0.0, 0.21138811435101745], 7)
        self.assertListsAlmostEqual(h, [0.0, 0.0, 0.02026349177575621], 7)
예제 #11
0
 def test_eval_gsl_error(self):
     DLL = find_GSL()
     if not DLL:
         self.skipTest("Could not find the amplgsl.dll library")
     model = ConcreteModel()
     model.bogus = ExternalFunction(library=DLL, function="bogus_function")
     with self.assertRaisesRegex(
             RuntimeError, "Error: external function 'bogus_function' was "
             "not registered within external library(?s:.*)gsl_sf_gamma"):
         f = model.bogus.evaluate((1, ))
예제 #12
0
 def test_unknown_library(self):
     m = ConcreteModel()
     with LoggingIntercept() as LOG:
         m.ef = ExternalFunction(
             library='unknown_pyomo_external_testing_function',
             function='f')
     self.assertEqual(
         LOG.getvalue(),
         'Defining AMPL external function, but cannot locate '
         'specified library "unknown_pyomo_external_testing_function"\n')
예제 #13
0
 def test_solve_gsl_function(self):
     DLL = find_GSL()
     if not DLL:
         self.skipTest("Could not find the amplgsl.dll library")
     model = ConcreteModel()
     model.z_func = ExternalFunction(library=DLL, function="gsl_sf_gamma")
     model.x = Var(initialize=3, bounds=(1e-5, None))
     model.o = Objective(expr=model.z_func(model.x))
     opt = SolverFactory('ipopt')
     res = opt.solve(model, tee=True)
     self.assertAlmostEqual(value(model.o), 0.885603194411, 7)
예제 #14
0
 def test_solve_gsl_function_const_arg(self):
     DLL = find_GSL()
     if not DLL:
         self.skipTest("Could not find the amplgsl.dll library")
     model = ConcreteModel()
     model.z_func = ExternalFunction(library=DLL, function="gsl_sf_beta")
     model.x = Var(initialize=1, bounds=(0.1, None))
     model.o = Objective(expr=-model.z_func(1, model.x))
     opt = SolverFactory('ipopt')
     res = opt.solve(model, tee=True)
     self.assertAlmostEqual(value(model.x), 0.1, 5)
예제 #15
0
    def test_getname(self):
        m = ConcreteModel()
        m.f = ExternalFunction(library="junk.so", function="junk")
        self.assertIsInstance(m.f, AMPLExternalFunction)
        self.assertEqual(m.f.name, "f")
        self.assertEqual(m.f.local_name, "f")
        self.assertEqual(m.f.getname(), "f")
        self.assertEqual(m.f.getname(True), "f")

        M = ConcreteModel()
        M.m = m
        self.assertEqual(M.m.f.name, "m.f")
        self.assertEqual(M.m.f.local_name, "f")
        self.assertEqual(M.m.f.getname(), "f")
        self.assertEqual(M.m.f.getname(True), "m.f")
예제 #16
0
    def test_getname(self):
        m = ConcreteModel()
        m.f = ExternalFunction(_sum)
        self.assertIsInstance(m.f, PythonCallbackFunction)
        self.assertEqual(m.f.name, "f")
        self.assertEqual(m.f.local_name, "f")
        self.assertEqual(m.f.getname(), "f")
        self.assertEqual(m.f.getname(True), "f")

        M = ConcreteModel()
        M.m = m
        self.assertEqual(M.m.f.name, "m.f")
        self.assertEqual(M.m.f.local_name, "f")
        self.assertEqual(M.m.f.getname(), "f")
        self.assertEqual(M.m.f.getname(True), "m.f")
예제 #17
0
    def test_evaluate_fgh_f_g_h(self):
        m = ConcreteModel()
        m.f = ExternalFunction(_f, _g, _h)
        f, g, h = m.f.evaluate_fgh((5, 7, 11, m.f._fcn_id))
        self.assertEqual(f, 5**2 + 3 * 5 * 7 + 5 * 7 * 11**2)
        self.assertEqual(
            g,
            [2 * 5 + 3 * 7 + 7 * 11**2, 3 * 5 + 5 * 11**2, 2 * 5 * 7 * 11, 0])
        self.assertEqual(h, [
            2,
            3 + 11**2,
            0,
            2 * 7 * 11,
            2 * 5 * 11,
            2 * 5 * 7,
            0,
            0,
            0,
            0,
        ])

        f, g, h = m.f.evaluate_fgh((5, 7, 11, m.f._fcn_id), fixed=[0, 1, 0, 1])
        self.assertEqual(f, 5**2 + 3 * 5 * 7 + 5 * 7 * 11**2)
        self.assertEqual(g, [2 * 5 + 3 * 7 + 7 * 11**2, 0, 2 * 5 * 7 * 11, 0])
        self.assertEqual(h, [
            2,
            0,
            0,
            2 * 7 * 11,
            0,
            2 * 5 * 7,
            0,
            0,
            0,
            0,
        ])

        f, g, h = m.f.evaluate_fgh((5, 7, 11, m.f._fcn_id), fgh=1)
        self.assertEqual(f, 5**2 + 3 * 5 * 7 + 5 * 7 * 11**2)
        self.assertEqual(
            g,
            [2 * 5 + 3 * 7 + 7 * 11**2, 3 * 5 + 5 * 11**2, 2 * 5 * 7 * 11, 0])
        self.assertIsNone(h)

        f, g, h = m.f.evaluate_fgh((5, 7, 11, m.f._fcn_id), fgh=0)
        self.assertEqual(f, 5**2 + 3 * 5 * 7 + 5 * 7 * 11**2)
        self.assertIsNone(g)
        self.assertIsNone(h)
예제 #18
0
    def test_evaluate_fgh_f(self):
        m = ConcreteModel()
        m.f = ExternalFunction(_f)
        with self.assertRaisesRegex(
                RuntimeError, "ExternalFunction 'f' was not defined "
                "with a gradient callback."):
            f, g, h = m.f.evaluate_fgh((5, 7, 11, m.f._fcn_id))

        with self.assertRaisesRegex(
                RuntimeError, "ExternalFunction 'f' was not defined "
                "with a gradient callback."):
            f, g, h = m.f.evaluate_fgh((5, 7, 11, m.f._fcn_id), fgh=1)

        f, g, h = m.f.evaluate_fgh((5, 7, 11, m.f._fcn_id), fgh=0)
        self.assertEqual(f, 5**2 + 3 * 5 * 7 + 5 * 7 * 11**2)
        self.assertIsNone(g)
        self.assertIsNone(h)
예제 #19
0
    def test_clone(self):
        m = ConcreteModel()
        m.f = ExternalFunction(_sum)
        m.x = Var(initialize=3)
        m.y = Var(initialize=5)
        m.e = Expression(expr=m.f(m.x, m.y))
        self.assertIsInstance(m.f, PythonCallbackFunction)
        self.assertEqual(m.f._fcn_id, m.e.arg(0).arg(-1).value)
        self.assertEqual(value(m.e), 10)

        i = m.clone()
        self.assertIsInstance(i.f, PythonCallbackFunction)
        self.assertIsNot(i.f, m.f)
        self.assertIsNot(i.e, m.e)
        self.assertIsNot(i.e.arg(0), m.e.arg(0))
        self.assertEqual(i.f._fcn_id, i.e.arg(0).arg(-1).value)
        self.assertNotEqual(i.f._fcn_id, m.f._fcn_id)
        self.assertEqual(value(i.e), 10)
예제 #20
0
    def test_evaluate_fgh_f_g(self):
        m = ConcreteModel()
        m.f = ExternalFunction(_f, _g)
        with self.assertRaisesRegex(
                RuntimeError, "ExternalFunction 'f' was not defined "
                "with a Hessian callback."):
            f, g, h = m.f.evaluate_fgh((5, 7, 11, m.f._fcn_id))

        f, g, h = m.f.evaluate_fgh((5, 7, 11, m.f._fcn_id), fgh=1)
        self.assertEqual(f, 5**2 + 3 * 5 * 7 + 5 * 7 * 11**2)
        self.assertEqual(
            g,
            [2 * 5 + 3 * 7 + 7 * 11**2, 3 * 5 + 5 * 11**2, 2 * 5 * 7 * 11, 0])
        self.assertIsNone(h)

        f, g, h = m.f.evaluate_fgh((5, 7, 11, m.f._fcn_id), fgh=0)
        self.assertEqual(f, 5**2 + 3 * 5 * 7 + 5 * 7 * 11**2)
        self.assertIsNone(g)
        self.assertIsNone(h)
예제 #21
0
    def test_evaluate_errors(self):
        m = ConcreteModel()
        m.f = ExternalFunction(_f, _g_bad, _h_bad)
        f = m.f.evaluate((5, 7, 11, m.f._fcn_id))
        self.assertEqual(f, 5**2 + 3 * 5 * 7 + 5 * 7 * 11**2)

        with self.assertRaisesRegex(
                RuntimeError,
                "PythonCallbackFunction called with invalid Global ID"):
            f = m.f.evaluate((5, 7, 11, -1))

        with self.assertRaisesRegex(
                RuntimeError, "External function 'f' returned an invalid "
                r"derivative vector \(expected 4, received 5\)"):
            f = m.f.evaluate_fgh((5, 7, 11, m.f._fcn_id), fgh=1)

        with self.assertRaisesRegex(
                RuntimeError, "External function 'f' returned an invalid "
                r"Hessian matrix \(expected 10, received 9\)"):
            f = m.f.evaluate_fgh((5, 7, 11, m.f._fcn_id), fgh=2)
예제 #22
0
def add_local_external_functions(block):
    ef_exprs = []
    for comp in block.component_data_objects(
            (Constraint, Expression), active=True
            ):
        ef_exprs.extend(identify_external_functions(comp.expr))
    unique_functions = []
    fcn_set = set()
    for expr in ef_exprs:
        fcn = expr._fcn
        data = (fcn._library, fcn._function)
        if data not in fcn_set:
            fcn_set.add(data)
            unique_functions.append(data)
    fcn_comp_map = {}
    for lib, name in unique_functions:
        comp_name = unique_component_name(block, "_" + name)
        comp = ExternalFunction(library=lib, function=name)
        block.add_component(comp_name, comp)
        fcn_comp_map[lib, name] = comp
    return fcn_comp_map
예제 #23
0
    def test_clone_gsl_function(self):
        DLL = find_GSL()
        if not DLL:
            self.skipTest("Could not find the amplgsl.dll library")
        m = ConcreteModel()
        m.z_func = ExternalFunction(library=DLL, function="gsl_sf_gamma")
        self.assertIsInstance(m.z_func, AMPLExternalFunction)
        m.x = Var(initialize=3, bounds=(1e-5, None))
        m.o = Objective(expr=m.z_func(m.x))

        opt = SolverFactory('ipopt')

        # Test a simple clone...
        model2 = m.clone()
        res = opt.solve(model2, tee=True)
        self.assertAlmostEqual(value(model2.o), 0.885603194411, 7)

        # Trigger the library to be loaded.  This tests that the CDLL
        # objects that are created when the SO/DLL are loaded do not
        # interfere with cloning the model.
        self.assertAlmostEqual(value(m.o), 2)
        model3 = m.clone()
        res = opt.solve(model3, tee=True)
        self.assertAlmostEqual(value(model3.o), 0.885603194411, 7)
예제 #24
0
 def test_extra_kwargs(self):
     m = ConcreteModel()
     with self.assertRaises(ValueError):
         m.f = ExternalFunction(_count, this_should_raise_error='foo')
예제 #25
0
    def test_eval_fgh_gsl_function(self):
        DLL = find_GSL()
        if not DLL:
            self.skipTest("Could not find the amplgsl.dll library")
        model = ConcreteModel()
        model.gamma = ExternalFunction(library=DLL, function="gsl_sf_gamma")
        model.beta = ExternalFunction(library=DLL, function="gsl_sf_beta")
        model.bessel = ExternalFunction(library=DLL,
                                        function="gsl_sf_bessel_Jnu")

        f, g, h = model.gamma.evaluate_fgh((2.0, ))
        self.assertAlmostEqual(f, 1.0, 7)
        self.assertListsAlmostEqual(g, [0.422784335098467], 7)
        self.assertListsAlmostEqual(h, [0.8236806608528794], 7)

        f, g, h = model.beta.evaluate_fgh((
            2.5,
            2.0,
        ), fixed=[1, 1])
        self.assertAlmostEqual(f, 0.11428571428571432, 7)
        self.assertListsAlmostEqual(g, [0.0, 0.0], 7)
        self.assertListsAlmostEqual(h, [0.0, 0.0, 0.0], 7)

        f, g, h = model.beta.evaluate_fgh((
            2.5,
            2.0,
        ), fixed=[0, 1])
        self.assertAlmostEqual(f, 0.11428571428571432, 7)
        self.assertListsAlmostEqual(g, [-0.07836734693877555, 0.0], 7)
        self.assertListsAlmostEqual(h, [0.08135276967930034, 0.0, 0.0], 7)

        f, g, h = model.beta.evaluate_fgh((
            2.5,
            2.0,
        ))
        self.assertAlmostEqual(f, 0.11428571428571432, 7)
        self.assertListsAlmostEqual(
            g, [-0.07836734693877555, -0.11040989614412142], 7)
        self.assertListsAlmostEqual(
            h, [0.08135276967930034, 0.0472839170086535, 0.15194654464270113],
            7)

        f, g, h = model.beta.evaluate_fgh((
            2.5,
            2.0,
        ), fgh=1)
        self.assertAlmostEqual(f, 0.11428571428571432, 7)
        self.assertListsAlmostEqual(
            g, [-0.07836734693877555, -0.11040989614412142], 7)
        self.assertIsNone(h)

        f, g, h = model.beta.evaluate_fgh((
            2.5,
            2.0,
        ), fgh=0)
        self.assertAlmostEqual(f, 0.11428571428571432, 7)
        self.assertIsNone(g)
        self.assertIsNone(h)

        f, g, h = model.bessel.evaluate_fgh((
            2.5,
            2.0,
        ), fixed=[1, 0])
        self.assertAlmostEqual(f, 0.223924531469, 7)
        self.assertListsAlmostEqual(g, [0.0, 0.21138811435101745], 7)
        self.assertListsAlmostEqual(h, [0.0, 0.0, 0.02026349177575621], 7)

        # Note: Not all AMPL-GSL functions honor the fixed flag
        # (notably, gamma and bessel do not as of 12/2021).  We will
        # test that our interface corrects that

        f, g, h = model.gamma.evaluate_fgh((2.0, ), fixed=[1])
        self.assertAlmostEqual(f, 1.0, 7)
        self.assertListsAlmostEqual(g, [0.0], 7)
        self.assertListsAlmostEqual(h, [0.0], 7)

        f, g, h = model.bessel.evaluate_fgh((
            2.5,
            2.0,
        ), fixed=[1, 1])
        self.assertAlmostEqual(f, 0.223924531469, 7)
        self.assertListsAlmostEqual(g, [0.0, 0.0], 7)
        self.assertListsAlmostEqual(h, [0.0, 0.0, 0.0], 7)