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

Last change on this file since 3100 was 3100, checked in by khunter, 10 years ago

NFC: remove EOL whitespace

  • Property svn:executable set to *
File size: 12.2 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
19try:
20    import cProfile as profile
21except ImportError:
22    import profile
23import pstats
24import gc
25
26from coopr.pysp.ef import *
27
28from coopr.opt.base import SolverFactory
29from coopr.opt.parallel import SolverManagerFactory
30
31from pyutilib.component.core import ExtensionPoint
32from coopr.pysp.solutionwriter import ISolutionWriterExtension
33
34#
35# utility method to construct an option parser for ef writer arguments
36#
37
38def construct_ef_writer_options_parser(usage_string):
39
40   parser = OptionParser()
41   parser.add_option("--verbose",
42                     help="Generate verbose output, beyond the usual status output. Default is False.",
43                     action="store_true",
44                     dest="verbose",
45                     default=False)
46   parser.add_option("--model-directory",
47                     help="The directory in which all model (reference and scenario) definitions are stored. Default is \".\".",
48                     action="store",
49                     dest="model_directory",
50                     type="string",
51                     default=".")
52   parser.add_option("--instance-directory",
53                     help="The directory in which all instance (reference and scenario) definitions are stored. Default is \".\".",
54                     action="store",
55                     dest="instance_directory",
56                     type="string",
57                     default=".")
58   parser.add_option("--generate-weighted-cvar",
59                     help="Add a weighted CVaR term to the primary objective",
60                     action="store_true",
61                     dest="generate_weighted_cvar",
62                     default=False)
63   parser.add_option("--cvar-weight",
64                     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.",
65                     action="store",
66                     dest="cvar_weight",
67                     type="float",
68                     default=1.0)
69   parser.add_option("--risk-alpha",
70                     help="The probability threshold associated with cvar (or any future) risk-oriented performance metrics. Default is 0.95.",
71                     action="store",
72                     dest="risk_alpha",
73                     type="float",
74                     default=0.95)
75   parser.add_option("--output-file",
76                     help="Specify the name of the extensive form output file",
77                     action="store",
78                     dest="output_file",
79                     type="string",
80                     default="efout.lp")
81   parser.add_option("--solve",
82                     help="Following write of the extensive form model, solve it.",
83                     action="store_true",
84                     dest="solve_ef",
85                     default=False)
86   parser.add_option("--solver",
87                     help="The type of solver used to solve scenario sub-problems. Default is cplex.",
88                     action="store",
89                     dest="solver_type",
90                     type="string",
91                     default="cplex")
92   parser.add_option("--solver-manager",
93                     help="The type of solver manager used to coordinate scenario sub-problem solves. Default is serial.",
94                     action="store",
95                     dest="solver_manager_type",
96                     type="string",
97                     default="serial")
98   parser.add_option("--solver-options",
99                     help="Solver options for the extension form problem.",
100                     action="append",
101                     dest="solver_options",
102                     type="string",
103                     default=[])
104   parser.add_option("--mipgap",
105                     help="Specifies the mipgap for the EF solve.",
106                     action="store",
107                     dest="mipgap",
108                     type="float",
109                     default=None)
110   parser.add_option("--solution-writer",
111                     help="The plugin invoked to write the scenario tree solution. Defaults to the empty list.",
112                     action="append",
113                     dest="solution_writer",
114                     type="string",
115                     default = [])
116   parser.add_option("--output-solver-log",
117                     help="Output solver log during the extensive form solve.",
118                     action="store_true",
119                     dest="output_solver_log",
120                     default=False)
121   parser.add_option("--keep-solver-files",
122                     help="Retain temporary input and output files for solve.",
123                     action="store_true",
124                     dest="keep_solver_files",
125                     default=False)
126   parser.add_option("--profile",
127                     help="Enable profiling of Python code.  The value of this option is the number of functions that are summarized.",
128                     action="store",
129                     dest="profile",
130                     default=0)
131   parser.add_option("--disable-gc",
132                     help="Disable the python garbage collecter. Default is False.",
133                     action="store_true",
134                     dest="disable_gc",
135                     default=False)
136   parser.add_option('--traceback',
137                     help="When an exception is thrown, show the entire call stack. Ignored if profiling is enabled. Default is False.",
138                     action="store_true",
139                     dest="traceback",
140                     default=False)
141   parser.usage=usage_string
142
143   return parser
144
145def run_ef_writer(options, args):
146
147   # if the user enabled the addition of the weighted cvar term to the objective,
148   # then validate the associated parameters.
149   generate_weighted_cvar = False
150   cvar_weight = None
151   risk_alpha = None
152
153   if options.generate_weighted_cvar is True:
154
155      generate_weighted_cvar = True
156      cvar_weight = options.cvar_weight
157      risk_alpha = options.risk_alpha
158
159   # validate the solution writer plugin exists, to avoid a lot of wasted work.
160   for solution_writer_name in options.solution_writer:
161      print "Trying to import solution writer="+solution_writer_name
162      __import__(solution_writer_name)
163      print "Module successfully loaded"
164
165   scenario_tree, binding_instance, scenario_instances = write_ef_from_scratch(os.path.expanduser(options.model_directory),
166                                                                               os.path.expanduser(options.instance_directory),
167                                                                               os.path.expanduser(options.output_file),
168                                                                               options.verbose,
169                                                                               generate_weighted_cvar, cvar_weight, risk_alpha)
170
171   if (scenario_tree is None) or (binding_instance is None) or (scenario_instances is None):
172      raise RuntimeError, "Failed to write extensive form."
173
174   if options.solve_ef is True:
175
176      ef_solver = SolverFactory(options.solver_type)
177      if ef_solver is None:
178         raise ValueError, "Failed to create solver of type="+options.solver_type+" for use in extensive form solve"
179      if len(options.solver_options) > 0:
180         print "Initializing ef solver with options="+str(options.solver_options)
181         ef_solver.set_options("".join(options.solver_options))
182      if options.mipgap is not None:
183         if (options.mipgap < 0.0) or (options.mipgap > 1.0):
184            raise ValueError, "Value of the mipgap parameter for the EF solve must be on the unit interval; value specified=" + `options.mipgap`
185         else:
186            ef_solver.mipgap = options.mipgap
187      if options.keep_solver_files is True:
188         ef_solver.keepFiles = True
189
190      ef_solver_manager = SolverManagerFactory(options.solver_manager_type)
191      if ef_solver is None:
192         raise ValueError, "Failed to create solver manager of type="+options.solver_type+" for use in extensive form solve"
193
194      # at this point you have a specific solver - communicate solver capabilities
195      # to the writer via the instance.
196      binding_instance.has_capability = ef_solver.has_capability
197      for scenario_name, scenario_instance in scenario_instances.items():
198         scenario_instance.has_capability = ef_solver.has_capability
199
200      print "Queuing extensive form solve"
201      ef_action_handle = ef_solver_manager.queue(os.path.expanduser(options.output_file), opt=ef_solver, tee=options.output_solver_log)
202      print "Waiting for extensive form solve"
203      ef_results = ef_solver_manager.wait_for(ef_action_handle)
204      load_ef_solution(ef_results, binding_instance, scenario_instances)
205      scenario_tree.snapshotSolutionFromInstances(scenario_instances)
206
207      # handle output of solution from the scenario tree.
208      print ""
209      print "Extensive form solution:"
210      scenario_tree.pprintSolution()
211      print ""
212      print "Extensive form costs:"
213      scenario_tree.pprintCosts(scenario_instances)
214
215      solution_writer_plugins = ExtensionPoint(ISolutionWriterExtension)
216      for plugin in solution_writer_plugins:
217         plugin.write(scenario_tree, "ef")
218
219def run(args=None):
220
221    #
222    # Top-level command that executes the extensive form writer.
223    # This is segregated from run_ef_writer to enable profiling.
224    #
225
226    #
227    # Parse command-line options.
228    #
229    try:
230       options_parser = construct_ef_writer_options_parser("runef [options]")
231       (options, args) = options_parser.parse_args(args=args)
232    except SystemExit:
233       # the parser throws a system exit if "-h" is specified - catch
234       # it to exit gracefully.
235       return
236
237    if options.disable_gc is True:
238       gc.disable()
239    else:
240       gc.enable()
241
242    if options.profile > 0:
243        #
244        # Call the main ef writer with profiling.
245        #
246        tfile = pyutilib.services.TempfileManager.create_tempfile(suffix=".profile")
247        tmp = profile.runctx('run_ef_writer(options,args)',globals(),locals(),tfile)
248        p = pstats.Stats(tfile).strip_dirs()
249        p.sort_stats('time', 'cum')
250        options.profile = eval(options.profile)
251        p = p.print_stats(options.profile)
252        p.print_callers(options.profile)
253        p.print_callees(options.profile)
254        p = p.sort_stats('cum','calls')
255        p.print_stats(options.profile)
256        p.print_callers(options.profile)
257        p.print_callees(options.profile)
258        p = p.sort_stats('calls')
259        p.print_stats(options.profile)
260        p.print_callers(options.profile)
261        p.print_callees(options.profile)
262        pyutilib.services.TempfileManager.clear_tempfiles()
263        ans = [tmp, None]
264    else:
265        #
266        # Call the main EF writer without profiling.
267        #
268        if options.traceback is True:
269           ans = run_ef_writer(options, args)
270        else:
271           try:
272              ans = run_ef_writer(options, args)
273           except ValueError, str:
274              print "VALUE ERROR:"
275              print str
276           except TypeError, str:
277              print "TYPE ERROR:"
278              print str
279           except NameError, str:
280              print "NAME ERROR:"
281              print str
282           except IOError, str:
283              print "IO ERROR:"
284              print str
285           except pyutilib.common.ApplicationError, str:
286              print "APPLICATION ERROR:"
287              print str
288           except RuntimeError, str:
289              print "RUN-TIME ERROR:"
290              print str
291           except:
292              print "Encountered unhandled exception"
293              traceback.print_exc()
294           sys.exit(0)
295
296    gc.enable()
297
298    return ans
299
Note: See TracBrowser for help on using the repository browser.