1#  ___________________________________________________________________________
2#
3#  Pyomo: Python Optimization Modeling Objects
4#  Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
5#  Under the terms of Contract DE-NA0003525 with National Technology and
6#  Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
7#  rights in this software.
8#  This software is distributed under the 3-clause BSD License.
9#  ___________________________________________________________________________
10
11#!/usr/python/env python
12
13import pyomo.common.unittest as unittest
14
15from pyomo.common.dependencies import numpy_available
16
17from pyomo.environ import (Var, ConcreteModel, Reals, ExternalFunction,
18                           Objective, Constraint, sqrt, sin, SolverFactory)
19
20@unittest.skipIf(not SolverFactory('ipopt').available(False), "The IPOPT solver is not available")
21@unittest.skipIf(not SolverFactory('gjh').available(False), "The GJH solver is not available")
22@unittest.skipIf(not numpy_available, "Cannot test the trustregion solver without numpy")
23class TestTrustRegionConfigBlock(unittest.TestCase):
24    def setUp(self):
25
26        m = ConcreteModel()
27        m.z = Var(range(3), domain=Reals, initialize=2.)
28        m.x = Var(range(2), initialize=2.)
29        m.x[1] = 1.0
30
31        def blackbox(a,b):
32            return sin(a-b)
33        self.bb = ExternalFunction(blackbox)
34
35        m.obj = Objective(
36            expr=(m.z[0]-1.0)**2 + (m.z[0]-m.z[1])**2 + (m.z[2]-1.0)**2 \
37                + (m.x[0]-1.0)**4 + (m.x[1]-1.0)**6 # + m.bb(m.x[0],m.x[1])
38            )
39        m.c1 = Constraint(expr=m.x[0] * m.z[0]**2 + self.bb(m.x[0],m.x[1]) == 2*sqrt(2.0))
40        m.c2 = Constraint(expr=m.z[2]**4 * m.z[1]**2 + m.z[1] == 8+sqrt(2.0))
41
42        self.m = m.clone()
43
44
45    def try_solve(self,**kwds):
46        '''
47        Wrap the solver call in a try block. It should complete without exception. However
48        if it does, at least we can check the values of the trust radius that are being
49        used by the algorithm.
50        '''
51        status = True
52        try:
53            self.optTRF.solve(self.m, [self.bb], **kwds)
54        except Exception as e:
55            print('error calling optTRF.solve: %s' % str(e))
56            status = False
57        return status
58
59
60    def test_config_vars(self):
61
62        # Initialized with 1.0
63        self.optTRF = SolverFactory('trustregion')
64        self.assertEqual(self.optTRF.config.trust_radius, 1.0)
65
66        # Both persistent and local values should be 1.0
67        solve_status = self.try_solve()
68        self.assertTrue(solve_status)
69        self.assertEqual(self.optTRF.config.trust_radius, 1.0)
70        self.assertEqual(self.optTRF._local_config.trust_radius, 1.0)
71
72
73    def test_solve_with_new_kwdval(self):
74
75        # Initialized with 1.0
76        self.optTRF = SolverFactory('trustregion')
77        self.assertEqual(self.optTRF.config.trust_radius, 1.0)
78
79        # Set local to 2.0; persistent should still be 1.0
80        solve_status = self.try_solve(trust_radius=2.0)
81        self.assertTrue(solve_status)
82        self.assertEqual(self.optTRF.config.trust_radius, 1.0)
83        self.assertEqual(self.optTRF._local_config.trust_radius, 2.0)
84
85
86    def test_update_kwdval(self):
87
88        # Initialized with 1.0
89        self.optTRF = SolverFactory('trustregion')
90        self.assertEqual(self.optTRF.config.trust_radius, 1.0)
91
92        # Set persistent value to 4.0; local value should also be set to 4.0
93        self.optTRF.config.trust_radius = 4.0
94        solve_status = self.try_solve()
95        self.assertTrue(solve_status)
96        self.assertEqual(self.optTRF.config.trust_radius, 4.0)
97        self.assertEqual(self.optTRF._local_config.trust_radius, 4.0)
98
99
100    def test_update_kwdval_solve_with_new_kwdval(self):
101
102        # Initialized with 1.0
103        self.optTRF = SolverFactory('trustregion')
104        self.assertEqual(self.optTRF.config.trust_radius, 1.0)
105
106        # Set persistent value to 4.0;
107        self.optTRF.config.trust_radius = 4.0
108        self.assertEqual(self.optTRF.config.trust_radius, 4.0)
109
110        # Set local to 2.0; persistent should still be 4.0
111        solve_status = self.try_solve(trust_radius=2.0)
112        self.assertTrue(solve_status)
113        self.assertEqual(self.optTRF.config.trust_radius, 4.0)
114        self.assertEqual(self.optTRF._local_config.trust_radius, 2.0)
115
116
117    def test_initialize_with_kwdval(self):
118
119        # Initialized with 3.0
120        self.optTRF = SolverFactory('trustregion', trust_radius=3.0)
121        self.assertEqual(self.optTRF.config.trust_radius, 3.0)
122
123        # Both persistent and local values should be set to 3.0
124        solve_status = self.try_solve()
125        self.assertTrue(solve_status)
126        self.assertEqual(self.optTRF.config.trust_radius, 3.0)
127        self.assertEqual(self.optTRF._local_config.trust_radius, 3.0)
128
129
130    def test_initialize_with_kwdval_solve_with_new_kwdval(self):
131
132        # Initialized with 3.0
133        self.optTRF = SolverFactory('trustregion', trust_radius=3.0)
134        self.assertEqual(self.optTRF.config.trust_radius, 3.0)
135
136        # Persistent should be 3.0, local should be 2.0
137        solve_status = self.try_solve(trust_radius=2.0)
138        self.assertTrue(solve_status)
139        self.assertEqual(self.optTRF.config.trust_radius, 3.0)
140        self.assertEqual(self.optTRF._local_config.trust_radius, 2.0)
141
142
143
144if __name__ =='__main__':
145    unittest.main()
146