source: coopr.pysp/stable/2.1/coopr/pysp/ph_script.py @ 2068

Last change on this file since 2068 was 2068, checked in by wehart, 10 years ago

Merged revisions 1952-2067 via svnmerge from
https://software.sandia.gov/svn/public/coopr/coopr.pysp/trunk

........

r1956 | jwatson | 2009-12-02 17:56:53 -0700 (Wed, 02 Dec 2009) | 3 lines


Added --scenario-solver-options and --ef-solver-options options to the "runph" script.

........

r1957 | dlwoodr | 2009-12-03 14:17:35 -0700 (Thu, 03 Dec 2009) | 2 lines


Documentation updates for pysp

........

r1974 | wehart | 2009-12-06 17:20:56 -0700 (Sun, 06 Dec 2009) | 2 lines


Updating PyPI categories

........

r1978 | jwatson | 2009-12-10 21:29:33 -0700 (Thu, 10 Dec 2009) | 3 lines


Eliminated exception-handling logic when loading user-defined extension modules in PH. The range of exceptions is too large, and for debugging purposes, it is more useful to see the raw trace output.

........

r1979 | jwatson | 2009-12-10 22:23:17 -0700 (Thu, 10 Dec 2009) | 5 lines


Biggest enhancement: The efwriter command-line script now has the option to output a CVaR-weighted objective term. Not extensively tested, but behaves sane on a number of small test cases.


Improved exception handling and error diagnostics in both the runph and efwriter scripts.

........

r1985 | jwatson | 2009-12-12 10:45:17 -0700 (Sat, 12 Dec 2009) | 3 lines


Modified PH to only use warm-starts if a solver has the capability!

........

r1998 | jwatson | 2009-12-13 15:17:58 -0700 (Sun, 13 Dec 2009) | 3 lines


Changed references to _component to active_component.

........

r2026 | wehart | 2009-12-21 23:27:06 -0700 (Mon, 21 Dec 2009) | 2 lines


Attempting to update PH. I'm not sure if this works, since I don't know how to test PH.

........

r2029 | jwatson | 2009-12-22 09:52:21 -0700 (Tue, 22 Dec 2009) | 3 lines


Some fixes to the ef writer based on Bill's recent changes to _initialize_constraint.

........

r2035 | jwatson | 2009-12-22 21:10:32 -0700 (Tue, 22 Dec 2009) | 3 lines


Added --scenario-mipgap option to PH script. Added _mipgap attribute to PH object. This attribute is mirrored to the solver plugin at the initiation of each iteration, after any PH extensions have the opportunity to provide a new value to the attribute. It is currently made use of by the WW PH extension.

........

r2037 | dlwoodr | 2009-12-23 14:38:43 -0700 (Wed, 23 Dec 2009) | 2 lines


add this example from Fernando

........

r2038 | dlwoodr | 2009-12-23 14:46:56 -0700 (Wed, 23 Dec 2009) | 3 lines


finish the job: we can now duplicate Fernando's example

........

r2039 | jwatson | 2009-12-23 15:13:54 -0700 (Wed, 23 Dec 2009) | 3 lines


Missed fix with new constraint initialization syntax in PH linearization.

........

r2058 | jwatson | 2009-12-29 10:57:58 -0700 (Tue, 29 Dec 2009) | 3 lines


Missed some _initialize_constraint function calls within the PySP EF writer during the recent switch to the corresponding "add" method.

........

r2059 | jwatson | 2009-12-29 10:58:34 -0700 (Tue, 29 Dec 2009) | 3 lines


Enabling garbage collection by default in PH.

........

r2060 | jwatson | 2009-12-29 10:59:05 -0700 (Tue, 29 Dec 2009) | 3 lines


Elimnating some debug output.

........

r2061 | jwatson | 2009-12-29 11:07:47 -0700 (Tue, 29 Dec 2009) | 3 lines


Fixing some option documentation in PH.

........

r2062 | jwatson | 2009-12-29 12:00:37 -0700 (Tue, 29 Dec 2009) | 3 lines


Added ef-mipgap option to PH scripts.

........

  • Property svn:executable set to *
File size: 26.3 KB
Line 
1#  _________________________________________________________________________
2#
3#  Coopr: A COmmon Optimization Python Repository
4#  Copyright (c) 2009 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
16import pyutilib.services
17import pyutilib.misc
18import textwrap
19import traceback
20
21# garbage collection control.
22import gc
23
24# for profiling
25import cProfile
26import pstats
27
28# for serializing
29import pickle
30
31from coopr.pysp.convergence import *
32from coopr.pysp.scenariotree import *
33from coopr.pysp.ph import *
34from coopr.pysp.ef import *
35from coopr.opt.base import SolverFactory
36from coopr.opt.parallel import SolverManagerFactory
37
38#
39# Setup command-line options
40#
41
42parser = OptionParser()
43parser.add_option("--verbose",
44                  help="Generate verbose output for both initialization and execution.",
45                  action="store_true",
46                  dest="verbose",
47                  default=False)
48parser.add_option("--model-directory",
49                  help="The directory in which all model (reference and scenario) definitions are stored. Default is \".\".",
50                  action="store",
51                  dest="model_directory",
52                  type="string",
53                  default=".")
54parser.add_option("--instance-directory",
55                  help="The directory in which all instance (reference and scenario) definitions are stored. Default is \".\".",
56                  action="store",
57                  dest="instance_directory",
58                  type="string",
59                  default=".")
60parser.add_option("--solver",
61                  help="The type of solver used to solve scenario sub-problems. Default is cplex.",
62                  action="store",
63                  dest="solver_type",
64                  type="string",
65                  default="cplex")
66parser.add_option("--solver-manager",
67                  help="The type of solver manager used to coordinate scenario sub-problem solves. Default is serial.",
68                  action="store",
69                  dest="solver_manager_type",
70                  type="string",
71                  default="serial")
72parser.add_option("--scenario-solver-options",
73                  help="Solver options for all PH scenario sub-problems",
74                  action="append",
75                  dest="scenario_solver_options",
76                  type="string",
77                  default=[])
78parser.add_option("--scenario-mipgap",
79                  help="Specifies the mipgap for all PH scenario sub-problems",
80                  action="store",
81                  dest="scenario_mipgap",
82                  type="float",
83                  default=None)
84parser.add_option("--ef-solver-options",
85                  help="Solver options for the extension form problem",
86                  action="append",
87                  dest="ef_solver_options",
88                  type="string",
89                  default=[])
90parser.add_option("--ef-mipgap",
91                  help="Specifies the mipgap for the EF solve",
92                  action="store",
93                  dest="ef_mipgap",
94                  type="float",
95                  default=None)
96parser.add_option("--max-iterations",
97                  help="The maximal number of PH iterations. Default is 100.",
98                  action="store",
99                  dest="max_iterations",
100                  type="int",
101                  default=100)
102parser.add_option("--default-rho",
103                  help="The default (global) rho for all blended variables. Default is 1.",
104                  action="store",
105                  dest="default_rho",
106                  type="float",
107                  default=1.0)
108parser.add_option("--rho-cfgfile",
109                  help="The name of a configuration script to compute PH rho values. Default is None.",
110                  action="store",
111                  dest="rho_cfgfile",
112                  type="string",
113                  default=None)
114parser.add_option("--bounds-cfgfile",
115                  help="The name of a configuration script to set variable bound values. Default is None.",
116                  action="store",
117                  dest="bounds_cfgfile",
118                  default=None)
119parser.add_option("--enable-termdiff-convergence",
120                  help="Terminate PH based on the termdiff convergence metric. Default is True.",
121                  action="store_true",
122                  dest="enable_termdiff_convergence",
123                  default=True)
124parser.add_option("--enable-normalized-termdiff-convergence",
125                  help="Terminate PH based on the normalized termdiff convergence metric. Default is True.",
126                  action="store_true",
127                  dest="enable_normalized_termdiff_convergence",
128                  default=False)
129parser.add_option("--termdiff-threshold",
130                  help="The convergence threshold used in the term-diff and normalized term-diff convergence criteria. Default is 0.01.",
131                  action="store",
132                  dest="termdiff_threshold",
133                  type="float",
134                  default=0.01)
135parser.add_option("--enable-free-discrete-count-convergence",
136                  help="Terminate PH based on the free discrete variable count convergence metric. Default is False.",
137                  action="store_true",
138                  dest="enable_free_discrete_count_convergence",
139                  default=False)
140parser.add_option("--free-discrete-count-threshold",
141                  help="The convergence threshold used in the criterion based on when the free discrete variable count convergence criterion. Default is 20.",
142                  action="store",
143                  dest="free_discrete_count_threshold",
144                  type="float",
145                  default=20)
146parser.add_option("--enable-ww-extensions",
147                  help="Enable the Watson-Woodruff PH extensions plugin. Default is False.",
148                  action="store_true",
149                  dest="enable_ww_extensions",
150                  default=False)
151parser.add_option("--ww-extension-cfgfile",
152                  help="The name of a configuration file for the Watson-Woodruff PH extensions plugin. Default is wwph.cfg.",
153                  action="store",
154                  dest="ww_extension_cfgfile",
155                  type="string",
156                  default="")
157parser.add_option("--ww-extension-suffixfile",
158                  help="The name of a variable suffix file for the Watson-Woodruff PH extensions plugin. Default is wwph.suffixes.",
159                  action="store",
160                  dest="ww_extension_suffixfile",
161                  type="string",
162                  default="")
163parser.add_option("--user-defined-extension",
164                  help="The name of a python module specifying a user-defined PH extension plugin.",
165                  action="store",
166                  dest="user_defined_extension",
167                  type="string",
168                  default=None)
169parser.add_option("--write-ef",
170                  help="Upon termination, write the extensive form of the model - accounting for all fixed variables.",
171                  action="store_true",
172                  dest="write_ef",
173                  default=False)
174parser.add_option("--solve-ef",
175                  help="Following write of the extensive form model, solve it.",
176                  action="store_true",
177                  dest="solve_ef",
178                  default=False)
179parser.add_option("--ef-output-file",
180                  help="The name of the extensive form output file (currently only LP format is supported), if writing of the extensive form is enabled. Default is efout.lp.",
181                  action="store",
182                  dest="ef_output_file",
183                  type="string",
184                  default="efout.lp")
185parser.add_option("--suppress-continuous-variable-output",
186                  help="Eliminate PH-related output involving continuous variables.",
187                  action="store_true",
188                  dest="suppress_continuous_variable_output",
189                  default=False)
190parser.add_option("--keep-solver-files",
191                  help="Retain temporary input and output files for scenario sub-problem solves",
192                  action="store_true",
193                  dest="keep_solver_files",
194                  default=False)
195parser.add_option("--output-solver-logs",
196                  help="Output solver logs during scenario sub-problem solves",
197                  action="store_true",
198                  dest="output_solver_logs",
199                  default=False)
200parser.add_option("--output-ef-solver-log",
201                  help="Output solver log during the extensive form solve",
202                  action="store_true",
203                  dest="output_ef_solver_log",
204                  default=False)
205parser.add_option("--output-solver-results",
206                  help="Output solutions obtained after each scenario sub-problem solve",
207                  action="store_true",
208                  dest="output_solver_results",
209                  default=False)
210parser.add_option("--output-times",
211                  help="Output timing statistics for various PH components",
212                  action="store_true",
213                  dest="output_times",
214                  default=False)
215parser.add_option("--disable-warmstarts",
216                  help="Disable warm-start of scenario sub-problem solves in PH iterations >= 1",
217                  action="store_true",
218                  dest="disable_warmstarts",
219                  default=False)
220parser.add_option("--drop-proximal-terms",
221                  help="Eliminate proximal terms (i.e., the quadratic penalty terms) from the weighted PH objective",
222                  action="store_true",
223                  dest="drop_proximal_terms",
224                  default=False)
225parser.add_option("--retain-quadratic-binary-terms",
226                  help="Do not linearize PH objective terms involving binary decision variables",
227                  action="store_true",
228                  dest="retain_quadratic_binary_terms",
229                  default=False)
230parser.add_option("--linearize-nonbinary-penalty-terms",
231                  help="Approximate the PH quadratic term for non-binary variables with a piece-wise linear function, using the supplied number of equal-length pieces from each bound to the average",
232                  action="store",
233                  dest="linearize_nonbinary_penalty_terms",
234                  type="int",
235                  default=0)
236parser.add_option("--breakpoint-strategy",
237                  help="Specify the strategy to distribute breakpoints on the [lb, ub] interval of each variable when linearizing. 0 indicates uniform distribution. 1 indicates breakpoints at the node min and max, uniformly in-between. 2 indicates more aggressive concentration of breakpoints near the observed node min/max.",
238                  action="store",
239                  dest="breakpoint_strategy",
240                  type="int",
241                  default=0)
242parser.add_option("--checkpoint-interval",
243                  help="The number of iterations between writing of a checkpoint file. Default is 0, indicating never.",
244                  action="store",
245                  dest="checkpoint_interval",
246                  type="int",
247                  default=0)
248parser.add_option("--restore-from-checkpoint",
249                  help="The name of the checkpoint file from which PH should be initialized. Default is \"\", indicating no checkpoint restoration",
250                  action="store",
251                  dest="restore_from_checkpoint",
252                  type="string",
253                  default="")
254parser.add_option("--profile",
255                  help="Enable profiling of Python code.  The value of this option is the number of functions that are summarized.",
256                  action="store",
257                  dest="profile",
258                  type="int",
259                  default=0)
260parser.add_option("--enable-gc",
261                  help="Enable the python garbage collecter. Default is True.",
262                  action="store_true",
263                  dest="enable_gc",
264                  default=True)
265
266
267parser.usage="runph [options]"
268
269#
270# The main PH initialization / runner routine.
271#
272
273def run_ph(options, args):
274
275   start_time = time.time()
276
277   ph = None
278
279   # if we are restoring from a checkpoint file, do so - otherwise, construct PH from scratch.
280   if len(options.restore_from_checkpoint) > 0:
281
282      # we need to load the reference model, as pickle doesn't save contents of .py files!
283      try:
284         reference_model_filename = options.model_directory+os.sep+"ReferenceModel.py"
285         if options.verbose is True:
286            print "Scenario reference model filename="+reference_model_filename
287         model_import = pyutilib.misc.import_file(reference_model_filename)
288         if "model" not in dir(model_import):
289            print ""
290            print "***ERROR: Exiting test driver: No 'model' object created in module "+reference_model_filename
291            return
292
293         if model_import.model is None:
294            print ""
295            print "***ERROR: Exiting test driver: 'model' object equals 'None' in module "+reference_model_filename
296            return
297 
298         reference_model = model_import.model
299      except IOError:
300         print "***ERROR: Failed to load scenario reference model from file="+reference_model_filename
301         return     
302
303      # import the saved state
304     
305      try:
306         checkpoint_file = open(options.restore_from_checkpoint,"r")
307         ph = pickle.load(checkpoint_file)
308         checkpoint_file.close()
309         
310#         print "PH=",ph
311#         ph._scenario_tree.pprint()         
312      except IOError, msg:
313         raise RuntimeError, msg
314
315      # tell PH to build the right solver manager and solver TBD - AND PLUGINS, BUT LATER
316
317      raise RuntimeError, "Checkpoint restoration is not fully supported/tested yet!"
318     
319   else:
320      #
321      # create and populate the reference model/instance pair.
322      #
323
324      reference_model = None
325      reference_instance = None
326
327      try:
328         reference_model_filename = options.model_directory+os.sep+"ReferenceModel.py"
329         if options.verbose is True:
330            print "Scenario reference model filename="+reference_model_filename
331         model_import = pyutilib.misc.import_file(reference_model_filename)
332         if "model" not in dir(model_import):
333            print ""
334            print "***ERROR: Exiting test driver: No 'model' object created in module "+reference_model_filename
335            return
336
337         if model_import.model is None:
338            print ""
339            print "***ERROR: Exiting test driver: 'model' object equals 'None' in module "+reference_model_filename
340            return
341 
342         reference_model = model_import.model
343      except IOError:
344         print "***ERROR: Failed to load scenario reference model from file="+reference_model_filename
345         return
346
347      try:
348         reference_instance_filename = options.instance_directory+os.sep+"ReferenceModel.dat"
349         if options.verbose is True:
350            print "Scenario reference instance filename="+reference_instance_filename
351         reference_instance = reference_model.create(reference_instance_filename)
352      except IOError:
353         print "***ERROR: Failed to load scenario reference instance data from file="+reference_instance_filename
354         return     
355
356      #
357      # create and populate the scenario tree model
358      #
359
360      scenario_tree_model = None
361      scenario_tree_instance = None
362
363      try:
364         scenario_tree_model_filename = options.model_directory+os.sep+"ScenarioStructure.py"
365         if options.verbose is True:
366            print "Scenario tree model filename="+scenario_tree_model_filename
367         scenario_tree_import = pyutilib.misc.import_file(scenario_tree_model_filename)
368         scenario_tree_model = scenario_tree_import.model
369      except IOError:
370         print "***ERROR: Failed to load scenario tree reference model from file="+scenario_tree_model_filename
371         return   
372
373      try:
374         scenario_tree_instance_filename = options.instance_directory+os.sep+"ScenarioStructure.dat"
375         if options.verbose is True:
376            print "Scenario tree instance filename="+scenario_tree_instance_filename
377         scenario_tree_instance = scenario_tree_model.create(scenario_tree_instance_filename)
378      except IOError:
379         print "***ERROR: Failed to load scenario tree reference instance data from file="+scenario_tree_instance_filename
380         return
381   
382      #
383      # construct the scenario tree
384      #
385      scenario_tree = ScenarioTree(model=reference_instance,
386                                   nodes=scenario_tree_instance.Nodes,
387                                   nodechildren=scenario_tree_instance.Children,
388                                   nodestages=scenario_tree_instance.NodeStage,
389                                   nodeprobabilities=scenario_tree_instance.ConditionalProbability,
390                                   stages=scenario_tree_instance.Stages,
391                                   stagevariables=scenario_tree_instance.StageVariables,
392                                   stagecostvariables=scenario_tree_instance.StageCostVariable,
393                                   scenarios=scenario_tree_instance.Scenarios,
394                                   scenarioleafs=scenario_tree_instance.ScenarioLeafNode,
395                                   scenariobaseddata=scenario_tree_instance.ScenarioBasedData)
396
397      #
398      # print the input tree for validation/information purposes.
399      #
400      if options.verbose is True:
401         scenario_tree.pprint()
402
403      #
404      # validate the tree prior to doing anything serious
405      #
406      print ""
407      if scenario_tree.validate() is False:
408         print "***ERROR: Scenario tree is invalid****"
409         return
410      else:
411         if options.verbose is True:
412            print "Scenario tree is valid!"
413      print ""
414
415      #
416      # if any of the ww extension configuration options are specified without the
417      # ww extension itself being enabled, halt and warn the user - this has led
418      # to confusion in the past, and will save user support time.
419      #
420      if len(options.ww_extension_cfgfile) > 0 and options.enable_ww_extensions is False:
421         print "***ERROR: A configuration file was specified for the WW extension module, but the WW extensions are not enabled!"
422         return
423
424      if len(options.ww_extension_suffixfile) > 0 and options.enable_ww_extensions is False:
425         print "***ERROR: A suffix file was specified for the WW extension module, but the WW extensions are not enabled!"         
426         return
427
428      #
429      # if a breakpoint strategy is specified without linearization eanbled, halt and warn the user.
430      #
431      if (options.breakpoint_strategy > 0) and (options.linearize_nonbinary_penalty_terms == 0):
432         print "***ERROR: A breakpoint distribution strategy was specified, but linearization is not enabled!"
433         return         
434
435      #
436      # deal with any plugins. ww extension comes first currently, followed by an option user-defined plugin.
437      # order only matters if both are specified.
438      #
439      if options.enable_ww_extensions is True:
440
441         from coopr.pysp import wwphextension
442
443         plugin = ExtensionPoint(IPHExtension)
444         if len(options.ww_extension_cfgfile) > 0:
445            plugin.service()._configuration_filename = options.ww_extension_cfgfile
446         if len(options.ww_extension_suffixfile) > 0:
447            plugin.service()._suffix_filename = options.ww_extension_suffixfile
448
449      if options.user_defined_extension is not None:
450         print "Trying to import user-defined PH extension module="+options.user_defined_extension
451         # JPW removed the exception handling logic, as the module importer
452         # can raise a broad array of exceptions.
453         __import__(options.user_defined_extension)
454         print "Module successfully loaded"
455
456      #
457      # construct the convergence "computer" class.
458      #
459      converger = None
460      # go with the non-defaults first, and then with the default.
461      if options.enable_free_discrete_count_convergence is True:
462         converger = NumFixedDiscreteVarConvergence(convergence_threshold=options.free_discrete_count_threshold)
463      elif options.enable_normalized_termdiff_convergence is True:
464         converger = NormalizedTermDiffConvergence(convergence_threshold=options.termdiff_threshold)     
465      else:
466         converger = TermDiffConvergence(convergence_threshold=options.termdiff_threshold)     
467
468     
469      #
470      # construct and initialize PH
471      #
472      ph = ProgressiveHedging(max_iterations=options.max_iterations, \
473                              rho=options.default_rho, \
474                              rho_setter=options.rho_cfgfile, \
475                              bounds_setter=options.bounds_cfgfile, \
476                              solver=options.solver_type, \
477                              solver_manager=options.solver_manager_type, \
478                              scenario_solver_options=options.scenario_solver_options, \
479                              scenario_mipgap=options.scenario_mipgap, \
480                              keep_solver_files=options.keep_solver_files, \
481                              output_solver_log=options.output_solver_logs, \
482                              output_solver_results=options.output_solver_results, \
483                              verbose=options.verbose, \
484                              output_times=options.output_times, \
485                              disable_warmstarts=options.disable_warmstarts,
486                              drop_proximal_terms=options.drop_proximal_terms,
487                              retain_quadratic_binary_terms=options.retain_quadratic_binary_terms, \
488                              linearize_nonbinary_penalty_terms=options.linearize_nonbinary_penalty_terms, \
489                              breakpoint_strategy=options.breakpoint_strategy, \
490                              checkpoint_interval=options.checkpoint_interval)
491   
492      ph.initialize(scenario_data_directory_name=options.instance_directory, \
493                    model=reference_model, \
494                    model_instance=reference_instance, \
495                    scenario_tree=scenario_tree, \
496                    converger=converger)
497
498      if options.suppress_continuous_variable_output is True:
499         ph._output_continuous_variable_stats = False # clutters up the screen, when we really only care about the binaries.     
500
501   #
502   # at this point, we have a PH object by some means.
503   #
504
505   #
506   # kick off the solve
507   #
508   ph.solve()
509
510   print ""
511   print "DONE..."
512
513   end_time = time.time()
514
515   print ""
516   print "Total execution time=%8.2f seconds" %(end_time - start_time)
517   print ""
518   if options.output_times is True:
519      ph.print_time_stats()
520
521   #
522   # write the extensive form, accounting for any fixed variables.
523   #
524   if (options.write_ef is True) or (options.solve_ef is True):
525      print ""
526      print "Writing EF for remainder problem"
527      print ""
528      write_ef(ph._scenario_tree, ph._instances, options.ef_output_file)
529
530   #
531   # solve the extensive form.
532   #
533   if options.solve_ef is True:
534      print ""
535      print "Solving extensive form written to file="+options.ef_output_file
536      print ""
537
538      ef_solver = SolverFactory(options.solver_type)
539      if ef_solver is None:
540         raise ValueError, "Failed to create solver of type="+options.solver_type+" for use in extensive form solve"
541      if len(options.ef_solver_options) > 0:
542         print "Initializing ef solver with options="+str(options.ef_solver_options)         
543         ef_solver.set_options("".join(options.ef_solver_options))
544      if options.ef_mipgap is not None:
545         if (options.ef_mipgap < 0.0) or (options.ef_mipgap > 1.0):
546            raise ValueError, "Value of the mipgap parameter for the EF solve must be on the unit interval; value specified=" + `options.ef_mipgap`
547         else:
548            ef_solver.mipgap = options.ef_mipgap
549
550      ef_solver_manager = SolverManagerFactory(options.solver_manager_type)
551      if ef_solver is None:
552         raise ValueError, "Failed to create solver manager of type="+options.solver_type+" for use in extensive form solve"
553
554      print "Queuing extensive form solve"
555      ef_action_handle = ef_solver_manager.queue(options.ef_output_file, opt=ef_solver, warmstart=False, tee=options.output_ef_solver_log)
556      print "Waiting for extensive form solve"
557      ef_results = ef_solver_manager.wait_for(ef_action_handle)
558      print "Extensive form solve results:"
559      ef_results.write(num=1)
560
561def run(args=None):
562
563    #
564    # Top-level command that executes the extensive form writer.
565    # This is segregated from run_ef_writer to enable profiling.
566    #
567
568    #
569    # Parse command-line options.
570    #
571    try:
572       (options, args) = parser.parse_args(args=args)
573    except SystemExit:
574       # the parser throws a system exit if "-h" is specified - catch
575       # it to exit gracefully.
576       return
577
578    # for a one-pass execution, garbage collection doesn't make
579    # much sense - so it is disabled by default. Because: It drops
580    # the run-time by a factor of 3-4 on bigger instances.
581    if options.enable_gc is False:
582       gc.disable()
583    else:
584       gc.enable()
585
586    if options.profile > 0:
587        #
588        # Call the main PH routine with profiling.
589        #
590        tfile = pyutilib.services.TempfileManager.create_tempfile(suffix=".profile")
591        tmp = cProfile.runctx('run_ph(options,args)',globals(),locals(),tfile)
592        p = pstats.Stats(tfile).strip_dirs()
593        p.sort_stats('time', 'cum')
594        p = p.print_stats(options.profile)
595        p.print_callers(options.profile)
596        p.print_callees(options.profile)
597        p = p.sort_stats('cum','calls')
598        p.print_stats(options.profile)
599        p.print_callers(options.profile)
600        p.print_callees(options.profile)
601        p = p.sort_stats('calls')
602        p.print_stats(options.profile)
603        p.print_callers(options.profile)
604        p.print_callees(options.profile)
605        pyutilib.services.TempfileManager.clear_tempfiles()
606        ans = [tmp, None]
607    else:
608        #
609        # Call the main PH routine without profiling.
610        #
611        ans = run_ph(options, args)
612
613    gc.enable()
614   
615    return ans
616
Note: See TracBrowser for help on using the repository browser.