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# Unit Tests for pyomo.opt.base.convert 12# 13 14from itertools import zip_longest 15import re 16import sys 17import os 18from os.path import join 19from filecmp import cmp 20 21import pyomo.common.unittest as unittest 22 23from pyomo.common.errors import ApplicationError 24from pyomo.common.fileutils import this_file_dir 25from pyomo.common.tempfiles import TempfileManager 26 27from pyomo.opt import ProblemFormat, ConverterError, convert_problem 28from pyomo.common import Executable 29 30def filter(line): 31 return 'Problem' in line or line.startswith('NAME') 32 33currdir = this_file_dir() 34deleteFiles = True 35 36class MockArg(object): 37 38 def __init__(self): 39 pass 40 41 def valid_problem_types(self): 42 return [ProblemFormat.pyomo] 43 44 def write(self,filename="", format=None, solver_capability=None, io_options={}): 45 return (filename,None) 46 47class MockArg2(MockArg): 48 49 def valid_problem_types(self): 50 return [ProblemFormat.nl] 51 52 def write(self,filename="", format=None, solver_capability=None, io_options={}): 53 OUTPUT=open(filename,"w") 54 INPUT=open(join(currdir, "test4.nl")) 55 for line in INPUT: 56 OUTPUT.write(line) 57 OUTPUT.close() 58 INPUT.close() 59 return (filename,None) 60 61class MockArg3(MockArg): 62 63 def valid_problem_types(self): 64 return [ProblemFormat.mod] 65 66 def write(self,filename="", format=None, solver_capability=None, io_options={}): 67 return (filename,None) 68 69class MockArg4(MockArg): 70 71 def write(self,filename="", format=None, solver_capability=None, io_options={}): 72 OUTPUT=open(filename,"w") 73 INPUT=open(join(currdir, "test4.nl")) 74 for line in INPUT: 75 OUTPUT.write(line) 76 OUTPUT.close() 77 INPUT.close() 78 return (filename,None) 79 80 81class Test(unittest.TestCase): 82 83 @classmethod 84 def setUpClass(cls): 85 import pyomo.environ 86 87 def setUp(self): 88 TempfileManager.push() 89 90 def tearDown(self): 91 TempfileManager.pop(remove=deleteFiles or self.currentTestPassed()) 92 93 def test_nl_nl1(self): 94 #""" Convert from NL to NL """ 95 ans = convert_problem( ("test4.nl",), None, [ProblemFormat.nl]) 96 self.assertEqual(ans[0],("test4.nl",)) 97 98 def test_nl_nl2(self): 99 #""" Convert from NL to NL """ 100 ans = convert_problem( ("test4.nl","tmp.nl"), None, [ProblemFormat.nl]) 101 self.assertEqual(ans[0],("test4.nl","tmp.nl")) 102 103 @unittest.skipUnless( 104 Executable("pico_convert").available(), 'pico_convert required') 105 def test_nl_lp1(self): 106 #""" Convert from NL to LP """ 107 ans = convert_problem( 108 (join(currdir, "test4.nl"),), None, [ProblemFormat.cpxlp]) 109 self.assertEqual(ans[0][0][-15:],"pico_convert.lp") 110 _out, _log = ans[0][0], join(currdir, "test1_convert.lp") 111 self.assertTrue(cmp(_out, _log), 112 msg="Files %s and %s differ" % (_out, _log)) 113 114 @unittest.skipUnless(Executable("glpsol").available(), 'glpsol required') 115 def test_mod_lp1(self): 116 #""" Convert from MOD to LP """ 117 ans = convert_problem( 118 (join(currdir, "test3.mod"),), None, [ProblemFormat.cpxlp]) 119 self.assertTrue(ans[0][0].endswith("glpsol.lp")) 120 with open(ans[0][0], 'r') as f1, open(join(currdir, "test2_convert.lp"), 'r') as f2: 121 for line1, line2 in zip_longest(f1, f2): 122 if 'Problem' in line1: 123 continue 124 self.assertEqual(line1, line2) 125 126 @unittest.skipUnless(Executable("glpsol").available(), 'glpsol required') 127 def test_mod_lp2(self): 128 #""" Convert from MOD+DAT to LP """ 129 ans = convert_problem( 130 (join(currdir, "test5.mod"), join(currdir, "test5.dat")), 131 None, [ProblemFormat.cpxlp]) 132 self.assertTrue(ans[0][0].endswith("glpsol.lp")) 133 with open(ans[0][0], 'r') as f1, open(join(currdir, "test3_convert.lp"), 'r') as f2: 134 for line1, line2 in zip_longest(f1, f2): 135 if 'Problem' in line1: 136 continue 137 self.assertEqual(line1, line2) 138 139 @unittest.skipUnless(Executable("ampl").available(), 'ampl required') 140 def test_mod_nl1(self): 141 #""" Convert from MOD to NL """ 142 ans = convert_problem( 143 (join(currdir, "test3.mod"),), None, [ProblemFormat.nl]) 144 self.assertTrue(ans[0][0].endswith('.nl')) 145 #self.assertFileEqualsBinaryFile(ans[0][0], join(currdir, "test_mod_nl1.nl") 146 147 @unittest.skipUnless(Executable("ampl").available(), 'ampl required') 148 def test_mod_nl2(self): 149 #""" Convert from MOD+DAT to NL """ 150 ans = convert_problem( 151 (join(currdir, "test5.mod"), join(currdir, "test5.dat")), 152 None, [ProblemFormat.nl]) 153 self.assertTrue(ans[0][0].endswith('.nl')) 154 #self.assertTrue(cmp(ans[0][0], join(currdir, "test_mod_nl2.nl") 155 156 def test_mock_lp1(self): 157 #""" Convert from Pyomo to LP """ 158 arg=MockArg() 159 ans = convert_problem( (arg, ProblemFormat.cpxlp,arg), None, [ProblemFormat.cpxlp]) 160 self.assertNotEqual(re.match(".*tmp.*pyomo.lp$",ans[0][0]), None) 161 162 def test_pyomo_lp1(self): 163 #""" Convert from Pyomo to LP with file""" 164 ans = convert_problem( (join(currdir, 'model.py'), ProblemFormat.cpxlp,), None, [ProblemFormat.cpxlp]) 165 self.assertNotEqual(re.match(".*tmp.*pyomo.lp$",ans[0][0]), None) 166 167 def test_mock_lp2(self): 168 #""" Convert from NL to LP """ 169 arg=MockArg2() 170 try: 171 ans = convert_problem( (arg,), None, [ProblemFormat.cpxlp]) 172 except ConverterError: 173 err = sys.exc_info()[1] 174 if not Executable("pico_convert"): 175 return 176 else: 177 self.fail("Expected ApplicationError because pico_convert " 178 "is not available: '%s'" % str(err)) 179 self.assertEqual(ans[0][0][-15:],"pico_convert.lp") 180 os.remove(ans[0][0]) 181 182 # Note sure what to do with this test now that we 183 # have a native MPS converter 184 def Xtest_mock_mps1(self): 185 #""" Convert from Pyomo to MPS """ 186 arg=MockArg4() 187 try: 188 ans = convert_problem((arg, ProblemFormat.mps,arg), None, [ProblemFormat.mps]) 189 except ConverterError: 190 err = sys.exc_info()[1] 191 if not Executable("pico_convert"): 192 return 193 else: 194 self.fail("Expected ApplicationError because pico_convert " 195 "is not available: '%s'" % str(err)) 196 self.assertEqual(ans[0][0][-16:],"pico_convert.mps") 197 os.remove(ans[0][0]) 198 199 def test_pyomo_mps1(self): 200 #""" Convert from Pyomo to MPS with file""" 201 try: 202 ans = convert_problem( (join(currdir, 'model.py'), ProblemFormat.mps,), None, [ProblemFormat.mps]) 203 except ConverterError: 204 err = sys.exc_info()[1] 205 if not Executable("pico_convert"): 206 return 207 else: 208 self.fail("Expected ApplicationError because pico_convert " 209 "is not available: '%s'" % str(err)) 210 self.assertEqual(ans[0][0][-16:],"pico_convert.mps") 211 os.remove(ans[0][0]) 212 213 def test_mock_nl1(self): 214 #""" Convert from Pyomo to NL """ 215 arg = MockArg4() 216 ans = convert_problem( (arg, ProblemFormat.nl,arg), None, [ProblemFormat.nl]) 217 self.assertNotEqual(re.match(".*tmp.*pyomo.nl$",ans[0][0]), None) 218 os.remove(ans[0][0]) 219 220 def test_pyomo_nl1(self): 221 #""" Convert from Pyomo to NL with file""" 222 ans = convert_problem( (join(currdir, 'model.py'), ProblemFormat.nl,), None, [ProblemFormat.nl]) 223 self.assertNotEqual(re.match(".*tmp.*pyomo.nl$",ans[0][0]), None) 224 os.remove(ans[0][0]) 225 226 def test_error1(self): 227 #""" No valid problem types """ 228 try: 229 convert_problem( ("test4.nl","tmp.nl"), ProblemFormat.nl, []) 230 self.fail("Expected ConverterError exception") 231 except ConverterError: 232 err = sys.exc_info()[1] 233 pass 234 235 def test_error2(self): 236 #""" Target problem type is not valid """ 237 try: 238 convert_problem( ("test4.nl","tmp.nl"), ProblemFormat.nl, [ProblemFormat.mps]) 239 self.fail("Expected ConverterError exception") 240 except ConverterError: 241 pass 242 243 def test_error3(self): 244 #""" Empty argument list """ 245 try: 246 convert_problem( (), None, [ProblemFormat.mps]) 247 self.fail("Expected ConverterError exception") 248 except ConverterError: 249 pass 250 251 def test_error4(self): 252 #""" Unknown source type """ 253 try: 254 convert_problem( ("prob.foo",), None, [ProblemFormat.mps]) 255 self.fail("Expected ConverterError exception") 256 except ConverterError: 257 pass 258 259 def test_error5(self): 260 #""" Unknown source type """ 261 try: 262 convert_problem( ("prob.lp",), ProblemFormat.nl, [ProblemFormat.nl]) 263 self.fail("Expected ConverterError exception") 264 except ConverterError: 265 pass 266 267 def test_error6(self): 268 #""" Cannot use pico_convert with more than one file """ 269 try: 270 ans = convert_problem( (join(currdir, "test4.nl"), "foo"), None, [ProblemFormat.cpxlp]) 271 self.fail("Expected ConverterError exception") 272 except ConverterError: 273 pass 274 275 def test_error8(self): 276 #""" Error when source file cannot be found """ 277 try: 278 ans = convert_problem( (join(currdir, "unknown.nl"),), None, [ProblemFormat.cpxlp]) 279 self.fail("Expected ConverterError exception") 280 except ApplicationError: 281 err = sys.exc_info()[1] 282 if not Executable("pico_convert"): 283 self.fail("Expected ApplicationError because pico_convert " 284 "is not available: '%s'" % str(err)) 285 return 286 except ConverterError: 287 pass 288 289 def test_error9(self): 290 #""" The Opt configuration has not been initialized """ 291 cmd = Executable("pico_convert").disable() 292 try: 293 ans = convert_problem( (join(currdir, "test4.nl"),), None, [ProblemFormat.cpxlp]) 294 self.fail("This test didn't fail, but pico_convert should not be defined.") 295 except ConverterError: 296 pass 297 cmd = Executable("pico_convert").rehash() 298 299 def test_error10(self): 300 #""" GLPSOL can only convert file data """ 301 try: 302 arg = MockArg3() 303 ans = convert_problem( (arg, ProblemFormat.cpxlp,arg), None, [ProblemFormat.cpxlp]) 304 self.fail("This test didn't fail, but glpsol cannot handle objects.") 305 except ConverterError: 306 pass 307 308 def test_error11(self): 309 #""" Cannot convert MOD that contains data """ 310 try: 311 ans = convert_problem( (join(currdir, "test3.mod"),join(currdir, "test5.dat")), None, [ProblemFormat.cpxlp]) 312 self.fail("Expected ConverterError exception because we provided a MOD file with a 'data;' declaration") 313 except ApplicationError: 314 err = sys.exc_info()[1] 315 if Executable("glpsol"): 316 self.fail("Expected ApplicationError because glpsol " 317 "is not available: '%s'" % str(err)) 318 return 319 except ConverterError: 320 pass 321 322if __name__ == "__main__": 323 deleteFiles = False 324 unittest.main() 325