def _declare_options(cls, options=None): if options is None: options = PySPConfigBlock() safe_declare_unique_option( options, "firststage_suffix", PySPConfigValue( "__DDSIP_FIRSTSTAGE", domain=_domain_must_be_str, description=( "The suffix used to identity first-stage " "variables to DDSIP. Default is " "'__DDSIP_FIRSTSTAGE'" ), doc=None, visibility=0), ap_group=_ddsip_group_label) safe_declare_unique_option( options, "config_file", PySPConfigValue( None, domain=_domain_must_be_str, description=( "The name of a partial DDSIP configuration file " "that contains option specifications unrelated to " "the problem structure. If specified, the contents " "of this file will be appended to the " "configuration created by this solver interface. " "Default is None." ), doc=None, visibility=0), ap_group=_ddsip_group_label) safe_declare_common_option(options, "verbose", ap_group=_ddsip_group_label) return options
def _declare_options(cls, options=None): if options is None: options = PySPConfigBlock() safe_declare_unique_option( options, "firststage_suffix", PySPConfigValue( "__DDSIP_FIRSTSTAGE", domain=_domain_must_be_str, description=("The suffix used to identity first-stage " "variables to DDSIP. Default is " "'__DDSIP_FIRSTSTAGE'"), doc=None, visibility=0), ap_group=_ddsip_group_label) safe_declare_unique_option( options, "config_file", PySPConfigValue( None, domain=_domain_must_be_str, description=( "The name of a partial DDSIP configuration file " "that contains option specifications unrelated to " "the problem structure. If specified, the contents " "of this file will be appended to the " "configuration created by this solver interface. " "Default is None."), doc=None, visibility=0), ap_group=_ddsip_group_label) safe_declare_common_option(options, "verbose", ap_group=_ddsip_group_label) return options
def _declare_options(cls, options=None): if options is None: options = PySPConfigBlock() safe_declare_common_option(options, "max_iterations", ap_group=_admm_group_label) safe_declare_unique_option( options, "primal_residual_relative_tolerance", PySPConfigValue( 1.0e-4, domain=_domain_positive, description=( "Relative primal-residual tolerance. Default is 1e-4." ), doc=None, visibility=0), ap_group=_admm_group_label) safe_declare_unique_option( options, "dual_residual_relative_tolerance", PySPConfigValue( 1.0e-4, domain=_domain_positive, description=( "Relative dual-residual tolerance. Default is 1e-4." ), doc=None, visibility=0), ap_group=_admm_group_label) ADMMAlgorithm._declare_options(options) for rstype in RhoStrategyFactory.registered_types.values(): rstype._declare_options(options) assert 'adaptive' in RhoStrategyFactory.registered_types safe_declare_unique_option( options, "rho_strategy", PySPConfigValue( 'adaptive', domain=_domain_must_be_str, description=( "Rho update strategy. Choices are: %s. Default is 'adaptive'." % (str(sorted(RhoStrategyFactory.registered_types.keys()))) ), doc=None, visibility=0), ap_group=_admm_group_label) return options
def _declare_options(cls, options=None): if options is None: options = PySPConfigBlock() safe_declare_common_option(options, "max_iterations", ap_group=_admm_group_label) safe_declare_unique_option( options, "primal_residual_relative_tolerance", PySPConfigValue( 1.0e-4, domain=_domain_positive, description=( "Relative primal-residual tolerance. Default is 1e-4." ), doc=None, visibility=0), ap_group=_admm_group_label) safe_declare_unique_option( options, "dual_residual_relative_tolerance", PySPConfigValue( 1.0e-4, domain=_domain_positive, description=( "Relative dual-residual tolerance. Default is 1e-4." ), doc=None, visibility=0), ap_group=_admm_group_label) ADMMAlgorithm._declare_options(options) for rstype in RhoStrategyFactory.registered_types.values(): rstype._declare_options(options) assert 'adaptive' in RhoStrategyFactory.registered_types safe_declare_unique_option( options, "rho_strategy", PySPConfigValue( 'adaptive', domain=_domain_must_be_str, description=( "Rho update strategy. Choices are: %s. Default is 'adaptive'." % (str(sorted(RhoStrategyFactory.registered_types.keys()))) ), doc=None, visibility=0), ap_group=_admm_group_label) return options
def _declare_options(cls, options=None): if options is None: options = PySPConfigBlock() safe_declare_unique_option( options, "cvar_weight", PySPConfigValue( 1.0, domain=_domain_nonnegative, description=( "The weight associated with the CVaR term in " "the risk-weighted objective " "formulation. 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. Default is 1.0." ), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_unique_option( options, "generate_weighted_cvar", PySPConfigValue( False, domain=bool, description=( "Add a weighted CVaR term to the " "primary objective. Default is False." ), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_unique_option( options, "risk_alpha", PySPConfigValue( 0.95, domain=_domain_unit_interval, description=( "The probability threshold associated with " "CVaR (or any future) risk-oriented " "performance metrics. Default is 0.95." ), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_unique_option( options, "cc_alpha", PySPConfigValue( 0.0, domain=_domain_unit_interval, description=( "The probability threshold associated with a " "chance constraint. The RHS will be one " "minus this value. Default is 0." ), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_unique_option( options, "cc_indicator_var", PySPConfigValue( None, domain=_domain_must_be_str, description=( "The name of the binary variable to be used " "to construct a chance constraint. Default " "is None, which indicates no chance " "constraint." ), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_common_option(options, "solver") safe_declare_common_option(options, "solver_io") safe_declare_common_option(options, "solver_manager") safe_declare_common_option(options, "solver_options") safe_declare_common_option(options, "disable_warmstart") safe_declare_common_option(options, "solver_manager_pyro_host") safe_declare_common_option(options, "solver_manager_pyro_port") safe_declare_common_option(options, "solver_manager_pyro_shutdown") safe_declare_common_option(options, "verbose", ap_group=_ef_group_label) safe_declare_common_option(options, "output_times", ap_group=_ef_group_label) safe_declare_common_option(options, "output_solver_results", ap_group=_ef_group_label) return options
def runef_register_options(options=None): if options is None: options = PySPConfigBlock() EFSolver.register_options(options) ScenarioTreeManagerClientSerial.register_options(options) safe_register_common_option(options, "verbose") safe_register_common_option(options, "disable_gc") safe_register_common_option(options, "profile") safe_register_common_option(options, "traceback") safe_register_common_option(options, "symbolic_solver_labels") safe_register_common_option(options, "output_solver_log") safe_register_common_option(options, "keep_solver_files") safe_register_common_option(options, "output_scenario_tree_solution") safe_register_common_option(options, "solution_saver_extension") safe_register_common_option(options, "solution_loader_extension") safe_register_unique_option( options, "solution_writer", PySPConfigValue( (), domain=_domain_tuple_of_str, description=( "The name of a python module specifying a user-defined " "plugin implementing the ISolutionWriterExtension " "interface. Invoked to save a scenario tree solution. Use " "this option when generating a template configuration file " "or invoking command-line help in order to include any " "plugin-specific options. This option can used multiple " "times from the command line to specify more than one " "plugin." ), doc=None, visibility=0), ap_kwds={'action': 'append'}, ap_group=_extension_options_group_title) safe_register_unique_option( options, "output_file", PySPConfigValue( None, domain=_domain_must_be_str, description=( "The name of the extensive form output file " "(currently LP, MPS, and NL file formats are " "supported). If the option value does not end " "in '.lp', '.mps', or '.nl', then the output format " "will be inferred from the settings for the chosen " "solver interface, and the appropriate suffix " "will be appended to the name. Use of this option " "will disable the solve." ), doc=None, visibility=0), ap_group=_output_options_group_title) safe_register_unique_option( options, "output_scenario_costs", PySPConfigValue( None, domain=_domain_must_be_str, description=( "A file name where individual scenario costs from the " "solution will be stored. The format is determined " "from the extension used in the filename. Recognized " "extensions: [.csv, .json, .yaml]" ), doc=None, visibility=0)) # # Deprecated # class _DeprecatedActivateJSONIOSolutionSaver( pyutilib.misc.config.argparse.Action): def __init__(self, option_strings, dest, nargs=None, **kwargs): if nargs is not None: raise ValueError("nargs not allowed") super(_DeprecatedActivateJSONIOSolutionSaver, self).\ __init__(option_strings, dest, nargs=0, **kwargs) def __call__(self, parser, namespace, values, option_string=None): logger.warning( "DEPRECATED: The '--activate-json-io-solution-saver " "command-line option has been deprecated and will " "be removed in the future. Please the following instead: " "'----solution-saver-extension=pyomo.pysp.plugins.jsonio'") val = getattr(namespace, 'CONFIGBLOCK.solution_saver_extension', []) setattr(namespace, 'CONFIGBLOCK.solution_saver_extension', val + ["pyomo.pysp.plugins.jsonio"]) def _warn_activate_jsonio_solution_saver(val): # don't use logger here since users might not import # the pyomo logger in a scripting interface sys.stderr.write( "\tWARNING: The 'activate_jsonio_solution_saver' " "config item will be ignored " "unless it is being used as a command-line option " "where it can be redirected to 'solution_saver_extension'. " "Please use 'solution_saver_extension=pyomo.pysp.plugins.jsonio' " "instead.\n") return _domain_tuple_of_str(val) safe_declare_unique_option( options, "activate_jsonio_solution_saver", PySPConfigValue( None, domain=_warn_activate_jsonio_solution_saver, description=( "Deprecated alias for " "--solution-saver-extension=pyomo.pysp.plugins.jsonio" ), doc=None, visibility=1), ap_kwds={'action':_DeprecatedActivateJSONIOSolutionSaver}, ap_group=_deprecated_options_group_title, declare_for_argparse=True) return options
def runef_register_options(options=None): if options is None: options = PySPConfigBlock() EFSolver.register_options(options) ScenarioTreeManagerClientSerial.register_options(options) safe_register_common_option(options, "verbose") safe_register_common_option(options, "disable_gc") safe_register_common_option(options, "profile") safe_register_common_option(options, "traceback") safe_register_common_option(options, "symbolic_solver_labels") safe_register_common_option(options, "output_solver_log") safe_register_common_option(options, "keep_solver_files") safe_register_common_option(options, "output_scenario_tree_solution") safe_register_common_option(options, "solution_saver_extension") safe_register_common_option(options, "solution_loader_extension") safe_register_unique_option( options, "solution_writer", PySPConfigValue( (), domain=_domain_tuple_of_str, description=( "The name of a python module specifying a user-defined " "plugin implementing the ISolutionWriterExtension " "interface. Invoked to save a scenario tree solution. Use " "this option when generating a template configuration file " "or invoking command-line help in order to include any " "plugin-specific options. This option can used multiple " "times from the command line to specify more than one " "plugin."), doc=None, visibility=0), ap_kwds={'action': 'append'}, ap_group=_extension_options_group_title) safe_register_unique_option( options, "output_file", PySPConfigValue( None, domain=_domain_must_be_str, description=("The name of the extensive form output file " "(currently LP, MPS, and NL file formats are " "supported). If the option value does not end " "in '.lp', '.mps', or '.nl', then the output format " "will be inferred from the settings for the chosen " "solver interface, and the appropriate suffix " "will be appended to the name. Use of this option " "will disable the solve."), doc=None, visibility=0), ap_group=_output_options_group_title) safe_register_unique_option( options, "output_scenario_costs", PySPConfigValue( None, domain=_domain_must_be_str, description=( "A file name where individual scenario costs from the " "solution will be stored. The format is determined " "from the extension used in the filename. Recognized " "extensions: [.csv, .json, .yaml]"), doc=None, visibility=0)) # # Deprecated # class _DeprecatedActivateJSONIOSolutionSaver( pyutilib.misc.config.argparse.Action): def __init__(self, option_strings, dest, nargs=None, **kwargs): if nargs is not None: raise ValueError("nargs not allowed") super(_DeprecatedActivateJSONIOSolutionSaver, self).\ __init__(option_strings, dest, nargs=0, **kwargs) def __call__(self, parser, namespace, values, option_string=None): logger.warning( "DEPRECATED: The '--activate-json-io-solution-saver " "command-line option has been deprecated and will " "be removed in the future. Please the following instead: " "'----solution-saver-extension=pyomo.pysp.plugins.jsonio'") val = getattr(namespace, 'CONFIGBLOCK.solution_saver_extension', []) setattr(namespace, 'CONFIGBLOCK.solution_saver_extension', val + ["pyomo.pysp.plugins.jsonio"]) def _warn_activate_jsonio_solution_saver(val): # don't use logger here since users might not import # the pyomo logger in a scripting interface sys.stderr.write( "\tWARNING: The 'activate_jsonio_solution_saver' " "config item will be ignored " "unless it is being used as a command-line option " "where it can be redirected to 'solution_saver_extension'. " "Please use 'solution_saver_extension=pyomo.pysp.plugins.jsonio' " "instead.\n") return _domain_tuple_of_str(val) safe_declare_unique_option( options, "activate_jsonio_solution_saver", PySPConfigValue( None, domain=_warn_activate_jsonio_solution_saver, description=( "Deprecated alias for " "--solution-saver-extension=pyomo.pysp.plugins.jsonio"), doc=None, visibility=1), ap_kwds={'action': _DeprecatedActivateJSONIOSolutionSaver}, ap_group=_deprecated_options_group_title, declare_for_argparse=True) return options
def _declare_options(cls, options=None): if options is None: options = PySPConfigBlock() safe_declare_unique_option( options, "cvar_weight", PySPConfigValue( 1.0, domain=_domain_nonnegative, description=("The weight associated with the CVaR term in " "the risk-weighted objective " "formulation. 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. Default is 1.0."), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_unique_option( options, "generate_weighted_cvar", PySPConfigValue( False, domain=bool, description=("Add a weighted CVaR term to the " "primary objective. Default is False."), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_unique_option( options, "risk_alpha", PySPConfigValue( 0.95, domain=_domain_unit_interval, description=("The probability threshold associated with " "CVaR (or any future) risk-oriented " "performance metrics. Default is 0.95."), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_unique_option( options, "cc_alpha", PySPConfigValue( 0.0, domain=_domain_unit_interval, description=("The probability threshold associated with a " "chance constraint. The RHS will be one " "minus this value. Default is 0."), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_unique_option( options, "cc_indicator_var", PySPConfigValue( None, domain=_domain_must_be_str, description=("The name of the binary variable to be used " "to construct a chance constraint. Default " "is None, which indicates no chance " "constraint."), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_common_option(options, "solver") safe_declare_common_option(options, "solver_io") safe_declare_common_option(options, "solver_manager") safe_declare_common_option(options, "solver_options") safe_declare_common_option(options, "disable_warmstart") safe_declare_common_option(options, "solver_manager_pyro_host") safe_declare_common_option(options, "solver_manager_pyro_port") safe_declare_common_option(options, "solver_manager_pyro_shutdown") safe_declare_common_option(options, "verbose", ap_group=_ef_group_label) safe_declare_common_option(options, "output_times", ap_group=_ef_group_label) safe_declare_common_option(options, "output_solver_results", ap_group=_ef_group_label) return options
class ExtensiveFormAlgorithm(PySPConfiguredObject): _declared_options = \ PySPConfigBlock("Options declared for the " "ExtensiveFormAlgorithm class") safe_declare_unique_option( _declared_options, "cvar_weight", PySPConfigValue( 1.0, domain=_domain_nonnegative, description=("The weight associated with the CVaR term in " "the risk-weighted objective " "formulation. 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. Default is 1.0."), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_unique_option( _declared_options, "generate_weighted_cvar", PySPConfigValue(False, domain=bool, description=("Add a weighted CVaR term to the " "primary objective. Default is False."), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_unique_option( _declared_options, "risk_alpha", PySPConfigValue( 0.95, domain=_domain_unit_interval, description=("The probability threshold associated with " "CVaR (or any future) risk-oriented " "performance metrics. Default is 0.95."), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_unique_option( _declared_options, "cc_alpha", PySPConfigValue( 0.0, domain=_domain_unit_interval, description=("The probability threshold associated with a " "chance constraint. The RHS will be one " "minus this value. Default is 0."), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_unique_option( _declared_options, "cc_indicator_var", PySPConfigValue( None, domain=_domain_must_be_str, description=("The name of the binary variable to be used " "to construct a chance constraint. Default " "is None, which indicates no chance " "constraint."), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_unique_option( _declared_options, "mipgap", PySPConfigValue(None, domain=_domain_unit_interval, description=("Specifies the mipgap for the EF solve."), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_unique_option( _declared_options, "solver", PySPConfigValue( "cplex", domain=_domain_must_be_str, description=("Specifies the solver used to solve the " "extensive form model. Default is cplex."), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_unique_option( _declared_options, "solver_io", PySPConfigValue( None, domain=_domain_must_be_str, description=("The type of IO used to execute the " "solver. Different solvers support different " "types of IO, but the following are common " "options: lp - generate LP files, nl - " "generate NL files, python - direct Python " "interface, os - generate OSiL XML files."), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_unique_option( _declared_options, "solver_manager", PySPConfigValue('serial', domain=_domain_must_be_str, description=("The type of solver manager used to " "coordinate solves. Default is serial."), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_unique_option( _declared_options, "solver_options", PySPConfigValue((), domain=_domain_tuple_of_str_or_dict, description=("Persistent solver options used when " "solving the extensive form model. This " "option can be used multiple times from " "the command line to specify more than " "one solver option."), doc=None, visibility=0), ap_kwds={'action': 'append'}, ap_group=_ef_group_label) safe_declare_unique_option( _declared_options, "disable_warmstart", PySPConfigValue(False, domain=bool, description=("Disable warm-start of EF solves. " "Default is False."), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_unique_option( _declared_options, "pyro_host", PySPConfigValue(None, domain=_domain_must_be_str, description=("The hostname to bind on when searching " "for a Pyro nameserver."), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_unique_option( _declared_options, "pyro_port", PySPConfigValue(None, domain=_domain_nonnegative_integer, description=("The port to bind on when searching for " "a Pyro nameserver."), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_unique_option( _declared_options, "pyro_shutdown", PySPConfigValue( False, domain=bool, description=( "Attempt to shut down all Pyro-related components " "associated with the Pyro name server used by any scenario " "tree manager or solver manager. Components to shutdown " "include the name server, dispatch server, and any " "scenariotreeserver or pyro_mip_server processes. Note " "that if Pyro4 is in use the nameserver will always " "ignore this request."), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_unique_option( _declared_options, "pyro_shutdown_workers", PySPConfigValue( False, domain=bool, description=( "Upon exit, send shutdown requests to all worker " "processes that were acquired through the dispatcher. " "This typically includes scenariotreeserver processes " "(used by the Pyro scenario tree manager) and pyro_mip_server " "processes (used by the Pyro solver manager). This leaves " "any dispatchers and namservers running as well as any " "processes registered with the dispather that were not " "acquired for work by this client."), doc=None, visibility=0), ap_group=_ef_group_label) safe_declare_common_option(_declared_options, "symbolic_solver_labels", ap_group=_ef_group_label) safe_declare_common_option(_declared_options, "output_solver_log", ap_group=_ef_group_label) safe_declare_common_option(_declared_options, "verbose", ap_group=_ef_group_label) safe_declare_common_option(_declared_options, "output_times", ap_group=_ef_group_label) safe_declare_common_option(_declared_options, "keep_solver_files", ap_group=_ef_group_label) safe_declare_common_option(_declared_options, "output_solver_results", ap_group=_ef_group_label) def __enter__(self): return self def __exit__(self, *args): self.close() def close(self): self.destroy_ef() if self._solver is not None: self._solver.deactivate() if self._solver_manager is not None: if isinstance(self._solver_manager, pyomo.solvers.plugins.smanager.\ pyro.SolverManager_Pyro): if self.get_option("pyro_shutdown_workers"): self._solver_manager.shutdown_workers() self._solver_manager.deactivate() self._solver_manager = None self._manager = None self.objective = undefined self.objective_sense = undefined self.gap = undefined self.termination_condition = undefined self.solver_status = undefined self.solution_status = undefined self.solver_results = undefined self.pyomo_solve_time = undefined self.solve_time = undefined def __init__(self, manager, *args, **kwds): import pyomo.solvers.plugins.smanager.pyro super(ExtensiveFormAlgorithm, self).__init__(*args, **kwds) # TODO: after PH moves over to the new code #if not isinstance(manager, ScenarioTreeManager): # raise TypeError("ExtensiveFormAlgorithm requires an instance of the " # "ScenarioTreeManager interface as the " # "second argument") if not manager.initialized: raise ValueError("ExtensiveFormAlgorithm requires a scenario tree " "manager that has been fully initialized") self._manager = manager self.instance = None self._solver_manager = None self._solver = None # The following attributes will be modified by the # solve() method. For users that are scripting, these # can be accessed after the solve() method returns. # They will be reset each time solve() is called. ############################################ self.objective = undefined self.gap = undefined self.termination_condition = undefined self.solver_status = undefined self.solution_status = undefined self.solver_results = undefined self.pyomo_solve_time = undefined self.solve_time = undefined ############################################ self._solver = SolverFactory(self.get_option("solver"), solver_io=self.get_option("solver_io")) if isinstance(self._solver, UnknownSolver): raise ValueError("Failed to create solver of type=" + self.get_option("solver") + " for use in extensive form solve") if len(self.get_option("solver_options")) > 0: if self.get_option("verbose"): print("Initializing ef solver with options=" + str(list(self.get_option("solver_options")))) self._solver.set_options("".join( self.get_option("solver_options"))) if self.get_option("mipgap") is not None: if (self.get_option("mipgap") < 0.0) or \ (self.get_option("mipgap") > 1.0): raise ValueError("Value of the mipgap parameter for the EF " "solve must be on the unit interval; " "value specified=" + str(self.get_option("mipgap"))) self._solver.options.mipgap = float(self.get_option("mipgap")) solver_manager_type = self.get_option("solver_manager") if solver_manager_type == "phpyro": print("*** WARNING ***: PHPyro is not a supported solver " "manager type for the extensive-form solver. " "Falling back to serial.") solver_manager_type = 'serial' self._solver_manager = SolverManagerFactory( solver_manager_type, host=self.get_option("pyro_host"), port=self.get_option("pyro_port")) if self._solver_manager is None: raise ValueError("Failed to create solver manager of type=" + self.get_option("solver") + " for use in extensive form solve") def build_ef(self): self.destroy_ef() if self.get_option("verbose"): print("Creating extensive form instance") start_time = time.time() # then validate the associated parameters. generate_weighted_cvar = False cvar_weight = None risk_alpha = None if self.get_option("generate_weighted_cvar"): generate_weighted_cvar = True cvar_weight = self.get_option("cvar_weight") risk_alpha = self.get_option("risk_alpha") self.instance = create_ef_instance( self._manager.scenario_tree, verbose_output=self.get_option("verbose"), generate_weighted_cvar=generate_weighted_cvar, cvar_weight=cvar_weight, risk_alpha=risk_alpha, cc_indicator_var_name=self.get_option("cc_indicator_var"), cc_alpha=self.get_option("cc_alpha")) if self.get_option("verbose") or self.get_option("output_times"): print("Time to construct extensive form instance=%.2f seconds" % (time.time() - start_time)) def destroy_ef(self): if self.instance is not None: for scenario in self._manager.scenario_tree.scenarios: self.instance.del_component(scenario.name) scenario._instance_objective.activate() self.instance = None def write(self, filename): if self.instance is None: raise RuntimeError( "The extensive form instance has not been constructed." "Call the build_ef() method to construct it.") suf = os.path.splitext(filename)[1] if suf not in ['.nl', '.lp', '.mps']: if self._solver.problem_format() == ProblemFormat.cpxlp: filename += '.lp' elif self._solver.problem_format() == ProblemFormat.nl: filename += '.nl' elif self._solver.problem_format() == ProblemFormat.mps: filename += '.mps' else: raise ValueError("Could not determine output file format. " "No recognized ending suffix was provided " "and no format was indicated was by the " "--solver-io option.") start_time = time.time() if self.get_option("verbose"): print("Starting to write extensive form") smap_id = write_ef(self.instance, filename, self.get_option("symbolic_solver_labels")) print("Extensive form written to file=" + filename) if self.get_option("verbose") or self.get_option("output_times"): print("Time to write output file=%.2f seconds" % (time.time() - start_time)) return filename, smap_id def solve(self, check_status=True, exception_on_failure=True, io_options=None): if self.instance is None: raise RuntimeError( "The extensive form instance has not been constructed." "Call the build_ef() method to construct it.") start_time = time.time() if self.get_option("verbose"): print("Queuing extensive form solve") self.objective = undefined self.gap = undefined self.bound = undefined self.pyomo_solve_time = undefined self.solve_time = undefined self.termination_condition = undefined self.solver_status = undefined self.solution_status = undefined self.solver_results = undefined if isinstance(self._solver, PersistentSolver): self._solver.set_instance(self.instance, symbolic_solver_labels=self.get_option( "symbolic_solver_labels")) solve_kwds = {} solve_kwds['load_solutions'] = False if self.get_option("keep_solver_files"): solve_kwds['keepfiles'] = True if self.get_option("symbolic_solver_labels"): solve_kwds['symbolic_solver_labels'] = True if self.get_option("output_solver_log"): solve_kwds['tee'] = True if io_options is not None: solve_kwds.update(io_options) self.objective_sense = \ find_active_objective(self.instance).sense if (not self.get_option("disable_warmstart")) and \ (self._solver.warm_start_capable()): action_handle = self._solver_manager.queue(self.instance, opt=self._solver, warmstart=True, **solve_kwds) else: action_handle = self._solver_manager.queue(self.instance, opt=self._solver, **solve_kwds) if self.get_option("verbose"): print("Waiting for extensive form solve") results = self._solver_manager.wait_for(action_handle) if self.get_option("verbose"): print("Done with extensive form solve - loading results") if self.get_option("output_solver_results"): print("Results for ef:") results.write(num=1) self.solver_results = results if hasattr(results.solver,"user_time") and \ (not isinstance(results.solver.user_time, UndefinedData)) and \ (results.solver.user_time is not None): # the solve time might be a string, or might # not be - we eventually would like more # consistency on this front from the solver # plugins. self.solve_time = \ float(results.solver.user_time) elif hasattr(results.solver, "time"): self.solve_time = \ float(results.solver.time) else: self.solve_time = undefined if hasattr(results, "pyomo_solve_time"): self.pyomo_solve_time = \ results.pyomo_solve_time else: self.pyomo_solve_times = undefined self.termination_condition = \ results.solver.termination_condition self.solver_status = \ results.solver.status if len(results.solution) > 0: assert len(results.solution) == 1 results_sm = results._smap self.instance.solutions.load_from(results) solution0 = results.solution(0) if hasattr(solution0, "gap") and \ (solution0.gap is not None): self.gap = solution0.gap else: self.gap = undefined self.solution_status = solution0.status if self.get_option("verbose"): print("Storing solution in scenario tree") for scenario in self._manager.scenario_tree.scenarios: scenario.update_solution_from_instance() self._manager.scenario_tree.snapshotSolutionFromScenarios() self.objective = self._manager.scenario_tree.\ findRootNode().\ computeExpectedNodeCost() if self.gap is not undefined: if self.objective_sense == pyomo.core.base.minimize: self.bound = self.objective - self.gap else: self.bound = self.objective + self.gap else: self.objective = undefined self.gap = undefined self.bound = undefined self.solution_status = undefined failure = False if check_status: if not ((self.solution_status == SolutionStatus.optimal) or \ (self.solution_status == SolutionStatus.feasible)): failure = True if self.get_option("verbose") or \ exception_on_failure: msg = ("EF solve failed solution status check:\n" "Solver Status: %s\n" "Termination Condition: %s\n" "Solution Status: %s\n" % (self.solver_status, self.termination_condition, self.solution_status)) if self.get_option("verbose"): print(msg) if exception_on_failure: raise RuntimeError(msg) else: if self.get_option("verbose"): print("EF solve completed. Skipping status check.") if self.get_option("verbose") or self.get_option("output_times"): print("Time to solve and load results for the " "extensive form=%.2f seconds" % (time.time() - start_time)) return failure
def _declare_options(cls, options=None): if options is None: options = PySPConfigBlock() safe_declare_unique_option( options, "stopping_rule_tolerance", PySPConfigValue( "nominal", domain=_domain_sd_tolerance, description=("Stopping rule tolerance used by the SD solver. " "Must be one of: %s. Default is 'nominal'." % (str(_domain_sd_tolerance._values))), doc=None, visibility=0), ap_group=_sd_group_label) safe_declare_unique_option( options, "single_replication", PySPConfigValue( False, domain=bool, description=("Disables multiple replication procedure in " "SD and uses a single replication."), doc=None, visibility=0), ap_group=_sd_group_label) safe_declare_unique_option( options, "print_cycle", PySPConfigValue( 100, domain=_domain_positive_integer, description=("Number of iterations between output of " "solution data to screen and file."), doc=None, visibility=0), ap_group=_sd_group_label) safe_declare_unique_option( options, "eval_run_flag", PySPConfigValue( False, domain=bool, description=( "Set to evaluate on the run. This should be " "only used for instances with relatively complete " "recourse. This flag is not recommended because " "accurate function evaluations are unnecessarily " "time consuming. It is best to use a large print " "cycle when this option is activated."), doc=None, visibility=0), ap_group=_sd_group_label) safe_declare_unique_option( options, "eval_flag", PySPConfigValue( False, domain=bool, description=( "Set to get an estimated objective function value " "for the final incumbent of each replication."), doc=None, visibility=0), ap_group=_sd_group_label) safe_declare_unique_option( options, "eval_seed1", PySPConfigValue( 2668655841019641, domain=int, description=( "Random number seed for re-sampling omegas during " "optimality test. Default is None, meaning no " "seed will be provided."), doc=None, visibility=0), ap_group=_sd_group_label) safe_declare_unique_option( options, "eval_error", PySPConfigValue( 0.01, domain=_domain_positive, description=( "Objective evaluation is accurate to within " "this much, with 95%% confidence. Default is 0.01."), doc=None, visibility=0), ap_group=_sd_group_label) safe_declare_unique_option( options, "mean_dev", PySPConfigValue( 0.05, domain=_domain_positive, description=("Solution tolerance for deciding the usage of " "mean solution. Default is 0.05."), doc=None, visibility=0), ap_group=_sd_group_label) safe_declare_unique_option( options, "min_iterations", PySPConfigValue( None, domain=_domain_nonnegative_integer, description=("Number of iterations which must pass before " "optimality is checked. Default is None, meaning " "no minimum is given."), doc=None, visibility=0), ap_group=_sd_group_label) safe_declare_unique_option( options, "max_iterations", PySPConfigValue( 5000, domain=_domain_positive_integer, description=("Maximum number of iterations for any given " "problem. Default is 5000."), doc=None, visibility=0), ap_group=_sd_group_label) safe_declare_common_option(options, "verbose", ap_group=_sd_group_label) return options