def solve(localsolver, solvername, instance, logfilename='logfile_loadobjective.log', get_suffixes=True, solver_options=None, outputfile=None): # Wall time - clock starts. starttime_modelsolve = time.time() if localsolver: solver = SolverFactory(solvername) # Configure with solver options # file_print_levels (Output Level-of-Detail): # 4 for just # of iterations, and final objective, infeas,etc. values # 6 for summary information about all iterations, but not variable values # 8 for variable values at all iterations # 10 for all iterations if solver_options: for k, v in solver_options.items(): solver.options[k] = v solver.options['OF_mumps_mem_percent'] = '5' # "OF_" prefix signals to Pyomo to create a temporary options file solver.options['OF_output_file'] = outputfile if get_suffixes: instance.dual = pyo.Suffix(direction=pyo.Suffix.IMPORT) instance.ipopt_zL_out = pyo.Suffix(direction=pyo.Suffix.IMPORT) instance.ipopt_zU_out = pyo.Suffix(direction=pyo.Suffix.IMPORT) setattr(instance, 'lambda', pyo.Suffix(direction=pyo.Suffix.IMPORT)) # use setattr because 'lambda' is reserved keyword try: results = solver.solve(instance, tee=True, symbolic_solver_labels=True, keepfiles=False, logfile=logfilename) except pyutilib.common._exceptions.ApplicationError: traceback.print_exc() return None else: opt = SolverFactory("cbc") solver_manager = SolverManagerFactory('neos') instance.dual = pyo.Suffix(direction=pyo.Suffix.IMPORT) instance.rc = pyo.Suffix(direction=pyo.Suffix.IMPORT) instance.dual = pyo.Suffix(direction=pyo.Suffix.IMPORT_EXPORT) # self.instance.slack = pyo.Suffix(direction=pyo.Suffix.IMPORT) opt.options["display_width"] = 170 opt.options["display"] = '_varname, _var.rc, _var.lb, _var, _var.ub, _var.slack' results = solver_manager.solve(instance, opt=opt, solver=solvername, logfile=logfilename) results.write() # Wall time - clock stops. _endtime_modelsolve = time.time() timefor_modelsolve = _endtime_modelsolve - starttime_modelsolve logger.info('*solving done* <- it took %f seconds>' % timefor_modelsolve) feasible = check_whether_feasible(instance, results) return instance, results, feasible
def optimize_model(model, email, cet, solver=OPT_DEFAULT): if not set_neos_email(email): if solver is not OPT_DEFAULT: assert_solver_available_locally(solver) elif cet == CET_ADDI: solver = "mosek" elif cet == CET_MULT: raise ValueError( "Please specify the solver for optimizing multiplicative model locally." ) solver_instance = SolverFactory(solver) print("Estimating the {} locally with {} solver.".format( CET_Model_Categories[cet], solver), flush=True) return solver_instance.solve(model, tee=True), 1 else: if solver is OPT_DEFAULT and cet is CET_ADDI: solver = "mosek" elif solver is OPT_DEFAULT and cet == CET_MULT: solver = "knitro" solver_instance = SolverManagerFactory('neos') print("Estimating the {} remotely with {} solver.".format( CET_Model_Categories[cet], solver), flush=True) return solver_instance.solve(model, tee=True, opt=solver), 1
def optimize(self, remote=True): """Optimize the function by requested method""" # TODO(error/warning handling): Check problem status after optimization if remote == False: if self.cet == "addi": solver = SolverFactory("mosek") self.problem_status = solver.solve(self.__model__, tee=True) self.optimization_status = 1 elif self.cet == "mult": # TODO(warning handling): Use log system instead of print() print( "Estimating the multiplicative model will be available in near future." ) return False else: if self.cet == "addi": opt = "mosek" elif self.cet == "mult": opt = "knitro" solver = SolverManagerFactory('neos') self.problem_status = solver.solve(self.__model__, tee=True, opt=opt) self.optimization_status = 1
def optimize(self, remote=True): """Optimize the function by requested method""" # TODO(error/warning handling): Check problem status after optimization if not remote: if self.cet == "addi": solver = SolverFactory("mosek") self.problem_status = solver.solve(self.__model__, tee=True) self.optimization_status = 1 elif self.cet == "mult": solver = SolverFactory('gams') self.problem_status = solver.solve(self.__model__, solver='minos', tee=True) self.optimization_status = 1 else: if self.cet == "addi": opt = "mosek" elif self.cet == "mult": opt = "knitro" solver = SolverManagerFactory('neos') self.problem_status = solver.solve(self.__model__, tee=True, opt=opt) self.optimization_status = 1
def solve_ef(master_instance, options): with SolverFactory(options.solver_type) as ef_solver: with SolverManagerFactory( options.solver_manager_type) as ef_solver_manager: if ef_solver is None: raise ValueError("Failed to create solver manager of type=" + options.solver_type + " for use in extensive form solve") if len(options.ef_solver_options) > 0: print("Initializing ef solver with options=" + str(options.ef_solver_options)) ef_solver.set_options("".join(options.ef_solver_options)) if options.ef_mipgap is not None: if (options.ef_mipgap < 0.0) or \ (options.ef_mipgap > 1.0): raise ValueError("Value of the mipgap parameter for the " "EF solve must be on the unit interval; " "value specified=" + str(options.ef_mipgap)) else: ef_solver.mipgap = options.ef_mipgap solve_kwds = {} solve_kwds['load_solutions'] = False if options.keep_solver_files: solve_kwds['keepfiles'] = True if options.symbolic_solver_labels: solve_kwds['symbolic_solver_labels'] = True if options.output_solver_log: solve_kwds['tee'] = True if options.write_fixed_variables: solve_kwds['output_fixed_variable_bounds'] = True if options.verbose: print("Solving extensive form.") if (not options.disable_warmstarts) and \ (ef_solver.warm_start_capable()): ef_action_handle = ef_solver_manager.queue(master_instance, opt=ef_solver, warmstart=True, **solve_kwds) else: ef_action_handle = ef_solver_manager.queue(master_instance, opt=ef_solver, **solve_kwds) results = ef_solver_manager.wait_for(ef_action_handle) # check the return code - if this is anything but "have a solution", we need to bail. if (results.solver.status == SolverStatus.ok) and \ ((results.solver.termination_condition == TerminationCondition.optimal) or \ ((len(results.solution) > 0) and (results.solution(0).status == SolutionStatus.optimal))): master_instance.solutions.load_from(results) return results raise RuntimeError("Extensive form was infeasible!")
def optimize(self, remote=True): """Optimize the function by requested method""" if remote == False: solver = SolverFactory("mosek") print("Estimating the model locally with mosek solver") self.problem_status = solver.solve(self.__model__, tee=True) self.optimization_status = 1 else: solver = SolverManagerFactory("neos") print("Estimating the model remotely with mosek solver") self.problem_status = solver.solve(self.__model__, tee=True, opt="mosek") self.optimization_status = 1
def optimize(self, remote=False): """Optimize the function by requested method""" # TODO(error/warning handling): Check problem status after optimization if remote == False: print("Estimating the model locally with mosek solver") solver = SolverFactory("mosek") self.problem_status = solver.solve(self.__model__, tee=True) print(self.problem_status) self.optimization_status = 1 else: print("Estimating the model remotely with mosek solver") solver = SolverManagerFactory('neos') self.problem_status = solver.solve(self.__model__, tee=True, opt="mosek") print(self.problem_status) self.optimization_status = 1
def run(args=None): ################################### # to import plugins import pyomo.environ import pyomo.solvers.plugins.smanager.phpyro def LagrangeMorePR(args=None): print("lagrangeMorePR begins %s" % datetime_string()) blanks = " " # used for formatting print statements class Object(object): pass Result = Object() # options used betaTol = options.beta_tol # tolerance used to separate b-values IndVarName = options.indicator_var_name multName = options.lambda_parm_name CCStageNum = options.stage_num MaxMorePR = options.max_number # max PR points to be generated (above F^* with all delta fixed) MaxTime = options.max_time # max time before terminate csvPrefix = options.csvPrefix # input filename prefix (eg, case name) probFileName = options.probFileName # name of file containing probabilities ##HG override # options.verbosity = 2 verbosity = options.verbosity Result.status = 'starting '+datetime_string() STARTTIME = time.time() ph = PHFromScratch(options) rootnode = ph._scenario_tree._stages[0]._tree_nodes[0] # use rootnode to loop over scenarios if find_active_objective(ph._scenario_tree._scenarios[0]._instance,safety_checks=True).is_minimizing(): print("We are solving a MINIMIZATION problem.") else: print("We are solving a MAXIMIZATION problem.") # initialize ScenarioList = [] with open(csvPrefix+"ScenarioList.csv",'r') as inputFile: for line in inputFile.readlines(): L = line.split(',') ScenarioList.append([L[0],float(L[1])]) addstatus = str(len(ScenarioList))+' scenarios read from file: ' + csvPrefix+'ScenarioList.csv' if verbosity > 0: print(addstatus) Result.status = Result.status + '\n' + addstatus PRoptimal = [] with open(csvPrefix+"PRoptimal.csv",'r') as inputFile: for line in inputFile.readlines(): bzS = line.split(',') PRoptimal.append( [None, float(bzS[0]), float(bzS[1])] ) addstatus = str(len(PRoptimal))+' PR points read from file: '+ csvPrefix+'PRoptimal.csv (envelope function)' if verbosity > 0: print(addstatus) Result.status = Result.status + '\n' + addstatus # ensure PR points on envelope function are sorted by probability PRoptimal.sort(key=operator.itemgetter(1)) PRoptimal[0][0] = 0 # initial lambda (for b=0) for p in range(1,len(PRoptimal)): dz = PRoptimal[p][2] - PRoptimal[p-1][2] db = PRoptimal[p][1] - PRoptimal[p-1][1] PRoptimal[p][0] = dz/db if verbosity > 0: PrintPRpoints(PRoptimal) Result.PRoptimal = PRoptimal lambdaval = 0. lagrUtil.Set_ParmValue(ph, options.lambda_parm_name,lambdaval) # IMPORTANT: Preprocess the scenario instances # before fixing variables, otherwise they # will be preprocessed out of the expressions # and the output_fixed_variable_bounds option # will have no effect when we update the # fixed variable values (and then assume we # do not need to preprocess again because # of this option). ph._preprocess_scenario_instances() ## read scenarios to select for each PR point on envelope function with open(csvPrefix+"OptimalSelections.csv",'r') as inputFile: OptimalSelections = [] for line in inputFile.readlines(): if len(line) == 0: break # eof selections = line.split(',') L = len(selections) Ls = len(selections[L-1]) selections[L-1] = selections[L-1][0:Ls-1] if verbosity > 1: print(str(selections)) OptimalSelections.append(selections) Result.OptimalSelections = OptimalSelections addstatus = str(len(OptimalSelections)) + ' Optimal selections read from file: ' \ + csvPrefix + 'OptimalSelections.csv' Result.status = Result.status + '\n' + addstatus if len(OptimalSelections) == len(PRoptimal): if verbosity > 0: print(addstatus) else: addstatus = addstatus + '\n** Number of selections not equal to number of PR points' print(addstatus) Result.status = Result.status + '\n' + addstatus print(str(OptimalSelections)) print((PRoptimal)) return Result ##################################################################################### # get probabilities if probFileName is None: # ...generate from widest gap regions PRlist = FindPRpoints(options, PRoptimal) else: # ...read probabilities probList = [] with open(probFileName,'r') as inputFile: if verbosity > 0: print("reading from probList = "+probFileName) for line in inputFile.readlines(): # 1 probability per line if len(line) == 0: break prob = float(line) probList.append(prob) if verbosity > 0: print("\t "+str(len(probList))+" probabilities") if verbosity > 1: print(str(probList)) PRlist = GetPoints(options, PRoptimal, probList) if verbosity > 1: print("PRlist:") for interval in PRlist: print(str(interval)) # We now have PRlist = [[i, b], ...], where b is in PRoptimal interval (i-1,i) addstatus = str(len(PRlist)) + ' probabilities' if verbosity > 0: print(addstatus) Result.status = Result.status + '\n' + addstatus ##################################################################################### lapsedTime = time.time() - STARTTIME addstatus = 'Initialize complete...lapsed time = ' + str(lapsedTime) if verbosity > 1: print(addstatus) Result.status = Result.status + '\n' + addstatus ##################################################################################### if verbosity > 1: print("\nlooping over Intervals to generate PR points by flipping heuristic") Result.morePR = [] for interval in PRlist: lapsedTime = time.time() - STARTTIME if lapsedTime > MaxTime: addstatus = '** lapsed time = ' + str(lapsedTime) + ' > max time = ' + str(MaxTime) if verbosity > 0: print(addstatus) Result.status = Result.status + '\n' + addstatus break i = interval[0] # = PR point index b = interval[1] # = target probability to reach by flipping from upper endpoint bU = PRoptimal[i][1] # = upper endpoint bL = PRoptimal[i-1][1] # = lower endpoint if verbosity > 1: print( "target probability = "+str(b)+" < bU = PRoptimal[" + str(i) + "][1]" \ " and > bL = PRoptimal["+str(i-1)+"][1]") if b < bL or b > bU: addstatus = '** probability = '+str(b) + ', not in gap interval: (' \ + str(bL) + ', ' + str(bU) + ')' print(addstatus) print(str(PRoptimal)) print(str(PRlist)) Result.status = Result.status + '\n' + addstatus return Result if verbosity > 1: print( "i = "+str(i)+" : Starting with bU = "+str(bU)+" having "+ \ str(len(OptimalSelections[i]))+ " selections:") print(str(OptimalSelections[i])) # first fix all scenarios = 0 for sname, sprob in ScenarioList: scenario = ph._scenario_tree.get_scenario(sname) lagrUtil.FixIndicatorVariableOneScenario(ph, scenario, IndVarName, 0) # now fix optimal selections = 1 for sname in OptimalSelections[i]: scenario = ph._scenario_tree.get_scenario(sname) lagrUtil.FixIndicatorVariableOneScenario(ph, scenario, IndVarName, 1) # flip scenario selections from bU until we reach b (target probability) bNew = bU for sname, sprob in ScenarioList: scenario = ph._scenario_tree.get_scenario(sname) if bNew - sprob < b: continue instance = ph._instances[sname] if getattr(instance, IndVarName).value == 0: continue bNew = bNew - sprob # flipped scenario selection lagrUtil.FixIndicatorVariableOneScenario(ph, scenario, IndVarName, 0) if verbosity > 1: print("\tflipped "+sname+" with prob = "+str(sprob)+" ...bNew = "+str(bNew)) if verbosity > 1: print("\tflipped selections reach "+str(bNew)+" >= target = "+str(b)+" (bL = "+str(bL)+")") if bNew <= bL + betaTol or bNew >= bU - betaTol: if verbosity > 0: print("\tNot generating PR point...flipping from bU failed") continue # to next interval in list # ready to solve to get cost for fixed scenario selections associated with probability = bNew if verbosity > 1: # check that scenarios are fixed as they should be totalprob = 0. for scenario in ScenarioList: sname = scenario[0] sprob = scenario[1] instance = ph._instances[sname] print("fix "+sname+" = "+str(getattr(instance,IndVarName).value)+\ " is "+str(getattr(instance,IndVarName).fixed)+" probability = "+str(sprob)) if getattr(instance,IndVarName).value == 1: totalprob = totalprob + sprob lambdaval = getattr(instance, multName).value print("\ttotal probability = %f" % totalprob) # solve (all delta fixed); lambda=0, so z = Lagrangian if verbosity > 0: print("solve begins %s" % datetime_string()) print("\t- lambda = %f" % lambdaval) SolStat, z = lagrUtil.solve_ph_code(ph, options) b = Compute_ExpectationforVariable(ph, IndVarName, CCStageNum) if verbosity > 0: print("solve ends %s" % datetime_string()) print("\t- SolStat = %s" % str(SolStat)) print("\t- b = %s" % str(b)) print("\t- z = %s" % str(z)) print("(adding to more PR points)") Result.morePR.append([None,b,z]) if verbosity > 1: PrintPRpoints(Result.morePR) ###################################################### # end loop over target probabilities with open(csvPrefix+"PRmore.csv",'w') as outFile: for point in Result.morePR: outFile.write(str(point[1])+','+str(point[2])) addstatus = str(len(Result.morePR)) + ' PR points written to file: '+ csvPrefix + 'PRmore.csv' if verbosity > 0: print(addstatus) Result.status = Result.status + '\n' + addstatus addstatus = 'lapsed time = ' + putcommas(time.time() - STARTTIME) if verbosity > 0: print(addstatus) Result.status = Result.status + '\n' + addstatus return Result ################################ # LagrangeMorePR ends here ################################ #### start run #### AllInOne = False # VERYSTARTTIME=time.time() # print "##############VERYSTARTTIME:",str(VERYSTARTTIME-VERYSTARTTIME) ########################## # options defined here ########################## try: conf_options_parser = construct_ph_options_parser("lagrange [options]") conf_options_parser.add_argument("--beta-min", help="The min beta level for the chance constraint. Default is None", action="store", dest="beta_min", type=float, default=None) conf_options_parser.add_argument("--beta-max", help="The beta level for the chance constraint. Default is None", action="store", dest="beta_max", type=float, default=None) conf_options_parser.add_argument("--min-prob", help="Tolerance for testing probability > 0. Default is 1e-5", action="store", dest="min_prob", type=float, default=1e-5) conf_options_parser.add_argument("--beta-tol", help="Tolerance for testing equality to beta. Default is 10^-2", action="store", dest="beta_tol", type=float, default=1e-2) conf_options_parser.add_argument("--Lagrange-gap", help="The (relative) Lagrangian gap acceptable for the chance constraint. Default is 10^-4.", action="store", type=float, dest="Lagrange_gap", default=0.0001) conf_options_parser.add_argument("--max-number", help="The max number of PR points. Default = 10.", action="store", dest="max_number", type=int, default=10) conf_options_parser.add_argument("--max-time", help="Maximum time (seconds). Default is 3600.", action="store", dest="max_time", type=float, default=3600) conf_options_parser.add_argument("--csvPrefix", help="Input file name prefix. Default is ''", action="store", dest="csvPrefix", type=str, default="") conf_options_parser.add_argument("--lambda-parm-name", help="The name of the lambda parameter in the model. Default is lambdaMult", action="store", dest="lambda_parm_name", type=str, default="lambdaMult") conf_options_parser.add_argument("--indicator-var-name", help="The name of the indicator variable for the chance constraint. The default is delta", action="store", dest="indicator_var_name", type=str, default="delta") conf_options_parser.add_argument("--stage-num", help="The stage number of the CC indicator variable (number, not name). Default is 2", action="store", dest="stage_num", type=int, default=2) conf_options_parser.add_argument("--verbosity", help="verbosity=0 is no extra output, =1 is medium, =2 is debug, =3 super-debug. Default is 1.", action="store", dest="verbosity", type=int, default=1) conf_options_parser.add_argument("--prob-file", help="file name specifiying probabilities", action="store", dest="probFileName", type=str, default=None) # The following needed for solve_ph_code in lagrangeutils conf_options_parser.add_argument("--solve-with-ph", help="Perform solves via PH rather than an EF solve. Default is False", action="store_true", dest="solve_with_ph", default=False) ################################################################ options = conf_options_parser.parse_args(args=args) # temporary hack options._ef_options = conf_options_parser._ef_options options._ef_options.import_argparse(options) except SystemExit as _exc: # the parser throws a system exit if "-h" is specified - catch # it to exit gracefully. return _exc.code if options.verbose is True: print("Loading reference model and scenario tree") scenario_instance_factory = \ ScenarioTreeInstanceFactory(options.model_directory, options.instance_directory) full_scenario_tree = \ GenerateScenarioTreeForPH(options, scenario_instance_factory) solver_manager = SolverManagerFactory(options.solver_manager_type) if solver_manager is None: raise ValueError("Failed to create solver manager of " "type="+options.solver_manager_type+ " specified in call to PH constructor") if isinstance(solver_manager, pyomo.solvers.plugins.smanager.phpyro.SolverManager_PHPyro): solver_manager.deactivate() raise ValueError("PHPyro can not be used as the solver manager") try: if (scenario_instance_factory is None) or (full_scenario_tree is None): raise RuntimeError("***ERROR: Failed to initialize the model and/or scenario tree data.") # load_model gets called again, so lets make sure unarchived directories are used options.model_directory = scenario_instance_factory._model_filename options.instance_directory = scenario_instance_factory._scenario_tree_filename scenario_count = len(full_scenario_tree._stages[-1]._tree_nodes) # create ph objects for finding the solution. we do this even if # we're solving the extensive form if options.verbose is True: print("Loading scenario instances and initializing scenario tree for full problem.") ########## Here is where multiplier search is called ############ Result = LagrangeMorePR() ##################################################################################### finally: solver_manager.deactivate() # delete temporary unarchived directories scenario_instance_factory.close() print("\n==================== returned from LagrangeMorePR") print(str(Result.status)) try: print("Envelope:") print(str(PrintPRpoints(Result.PRoptimal))) print("\nAdded:") PrintPRpoints(Result.morePR) except: print("from run: PrintPRpoints failed") sys.exit() # combine tables and sort by probability if len(Result.morePR) > 0: PRpoints = copy.deepcopy(Result.PRoptimal) for lbz in Result.morePR: PRpoints.append(lbz) print("Combined table of PR points (sorted):") PRpoints.sort(key=operator.itemgetter(1)) print(str(PrintPRpoints(PRpoints)))
def solve_model(self, model): """ Method to solve an optimization model using a specified solver Returns: :dict - solver statistics and model solution """ # Set a few default values attr_to_check = [ 'solver_name', 'neos', 'write_solution', 'return_solution', 'verbosity', 'solver_progress' ] for attr in attr_to_check: self.__chkattrt(attr) # Get model name model_name = model.name self.__model_name_str = str(re.sub(" ", "_", model_name)) # Solver name to lower case characters self.solver_name = self.solver_name.lower() # Confirm solver paths and thus availability self.__solvers_path_check() # NEOS vs local solvers: check solvers are recognised/available self.__solvers_compatibility_check() # Run solvers check # Call solver factory opt_solver = SolverFactory(self.solver_name) # Change solver temporary folder path log_folder = path.join('_log', '') if self.solver_name in ['gurobi', 'baron', 'cplex']: if not path.exists(log_folder): makedirs(log_folder) self.__set_tempdir(log_folder) else: pass # Include solver-compatible options if self.solver_name in ['cplex', 'gurobi']: opt_solver.options['threads'] = self.threads opt_solver.options['mipgap'] = self.rel_gap opt_solver.options['timelimit'] = self.time_limit elif self.solver_name in ['baron']: opt_solver.options['threads'] = self.threads opt_solver.options['LPSol'] = 3 opt_solver.options['EpsR'] = self.rel_gap opt_solver.options['MaxTime'] = self.time_limit # For Unix systems ensure "libcplexxxxx.dylib" is in the system PATH for baron to use CPLEX for MIPs elif self.solver_name in ['cbc']: opt_solver.options['threads'] = self.threads opt_solver.options['ratio'] = self.rel_gap opt_solver.options['seconds'] = self.time_limit opt_solver.options['log'] = int(self.solver_progress) * 2 opt_solver.options['mess'] = 'on' opt_solver.options['timeM'] = "elapsed" opt_solver.options['preprocess'] = "equal" elif self.solver_name in ['glpk']: opt_solver.options['mipgap'] = self.rel_gap opt_solver.options['tmlim'] = self.time_limit elif self.solver_name in ['ipopt']: opt_solver.options['max_wall_time'] = self.time_limit elif self.solver_name in ['bonmin']: opt_solver.options['time_limit'] = self.time_limit opt_solver.options['number_cpx_threads'] = self.threads opt_solver.options['allowable_fraction_gap'] = self.rel_gap elif self.solver_name in ['couenne']: opt_solver.options['time_limit'] = self.time_limit opt_solver.options['threads'] = self.threads opt_solver.options['ratio'] = self.rel_gap opt_solver.options['seconds'] = self.time_limit opt_solver.options['log'] = int(self.solver_progress) * 2 opt_solver.options['mess'] = 'on' opt_solver.options['timeM'] = "elapsed" opt_solver.options['preprocess'] = "equal" else: pass # Write log to file named <model_name>/DD_MM_YY_HH_MM_xx.log # Create (if it does not exist) the '_log' folder log_store_folder = path.join(log_folder, self.__model_name_str, '') if not path.exists(log_store_folder): makedirs(log_store_folder) self.__current_datetime_str = datetime.now().strftime( "%d_%m_%y_%H_%M_") file_suffix = 0 # Results filename if self.__model_name_str == 'Unknown' or len( self.__model_name_str) <= 10: log_filename = self.__model_name_str + self.__current_datetime_str + str( file_suffix) + ".log" else: log_filename = self.__model_name_str[:4] + '..' + self.__model_name_str[-4:] + \ self.__current_datetime_str + str(file_suffix) + ".log" while path.exists(log_store_folder + log_filename): file_suffix += 1 log_filename = self.__current_datetime_str + str( file_suffix) + ".log" log_filename = self.__current_datetime_str + str(file_suffix) + ".log" # Solve <model> with/without writing final solution to stdout processed_results = None self.__page_borders() # Headers for page try: if self.neos: self.solver_results = SolverManagerFactory('neos').solve( model, opt=opt_solver, tee=self.solver_progress) else: self.solver_results = opt_solver.solve( model, tee=self.solver_progress, logfile=log_store_folder + log_filename) # Process results obtained if self.neos: self.__msg( "Currently, results are not post-processed for NEOS server runs" ) #FIXME Find a work around else: processed_results = self._process_solver_results(model) except ValueError: self.__psmsg("Something went wrong with the solver") # Return model solution and solver statistics self.final_results = processed_results self.__page_borders(bottom=True) # Footer for page
class SolverWrapper: class __SolversInfo: """ Default info for solvers """ def __init__(self): self.configured_solvers = { # solver_name: ['windows executable', 'unix executable', 'solver_io'] 'cbc': ['cbc', 'cbc', 'lp'], 'cplex': ['cplex', 'cplex', 'lp'], 'glpk': ['glpk', 'glpk', 'lp'], 'gurobi': ['gurobi', 'gurobi.sh', 'python'], # Configure gurobi to use python api? 'baron': ['baron', 'baron', 'nl'], 'ipopt': ['ipopt', 'ipopt', 'lp'], 'couenne': ['couenne', 'couenne', 'nl'], 'bonmin': ['bonmin', 'bonmin', 'nl'] } self.neos_compatible = [ 'bonmin', 'cbc', 'conopt', 'couenne', 'cplex', 'filmint', 'filter', 'ipopt', 'knitro', 'l-bfgs-b', 'lancelot', 'lgo', 'loqo', 'minlp', 'minos', 'minto', 'mosek', 'ooqp', 'path', 'raposa', 'snopt' ] class __Constants: """ Default constants for use throughout the class """ def __init__(self): self.var_defaults = { 'solver_name': 'gurobi', 'solver_path': False, 'time_limit': 1200, 'threads': 2, 'neos': False, 'verbosity': False, 'debug_mode': False, 'solver_progress': True, 'write_solution': True, 'write_solution_to_stdout': True, 'return_solution': True, 'rel_gap': 0.0, 'result_precision': 6 } self.var_types = { 'time_limit': [int, float], 'threads': [int], 'neos': [bool], 'verbosity': [bool], 'debug_mode': [bool], 'solver_progress': [bool], 'write_solution': [bool], 'write_solution_to_stdout': [bool], 'return_solution': [bool], 'rel_gap': [int, float], 'result_precision': [int] } self.os_name = platform.system() def __init__(self, solver_name=None, solver_path=None, time_limit=None, threads=None, neos=None, verbosity=None, debug_mode=None, solver_progress=None, write_solution=None, write_solution_to_stdout=None, return_solution=None, rel_gap=None, result_precision=None, neos_registered_email=None): # Set methods defaults self.solver_info = self.__SolversInfo() self.constants = self.__Constants() self.solver_name = self.__apattr( solver_name, self.constants.var_defaults['solver_name']) self.solver_path = self.__apattr( solver_path, self.constants.var_defaults['solver_path']) # Set solver defaults self.time_limit = self.__apattr( time_limit, self.constants.var_defaults['time_limit']) self.threads = self.__apattr(threads, self.constants.var_defaults['threads']) self.neos = self.__apattr(neos, self.constants.var_defaults['neos']) self.verbosity = self.__apattr( verbosity, self.constants.var_defaults['verbosity']) self.debug_mode = self.__apattr( debug_mode, self.constants.var_defaults['debug_mode']) self.verbose_debug_mode = False self.solver_progress = self.__apattr( solver_progress, self.constants.var_defaults['solver_progress']) self.write_solution = self.__apattr( write_solution, self.constants.var_defaults['write_solution']) self.write_solution_to_stdout = self.__apattr( write_solution_to_stdout, self.constants.var_defaults['write_solution_to_stdout']) self.return_solution = self.__apattr( return_solution, self.constants.var_defaults['return_solution']) self.rel_gap = self.__apattr(rel_gap, self.constants.var_defaults['rel_gap']) self.result_precision = self.__apattr( result_precision, self.constants.var_defaults['result_precision']) # Set other defaults self.__model_name_str = None self.__current_datetime_str = None self.__pyomo_version = pyoversion.version self.__pyutilib_version = self.__get_pkg_version("PyUtilib") self.__dependency_check_count = 1 self.__dependency_check = self.__pyutilib_dependency_check() self.__DEF_registered_email = "*****@*****.**" self.__DEF_REGEX = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b' self.neos_registered_email = neos_registered_email self.neos_registered_email = self.__sg_neos_registered_email( defaults=False) def __sg_neos_registered_email(self, defaults=True): if self.neos_registered_email is None: if defaults: self.__msg( "NB: An email address can be passed to 'neos_registered_email' instead of using defaults." ) self.neos_registered_email = self.__DEF_registered_email return self.neos_registered_email else: if re.match(self.__DEF_REGEX, self.neos_registered_email): return self.neos_registered_email else: self.__msg( "An invalid email address was passed. Resorting to default..." ) self.neos_registered_email = None self.__sg_neos_registered_email( defaults=False ) # Tiny way to avoid repeated warnings to users return self.neos_registered_email def __apattr(self, attrib, value): """ Set value to an attrib :param attrib: :param value: :return: None """ if attrib is None: return value else: return attrib def __chkattrt(self, attrib): """ Check type of attrib against requirement and set to default else :param attrib: :return: None """ # Get attrib name as string c_var_list = [vars for vars in locals().keys() if "_" not in vars[:2]] attrib_str = None for var_l in c_var_list: if id(attrib) == id(var_l): attrib_str = var_l break else: pass if attrib_str is not None and attrib_str in self.constants.var_types.keys( ): if type(attrib) in self.constants.var_types[attrib_str]: pass else: self.__psmsg( 'Value given to ' + attrib_str + ' is invalid', 'The following value types are acceptable: ' + str(self.constants.var_types[attrib_str])) self.__psmsg('Setting default value. . .') setattr(self, attrib_str, self.constants.var_defaults[attrib_str]) else: pass def __msg(self, *msg, text_indent=4): text_indent = " " * int(text_indent) # Text wrapper function wrapper = textwrap.TextWrapper(width=60, initial_indent=text_indent, subsequent_indent=text_indent) # Print message print("\n") for message in msg: message = wrapper.wrap(text=str(message)) for element in message: print(element) return text_indent def __pemsg(self, *msg, exit=True): """ Custom error messages to print to stdout and stop execution :param message: Error message to be printed """ if self.debug_mode: exit = self.debug_mode else: exit = exit text_indent = self.__msg(*msg, text_indent=4) if exit: # Stop run print(text_indent + "Exiting . . .") sys.exit(1) else: pass def __psmsg(self, *msg): """ Custom status messages to print to stdout and stop execution :param message: Error message to be printed """ if self.verbosity: self.__msg("INFO:", *msg, text_indent=1) else: pass def __page_borders(self, bottom=False): if self.verbosity: if bottom: self.__msg("- - " * 15, "\n", text_indent=0) else: self.__msg("- - " * 15, text_indent=0) else: pass def __run_ext_command(self, cmd=[" "]): return subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0] def __get_solver_path(self, solver_exct): if self.constants.os_name == 'Windows': path = self.__run_ext_command(['where', solver_exct]).decode('utf-8') else: path = self.__run_ext_command(['which', solver_exct]).decode('utf-8') if path != '': return path, True else: return None, False def __get_pkg_version(self, pkg): parent_cmd = subprocess.Popen(['pip', 'freeze'], stdout=subprocess.PIPE) if self.constants.os_name == 'Windows': value = subprocess.check_output( ['findstr', str(pkg)], stdin=parent_cmd.stdout).decode('utf-8') else: value = subprocess.check_output( ['grep', str(pkg)], stdin=parent_cmd.stdout).decode('utf-8') if value == '': return value elif len(value) > len(pkg): value = value[len(pkg) + 2:] return value else: return None def __pyutilib_dependency_check(self): if self.__dependency_check_count <= 3: if self.__pyomo_version == '5.6.8': if '5.7.3' not in self.__pyutilib_version: system('pip install pyutilib==5.7.3') self.__pyutilib_version = self.__get_pkg_version( "PyUtilib") self.__dependency_check_count += 1 self.__pyutilib_dependency_check() else: self.__dependency_check = True elif self.__pyomo_version == '5.6.9': if '5.8.0' not in self.__pyutilib_version: system('pip install pyutilib==5.8.0') self.__pyutilib_version = self.__get_pkg_version( "PyUtilib") self.__dependency_check_count += 1 self.__pyutilib_dependency_check() else: self.__dependency_check = True elif self.__pyomo_version > '5.6.9': if '6.0.0' not in self.__pyutilib_version: system('pip install pyutilib==6.0.0') self.__pyutilib_version = self.__get_pkg_version( "PyUtilib") self.__dependency_check_count += 1 self.__pyutilib_dependency_check() else: self.__dependency_check = True else: self.__pemsg( "The right version of pyutilib could not be installed.") def __set_tempdir(self, folder): """ Set temporary solver folder :param folder: path to folder :return: """ if self.__pyomo_version <= '5.7.1': from pyutilib.services import TempfileManager TempfileManager.tempdir = folder else: from pyomo.common.tempfiles import TempfileManager TempfileManager.tempdir = folder def __get_set_list(self, pyo_obj): if self.__pyomo_version < '5.7.0'[:len(self.__pyomo_version)]: return [set for set in pyo_obj._index.set_tuple] else: return [set.name for set in pyo_obj._index.subsets()] def __get_set_list_alt(self, pyo_obj): if self.__pyomo_version < '5.7.0'[:len(self.__pyomo_version)]: return [set for set in pyo_obj.domain.set_tuple] else: return [set.name for set in pyo_obj.domain.subsets()] def __solvers_compatibility_check(self): """ NEOS vs local solvers: Check solvers are recognised/available :return: """ if self.neos: # using NEOS if self.solver_name not in self.solver_info.neos_compatible: self.__pemsg( "NEOS server does not seem to be configure for " + str(self.solver_name), "If you must used this solver, install a local version and set option 'neos' to 'False'", exit=False) self.__pemsg("Attempting to use a local solver instance . . .", exit=False) self.neos = False self.__solvers_path_check() self.__solvers_compatibility_check() else: environ['NEOS_EMAIL'] = self.__sg_neos_registered_email() if self.verbosity: self.__psmsg("Using NEOS server to solve model . . .") else: pass else: # using a locally installed solver if self.solver_name not in self.solver_info.configured_solvers.keys( ): self.__pemsg( self.solver_name + " is not amongst those currently configured by this package" ) elif not self.solver_avail: if self.solver_path is False: self.__pemsg(self.solver_name + " is not installed or at the path specified") else: self.solver_path = False self.__solvers_path_check() self.__solvers_compatibility_check() else: if self.verbosity: self.__psmsg("Solver located in {}".format( self.solver_path)) else: pass def __solvers_path_check(self): """ # Confirm solver paths and thus availability :return: """ if not self.neos: if self.solver_path is False: if self.constants.os_name == 'Windows': self.solver_path, self.solver_avail = \ self.__get_solver_path(self.solver_info.configured_solvers[self.solver_name][0]) else: self.solver_path, self.solver_avail = \ self.__get_solver_path(self.solver_info.configured_solvers[self.solver_name][1]) else: self.solver_avail = path.exists(self.solver_path) else: self.solver_avail = False def solve_model(self, model): """ Method to solve an optimization model using a specified solver Returns: :dict - solver statistics and model solution """ # Set a few default values attr_to_check = [ 'solver_name', 'neos', 'write_solution', 'return_solution', 'verbosity', 'solver_progress' ] for attr in attr_to_check: self.__chkattrt(attr) # Get model name model_name = model.name self.__model_name_str = str(re.sub(" ", "_", model_name)) # Solver name to lower case characters self.solver_name = self.solver_name.lower() # Confirm solver paths and thus availability self.__solvers_path_check() # NEOS vs local solvers: check solvers are recognised/available self.__solvers_compatibility_check() # Run solvers check # Call solver factory opt_solver = SolverFactory(self.solver_name) # Change solver temporary folder path log_folder = path.join('_log', '') if self.solver_name in ['gurobi', 'baron', 'cplex']: if not path.exists(log_folder): makedirs(log_folder) self.__set_tempdir(log_folder) else: pass # Include solver-compatible options if self.solver_name in ['cplex', 'gurobi']: opt_solver.options['threads'] = self.threads opt_solver.options['mipgap'] = self.rel_gap opt_solver.options['timelimit'] = self.time_limit elif self.solver_name in ['baron']: opt_solver.options['threads'] = self.threads opt_solver.options['LPSol'] = 3 opt_solver.options['EpsR'] = self.rel_gap opt_solver.options['MaxTime'] = self.time_limit # For Unix systems ensure "libcplexxxxx.dylib" is in the system PATH for baron to use CPLEX for MIPs elif self.solver_name in ['cbc']: opt_solver.options['threads'] = self.threads opt_solver.options['ratio'] = self.rel_gap opt_solver.options['seconds'] = self.time_limit opt_solver.options['log'] = int(self.solver_progress) * 2 opt_solver.options['mess'] = 'on' opt_solver.options['timeM'] = "elapsed" opt_solver.options['preprocess'] = "equal" elif self.solver_name in ['glpk']: opt_solver.options['mipgap'] = self.rel_gap opt_solver.options['tmlim'] = self.time_limit elif self.solver_name in ['ipopt']: opt_solver.options['max_wall_time'] = self.time_limit elif self.solver_name in ['bonmin']: opt_solver.options['time_limit'] = self.time_limit opt_solver.options['number_cpx_threads'] = self.threads opt_solver.options['allowable_fraction_gap'] = self.rel_gap elif self.solver_name in ['couenne']: opt_solver.options['time_limit'] = self.time_limit opt_solver.options['threads'] = self.threads opt_solver.options['ratio'] = self.rel_gap opt_solver.options['seconds'] = self.time_limit opt_solver.options['log'] = int(self.solver_progress) * 2 opt_solver.options['mess'] = 'on' opt_solver.options['timeM'] = "elapsed" opt_solver.options['preprocess'] = "equal" else: pass # Write log to file named <model_name>/DD_MM_YY_HH_MM_xx.log # Create (if it does not exist) the '_log' folder log_store_folder = path.join(log_folder, self.__model_name_str, '') if not path.exists(log_store_folder): makedirs(log_store_folder) self.__current_datetime_str = datetime.now().strftime( "%d_%m_%y_%H_%M_") file_suffix = 0 # Results filename if self.__model_name_str == 'Unknown' or len( self.__model_name_str) <= 10: log_filename = self.__model_name_str + self.__current_datetime_str + str( file_suffix) + ".log" else: log_filename = self.__model_name_str[:4] + '..' + self.__model_name_str[-4:] + \ self.__current_datetime_str + str(file_suffix) + ".log" while path.exists(log_store_folder + log_filename): file_suffix += 1 log_filename = self.__current_datetime_str + str( file_suffix) + ".log" log_filename = self.__current_datetime_str + str(file_suffix) + ".log" # Solve <model> with/without writing final solution to stdout processed_results = None self.__page_borders() # Headers for page try: if self.neos: self.solver_results = SolverManagerFactory('neos').solve( model, opt=opt_solver, tee=self.solver_progress) else: self.solver_results = opt_solver.solve( model, tee=self.solver_progress, logfile=log_store_folder + log_filename) # Process results obtained if self.neos: self.__msg( "Currently, results are not post-processed for NEOS server runs" ) #FIXME Find a work around else: processed_results = self._process_solver_results(model) except ValueError: self.__psmsg("Something went wrong with the solver") # Return model solution and solver statistics self.final_results = processed_results self.__page_borders(bottom=True) # Footer for page # Method for post processing solver results def _process_solver_results(self, model): """ Method to post process results from 'solve_model' method :param model: solved model :return: dictionary of solver results """ from pyomo.environ import Set, RealSet, RangeSet, Param, Var # Write solution to stdout/file if self.write_solution and ( str(self.solver_results.solver.Status) in ['ok'] or str(self.solver_results.solver.Termination_condition) in ['maxTimeLimit']): if self.write_solution_to_stdout: # Write solution to screen self.solver_results.write() else: pass # Write solution to file named <model_name>/DD_MM_YY_HH_MM_xx.json # Create (if it does not exist) the '_results_store' folder results_store_folder = path.join('_results_store', self.__model_name_str, '') if not path.exists(results_store_folder): makedirs(results_store_folder) if self.__pyomo_version <= '5.7.1': model.solutions.store_to( self.solver_results) # define solutions storage folder else: pass self.__current_datetime_str = datetime.now().strftime( "%d_%m_%y_%H_%M_") file_suffix = 0 # Results filename if self.__model_name_str == 'Unknown' or len( self.__model_name_str) <= 10: result_filename = self.__model_name_str + self.__current_datetime_str + str( file_suffix) + ".json" else: result_filename = self.__model_name_str[:4] + '..' + self.__model_name_str[-4:] + \ self.__current_datetime_str + str(file_suffix) + ".json" while path.exists(results_store_folder + result_filename): file_suffix += 1 result_filename = self.__current_datetime_str + str( file_suffix) + ".json" result_filename = self.__current_datetime_str + str( file_suffix) + ".json" self.solver_results.write(filename=results_store_folder + result_filename, format="json") else: pass # Create dictionary to for solver statistics and solution final_result = dict() # Include the default solver results from opt_solver.solve & current state of model final_result['solver_results_def'] = self.solver_results final_result[ 'model'] = model # copy.deepcopy(model) # include all model attributes # _include solver statistics acceptable_termination_conditions = [ 'maxTimeLimit', 'maxIterations', 'locallyOptimal', 'globallyOptimal', 'optimal', 'other' ] if str(self.solver_results.solver.Status) == 'ok' or ( str(self.solver_results.solver.Status) == 'aborted' and str(self.solver_results.solver.Termination_condition) in acceptable_termination_conditions): final_result['solver'] = dict( ) # Create dictionary for solver statistics final_result['solver'] = { 'status': str(self.solver_results.solver.Status), 'solver_message': str(self.solver_results.solver.Message), 'termination_condition': str(self.solver_results.solver.Termination_condition) } try: final_result['solver'][ 'wall_time'] = self.solver_results.solver.wall_time except AttributeError: final_result['solver']['wall_time'] = None try: final_result['solver'][ 'wall_time'] = self.solver_results.solver.wall_time except AttributeError: final_result['solver']['wall_time'] = None try: final_result['solver'][ 'cpu_time'] = self.solver_results.solver.time except AttributeError: final_result['solver']['cpu_time'] = None try: if self.solver_results.problem.Upper_bound == 0 and self.solver_results.problem.Lower_bound == 0: final_result['solver']['gap'] = 0 elif self.solver_results.problem.Upper_bound == 0: final_result['solver']['gap'] = abs( round(self.solver_results.problem.Lower_bound, 2)) else: final_result['solver']['gap'] = abs(round( (self.solver_results.problem.Upper_bound - self.solver_results.problem.Lower_bound) \ * 100 / self.solver_results.problem.Upper_bound, 2)) except AttributeError: final_result['solver']['gap'] = None # Check state of available solution if self.__pyomo_version < '5.7.1': try: for key, value in final_result['solver_results_def'][ 'Solution'][0]['Objective'].items(): objective_value = value['Value'] final_result['solution_status'] = True except: final_result['solution_status'] = False objective_value = 'Unk' else: try: objective_value = model.solutions.solutions[0]._entry[ 'objective'][list( model.solutions.solutions[0]._entry['objective']. keys())[0]][1]['Value'] final_result['solution_status'] = True except: final_result['solution_status'] = False objective_value = 'Unk' if self.return_solution and final_result['solution_status']: # True: include values of all model objects in 'final_result' # write list of sets, parameters and variables final_result['sets_list'] = [ str(i) for i in chain(model.component_objects(Set), model.component_objects(RealSet), model.component_objects(RangeSet)) if (re.split("_", str(i))[-1] != 'index') if (re.split("_", str(i))[-1] != 'domain') ] final_result['parameters_list'] = [ str(i) for i in model.component_objects(Param) ] final_result['variables_list'] = [ str(i) for i in model.component_objects(Var) ] # Populate final results for sets, parameters and variables # Create method to return array def indexed_value_extract(index, object): return array([value for value in object[index].value]) # Sets final_result['sets'] = dict() for set in final_result['sets_list']: set_object = getattr(model, str(set)) final_result['sets'][set] = array( list(set_object)) # save array of set elements # Parameters final_result['parameters'] = dict() if self.verbosity: print('\nProcessing parameters . . . ') else: pass for par in final_result['parameters_list']: if self.verbosity: print(par, ' ', end="") else: pass par_object = getattr(model, str(par)) par_object_dim = par_object.dim( ) # get dimension of parameter if par_object_dim == 0: final_result['parameters'][par] = par_object.value elif par_object_dim == 1: final_result['parameters'][par] = array( [value for value in par_object.values()]) else: try: par_set_list = self.__get_set_list(par_object) par_set_lens = [ len(getattr(model, str(set))) for set in par_set_list ] except AttributeError: par_set_list = [str(par_object._index.name)] temp_par_set = getattr(model, par_set_list[0]) if temp_par_set.dimen == 1: par_set_lens = [len(temp_par_set)] else: par_set_lens = [ len(set) for set in self.__get_set_list_alt(temp_par_set) ] # print(par_set_lens) final_result['parameters'][par] = zeros( shape=par_set_lens, dtype=float) if par_object_dim == 2: if len(par_set_list) == par_object_dim: for ind_i, i in enumerate( getattr(model, str(par_set_list[0]))): for ind_j, j in enumerate( getattr(model, str(par_set_list[1]))): final_result['parameters'][par][ind_i][ ind_j] = par_object[i, j] elif len(par_set_list) == 1: for set in par_set_list: for ind, (i, j) in enumerate( getattr(model, str(set))): # print(type(final_result['parameters'][par]),final_result['parameters'][par]) # print(i,j,final_result['parameters'][par][i-1][j-1]) # print(par_set_lens) # print(par_set_list) # print(par_object_dim) if self.__pyomo_version < '5.7': # FIXME: Better way to do this? final_result['parameters'][par][ i - 1][j - 1] = par_object[i, j] else: final_result['parameters'][par][ ind] = par_object[i, j] else: pass else: pass # FIXME 3-dimensional variables are not considered yet # Variables final_result['variables'] = dict() # Include objective functionv value final_result['variables']['Objective'] = objective_value if self.verbosity: print('\nProcessing results of variables . . . ') else: pass for variable in final_result['variables_list']: try: if self.verbosity: print(variable, ' ', end="") else: pass variable_object = getattr(model, str(variable)) variable_object_dim = variable_object.dim( ) # get dimension of variable if variable_object_dim == 0: final_result['variables'][ variable] = variable_object.value elif variable_object_dim == 1: final_result['variables'][variable] = array([ value.value for value in variable_object.values() ]) else: try: variable_set_list = self.__get_set_list( variable_object) variable_set_lens = [ len(getattr(model, str(set))) for set in variable_set_list ] except AttributeError: variable_set_list = [ str(variable_object._index.name) ] temp_variable_set = getattr( model, variable_set_list[0]) if temp_variable_set.dimen == 1: variable_set_lens = [ len(temp_variable_set) ] else: variable_set_lens = [ len(set) for set in self.__get_set_list_alt( temp_variable_set) ] # print(variable_set_lens) final_result['variables'][variable] = zeros( shape=variable_set_lens, dtype=float) if variable_object_dim == 2: if len(variable_set_list ) == variable_object_dim: for ind_i, i in enumerate( getattr( model, str(variable_set_list[0]))): for ind_j, j in enumerate( getattr( model, str(variable_set_list[1])) ): final_result['variables'][ variable][ind_i][ ind_j] = variable_object[ i, j].value elif len(variable_set_list) == 1: for set in variable_set_list: for ind, (i, j) in enumerate( getattr(model, str(set))): # print(type(final_result['variables'][variable]),final_result['variables'][variable]) # print(i,j,final_result['variables'][variable][i-1][j-1]) if self.__pyomo_version < '5.7': # FIXME: Better way to do this? final_result['variables'][ variable][i - 1][ j - 1] = variable_object[ i, j].value else: final_result['variables'][ variable][ ind] = variable_object[ i, j].value else: pass else: pass # FIXME 3-dimensional variables are not considered yet except AttributeError: pass print('\n') else: # if solver_status != 'ok' or amongst acceptable termination conditions if self.debug_mode: if self.verbose_debug_mode: # Print troublesome constraints from pyomo.util.infeasible import log_infeasible_constraints log_infeasible_constraints(model) else: pass self.__psmsg('An optimal solution could not be processed' ) # leave program running to debug else: self.__pemsg('An optimal solution could not be processed') else: # if solver_status != ok self.__pemsg('An optimal solution was NOT found') return final_result
from pyomo.core import * from pyomo.opt import SolverFactory, SolverManagerFactory from DiseaseEstimation import model # create the instance instance = model.create('DiseaseEstimation.dat') # define the solver and its options solver = 'ipopt' opt = SolverFactory( solver ) if opt is None: raise ValueError, "Problem constructing solver `"+str(solver) opt.set_options('max_iter=2') # create the solver manager solver_manager = SolverManagerFactory( 'serial' ) # solve results = solver_manager.solve(instance, opt=opt, tee=True, timelimit=None) instance.load(results) # display results display(instance)
def run(args=None): ##########################================================######### # to import plugins import pyomo.environ import pysp.pyro.smanager_pyro import pysp.plugins.phpyro def partialLagrangeParametric(args=None): print("lagrangeParam begins ") blanks = " " # used for formatting print statements class Object(object): pass Result = Object() # options used IndVarName = options.indicator_var_name CCStageNum = options.stage_num alphaTol = options.alpha_tol MaxMorePR = options.MaxMorePR # option to include up to this many PR points above F^* with all delta fixed outputFilePrefix = options.outputFilePrefix # We write ScenarioList = name, probability # PRoptimal = probability, min-cost, [selections] # PRmore = probability, min-cost, [selections] # ================ sorted by probability ======================== # # These can be read to avoid re-computing points ph = PHFromScratch(options) Result.ph = ph rootnode = ph._scenario_tree._stages[0]._tree_nodes[ 0] # use rootnode to loop over scenarios if find_active_objective(ph._scenario_tree._scenarios[0]._instance, safety_checks=True).is_minimizing(): print("We are solving a MINIMIZATION problem.\n") else: print("We are solving a MAXIMIZATION problem.\n") # initialize ScenarioList = [] lambdaval = 0. lagrUtil.Set_ParmValue(ph, options.lambda_parm_name, lambdaval) # IMPORTANT: Preprocess the scenario instances # before fixing variables, otherwise they # will be preprocessed out of the expressions # and the output_fixed_variable_bounds option # will have no effect when we update the # fixed variable values (and then assume we # do not need to preprocess again because # of this option). ph._preprocess_scenario_instances() lagrUtil.FixAllIndicatorVariables(ph, IndVarName, 0) for scenario in rootnode._scenarios: ScenarioList.append((scenario._name, scenario._probability)) # sorts from min to max probability ScenarioList.sort(key=operator.itemgetter(1)) with open(outputFilePrefix + 'ScenarioList.csv', 'w') as outFile: for scenario in ScenarioList: outFile.write(scenario[0] + ", " + str(scenario[1]) + "\n") Result.ScenarioList = ScenarioList print("lambda= " + str(lambdaval) + " ...run begins " + str(len(ScenarioList)) + " scenarios") SolStat, zL = lagrUtil.solve_ph_code(ph, options) print("\t...ends") bL = Compute_ExpectationforVariable(ph, IndVarName, CCStageNum) if bL > 0: print("** bL = " + str(bL) + " > 0") return Result print("Initial cost = " + str(zL) + " for bL = " + str(bL)) lagrUtil.FixAllIndicatorVariables(ph, IndVarName, 1) print("lambda= " + str(lambdaval) + " ...run begins") SolStat, zU = lagrUtil.solve_ph_code(ph, options) print("\t...ends") bU = Compute_ExpectationforVariable(ph, IndVarName, CCStageNum) if bU < 1: print("** bU = " + str(bU) + " < 1") lagrUtil.FreeAllIndicatorVariables(ph, IndVarName) Result.lbz = [[0, bL, zL], [None, bU, zU]] Result.selections = [[], ScenarioList] NumIntervals = 1 print("initial gap = " + str(1 - zL / zU) + " \n") print("End of test; this is only a test.") return Result ################################ # LagrangeParametric ends here ################################ #### start run #### AllInOne = False ########################## # options defined here ########################## try: conf_options_parser = construct_ph_options_parser("lagrange [options]") conf_options_parser.add_argument( "--alpha", help="The alpha level for the chance constraint. Default is 0.05", action="store", dest="alpha", type=float, default=0.05) conf_options_parser.add_argument( "--alpha-min", help= "The min alpha level for the chance constraint. Default is None", action="store", dest="alpha_min", type=float, default=None) conf_options_parser.add_argument( "--alpha-max", help="The alpha level for the chance constraint. Default is None", action="store", dest="alpha_max", type=float, default=None) conf_options_parser.add_argument( "--min-prob", help="Tolerance for testing probability > 0. Default is 1e-5", action="store", dest="min_prob", type=float, default=1e-5) conf_options_parser.add_argument( "--alpha-tol", help="Tolerance for testing equality to alpha. Default is 1e-5", action="store", dest="alpha_tol", type=float, default=1e-5) conf_options_parser.add_argument( "--MaxMorePR", help= "Generate up to this many additional PR points after response function. Default is 0", action="store", dest="MaxMorePR", type=int, default=0) conf_options_parser.add_argument( "--outputFilePrefix", help="Output file name. Default is ''", action="store", dest="outputFilePrefix", type=str, default="") conf_options_parser.add_argument( "--stage-num", help= "The stage number of the CC indicator variable (number, not name). Default is 2", action="store", dest="stage_num", type=int, default=2) conf_options_parser.add_argument( "--lambda-parm-name", help= "The name of the lambda parameter in the model. Default is lambdaMult", action="store", dest="lambda_parm_name", type=str, default="lambdaMult") conf_options_parser.add_argument( "--indicator-var-name", help= "The name of the indicator variable for the chance constraint. The default is delta", action="store", dest="indicator_var_name", type=str, default="delta") conf_options_parser.add_argument( "--use-Loane-cuts", help="Add the Loane cuts if there is a gap. Default is False", action="store_true", dest="add_Loane_cuts", default=False) conf_options_parser.add_argument( "--fofx-var-name", help= "(Loane) The name of the model's auxiliary variable that is constrained to be f(x). Default is fofox", action="store", dest="fofx_var_name", type=str, default="fofx") conf_options_parser.add_argument( "--solve-with-ph", help= "Perform solves via PH rather than an EF solve. Default is False", action="store_true", dest="solve_with_ph", default=False) conf_options_parser.add_argument( "--skip-graph", help= "Do not show the graph at the end. Default is False (i.e. show the graph)", action="store_true", dest="skip_graph", default=False) conf_options_parser.add_argument( "--write-xls", help="Write results into a xls file. Default is False", action="store_true", dest="write_xls", default=False) conf_options_parser.add_argument( "--skip-ExpFlip", help= "Do not show the results for flipping the indicator variable for each scenario. Default is False (i.e. show the flipping-results)", action="store_true", dest="skip_ExpFlip", default=False) conf_options_parser.add_argument( "--HeurFlip", help= "The number of solutions to evaluate after the heuristic. Default is 3. For 0 the heuristic flip gets skipped.", action="store", type=int, dest="HeurFlip", default=3) conf_options_parser.add_argument( "--HeurMIP", help= "The mipgap for the scenariowise solves in the heuristic. Default is 0.0001", action="store", type=float, dest="HeurMIP", default=0.0001) conf_options_parser.add_argument( "--interactive", help="Enable interactive version of the code. Default is False.", action="store_true", dest="interactive", default=False) conf_options_parser.add_argument( "--Lgap", help= "The (relative) Lagrangian gap acceptable for the chance constraint. Default is 10^-4", action="store", type=float, dest="LagrangeGap", default=0.0001) conf_options_parser.add_argument( "--lagrange-method", help="The Lagrange multiplier search method", action="store", dest="lagrange_search_method", type=str, default="tangential") conf_options_parser.add_argument( "--max-lambda", help="The max value of the multiplier. Default=10^10", action="store", dest="max_lambda", type=float, default=10**10) conf_options_parser.add_argument( "--min-lambda", help="The min value of the multiplier. Default=0.0", action="store", dest="min_lambda", type=float, default=0) conf_options_parser.add_argument( "--min-probability", help="The min value of scenario probability. Default=10^-15", action="store", dest="min_probability", type=float, default=10**(-15)) ################################################################ options = conf_options_parser.parse_args(args=args) # temporary hack options._ef_options = conf_options_parser._ef_options options._ef_options.import_argparse(options) except SystemExit as _exc: # the parser throws a system exit if "-h" is specified - catch # it to exit gracefully. return _exc.code # load the reference model and create the scenario tree - no # scenario instances yet. if options.verbose: print("Loading reference model and scenario tree") #scenario_instance_factory, full_scenario_tree = load_models(options) scenario_instance_factory = \ ScenarioTreeInstanceFactory(options.model_directory, options.instance_directory) full_scenario_tree = \ GenerateScenarioTreeForPH(options, scenario_instance_factory) solver_manager = SolverManagerFactory(options.solver_manager_type) if solver_manager is None: raise ValueError("Failed to create solver manager of " "type=" + options.solver_manager_type + " specified in call to PH constructor") if isinstance(solver_manager, pysp.plugins.phpyro.SolverManager_PHPyro): raise ValueError("PHPyro can not be used as the solver manager") try: if (scenario_instance_factory is None) or (full_scenario_tree is None): raise RuntimeError( "***ERROR: Failed to initialize model and/or the scenario tree data." ) # load_model gets called again, so lets make sure unarchived directories are used options.model_directory = scenario_instance_factory._model_filename options.instance_directory = scenario_instance_factory._scenario_tree_filename scenario_count = len(full_scenario_tree._stages[-1]._tree_nodes) # create ph objects for finding the solution. we do this even if # we're solving the extensive form if options.verbose: print( "Loading scenario instances and initializing scenario tree for full problem." ) ########## Here is where multiplier search is called ############ Result = partialLagrangeParametric() ##################################################################################### finally: # delete temporary unarchived directories scenario_instance_factory.close() print("\nreturned from partialLagrangeParametric")
def run(args=None): ##########################================================######### # to import plugins import pyomo.environ import pyomo.solvers.plugins.smanager.phpyro import pyomo.solvers.plugins.smanager.pyro def partialLagrangeParametric(args=None): print("lagrangeParam begins ") blanks = " " # used for formatting print statements class Object(object): pass Result = Object() # options used IndVarName = options.indicator_var_name CCStageNum = options.stage_num alphaTol = options.alpha_tol MaxMorePR = options.MaxMorePR # option to include up to this many PR points above F^* with all delta fixed outputFilePrefix = options.outputFilePrefix # We write ScenarioList = name, probability # PRoptimal = probability, min-cost, [selections] # PRmore = probability, min-cost, [selections] # ================ sorted by probability ======================== # # These can be read to avoid re-computing points ph = PHFromScratch(options) Result.ph = ph rootnode = ph._scenario_tree._stages[0]._tree_nodes[0] # use rootnode to loop over scenarios if find_active_objective(ph._scenario_tree._scenarios[0]._instance,safety_checks=True).is_minimizing(): print("We are solving a MINIMIZATION problem.\n") else: print("We are solving a MAXIMIZATION problem.\n") # initialize ScenarioList = [] lambdaval = 0. lagrUtil.Set_ParmValue(ph, options.lambda_parm_name, lambdaval) # IMPORTANT: Preprocess the scenario instances # before fixing variables, otherwise they # will be preprocessed out of the expressions # and the output_fixed_variable_bounds option # will have no effect when we update the # fixed variable values (and then assume we # do not need to preprocess again because # of this option). ph._preprocess_scenario_instances() lagrUtil.FixAllIndicatorVariables(ph, IndVarName, 0) for scenario in rootnode._scenarios: ScenarioList.append((scenario._name, scenario._probability)) # sorts from min to max probability ScenarioList.sort(key=operator.itemgetter(1)) with open(outputFilePrefix+'ScenarioList.csv','w') as outFile: for scenario in ScenarioList: outFile.write(scenario[0]+ ", " +str(scenario[1])+"\n") Result.ScenarioList = ScenarioList print("lambda= "+str(lambdaval)+" ...run begins "+str(len(ScenarioList))+" scenarios") SolStat, zL = lagrUtil.solve_ph_code(ph, options) print("\t...ends") bL = Compute_ExpectationforVariable(ph, IndVarName, CCStageNum) if bL > 0: print("** bL = "+str(bL)+" > 0") return Result print("Initial cost = "+str(zL)+" for bL = "+str(bL)) lagrUtil.FixAllIndicatorVariables(ph, IndVarName, 1) print("lambda= "+str(lambdaval)+" ...run begins") SolStat, zU = lagrUtil.solve_ph_code(ph, options) print("\t...ends") bU = Compute_ExpectationforVariable(ph, IndVarName, CCStageNum) if bU < 1: print("** bU = "+str(bU)+" < 1") lagrUtil.FreeAllIndicatorVariables(ph, IndVarName) Result.lbz = [ [0,bL,zL], [None,bU,zU] ] Result.selections = [[], ScenarioList] NumIntervals = 1 print("initial gap = "+str(1-zL/zU)+" \n") print("End of test; this is only a test.") return Result ################################ # LagrangeParametric ends here ################################ #### start run #### AllInOne = False ########################## # options defined here ########################## try: conf_options_parser = construct_ph_options_parser("lagrange [options]") conf_options_parser.add_argument("--alpha", help="The alpha level for the chance constraint. Default is 0.05", action="store", dest="alpha", type=float, default=0.05) conf_options_parser.add_argument("--alpha-min", help="The min alpha level for the chance constraint. Default is None", action="store", dest="alpha_min", type=float, default=None) conf_options_parser.add_argument("--alpha-max", help="The alpha level for the chance constraint. Default is None", action="store", dest="alpha_max", type=float, default=None) conf_options_parser.add_argument("--min-prob", help="Tolerance for testing probability > 0. Default is 1e-5", action="store", dest="min_prob", type=float, default=1e-5) conf_options_parser.add_argument("--alpha-tol", help="Tolerance for testing equality to alpha. Default is 1e-5", action="store", dest="alpha_tol", type=float, default=1e-5) conf_options_parser.add_argument("--MaxMorePR", help="Generate up to this many additional PR points after response function. Default is 0", action="store", dest="MaxMorePR", type=int, default=0) conf_options_parser.add_argument("--outputFilePrefix", help="Output file name. Default is ''", action="store", dest="outputFilePrefix", type=str, default="") conf_options_parser.add_argument("--stage-num", help="The stage number of the CC indicator variable (number, not name). Default is 2", action="store", dest="stage_num", type=int, default=2) conf_options_parser.add_argument("--lambda-parm-name", help="The name of the lambda parameter in the model. Default is lambdaMult", action="store", dest="lambda_parm_name", type=str, default="lambdaMult") conf_options_parser.add_argument("--indicator-var-name", help="The name of the indicator variable for the chance constraint. The default is delta", action="store", dest="indicator_var_name", type=str, default="delta") conf_options_parser.add_argument("--use-Loane-cuts", help="Add the Loane cuts if there is a gap. Default is False", action="store_true", dest="add_Loane_cuts", default=False) conf_options_parser.add_argument("--fofx-var-name", help="(Loane) The name of the model's auxiliary variable that is constrained to be f(x). Default is fofox", action="store", dest="fofx_var_name", type=str, default="fofx") conf_options_parser.add_argument("--solve-with-ph", help="Perform solves via PH rather than an EF solve. Default is False", action="store_true", dest="solve_with_ph", default=False) conf_options_parser.add_argument("--skip-graph", help="Do not show the graph at the end. Default is False (i.e. show the graph)", action="store_true", dest="skip_graph", default=False) conf_options_parser.add_argument("--write-xls", help="Write results into a xls file. Default is False", action="store_true", dest="write_xls", default=False) conf_options_parser.add_argument("--skip-ExpFlip", help="Do not show the results for flipping the indicator variable for each scenario. Default is False (i.e. show the flipping-results)", action="store_true", dest="skip_ExpFlip", default=False) conf_options_parser.add_argument("--HeurFlip", help="The number of solutions to evaluate after the heuristic. Default is 3. For 0 the heuristic flip gets skipped.", action="store", type=int, dest="HeurFlip", default=3) conf_options_parser.add_argument("--HeurMIP", help="The mipgap for the scenariowise solves in the heuristic. Default is 0.0001", action="store", type=float, dest="HeurMIP", default=0.0001) conf_options_parser.add_argument("--interactive", help="Enable interactive version of the code. Default is False.", action="store_true", dest="interactive", default=False) conf_options_parser.add_argument("--Lgap", help="The (relative) Lagrangian gap acceptable for the chance constraint. Default is 10^-4", action="store", type=float, dest="LagrangeGap", default=0.0001) conf_options_parser.add_argument("--lagrange-method", help="The Lagrange multiplier search method", action="store", dest="lagrange_search_method", type=str, default="tangential") conf_options_parser.add_argument("--max-lambda", help="The max value of the multiplier. Default=10^10", action="store", dest="max_lambda", type=float, default=10**10) conf_options_parser.add_argument("--min-lambda", help="The min value of the multiplier. Default=0.0", action="store", dest="min_lambda", type=float, default=0) conf_options_parser.add_argument("--min-probability", help="The min value of scenario probability. Default=10^-15", action="store", dest="min_probability", type=float, default=10**(-15)) ################################################################ options = conf_options_parser.parse_args(args=args) # temporary hack options._ef_options = conf_options_parser._ef_options options._ef_options.import_argparse(options) except SystemExit as _exc: # the parser throws a system exit if "-h" is specified - catch # it to exit gracefully. return _exc.code # load the reference model and create the scenario tree - no # scenario instances yet. if options.verbose: print("Loading reference model and scenario tree") #scenario_instance_factory, full_scenario_tree = load_models(options) scenario_instance_factory = \ ScenarioTreeInstanceFactory(options.model_directory, options.instance_directory, options.verbose) full_scenario_tree = \ GenerateScenarioTreeForPH(options, scenario_instance_factory) solver_manager = SolverManagerFactory(options.solver_manager_type) if solver_manager is None: raise ValueError("Failed to create solver manager of " "type="+options.solver_manager_type+ " specified in call to PH constructor") if isinstance(solver_manager, pyomo.solvers.plugins.smanager.phpyro.SolverManager_PHPyro): solver_manager.deactivate() raise ValueError("PHPyro can not be used as the solver manager") try: if (scenario_instance_factory is None) or (full_scenario_tree is None): raise RuntimeError("***ERROR: Failed to initialize model and/or the scenario tree data.") # load_model gets called again, so lets make sure unarchived directories are used options.model_directory = scenario_instance_factory._model_filename options.instance_directory = scenario_instance_factory._scenario_tree_filename scenario_count = len(full_scenario_tree._stages[-1]._tree_nodes) # create ph objects for finding the solution. we do this even if # we're solving the extensive form if options.verbose: print("Loading scenario instances and initializing scenario tree for full problem.") ########## Here is where multiplier search is called ############ Result = partialLagrangeParametric() ##################################################################################### finally: solver_manager.deactivate() # delete temporary unarchived directories scenario_instance_factory.close() print("\nreturned from partialLagrangeParametric")
return ( sum( modelo.tiempo_produccion[planta, producto] * modelo.produccion[producto] for producto in modelo.productos ) <= modelo.tiempo_disponible[planta] ) modelo.disponibilidad_tiempo = Constraint( modelo.plantas, rule=funcion_disponibilidad_tiempo ) def funcion_ganancias(modelo): return sum( modelo.ganancia_unitaria[producto] * modelo.produccion[producto] for producto in modelo.productos ) modelo.ganancias = Objective(rule=funcion_ganancias, sense=maximize) instancia = modelo.create_instance("wyndor.dat") opt = SolverFactory("cbc") solver_manager = SolverManagerFactory('neos') resultados = solver_manager.solve(instancia, opt=opt) # resolver en la nube # resultados = opt.solve(instancia) # resolver localmente instancia.display()
def solve_model(model, p_summary=False, p_log=False): # Custom Solve Method import datetime # Choose the best solution from the trial pool # trial_pool = { # 'sample1':{'solution_file':None,'aspiration':None}, # 'sample2':{'solution_file':None,'aspiration':None}, # 'sample3':{'solution_file':None,'aspiration':None} # } #model1 = copy.deepcopy(model) #model2 = copy.deepcopy(model) #model3 = copy.deepcopy(model) import configparser config = configparser.ConfigParser() config.read('../start_config.ini') #initialization Setting mip_gap = float(config['solver']['mip_gap']) solver_timeout = int(config['solver']['solver_timeout']) solver_sh = config['solver']['solver_sh'] number_of_trials = int(config['solver']['number_of_trials']) engage_neos = bool(int( config['solver']['engage_neos'])) #initialization Setting threads = int(config['solver']['threads']) if solver_sh not in set(["cbc", "cplex"]): raise AssertionError("Invalid Solver!, Error Code : 200B") logger.info("success! \n loading solver......") j = 1 timeout_arguments = {'cplex': 'timelimit', 'cbc': 'sec'} gap_arguments = { 'cplex': 'mipgap', 'cbc': 'ratio' } # Cplex Local Executable will take : "mip_tolerance_mipgap", mipgap is for neos version # NEOS Server Library Dependency # pyro4 # suds # openopt while j < number_of_trials + 1: from pyomo.opt import SolverFactory, SolverManagerFactory #model.pprint() opt = SolverFactory(solver_sh, solver_io='lp') # print ('\ninterfacing solver shell :',solver_sh) logger.debug('interfacing solver shell : %s' % (solver_sh)) if engage_neos: solver_manager = SolverManagerFactory('neos') opt.options[timeout_arguments[solver_sh]] = solver_timeout opt.options[gap_arguments[solver_sh]] = mip_gap #opt.symbolic_solver_labels=True # #opt.enable = 'parallel' print( '\tsolver options >> \n\n\tTolerance Limits:\n\tmip_gap = %s \n\ttimeout = %s' % (str(mip_gap), str(solver_timeout))) # print ("\nProcessing Trial Number :",j) # print ("\nJob Triggered at :",str(datetime.datetime.now())) print( '\ngenerating solution ...... !! please wait !! \n to interrupt press ctrl+C\n' ) # logger.debug('\tsolver options >> \n\n\tTolerance Limits:\n\tmip_gap = %s \n\ttimeout = %s'%(str(mip_gap),str(solver_timeout))) logger.debug('Processing Trial Number :%d' % (j)) logger.debug("Job Triggered") try: if engage_neos: p_log = False results = solver_manager.solve(model, opt=opt, tee=True) else: opt.options['threads'] = threads if p_log: opt.options['slog'] = 1 results = opt.solve( model ) # Method Load Solutions is not available in pyomo versions less than 4.x except: j = j + 1 mip_gap = (j - 1) * mip_gap solver_sh = 'cplex' engage_neos = True continue #results.write(filename='results'+str(datetime.date.today())+'.json',format = 'json') #print (results) if str(results['Solver'][0]['Termination condition']) in [ 'infeasible', 'maxTimeLimit', 'maxIterations', 'intermediateNonInteger', 'unbounded' ]: j = j + 1 mip_gap = (j - 1) * mip_gap solver_sh = 'cplex' engage_neos = True if j == number_of_trials + 1: #print (results['Problem']) #print (results['Solver']) raise AssertionError( "Solver Failed with Termination Status : %s \nError Code : 200C" % (str(results['Solver'][0]['Termination condition']))) exit(0) # print ('Terminated by:',str(results['Solver'][0]['Termination condition'])) # print ("\n\nRetrying...\n\n") logger.info('Terminated by:', str(results['Solver'][0]['Termination condition'])) logger.info("\n\nRetrying...\n\n") else: # print ("SUCCESS: Solution Captured!") logger.info("Solution Captured!") model.solutions.store_to(results) #post_process_results() break if p_summary: print(results['Problem']) # print (results['Solver']) # print ("\nSolution Retrived at:",str(datetime.datetime.now())) # logger.info("Solution Retrived") return [model, results]
modelo.ganancias = Objective(rule=funcion_ganancias, sense=maximize) def funcion_capacidad_doug(modelo): return modelo.produccion["madera"] <= 6 modelo.capacidad_doug = Constraint(rule=funcion_capacidad_doug) def funcion_capacidad_linda(modelo): return modelo.produccion["aluminio"] <= 4 modelo.capacidad_linda = Constraint(rule=funcion_capacidad_linda) def funcion_capacidad_bob(modelo): return ( modelo.produccion["madera"]*6 + modelo.produccion["aluminio"]*8 <= 48 ) modelo.capacidad_bob = Constraint(rule=funcion_capacidad_bob) opt = SolverFactory("cbc") solver_manager = SolverManagerFactory('neos') resultados = solver_manager.solve(modelo, opt=opt) # resolver en la nube # resultados = opt.solve(modelo) # resolver localmente modelo.display()
def run(args=None): ################################### # to import plugins import pyomo.environ import pyomo.solvers.plugins.smanager.phpyro def LagrangeMorePR(args=None): print("lagrangeMorePR begins %s" % datetime_string()) blanks = " " # used for formatting print statements class Object(object): pass Result = Object() # options used betaTol = options.beta_tol # tolerance used to separate b-values IndVarName = options.indicator_var_name multName = options.lambda_parm_name CCStageNum = options.stage_num MaxMorePR = options.max_number # max PR points to be generated (above F^* with all delta fixed) MaxTime = options.max_time # max time before terminate csvPrefix = options.csvPrefix # input filename prefix (eg, case name) probFileName = options.probFileName # name of file containing probabilities ##HG override # options.verbosity = 2 verbosity = options.verbosity Result.status = 'starting '+datetime_string() STARTTIME = time.time() ph = PHFromScratch(options) rootnode = ph._scenario_tree._stages[0]._tree_nodes[0] # use rootnode to loop over scenarios if find_active_objective(ph._scenario_tree._scenarios[0]._instance,safety_checks=True).is_minimizing(): print("We are solving a MINIMIZATION problem.") else: print("We are solving a MAXIMIZATION problem.") # initialize ScenarioList = [] with open(csvPrefix+"ScenarioList.csv",'r') as inputFile: for line in inputFile.readlines(): L = line.split(',') ScenarioList.append([L[0],float(L[1])]) addstatus = str(len(ScenarioList))+' scenarios read from file: ' + csvPrefix+'ScenarioList.csv' if verbosity > 0: print(addstatus) Result.status = Result.status + '\n' + addstatus PRoptimal = [] with open(csvPrefix+"PRoptimal.csv",'r') as inputFile: for line in inputFile.readlines(): bzS = line.split(',') PRoptimal.append( [None, float(bzS[0]), float(bzS[1])] ) addstatus = str(len(PRoptimal))+' PR points read from file: '+ csvPrefix+'PRoptimal.csv (envelope function)' if verbosity > 0: print(addstatus) Result.status = Result.status + '\n' + addstatus # ensure PR points on envelope function are sorted by probability PRoptimal.sort(key=operator.itemgetter(1)) PRoptimal[0][0] = 0 # initial lambda (for b=0) for p in range(1,len(PRoptimal)): dz = PRoptimal[p][2] - PRoptimal[p-1][2] db = PRoptimal[p][1] - PRoptimal[p-1][1] PRoptimal[p][0] = dz/db if verbosity > 0: PrintPRpoints(PRoptimal) Result.PRoptimal = PRoptimal lambdaval = 0. lagrUtil.Set_ParmValue(ph, options.lambda_parm_name,lambdaval) # IMPORTANT: Preprocess the scenario instances # before fixing variables, otherwise they # will be preprocessed out of the expressions # and the output_fixed_variable_bounds option # will have no effect when we update the # fixed variable values (and then assume we # do not need to preprocess again because # of this option). ph._preprocess_scenario_instances() ## read scenarios to select for each PR point on envelope function with open(csvPrefix+"OptimalSelections.csv",'r') as inputFile: OptimalSelections = [] for line in inputFile.readlines(): if len(line) == 0: break # eof selections = line.split(',') L = len(selections) Ls = len(selections[L-1]) selections[L-1] = selections[L-1][0:Ls-1] if verbosity > 1: print(str(selections)) OptimalSelections.append(selections) Result.OptimalSelections = OptimalSelections addstatus = str(len(OptimalSelections)) + ' Optimal selections read from file: ' \ + csvPrefix + 'OptimalSelections.csv' Result.status = Result.status + '\n' + addstatus if len(OptimalSelections) == len(PRoptimal): if verbosity > 0: print(addstatus) else: addstatus = addstatus + '\n** Number of selections not equal to number of PR points' print(addstatus) Result.status = Result.status + '\n' + addstatus print(str(OptimalSelections)) print((PRoptimal)) return Result ##################################################################################### # get probabilities if probFileName is None: # ...generate from widest gap regions PRlist = FindPRpoints(options, PRoptimal) else: # ...read probabilities probList = [] with open(probFileName,'r') as inputFile: if verbosity > 0: print("reading from probList = "+probFileName) for line in inputFile.readlines(): # 1 probability per line if len(line) == 0: break prob = float(line) probList.append(prob) if verbosity > 0: print("\t "+str(len(probList))+" probabilities") if verbosity > 1: print(str(probList)) PRlist = GetPoints(options, PRoptimal, probList) if verbosity > 1: print("PRlist:") for interval in PRlist: print(str(interval)) # We now have PRlist = [[i, b], ...], where b is in PRoptimal interval (i-1,i) addstatus = str(len(PRlist)) + ' probabilities' if verbosity > 0: print(addstatus) Result.status = Result.status + '\n' + addstatus ##################################################################################### lapsedTime = time.time() - STARTTIME addstatus = 'Initialize complete...lapsed time = ' + str(lapsedTime) if verbosity > 1: print(addstatus) Result.status = Result.status + '\n' + addstatus ##################################################################################### if verbosity > 1: print("\nlooping over Intervals to generate PR points by flipping heuristic") Result.morePR = [] for interval in PRlist: lapsedTime = time.time() - STARTTIME if lapsedTime > MaxTime: addstatus = '** lapsed time = ' + str(lapsedTime) + ' > max time = ' + str(MaxTime) if verbosity > 0: print(addstatus) Result.status = Result.status + '\n' + addstatus break i = interval[0] # = PR point index b = interval[1] # = target probability to reach by flipping from upper endpoint bU = PRoptimal[i][1] # = upper endpoint bL = PRoptimal[i-1][1] # = lower endpoint if verbosity > 1: print( "target probability = "+str(b)+" < bU = PRoptimal[" + str(i) + "][1]" \ " and > bL = PRoptimal["+str(i-1)+"][1]") if b < bL or b > bU: addstatus = '** probability = '+str(b) + ', not in gap interval: (' \ + str(bL) + ', ' + str(bU) + ')' print(addstatus) print(str(PRoptimal)) print(str(PRlist)) Result.status = Result.status + '\n' + addstatus return Result if verbosity > 1: print( "i = "+str(i)+" : Starting with bU = "+str(bU)+" having "+ \ str(len(OptimalSelections[i]))+ " selections:") print(str(OptimalSelections[i])) # first fix all scenarios = 0 for sname, sprob in ScenarioList: scenario = ph._scenario_tree.get_scenario(sname) lagrUtil.FixIndicatorVariableOneScenario(ph, scenario, IndVarName, 0) # now fix optimal selections = 1 for sname in OptimalSelections[i]: scenario = ph._scenario_tree.get_scenario(sname) lagrUtil.FixIndicatorVariableOneScenario(ph, scenario, IndVarName, 1) # flip scenario selections from bU until we reach b (target probability) bNew = bU for sname, sprob in ScenarioList: scenario = ph._scenario_tree.get_scenario(sname) if bNew - sprob < b: continue instance = ph._instances[sname] if getattr(instance, IndVarName).value == 0: continue bNew = bNew - sprob # flipped scenario selection lagrUtil.FixIndicatorVariableOneScenario(ph, scenario, IndVarName, 0) if verbosity > 1: print("\tflipped "+sname+" with prob = "+str(sprob)+" ...bNew = "+str(bNew)) if verbosity > 1: print("\tflipped selections reach "+str(bNew)+" >= target = "+str(b)+" (bL = "+str(bL)+")") if bNew <= bL + betaTol or bNew >= bU - betaTol: if verbosity > 0: print("\tNot generating PR point...flipping from bU failed") continue # to next interval in list # ready to solve to get cost for fixed scenario selections associated with probability = bNew if verbosity > 1: # check that scenarios are fixed as they should be totalprob = 0. for scenario in ScenarioList: sname = scenario[0] sprob = scenario[1] instance = ph._instances[sname] print("fix "+sname+" = "+str(getattr(instance,IndVarName).value)+\ " is "+str(getattr(instance,IndVarName).fixed)+" probability = "+str(sprob)) if getattr(instance,IndVarName).value == 1: totalprob = totalprob + sprob lambdaval = getattr(instance, multName).value print("\ttotal probability = %f" % totalprob) # solve (all delta fixed); lambda=0, so z = Lagrangian if verbosity > 0: print("solve begins %s" % datetime_string()) print("\t- lambda = %f" % lambdaval) SolStat, z = lagrUtil.solve_ph_code(ph, options) b = Compute_ExpectationforVariable(ph, IndVarName, CCStageNum) if verbosity > 0: print("solve ends %s" % datetime_string()) print("\t- SolStat = %s" % str(SolStat)) print("\t- b = %s" % str(b)) print("\t- z = %s" % str(z)) print("(adding to more PR points)") Result.morePR.append([None,b,z]) if verbosity > 1: PrintPRpoints(Result.morePR) ###################################################### # end loop over target probabilities with open(csvPrefix+"PRmore.csv",'w') as outFile: for point in Result.morePR: outFile.write(str(point[1])+','+str(point[2])) addstatus = str(len(Result.morePR)) + ' PR points written to file: '+ csvPrefix + 'PRmore.csv' if verbosity > 0: print(addstatus) Result.status = Result.status + '\n' + addstatus addstatus = 'lapsed time = ' + putcommas(time.time() - STARTTIME) if verbosity > 0: print(addstatus) Result.status = Result.status + '\n' + addstatus return Result ################################ # LagrangeMorePR ends here ################################ #### start run #### AllInOne = False # VERYSTARTTIME=time.time() # print "##############VERYSTARTTIME:",str(VERYSTARTTIME-VERYSTARTTIME) ########################## # options defined here ########################## try: conf_options_parser = construct_ph_options_parser("lagrange [options]") conf_options_parser.add_argument("--beta-min", help="The min beta level for the chance constraint. Default is None", action="store", dest="beta_min", type=float, default=None) conf_options_parser.add_argument("--beta-max", help="The beta level for the chance constraint. Default is None", action="store", dest="beta_max", type=float, default=None) conf_options_parser.add_argument("--min-prob", help="Tolerance for testing probability > 0. Default is 1e-5", action="store", dest="min_prob", type=float, default=1e-5) conf_options_parser.add_argument("--beta-tol", help="Tolerance for testing equality to beta. Default is 10^-2", action="store", dest="beta_tol", type=float, default=1e-2) conf_options_parser.add_argument("--Lagrange-gap", help="The (relative) Lagrangian gap acceptable for the chance constraint. Default is 10^-4.", action="store", type=float, dest="Lagrange_gap", default=0.0001) conf_options_parser.add_argument("--max-number", help="The max number of PR points. Default = 10.", action="store", dest="max_number", type=int, default=10) conf_options_parser.add_argument("--max-time", help="Maximum time (seconds). Default is 3600.", action="store", dest="max_time", type=float, default=3600) conf_options_parser.add_argument("--csvPrefix", help="Input file name prefix. Default is ''", action="store", dest="csvPrefix", type=str, default="") conf_options_parser.add_argument("--lambda-parm-name", help="The name of the lambda parameter in the model. Default is lambdaMult", action="store", dest="lambda_parm_name", type=str, default="lambdaMult") conf_options_parser.add_argument("--indicator-var-name", help="The name of the indicator variable for the chance constraint. The default is delta", action="store", dest="indicator_var_name", type=str, default="delta") conf_options_parser.add_argument("--stage-num", help="The stage number of the CC indicator variable (number, not name). Default is 2", action="store", dest="stage_num", type=int, default=2) conf_options_parser.add_argument("--verbosity", help="verbosity=0 is no extra output, =1 is medium, =2 is debug, =3 super-debug. Default is 1.", action="store", dest="verbosity", type=int, default=1) conf_options_parser.add_argument("--prob-file", help="file name specifiying probabilities", action="store", dest="probFileName", type=str, default=None) # The following needed for solve_ph_code in lagrangeutils conf_options_parser.add_argument("--solve-with-ph", help="Perform solves via PH rather than an EF solve. Default is False", action="store_true", dest="solve_with_ph", default=False) ################################################################ options = conf_options_parser.parse_args(args=args) # temporary hack options._ef_options = conf_options_parser._ef_options options._ef_options.import_argparse(options) except SystemExit as _exc: # the parser throws a system exit if "-h" is specified - catch # it to exit gracefully. return _exc.code if options.verbose is True: print("Loading reference model and scenario tree") scenario_instance_factory = \ ScenarioTreeInstanceFactory(options.model_directory, options.instance_directory, options.verbose) full_scenario_tree = \ GenerateScenarioTreeForPH(options, scenario_instance_factory) solver_manager = SolverManagerFactory(options.solver_manager_type) if solver_manager is None: raise ValueError("Failed to create solver manager of " "type="+options.solver_manager_type+ " specified in call to PH constructor") if isinstance(solver_manager, pyomo.solvers.plugins.smanager.phpyro.SolverManager_PHPyro): solver_manager.deactivate() raise ValueError("PHPyro can not be used as the solver manager") try: if (scenario_instance_factory is None) or (full_scenario_tree is None): raise RuntimeError("***ERROR: Failed to initialize the model and/or scenario tree data.") # load_model gets called again, so lets make sure unarchived directories are used options.model_directory = scenario_instance_factory._model_filename options.instance_directory = scenario_instance_factory._scenario_tree_filename scenario_count = len(full_scenario_tree._stages[-1]._tree_nodes) # create ph objects for finding the solution. we do this even if # we're solving the extensive form if options.verbose is True: print("Loading scenario instances and initializing scenario tree for full problem.") ########## Here is where multiplier search is called ############ Result = LagrangeMorePR() ##################################################################################### finally: solver_manager.deactivate() # delete temporary unarchived directories scenario_instance_factory.close() print("\n==================== returned from LagrangeMorePR") print(str(Result.status)) try: print("Envelope:") print(str(PrintPRpoints(Result.PRoptimal))) print("\nAdded:") PrintPRpoints(Result.morePR) except: print("from run: PrintPRpoints failed") sys.exit() # combine tables and sort by probability if len(Result.morePR) > 0: PRpoints = copy.deepcopy(Result.PRoptimal) for lbz in Result.morePR: PRpoints.append(lbz) print("Combined table of PR points (sorted):") PRpoints.sort(key=operator.itemgetter(1)) print(str(PrintPRpoints(PRpoints)))
from pyomo.environ import * from pyomo.opt import SolverFactory, SolverManagerFactory from DiseaseEstimation import model # create the instance instance = model.create('DiseaseEstimation.dat') # define the solver and its options solver = 'ipopt' opt = SolverFactory(solver) if opt is None: raise ValueError, "Problem constructing solver `" + str(solver) opt.set_options('max_iter=2') # create the solver manager solver_manager = SolverManagerFactory('serial') # solve results = solver_manager.solve(instance, opt=opt, tee=True, timelimit=None) instance.load(results) # display results display(instance)
def solveGeneratedInstance(self, instance, inst_name): # Nutze Solver Manager None/string if self.solver_manager_name is not None: with SolverManagerFactory(self.solver_manager_name) as solver_manager: if self.EXE_path is None: opt = SolverFactory(self.solver, solver_io=self.solver_io) else: opt = SolverFactory(self.solver, solver_io=self.solver_io, executable=self.EXE_path) # Solve the instance :: Clean gets no Logs if not self.clean: self.result = solver_manager.solve(instance, opt=opt, tee=self.tee, logfile=inst_name+".log") else: self.result = solver_manager.solve(instance, opt=opt, tee=self.tee,) else: path_log = ["logs", "logfiles", inst_name+".log"] if self.EXE_path is None: with SolverFactory(self.solver, solver_io=self.solver_io) as opt: # Set Solver Options try: for key, value in self.solver_options.items(): opt.options[key] = value except AttributeError: pass # Solve the instance :: Clean gets no Logs if not self.clean: self.result = opt.solve(instance, tee=self.tee, load_solutions=self.load_solutions, symbolic_solver_labels= self.symbolic_solver_labels, logfile=os.path.join(*path_log)) else: self.result = opt.solve(instance, tee=self.tee, load_solutions=self.load_solutions, symbolic_solver_labels= self.symbolic_solver_labels) else: with SolverFactory(self.solver, solver_io=self.solver_io, executable=self.EXE_path) as opt: # Set Solver Options try: for key, value in self.solver_options.items(): opt.options[key] = value except AttributeError: pass # Solve the instance :: Clean gets no Logs if not self.clean: self.result = opt.solve(instance, tee=self.tee, load_solutions=self.load_solutions, symbolic_solver_labels= self.symbolic_solver_labels, logfile=os.path.join(*path_log)) else: self.result = opt.solve(instance, tee=self.tee, load_solutions=self.load_solutions, symbolic_solver_labels= self.symbolic_solver_labels) if not self.load_solutions: if len(self.result.solution) > 0: # you may need to relax these checks in certain cases assert str(self.result.solver.status) == "ok" assert str(self.result.solver.termination_condition) == "optimal" self.absgap = self.result.solution(0).gap # now load the solution instance.solutions.load_from(self.result) self.updateResults({inst_name: self.result}) return instance
def solve_model(model): # Custom Solve Method import datetime trial_pool = { 'sample1':{'solution_file':None,'aspiration':None}, 'sample2':{'solution_file':None,'aspiration':None}, 'sample3':{'solution_file':None,'aspiration':None} } #model1 = copy.deepcopy(model) #model2 = copy.deepcopy(model) #model3 = copy.deepcopy(model) print ("success! \n loading solver......") mip_gap = 0.005 solver_timeout = 300 number_of_trials = 2 solver_sh = 'cplex' #initialization Setting engage_neos = True #initialization Setting j = 1 timeout_arguments = {'cplex':'timelimit','cbc':'sec'} gap_arguments = {'cplex':'mipgap','cbc':'ratio'} # Cplex Local Executable Take : "mip_tolerance_mipgap", mipgap is for neos version # NEOS Server Library Dependency # pyro4 # suds # openopt while j < number_of_trials + 1: from pyomo.opt import SolverFactory, SolverManagerFactory #model.pprint() opt = SolverFactory(solver_sh, solver_io = 'lp') print ('\ninterfacing solver shell :',solver_sh) if engage_neos: solver_manager = SolverManagerFactory('neos') opt.options[timeout_arguments[solver_sh]]= solver_timeout opt.options[gap_arguments[solver_sh]] = mip_gap #opt.symbolic_solver_labels=True #opt.options['slog'] = 1 #opt.enable = 'parallel' print ('\tsolver options >> \n\n\tTolerance Limits:\n\tmip_gap = %s \n\ttimeout = %s'%(str(mip_gap),str(solver_timeout))) print ("\nProcessing Trial Number :",j) print ("\nJob Triggered at :",str(datetime.datetime.now())) print ('\ngenerating production plan...... !! please wait !! \n to interrupt press ctrl+C\n') try: if engage_neos: results = solver_manager.solve(model,opt = opt, tee= True) else: opt.options['threads'] = 3 results = opt.solve(model) #,tee=True) # Method Load Solutions is not available in pyomo versions less than 4.x except: j = j+1 mip_gap = (j-1)*mip_gap solver_sh = 'cplex' engage_neos = True continue #results.write(filename='results'+str(datetime.date.today())+'.json',format = 'json') #print (results) if str(results['Solver'][0]['Termination condition']) in ['infeasible','maxTimeLimit','maxIterations','intermediateNonInteger']: j = j+1 mip_gap = (j-1)*mip_gap solver_sh = 'cplex' engage_neos = True if j == number_of_trials + 1: #print (results['Problem']) #print (results['Solver']) raise AssertionError("Solver Failed with Termination Status : %s"%(str(results['Solver'][0]['Termination condition']))) exit(0) print ('Terminated by:',str(results['Solver'][0]['Termination condition'])) print ("\n\nRetrying...\n\n") else: print ("solution captured") model.solutions.store_to(results) #post_process_results() break print (results['Problem']) print (results['Solver']) print ("\nSolution Retrived at:",str(datetime.datetime.now())) return [model,results]