source: trunk/coopr/pyomo/main_script.py @ 1768

Last change on this file since 1768 was 1768, checked in by wehart, 11 years ago

Rework of Coopr to use the new PyUtilib? package decomposition.

NOTE: to use Coopr with this update, we need to work with a new version of coopr_install.

  • Property svn:executable set to *
File size: 13.8 KB
Line 
1#  _________________________________________________________________________
2#
3#  Coopr: A COmmon Optimization Python Repository
4#  Copyright (c) 2008 Sandia Corporation.
5#  This software is distributed under the BSD License.
6#  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
7#  the U.S. Government retains certain rights in this software.
8#  For more information, see the Coopr README.txt file.
9#  _________________________________________________________________________
10
11
12import sys
13import os
14from optparse import OptionParser
15#
16# Finish imports
17#
18from coopr.pyomo import *
19from coopr.opt.base import SolverFactory
20from coopr.opt.parallel import SolverManagerFactory
21import pyutilib.services
22import pyutilib.misc
23import textwrap
24import traceback
25import cProfile
26import pstats
27import gc
28
29#
30#
31# Setup command-line options
32#
33#
34solver_help=\
35"This option specifies the type of solver that is used "\
36"to solve the Pyomo model instance.  The following solver "\
37"types are are currently supported:"
38_tmp = SolverFactory()
39_tmp.sort()
40for item in _tmp:
41  if item[0] != "_":
42     solver_help += "\n.."+item
43solver_help += ".\nThe default solver is 'glpk'."
44debug_help=\
45"This option is used to turn on debugging output. This option "\
46"can be specified multiple times to turn on different debugging"\
47"output. The following debugging options can be specified:"
48debug_choices=[]
49for item in pyomo.Debug:
50  if str(item) != "none":
51     debug_choices.append( str(item) )
52     debug_help += "\n.."+str(item)
53
54parser = OptionParser()
55parser.add_option("--solver",
56    help=solver_help,
57    action="store",
58    dest="solver",
59    type="string",
60    default="glpk")
61parser.add_option("--path",
62    help="Give a path that is used to find the Pyomo python files",
63    action="store",
64    dest="path",
65    type="string",
66    default=".")
67parser.add_option("--help-components",
68        help="Print information about modeling components supported by Pyomo",
69        action="store_true",
70        dest="help_components",
71        default=False)
72parser.add_option("--debug",
73        help=debug_help,
74        action="append",
75        dest="debug",
76        choices=debug_choices)
77parser.add_option("-k","--keepfiles",
78        help="Keep temporary files",
79        action="store_true",
80        dest="keepfiles",
81        default=False)
82parser.add_option("--tempdir",
83        help="Specify the directory where temporary files are generated",
84        action="store",
85        dest="tempdir",
86        default=None)
87parser.add_option("-q","--quiet",
88        help="Turn off solver output",
89        action="store_true",
90        dest="quiet",
91        default=False)
92parser.add_option("-l","--log",
93        help="Print the solver logfile after performing optimization",
94        action="store_true",
95        dest="log",
96        default=False)
97parser.add_option("--logfile",
98        help="Redirect output to the specified logfile",
99        action="store",
100        dest="logfile",
101        default=None)
102parser.add_option("-s","--summary",
103        help="Summarize the final solution after performing optimization",
104        action="store_true",
105        dest="summary",
106        default=False)
107parser.add_option("--instance-only",
108        help="Generate a model instance, and then return",
109        action="store_true",
110        dest="only_instance",
111        default=False)
112parser.add_option("--profile",
113        help="Enable profiling of Python code.  The value of this option is the number of functions that are summarized.",
114        action="store",
115        dest="profile",
116        default=0)
117parser.add_option("--timelimit",
118        help="Limit to the number of seconds that the solver is run",
119        action="store",
120        dest="timelimit",
121        type="int",
122        default=0)
123parser.add_option("--postprocess",
124        help="Specify a Python module that gets executed after optimization.  If this option is specified multiple times, then the modules are executed in the specified order.",
125        action="append",
126        dest="postprocess",
127        default=[])
128parser.add_option("--preprocess",
129        help="Specify a Python module that gets immediately executed (before the optimization model is setup).  If this option is specified multiple times, then the modules are executed in the specified order.",
130        action="append",
131        dest="preprocess",
132        default=[])
133parser.add_option("-v","--verbose",
134        help="Make solver output verbose",
135        action="store_true",
136        dest="verbose",
137        default=False)
138parser.add_option("--solver-options",
139        help="Options passed into the solver",
140        action="append",
141        dest="solver_options",
142        type="string",
143        default=[])
144parser.add_option("--disable-gc",
145        help="Disable the garbage collecter",
146        action="store_true",
147        dest="disable_gc",
148        default=False)
149parser.add_option("--solver-manager",
150        help="Specify the technique that is used to manage solver executions.",
151        action="store",
152        dest="smanager_type",
153        default="serial")
154parser.add_option("--stream-output",
155        help="Stream the solver output to provide information about the solver's progress.",
156        action="store_true",
157        dest="tee",
158        default=False)
159parser.add_option("--save-model",
160        help="Specify the filename to which the model is saved.  The suffix of this filename specifies the file format.  If debugging is on, then this defaults to writing the file 'unknown.lp'.",
161        action="store",
162        dest="save_model",
163        default=None)
164#
165# These options are depricated until we have a specific use-case for them
166#
167if False:
168  parser.add_option("--seed",
169        help="Specify a seed to derandomize the solver",
170        action="store",
171        dest="seed",
172        type="int",
173        default=0)
174  parser.add_option("--first-feasible",
175        help="Terminate after the first feasible incumbent",
176        action="store_true",
177        dest="ff",
178        default=False)
179parser.usage="pyomo [options] <model.py> [<model.dat>]"
180
181
182def run_pyomo(options, args):
183    #
184    # Run the a command that executes a Pyomo script
185    #
186    if options.help_components:
187        print ""
188        print "----------------------------------------------------------------" 
189        print "Pyomo Model Components:"
190        print "----------------------------------------------------------------" 
191        components = pyomo.model_components()
192        index = pyutilib.misc.sort_index(components)
193        for i in index:
194            print ""
195            print " "+components[i][0]
196            for line in textwrap.wrap(components[i][1], 59):
197                print "    "+line
198        print ""
199        print "----------------------------------------------------------------" 
200        print "Predefined Pyomo Sets:"
201        print "----------------------------------------------------------------" 
202        pyomo_sets = pyomo.predefined_sets()
203        index = pyutilib.misc.sort_index(pyomo_sets)
204        for i in index:
205            print ""
206            print " "+pyomo_sets[i][0]
207            print "    "+pyomo_sets[i][1]
208        return
209
210    #
211    # Process command-line options
212    #
213    if options.disable_gc:
214        gc.disable()
215    if options.verbose:
216       pyomo.set_debugging("verbose")
217    if options.debug is not None:
218       for val in options.debug:
219         pyomo.set_debugging( val )
220    if not options.logfile is None:
221        pyutilib.misc.setup_redirect(options.logfile)
222    if not options.tempdir is None:
223        if not os.path.exists(options.tempdir):
224            raise ValueError, "Directory for temporary files does not exist: "+options.tempdir
225        pyutilib.services.TempfileManager.tempdir = options.tempdir
226
227    filter_excepthook=True
228    def pyomo_excepthook(etype,value,tb):
229      print ""
230      if filter_excepthook:
231         print "ERROR: Unexpected exception while loading Pyomo model "+args[0]
232      else:
233         print "ERROR: Unexpected exception while running Pyomo model "+args[0]
234      print "  ",value
235      print ""
236      tb_list = traceback.extract_tb(tb,None)
237      i=0
238      if not pyomo.debug("all") and filter_excepthook:
239         while i < len(tb_list):
240           if args[0] in tb_list[i][0]:
241              break
242           i += 1
243      print "Pyomo Traceback (most recent call last):"
244      for item in tb_list[i:]:
245        print "  File \""+item[0]+"\", line "+str(item[1])+", in "+item[2]
246        if item[3] is not None:
247           print "    "+item[3]
248      sys.exit(1)
249   
250    sys.excepthook = pyomo_excepthook
251
252    #
253    # Apply preprocessing steps
254    #
255    for file in options.preprocess:
256        preprocess = pyutilib.misc.import_file(file)
257       
258    #
259    #
260    # Setup solver and model
261    #
262    #
263    if len(args) == 0:
264       parser.print_help()
265       return
266    for file in args:
267      if not os.path.exists(file):
268         print "File "+file+" does not exist!"
269         sys.exit(1)
270
271    #
272    # Create Model
273    #
274    usermodel = pyutilib.misc.import_file(args[0])
275    filter_excepthook=False
276    if "model" not in dir(usermodel):
277       print ""
278       print "Exiting pyomo: No 'model' object created in module "+args[0]
279       sys.exit(0)
280    if usermodel.model is None:
281       print ""
282       print "Exiting pyomo: 'model' object equals 'None' in module "+args[0]
283       sys.exit(0)
284    #
285    # Create Problem Instance
286    #
287    if len(args) == 2:
288       suffix = (args[1]).split(".")[-1]
289       if suffix == "dat":
290          instance = usermodel.model.create(args[1])
291       elif suffix == "py":
292          userdata = pyutilib.misc.import_file(args[1])
293          if "modeldata" not in dir(userdata):
294             print ""
295             print "Exiting pyomo: No 'modeldata' object created in module "+args[1]
296             sys.exit(0)
297          if userdata.modeldata is None:
298             print ""
299             print "Exiting pyomo: 'modeldata' object equals 'None' in module "+args[1]
300             sys.exit(0)
301          userdata.modeldata.read(usermodel.model)
302          instance = usermodel.model.create(userdata.modeldata)
303       else:
304          raise ValueError, "Unknown data file type: "+args[1]
305    else:
306       instance = usermodel.model.create()
307    if pyomo.debug("instance"):
308       print "MODEL INSTANCE"
309       instance.pprint()
310       print ""
311       options.save_model = 'unknown.lp'
312       print "Model instance written in file",options.save_model,"to allow debugging"
313
314    if not options.save_model is None:
315        instance.write(filename=options.save_model, format=None)
316        if not os.path.exists(options.save_model):
317            print "ERROR: file "+options.save_model+" has not been created!"
318
319    if options.only_instance:
320        return [instance, None]
321
322    #
323    # Create Solver and Perform Optimization
324    #
325    opt = SolverFactory( options.solver )
326    if opt is None:
327       raise ValueError, "Problem constructing solver `"+str(options.solver)+"'"
328    opt.keepFiles=options.keepfiles or options.log
329    if options.timelimit == 0:
330       options.timelimit=None
331    solver_mngr = SolverManagerFactory( options.smanager_type )
332    if solver_mngr is None:
333       raise ValueError, "Problem constructing solver manager `"+str(options.smanager_type)+"'"
334    results = solver_mngr.solve(instance, opt=opt, tee=options.tee, timelimit=options.timelimit, options=" ".join(options.solver_options))
335    if results == None:
336            raise ValueError, "opt.solve returned None"
337   
338    if options.log:
339       print ""
340       print "=========================================================="
341       print "Solver Logfile:",opt.log_file
342       print "=========================================================="
343       print ""
344       INPUT = open(opt.log_file, "r")
345       for line in INPUT:
346         print line,
347       INPUT.close()
348   
349    try:
350        instance.load(results)
351    except Exception, e:
352        raise ValueError, "Problem loading solver results: "+str(e)
353    print ""
354    results.write(num=1)
355   
356    if options.summary:
357       print ""
358       print "=========================================================="
359       print "Solution Summary"
360       print "=========================================================="
361       if len(results.solution(0).variable) > 0:
362          print ""
363          display(instance)
364       else:
365          print "No solutions reported by solver."
366
367    for file in options.postprocess:
368        postprocess = pyutilib.misc.import_file(file)
369        if "postprocess" in dir(postprocess):
370            postprocess.postprocess(instance,results)
371       
372    #
373    # Return the model instance and optimization results
374    #
375    return [instance,results]
376
377
378def run(args=None):
379    #
380    # Top-level command that executes a Pyomo script.  This
381    # is segregated from run_pyomo to enable Pyomo profiling.
382    #
383
384    #
385    #
386    # Parse command-line options
387    #
388    #
389    try:
390       (options, args) = parser.parse_args(args=args)
391    except SystemExit:
392       # the parser throws a system exit if "-h" is specified - catch
393       # it to exit gracefully.
394       return
395
396    #
397    # Call the main Pyomo runner with profiling
398    #
399    if options.profile > 0:
400        tfile = pyutilib.services.TempfileManager.create_tempfile(suffix=".profile")
401        tmp = cProfile.runctx('run_pyomo(options,args)',globals(),locals(),tfile)
402        p = pstats.Stats(tfile).strip_dirs()
403        p.sort_stats('time', 'cum')
404        options.profile = eval(options.profile)
405        p = p.print_stats(options.profile)
406        p.print_callers(options.profile)
407        p.print_callees(options.profile)
408        p = p.sort_stats('cum','calls')
409        p.print_stats(options.profile)
410        p.print_callers(options.profile)
411        p.print_callees(options.profile)
412        p = p.sort_stats('calls')
413        p.print_stats(options.profile)
414        p.print_callers(options.profile)
415        p.print_callees(options.profile)
416        pyutilib.services.TempfileManager.clear_tempfiles()
417        ans = [tmp, None]
418    else:
419        #
420        # Call the main Pyomo runner without profiling
421        #
422        ans = run_pyomo(options, args)
423
424    gc.enable()
425    return ans
426
Note: See TracBrowser for help on using the repository browser.