source: coopr.pysp/trunk/coopr/pysp/ef_writer_script.py @ 2453

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

Added some error handling logic to the extensive form writer, to deal with an unexpected (but valid) exception.

  • Property svn:executable set to *
File size: 9.5 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 textwrap
18import traceback
19import cProfile
20import pstats
21import gc
22
23from coopr.pysp.ef import *
24
25from coopr.opt.base import SolverFactory
26from coopr.opt.parallel import SolverManagerFactory
27
28#
29# utility method to construct an option parser for ef writer arguments
30#
31
32def construct_ef_writer_options_parser(usage_string):
33
34   parser = OptionParser()
35   parser.add_option("--verbose",
36                     help="Generate verbose output, beyond the usual status output. Default is False.",
37                     action="store_true",
38                     dest="verbose",
39                     default=False)
40   parser.add_option("--model-directory",
41                     help="The directory in which all model (reference and scenario) definitions are stored. Default is \".\".",
42                     action="store",
43                     dest="model_directory",
44                     type="string",
45                     default=".")
46   parser.add_option("--instance-directory",
47                     help="The directory in which all instance (reference and scenario) definitions are stored. Default is \".\".",
48                     action="store",
49                     dest="instance_directory",
50                     type="string",
51                     default=".")
52   parser.add_option("--generate-weighted-cvar",
53                     help="Add a weighted CVaR term to the primary objective",
54                     action="store_true",
55                     dest="generate_weighted_cvar",
56                     default=False)
57   parser.add_option("--cvar-weight",
58                     help="The weight associated with the CVaR term in the risk-weighted objective formulation. Default is 1.0. If the weight is 0, then *only* a non-weighted CVaR cost will appear in the EF objective - the expected cost component will be dropped.",
59                     action="store",
60                     dest="cvar_weight",
61                     type="float",
62                     default=1.0)
63   parser.add_option("--risk-alpha",
64                     help="The probability threshold associated with cvar (or any future) risk-oriented performance metrics. Default is 0.95.",
65                     action="store",
66                     dest="risk_alpha",
67                     type="float",
68                     default=0.95)
69   parser.add_option("--output-file",
70                     help="Specify the name of the extensive form output file",
71                     action="store",
72                     dest="output_file",
73                     type="string",
74                     default="efout.lp")
75   parser.add_option("--solve",
76                     help="Following write of the extensive form model, solve it.",
77                     action="store_true",
78                     dest="solve_ef",
79                     default=False)
80   parser.add_option("--solver",
81                     help="The type of solver used to solve scenario sub-problems. Default is cplex.",
82                     action="store",
83                     dest="solver_type",
84                     type="string",
85                     default="cplex")
86   parser.add_option("--solver-manager",
87                     help="The type of solver manager used to coordinate scenario sub-problem solves. Default is serial.",
88                     action="store",
89                     dest="solver_manager_type",
90                     type="string",
91                     default="serial")
92   parser.add_option("--solver-options",
93                     help="Solver options for the extension form problem",
94                     action="append",
95                     dest="solver_options",
96                     type="string",
97                     default=[])
98   parser.add_option("--mipgap",
99                     help="Specifies the mipgap for the EF solve",
100                     action="store",
101                     dest="mipgap",
102                     type="float",
103                     default=None)   
104   parser.add_option("--output-solver-log",
105                     help="Output solver log during the extensive form solve",
106                     action="store_true",
107                     dest="output_solver_log",
108                     default=False)   
109   parser.add_option("--profile",
110                     help="Enable profiling of Python code.  The value of this option is the number of functions that are summarized.",
111                     action="store",
112                     dest="profile",
113                     default=0)
114   parser.add_option("--disable-gc",
115                     help="Disable the python garbage collecter. Default is False.",
116                     action="store_true",
117                     dest="disable_gc",
118                     default=False)
119   parser.usage=usage_string
120
121   return parser
122   
123def run_ef_writer(options, args):
124
125   # if the user enabled the addition of the weighted cvar term to the objective,
126   # then validate the associated parameters.
127   generate_weighted_cvar = False
128   cvar_weight = None
129   risk_alpha = None
130
131   if options.generate_weighted_cvar is True:
132
133      generate_weighted_cvar = True
134      cvar_weight = options.cvar_weight
135      risk_alpha = options.risk_alpha
136
137   scenario_tree, binding_instance, scenario_instances = write_ef_from_scratch(os.path.expanduser(options.model_directory),
138                                                                               os.path.expanduser(options.instance_directory),
139                                                                               os.path.expanduser(options.output_file),
140                                                                               options.verbose,
141                                                                               generate_weighted_cvar, cvar_weight, risk_alpha)
142
143   if (scenario_tree is None) or (binding_instance is None) or (scenario_instances is None):
144      raise RuntimeError, "Failed to write extensive form."     
145
146   if options.solve_ef is True:
147
148      ef_solver = SolverFactory(options.solver_type)
149      if ef_solver is None:
150         raise ValueError, "Failed to create solver of type="+options.solver_type+" for use in extensive form solve"
151      if len(options.solver_options) > 0:
152         print "Initializing ef solver with options="+str(options.solver_options)         
153         ef_solver.set_options("".join(options.solver_options))
154      if options.mipgap is not None:
155         if (options.mipgap < 0.0) or (options.mipgap > 1.0):
156            raise ValueError, "Value of the mipgap parameter for the EF solve must be on the unit interval; value specified=" + `options.mipgap`
157         else:
158            ef_solver.mipgap = options.mipgap
159
160      ef_solver_manager = SolverManagerFactory(options.solver_manager_type)
161      if ef_solver is None:
162         raise ValueError, "Failed to create solver manager of type="+options.solver_type+" for use in extensive form solve"
163
164      print "Queuing extensive form solve"
165      ef_action_handle = ef_solver_manager.queue(os.path.expanduser(options.output_file), opt=ef_solver, warmstart=False, tee=options.output_solver_log)
166      print "Waiting for extensive form solve"
167      ef_results = ef_solver_manager.wait_for(ef_action_handle)
168      load_ef_solution(ef_results, binding_instance, scenario_instances)
169      scenario_tree.snapshotSolutionFromInstances(scenario_instances)
170      print ""
171      print "Extensive form solution:"
172      scenario_tree.pprintSolution()
173      print ""
174      print "Extensive form costs:"
175      scenario_tree.pprintCosts(scenario_instances)
176
177def run(args=None):
178
179    #
180    # Top-level command that executes the extensive form writer.
181    # This is segregated from run_ef_writer to enable profiling.
182    #
183
184    #
185    # Parse command-line options.
186    #
187    try:
188       options_parser = construct_ef_writer_options_parser("efwriter [options]")
189       (options, args) = options_parser.parse_args(args=args)
190    except SystemExit:
191       # the parser throws a system exit if "-h" is specified - catch
192       # it to exit gracefully.
193       return
194
195    if options.disable_gc is True:
196       gc.disable()
197    else:
198       gc.enable()
199
200    if options.profile > 0:
201        #
202        # Call the main ef writer with profiling.
203        #
204        tfile = pyutilib.services.TempfileManager.create_tempfile(suffix=".profile")
205        tmp = cProfile.runctx('run_ef_writer(options,args)',globals(),locals(),tfile)
206        p = pstats.Stats(tfile).strip_dirs()
207        p.sort_stats('time', 'cum')
208        options.profile = eval(options.profile)
209        p = p.print_stats(options.profile)
210        p.print_callers(options.profile)
211        p.print_callees(options.profile)
212        p = p.sort_stats('cum','calls')
213        p.print_stats(options.profile)
214        p.print_callers(options.profile)
215        p.print_callees(options.profile)
216        p = p.sort_stats('calls')
217        p.print_stats(options.profile)
218        p.print_callers(options.profile)
219        p.print_callees(options.profile)
220        pyutilib.services.TempfileManager.clear_tempfiles()
221        ans = [tmp, None]
222    else:
223        #
224        # Call the main EF writer without profiling.
225        #
226        ans = run_ef_writer(options, args)
227
228    gc.enable()
229   
230    return ans
231
Note: See TracBrowser for help on using the repository browser.