Пример #1
0
    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
Пример #2
0
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
Пример #3
0
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
Пример #4
0
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)
Пример #5
0
    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
Пример #6
0
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
Пример #7
0
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
Пример #8
0
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)
Пример #9
0
    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
Пример #10
0
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')
Пример #11
0
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')
Пример #12
0
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
Пример #13
0
    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)
Пример #14
0
    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)
Пример #15
0
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')
Пример #16
0
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
Пример #17
0
    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
Пример #18
0
    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
Пример #19
0
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')