def vector2point(x): # x = asarray(x) # if not str(x.dtype).startswith('float'): # x = asfarray(x) x = atleast_1d(x).copy() if array_equal(x, p._FDtranslator['prevX']): return p._FDtranslator['prevVal'] # without copy() ipopt and probably others can replace it by noise after closing # r = oopoint(startDictData + \ # [(oov, x[oovar_indexes[i]:oovar_indexes[i+1]]) for i, oov in enumerate(freeVars)]) r = startDictData tmp = [ (oov, x[oovar_indexes[i]:oovar_indexes[i + 1]] if oovar_indexes[i + 1] - oovar_indexes[i] > 1 else x[oovar_indexes[i]]) for i, oov in enumerate(freeVars) ] # for i, oov in enumerate(freeVars): # #I, J = oovar_indexes[i], oovar_indexes[i+1] # #r.append((oov, x[I] if J - I == 1 else x[I:J])) # r.append((oov, x[oovar_indexes[i]:oovar_indexes[i+1]])) r = oopoint(r + tmp, skipArrayCast=True) r.maxDistributionSize = p.maxDistributionSize p._FDtranslator['prevVal'] = r p._FDtranslator['prevX'] = copy(x) return r
def func82(y, e, vv, f, dataType, p, Th = None): domain = oopoint([(v, (y[:, i], e[:, i])) for i, v in enumerate(vv)], skipArrayCast=True, isMultiPoint=True) domain.dictOfFixedFuncs = p.dictOfFixedFuncs #print(Th) r, r0 = f.iqg(domain, dataType, UB = Th) o_l, o_u, a_l, a_u = [], [], [], [] definiteRange = r0.definiteRange for v in vv: # TODO: rework and optimize it tmp = r.get(v, None) if tmp is not None: o_l.append(tmp[0].lb) o_u.append(tmp[1].lb) a_l.append(tmp[0].ub) a_u.append(tmp[1].ub) definiteRange = logical_and(definiteRange, tmp[0].definiteRange) definiteRange = logical_and(definiteRange, tmp[1].definiteRange) else: o_l.append(r0.lb) o_u.append(r0.lb) a_l.append(r0.ub) a_u.append(r0.ub) #definiteRange = logical_and(definiteRange, r0.definiteRange) o, a = hstack(o_l+o_u), hstack(a_l+a_u) return o, a, definiteRange
def func82(y, e, vv, f, dataType, p, Th=None): domain = oopoint([(v, (y[:, i], e[:, i])) for i, v in enumerate(vv)], skipArrayCast=True, isMultiPoint=True) domain.dictOfFixedFuncs = p.dictOfFixedFuncs r, r0 = f.iqg(domain, dataType, UB=Th) o_l, o_u, a_l, a_u = [], [], [], [] definiteRange = r0.definiteRange for v in vv: # TODO: rework and optimize it tmp = r.get(v, None) if tmp is not None: o_l.append(tmp[0].lb) o_u.append(tmp[1].lb) a_l.append(tmp[0].ub) a_u.append(tmp[1].ub) definiteRange = logical_and(definiteRange, tmp[0].definiteRange) definiteRange = logical_and(definiteRange, tmp[1].definiteRange) else: o_l.append(r0.lb) o_u.append(r0.lb) a_l.append(r0.ub) a_u.append(r0.ub) #definiteRange = logical_and(definiteRange, r0.definiteRange) o, a = hstack(o_l + o_u), hstack(a_l + a_u) return o, a, definiteRange, domain.exactRange
def setNonLinFuncsNumber(p, userFunctionType): # userFunctionType should be 'f', 'c' or 'h' args = getattr(p.args, userFunctionType) fv = getattr(p.user, userFunctionType) if p.isFDmodel: from FuncDesigner import oopoint X = oopoint(p._x0, maxDistributionSize=p.maxDistributionSize) kwargs = { 'Vars': p.freeVars, 'fixedVarsScheduleID': p._FDVarsID, 'fixedVars': p.fixedVars } else: X = p.x0 kwargs = {} if len(fv) == 1: p.functype[userFunctionType] = 'single func' if fv is None or (type(fv) in [list, tuple] and (len(fv) == 0 or fv[0] is None)): setattr(p, 'n' + userFunctionType, 0) elif type(fv) in [list, tuple] and len(fv) > 1: # TODO: handle problems w/o x0, like GLP number = 0 arr = [] for func in fv: if isinstance(func, (list, tuple, set, ndarray)): for elem in func: number += asarray(elem(*(X, ) + args)).size else: number += asarray(func(*(X, ) + args)).size arr.append(number) if len(arr) < number: p.functype[userFunctionType] = 'block' elif len(arr) > 1: p.functype[userFunctionType] = 'some funcs R^nvars -> R' else: assert p.functype[userFunctionType] == 'single func' setattr(p, 'n' + userFunctionType, number) if p.functype[userFunctionType] == 'block': setattr(p, 'arr_of_indexes_' + userFunctionType, array(arr) - 1) else: if type(fv) in [list, tuple]: FV = fv[0] else: FV = fv tmp = FV(*(X, ) + args, **kwargs) if p.isFDmodel: #from FuncDesigner.baseClasses import Stochastic #if isinstance(tmp, Stochastic): if 'quantified' in dir(tmp): p.err(''' Optimization problem objective and constraints cannot be of type Stochastic, you can handle only functions on them like mean(X), std(X), var(X), P(X<Y) etc''' ) setattr(p, 'n'+userFunctionType, \ sum([asarray(elem).size for elem in tmp]) if isinstance(tmp, (list, tuple)) else asarray(tmp).size)
def __init__(self, p): self.rf = asscalar(asarray(p.rf)) self.ff = asscalar(asarray(p.ff)) self.isFDmodel = p.isFDmodel self.probType = p.probType if p.probType == 'EIG': self.eigenvalues, self.eigenvectors = p.eigenvalues, p.eigenvectors if p.isFDmodel: from FuncDesigner import oopoint self.xf = dict([(v, asscalar(val) if isinstance(val, ndarray) and val.size ==1 else v.aux_domain[val] if 'aux_domain' in v.__dict__ else val) for v, val in p.xf.items()]) if not hasattr(self, '_xf'): #self._xf = dict([(v.name, asscalar(val) if isinstance(val, ndarray) and val.size ==1 else val) for v, val in p.xf.items()]) self._xf = dict([(v.name, val) for v, val in self.xf.items()]) self.xf = oopoint(self.xf, maxDistributionSize = p.maxDistributionSize) else: self.xf = p.xf #if len(p.solutions) == 0 and p.isFeas(p.xk): p.solutions = [p.xk] # TODO: mb perform check on each solution for more safety? # although it can slow down calculations for huge solutions number #self.solutions = p.solutions self.elapsed = dict() self.elapsed['solver_time'] = round(100.0*(time() - p.timeStart))/100.0 self.elapsed['solver_cputime'] = round(100.0*(clock() - p.cpuTimeStart))/100.0 for fn in ('ff', 'istop', 'duals', 'isFeasible', 'msg', 'stopcase', 'iterValues', 'special', 'extras', 'solutions'): if hasattr(p, fn): setattr(self, fn, getattr(p, fn)) if hasattr(p.solver, 'innerState'): self.extras['innerState'] = p.solver.innerState self.solverInfo = dict() for fn in ('homepage', 'alg', 'authors', 'license', 'info', 'name'): self.solverInfo[fn] = getattr(p.solver, '__' + fn + '__') # note - it doesn't work for len(args)>1 for current Python ver 2.6 #self.__getitem__ = c # = self.__call__ if p.plot: #for df in p.graphics.drawFuncs: df(p) #TODO: include time spent here to (/cpu)timeElapsedForPlotting self.elapsed['plot_time'] = round(100*p.timeElapsedForPlotting[-1])/100 # seconds self.elapsed['plot_cputime'] = p.cpuTimeElapsedForPlotting[-1] else: self.elapsed['plot_time'] = 0 self.elapsed['plot_cputime'] = 0 self.elapsed['solver_time'] -= self.elapsed['plot_time'] self.elapsed['solver_cputime'] -= self.elapsed['plot_cputime'] self.evals = dict([(key, val if type(val) == int else round(val *10) /10.0) for key, val in p.nEvals.items()]) self.evals['iter'] = p.iter
def func10(y, e, vv): m, n = y.shape LB = [[] for i in range(n)] UB = [[] for i in range(n)] r4 = (y + e) / 2 # TODO: remove the cycle #T1, T2 = tile(y, (2*n,1)), tile(e, (2*n,1)) for i in range(n): t1, t2 = tile(y[:, i], 2*n), tile(e[:, i], 2*n) #t1, t2 = T1[:, i], T2[:, i] #T1[(n+i)*m:(n+i+1)*m, i] = T2[i*m:(i+1)*m, i] = r4[:, i] t1[(n+i)*m:(n+i+1)*m] = t2[i*m:(i+1)*m] = r4[:, i] # if vv[i].domain is bool: # indINQ = y[:, i] != e[:, i] # tmp = t1[(n+i)*m:(n+i+1)*m] # tmp[indINQ] = 1 # tmp = t2[i*m:(i+1)*m] # tmp[indINQ] = 0 # if vv[i].domain is bool: # t1[(n+i)*m:(n+i+1)*m] = 1 # t2[i*m:(i+1)*m] = 0 # else: # t1[(n+i)*m:(n+i+1)*m] = t2[i*m:(i+1)*m] = r4[:, i] LB[i], UB[i] = t1, t2 #### LB[i], UB[i] = T1[:, i], T2[:, i] # sh1, sh2, inds = [], [], [] # for i in range(n): # sh1+= arange((n+i)*m, (n+i+1)*m).tolist() # inds += [i]*m # sh2 += arange(i*m, (i+1)*m).tolist() # sh1, sh2, inds = asdf(m, n) # asdf2(T1, T2, r4, sh1, sh2, inds) #domain = dict([(v, (T1[:, i], T2[:, i])) for i, v in enumerate(vv)]) domain = dict([(v, (LB[i], UB[i])) for i, v in enumerate(vv)]) domain = oopoint(domain, skipArrayCast = True) domain.isMultiPoint = True return domain
def func10(y, e, vv): m, n = y.shape LB = [[] for i in range(n)] UB = [[] for i in range(n)] r4 = (y + e) / 2 # TODO: remove the cycle #T1, T2 = tile(y, (2*n,1)), tile(e, (2*n,1)) for i in range(n): t1, t2 = tile(y[:, i], 2 * n), tile(e[:, i], 2 * n) #t1, t2 = T1[:, i], T2[:, i] #T1[(n+i)*m:(n+i+1)*m, i] = T2[i*m:(i+1)*m, i] = r4[:, i] t1[(n + i) * m:(n + i + 1) * m] = t2[i * m:(i + 1) * m] = r4[:, i] # if vv[i].domain is bool: # indINQ = y[:, i] != e[:, i] # tmp = t1[(n+i)*m:(n+i+1)*m] # tmp[indINQ] = 1 # tmp = t2[i*m:(i+1)*m] # tmp[indINQ] = 0 # if vv[i].domain is bool: # t1[(n+i)*m:(n+i+1)*m] = 1 # t2[i*m:(i+1)*m] = 0 # else: # t1[(n+i)*m:(n+i+1)*m] = t2[i*m:(i+1)*m] = r4[:, i] LB[i], UB[i] = t1, t2 #### LB[i], UB[i] = T1[:, i], T2[:, i] # sh1, sh2, inds = [], [], [] # for i in range(n): # sh1+= arange((n+i)*m, (n+i+1)*m).tolist() # inds += [i]*m # sh2 += arange(i*m, (i+1)*m).tolist() # sh1, sh2, inds = asdf(m, n) # asdf2(T1, T2, r4, sh1, sh2, inds) #domain = dict([(v, (T1[:, i], T2[:, i])) for i, v in enumerate(vv)]) domain = dict([(v, (LB[i], UB[i])) for i, v in enumerate(vv)]) domain = oopoint(domain, skipArrayCast=True) domain.isMultiPoint = True return domain
def setNonLinFuncsNumber(p, userFunctionType): # userFunctionType should be 'f', 'c' or 'h' args = getattr(p.args, userFunctionType) fv = getattr(p.user, userFunctionType) if p.isFDmodel: from FuncDesigner import oopoint X = oopoint(p._x0, maxDistributionSize = p.maxDistributionSize) kwargs = {'Vars': p.freeVars, 'fixedVarsScheduleID':p._FDVarsID, 'fixedVars': p.fixedVars} else: X = p.x0 kwargs = {} if len(fv) == 1: p.functype[userFunctionType] = 'single func' if fv is None or (type(fv) in [list, tuple] and (len(fv)==0 or fv[0] is None)): setattr(p, 'n'+userFunctionType, 0) elif type(fv) in [list, tuple] and len(fv)>1: # TODO: handle problems w/o x0, like GLP number = 0 arr = [] for func in fv: if isinstance(func, (list, tuple, set, ndarray)): for elem in func: number += asarray(elem(*(X,) + args)).size else: number += asarray(func(*(X,) + args)).size arr.append(number) if len(arr) < number: p.functype[userFunctionType] = 'block' elif len(arr) > 1: p.functype[userFunctionType] = 'some funcs R^nvars -> R' else: assert p.functype[userFunctionType] == 'single func' setattr(p, 'n' + userFunctionType, number) if p.functype[userFunctionType] == 'block': setattr(p, 'arr_of_indexes_' + userFunctionType, array(arr)-1) else: if type(fv) in [list, tuple]: FV = fv[0] else: FV = fv tmp = FV(*(X, ) + args, **kwargs) if p.isFDmodel: #from FuncDesigner.baseClasses import Stochastic #if isinstance(tmp, Stochastic): if 'quantified' in dir(tmp): p.err(''' Optimization problem objective and constraints cannot be of type Stochastic, you can handle only functions on them like mean(X), std(X), var(X), P(X<Y) etc''') setattr(p, 'n'+userFunctionType, \ sum([asarray(elem).size for elem in tmp]) if isinstance(tmp, (list, tuple)) else asarray(tmp).size)
def vector2point(x): # x = asarray(x) # if not str(x.dtype).startswith('float'): # x = asfarray(x) x = atleast_1d(x).copy() if array_equal(x, p._FDtranslator['prevX']): return p._FDtranslator['prevVal'] # without copy() ipopt and probably others can replace it by noise after closing # r = oopoint(startDictData + \ # [(oov, x[oovar_indexes[i]:oovar_indexes[i+1]]) for i, oov in enumerate(freeVars)]) r = startDictData tmp = [(oov, x[oovar_indexes[i]:oovar_indexes[i+1]] if oovar_indexes[i+1]-oovar_indexes[i]>1 else x[oovar_indexes[i]]) for i, oov in enumerate(freeVars)] # for i, oov in enumerate(freeVars): # #I, J = oovar_indexes[i], oovar_indexes[i+1] # #r.append((oov, x[I] if J - I == 1 else x[I:J])) # r.append((oov, x[oovar_indexes[i]:oovar_indexes[i+1]])) r = oopoint(r+tmp, skipArrayCast = True) r.maxDistributionSize = p.maxDistributionSize p._FDtranslator['prevVal'] = r p._FDtranslator['prevX'] = copy(x) return r
def interalg_ODE_routine(p, solver): isIP = p.probType == 'IP' isODE = p.probType == 'ODE' if isODE: f, y0, t, r30, ftol = p.equations, p.x0, p.timeVariable, p.times, p.ftol assert len(f) == 1, 'multiple ODE equations are unimplemented for FuncDesigner yet' f = list(f.values())[0] elif isIP: assert p.n == 1 and p.__isNoMoreThanBoxBounded__() f, y0, ftol = p.user.f[0], 0.0, p.ftol if p.fTol is not None: ftol = p.fTol t = list(f._getDep())[0] r30 = p.domain[t] p.iterfcn(p.point([nan]*p.n)) else: p.err('incorrect prob type for interalg ODE routine') eq_var = list(p._x0.keys())[0] dataType = solver.dataType if type(ftol) == int: ftol = float(ftol) # e.g. someone set ftol = 1 # Currently ftol is scalar, in future it can be array of same length as timeArray if len(r30) < 2: p.err('length ot time array must be at least 2') # if any(r30[1:] < r30[:-1]): # p.err('currently interalg can handle only time arrays sorted is ascending order') # if any(r30 < 0): # p.err('currently interalg can handle only time arrays with positive values') # if p.times[0] != 0: # p.err('currently solver interalg requires times start from zero') r37 = abs(r30[-1] - r30[0]) r28 = asarray(atleast_1d(r30[0]), dataType) r29 = asarray(atleast_1d(r30[-1]), dataType) storedr28 = [] r27 = [] r31 = [] r32 = [] r33 = ftol F = 0.0 p._Residual = 0 # Main cycle for itn in range(p.maxIter+1): if r30[-1] > r30[0]: mp = oopoint({t: [r28, r29]}, skipArrayCast = True) else: mp = oopoint({t: [r29, r28]}, skipArrayCast = True) mp.isMultiPoint = True delta_y = f.interval(mp, dataType) if not all(delta_y.definiteRange): p.err(''' solving ODE with interalg is implemented for definite (real) range only, no NaN values in integrand are allowed''') # TODO: perform check on NaNs r34 = atleast_1d(delta_y.ub) r35 = atleast_1d(delta_y.lb) r36 = atleast_1d(r34 - r35 <= 0.95 * r33 / r37) ind = where(r36)[0] if isODE: storedr28.append(r28[ind]) r27.append(r29[ind]) r31.append(r34[ind]) r32.append(r35[ind]) else: assert isIP F += 0.5 * sum((r29[ind]-r28[ind])*(r34[ind]+r35[ind])) #p._Residual = p._residual + 0.5*sum((abs(r34) +abs(r35)) * (r29 - r28)) if ind.size != 0: tmp = abs(r29[ind] - r28[ind]) Tmp = sum((r34[ind] - r35[ind]) * tmp) r33 -= Tmp if isIP: p._residual += Tmp r37 -= sum(tmp) ind = where(logical_not(r36))[0] if ind.size == 0: p.istop = 1000 p.msg = 'problem has been solved according to required tolerance' break # OLD # for i in ind: # t0, t1 = r28[i], r29[i] # t_m = 0.5 * (t0+t1) # newr28.append(t0) # newr28.append(t_m) # newr29.append(t_m) # newr29.append(t1) # NEW r38, r39 = r28[ind], r29[ind] r40 = 0.5 * (r38 + r39) r28 = vstack((r38, r40)).flatten() r29 = vstack((r40, r39)).flatten() # !!! unestablished !!! if isODE: p.iterfcn(fk = r33/ftol) elif isIP: p.iterfcn(xk=array(nan), fk=F, rk = 0) else: p.err('bug in interalgODE.py') if p.istop != 0 : break #print(itn, r28.size) if isODE: t0, t1, lb, ub = hstack(storedr28), hstack(r27), hstack(r32), hstack(r31) ind = argsort(t0) if r30[0] > r30[-1]: ind = ind[::-1] # reverse t0, t1, lb, ub = t0[ind], t1[ind], lb[ind], ub[ind] lb, ub = y0+(lb*(t1-t0)).cumsum(), y0+(ub*(t1-t0)).cumsum() #y_var = p._x0.keys()[0] #p.xf = p.xk = 0.5*(lb+ub) p.extras = {'startTimes': t0, 'endTimes': t1, eq_var:{'infinums': lb, 'supremums': ub}} return t0, t1, lb, ub elif isIP: P = p.point([nan]*p.n) P._f = F P._mr = r33 P._mrName = 'None' P._mrInd = 0 # p.xk = array([nan]*p.n) # p.rk = r33 # p.fk = F #p._Residual = p.iterfcn(asarray([nan]*p.n), fk=F, rk=0) else: p.err('incorrect prob type in interalg ODE routine')
def interalg_ODE_routine(p, solver): isIP = p.probType == 'IP' isODE = p.probType == 'ODE' if isODE: f, y0, r30, ftol = p.equations, p.x0, p.times, p.ftol assert len( f ) == 1, 'multiple ODE equations are unimplemented for FuncDesigner yet' f = list(f.values())[0] t = list(f._getDep())[0] elif isIP: assert p.n == 1 and p.__isNoMoreThanBoxBounded__() f, y0, ftol = p.user.f[0], 0.0, p.ftol if p.fTol is not None: ftol = p.fTol t = list(f._getDep())[0] r30 = p.domain[t] p.iterfcn(p.point([nan] * p.n)) else: p.err('incorrect prob type for interalg ODE routine') eq_var = list(p._x0.keys())[0] dataType = solver.dataType if type(ftol) == int: ftol = float(ftol) # e.g. someone set ftol = 1 # Currently ftol is scalar, in future it can be array of same length as timeArray if len(r30) < 2: p.err('length ot time array must be at least 2') # if any(r30[1:] < r30[:-1]): # p.err('currently interalg can handle only time arrays sorted is ascending order') # if any(r30 < 0): # p.err('currently interalg can handle only time arrays with positive values') # if p.times[0] != 0: # p.err('currently solver interalg requires times start from zero') r37 = abs(r30[-1] - r30[0]) # if len(r30) == 2: # r30 = np.linspace(r30[0], r30[-1], 150) r28 = asarray(atleast_1d(r30[:-1]), dataType) r29 = asarray(atleast_1d(r30[1:]), dataType) r20_store = array([], float) r38_store = array([], float) r39_store = array([], float) maxActiveNodes = 150000 #solver.maxActiveNodes storedr28 = [] r27 = [] r31 = [] r32 = [] r33 = ftol F = 0.0 p._Residual = 0 # Main cycle for itn in range(p.maxIter + 1): p.extras['nNodes'].append(r28.size) p.extras['nActiveNodes'].append(r28.size) mp = oopoint({t: [r28, r29] if r30[-1] > r30[0] else [r29, r28]}, skipArrayCast=True) mp.isMultiPoint = True mp.dictOfFixedFuncs = p.dictOfFixedFuncs mp.surf_preference = True tmp = f.interval(mp, ia_surf_level=2 if isIP else 1) if not all(tmp.definiteRange): p.err(''' solving ODE and IP by interalg is implemented for definite (real) range only, no NaN values in integrand are allowed''') # TODO: perform check on NaNs isBoundsurf = hasattr(tmp, 'resolve') if isBoundsurf: if isIP: if tmp.level == 1: #adjustr4WithDiscreteVariables(wr4, p) cs = oopoint([(v, asarray(0.5 * (val[0] + val[1]), dataType)) for v, val in mp.items()]) cs.dictOfFixedFuncs = p.dictOfFixedFuncs r21, r22 = tmp.values(cs) o, a = atleast_1d(r21), atleast_1d(r22) r20 = a - o approx_value = 0.5 * (a + o) else: assert tmp.level == 2 ts, te = r28, r29 A, B = (te**2 + te * ts + ts**2) / 3.0, 0.5 * (te + ts) a, b, c = tmp.l.d2.get(t, 0.0), tmp.l.d.get(t, 0.0), tmp.l.c val_l = a * A + b * B + c a, b, c = tmp.u.d2.get(t, 0.0), tmp.u.d.get(t, 0.0), tmp.u.c val_u = a * A + b * B + c r20 = val_u - val_l approx_value = 0.5 * (val_l + val_u) # import pylab, numpy # xx = numpy.linspace(-1, 0, 1000) # pylab.plot(xx, tmp.l.d2.get(t, 0.0)[1]*xx**2+ tmp.l.d.get(t, 0.0)[1]*xx+ tmp.l.c[1], 'r') # pylab.plot(xx, tmp.u.d2.get(t, 0.0)[1]*xx**2+ tmp.u.d.get(t, 0.0)[1]*xx+ tmp.u.c[1], 'b') # pylab.grid() # pylab.show() elif isODE: l, u = tmp.l, tmp.u assert len(l.d) <= 1 and len(u.d) <= 1 # at most time variable l_koeffs, u_koeffs = l.d.get(t, 0.0), u.d.get(t, 0.0) l_c, u_c = l.c, u.c # dT = r29 - r28 if r30[-1] > r30[0] else r28 - r29 ends = oopoint([(v, asarray(val[1], dataType)) for v, val in mp.items()]) ends.dictOfFixedFuncs = p.dictOfFixedFuncs ends_L, ends_U = tmp.values(ends) starts = oopoint([(v, asarray(val[0], dataType)) for v, val in mp.items()]) starts.dictOfFixedFuncs = p.dictOfFixedFuncs starts_L, starts_U = tmp.values(starts) # o, a = atleast_1d(r21), atleast_1d(r22) o, a = tmp.resolve()[0] # r20 = 0.5 * u_koeffs * dT + u_c - (0.5 * l_koeffs * dT + l_c) r20_end = 0.5 * (ends_U - ends_L) r20_start = 0.5 * (starts_U - starts_L) r20 = where(r20_end > r20_start, r20_end, r20_start) # r20 = 0.5 * u_koeffs * dT ** 2 + u_c * dT - (0.5 * l_koeffs * dT ** 2 + l_c * dT) # r20 = 0.5*u_koeffs * dT + u_c - ( 0.5*l_koeffs * dT + l_c) # o = 0.5*l_koeffs * dT + l_c # a = 0.5*u_koeffs * dT + u_c #assert 0, 'unimplemented' else: assert 0 else: o, a = atleast_1d(tmp.lb), atleast_1d(tmp.ub) ends_L = starts_L = o ends_U = starts_U = a r20 = a - o approx_value = 0.5 * (a + o) if isODE: r36 = atleast_1d(r20 <= 0.95 * r33) r36 = np.logical_and(r36, r20 < ftol) r36 = np.logical_and(r36, a - o < ftol) # else: # r36 = atleast_1d(r20 <= 0.95 * r33 / r37) if isODE and isBoundsurf: d = r37 #if not isODE or not isBoundsurf else len(r28) r36 = np.logical_and(atleast_1d(r20_end <= 0.95 * r33 / d), atleast_1d(r20_start <= 0.95 * r33 / d)) r36 &= atleast_1d(r20_end <= ftol) r36 &= atleast_1d(r20_start <= ftol) else: r36 = atleast_1d(r20 <= 0.95 * r33 / r37) # r36 = np.logical_and(r36, r20 < ftol) # r36 = np.logical_and(r36, a-o < ftol) ind = where(r36)[0] if isODE: storedr28.append(r28[ind]) r27.append(r29[ind]) r31.append(a[ind]) r32.append(o[ind]) # r31.append(ends_U[ind]) # r32.append(ends_L[ind]) else: assert isIP #F += 0.5 * sum((r29[ind]-r28[ind])*(a[ind]+o[ind])) F += sum((r29[ind] - r28[ind]) * approx_value[ind]) if ind.size != 0: tmp = abs(r29[ind] - r28[ind]) Tmp = sum(r20[ind] * tmp) #if not isODE or not isBoundsurf else sum(r20[ind]) r33 -= Tmp if isIP: p._residual += Tmp r37 -= sum(tmp) ind = where(logical_not(r36))[0] if 1: #new if ind.size == 0 and r20_store.size == 0: p.istop = 1000 p.msg = 'problem has been solved according to required user-defined accuracy %0.1g' % ftol break if ind.size != 0: # TODO: use merge sorted lists if r20_store.size != 0: r20_store = hstack( (r20_store, r20[ind] * abs(r29[ind] - r28[ind]))) r38_store = hstack((r38_store, r28[ind])) r39_store = hstack((r39_store, r29[ind])) else: r20_store = r20[ind] * abs(r29[ind] - r28[ind]) r38_store, r39_store = r28[ind], r29[ind] ind_a = argsort(r20_store) r20_store = r20_store[ind_a] r38_store = r38_store[ind_a] r39_store = r39_store[ind_a] r38_store, r38 = r38_store[:-maxActiveNodes], r38_store[ -maxActiveNodes:] r39_store, r39 = r39_store[:-maxActiveNodes], r39_store[ -maxActiveNodes:] r20_store = r20_store[:-maxActiveNodes] r40 = 0.5 * (r38 + r39) r28 = vstack((r38, r40)).flatten() r29 = vstack((r40, r39)).flatten() else: if ind.size == 0: p.istop = 1000 p.msg = 'problem has been solved according to required user-defined accuracy %0.1g' % ftol break r38, r39 = r28[ind], r29[ind] r40 = 0.5 * (r38 + r39) r28 = vstack((r38, r40)).flatten() r29 = vstack((r40, r39)).flatten() # !!! unestablished !!! if isODE: p.iterfcn(fk=r33 / ftol) elif isIP: p.iterfcn(xk=array(nan), fk=F, rk=ftol - r33) else: p.err('bug in interalgODE.py') if p.istop != 0: break #print(itn, r28.size) if isODE: t0, t1, lb, ub = hstack(storedr28), hstack(r27), hstack(r32), hstack( r31) ind = argsort(t0) if r30[0] > r30[-1]: ind = ind[::-1] # reverse t0, t1, lb, ub = t0[ind], t1[ind], lb[ind], ub[ind] lb, ub = hstack((y0, y0 + (lb * (t1 - t0)).cumsum())), hstack( (y0, y0 + (ub * (t1 - t0)).cumsum())) #y_var = p._x0.keys()[0] #p.xf = p.xk = 0.5*(lb+ub) p.extras = { 'startTimes': t0, 'endTimes': t1, eq_var: { 'infinums': lb, 'supremums': ub } } return t0, t1, lb, ub elif isIP: P = p.point([nan] * p.n) P._f = F P._mr = ftol - r33 P._mrName = 'None' P._mrInd = 0 # p.xk = array([nan]*p.n) # p.rk = r33 # p.fk = F #p._Residual = p.iterfcn(asarray([nan] * p.n), fk=F, rk=ftol - r33) else: p.err('incorrect prob type in interalg ODE routine')
def getr4Values(vv, y, e, tnlh, func, C, contol, dataType, p, fo=inf): #print where(y), where(e!=1) n = y.shape[1] # TODO: rework it wrt nlh #cs = dict([(key, asarray((val[0]+val[1])/2, dataType)) for key, val in domain.items()]) wr4_0 = (y + e) / 2 if tnlh is None: # or p.probType =='MOP': wr4 = wr4_0 else: tnlh = tnlh.copy() tnlh[atleast_1d(tnlh < 1e-300)] = 1e-300 # to prevent division by zero tnlh[atleast_1d(isnan(tnlh))] = inf #- check it! tnlh_l_inv, tnlh_u_inv = 1.0 / tnlh[:, :n], 1.0 / tnlh[:, n:] wr4 = (y * tnlh_l_inv + e * tnlh_u_inv) / (tnlh_l_inv + tnlh_u_inv) ind = tnlh_l_inv == tnlh_u_inv # especially important for tnlh_l_inv == tnlh_u_inv = 0 wr4[ind] = (y[ind] + e[ind]) / 2 wr4_1 = (wr4 + wr4_0) / 2 wr4 = vstack((wr4, wr4_0, wr4_1)) adjustr4WithDiscreteVariables(wr4, p) cs = dict([(oovar, asarray(wr4[:, i], dataType)) for i, oovar in enumerate(vv)]) cs = oopoint(cs, skipArrayCast=True) cs.isMultiPoint = True cs.update(p.dictOfFixedFuncs) m = wr4.shape[0] kw = { 'Vars': p.freeVars } if p.freeVars is None or (p.fixedVars is not None and len(p.freeVars) < len(p.fixedVars)) else { 'fixedVars': p.fixedVars } kw['fixedVarsScheduleID'] = p._FDVarsID if len(C) != 0: r15 = empty(m, bool) r15.fill(True) for _c, f, r16, r17 in C: c = f(cs, **kw) ind = logical_and( c >= r16, c <= r17 ) # here r16 and r17 are already shifted by required tolerance r15 = logical_and(r15, ind) else: r15 = True isMOP = p.probType == 'MOP' if not any(r15): F = empty(m, dataType) F.fill(2**31 - 2 if dataType in (int16, int32, int64, int) else nan) if isMOP: FF = [F for k in range(p.nf)] elif all(r15): if isMOP: FF = [fun(cs, **kw) for fun in func] else: F = func(cs, **kw) if func is not None else zeros( m) # func is None for SNLE else: #cs = dict([(oovar, (y[r15, i] + e[r15, i])/2) for i, oovar in enumerate(vv)]) #cs = ooPoint(cs, skipArrayCast = True) #cs.isMultiPoint = True if isMOP: FF = [] for fun in func: tmp = fun(cs, **kw) F = empty(m, dataType) F.fill(2**31 - 15 if dataType in (int16, int32, int64, int) else nan) F[r15] = tmp[r15] FF.append(F) else: tmp = asarray(func(cs, ** kw), dataType) if func is not None else zeros( m) # func is None for SNLE F = empty(m, dataType) F.fill(2**31 - 15 if dataType in (int16, int32, int64, int) else nan) F[r15] = tmp[r15] if isMOP: return array(FF).T.reshape(m, len(func)).tolist(), wr4.tolist() else: return atleast_1d(F), wr4
def __solver__(self, p): isMOP = p.probType == 'MOP' if isMOP: from interalgMOP import r14MOP #isOpt = p.probType in ['NLP', 'NSP', 'GLP', 'MINLP'] isODE = p.probType == 'ODE' isSNLE = p.probType in ('NLSP', 'SNLE') if not p.__isFiniteBoxBounded__() and not isODE: p.err(''' solver %s requires finite lb, ub: lb <= x <= ub (you can use "implicitBoounds") ''' % self.__name__) # if p.fixedVars is not None: # p.err('solver %s cannot handle FuncDesigner problems with some variables declared as fixed' % self.__name__) if p.probType in ('LP', 'MILP'): p.err("the solver can't handle problems of type " + p.probType) if not p.isFDmodel: p.err('solver %s can handle only FuncDesigner problems' % self.__name__) dataType = self.dataType if type(dataType) == str: if not hasattr(np, dataType): p.pWarn( 'your architecture has no type "%s", float64 will be used instead' % dataType) dataType = 'float64' dataType = getattr(np, dataType) self.dataType = dataType isIP = p.probType == 'IP' if isIP: pb = r14IP p._F = asarray(0, self.dataType) p._residual = 0.0 f_int = p.user.f[0].interval(p.domain, self.dataType) p._r0 = prod(p.ub - p.lb) * (f_int.ub - f_int.lb) p._volume = 0.0 p.kernelIterFuncs.pop(IS_NAN_IN_X) elif isMOP: pb = r14MOP else: pb = r14 for val in p._x0.values(): if isinstance(val, (list, tuple, np.ndarray)) and len(val) > 1: p.pWarn(''' solver %s currently can handle only single-element variables, use oovars(n) instead of oovar(size=n), elseware correct result is not guaranteed ''' % self.__name__) vv = list(p._freeVarsList) x0 = dict([(v, p._x0[v]) for v in vv]) for val in x0.values(): if isinstance(val, (list, tuple, np.ndarray)) and len(val) > 1: p.err(''' solver %s currently can handle only single-element variables, use oovars(n) instead of oovar(size=n)''' % self.__name__) point = p.point p.kernelIterFuncs.pop(SMALL_DELTA_X, None) p.kernelIterFuncs.pop(SMALL_DELTA_F, None) p.kernelIterFuncs.pop(MAX_NON_SUCCESS, None) if not bottleneck_is_present and not isODE: p.pWarn(''' installation of Python module "bottleneck" (http://berkeleyanalytics.com/bottleneck, available via easy_install, takes several minutes for compilation) could speedup the solver %s''' % self.__name__) n = p.n maxSolutions = p.maxSolutions if maxSolutions == 0: maxSolutions = 10**50 if maxSolutions != 1 and p.fEnough != -np.inf: p.warn(''' using the solver interalg with non-single solutions mode is not ajusted with fEnough stop criterium yet, it will be omitted ''') p.kernelIterFuncs.pop(FVAL_IS_ENOUGH) nNodes = [] p.extras['nNodes'] = nNodes nActiveNodes = [] p.extras['nActiveNodes'] = nActiveNodes Solutions = Solution() Solutions.maxNum = maxSolutions Solutions.solutions = [] Solutions.coords = np.array([]).reshape(0, n) p.solutions = Solutions lb, ub = asarray(p.lb, dataType).copy(), asarray(p.ub, dataType).copy() fTol = p.fTol if isIP or isODE: if p.ftol is None: if fTol is not None: p.ftol = fTol else: p.err( 'interalg requires user-supplied ftol (required precision)' ) if fTol is None: fTol = p.ftol elif fTol != p.ftol: p.err('you have provided both ftol and fTol') if fTol is None and not isMOP: # TODO: require tols for MOP fTol = 1e-7 p.warn( 'solver %s require p.fTol value (required objective function tolerance); 10^-7 will be used' % self.__name__) xRecord = 0.5 * (lb + ub) adjustr4WithDiscreteVariables(xRecord.reshape(1, -1), p) r40 = np.inf y = lb.reshape(1, -1) e = ub.reshape(1, -1) r41 = np.inf # TODO: maybe rework it, especially for constrained case fStart = self.fStart # TODO: remove it after proper SNLE handling implementation if isSNLE: r41 = 0.0 # asdf1 = None eqs = [fd_abs(elem) for elem in p.user.f] asdf1 = fd_sum(eqs) # TODO: check it, for reducing calculations #C.update([elem == 0 for elem in p.user.f]) elif isMOP: asdf1 = p.user.f Solutions.F = [] if point(p.x0).isFeas(altLinInEq=False): Solutions.solutions.append(p.x0.copy()) Solutions.coords = asarray(Solutions.solutions) Solutions.F.append(p.f(p.x0)) p._solutions = Solutions elif not isODE: asdf1 = p.user.f[0] #if p.fOpt is not None: fOpt = p.fOpt if p.goal in ('max', 'maximum'): asdf1 = -asdf1 if p.fOpt is not None: p.fOpt = -p.fOpt if fStart is not None and fStart < r40: r41 = fStart for X0 in [point(xRecord), point(p.x0)]: if X0.isFeas(altLinInEq=False) and X0.f() < r40: r40 = X0.f() if p.isFeas(p.x0): tmp = asdf1(p._x0) if tmp < r41: r41 = tmp if p.fOpt is not None: if p.fOpt > r41: p.warn('user-provided fOpt seems to be incorrect, ') r41 = p.fOpt # if isSNLE: # if self.dataHandling == 'raw': # p.pWarn(''' # this interalg data handling approach ("%s") # is unimplemented for SNLE yet, dropping to "sorted"'''%self.dataHandling) # # # handles 'auto' as well # self.dataHandling ='sorted' domain = oopoint([(v, [p.lb[i], p.ub[i]]) for i, v in enumerate(vv)], skipArrayCast=True) domain.dictOfFixedFuncs = p.dictOfFixedFuncs #from FuncDesigner.ooFun import BooleanOOFun, SmoothFDConstraint if self.dataHandling == 'auto': if isIP or isODE: self.dataHandling = 'sorted' elif isMOP or p.hasLogicalConstraints: self.dataHandling = 'raw' else: r = p.user.f[0].interval(domain, self.dataType) M = np.max((np.max(np.atleast_1d(np.abs(r.lb))), np.max(np.atleast_1d(np.abs(r.ub))))) for ( c, func, lb, ub, tol ) in p._FD.nonBoxCons: #[Elem[1] for Elem in p._FD.nonBoxCons]: # !!!!!!!!!!!!!!!!!!!! check it - mb 2nd condition is incorrect #if isinstance(c, BooleanOOFun) and not isinstance(c, SmoothFDConstraint): continue if hasattr(c, '_unnamedBooleanOOFunNumber'): continue r = func.interval(domain, self.dataType) M = np.max((M, np.max(np.atleast_1d(np.abs(r.lb))))) M = np.max((M, np.max(np.atleast_1d(np.abs(r.ub))))) self.dataHandling = 'raw' if M < 1e5 else 'sorted' #self.dataHandling = 'sorted' if isIP or (p.__isNoMoreThanBoxBounded__() and n < 50) else 'raw' # TODO: is it required yet? if not isMOP and not p.hasLogicalConstraints: p._isOnlyBoxBounded = p.__isNoMoreThanBoxBounded__() if isODE or (asdf1.isUncycled and p._isOnlyBoxBounded and np.all( np.isfinite(p.user.f[0].interval(domain).lb))): #maxNodes = 1 self.dataHandling = 'sorted' if self.dataHandling == 'sorted' and p.hasLogicalConstraints: p.warn( "interalg: for general logical constraints only dataHandling='raw' mode works" ) self.dataHandling = 'raw' self.maxActiveNodes = int(self.maxActiveNodes) # if self.maxActiveNodes < 2: # p.warn('maxActiveNodes should be at least 2 while you have provided %d. Setting it to 2.' % self.maxActiveNodes) self.maxNodes = int(self.maxNodes) _in = np.array([], object) g = np.inf C = p._FD.nonBoxConsWithTolShift C0 = p._FD.nonBoxCons # if isOpt: # r = [] # for (elem, lb, ub, tol) in C0: # if tol == 0: tol = p.contol # if lb == ub: # r.append(fd_max((fd_abs(elem-lb)-tol, 0)) * (fTol/tol)) # elif lb == -inf: # r.append(fd_max((0, elem-ub-tol)) * (fTol/tol)) # elif ub == inf: # r.append(fd_max((0, lb-elem-tol)) * (fTol/tol)) # else: # p.err('finite box constraints are unimplemented for interalg yet') #p._cons_obj = 1e100 * fd_sum(r) if len(r) != 0 else None #p._cons_obj = fd_sum(r) if len(r) != 0 else None if isSNLE: C += [(elem == 0, elem, -(elem.tol if elem.tol != 0 else p.ftol), (elem.tol if elem.tol != 0 else p.ftol)) for elem in p.user.f] C0 += [(elem == 0, elem, 0, 0, (elem.tol if elem.tol != 0 else p.ftol)) for elem in p.user.f] # TODO: hanlde fixed variables here varTols = p.variableTolerances if Solutions.maxNum != 1: if not isSNLE: p.err(''' "search several solutions" mode is unimplemented for the prob type %s yet''' % p.probType) if any(varTols == 0): p.err(''' for the mode "search all solutions" you have to provide all non-zero tolerances for each variable (oovar) ''') pnc = 0 an = [] maxNodes = self.maxNodes # TODO: change for constrained probs _s = atleast_1d(inf) if isODE or (isIP and p.n == 1): interalg_ODE_routine(p, self) return while 1: if len(C0) != 0: y, e, nlhc, residual, definiteRange, indT, _s = processConstraints( C0, y, e, _s, p, dataType) else: nlhc, residual, definiteRange, indT = None, None, True, None if y.size != 0: an, g, fo, _s, Solutions, xRecord, r41, r40 = \ pb(p, nlhc, residual, definiteRange, y, e, vv, asdf1, C, r40, g, \ nNodes, r41, fTol, Solutions, varTols, _in, \ dataType, maxNodes, _s, indT, xRecord) if _s is None: break else: an = _in fo = 0.0 if isSNLE or isMOP else min( (r41, r40 - (fTol if Solutions.maxNum == 1 else 0.0))) pnc = max((len(np.atleast_1d(an)), pnc)) if isIP: y, e, _in, _s = \ func12(an, self.maxActiveNodes, p, Solutions, vv, varTols, np.inf) else: y, e, _in, _s = \ func12(an, self.maxActiveNodes, p, Solutions, vv, varTols, fo) nActiveNodes.append(y.shape[0] / 2) if y.size == 0: if len(Solutions.coords) > 1: p.istop, p.msg = 1001, 'all solutions have been obtained' else: p.istop, p.msg = 1000, 'solution has been obtained' break ############# End of main cycle ############### if not isSNLE and not isIP and not isMOP: if p._bestPoint.betterThan(p.point(p.xk)): p.iterfcn(p._bestPoint) else: p.iterfcn(p.xk) ff = p.fk # ff may be not assigned yet # ff = p._bestPoint.f() # p.xk = p._bestPoint.x if isIP: p.xk = np.array([np.nan] * p.n) p.rk = p._residual p.fk = p._F isFeas = len(Solutions.F) != 0 if isMOP else p.isFeas( p.xk) if not isIP else p.rk < fTol if not isFeas and p.istop > 0: p.istop, p.msg = -1000, 'no feasible solution has been obtained' o = asarray([t.o for t in an]) if o.size != 0: g = nanmin([nanmin(o), g]) if not isMOP: p.extras['isRequiredPrecisionReached'] = \ True if ff - g < fTol and isFeas else False # and (k is False or (isSNLE and (p._nObtainedSolutions >= maxSolutions or maxSolutions==1))) if not isMOP and not p.extras[ 'isRequiredPrecisionReached'] and p.istop > 0: p.istop = -1 p.msg = 'required precision is not guarantied' # TODO: simplify it if not isMOP: tmp = [ nanmin(np.hstack((ff, g, o.flatten()))), np.asscalar(np.array(ff)) ] if p.goal in ['max', 'maximum']: tmp = (-tmp[1], -tmp[0]) p.extras[ 'extremumBounds'] = tmp if not isIP else 'unimplemented for IP yet' p.solutions = [p._vector2point(s) for s in Solutions.coords] if not isMOP else \ MOPsolutions([p._vector2point(s) for s in Solutions.coords]) if isMOP: for i, s in enumerate(p.solutions): s.useAsMutable = True for j, goal in enumerate(p.user.f): s[goal] = Solutions.F[i][j] s.useAsMutable = False p.solutions.values = np.asarray(Solutions.F) p.solutions.coords = Solutions.coords if not isMOP and p.maxSolutions == 1: delattr(p, 'solutions') if isSNLE and p.maxSolutions != 1: for v in p._categoricalVars: for elem in r.solutions: elem.useAsMutable = True elem[v] = v.aux_domain[elem[v]] elem.useAsMutable = False if p.iprint >= 0 and not isMOP: # s = 'Solution with required tolerance %0.1e \n is%s guarantied (obtained precision: %0.1e)' \ # %(fTol, '' if p.extras['isRequiredPrecisionReached'] else ' NOT', tmp[1]-tmp[0]) s = 'Solution with required tolerance %0.1e \n is%s guarantied' \ %(fTol, '' if p.extras['isRequiredPrecisionReached'] else ' NOT') if not isIP and p.maxSolutions == 1: s += ' (obtained precision: %0.1e)' % np.abs(tmp[1] - tmp[0]) if not p.extras[ 'isRequiredPrecisionReached'] and pnc == self.maxNodes: s += '\nincrease maxNodes (current value %d)' % self.maxNodes p.info(s)
def __solver__(self, p): isMOP = p.probType == 'MOP' if isMOP: from interalgMOP import r14MOP #isOpt = p.probType in ['NLP', 'NSP', 'GLP', 'MINLP'] isODE = p.probType == 'ODE' isSNLE = p.probType in ('NLSP', 'SNLE') if not p.__isFiniteBoxBounded__() and not isODE: p.err(''' solver %s requires finite lb, ub: lb <= x <= ub (you can use "implicitBoounds") ''' % self.__name__) # if p.fixedVars is not None: # p.err('solver %s cannot handle FuncDesigner problems with some variables declared as fixed' % self.__name__) if p.probType in ('LP', 'MILP'): p.err("the solver can't handle problems of type " + p.probType) if not p.isFDmodel: p.err('solver %s can handle only FuncDesigner problems' % self.__name__) dataType = self.dataType if type(dataType) == str: if not hasattr(np, dataType): p.pWarn('your architecture has no type "%s", float64 will be used instead' % dataType) dataType = 'float64' dataType = getattr(np, dataType) self.dataType = dataType isIP = p.probType == 'IP' if isIP: pb = r14IP p._F = asarray(0, self.dataType) p._residual = 0.0 f_int = p.user.f[0].interval(p.domain, self.dataType) p._r0 = prod(p.ub-p.lb) * (f_int.ub - f_int.lb) p._volume = 0.0 p.kernelIterFuncs.pop(IS_NAN_IN_X) elif isMOP: pb = r14MOP else: pb = r14 for val in p._x0.values(): if isinstance(val, (list, tuple, np.ndarray)) and len(val) > 1: p.pWarn(''' solver %s currently can handle only single-element variables, use oovars(n) instead of oovar(size=n), elseware correct result is not guaranteed '''% self.__name__) vv = list(p._freeVarsList) x0 = dict([(v, p._x0[v]) for v in vv]) for val in x0.values(): if isinstance(val, (list, tuple, np.ndarray)) and len(val) > 1: p.err(''' solver %s currently can handle only single-element variables, use oovars(n) instead of oovar(size=n)'''% self.__name__) point = p.point p.kernelIterFuncs.pop(SMALL_DELTA_X, None) p.kernelIterFuncs.pop(SMALL_DELTA_F, None) p.kernelIterFuncs.pop(MAX_NON_SUCCESS, None) if not bottleneck_is_present and not isODE: p.pWarn(''' installation of Python module "bottleneck" (http://berkeleyanalytics.com/bottleneck, available via easy_install, takes several minutes for compilation) could speedup the solver %s''' % self.__name__) n = p.n maxSolutions = p.maxSolutions if maxSolutions == 0: maxSolutions = 10**50 if maxSolutions != 1 and p.fEnough != -np.inf: p.warn(''' using the solver interalg with non-single solutions mode is not ajusted with fEnough stop criterium yet, it will be omitted ''') p.kernelIterFuncs.pop(FVAL_IS_ENOUGH) nNodes = [] p.extras['nNodes'] = nNodes nActiveNodes = [] p.extras['nActiveNodes'] = nActiveNodes Solutions = Solution() Solutions.maxNum = maxSolutions Solutions.solutions = [] Solutions.coords = np.array([]).reshape(0, n) p.solutions = Solutions lb, ub = asarray(p.lb, dataType).copy(), asarray(p.ub, dataType).copy() fTol = p.fTol if isIP or isODE: if p.ftol is None: if fTol is not None: p.ftol = fTol else: p.err('interalg requires user-supplied ftol (required precision)') if fTol is None: fTol = p.ftol elif fTol != p.ftol: p.err('you have provided both ftol and fTol') if fTol is None and not isMOP: # TODO: require tols for MOP fTol = 1e-7 p.warn('solver %s require p.fTol value (required objective function tolerance); 10^-7 will be used' % self.__name__) xRecord = 0.5 * (lb + ub) adjustr4WithDiscreteVariables(xRecord.reshape(1, -1), p) r40 = np.inf y = lb.reshape(1, -1) e = ub.reshape(1, -1) r41 = np.inf # TODO: maybe rework it, especially for constrained case fStart = self.fStart # TODO: remove it after proper SNLE handling implementation if isSNLE: r41 = 0.0 # asdf1 = None eqs = [fd_abs(elem) for elem in p.user.f] asdf1 = fd_sum(eqs) # TODO: check it, for reducing calculations #C.update([elem == 0 for elem in p.user.f]) elif isMOP: asdf1 = p.user.f Solutions.F = [] if point(p.x0).isFeas(altLinInEq=False): Solutions.solutions.append(p.x0.copy()) Solutions.coords = asarray(Solutions.solutions) Solutions.F.append(p.f(p.x0)) p._solutions = Solutions elif not isODE: asdf1 = p.user.f[0] #if p.fOpt is not None: fOpt = p.fOpt if p.goal in ('max', 'maximum'): asdf1 = -asdf1 if p.fOpt is not None: p.fOpt = -p.fOpt if fStart is not None and fStart < r40: r41 = fStart for X0 in [point(xRecord), point(p.x0)]: if X0.isFeas(altLinInEq=False) and X0.f() < r40: r40 = X0.f() if p.isFeas(p.x0): tmp = asdf1(p._x0) if tmp < r41: r41 = tmp if p.fOpt is not None: if p.fOpt > r41: p.warn('user-provided fOpt seems to be incorrect, ') r41 = p.fOpt # if isSNLE: # if self.dataHandling == 'raw': # p.pWarn(''' # this interalg data handling approach ("%s") # is unimplemented for SNLE yet, dropping to "sorted"'''%self.dataHandling) # # # handles 'auto' as well # self.dataHandling ='sorted' domain = oopoint([(v, [p.lb[i], p.ub[i]]) for i, v in enumerate(vv)], skipArrayCast=True) domain.dictOfFixedFuncs = p.dictOfFixedFuncs #from FuncDesigner.ooFun import BooleanOOFun, SmoothFDConstraint if self.dataHandling == 'auto': if isIP or isODE: self.dataHandling = 'sorted' elif isMOP or p.hasLogicalConstraints: self.dataHandling = 'raw' else: r = p.user.f[0].interval(domain, self.dataType) M = np.max((np.max(np.atleast_1d(np.abs(r.lb))), np.max(np.atleast_1d(np.abs(r.ub))))) for (c, func, lb, ub, tol) in p._FD.nonBoxCons:#[Elem[1] for Elem in p._FD.nonBoxCons]: # !!!!!!!!!!!!!!!!!!!! check it - mb 2nd condition is incorrect #if isinstance(c, BooleanOOFun) and not isinstance(c, SmoothFDConstraint): continue if hasattr(c,'_unnamedBooleanOOFunNumber'): continue r = func.interval(domain, self.dataType) M = np.max((M, np.max(np.atleast_1d(np.abs(r.lb))))) M = np.max((M, np.max(np.atleast_1d(np.abs(r.ub))))) self.dataHandling = 'raw' if M < 1e5 else 'sorted' #self.dataHandling = 'sorted' if isIP or (p.__isNoMoreThanBoxBounded__() and n < 50) else 'raw' # TODO: is it required yet? if not isMOP and not p.hasLogicalConstraints: p._isOnlyBoxBounded = p.__isNoMoreThanBoxBounded__() if isODE or (asdf1.isUncycled and p._isOnlyBoxBounded and np.all(np.isfinite(p.user.f[0].interval(domain).lb))): #maxNodes = 1 self.dataHandling = 'sorted' if self.dataHandling == 'sorted' and p.hasLogicalConstraints: p.warn("interalg: for general logical constraints only dataHandling='raw' mode works") self.dataHandling = 'raw' self.maxActiveNodes = int(self.maxActiveNodes) # if self.maxActiveNodes < 2: # p.warn('maxActiveNodes should be at least 2 while you have provided %d. Setting it to 2.' % self.maxActiveNodes) self.maxNodes = int(self.maxNodes) _in = np.array([], object) g = np.inf C = p._FD.nonBoxConsWithTolShift C0 = p._FD.nonBoxCons # if isOpt: # r = [] # for (elem, lb, ub, tol) in C0: # if tol == 0: tol = p.contol # if lb == ub: # r.append(fd_max((fd_abs(elem-lb)-tol, 0)) * (fTol/tol)) # elif lb == -inf: # r.append(fd_max((0, elem-ub-tol)) * (fTol/tol)) # elif ub == inf: # r.append(fd_max((0, lb-elem-tol)) * (fTol/tol)) # else: # p.err('finite box constraints are unimplemented for interalg yet') #p._cons_obj = 1e100 * fd_sum(r) if len(r) != 0 else None #p._cons_obj = fd_sum(r) if len(r) != 0 else None if isSNLE: C += [(elem==0, elem, -(elem.tol if elem.tol != 0 else p.ftol), (elem.tol if elem.tol != 0 else p.ftol)) for elem in p.user.f] C0 += [(elem==0, elem, 0, 0, (elem.tol if elem.tol != 0 else p.ftol)) for elem in p.user.f] # TODO: hanlde fixed variables here varTols = p.variableTolerances if Solutions.maxNum != 1: if not isSNLE: p.err(''' "search several solutions" mode is unimplemented for the prob type %s yet''' % p.probType) if any(varTols == 0): p.err(''' for the mode "search all solutions" you have to provide all non-zero tolerances for each variable (oovar) ''') pnc = 0 an = [] maxNodes = self.maxNodes # TODO: change for constrained probs _s = atleast_1d(inf) if isODE or (isIP and p.n == 1): interalg_ODE_routine(p, self) return while 1: if len(C0) != 0: y, e, nlhc, residual, definiteRange, indT, _s = processConstraints(C0, y, e, _s, p, dataType) else: nlhc, residual, definiteRange, indT = None, None, True, None if y.size != 0: an, g, fo, _s, Solutions, xRecord, r41, r40 = \ pb(p, nlhc, residual, definiteRange, y, e, vv, asdf1, C, r40, g, \ nNodes, r41, fTol, Solutions, varTols, _in, \ dataType, maxNodes, _s, indT, xRecord) if _s is None: break else: an = _in fo = 0.0 if isSNLE or isMOP else min((r41, r40 - (fTol if Solutions.maxNum == 1 else 0.0))) pnc = max((len(np.atleast_1d(an)), pnc)) if isIP: y, e, _in, _s = \ func12(an, self.maxActiveNodes, p, Solutions, vv, varTols, np.inf) else: y, e, _in, _s = \ func12(an, self.maxActiveNodes, p, Solutions, vv, varTols, fo) nActiveNodes.append(y.shape[0]/2) if y.size == 0: if len(Solutions.coords) > 1: p.istop, p.msg = 1001, 'all solutions have been obtained' else: p.istop, p.msg = 1000, 'solution has been obtained' break ############# End of main cycle ############### if not isSNLE and not isIP and not isMOP: if p._bestPoint.betterThan(p.point(p.xk)): p.iterfcn(p._bestPoint) else: p.iterfcn(p.xk) ff = p.fk # ff may be not assigned yet # ff = p._bestPoint.f() # p.xk = p._bestPoint.x if isIP: p.xk = np.array([np.nan]*p.n) p.rk = p._residual p.fk = p._F isFeas = len(Solutions.F) != 0 if isMOP else p.isFeas(p.xk) if not isIP else p.rk < fTol if not isFeas and p.istop > 0: p.istop, p.msg = -1000, 'no feasible solution has been obtained' o = asarray([t.o for t in an]) if o.size != 0: g = nanmin([nanmin(o), g]) if not isMOP: p.extras['isRequiredPrecisionReached'] = \ True if ff - g < fTol and isFeas else False # and (k is False or (isSNLE and (p._nObtainedSolutions >= maxSolutions or maxSolutions==1))) if not isMOP and not p.extras['isRequiredPrecisionReached'] and p.istop > 0: p.istop = -1 p.msg = 'required precision is not guarantied' # TODO: simplify it if not isMOP: tmp = [nanmin(np.hstack((ff, g, o.flatten()))), np.asscalar(np.array(ff))] if p.goal in ['max', 'maximum']: tmp = (-tmp[1], -tmp[0]) p.extras['extremumBounds'] = tmp if not isIP else 'unimplemented for IP yet' p.solutions = [p._vector2point(s) for s in Solutions.coords] if not isMOP else \ MOPsolutions([p._vector2point(s) for s in Solutions.coords]) if isMOP: for i, s in enumerate(p.solutions): s.useAsMutable = True for j, goal in enumerate(p.user.f): s[goal] = Solutions.F[i][j] s.useAsMutable = False p.solutions.values = np.asarray(Solutions.F) p.solutions.coords = Solutions.coords if not isMOP and p.maxSolutions == 1: delattr(p, 'solutions') if isSNLE and p.maxSolutions != 1: for v in p._categoricalVars: for elem in r.solutions: elem.useAsMutable = True elem[v] = v.aux_domain[elem[v]] elem.useAsMutable = False if p.iprint >= 0 and not isMOP: # s = 'Solution with required tolerance %0.1e \n is%s guarantied (obtained precision: %0.1e)' \ # %(fTol, '' if p.extras['isRequiredPrecisionReached'] else ' NOT', tmp[1]-tmp[0]) s = 'Solution with required tolerance %0.1e \n is%s guarantied' \ %(fTol, '' if p.extras['isRequiredPrecisionReached'] else ' NOT') if not isIP and p.maxSolutions == 1: s += ' (obtained precision: %0.1e)' % np.abs(tmp[1]-tmp[0]) if not p.extras['isRequiredPrecisionReached'] and pnc == self.maxNodes: s += '\nincrease maxNodes (current value %d)' % self.maxNodes p.info(s)
def interalg_ODE_routine(p, solver): isIP = p.probType == 'IP' isODE = p.probType == 'ODE' if isODE: f, y0, t, r30, ftol = p.equations, p.x0, p.timeVariable, p.times, p.ftol assert len( f ) == 1, 'multiple ODE equations are unimplemented for FuncDesigner yet' f = list(f.values())[0] elif isIP: assert p.n == 1 and p.__isNoMoreThanBoxBounded__() f, y0, ftol = p.user.f[0], 0.0, p.ftol if p.fTol is not None: ftol = p.fTol t = list(f._getDep())[0] r30 = p.domain[t] p.iterfcn(p.point([nan] * p.n)) else: p.err('incorrect prob type for interalg ODE routine') eq_var = list(p._x0.keys())[0] dataType = solver.dataType if type(ftol) == int: ftol = float(ftol) # e.g. someone set ftol = 1 # Currently ftol is scalar, in future it can be array of same length as timeArray if len(r30) < 2: p.err('length ot time array must be at least 2') # if any(r30[1:] < r30[:-1]): # p.err('currently interalg can handle only time arrays sorted is ascending order') # if any(r30 < 0): # p.err('currently interalg can handle only time arrays with positive values') # if p.times[0] != 0: # p.err('currently solver interalg requires times start from zero') r37 = abs(r30[-1] - r30[0]) r28 = asarray(atleast_1d(r30[0]), dataType) r29 = asarray(atleast_1d(r30[-1]), dataType) storedr28 = [] r27 = [] r31 = [] r32 = [] r33 = ftol F = 0.0 p._Residual = 0 # Main cycle for itn in range(p.maxIter + 1): if r30[-1] > r30[0]: mp = oopoint({t: [r28, r29]}, skipArrayCast=True) else: mp = oopoint({t: [r29, r28]}, skipArrayCast=True) mp.isMultiPoint = True delta_y = f.interval(mp, dataType) if not all(delta_y.definiteRange): p.err(''' solving ODE with interalg is implemented for definite (real) range only, no NaN values in integrand are allowed''') # TODO: perform check on NaNs r34 = atleast_1d(delta_y.ub) r35 = atleast_1d(delta_y.lb) r36 = atleast_1d(r34 - r35 <= 0.95 * r33 / r37) ind = where(r36)[0] if isODE: storedr28.append(r28[ind]) r27.append(r29[ind]) r31.append(r34[ind]) r32.append(r35[ind]) else: assert isIP F += 0.5 * sum((r29[ind] - r28[ind]) * (r34[ind] + r35[ind])) #p._Residual = p._residual + 0.5*sum((abs(r34) +abs(r35)) * (r29 - r28)) if ind.size != 0: tmp = abs(r29[ind] - r28[ind]) Tmp = sum((r34[ind] - r35[ind]) * tmp) r33 -= Tmp if isIP: p._residual += Tmp r37 -= sum(tmp) ind = where(logical_not(r36))[0] if ind.size == 0: p.istop = 1000 p.msg = 'problem has been solved according to required tolerance' break # OLD # for i in ind: # t0, t1 = r28[i], r29[i] # t_m = 0.5 * (t0+t1) # newr28.append(t0) # newr28.append(t_m) # newr29.append(t_m) # newr29.append(t1) # NEW r38, r39 = r28[ind], r29[ind] r40 = 0.5 * (r38 + r39) r28 = vstack((r38, r40)).flatten() r29 = vstack((r40, r39)).flatten() # !!! unestablished !!! if isODE: p.iterfcn(fk=r33 / ftol) elif isIP: p.iterfcn(xk=array(nan), fk=F, rk=0) else: p.err('bug in interalgODE.py') if p.istop != 0: break #print(itn, r28.size) if isODE: t0, t1, lb, ub = hstack(storedr28), hstack(r27), hstack(r32), hstack( r31) ind = argsort(t0) if r30[0] > r30[-1]: ind = ind[::-1] # reverse t0, t1, lb, ub = t0[ind], t1[ind], lb[ind], ub[ind] lb, ub = y0 + (lb * (t1 - t0)).cumsum(), y0 + (ub * (t1 - t0)).cumsum() #y_var = p._x0.keys()[0] #p.xf = p.xk = 0.5*(lb+ub) p.extras = { 'startTimes': t0, 'endTimes': t1, eq_var: { 'infinums': lb, 'supremums': ub } } return t0, t1, lb, ub elif isIP: P = p.point([nan] * p.n) P._f = F P._mr = r33 P._mrName = 'None' P._mrInd = 0 # p.xk = array([nan]*p.n) # p.rk = r33 # p.fk = F #p._Residual = p.iterfcn(asarray([nan] * p.n), fk=F, rk=0) else: p.err('incorrect prob type in interalg ODE routine')
def getr4Values(vv, y, e, tnlh, func, C, contol, dataType, p, fo = inf): #print where(y), where(e!=1) n = y.shape[1] # TODO: rework it wrt nlh #cs = dict([(key, asarray((val[0]+val[1])/2, dataType)) for key, val in domain.items()]) if tnlh is None:# or p.probType =='MOP': wr4 = (y+e) / 2 adjustr4WithDiscreteVariables(wr4, p) #cs = dict([(oovar, asarray((y[:, i]+e[:, i])/2, dataType)) for i, oovar in enumerate(vv)]) cs = dict([(oovar, asarray(wr4[:, i], dataType)) for i, oovar in enumerate(vv)]) else: tnlh = tnlh.copy() tnlh[atleast_1d(tnlh<1e-300)] = 1e-300 # to prevent division by zero tnlh[atleast_1d(isnan(tnlh))] = inf #- check it! tnlh_l_inv, tnlh_u_inv = 1.0 / tnlh[:, :n], 1.0 / tnlh[:, n:] wr4 = (y * tnlh_l_inv + e * tnlh_u_inv) / (tnlh_l_inv + tnlh_u_inv) ind = tnlh_l_inv == tnlh_u_inv # especially important for tnlh_l_inv == tnlh_u_inv = 0 wr4[ind] = (y[ind] + e[ind]) / 2 adjustr4WithDiscreteVariables(wr4, p) cs = dict([(oovar, asarray(wr4[:, i], dataType)) for i, oovar in enumerate(vv)]) cs = oopoint(cs, skipArrayCast = True) cs.isMultiPoint = True cs.update(p.dictOfFixedFuncs) m = y.shape[0] kw = {'Vars': p.freeVars} if p.freeVars is None or (p.fixedVars is not None and len(p.freeVars) < len(p.fixedVars)) else {'fixedVars': p.fixedVars} kw['fixedVarsScheduleID'] = p._FDVarsID if len(C) != 0: r15 = empty(m, bool) r15.fill(True) for _c, f, r16, r17 in C: c = f(cs, **kw) ind = logical_and(c >= r16, c <= r17) # here r16 and r17 are already shifted by required tolerance r15 = logical_and(r15, ind) else: r15 = True isMOP = p.probType =='MOP' if not any(r15): F = empty(m, dataType) F.fill(2**31-2 if dataType in (int16, int32, int64, int) else nan) if isMOP: FF = [F for k in range(p.nf)] elif all(r15): if isMOP: FF = [fun(cs, **kw) for fun in func] else: F = func(cs, **kw) if func is not None else zeros(m) # func is None for SNLE else: #cs = dict([(oovar, (y[r15, i] + e[r15, i])/2) for i, oovar in enumerate(vv)]) #cs = ooPoint(cs, skipArrayCast = True) #cs.isMultiPoint = True if isMOP: FF = [] for fun in func: tmp = fun(cs, **kw) F = empty(m, dataType) F.fill(2**31-15 if dataType in (int16, int32, int64, int) else nan) F[r15] = tmp[r15] FF.append(F) else: tmp = asarray(func(cs, **kw), dataType) if func is not None else zeros(m) # func is None for SNLE F = empty(m, dataType) F.fill(2**31-15 if dataType in (int16, int32, int64, int) else nan) F[r15] = tmp[r15] if isMOP: return array(FF).T.reshape(m, len(func)).tolist(), wr4.tolist() else: return atleast_1d(F) , wr4
def __init__(self, p): self.rf = asscalar(asarray(p.rf)) self.ff = asscalar(asarray(p.ff)) self.isFDmodel = p.isFDmodel self.probType = p.probType if p.probType == 'EIG': self.eigenvalues, self.eigenvectors = p.eigenvalues, p.eigenvectors if p.isFDmodel: from FuncDesigner import oopoint self.xf = dict((v, asscalar(val) if isinstance(val, ndarray) and val.size ==1 \ else dict((field, v.domain[int(val)][j]) for j, field in enumerate(v.fields)) if v.fields != ()\ else v.reverse_aux_domain[int(val)] if 'reverse_aux_domain' in v.__dict__\ else v.aux_domain[val] if 'aux_domain' in v.__dict__ else val) \ for v, val in p.xf.items()) if not hasattr(self, '_xf'): #self._xf = dict([(v.name, asscalar(val) if isinstance(val, ndarray) and val.size ==1 else val) for v, val in p.xf.items()]) self._xf = dict((v.name, val) for v, val in self.xf.items()) self.xf = oopoint(self.xf, maxDistributionSize=p.maxDistributionSize, skipArrayCast=True) else: self.xf = p.xf # TODO: mb use the fields in MOP if p.probType == 'MOP': for attr in ('xf', 'ff', 'rf', '_xf'): delattr(self, attr) #if len(p.solutions) == 0 and p.isFeas(p.xk): p.solutions = [p.xk] # TODO: mb perform check on each solution for more safety? # although it can slow down calculations for huge solutions number #self.solutions = p.solutions self.elapsed = dict() self.elapsed['solver_time'] = round(100.0 * (time() - p.timeStart)) / 100.0 self.elapsed['solver_cputime'] = round( 100.0 * (clock() - p.cpuTimeStart)) / 100.0 self.elapsed['initialization_time'] = round(100.0 * p.initTime) / 100.0 self.elapsed['initialization_cputime'] = round( 100.0 * p.initCPUTime) / 100.0 for fn in ('ff', 'istop', 'duals', 'isFeasible', 'msg', 'stopcase', 'iterValues', 'special', 'extras', 'solutions'): if hasattr(p, fn): setattr(self, fn, getattr(p, fn)) if hasattr(p.solver, 'innerState'): self.extras['innerState'] = p.solver.innerState self.solverInfo = dict() for fn in ('homepage', 'alg', 'authors', 'license', 'info', 'name'): self.solverInfo[fn] = getattr(p.solver, '__' + fn + '__') # note - it doesn't work for len(args)>1 for current Python ver 2.6 #self.__getitem__ = c # = self.__call__ if p.plot: #for df in p.graphics.drawFuncs: df(p) #TODO: include time spent here to (/cpu)timeElapsedForPlotting self.elapsed['plot_time'] = round( 100 * p.timeElapsedForPlotting[-1]) / 100 # seconds self.elapsed['plot_cputime'] = p.cpuTimeElapsedForPlotting[-1] else: self.elapsed['plot_time'] = 0 self.elapsed['plot_cputime'] = 0 self.elapsed['solver_time'] -= self.elapsed['plot_time'] self.elapsed['solver_cputime'] -= self.elapsed['plot_cputime'] self.evals = dict([ (key, val if type(val) == int else round(val * 10) / 10.0) for key, val in p.nEvals.items() ]) self.evals['iter'] = p.iter
def _prepare(self): if self._baseProblemIsPrepared: return if self.useSparse == 0: self.useSparse = False elif self.useSparse == 1: self.useSparse = True if self.useSparse == 'auto' and not scipyInstalled: self.useSparse = False if self.useSparse == True and not scipyInstalled: self.err("You can't set useSparse=True without scipy installed") if self._isFDmodel(): self.isFDmodel = True self._FD = EmptyClass() self._FD.nonBoxConsWithTolShift = [] self._FD.nonBoxCons = [] from FuncDesigner import _getAllAttachedConstraints, _getDiffVarsID, ooarray, oopoint, oofun#, _Stochastic self._FDVarsID = _getDiffVarsID() probDep = set() updateDep = lambda Dep, elem: \ [updateDep(Dep, f) for f in elem] if isinstance(elem, (tuple, list, set))\ else [updateDep(Dep, f) for f in atleast_1d(elem)] if isinstance(elem, ndarray)\ else Dep.update(set([elem]) if elem.is_oovar else elem._getDep()) if isinstance(elem, oofun) else None if self.probType in ['SLE', 'NLSP', 'SNLE', 'LLSP']: equations = self.C if self.probType in ('SLE', 'LLSP') else self.f F = equations updateDep(probDep, equations) ConstraintTags = [(elem if not isinstance(elem, (set, list, tuple, ndarray)) else elem[0]).isConstraint for elem in equations] cond_all_oofuns_but_not_cons = not any(ConstraintTags) cond_cons = all(ConstraintTags) if not cond_all_oofuns_but_not_cons and not cond_cons: raise OpenOptException('for FuncDesigner SLE/SNLE constructors args must be either all-equalities or all-oofuns') if self.fTol is not None: fTol = min((self.ftol, self.fTol)) self.warn(''' both ftol and fTol are passed to the SNLE; minimal value of the pair will be used (%0.1e); also, you can modify each personal tolerance for equation, e.g. equations = [(sin(x)+cos(y)=-0.5)(tol = 0.001), ...] ''' % fTol) else: fTol = self.ftol self.fTol = self.ftol = fTol appender = lambda arg: [appender(elem) for elem in arg] if isinstance(arg, (ndarray, list, tuple, set))\ else ((arg.oofun*(fTol/arg.tol) if arg.tol != fTol and arg.tol != 0 else arg.oofun) if arg.isConstraint else arg) EQs = [] for eq in equations: rr = appender(eq) if type(rr) == list: EQs += rr else: EQs.append(rr) #EQs = [((elem.oofun*(fTol/elem.tol) if elem.tol != 0 else elem.oofun) if elem.isConstraint else elem) for elem in equations] if self.probType in ('SLE', 'LLSP'): self.C = EQs elif self.probType in ('NLSP', 'SNLE'): self.f = EQs # self.user.F = EQs else: raise OpenOptException('bug in OO kernel') else: F = [self.f] updateDep(probDep, self.f) updateDep(probDep, self.constraints) # TODO: implement it # startPointVars = set(self.x0.keys()) # D = startPointVars.difference(probDep) # if len(D): # print('values for variables %s are missing in start point' % D) # D2 = probDep.difference(startPointVars) # if len(D2): # self.x0 = dict([(key, self.x0[key]) for key in D2]) for fn in ['lb', 'ub', 'A', 'Aeq', 'b', 'beq']: if not hasattr(self, fn): continue val = getattr(self, fn) if val is not None and any(isfinite(val)): self.err('while using oovars providing lb, ub, A, Aeq for whole prob is forbidden, use for each oovar instead') if not isinstance(self.x0, dict): self.err('Unexpected start point type: ooPoint or Python dict expected, '+ str(type(self.x0)) + ' obtained') x0 = self.x0.copy() tmp = [] for key, val in x0.items(): if not isinstance(key, (list, tuple, ndarray)): tmp.append((key, val)) else: # can be only ooarray although val = atleast_1d(val) if len(key) != val.size: self.err(''' for the sake of possible bugs prevention lenght of oovars array must be equal to lenght of its start point value, assignments like x = oovars(m); startPoint[x] = 0 are forbidden, use startPoint[x] = [0]*m or np.zeros(m) instead''') for i in range(val.size): tmp.append((key[i], val[i])) Tmp = dict(tmp) if isinstance(self.fixedVars, dict): for key, val in self.fixedVars.items(): if isinstance(key, (list, tuple, ndarray)): # can be only ooarray although if len(key) != len(val): self.err(''' for the sake of possible bugs prevention lenght of oovars array must be equal to lenght of its start point value, assignments like x = oovars(m); fixedVars[x] = 0 are forbidden, use fixedVars[x] = [0]*m or np.zeros(m) instead''') for i in range(len(val)): Tmp[key[i]] = val[i] else: Tmp[key] = val self.fixedVars = set(self.fixedVars.keys()) # mb other operations will speedup it? if self.probType != 'ODE': Keys = set(Tmp.keys()).difference(probDep) for key in Keys: Tmp.pop(key) self.probDep = probDep self.x0 = Tmp self._stringVars = set() for key, val in self.x0.items(): #if key.domain is not None and key.domain is not bool and key.domain is not 'bool': if type(val) in (str, string_): self._stringVars.add(key) key.formAuxDomain() self.x0[key] = key.aux_domain[val]#searchsorted(key.aux_domain, val, 'left') elif key.fields == () and key.domain is not None and key.domain is not bool and key.domain is not 'bool' \ and key.domain is not int and key.domain is not 'int' and val not in key.domain: self.x0[key] = key.domain[0] self.x0 = oopoint(self.x0) self.x0.maxDistributionSize = self.maxDistributionSize setStartVectorAndTranslators(self) if self.probType in ['LP', 'MILP', 'SOCP'] and self.f.getOrder(self.freeVarsSet, self.fixedVarsSet, fixedVarsScheduleID = self._FDVarsID) > 1: self.err('for LP/MILP objective function has to be linear, while this one ("%s") is not' % self.f.name) if self.fixedVars is None: D_kwargs = {'fixedVars':self.fixedVarsSet} elif self.freeVars is not None and len(self.freeVars)<len(self.fixedVars): D_kwargs = {'Vars':self.freeVarsSet} else: D_kwargs = {'fixedVars':self.fixedVarsSet} D_kwargs['useSparse'] = self.useSparse D_kwargs['fixedVarsScheduleID'] = self._FDVarsID D_kwargs['exactShape'] = True self._D_kwargs = D_kwargs variableTolerancesDict = dict((v, v.tol) for v in self._freeVars) self.variableTolerances = self._point2vector(variableTolerancesDict) if len(self._fixedVars) < len(self._freeVars) and 'isdisjoint' in dir(set()): areFixed = lambda dep: dep.issubset(self.fixedVarsSet) #isFixed = lambda v: v in self._fixedVars Z = dict((v, zeros_like(val) if v not in self.fixedVarsSet else val) for v, val in self._x0.items()) else: areFixed = lambda dep: dep.isdisjoint(self.freeVarsSet) #isFixed = lambda v: v not in self._freeVars Z = dict((v, zeros_like(val) if v in self.freeVarsSet else val) for v, val in self._x0.items()) Z = oopoint(Z, maxDistributionSize = self.maxDistributionSize) self._Z = Z #p.isFixed = isFixed lb, ub = -inf*ones(self.n), inf*ones(self.n) # TODO: get rid of start c, h = None, use [] instead A, b, Aeq, beq = [], [], [], [] if type(self.constraints) not in (list, tuple, set): self.constraints = [self.constraints] oovD = self._oovarsIndDict LB = {} UB = {} """ gather attached constraints """ C = list(self.constraints) self.constraints = set(self.constraints) for v in self._x0.keys(): # if v.fields != (): # v.aux_domain = Copy(v.domain) ## # TODO: mb rework it ## ind_numeric = [j for j, elem in enumerate(v.aux_domain[0]) if type(elem) not in (str, np.str_)] ## if len(ind_numeric): ## ind_first_numeric = ind_numeric[0] ## v.aux_domain.sort(key = lambda elem: elem[ind_first_numeric]) # v.domain = np.arange(len(v.domain)) if not array_equal(v.lb, -inf): self.constraints.add(v >= v.lb) if not array_equal(v.ub, inf): self.constraints.add(v <= v.ub) if self.useAttachedConstraints: if hasattr(self, 'f'): if type(self.f) in [list, tuple, set]: C += list(self.f) else: # self.f is oofun C.append(self.f) self.constraints.update(_getAllAttachedConstraints(C)) FF = self.constraints.copy() for _F in F: if isinstance(_F, (tuple, list, set)): FF.update(_F) elif isinstance(_F, ndarray): if _F.size > 1: FF.update(_F) else: FF.add(_F.item()) else: FF.add(_F) unvectorizableFuncs = set() #unvectorizableVariables = set([var for var, val in self._x0.items() if isinstance(val, _Stochastic) or asarray(val).size > 1]) # TODO: use this unvectorizableVariables = set([]) # temporary replacement: #unvectorizableVariables = set([var for var, val in self._x0.items() if asarray(val).size > 1]) cond = False #debug # unvectorizableVariables = set(self._x0.keys()) # hasVectorizableFuncs = False # cond = True #debug end if 1 and isPyPy: hasVectorizableFuncs = False unvectorizableFuncs = FF else: hasVectorizableFuncs = False if len(unvectorizableVariables) != 0: for ff in FF: _dep = ff._getDep() if cond or len(_dep & unvectorizableVariables) != 0: unvectorizableFuncs.add(ff) else: hasVectorizableFuncs = True else: hasVectorizableFuncs = True self.unvectorizableFuncs = unvectorizableFuncs self.hasVectorizableFuncs = hasVectorizableFuncs for v in self.freeVarsSet: d = v.domain if d is bool or d is 'bool': self.constraints.update([v>0, v<1]) elif d is not None and d is not int and d is not 'int': # TODO: mb add integer domains? v.domain = array(list(d)) v.domain.sort() self.constraints.update([v >= v.domain[0], v <= v.domain[-1]]) if hasattr(v, 'aux_domain'): self.constraints.add(v <= len(v.aux_domain)-1) # for v in self._stringVars: # if isFixed(v): # ind = searchsorted(v.aux_domain, p._x0[v], 'left') # if v.aux_domain """ handling constraints """ StartPointVars = set(self._x0.keys()) self.dictOfFixedFuncs = {} from FuncDesigner import broadcast if self.probType in ['SLE', 'NLSP', 'SNLE', 'LLSP']: for eq in equations: broadcast(formDictOfFixedFuncs, eq, self.useAttachedConstraints, self.dictOfFixedFuncs, areFixed, self._x0) else: broadcast(formDictOfFixedFuncs, self.f, self.useAttachedConstraints, self.dictOfFixedFuncs, areFixed, self._x0) if oosolver(self.solver).useLinePoints: self._firstLinePointDict = {} self._secondLinePointDict = {} self._currLinePointDict = {} inplaceLinearRender = oosolver(self.solver).__name__ == 'interalg' if inplaceLinearRender and hasattr(self, 'f'): D_kwargs2 = D_kwargs.copy() D_kwargs2['useSparse'] = False if type(self.f) in [list, tuple, set]: ff = [] for f in self.f: if f.getOrder(self.freeVarsSet, self.fixedVarsSet, fixedVarsScheduleID = self._FDVarsID) < 2: D = f.D(Z, **D_kwargs2) f2 = linear_render(f, D, Z) ff.append(f2) else: ff.append(f) self.f = ff else: # self.f is oofun if self.f.getOrder(self.freeVarsSet, self.fixedVarsSet, fixedVarsScheduleID = self._FDVarsID) < 2: D = self.f.D(Z, **D_kwargs2) self.f = linear_render(self.f, D, Z) if self.isObjFunValueASingleNumber: self._linear_objective = True self._linear_objective_factor = self._pointDerivative2array(D).flatten() self._linear_objective_scalar = self.f(Z) handleConstraint_args = (StartPointVars, areFixed, oovD, A, b, Aeq, beq, Z, D_kwargs, LB, UB, inplaceLinearRender) for c in self.constraints: if isinstance(c, ooarray): for elem in c: self.handleConstraint(elem, *handleConstraint_args) elif c is True: continue elif c is False: self.err('one of elements from constraints is "False", solution is impossible') elif not hasattr(c, 'isConstraint'): self.err('The type ' + str(type(c)) + ' is inappropriate for problem constraints') else: self.handleConstraint(c, *handleConstraint_args) if len(b) != 0: self.A, self.b = Vstack(A), Hstack([asfarray(elem).flatten() for elem in b])#Vstack(b).flatten() if hasattr(self.b, 'toarray'): self.b = self.b.toarray() if len(beq) != 0: self.Aeq, self.beq = Vstack(Aeq), Hstack([ravel(elem) for elem in beq])#Vstack(beq).flatten() if hasattr(self.beq, 'toarray'): self.beq = self.beq.toarray() for vName, vVal in LB.items(): inds = oovD[vName] lb[inds[0]:inds[1]] = vVal for vName, vVal in UB.items(): inds = oovD[vName] ub[inds[0]:inds[1]] = vVal self.lb, self.ub = lb, ub else: # not FuncDesigner if self.fixedVars is not None or self.freeVars is not None: self.err('fixedVars and freeVars are valid for optimization of FuncDesigner models only') if self.x0 is None: arr = ['lb', 'ub'] if self.probType in ['LP', 'MILP', 'QP', 'SOCP', 'SDP']: arr.append('f') if self.probType in ['LLSP', 'LLAVP', 'LUNP']: arr.append('D') for fn in arr: if not hasattr(self, fn): continue tmp = getattr(self, fn) fv = asarray(tmp) if not isspmatrix(tmp) else tmp.A if any(isfinite(fv)): self.x0 = np.zeros(fv.size) break self.x0 = ravel(self.x0) if not hasattr(self, 'n'): self.n = self.x0.size if not hasattr(self, 'lb'): self.lb = -inf * ones(self.n) if not hasattr(self, 'ub'): self.ub = inf * ones(self.n) for fn in ('A', 'Aeq'): fv = getattr(self, fn) if fv is not None: #afv = asfarray(fv) if not isspmatrix(fv) else fv.toarray() # TODO: omit casting to dense matrix afv = asfarray(fv) if type(fv) in [list, tuple] else fv if len(afv.shape) > 1: if afv.shape[1] != self.n: self.err('incorrect ' + fn + ' size') else: if afv.shape != () and afv.shape[0] == self.n: afv = afv.reshape(1, self.n) setattr(self, fn, afv) else: setattr(self, fn, asfarray([]).reshape(0, self.n)) nA, nAeq = prod(self.A.shape), prod(self.Aeq.shape) SizeThreshold = 2 ** 15 if scipyInstalled: from scipy.sparse import csc_matrix if isspmatrix(self.A) or (nA > SizeThreshold and np.flatnonzero(self.A).size < 0.25*nA): self._A = csc_matrix(self.A) if isspmatrix(self.Aeq) or (nAeq > SizeThreshold and np.flatnonzero(self.Aeq).size < 0.25*nAeq): self._Aeq = csc_matrix(self.Aeq) elif nA > SizeThreshold or nAeq > SizeThreshold: self.pWarn(scipyAbsentMsg) self._baseProblemIsPrepared = True
def interalg_ODE_routine(p, solver): isIP = p.probType == 'IP' isODE = p.probType == 'ODE' if isODE: f, y0, r30, ftol = p.equations, p.x0, p.times, p.ftol assert len(f) == 1, 'multiple ODE equations are unimplemented for FuncDesigner yet' f = list(f.values())[0] t = list(f._getDep())[0] elif isIP: assert p.n == 1 and p.__isNoMoreThanBoxBounded__() f, y0, ftol = p.user.f[0], 0.0, p.ftol if p.fTol is not None: ftol = p.fTol t = list(f._getDep())[0] r30 = p.domain[t] p.iterfcn(p.point([nan]*p.n)) else: p.err('incorrect prob type for interalg ODE routine') eq_var = list(p._x0.keys())[0] dataType = solver.dataType if type(ftol) == int: ftol = float(ftol) # e.g. someone set ftol = 1 # Currently ftol is scalar, in future it can be array of same length as timeArray if len(r30) < 2: p.err('length ot time array must be at least 2') # if any(r30[1:] < r30[:-1]): # p.err('currently interalg can handle only time arrays sorted is ascending order') # if any(r30 < 0): # p.err('currently interalg can handle only time arrays with positive values') # if p.times[0] != 0: # p.err('currently solver interalg requires times start from zero') r37 = abs(r30[-1] - r30[0]) # if len(r30) == 2: # r30 = np.linspace(r30[0], r30[-1], 150) r28 = asarray(atleast_1d(r30[:-1]), dataType) r29 = asarray(atleast_1d(r30[1:]), dataType) r20_store = array([], float) r38_store = array([], float) r39_store = array([], float) maxActiveNodes = 150000#solver.maxActiveNodes storedr28 = [] r27 = [] r31 = [] r32 = [] r33 = ftol F = 0.0 p._Residual = 0 # Main cycle for itn in range(p.maxIter+1): p.extras['nNodes'].append(r28.size) p.extras['nActiveNodes'].append(r28.size) mp = oopoint( {t: [r28, r29] if r30[-1] > r30[0] else [r29, r28]}, skipArrayCast = True ) mp.isMultiPoint = True mp.dictOfFixedFuncs = p.dictOfFixedFuncs mp.surf_preference = True tmp = f.interval(mp, ia_surf_level = 2 if isIP else 1) if not all(tmp.definiteRange): p.err(''' solving ODE and IP by interalg is implemented for definite (real) range only, no NaN values in integrand are allowed''') # TODO: perform check on NaNs isBoundsurf = hasattr(tmp, 'resolve') if isBoundsurf: if isIP: if tmp.level == 1: #adjustr4WithDiscreteVariables(wr4, p) cs = oopoint([(v, asarray(0.5*(val[0] + val[1]), dataType)) for v, val in mp.items()]) cs.dictOfFixedFuncs = p.dictOfFixedFuncs r21, r22 = tmp.values(cs) o, a = atleast_1d(r21), atleast_1d(r22) r20 = a-o approx_value = 0.5*(a+o) else: assert tmp.level == 2 ts, te = r28, r29 A, B = (te**2 + te*ts+ts**2) / 3.0, 0.5 * (te + ts) a, b, c = tmp.l.d2.get(t, 0.0), tmp.l.d.get(t, 0.0), tmp.l.c val_l = a * A + b * B + c a, b, c = tmp.u.d2.get(t, 0.0), tmp.u.d.get(t, 0.0), tmp.u.c val_u = a * A + b * B + c r20 = val_u - val_l approx_value = 0.5 * (val_l + val_u) # import pylab, numpy # xx = numpy.linspace(-1, 0, 1000) # pylab.plot(xx, tmp.l.d2.get(t, 0.0)[1]*xx**2+ tmp.l.d.get(t, 0.0)[1]*xx+ tmp.l.c[1], 'r') # pylab.plot(xx, tmp.u.d2.get(t, 0.0)[1]*xx**2+ tmp.u.d.get(t, 0.0)[1]*xx+ tmp.u.c[1], 'b') # pylab.grid() # pylab.show() elif isODE: l, u = tmp.l, tmp.u assert len(l.d) <= 1 and len(u.d) <= 1 # at most time variable l_koeffs, u_koeffs = l.d.get(t, 0.0), u.d.get(t, 0.0) l_c, u_c = l.c, u.c # dT = r29 - r28 if r30[-1] > r30[0] else r28 - r29 ends = oopoint([(v, asarray(val[1], dataType)) for v, val in mp.items()]) ends.dictOfFixedFuncs = p.dictOfFixedFuncs ends_L, ends_U = tmp.values(ends) starts = oopoint([(v, asarray(val[0], dataType)) for v, val in mp.items()]) starts.dictOfFixedFuncs = p.dictOfFixedFuncs starts_L, starts_U = tmp.values(starts) # o, a = atleast_1d(r21), atleast_1d(r22) o, a = tmp.resolve()[0] # r20 = 0.5 * u_koeffs * dT + u_c - (0.5 * l_koeffs * dT + l_c) r20_end = 0.5 * (ends_U - ends_L) r20_start = 0.5 * (starts_U - starts_L) r20 = where(r20_end>r20_start, r20_end, r20_start) # r20 = 0.5 * u_koeffs * dT ** 2 + u_c * dT - (0.5 * l_koeffs * dT ** 2 + l_c * dT) # r20 = 0.5*u_koeffs * dT + u_c - ( 0.5*l_koeffs * dT + l_c) # o = 0.5*l_koeffs * dT + l_c # a = 0.5*u_koeffs * dT + u_c #assert 0, 'unimplemented' else: assert 0 else: o, a = atleast_1d(tmp.lb), atleast_1d(tmp.ub) ends_L = starts_L = o ends_U = starts_U = a r20 = a - o approx_value = 0.5 * (a+o) if isODE: r36 = atleast_1d(r20 <= 0.95 * r33) r36 = np.logical_and(r36, r20 < ftol) r36 = np.logical_and(r36, a-o < ftol) # else: # r36 = atleast_1d(r20 <= 0.95 * r33 / r37) if isODE and isBoundsurf: d = r37 #if not isODE or not isBoundsurf else len(r28) r36 = np.logical_and( atleast_1d(r20_end <= 0.95 * r33 / d), atleast_1d(r20_start <= 0.95 * r33 / d) ) r36 &= atleast_1d(r20_end <= ftol) r36 &= atleast_1d(r20_start <= ftol) else: r36 = atleast_1d(r20 <= 0.95 * r33 / r37) # r36 = np.logical_and(r36, r20 < ftol) # r36 = np.logical_and(r36, a-o < ftol) ind = where(r36)[0] if isODE: storedr28.append(r28[ind]) r27.append(r29[ind]) r31.append(a[ind]) r32.append(o[ind]) # r31.append(ends_U[ind]) # r32.append(ends_L[ind]) else: assert isIP #F += 0.5 * sum((r29[ind]-r28[ind])*(a[ind]+o[ind])) F += sum((r29[ind]-r28[ind])*approx_value[ind]) if ind.size != 0: tmp = abs(r29[ind] - r28[ind]) Tmp = sum(r20[ind] * tmp) #if not isODE or not isBoundsurf else sum(r20[ind]) r33 -= Tmp if isIP: p._residual += Tmp r37 -= sum(tmp) ind = where(logical_not(r36))[0] if 1:#new if ind.size == 0 and r20_store.size == 0: p.istop = 1000 p.msg = 'problem has been solved according to required user-defined accuracy %0.1g' % ftol break if ind.size != 0: # TODO: use merge sorted lists if r20_store.size != 0: r20_store = hstack((r20_store, r20[ind]*abs(r29[ind] - r28[ind]))) r38_store = hstack((r38_store, r28[ind])) r39_store = hstack((r39_store, r29[ind])) else: r20_store = r20[ind]*abs(r29[ind] - r28[ind]) r38_store, r39_store = r28[ind], r29[ind] ind_a = argsort(r20_store) r20_store = r20_store[ind_a] r38_store = r38_store[ind_a] r39_store = r39_store[ind_a] r38_store, r38 = r38_store[:-maxActiveNodes], r38_store[-maxActiveNodes:] r39_store, r39 = r39_store[:-maxActiveNodes], r39_store[-maxActiveNodes:] r20_store = r20_store[:-maxActiveNodes] r40 = 0.5 * (r38 + r39) r28 = vstack((r38, r40)).flatten() r29 = vstack((r40, r39)).flatten() else: if ind.size == 0: p.istop = 1000 p.msg = 'problem has been solved according to required user-defined accuracy %0.1g' % ftol break r38, r39 = r28[ind], r29[ind] r40 = 0.5 * (r38 + r39) r28 = vstack((r38, r40)).flatten() r29 = vstack((r40, r39)).flatten() # !!! unestablished !!! if isODE: p.iterfcn(fk = r33/ftol) elif isIP: p.iterfcn(xk=array(nan), fk=F, rk = ftol - r33) else: p.err('bug in interalgODE.py') if p.istop != 0 : break #print(itn, r28.size) if isODE: t0, t1, lb, ub = hstack(storedr28), hstack(r27), hstack(r32), hstack(r31) ind = argsort(t0) if r30[0] > r30[-1]: ind = ind[::-1] # reverse t0, t1, lb, ub = t0[ind], t1[ind], lb[ind], ub[ind] lb, ub = hstack((y0, y0+(lb*(t1-t0)).cumsum())), hstack((y0, y0+(ub*(t1-t0)).cumsum())) #y_var = p._x0.keys()[0] #p.xf = p.xk = 0.5*(lb+ub) p.extras = {'startTimes': t0, 'endTimes': t1, eq_var:{'infinums': lb, 'supremums': ub}} return t0, t1, lb, ub elif isIP: P = p.point([nan]*p.n) P._f = F P._mr = ftol - r33 P._mrName = 'None' P._mrInd = 0 # p.xk = array([nan]*p.n) # p.rk = r33 # p.fk = F #p._Residual = p.iterfcn(asarray([nan]*p.n), fk=F, rk = ftol - r33) else: p.err('incorrect prob type in interalg ODE routine')