Changeset 791
- Timestamp:
- 06/10/15 09:03:56 (11 months ago)
- Location:
- mystic
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
mystic/_math/measures.py
r789 r791 362 362 solved = solver.Solution() 363 363 diameter_squared = solver.bestEnergy 364 func_evals = len(evalmon .y)364 func_evals = len(evalmon) 365 365 return solved, diameter_squared, func_evals 366 366 -
mystic/examples/example08.py
r776 r791 91 91 92 92 # use monitor to retrieve results information 93 iterations = len(stepmon .x)93 iterations = len(stepmon) 94 94 cost = stepmon.y[-1] 95 95 print "Generation %d has best Chi-Squared: %f" % (iterations, cost) -
mystic/examples/example09.py
r776 r791 98 98 99 99 # use monitor to retrieve results information 100 iterations = len(stepmon .x)100 iterations = len(stepmon) 101 101 cost = stepmon.y[-1] 102 102 print "Generation %d has best Chi-Squared: %f" % (iterations, cost) -
mystic/examples/example10.py
r776 r791 47 47 # plot the polynomial trajectories 48 48 def plot_params(monitor): 49 x = range(len(monitor.y)) 50 pylab.plot(x,monitor.y,'b-') 51 pylab.axis([1,0.5*x[-1],0,monitor.y[1]],'k-') 49 x = range(len(monitor)) 50 y = monitor.y 51 pylab.plot(x,y,'b-') 52 pylab.axis([1,0.5*x[-1],0,y[1]],'k-') 52 53 pylab.draw() 53 54 return -
mystic/examples/example11.py
r776 r791 46 46 # plot the polynomial trajectories 47 47 def plot_params(monitor): 48 x = range(len(monitor .y))48 x = range(len(monitor)) 49 49 y = monitor.y 50 50 pylab.plot(x,y,'b-') -
mystic/mystic/abstract_solver.py
r787 r791 167 167 def __generations(self): 168 168 """get the number of iterations""" 169 return max(0,len(self.energy_history)-1) 170 #return max(0,len(self._stepmon)-1) 169 return max(0,len(self._stepmon)-1) 171 170 172 171 def __energy_history(self): -
mystic/mystic/differential_evolution.py
r787 r791 374 374 raw = cost 375 375 if ExtraArgs is None: ExtraArgs = () 376 #FIXME: EvaluationMonitor fails for MPI, throws error for 'pp'377 376 from python_map import python_map 378 377 if self._map != python_map: 379 self._fcalls = [0] #FIXME: temporary patch for removing the following line 380 else: 381 self._fcalls, cost = wrap_function(cost, ExtraArgs, self._evalmon) 378 pass #FIXME: EvaluationMonitor fails for MPI, throws error for 'pp' 379 else: fcalls, cost = wrap_function(cost, ExtraArgs, self._evalmon) 382 380 if self._useStrictRange: 383 381 for i in range(self.nPop): … … 428 426 # calculate cost 429 427 trialEnergy = self._map(cost, self.trialSolution, **self._mapconfig) 428 self._fcalls[0] += len(self.trialSolution) #FIXME: manually increment 430 429 431 430 # each trialEnergy should be a scalar -
mystic/mystic/ensemble.py
r790 r791 93 93 #------------------------------------------------------------- 94 94 95 #FIXME: EvaluationMonitor fails for MPI, throws error for 'pp'96 95 from python_map import python_map 97 96 if self._map != python_map: 98 self._fcalls = [0] #FIXME: temporary patch for removing the following line 99 else: 100 self._fcalls, cost = wrap_function(cost, ExtraArgs, self._evalmon) 97 pass #FIXME: EvaluationMonitor fails for MPI, throws error for 'pp' 98 else: fcalls, cost = wrap_function(cost, ExtraArgs, self._evalmon) 101 99 102 100 # set up signal handler … … 210 208 self._stepmon = bestpath #XXX: pointer? copy? 211 209 self._evalmon = besteval #XXX: pointer? copy? 210 self.energy_history = None 211 self.solution_history = None 212 212 #from mystic.tools import isNull 213 213 #if isNull(bestpath): … … 287 287 #------------------------------------------------------------- 288 288 289 #FIXME: EvaluationMonitor fails for MPI, throws error for 'pp'290 289 from python_map import python_map 291 290 if self._map != python_map: 292 self._fcalls = [0] #FIXME: temporary patch for removing the following line 293 else: 294 self._fcalls, cost = wrap_function(cost, ExtraArgs, self._evalmon) 291 pass #FIXME: EvaluationMonitor fails for MPI, throws error for 'pp' 292 else: fcalls, cost = wrap_function(cost, ExtraArgs, self._evalmon) 295 293 296 294 # set up signal handler … … 397 395 self._stepmon = bestpath #XXX: pointer? copy? 398 396 self._evalmon = besteval #XXX: pointer? copy? 397 self.energy_history = None 398 self.solution_history = None 399 399 #from mystic.tools import isNull 400 400 #if isNull(bestpath): … … 532 532 fcalls = solver.evaluations 533 533 all_fcalls = solver._total_evals 534 iterations = max(0,len(solver._stepmon.y)-1) #FIXME:solver.generations534 iterations = solver.generations 535 535 allvecs = solver._stepmon.x 536 536 … … 663 663 fcalls = solver.evaluations 664 664 all_fcalls = solver._total_evals 665 iterations = max(0,len(solver._stepmon.y)-1) #FIXME:solver.generations665 iterations = solver.generations 666 666 allvecs = solver._stepmon.x 667 667 -
mystic/mystic/monitors.py
r776 r791 65 65 import numpy 66 66 from mystic.tools import list_or_tuple_or_ndarray 67 from mystic.tools import listify 67 from mystic.tools import listify, multiply, divide, _kdiv 68 68 69 69 class Null(object): … … 91 91 # comply with monitor interface 92 92 Null.info = Null() 93 Null.k = None 93 94 #XXX: should also have Null.x, Null.y ? 94 95 … … 117 118 self._info = [] 118 119 #self._all = all 120 self.k = kwds.pop('k', None) 119 121 120 122 def __len__(self): … … 126 128 127 129 def __call__(self, x, y, id=None, **kwds):#, best=0): 128 self._x.append(listify(x)) #XXX: better to save as-is?129 self._y.append(listify( y)) #XXX: better to save as-is?130 self._x.append(listify(x)) #XXX: listify? 131 self._y.append(listify(self._k(y, iter))) #XXX: listify? 130 132 self._id.append(id) 131 133 #if not self._all and list_or_tuple_or_ndarray(x): … … 138 140 if isinstance(monitor, Monitor): # is Monitor() 139 141 pass 140 elif (monitor == Null) or isinstance(monitor, Null): # isNull or Null()142 elif (monitor == Null) or isinstance(monitor, Null): # Null or Null() 141 143 monitor = Monitor() 142 144 elif hasattr(monitor, '__module__') and \ 143 monitor.__module__ in ['mystic._genSow']: # isCustomMonitor()145 monitor.__module__ in ['mystic._genSow']: # CustomMonitor() 144 146 pass #XXX: CustomMonitor may fail... 145 147 else: 146 148 raise TypeError, "'%s' is not a monitor instance" % monitor 147 149 self._x.extend(monitor._x) 148 self._y.extend(monitor._y) 150 self._y.extend(self._get_y(monitor)) # scalar, up to 2x faster 151 #self._y.extend(self._k(monitor.iy, iter)) # vector, results like numpy 149 152 self._id.extend(monitor._id) 150 153 self._info.extend(monitor._info) … … 154 157 if isinstance(monitor, Monitor): # is Monitor() 155 158 pass 156 elif (monitor == Null) or isinstance(monitor, Null): # isNull or Null()159 elif (monitor == Null) or isinstance(monitor, Null): # Null or Null() 157 160 monitor = Monitor() 158 161 elif hasattr(monitor, '__module__') and \ 159 monitor.__module__ in ['mystic._genSow']: # isCustomMonitor()162 monitor.__module__ in ['mystic._genSow']: # CustomMonitor() 160 163 pass #XXX: CustomMonitor may fail... 161 164 else: 162 165 raise TypeError, "'%s' is not a monitor instance" % monitor 163 [self._x.insert(i,j) for (i,j) in list(enumerate(monitor._x))] 164 [self._y.insert(i,j) for (i,j) in list(enumerate(monitor._y))] 165 [self._id.insert(i,j) for (i,j) in list(enumerate(monitor._id))] 166 [self._info.insert(i,j) for (i,j) in list(enumerate(monitor._info))] 166 [self._x.insert(*i) for i in enumerate(monitor._x)] 167 [self._y.insert(*i) for i in enumerate(self._get_y(monitor))] 168 #[self._y.insert(*i) for i in enumerate(self._k(monitor.iy, iter))] 169 [self._id.insert(*i) for i in enumerate(monitor._id)] 170 [self._info.insert(*i) for i in enumerate(monitor._info)] 167 171 #XXX: may be faster ways of doing the above... 168 172 # (e.g. deepcopy(monitor) allows enumerate w/o list()) … … 171 175 return self._x 172 176 173 def get_y(self):174 return self._y175 176 177 def get_id(self): 177 178 return self._id … … 182 183 def __step(self): 183 184 return len(self.x) 185 186 #BELOW: madness due to monitor k-conversion 187 188 def get_y(self): # can be slow if k not in (1, None) 189 return divide(self._y, self.k, list) 190 #XXX: better if everywhere y = _y, as opposed to y = _ik(_y) ? 191 # better if k only applied to 'output' of __call__ ? 192 # better if k ionly applied on 'exit' from solver ? 193 194 def _get_y(self, monitor): 195 "avoid double-conversion by combining k's" 196 _ik = _kdiv(monitor.k, self.k, float) #XXX: always a float? 197 return divide(monitor._y, _ik, iter) 198 199 def get_ix(self): 200 return divide(self._y, 1, iter) 201 202 def get_ax(self): 203 return divide(self._y, 1, numpy.array) 204 205 def get_iy(self): 206 return divide(self._y, self.k, iter) 207 208 def get_ay(self): 209 return divide(self._y, self.k, numpy.array) 210 211 def _k(self, y, type=list): 212 return multiply(y, self.k, type) 213 214 def _ik(self, y, k=False, type=list): 215 if k: return y # k's already applied, so don't un-apply it 216 return divide(y, self.k, type) 217 184 218 _step = property(__step) 185 219 x = property(get_x, doc = "Params") 220 ix = property(get_ix, doc = "Params") 221 ax = property(get_ax, doc = "Params") 186 222 y = property(get_y, doc = "Costs") 223 iy = property(get_iy, doc = "Costs") 224 ay = property(get_ay, doc = "Costs") 187 225 id = property(get_id, doc = "Id") 188 226 pass … … 194 232 current parameters every 'xinterval'. 195 233 """ 196 def __init__(self, interval = 10, xinterval = numpy.inf, all=True):197 super(VerboseMonitor,self).__init__( )234 def __init__(self, interval=10, xinterval=numpy.inf, all=True, **kwds): 235 super(VerboseMonitor,self).__init__(**kwds) 198 236 if not interval or interval is numpy.nan: interval = numpy.inf 199 237 if not xinterval or xinterval is numpy.nan: xinterval = numpy.inf … … 206 244 print "%s" % "".join(["",str(message)]) 207 245 return 208 def __call__(self, x, y, id=None, best=0 ):209 super(VerboseMonitor,self).__call__(x, y, id )246 def __call__(self, x, y, id=None, best=0, k=False): 247 super(VerboseMonitor,self).__call__(x, y, id, k=k) 210 248 if self._yinterval is not numpy.inf and \ 211 249 int((self._step-1) % self._yinterval) == 0: 212 250 if not list_or_tuple_or_ndarray(y): 213 251 who = '' 214 y = " %f" % self._ y[-1]215 elif self._all: 216 who = '' 217 y = " %s" % self._ y[-1]252 y = " %f" % self._ik(self._y[-1], k) 253 elif self._all: 254 who = '' 255 y = " %s" % self._ik(self._y[-1], k) 218 256 else: 219 257 who = ' best' 220 y = " %f" % self._ y[-1][best]258 y = " %f" % self._ik(self._y[-1][best], k) 221 259 msg = "Generation %d has%s Chi-Squared:%s" % (self._step-1,who,y) 222 260 if id is not None: msg = "[id: %d] " % (id) + msg … … 244 282 Logs ChiSq and parameters to a file every 'interval' 245 283 """ 246 def __init__(self, interval=1, filename='log.txt', new=False, all=True, info=None ):284 def __init__(self, interval=1, filename='log.txt', new=False, all=True, info=None, **kwds): 247 285 import datetime 248 super(LoggingMonitor,self).__init__( )286 super(LoggingMonitor,self).__init__(**kwds) 249 287 self._filename = filename 250 288 if not interval or interval is numpy.nan: interval = numpy.inf … … 266 304 self._file.close() 267 305 return 268 def __call__(self, x, y, id=None, best=0 ):306 def __call__(self, x, y, id=None, best=0, k=False): 269 307 self._file = open(self._filename,'a') 270 super(LoggingMonitor,self).__call__(x, y, id )308 super(LoggingMonitor,self).__call__(x, y, id, k=k) 271 309 if self._yinterval is not numpy.inf and \ 272 310 int((self._step-1) % self._yinterval) == 0: 273 311 if not list_or_tuple_or_ndarray(y): 274 y = "%f" % self._ y[-1]275 elif self._all: 276 y = "%s" % self._ y[-1]277 else: 278 y = "%f" % self._ y[-1][best]312 y = "%f" % self._ik(self._y[-1], k) 313 elif self._all: 314 y = "%s" % self._ik(self._y[-1], k) 315 else: 316 y = "%f" % self._ik(self._y[-1][best], k) 279 317 if not list_or_tuple_or_ndarray(x): 280 318 x = "[%f]" % self._x[-1] … … 299 337 interval = self._yinterval 300 338 filename = self._filename 301 new=False 302 all=self._all 303 info=None 304 return (self.__class__, (interval, filename, new, all, info)) 339 new = False 340 all = self._all 341 info = None 342 args = (interval, filename, new, all, info) 343 k = self.k 344 state = dict(_x=self._x,_y=self._y,_id=self._id,_info=self._info,k=k) 345 return (self.__class__, args, state) 346 def __setstate__(self, state): 347 self.__dict__.update(state) 348 return 305 349 pass 306 350 … … 310 354 Logs ChiSq and parameters to a file every 'interval', print every 'yinterval' 311 355 """ 312 def __init__(self, interval=1, yinterval=10, xinterval=numpy.inf, filename='log.txt', new=False, all=True, info=None ):313 super(VerboseLoggingMonitor,self).__init__(interval,filename,new,all,info )356 def __init__(self, interval=1, yinterval=10, xinterval=numpy.inf, filename='log.txt', new=False, all=True, info=None, **kwds): 357 super(VerboseLoggingMonitor,self).__init__(interval,filename,new,all,info,**kwds) 314 358 if not yinterval or yinterval is numpy.nan: yinterval = numpy.inf 315 359 if not xinterval or xinterval is numpy.nan: xinterval = numpy.inf … … 321 365 print "%s" % "".join(["",str(message)]) 322 366 return 323 def __call__(self, x, y, id=None, best=0 ):324 super(VerboseLoggingMonitor,self).__call__(x, y, id, best )367 def __call__(self, x, y, id=None, best=0, k=False): 368 super(VerboseLoggingMonitor,self).__call__(x, y, id, best, k=k) 325 369 if self._vyinterval is not numpy.inf and \ 326 370 int((self._step-1) % self._vyinterval) == 0: 327 371 if not list_or_tuple_or_ndarray(y): 328 372 who = '' 329 y = " %f" % self._ y[-1]330 elif self._all: 331 who = '' 332 y = " %s" % self._ y[-1]373 y = " %f" % self._ik(self._y[-1], k) 374 elif self._all: 375 who = '' 376 y = " %s" % self._ik(self._y[-1], k) 333 377 else: 334 378 who = ' best' 335 y = " %f" % self._ y[-1][best]379 y = " %f" % self._ik(self._y[-1][best], k) 336 380 msg = "Generation %d has%s Chi-Squared:%s" % (self._step-1,who,y) 337 381 if id is not None: msg = "[id: %d] " % (id) + msg … … 353 397 return 354 398 def __reduce__(self): 355 interval = self._yinterval 356 yint erval =self._vyinterval357 xint erval =self._vxinterval399 interval = self._yinterval 400 yint = self._vyinterval 401 xint = self._vxinterval 358 402 filename = self._filename 359 new=False 360 all=self._all 361 info=None 362 return (self.__class__, (interval, yinterval, xinterval, filename, new, all, info)) 403 new = False 404 all = self._all 405 info = None 406 args = (interval, yint, xint, filename, new, all, info) 407 k = self.k 408 state = dict(_x=self._x,_y=self._y,_id=self._id,_info=self._info,k=k) 409 return (self.__class__, args, state) 410 def __setstate__(self, state): 411 self.__dict__.update(state) 412 return 363 413 pass 364 414 -
mystic/mystic/munge.py
r776 r791 81 81 return steps, energy, id 82 82 83 def write_monitor(steps, energy, id=[] ):83 def write_monitor(steps, energy, id=[], k=None): 84 84 from mystic.monitors import Monitor 85 85 mon = Monitor() 86 mon._x = steps[:] 87 mon._y = energy[:] 88 mon._id = id[:] 86 mon.k = k 87 mon._x.extend(steps) 88 mon._y.extend(mon._k(energy, iter)) 89 mon._id.extend(id) 89 90 return mon 90 91 -
mystic/mystic/scipy_optimize.py
r785 r791 463 463 self._termination = NCOG(ftol,gtol) 464 464 465 def __generations(self): 466 """get the number of iterations""" 467 return max(0,len(self.energy_history)-1) #XXX: slower for k=-1 ? 468 465 469 def _SetEvaluationLimits(self, iterscale=1000, evalscale=1000): 466 470 super(PowellDirectionalSolver, self)._SetEvaluationLimits(iterscale,evalscale) … … 632 636 ExtraArgs, **kwds) 633 637 return 638 639 # extensions to the solver interface 640 generations = property(__generations ) 641 pass 634 642 635 643 -
mystic/mystic/tools.py
r781 r791 16 16 Main functions exported are:: 17 17 - isiterable: check if an object is iterable 18 - itertype: get the 'underlying' type used to construct x 19 - multiply: recursive elementwise casting multiply of x by n 20 - divide: recursive elementwise casting divide of x by n 18 21 - flatten: flatten a sequence 19 22 - flatten_array: flatten an array … … 50 53 #return hasattr(x, '__len__') or hasattr(x, '__iter__') 51 54 52 def list_or_tuple(x): 55 def itertype(x, default=tuple): 56 """get the 'underlying' type used to construct x""" 57 _type = type(x) 58 try: 59 if _type((0,)): return _type # non-iterator iterables 60 except TypeError: pass 61 try: 62 if _type(1): return _type # non-iterables 63 except TypeError: pass 64 # iterators, etc 65 _type = type(x).__name__.split('iterator')[0] 66 types = ('xrange','generator','') # and ...? 67 if _type in types: return default 68 try: 69 return eval(_type) 70 except NameError: return default 71 72 def _kdiv(num, denom, type=None): 73 """'special' scalar division for 'k'""" 74 if num is denom is None: return None 75 if denom is None: denom = 1 76 if num is None: num = 1 77 if type is not None: num = type(num) 78 return num/denom 79 80 def multiply(x, n, type=list, recurse=False): # list, iter, numpy.array, ... 81 """multiply: recursive elementwise casting multiply of x by n""" 82 # short-circuit cases for speed 83 if n is None: return x 84 try: # for scalars and vectors (numpy.arrays) 85 -x # x*n might not throw an error 86 return x*n 87 except TypeError: pass 88 if n is 1: return type(x) 89 if type.__name__ == 'array': return type(x)*n 90 # multiply by n != 1 for iterables (iter and non-iter) 91 if recurse: 92 return type(multiply(i,n,type) for i in x) 93 return type(i*n for i in x) 94 95 def divide(x, n, type=list, recurse=False): # list, iter, numpy.array, ... 96 """elementwise division of x by n, returning the selected type""" 97 # short-circuit cases for speed 98 if n is None: return x 99 try: # for scalars and vectors (numpy.arrays) 100 return x/n 101 except TypeError: pass 102 if n is 1: return type(x) 103 if type.__name__ == 'array': return type(x)/n 104 # divide by n != 1 for iterables (iter and non-iter) 105 if recurse: 106 return type(divide(i,n,type) for i in x) 107 return type(i/n for i in x) 108 109 def _multiply(x, n): 110 """elementwise multiplication of x by n, as if x were an array""" 111 # short-circuit cases for speed 112 if n is None: return x 113 try: # for scalars and vectors (numpy.arrays) 114 -x # x*n might not throw an error 115 return x*n 116 except TypeError: pass 117 if n is 1: return itertype(x)(x) 118 # multiply by n != 1 for iterables (iter and non-iter) 119 xn = (_multiply(i,n) for i in x) 120 # return astype used to construct x, if possible 121 return itertype(x)(xn) 122 123 def _divide(x, n): 124 """elementwise division of x by n, as if x were an array""" 125 # short-circuit cases for speed 126 if n is None: return x 127 try: # for scalars and vectors (numpy.arrays) 128 return x/n 129 except TypeError: pass 130 if n is 1: return itertype(x)(x) 131 # divide by n != 1 for iterables (iter and non-iter) 132 xn = (_divide(i,n) for i in x) 133 # return astype used to construct x, if possible 134 return itertype(x)(xn) 135 136 def _imultiply(x, n): 137 """iterator for elementwise 'array-like' multiplication of x by n""" 138 # short-circuit cases for speed 139 if n is None: return x 140 try: # for scalars and vectors (numpy.arrays) 141 -x # x*n might not throw an error 142 return iter(x*n) 143 except TypeError: pass 144 if n is 1: return iter(x) 145 # multiply by n != 1 for iterables (iter and non-iter) 146 return (_multiply(i,n) for i in x) 147 148 def _idivide(x, n): 149 """iterator for elementwise 'array-like' division of x by n""" 150 # short-circuit cases for speed 151 if n is None: return x 152 try: # for scalars and vectors (numpy.arrays) 153 return iter(x/n) 154 except TypeError: pass 155 if n is 1: return iter(x) 156 # divide by n != 1 for iterables (iter and non-iter) 157 return (_divide(i,n) for i in x) 158 159 def _amultiply(x, n): 160 """elementwise 'array-casting' multiplication of x by n""" 161 # short-circuit cases for speed 162 if n is None: return x 163 # convert to numpy array 164 import numpy 165 x = numpy.asarray(x) 166 if n is 1: return x 167 return x*n 168 169 def _adivide(x, n): 170 """elementwise 'array-casting' division of x by n""" 171 # short-circuit cases for speed 172 if n is None: return x 173 # convert to numpy array 174 import numpy 175 x = numpy.asarray(x) 176 if n is 1: return x 177 return x/n 178 179 def list_or_tuple(x): # set, ...? 53 180 "True if x is a list or a tuple" 54 181 return isinstance(x, (list, tuple)) 55 182 56 def list_or_tuple_or_ndarray(x): 183 def list_or_tuple_or_ndarray(x): # set, ...? 57 184 "True if x is a list, tuple, or a ndarray" 58 185 import numpy … … 61 188 def listify(x): 62 189 "recursivly convert all members of a sequence to a list" 63 if not list_or_tuple_or_ndarray(x): return x 64 #if isinstance(x, numpy.ndarray) and x.ndim == 0: return x # i.e. array(1) 65 if not list_or_tuple(x) and x.ndim == 0: return x.flatten()[0] 190 if not isiterable(x): return x 191 if x is iter(x): return listify(list(x)) 192 try: # e.g. if array(1) 193 if x.ndim == 0: return x.flatten()[0] 194 except Exception: pass 66 195 return [listify(i) for i in x] 67 196 -
mystic/tests/test_solver_sanity.py
r776 r791 74 74 #if self.uselimits and self.maxiter == 0: iter=0 75 75 # sanity check solver internals 76 self.assertTrue(solver.generations == len(solver._stepmon. y)-iter)76 self.assertTrue(solver.generations == len(solver._stepmon._y)-iter) 77 77 self.assertTrue(list(solver.bestSolution) == solver._stepmon.x[-1]) #XXX 78 78 self.assertTrue(solver.bestEnergy == solver._stepmon.y[-1]) … … 82 82 self.assertTrue(ssow.x == solver._stepmon.x) 83 83 self.assertTrue(ssow.y == solver._stepmon.y) 84 self.assertTrue(ssow._y == solver._stepmon._y) 84 85 if self.useevalmon: 85 self.assertTrue(solver.evaluations == len(solver._evalmon. y))86 self.assertTrue(solver.evaluations == len(solver._evalmon._y)) 86 87 self.assertTrue(esow.x == solver._evalmon.x) 87 88 self.assertTrue(esow.y == solver._evalmon.y) 89 self.assertTrue(esow._y == solver._evalmon._y) 88 90 89 91 # Fail appropriately for solver/termination mismatch
Note: See TracChangeset
for help on using the changeset viewer.