source: coopr.pysp/trunk/coopr/pysp/phinit.py @ 3104

Last change on this file since 3104 was 3092, checked in by jwatson, 11 years ago

Update to PySP to suppress canonical expression representations when using ASL. Otherwise, things choke badly.

  • Property svn:executable set to *
File size: 29.1 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 os
13import sys
14
15from optparse import OptionParser, OptionGroup
16
17import pyutilib.services
18import pyutilib.misc
19
20# garbage collection control.
21import gc
22
23# for profiling
24try:
25    import cProfile as profile
26except ImportError:
27    import profile
28import pstats
29
30# for serializing
31import pickle
32
33from coopr.pysp.convergence import *
34from coopr.pysp.scenariotree import *
35from coopr.pysp.ph import *
36from coopr.pysp.ef import *
37from coopr.opt.base import SolverFactory
38from coopr.opt.parallel import SolverManagerFactory
39
40from pyutilib.component.core import ExtensionPoint
41from coopr.pysp.solutionwriter import ISolutionWriterExtension
42
43#
44# utility method to construct an option parser for ph arguments,
45# to be supplied as an argument to the runph method.
46#
47
48def construct_ph_options_parser(usage_string):
49
50   parser = OptionParser()
51   parser.usage = usage_string
52
53   inputOpts       = OptionGroup( parser, 'Input Options' )
54   phOpts          = OptionGroup( parser, 'PH Options' )
55   solverOpts      = OptionGroup( parser, 'Solver Options' )
56   postprocessOpts = OptionGroup( parser, 'Postprocessing Options' )   
57   outputOpts      = OptionGroup( parser, 'Output Options' )
58   otherOpts       = OptionGroup( parser, 'Other Options' )
59   parser.add_option_group( inputOpts )
60   parser.add_option_group( phOpts )
61   parser.add_option_group( solverOpts )
62   parser.add_option_group( postprocessOpts )   
63   parser.add_option_group( outputOpts )
64   parser.add_option_group( otherOpts )
65
66   inputOpts.add_option('-m','--model-directory',
67     help="The directory in which all model (reference and scenario) definitions are stored. Default is \".\".",
68     action="store",
69     dest="model_directory",
70     type="string",
71     default=".")
72   inputOpts.add_option('-i','--instance-directory',
73     help="The directory in which all instance (reference and scenario) definitions are stored. Default is '.'.",
74     action="store",
75     dest="instance_directory",
76     type="string",
77     default=".")
78   inputOpts.add_option('--bounds-cfgfile',
79     help="The name of a configuration script to set variable bound values. Default is None.",
80     action="store",
81     dest="bounds_cfgfile",
82     default=None)
83
84   phOpts.add_option('-r','--default-rho',
85     help="The default (global) rho for all blended variables. Default is 1.",
86     action="store",
87     dest="default_rho",
88     type="float",
89     default=1.0)
90   phOpts.add_option('--rho-cfgfile',
91     help="The name of a configuration script to compute PH rho values. Default is None.",
92     action="store",
93     dest="rho_cfgfile",
94     type="string",
95     default=None)
96   phOpts.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)
102   phOpts.add_option('--termdiff-threshold',
103     help="The convergence threshold used in the term-diff and normalized term-diff convergence criteria. Default is 0.01.",
104     action="store",
105     dest="termdiff_threshold",
106     type="float",
107     default=0.01)
108   phOpts.add_option('--enable-free-discrete-count-convergence',
109     help="Terminate PH based on the free discrete variable count convergence metric. Default is False.",
110     action="store_true",
111     dest="enable_free_discrete_count_convergence",
112     default=False)
113   phOpts.add_option('--enable-normalized-termdiff-convergence',
114     help="Terminate PH based on the normalized termdiff convergence metric. Default is True.",
115     action="store_true",
116     dest="enable_normalized_termdiff_convergence",
117     default=False)
118   phOpts.add_option('--enable-termdiff-convergence',
119     help="Terminate PH based on the termdiff convergence metric. Default is True.",
120     action="store_true",
121     dest="enable_termdiff_convergence",
122     default=True)
123   phOpts.add_option('--free-discrete-count-threshold',
124     help="The convergence threshold used in the criterion based on when the free discrete variable count convergence criterion. Default is 20.",
125     action="store",
126     dest="free_discrete_count_threshold",
127     type="float",
128     default=20)
129   phOpts.add_option('--linearize-nonbinary-penalty-terms',
130     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",
131     action="store",
132     dest="linearize_nonbinary_penalty_terms",
133     type="int",
134     default=0)
135   phOpts.add_option('--breakpoint-strategy',
136     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.",
137     action="store",
138     dest="breakpoint_strategy",
139     type="int",
140     default=0)   
141   phOpts.add_option('--retain-quadratic-binary-terms',
142     help="Do not linearize PH objective terms involving binary decision variables",
143     action="store_true",
144     dest="retain_quadratic_binary_terms",
145     default=False)
146   phOpts.add_option('--drop-proximal-terms',
147     help="Eliminate proximal terms (i.e., the quadratic penalty terms) from the weighted PH objective. Default is False.",
148     action="store_true",
149     dest="drop_proximal_terms",
150     default=False)
151   phOpts.add_option('--enable-ww-extensions',
152     help="Enable the Watson-Woodruff PH extensions plugin. Default is False.",
153     action="store_true",
154     dest="enable_ww_extensions",
155     default=False)
156   phOpts.add_option('--ww-extension-cfgfile',
157     help="The name of a configuration file for the Watson-Woodruff PH extensions plugin. Default is wwph.cfg.",
158     action="store",
159     dest="ww_extension_cfgfile",
160     type="string",
161     default="")
162   phOpts.add_option('--ww-extension-suffixfile',
163     help="The name of a variable suffix file for the Watson-Woodruff PH extensions plugin. Default is wwph.suffixes.",
164     action="store",
165     dest="ww_extension_suffixfile",
166     type="string",
167     default="")
168   phOpts.add_option('--user-defined-extension',
169     help="The name of a python module specifying a user-defined PH extension plugin.",
170     action="store",
171     dest="user_defined_extension",
172     type="string",
173     default=None)
174   
175   solverOpts.add_option('--scenario-mipgap',
176     help="Specifies the mipgap for all PH scenario sub-problems",
177     action="store",
178     dest="scenario_mipgap",
179     type="float",
180     default=None)
181   solverOpts.add_option('--scenario-solver-options',
182     help="Solver options for all PH scenario sub-problems",
183     action="append",
184     dest="scenario_solver_options",
185     type="string",
186     default=[])
187   solverOpts.add_option('--solver',
188     help="The type of solver used to solve scenario sub-problems. Default is cplex.",
189     action="store",
190     dest="solver_type",
191     type="string",
192     default="cplex")
193   solverOpts.add_option('--solver-manager',
194     help="The type of solver manager used to coordinate scenario sub-problem solves. Default is serial.",
195     action="store",
196     dest="solver_manager_type",
197     type="string",
198     default="serial")
199   solverOpts.add_option('--disable-warmstarts',
200     help="Disable warm-start of scenario sub-problem solves in PH iterations >= 1. Default is False.",
201     action="store_true",
202     dest="disable_warmstarts",
203     default=False)
204
205   postprocessOpts.add_option('--ef-output-file',
206     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.",
207     action="store",
208     dest="ef_output_file",
209     type="string",
210     default="efout.lp")
211   postprocessOpts.add_option('--solve-ef',
212     help="Following write of the extensive form model, solve it.",
213     action="store_true",
214     dest="solve_ef",
215     default=False)
216   postprocessOpts.add_option('--ef-mipgap',
217     help="Specifies the mipgap for the EF solve",
218     action="store",
219     dest="ef_mipgap",
220     type="float",
221     default=None)
222   postprocessOpts.add_option('--ef-solver-options',
223     help="Solver options for the extension form problem",
224     action="append",
225     dest="ef_solver_options",
226     type="string",
227     default=[])   
228   postprocessOpts.add_option('--output-ef-solver-log',
229     help="Output solver log during the extensive form solve",
230     action="store_true",
231     dest="output_ef_solver_log",
232     default=False)
233
234   
235   outputOpts.add_option('--output-scenario-tree-solution',
236     help="Report the full solution (even leaves) in scenario tree format upon termination. Values represent averages, so convergence is not an issue. Default is False.",
237     action="store_true",
238     dest="output_scenario_tree_solution",
239     default=False)
240   outputOpts.add_option('--output-solver-logs',
241     help="Output solver logs during scenario sub-problem solves",
242     action="store_true",
243     dest="output_solver_logs",
244     default=False)
245   outputOpts.add_option('--output-solver-results',
246     help="Output solutions obtained after each scenario sub-problem solve",
247     action="store_true",
248     dest="output_solver_results",
249     default=False)
250   outputOpts.add_option('--output-times',
251     help="Output timing statistics for various PH components",
252     action="store_true",
253     dest="output_times",
254     default=False)
255   outputOpts.add_option('--report-only-statistics',
256     help="When reporting solutions (if enabled), only output per-variable statistics - not the individual scenario values. Default is False.",
257     action="store_true",
258     dest="report_only_statistics",
259     default=False)
260   outputOpts.add_option('--report-solutions',
261     help="Always report PH solutions after each iteration. Enabled if --verbose is enabled. Default is False.",
262     action="store_true",
263     dest="report_solutions",
264     default=False)
265   outputOpts.add_option('--report-weights',
266     help="Always report PH weights prior to each iteration. Enabled if --verbose is enabled. Default is False.",
267     action="store_true",
268     dest="report_weights",
269     default=False)
270   outputOpts.add_option('--restore-from-checkpoint',
271     help="The name of the checkpoint file from which PH should be initialized. Default is \"\", indicating no checkpoint restoration",
272     action="store",
273     dest="restore_from_checkpoint",
274     type="string",
275     default="")
276   outputOpts.add_option('--solution-writer',
277     help="The plugin invoked to write the scenario tree solution. Defaults to the empty list.",
278     action="append",
279     dest="solution_writer",
280     type="string",
281     default = [])
282   outputOpts.add_option('--suppress-continuous-variable-output',
283     help="Eliminate PH-related output involving continuous variables.",
284     action="store_true",
285     dest="suppress_continuous_variable_output",
286     default=False)
287   outputOpts.add_option('--verbose',
288     help="Generate verbose output for both initialization and execution. Default is False.",
289     action="store_true",
290     dest="verbose",
291     default=False)
292   outputOpts.add_option('--write-ef',
293     help="Upon termination, write the extensive form of the model - accounting for all fixed variables.",
294     action="store_true",
295     dest="write_ef",
296     default=False)
297
298   otherOpts.add_option('--disable-gc',
299     help="Disable the python garbage collecter. Default is False.",
300     action="store_true",
301     dest="disable_gc",
302     default=False)
303   otherOpts.add_option('--keep-solver-files',
304     help="Retain temporary input and output files for scenario sub-problem solves",
305     action="store_true",
306     dest="keep_solver_files",
307     default=False)
308   otherOpts.add_option('--profile',
309     help="Enable profiling of Python code.  The value of this option is the number of functions that are summarized.",
310     action="store",
311     dest="profile",
312     type="int",
313     default=0)
314   otherOpts.add_option('--checkpoint-interval',
315     help="The number of iterations between writing of a checkpoint file. Default is 0, indicating never.",
316     action="store",
317     dest="checkpoint_interval",
318     type="int",
319     default=0)
320   otherOpts.add_option('--traceback',
321     help="When an exception is thrown, show the entire call stack. Ignored if profiling is enabled. Default is False.",
322     action="store_true",
323     dest="traceback",
324     default=False)   
325
326   return parser
327
328#
329# Create the reference model / instance and scenario tree instance for PH.
330# IMPT: This method should be moved into a more generic module - it has nothing
331#       to do with PH, and is used elsewhere (by routines that shouldn't have
332#       to know about PH).
333#
334
335def load_reference_and_scenario_models(options):
336
337   #
338   # create and populate the reference model/instance pair.
339   #
340
341   reference_model = None
342   reference_instance = None
343
344   try:
345      reference_model_filename = os.path.expanduser(options.model_directory)+os.sep+"ReferenceModel.py"
346      if options.verbose is True:
347         print "Scenario reference model filename="+reference_model_filename
348      model_import = pyutilib.misc.import_file(reference_model_filename)
349      if "model" not in dir(model_import):
350         print ""
351         print "***ERROR: Exiting test driver: No 'model' object created in module "+reference_model_filename
352         return None, None, None, None
353
354      if model_import.model is None:
355         print ""
356         print "***ERROR: Exiting test driver: 'model' object equals 'None' in module "+reference_model_filename
357         return None, None, None, None
358
359      reference_model = model_import.model
360   except IOError:
361      print "***ERROR: Failed to load scenario reference model from file="+reference_model_filename
362      return None, None, None, None
363
364   try:
365      reference_instance_filename = os.path.expanduser(options.instance_directory)+os.sep+"ReferenceModel.dat"
366      if options.verbose is True:
367         print "Scenario reference instance filename="+reference_instance_filename
368      reference_instance = reference_model.create(reference_instance_filename, preprocess=False)
369      # IMPT: disable canonical representation construction for ASL solvers.
370      #       this is a hack, in that we need to address encodings and
371      #       the like at a more general level.
372      if options.solver_type == "asl":
373         reference_instance.skip_canonical_repn = True
374      else:
375         reference_instance.preprocess()
376     
377   except IOError:
378      print "***ERROR: Failed to load scenario reference instance data from file="+reference_instance_filename
379      return None, None, None, None
380
381   #
382   # create and populate the scenario tree model
383   #
384
385   from coopr.pysp.util.scenariomodels import scenario_tree_model
386   scenario_tree_instance = None
387
388   try:
389      scenario_tree_instance_filename = os.path.expanduser(options.instance_directory)+os.sep+"ScenarioStructure.dat"
390      if options.verbose is True:
391         print "Scenario tree instance filename="+scenario_tree_instance_filename
392      scenario_tree_instance = scenario_tree_model.create(scenario_tree_instance_filename)
393   except IOError:
394      print "***ERROR: Failed to load scenario tree reference instance data from file="+scenario_tree_instance_filename
395      return None, None, None, None
396
397   #
398   # construct the scenario tree
399   #
400   scenario_tree = ScenarioTree(scenarioinstance=reference_instance,
401                                scenariotreeinstance=scenario_tree_instance)
402
403   return reference_model, reference_instance, scenario_tree, scenario_tree_instance
404
405#
406# Create a PH object from a (pickl) checkpoint. Experimental at the moment.
407#
408def create_ph_from_checkpoint(options):
409
410   # we need to load the reference model, as pickle doesn't save contents of .py files!
411   try:
412      reference_model_filename = os.path.expanduser(options.model_directory)+os.sep+"ReferenceModel.py"
413      if options.verbose is True:
414         print "Scenario reference model filename="+reference_model_filename
415      model_import = pyutilib.misc.import_file(reference_model_filename)
416      if "model" not in dir(model_import):
417         print "***ERROR: Exiting test driver: No 'model' object created in module "+reference_model_filename
418         return
419
420      if model_import.model is None:
421         print "***ERROR: Exiting test driver: 'model' object equals 'None' in module "+reference_model_filename
422         return None
423
424      reference_model = model_import.model
425   except IOError:
426      print "***ERROR: Failed to load scenario reference model from file="+reference_model_filename
427      return None
428
429   # import the saved state
430
431   try:
432      checkpoint_file = open(options.restore_from_checkpoint,"r")
433      ph = pickle.load(checkpoint_file)
434      checkpoint_file.close()
435
436   except IOError, msg:
437      raise RuntimeError, msg
438
439   # tell PH to build the right solver manager and solver TBD - AND PLUGINS, BUT LATER
440
441   raise RuntimeError, "Checkpoint restoration is not fully supported/tested yet!"
442
443   return ph
444
445#
446# Create a PH object from scratch.
447#
448
449def create_ph_from_scratch(options, reference_model, reference_instance, scenario_tree):
450
451   #
452   # print the input tree for validation/information purposes.
453   #
454   if options.verbose is True:
455      scenario_tree.pprint()
456
457   #
458   # validate the tree prior to doing anything serious
459   #
460   if scenario_tree.validate() is False:
461      print "***ERROR: Scenario tree is invalid****"
462      return None
463   else:
464      if options.verbose is True:
465         print "Scenario tree is valid!"
466
467   #
468   # if any of the ww extension configuration options are specified without the
469   # ww extension itself being enabled, halt and warn the user - this has led
470   # to confusion in the past, and will save user support time.
471   #
472   if len(options.ww_extension_cfgfile) > 0 and options.enable_ww_extensions is False:
473      print "***ERROR: A configuration file was specified for the WW extension module, but the WW extensions are not enabled!"
474      return None
475
476   if len(options.ww_extension_suffixfile) > 0 and options.enable_ww_extensions is False:
477      print "***ERROR: A suffix file was specified for the WW extension module, but the WW extensions are not enabled!"
478      return None
479
480   #
481   # if a breakpoint strategy is specified without linearization eanbled, halt and warn the user.
482   #
483   if (options.breakpoint_strategy > 0) and (options.linearize_nonbinary_penalty_terms == 0):
484      print "***ERROR: A breakpoint distribution strategy was specified, but linearization is not enabled!"
485      return None
486
487   #
488   # deal with any plugins. ww extension comes first currently, followed by an option user-defined plugin.
489   # order only matters if both are specified.
490   #
491   if options.enable_ww_extensions is True:
492
493      from coopr.pysp import wwphextension
494
495      plugin = ExtensionPoint(IPHExtension)
496      if len(options.ww_extension_cfgfile) > 0:
497         plugin.service()._configuration_filename = options.ww_extension_cfgfile
498      if len(options.ww_extension_suffixfile) > 0:
499         plugin.service()._suffix_filename = options.ww_extension_suffixfile
500
501   if options.user_defined_extension is not None:
502      print "Trying to import user-defined PH extension module="+options.user_defined_extension
503      # JPW removed the exception handling logic, as the module importer
504      # can raise a broad array of exceptions.
505      __import__(options.user_defined_extension)
506      print "Module successfully loaded"
507
508   #
509   # construct the convergence "computer" class.
510   #
511   converger = None
512   # go with the non-defaults first, and then with the default.
513   if options.enable_free_discrete_count_convergence is True:
514      converger = NumFixedDiscreteVarConvergence(convergence_threshold=options.free_discrete_count_threshold)
515   elif options.enable_normalized_termdiff_convergence is True:
516      converger = NormalizedTermDiffConvergence(convergence_threshold=options.termdiff_threshold)
517   else:
518      converger = TermDiffConvergence(convergence_threshold=options.termdiff_threshold)
519
520
521   #
522   # construct and initialize PH
523   #
524   ph = ProgressiveHedging(max_iterations=options.max_iterations, \
525                           rho=options.default_rho, \
526                           rho_setter=options.rho_cfgfile, \
527                           bounds_setter=options.bounds_cfgfile, \
528                           solver=options.solver_type, \
529                           solver_manager=options.solver_manager_type, \
530                           output_scenario_tree_solution=options.output_scenario_tree_solution, \
531                           scenario_solver_options=options.scenario_solver_options, \
532                           scenario_mipgap=options.scenario_mipgap, \
533                           keep_solver_files=options.keep_solver_files, \
534                           output_solver_log=options.output_solver_logs, \
535                           output_solver_results=options.output_solver_results, \
536                           verbose=options.verbose, \
537                           report_solutions=options.report_solutions, \
538                           report_weights=options.report_weights, \
539                           report_only_statistics=options.report_only_statistics, \
540                           output_times=options.output_times, \
541                           disable_warmstarts=options.disable_warmstarts,
542                           drop_proximal_terms=options.drop_proximal_terms,
543                           retain_quadratic_binary_terms=options.retain_quadratic_binary_terms, \
544                           linearize_nonbinary_penalty_terms=options.linearize_nonbinary_penalty_terms, \
545                           breakpoint_strategy=options.breakpoint_strategy, \
546                           checkpoint_interval=options.checkpoint_interval)
547
548   ph.initialize(scenario_data_directory_name=os.path.expanduser(options.instance_directory), \
549                 model=reference_model, \
550                 model_instance=reference_instance, \
551                 scenario_tree=scenario_tree, \
552                 converger=converger)
553
554   if options.suppress_continuous_variable_output is True:
555      ph._output_continuous_variable_stats = False # clutters up the screen, when we really only care about the binaries.
556
557   return ph
558
559
560
561
562#
563# Given a PH object, execute it and optionally solve the EF at the end.
564#
565
566def run_ph(options, ph):
567
568   #
569   # at this point, we have an initialized PH object by some means.
570   #
571   start_time = time.time()
572
573   #
574   # kick off the solve
575   #
576   ph.solve()
577
578   end_time = time.time()
579
580   print ""
581   print "Total PH execution time=%8.2f seconds" %(end_time - start_time)
582   print ""
583   if options.output_times is True:
584      ph.print_time_stats()
585
586   solution_writer_plugins = ExtensionPoint(ISolutionWriterExtension)
587   for plugin in solution_writer_plugins:
588      plugin.write(ph._scenario_tree, "ph")
589
590   # store the binding instance, if created, in order to load
591   # the solution back into the scenario tree.
592   binding_instance = None
593
594   #
595   # write the extensive form, accounting (implicitly) for any fixed variables.
596   #
597   if (options.write_ef is True) or (options.solve_ef is True):
598      print ""
599      print "Writing EF for remainder problem"
600      print ""
601      binding_instance = create_and_write_ef(ph._scenario_tree, ph._instances, os.path.expanduser(options.ef_output_file))
602
603   #
604   # solve the extensive form and load the solution back into the PH scenario tree.
605   # contents from the PH solve will obviously be over-written!
606   #
607   if options.solve_ef is True:
608      print ""
609      print "Solving extensive form written to file="+os.path.expanduser(options.ef_output_file)
610      print ""
611
612      ef_solver = SolverFactory(options.solver_type)
613      if ef_solver is None:
614         raise ValueError, "Failed to create solver of type="+options.solver_type+" for use in extensive form solve"
615      if len(options.ef_solver_options) > 0:
616         print "Initializing ef solver with options="+str(options.ef_solver_options)
617         ef_solver.set_options("".join(options.ef_solver_options))
618      if options.ef_mipgap is not None:
619         if (options.ef_mipgap < 0.0) or (options.ef_mipgap > 1.0):
620            raise ValueError, "Value of the mipgap parameter for the EF solve must be on the unit interval; value specified=" + `options.ef_mipgap`
621         else:
622            ef_solver.mipgap = options.ef_mipgap
623
624      ef_solver_manager = SolverManagerFactory(options.solver_manager_type)
625      if ef_solver is None:
626         raise ValueError, "Failed to create solver manager of type="+options.solver_type+" for use in extensive form solve"
627
628      print "Queuing extensive form solve"
629      ef_action_handle = ef_solver_manager.queue(os.path.expanduser(options.ef_output_file), opt=ef_solver, tee=options.output_ef_solver_log)
630      print "Waiting for extensive form solve"
631      ef_results = ef_solver_manager.wait_for(ef_action_handle)
632
633      load_ef_solution(ef_results, binding_instance, ph._instances)
634      ph._scenario_tree.snapshotSolutionFromInstances(ph._instances)
635
636      print ""
637      print "Extensive form solution:"
638      ph._scenario_tree.pprintSolution()
639      print ""
640      print "Extensive form costs:"
641      ph._scenario_tree.pprintCosts(ph._instances)
642
643      solution_writer_plugins = ExtensionPoint(ISolutionWriterExtension)
644      for plugin in solution_writer_plugins:
645         plugin.write(ph._scenario_tree, "postphef")
646
647#
648# The main PH initialization / runner routine. Really only branches based on
649# the construction source - a checkpoint or from scratch.
650#
651
652def exec_ph(options):
653
654   ph = None
655
656   # validate the solution writer plugin exists, to avoid a lot of wasted work.
657   for solution_writer_name in options.solution_writer:
658      print "Trying to import solution writer="+solution_writer_name
659      __import__(solution_writer_name)
660      print "Module successfully loaded"
661
662   # if we are restoring from a checkpoint file, do so - otherwise, construct PH from scratch.
663   if len(options.restore_from_checkpoint) > 0:
664      ph = create_ph_from_checkpoint(options)
665
666   else:
667      reference_model, reference_instance, scenario_tree, scenario_tree_instance = load_reference_and_scenario_models(options)
668      if reference_model is None or reference_instance is None or scenario_tree is None:
669         return
670      ph = create_ph_from_scratch(options, reference_model, reference_instance, scenario_tree)
671
672   if ph is None:
673      print "***FAILED TO CREATE PH OBJECT"
674      return
675
676   run_ph(options, ph)
677
678#
679# the main driver routine for the runph script.
680#
681
682def run(args=None):
683
684    #
685    # Top-level command that executes the extensive form writer.
686    # This is segregated from run_ef_writer to enable profiling.
687    #
688
689    #
690    # Parse command-line options.
691    #
692    try:
693       ph_options_parser = construct_ph_options_parser("runph [options]")
694       (options, args) = ph_options_parser.parse_args(args=args)
695    except SystemExit:
696       # the parser throws a system exit if "-h" is specified - catch
697       # it to exit gracefully.
698       return
699    #
700    # Control the garbage collector - more critical than I would like at the moment.
701    #
702
703    if options.disable_gc is True:
704       gc.disable()
705    else:
706       gc.enable()
707
708    #
709    # Run PH - precise invocation depends on whether we want profiling output.
710    #
711
712    if options.profile > 0:
713        #
714        # Call the main PH routine with profiling.
715        #
716        tfile = pyutilib.services.TempfileManager.create_tempfile(suffix=".profile")
717        tmp = profile.runctx('exec_ph(options)',globals(),locals(),tfile)
718        p = pstats.Stats(tfile).strip_dirs()
719        p.sort_stats('time', 'cum')
720        p = p.print_stats(options.profile)
721        p.print_callers(options.profile)
722        p.print_callees(options.profile)
723        p = p.sort_stats('cum','calls')
724        p.print_stats(options.profile)
725        p.print_callers(options.profile)
726        p.print_callees(options.profile)
727        p = p.sort_stats('calls')
728        p.print_stats(options.profile)
729        p.print_callers(options.profile)
730        p.print_callees(options.profile)
731        pyutilib.services.TempfileManager.clear_tempfiles()
732        ans = [tmp, None]
733    else:
734        #
735        # Call the main PH routine without profiling.
736        #
737
738        if options.traceback is True:
739           ans = exec_ph(options)
740        else:
741           try:
742              ans = exec_ph(options)
743           except ValueError, str:
744              print "VALUE ERROR:"
745              print str
746           except TypeError, str:
747              print "TYPE ERROR:"
748              print str
749           except NameError, str:
750              print "NAME ERROR:"
751              print str                           
752           except IOError, str:
753              print "IO ERROR:"
754              print str
755           except pyutilib.common.ApplicationError, str:
756              print "APPLICATION ERROR:"
757              print str
758           except RuntimeError, str:
759              print "RUN-TIME ERROR:"   
760              print str       
761           except:
762              print "Encountered unhandled exception"
763              traceback.print_exc()
764           sys.exit(0)
765
766    gc.enable()
767
768    return ans
Note: See TracBrowser for help on using the repository browser.