1# ___________________________________________________________________________ 2# 3# Pyomo: Python Optimization Modeling Objects 4# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC 5# Under the terms of Contract DE-NA0003525 with National Technology and 6# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain 7# rights in this software. 8# This software is distributed under the 3-clause BSD License. 9# ___________________________________________________________________________ 10 11import time 12import pyomo.opt 13from pyomo.core import TransformationFactory, Var, Set 14from pyomo.common.collections import Bunch 15 16 17@pyomo.opt.SolverFactory.register('bilevel_bqp', 18 doc='Global solver for bilevel quadratic problems') 19class BILEVEL_Solver4(pyomo.opt.OptSolver): 20 21 def __init__(self, **kwds): 22 kwds['type'] = 'bilevel_bqp' 23 pyomo.opt.OptSolver.__init__(self,**kwds) 24 self._metasolver = True 25 26 def _presolve(self, *args, **kwds): 27 self._instance = args[0] 28 pyomo.opt.OptSolver._presolve(self, *args, **kwds) 29 30 def _apply_solver(self): 31 start_time = time.time() 32 if not self.options.bigM: 33 self._bigM = 999 34 else: 35 self._bigM = self.options.bigM 36 # 37 # Cache the instance 38 # 39 xfrm = TransformationFactory('bilevel.linear_mpec') 40 xfrm.apply_to(self._instance) 41 xfrm = TransformationFactory('mpec.simple_disjunction') 42 xfrm.apply_to(self._instance) 43 xfrm = TransformationFactory('gdp.bigm') 44 xfrm.apply_to(self._instance, bigM=self.options.get('bigM',self._bigM)) 45 # 46 ##self._instance.pprint() 47 48 xfrm = TransformationFactory('gdp.bilinear') 49 xfrm.apply_to(self._instance) 50 xfrm = TransformationFactory('gdp.bigm') 51 #xfrm.apply_to(self._instance, bigM=self.options.get('bigM',self._bigM)) 52 xfrm.apply_to(self._instance, bigM=8888) 53 54 ##self._instance.pprint() 55 # 56 # Solve with a specified solver 57 # 58 solver = self.options.solver 59 if not solver: 60 solver = 'glpk' 61 # use the with block here so that deactivation of the 62 # solver plugin always occurs thereby avoiding memory 63 # leaks caused by plugins! 64 with pyomo.opt.SolverFactory(solver) as opt: 65 # 66 self.results = [] 67 # 68 # **NOTE: It would be better to override _presolve on the 69 # base class of this solver as you might be 70 # missing a number of keywords that were passed 71 # into the solve method (e.g., none of the 72 # io_options are getting relayed to the subsolver 73 # here). 74 # 75 self.results.append(opt.solve(self._instance, 76 tee=self._tee, 77 timelimit=self._timelimit, 78 symbolic_solver_labels=False, 79 keepfiles=False 80 )) 81 # 82 stop_time = time.time() 83 self.wall_time = stop_time - start_time 84 #self._instance.pprint() 85 #self._instance.display() 86 # 87 # Deactivate the block that contains the optimality conditions, 88 # and reactivate SubModel 89 # 90 submodel = self._instance._transformation_data[ 91 'bilevel.linear_mpec'].submodel_cuid.find_component_on( 92 self._instance) 93 for (name, data) in submodel.component_map(active=False).items(): 94 if not isinstance(data,Var) and not isinstance(data,Set): 95 data.activate() 96 # 97 # TODO: delete this subblock 98 # TODO: Remove bilinear and bigM blocks 99 # 100 self._instance._transformation_data[ 101 'bilevel.linear_mpec'].block_cuid.find_component_on( 102 self._instance).deactivate() 103 # 104 # Return the sub-solver return condition value and log 105 # 106 return Bunch(rc=getattr(opt,'_rc', None), 107 log=getattr(opt,'_log',None)) 108 109 def _postsolve(self): 110 # 111 # Create a results object 112 # 113 results = pyomo.opt.SolverResults() 114 # 115 # SOLVER 116 # 117 solv = results.solver 118 solv.name = self.options.subsolver 119 #solv.status = self._glpk_get_solver_status() 120 #solv.memory_used = "%d bytes, (%d KiB)" % (peak_mem, peak_mem/1024) 121 solv.wallclock_time = self.wall_time 122 cpu_ = [] 123 for res in self.results: 124 if not getattr(res.solver, 'cpu_time', None) is None: 125 cpu_.append( res.solver.cpu_time ) 126 if len(cpu_) > 0: 127 solv.cpu_time = sum(cpu_) 128 # 129 # TODO: detect infeasibilities, etc 130 # 131 solv.termination_condition = pyomo.opt.TerminationCondition.optimal 132 # 133 # PROBLEM 134 # 135 prob = results.problem 136 prob.name = self._instance.name 137 prob.number_of_constraints = self._instance.statistics.number_of_constraints 138 prob.number_of_variables = self._instance.statistics.number_of_variables 139 prob.number_of_binary_variables = self._instance.statistics.number_of_binary_variables 140 prob.number_of_integer_variables = self._instance.statistics.number_of_integer_variables 141 prob.number_of_continuous_variables = self._instance.statistics.number_of_continuous_variables 142 prob.number_of_objectives = self._instance.statistics.number_of_objectives 143 # 144 ##from pyomo.core import maximize 145 ##if self._instance.sense == maximize: 146 ##prob.sense = pyomo.opt.ProblemSense.maximize 147 ##else: 148 ##prob.sense = pyomo.opt.ProblemSense.minimize 149 # 150 # SOLUTION(S) 151 # 152 self._instance.solutions.store_to(results) 153 # 154 # Uncache the instance 155 # 156 self._instance = None 157 return results 158 159