Пример #1
0
    def _Prepare(self):
        if self._isPrepared: return
        self._isPrepared = True
        if isinstance(self.d, dict): # FuncDesigner startPoint 
            self.x0 = self.d
        MatrixProblem._Prepare(self)
        if self.isFDmodel:
            equations = self.C
            AsSparse = bool(self.useSparse) if type(self.useSparse) != str else self._useSparse()
            C, d = [], []
            if len(self._fixedVars) < len(self._freeVars):
                Z = dict([(v, zeros_like(self._x0[v]) if v not in self._fixedVars else self._x0[v]) for v in self._x0.keys()])
            else:
                Z = dict([(v, zeros_like(self._x0[v]) if v in self._freeVars else self._x0[v]) for v in self._x0.keys()])
            #Z = self.x0#self._vector2point(zeros(self.n))

            for lin_oofun in equations:
                if lin_oofun.getOrder(self.freeVars, self.fixedVars) > 1:
                    raise OpenOptException('SLE constructor requires all equations to be linear')
                C.append(self._pointDerivative2array(lin_oofun.D(Z, **self._D_kwargs), useSparse = AsSparse))
                d.append(-lin_oofun(Z))
                
            self.d = hstack(d).flatten()
            self.C  = Vstack(C)
            
            if hasattr(self.C, 'tocsc'): self.C_as_csc = self.C.tocsc()
            if isinstance(self.C,ndarray) and self.n > 100 and len(flatnonzero(self.C))/self.C.size < 0.3:
                s = "Probably you'd better solve this SLE as sparse"
                if not scipyInstalled: s += ' (requires scipy installed)'
                self.pWarn(s)


        self.x0 = zeros(self.C.shape[1])
Пример #2
0
    def _Prepare(self):
        if self._isPrepared: return
        self._isPrepared = True
        if isinstance(self.d, dict): # FuncDesigner startPoint 
            self.x0 = self.d
        MatrixProblem._Prepare(self)
        if self.isFDmodel:
            equations = self.C
            AsSparse = bool(self.useSparse) if type(self.useSparse) != str else self._useSparse()
            C, d = [], []
            if len(self._fixedVars) < len(self._freeVars):
                Z = dict([(v, zeros_like(self._x0[v]) if v not in self._fixedVars else self._x0[v]) for v in self._x0.keys()])
            else:
                Z = dict([(v, zeros_like(self._x0[v]) if v in self._freeVars else self._x0[v]) for v in self._x0.keys()])
            #Z = self.x0#self._vector2point(zeros(self.n))

            for lin_oofun in equations:
                if lin_oofun.getOrder(self.freeVars, self.fixedVars) > 1:
                    raise OpenOptException('SLE constructor requires all equations to be linear')
                C.append(self._pointDerivative2array(lin_oofun.D(Z, **self._D_kwargs), useSparse = AsSparse))
                d.append(-lin_oofun(Z))
                
            self.d = hstack(d).flatten()
            self.C  = Vstack(C)
            
            if hasattr(self.C, 'tocsc'): self.C_as_csc = self.C.tocsc()
            if isinstance(self.C,ndarray) and self.n > 100 and len(flatnonzero(self.C))/self.C.size < 0.3:
                s = "Probably you'd better solve this SLE as sparse"
                if not scipyInstalled: s += ' (requires scipy installed)'
                self.pWarn(s)


        self.x0 = zeros(self.C.shape[1])
Пример #3
0
 def getPattern(oofuns):
     # oofuns is Python list of oofuns
     assert isinstance(oofuns, list), 'oofuns should be Python list, inform developers of the bug'
     R = []
     for oof in oofuns:
         SIZE = asarray(oof(startPoint)).size
         r = []
         dep = oof._getDep()
         if len(p._fixedVars) != 0:
             dep = dep & p._freeVars if len(p._freeVars) < len(p._fixedVars) else dep.difference(p._fixedVars)
         
         # NEW
         ind_Z = 0
         vars = list(dep)
         vars.sort(key=lambda elem: elem._id)
         for oov in vars:
             ind_start, ind_end = oovarsIndDict[oov]
             if ind_start != ind_Z:
                 r.append(SparseMatrixConstructor((SIZE, ind_start - ind_Z)))
             r.append(ones((SIZE, ind_end - ind_start)))
             ind_Z = ind_end
         if ind_Z != n:
             # assert ind_Z < n
             r.append(SparseMatrixConstructor((SIZE, n - ind_Z)))
         if any([isspmatrix(elem) for elem in r]):
             rr = Hstack(r) if len(r) > 1 else r[0]
         elif len(r)>1:
             rr = hstack(r)
         else:
             rr = r[0]
         R.append(rr)
     result = Vstack(R) if any([isspmatrix(_r) for _r in R]) else vstack(R)
     
     return result
Пример #4
0
    def linearOOFunsToMatrices(oofuns): #, useSparse = 'auto'
        # oofuns should be linear
        C, d = [], []
        Z = p._vector2point(zeros(p.n))
        for elem in oofuns:
            if elem.isConstraint:
                lin_oofun = elem.oofun
            else:
                lin_oofun = elem
            if lin_oofun.getOrder(p.freeVars, p.fixedVars) > 1:
                from oologfcn import OpenOptException
                raise OpenOptException("this function hasn't been intended to work with nonlinear FuncDesigner oofuns")
            C.append(p._pointDerivative2array(lin_oofun.D(Z, **p._D_kwargs), useSparse = p.useSparse))
            d.append(-lin_oofun(Z))

        C, d = Vstack(C), hstack(d).flatten()

        return C, d    
Пример #5
0
def LinConst2WholeRepr(p):
    """
    transforms  (A, x) <= b, (Aeq, x) = beq into Awhole, bwhole, dwhole constraints (see help(LP))
    this func is developed for those solvers that can handle linear (in)equality constraints only via Awhole
    """
    if p.A == None and p.Aeq == None:
        return

    # new
    p.Awhole = Vstack(
        [elem for elem in [p.Awhole, p.A, p.Aeq] if elem is not None])

    #old
    #    Awhole = Copy(p.Awhole) # maybe it's already present and not equal to None
    #    p.Awhole = zeros([Len(p.b) + Len(p.beq) + Len(p.bwhole), p.n])
    #    if Awhole.size>0: p.Awhole[:Len(p.bwhole)] = Awhole
    #    p.Awhole[Len(p.bwhole):Len(p.bwhole)+Len(p.b)] = p.A
    #    if p.Aeq.size: p.Awhole[Len(p.bwhole)+Len(p.b):] = p.Aeq

    p.A, p.Aeq = None, None

    bwhole = Copy(p.bwhole)
    p.bwhole = zeros(Len(p.b) + Len(p.beq) + Len(p.bwhole))
    p.bwhole[:Len(bwhole)] = bwhole

    p.bwhole[Len(bwhole):Len(bwhole) + Len(p.b)] = p.b

    p.bwhole[Len(bwhole) + Len(p.b):] = p.beq

    dwhole = Copy(p.dwhole)
    p.dwhole = zeros(Len(p.bwhole))
    if dwhole.size: p.dwhole[:Len(bwhole)] = dwhole
    p.dwhole[Len(bwhole):Len(bwhole) + Len(p.b)] = -1
    p.dwhole[Len(bwhole) + Len(p.b):] = 0

    p.b = None
    p.beq = None
Пример #6
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
Пример #7
0
class SLE(MatrixProblem):
    expectedArgs = ['C', 'd']# for FD it should be Cd and x0
    probType = 'SLE'
    goal = 'solution'
    allowedGoals = ['solution']
    showGoal = False
    FuncDesignerSign = 'C'
    solver = 'defaultSLEsolver'
    _optionalData = []
    _isPrepared = False
    
    def __init__(self, *args, **kwargs):
        MatrixProblem.__init__(self, *args, **kwargs)
    
    _useSparse = lambda self: True if (scipyInstalled and self.n > 100) else False

    def objFunc(self, x):
        if isinstance(self.C, ndarray):
            return norm(dot(self.C, x) - self.d, inf)
        else:
            # TODO: omit code clone in FD ooFun.py, function _D
            t1 = self.C_as_csc
            t2 = scipy.sparse.csr_matrix(x)
            if t2.shape[0] != t1.shape[1]:
                if t2.shape[1] == t1.shape[1]:
                    t2 = t2.T
                else:
                    raise FuncDesignerException('incorrect shape in FuncDesigner function _D(), inform developers about the bug')
            rr =  t1._mul_sparse_matrix(t2)            
            return norm(rr.toarray().flatten() - self.d, inf)

    def _Prepare(self):
        if self._isPrepared: return
        self._isPrepared = True
        if isinstance(self.d, dict): # FuncDesigner startPoint 
            self.x0 = self.d
        MatrixProblem._Prepare(self)
        if self.isFDmodel:
            equations = self.C
            AsSparse = bool(self.useSparse) if type(self.useSparse) != str else self._useSparse()
            C, d = [], []
            if len(self._fixedVars) < len(self._freeVars):
                Z = dict([(v, zeros_like(self._x0[v]) if v not in self._fixedVars else self._x0[v]) for v in self._x0.keys()])
            else:
                Z = dict([(v, zeros_like(self._x0[v]) if v in self._freeVars else self._x0[v]) for v in self._x0.keys()])
            #Z = self.x0#self._vector2point(zeros(self.n))

            for lin_oofun in equations:
                if lin_oofun.getOrder(self.freeVars, self.fixedVars) > 1:
                    raise OpenOptException('SLE constructor requires all equations to be linear')
                C.append(self._pointDerivative2array(lin_oofun.D(Z, **self._D_kwargs), useSparse = AsSparse))
                d.append(-lin_oofun(Z))
                
            self.d = hstack(d).flatten()
            self.C  = Vstack(C)
            
            if hasattr(self.C, 'tocsc'): self.C_as_csc = self.C.tocsc()
            if isinstance(self.C,ndarray) and self.n > 100 and len(flatnonzero(self.C))/self.C.size < 0.3:
                s = "Probably you'd better solve this SLE as sparse"
                if not scipyInstalled: s += ' (requires scipy installed)'
                self.pWarn(s)


        self.x0 = zeros(self.C.shape[1])
Пример #8
0
class SLE(MatrixProblem):
    expectedArgs = ['C', 'd']# for FD it should be Cd and x0
    probType = 'SLE'
    goal = 'solution'
    allowedGoals = ['solution']
    showGoal = False
    FuncDesignerSign = 'C'
    solver = 'defaultSLEsolver'
    _optionalData = []
    _isPrepared = False
    
    def __init__(self, *args, **kwargs):
        MatrixProblem.__init__(self, *args, **kwargs)
    
    _useSparse = lambda self: True if (scipyInstalled and self.n > 100) else False

    def objFunc(self, x):
        if isinstance(self.C, ndarray):
            return norm(dot(self.C, x) - self.d, inf)
        else:
            # TODO: omit code clone in FD ooFun.py, function _D
            t1 = self.C_as_csc
            t2 = csr_matrix(x)
            if t2.shape[0] != t1.shape[1]:
                assert t2.shape[1] == t1.shape[1], 'incorrect shape in OpenOpt SLE, inform developers about the bug'
                t2 = t2.T
            rr =  t1._mul_sparse_matrix(t2)            
            return norm(rr.toarray().flatten() - self.d, inf)

    def _Prepare(self):
        if self._isPrepared: return
        self._isPrepared = True
        if isinstance(self.d, dict): # FuncDesigner startPoint 
            self.x0 = self.d
        MatrixProblem._Prepare(self)
        if self.isFDmodel:
            equations = self.C
            AsSparse = bool(self.useSparse) if type(self.useSparse) != str else self._useSparse()
            C, d = [], []
            if len(self._fixedVars) < len(self._freeVars):
                Z = dict([(v, zeros_like(self._x0[v]) if v not in self._fixedVars else self._x0[v]) for v in self._x0.keys()])
            else:
                Z = dict([(v, zeros_like(self._x0[v]) if v in self._freeVars else self._x0[v]) for v in self._x0.keys()])
            #Z = self.x0#self._vector2point(zeros(self.n))

            for lin_oofun in equations:
                if lin_oofun.getOrder(self.freeVars, self.fixedVars) > 1:
                    raise OpenOptException('SLE constructor requires all equations to be linear')
                C.append(self._pointDerivative2array(lin_oofun.D(Z, **self._D_kwargs), useSparse = AsSparse))
                d.append(-lin_oofun(Z))
                
            self.d = hstack(d).flatten()
            self.C  = Vstack(C)
            
            if hasattr(self.C, 'tocsc'): self.C_as_csc = self.C.tocsc()
            if isinstance(self.C,ndarray) and self.n > 100 and len(flatnonzero(self.C))/self.C.size < 0.3:
                s = "Probably you'd better solve this SLE as sparse"
                if not scipyInstalled: s += ' (requires scipy installed)'
                self.pWarn(s)


        self.x0 = zeros(self.C.shape[1])
Пример #9
0
    def wrapped_1st_derivatives(p, x, ind_, funcType, ignorePrev, useSparse):
        if isinstance(x, dict):
            if not p.isFDmodel:
                p.err(
                    'calling the function with argument of type dict is allowed for FuncDesigner models only'
                )
            if ind_ is not None:
                p.err(
                    'the operation is turned off for argument of type dict when ind!=None'
                )
            x = p._point2vector(x)
        if ind_ is not None:
            ind = p.getCorrectInd(ind_)
        else:
            ind = None

        if p.istop == USER_DEMAND_EXIT:
            if p.solver.useStopByException:
                raise killThread
            else:
                return nan
        derivativesType = 'd' + funcType
        prevKey = p.prevVal[derivativesType]['key']
        if prevKey is not None and p.iter > 0 and array_equal(
                x, prevKey) and ind is None and not ignorePrev:
            #TODO: add counter of the situations
            assert p.prevVal[derivativesType]['val'] is not None
            return copy(p.prevVal[derivativesType]['val'])

        if ind is None and not ignorePrev:
            p.prevVal[derivativesType]['ind'] = copy(x)

        #TODO: patterns!
        nFuncs = getattr(p, 'n' + funcType)
        x = atleast_1d(x)
        if hasattr(p.userProvided, derivativesType) and getattr(
                p.userProvided, derivativesType):

            funcs = getattr(p.user, derivativesType)

            if ind is None or (nFuncs == 1
                               and p.functype[funcType] == 'single func'):
                Funcs = funcs
            elif ind is not None and p.functype[
                    funcType] == 'some funcs R^nvars -> R':
                Funcs = [funcs[i] for i in ind]
            else:
                Funcs = getFuncsAndExtractIndexes(p, funcs, ind, funcType)

#            if ind is None: derivativesNumber = nFuncs
#            else: derivativesNumber = len(ind)

#derivatives = empty((derivativesNumber, p.n))
            derivatives = []
            #agregate_counter = 0
            for fun in Funcs:  #getattr(p.user, derivativesType):
                tmp = atleast_1d(fun(*(x, ) + getattr(p.args, funcType)))
                # TODO: replace tmp.size here for sparse matrices
                #assert tmp.size % p.n == mod(tmp.size, p.n)
                if tmp.size % p.n != 0:
                    if funcType == 'f':
                        p.err(
                            'incorrect user-supplied (sub)gradient size of objective function'
                        )
                    elif funcType == 'c':
                        p.err(
                            'incorrect user-supplied (sub)gradient size of non-lin inequality constraints'
                        )
                    elif funcType == 'h':
                        p.err(
                            'incorrect user-supplied (sub)gradient size of non-lin equality constraints'
                        )

                if tmp.ndim == 1: m = 1
                else: m = tmp.shape[0]
                if p.functype[funcType] == 'some funcs R^nvars -> R' and m != 1:
                    # TODO: more exact check according to stored p.arr_of_indexes_* arrays
                    p.err(
                        'incorrect shape of user-supplied derivative, it should be in accordance with user-provided func size'
                    )
                derivatives.append(tmp)
                #derivatives[agregate_counter : agregate_counter + m] =  tmp#.reshape(tmp.size/p.n,p.n)
                #agregate_counter += m
            #TODO: inline ind modification!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

            derivatives = Vstack(derivatives) if any(
                isspmatrix(derivatives)) else vstack(derivatives)
            if ind is None:
                p.nEvals[derivativesType] += 1
            else:
                #derivatives = derivatives[ind]
                p.nEvals[derivativesType] = p.nEvals[derivativesType] + float(
                    len(ind)) / nFuncs

            if funcType == 'f':
                if p.invertObjFunc: derivatives = -derivatives
                if p.isObjFunValueASingleNumber:
                    if not isinstance(derivatives, ndarray):
                        derivatives = derivatives.toarray()
                    derivatives = derivatives.flatten()

        else:
            #if not getattr(p.userProvided, derivativesType) or p.isFDmodel:
            #                                            x, IND, userFunctionType, ignorePrev, getDerivative
            derivatives = p.wrapped_func(x, ind, funcType, True, True)

            if ind is None:
                p.nEvals[derivativesType] -= 1
            else:
                p.nEvals[derivativesType] = p.nEvals[derivativesType] - float(
                    len(ind)) / nFuncs
        #else:

        if useSparse is False or not scipyInstalled or not hasattr(
                p, 'solver') or not p.solver._canHandleScipySparse:
            # p can has no attr 'solver' if it is called from checkdf, checkdc, checkdh
            if not isinstance(derivatives, ndarray):
                derivatives = derivatives.toarray()


#        if min(derivatives.shape) == 1:
#            if isspmatrix(derivatives): derivatives = derivatives.A
#            derivatives = derivatives.flatten()
        if type(derivatives) != ndarray and isinstance(
                derivatives, ndarray):  # dense numpy matrix
            derivatives = derivatives.A

        if ind is None and not ignorePrev:
            p.prevVal[derivativesType]['val'] = derivatives

        if funcType == 'f':
            if hasattr(
                    p, 'solver'
            ) and not p.solver.iterfcnConnected and p.solver.funcForIterFcnConnection == 'df':
                if p.df_iter is True: p.iterfcn(x)
                elif p.nEvals[derivativesType] % p.df_iter == 0:
                    p.iterfcn(x)  # call iterfcn each {p.df_iter}-th df call
            if p.isObjFunValueASingleNumber and type(
                    derivatives) == ndarray and derivatives.ndim > 1:
                derivatives = derivatives.flatten()

        return derivatives
Пример #10
0
    def wrapped_func(p, x, IND, userFunctionType, ignorePrev,
                     getDerivative):  #, _linePointDescriptor = None):
        if isinstance(x, dict):
            if not p.isFDmodel:
                p.err(
                    'calling the function with argument of type dict is allowed for FuncDesigner models only'
                )
            x = p._point2vector(x)
        if not getattr(p.userProvided, userFunctionType): return array([])
        if p.istop == USER_DEMAND_EXIT:
            if p.solver.useStopByException:
                raise killThread
            else:
                return nan

        if getDerivative and not p.isFDmodel and not DerApproximatorIsInstalled:
            p.err(
                'For the problem you should have DerApproximator installed, see http://openopt.org/DerApproximator'
            )

        #userFunctionType should be 'f', 'c', 'h'
        funcs = getattr(p.user, userFunctionType)
        #funcs_num = getattr(p, 'n'+userFunctionType)
        if IND is not None:
            ind = p.getCorrectInd(IND)
        else:
            ind = None

        # this line had been added because some solvers pass tuple instead of
        # x being vector p.n x 1 or matrix X=[x1 x2 x3...xk], size(X)=[p.n, k]
        if not isspmatrix(x):
            x = atleast_1d(x)
#            if not str(x.dtype).startswith('float'):
#                x = asfarray(x)
        else:
            if p.debug:
                p.pWarn(
                    '[oo debug] sparse matrix x in nonlinfuncs.py has been encountered'
                )

#        if not ignorePrev:
#            prevKey = p.prevVal[userFunctionType]['key']
#        else:
#            prevKey = None
#
#        # TODO: move it into runprobsolver or baseproblem
#        if p.prevVal[userFunctionType]['val'] is None:
#            p.prevVal[userFunctionType]['val'] = zeros(getattr(p, 'n'+userFunctionType))
#
#        if prevKey is not None and p.iter > 0 and array_equal(x,  prevKey) and ind is None and not ignorePrev:
#            #TODO: add counter of the situations
#            if not getDerivative:
#                r = copy(p.prevVal[userFunctionType]['val'])
#                #if p.debug: assert array_equal(r,  p.wrapped_func(x, IND, userFunctionType, True, getDerivative))
#                if ind is not None: r = r[ind]
#
#                if userFunctionType == 'f':
#                    if p.isObjFunValueASingleNumber: r = r.sum(0)
#                    if p.invertObjFunc: r = -r
#                    if  p.solver.funcForIterFcnConnection=='f' and any(isnan(x)):
#                        p.nEvals['f'] += 1
#
#                        if p.nEvals['f']%p.f_iter == 0:
#                            p.iterfcn(x, fk = r)
#                return r

        args = getattr(p.args, userFunctionType)

        # TODO: handle it in prob prepare
        if not hasattr(p, 'n' + userFunctionType):
            setNonLinFuncsNumber(p, userFunctionType)

        #        if ind is None:
        #            nFuncsToObtain = getattr(p, 'n'+ userFunctionType)
        #        else:
        #            nFuncsToObtain = len(ind)

        if x.shape[0] != p.n and (x.ndim < 2 or x.shape[1] != p.n):
            p.err('x with incorrect shape passed to non-linear function')

        #TODO: code cleanup (below)
        if getDerivative or x.ndim <= 1 or x.shape[0] == 1:
            nXvectors = 1
            x_0 = copy(x)
        else:
            nXvectors = x.shape[0]

        # TODO: use certificate instead
        if p.isFDmodel:
            if getDerivative:
                if p.freeVars is None or (p.fixedVars is not None and
                                          len(p.freeVars) < len(p.fixedVars)):
                    funcs2 = [(lambda x, i=i: \
                      p._pointDerivative2array(
                                               funcs[i].D(x, Vars = p.freeVars, useSparse=p.useSparse, fixedVarsScheduleID=p._FDVarsID, exactShape=True),
                                               useSparse=p.useSparse, func=funcs[i], point=x)) \
                      for i in range(len(funcs))]
                else:
                    funcs2 = [(lambda x, i=i: \
                      p._pointDerivative2array(
                                               funcs[i].D(x, fixedVars = p.fixedVars, useSparse=p.useSparse, fixedVarsScheduleID=p._FDVarsID, exactShape=True),
                                               useSparse=p.useSparse, func=funcs[i], point=x)) \
                      for i in range(len(funcs))]
            else:
                if p.freeVars is None or (p.fixedVars is not None and
                                          len(p.freeVars) < len(p.fixedVars)):
                    funcs2 = [(lambda x, i=i: \
                               funcs[i]._getFuncCalcEngine(x, Vars = p.freeVars, fixedVarsScheduleID=p._FDVarsID))\
                      for i in range(len(funcs))]
                else:
                    funcs2 = [(lambda x, i=i: \
                               funcs[i]._getFuncCalcEngine(x, fixedVars = p.fixedVars, fixedVarsScheduleID=p._FDVarsID))\
                      for i in range(len(funcs))]
        else:
            funcs2 = funcs

        if ind is None:
            Funcs = funcs2
        elif ind is not None and p.functype[
                userFunctionType] == 'some funcs R^nvars -> R':
            Funcs = [funcs2[i] for i in ind]
        else:
            Funcs = getFuncsAndExtractIndexes(p, funcs2, ind, userFunctionType)

#        agregate_counter = 0

        Args = () if p.isFDmodel else args

        if nXvectors == 1:
            if p.isFDmodel:
                X = p._vector2point(x)
                X._p = p
                #X._linePointDescriptor = _linePointDescriptor
            else:
                X = x

        if nXvectors > 1:  # and hence getDerivative isn't involved
            #temporary, to be fixed
            if userFunctionType == 'f':
                assert p.isObjFunValueASingleNumber

            if p.isFDmodel:
                assert ind is None
                if isPyPy or p.hasVectorizableFuncs:  # TODO: get rid of box-bound constraints
                    from FuncDesigner.ooPoint import ooPoint as oopoint
                    from FuncDesigner.multiarray import multiarray

                    # TODO: new
                    xx = []
                    counter = 0
                    #xT = x.T
                    for i, oov in enumerate(p._freeVarsList):
                        s = p._optVarSizes[oov]
                        xx.append(
                            (oov,
                             (x[:, counter:counter + s].flatten() if s == 1
                              else x[:,
                                     counter:counter + s]).view(multiarray)))
                        #                        xx.append((oov, multiarray(x[:, counter: counter + s].flatten() if s == 1 else x[:, counter: counter + s])))
                        counter += s
                    X = oopoint(xx)
                    X.update(p.dictOfFixedFuncs)
                    X.maxDistributionSize = p.maxDistributionSize
                    X._p = p
                if len(p.unvectorizableFuncs) != 0:
                    XX = [p._vector2point(x[i]) for i in range(nXvectors)]
                    for _X in XX:
                        _X._p = p
                        _X.update(p.dictOfFixedFuncs)

                r = vstack([[fun(xx) for xx in XX]
                            if funcs[i] in p.unvectorizableFuncs else fun(X).T
                            for i, fun in enumerate(Funcs)]).T

#                X = [p._vector2point(x[i]) for i in range(nXvectors)]
#                r = hstack([[fun(xx) for xx in X] for fun in Funcs]).reshape(1, -1)

#new
#                if p.vectorizable:
#                    from FuncDesigner.ooPoint import ooPoint as oopoint, multiarray
#
#                    X = dict([(oovar, x[:, i].view(multiarray)) for i, oovar in enumerate(p._freeVarsList)])
#                    X = oopoint(X, skipArrayCast = True)
#                    X.N = nXvectors
#                    X.isMultiPoint = True
#                    X.update(p.dictOfFixedFuncs)
#                    r = hstack([fun(X) for fun in Funcs]).reshape(1, -1)
#
#                #old
#                else:
#                    X = [p._vector2point(x[i]) for i in range(nXvectors)]
#                    r = hstack([[fun(xx) for xx in X] for fun in Funcs]).reshape(1, -1)
            else:
                X = [(x[i], ) + Args for i in range(nXvectors)]

                #r = hstack([[fun(*xx) for xx in X] for fun in Funcs])
                R = []
                for xx in X:
                    tmp = [fun(*xx) for fun in Funcs]
                    r_ = hstack(tmp[0]) if len(tmp) == 1 and isinstance(
                        tmp[0],
                        (list,
                         tuple)) else hstack(tmp) if len(tmp) > 1 else tmp[0]
                    R.append(r_)

                r = hstack(R)  #.T
                #print(r.shape, userFunctionType)

        elif not getDerivative:
            tmp = [fun(*(X, ) + Args) for fun in Funcs]
            r = hstack(tmp[0]) if len(tmp) == 1 and isinstance(
                tmp[0],
                (list, tuple)) else hstack(tmp) if len(tmp) > 1 else tmp[0]

            #print(x.shape, r.shape, x, r)
#            if not ignorePrev and ind is None:
#                p.prevVal[userFunctionType]['key'] = copy(x_0)
#                p.prevVal[userFunctionType]['val'] = r.copy()
        elif getDerivative and p.isFDmodel:
            rr = [fun(X) for fun in Funcs]
            r = Vstack(rr) if scipyInstalled and any(
                [isspmatrix(elem) for elem in rr]) else vstack(rr)
        else:
            r = []
            if getDerivative:
                #r = zeros((nFuncsToObtain, p.n))
                diffInt = p.diffInt
                abs_x = abs(x)
                finiteDiffNumbers = 1e-10 * abs_x
                if p.diffInt.size == 1:
                    finiteDiffNumbers[finiteDiffNumbers < diffInt] = diffInt
                else:
                    finiteDiffNumbers[finiteDiffNumbers < diffInt] = diffInt[
                        finiteDiffNumbers < diffInt]
            else:
                #r = zeros((nFuncsToObtain, nXvectors))
                r = []

            for index, fun in enumerate(Funcs):
                # OLD
                #                v = ravel(fun(*((X,) + Args)))
                #                if  (ind is None or funcs_num == 1) and not ignorePrev:
                #                    #TODO: ADD COUNTER OF THE CASE
                #                    if index == 0: p.prevVal[userFunctionType]['key'] = copy(x_0)
                #                    p.prevVal[userFunctionType]['val'][agregate_counter:agregate_counter+v.size] = v.copy()
                #                r[agregate_counter:agregate_counter+v.size,0] = v

                #NEW

                if not getDerivative:
                    r.append(fun(*((X, ) + Args)))
#                    v = r[-1]
#r[agregate_counter:agregate_counter+v.size,0] = fun(*((X,) + Args))

#                if (ind is None or funcs_num == 1) and not ignorePrev:
#                    #TODO: ADD COUNTER OF THE CASE
#                    if index == 0: p.prevVal[userFunctionType]['key'] = copy(x_0)
#                    p.prevVal[userFunctionType]['val'][agregate_counter:agregate_counter+v.size] = v.copy()
                """                                                 getting derivatives                                                 """
                if getDerivative:

                    def func(x):
                        r = fun(*((x, ) + Args))
                        return r if type(r) not in (
                            list, tuple) or len(r) != 1 else r[0]

                    d1 = get_d1(func,
                                x,
                                pointVal=None,
                                diffInt=finiteDiffNumbers,
                                stencil=p.JacobianApproximationStencil,
                                exactShape=True)
                    #r[agregate_counter:agregate_counter+d1.size] = d1
                    r.append(d1)
#                    v = r[-1]

#                agregate_counter += atleast_1d(v).shape[0]
            r = hstack(r) if not getDerivative else vstack(r)
            #assert r.size != 30
        #if type(r) == matrix: r = r.A

        if type(r) != ndarray and not isscalar(r):  # multiarray
            r = r.view(ndarray).flatten(
            ) if userFunctionType == 'f' else r.view(ndarray)
        #elif userFunctionType == 'f' and p.isObjFunValueASingleNumber and prod(r.shape) > 1 and (type(r) == ndarray or min(r.shape) > 1):
        #r = r.sum(0)
        elif userFunctionType == 'f' and p.isObjFunValueASingleNumber and not isscalar(
                r):
            if prod(r.shape) > 1 and not getDerivative and nXvectors == 1:
                p.err(
                    'implicit summation in objective is no longer available to prevent possibly hidden bugs'
                )
#            if r.size == 1:
#                r = r.item()

        if userFunctionType == 'f' and p.isObjFunValueASingleNumber:
            if getDerivative and r.ndim > 1:
                if min(r.shape) > 1:
                    p.err('incorrect shape of objective func derivative')

                # TODO: omit cast to dense array. Somewhere bug triggers?
                if hasattr(r, 'toarray'):
                    r = r.toarray()
                r = r.flatten()

        if userFunctionType != 'f' and nXvectors != 1:
            r = r.reshape(nXvectors, int(r.size / nXvectors))
#        if type(r) == matrix:
#            raise 0
#            r = r.A # if _dense_numpy_matrix !

        if nXvectors == 1 and (not getDerivative or prod(
                r.shape) == 1):  # DO NOT REPLACE BY r.size - r may be sparse!
            r = r.flatten() if type(r) == ndarray else r.toarray().flatten(
            ) if not isscalar(r) else atleast_1d(r)

        if p.invertObjFunc and userFunctionType == 'f':
            r = -r

        if not getDerivative:
            if ind is None:
                p.nEvals[userFunctionType] += nXvectors
            else:
                p.nEvals[userFunctionType] = p.nEvals[userFunctionType] + float(
                    nXvectors * len(ind)) / getattr(p, 'n' + userFunctionType)

        if getDerivative:
            assert x.size == p.n  #TODO: add python list possibility here
            x = x_0  # for to suppress numerical instability effects while x +/- delta_x

        #if userFunctionType == 'f' and p.isObjFunValueASingleNumber and r.size == 1:
        #r = r.item()

        if userFunctionType == 'f' and hasattr(
                p, 'solver'
        ) and p.solver.funcForIterFcnConnection == 'f' and hasattr(
                p, 'f_iter') and not getDerivative:
            if p.nEvals['f'] % p.f_iter == 0 or nXvectors > 1:
                p.iterfcn(x, r)

        return r
Пример #11
0
def xBounds2Matrix(p):
    """
    transforms lb - ub bounds into (A, x) <= b, (Aeq, x) = beq conditions
    this func is developed for those solvers that can handle lb, ub only via c(x)<=0, h(x)=0
    """

    #TODO: is reshape/flatten required in newest numpy versions?

    # for PyPy
    IndLB, IndUB, IndEQ = \
    isfinite(p.lb) & ~(p.lb == p.ub), \
    isfinite(p.ub) & ~(p.lb == p.ub), \
    p.lb == p.ub

    indLB, indUB, indEQ = \
    where(IndLB)[0], \
    where(IndUB)[0], \
    where(IndEQ)[0]

    nLB, nUB, nEQ = Len(indLB), Len(indUB), Len(indEQ)

    if nLB > 0 or nUB > 0:
        if p.useSparse is True or (isspmatrix(
                p.A) or (scipyInstalled and nLB + nUB >= p.A.shape[0])
                                   and p.useSparse is not False):
            R1 = coo_matrix(
                (-ones(nLB),
                 (range(nLB), indLB)), shape=(nLB,
                                              p.n)) if nLB != 0 else zeros(
                                                  (0, p.n))
            R2 = coo_matrix(
                (ones(nUB),
                 (range(nUB), indUB)), shape=(nUB,
                                              p.n)) if nUB != 0 else zeros(
                                                  (0, p.n))
        else:
            R1 = zeros((nLB, p.n))
            if isPyPy:
                for i in range(nLB):
                    R1[i, indLB[i]] = -1
            else:
                R1[range(nLB), indLB] = -1
            R2 = zeros((nUB, p.n))
            if isPyPy:
                for i in range(nUB):
                    R2[i, indUB[i]] = -1
            else:
                R2[range(nUB), indUB] = 1

        p.A = Vstack((p.A, R1, R2))
        if hasattr(p, '_A'): delattr(p, '_A')
        if isspmatrix(p.A):
            if prod(p.A.shape) > 10000:
                p.A = p.A.tocsc()
                p._A = p.A
            else:
                p.A = p.A.A

        p.b = Hstack((p.b, -p.lb[IndLB], p.ub[IndUB]))

    if nEQ > 0:

        if p.useSparse is True or (isspmatrix(p.Aeq) or
                                   (scipyInstalled and nEQ >= p.Aeq.shape[0])
                                   and p.useSparse is not False):
            R = coo_matrix(([1] * nEQ, (range(nEQ), indEQ)), shape=(nEQ, p.n))
        else:
            R = zeros((nEQ, p.n))
        #raise 0
        p.Aeq = Vstack((p.Aeq, R))

        if hasattr(p, '_Aeq'): delattr(p, '_Aeq')
        if isspmatrix(p.Aeq):
            if prod(p.Aeq.shape) > 10000:
                p.Aeq = p.Aeq.tocsc()
                p._Aeq = p.Aeq
            else:
                p.Aeq = p.Aeq.A

        p.beq = Hstack((p.beq, p.lb[IndEQ]))

    p.lb = -inf * ones(p.n)
    p.ub = inf * ones(p.n)

    # TODO: prevent code clone with baseProblem.py
    nA, nAeq = prod(p.A.shape), prod(p.Aeq.shape)
    SizeThreshold = 2**15
    if scipyInstalled and p.useSparse is not False:
        from scipy.sparse import csc_matrix
        if nA > SizeThreshold and not isspmatrix(
                p.A) and flatnonzero(p.A).size < 0.25 * nA:
            p._A = csc_matrix(p.A)
        if nAeq > SizeThreshold and not isspmatrix(
                p.Aeq) and flatnonzero(p.Aeq).size < 0.25 * nAeq:
            p._Aeq = csc_matrix(p.Aeq)
    if (nA > SizeThreshold or nAeq > SizeThreshold
        ) and not scipyInstalled and p.useSparse is not False:
        p.pWarn(scipyAbsentMsg)
Пример #12
0
    def wrapped_1st_derivatives(p, x, ind_, funcType, ignorePrev, useSparse):
        if isinstance(x, dict):
            if not p.isFDmodel: p.err('calling the function with argument of type dict is allowed for FuncDesigner models only')
            if ind_ is not None:p.err('the operation is turned off for argument of type dict when ind!=None')
            x = p._point2vector(x)
        if ind_ is not None:
            ind = p.getCorrectInd(ind_)
        else: ind = None

        if p.istop == USER_DEMAND_EXIT:
            if p.solver.useStopByException:
                raise killThread                
            else:
                return nan
        derivativesType = 'd'+ funcType
        prevKey = p.prevVal[derivativesType]['key']
        if prevKey is not None and p.iter > 0 and array_equal(x, prevKey) and ind is None and not ignorePrev:
            #TODO: add counter of the situations
            assert p.prevVal[derivativesType]['val'] is not None
            return copy(p.prevVal[derivativesType]['val'])

        if ind is None and not ignorePrev: p.prevVal[derivativesType]['ind'] = copy(x)

        #TODO: patterns!
        nFuncs = getattr(p, 'n'+funcType)
        x = atleast_1d(x)
        if hasattr(p.userProvided, derivativesType) and getattr(p.userProvided, derivativesType):
               
            funcs = getattr(p.user, derivativesType)
            
            if ind is None or (nFuncs == 1 and p.functype[funcType] == 'single func'): 
                Funcs = funcs
            elif ind is not None and p.functype[funcType] == 'some funcs R^nvars -> R':
                Funcs = [funcs[i] for i in ind]
            else:
                Funcs = getFuncsAndExtractIndexes(p, funcs, ind, funcType)
            
#            if ind is None: derivativesNumber = nFuncs
#            else: derivativesNumber = len(ind)
                
            #derivatives = empty((derivativesNumber, p.n))
            derivatives = []
            #agregate_counter = 0
            for fun in Funcs:#getattr(p.user, derivativesType):
                tmp = atleast_1d(fun(*(x,)+getattr(p.args, funcType)))
                # TODO: replace tmp.size here for sparse matrices
                #assert tmp.size % p.n == mod(tmp.size, p.n)
                if tmp.size % p.n != 0:
                    if funcType=='f':
                        p.err('incorrect user-supplied (sub)gradient size of objective function')
                    elif funcType=='c':
                        p.err('incorrect user-supplied (sub)gradient size of non-lin inequality constraints')
                    elif funcType=='h':
                        p.err('incorrect user-supplied (sub)gradient size of non-lin equality constraints')
                
                if tmp.ndim == 1: m= 1
                else: m = tmp.shape[0]
                if p.functype[funcType] == 'some funcs R^nvars -> R' and m != 1:
                    # TODO: more exact check according to stored p.arr_of_indexes_* arrays
                    p.err('incorrect shape of user-supplied derivative, it should be in accordance with user-provided func size')
                derivatives.append(tmp)
                #derivatives[agregate_counter : agregate_counter + m] =  tmp#.reshape(tmp.size/p.n,p.n)
                #agregate_counter += m
            #TODO: inline ind modification!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            
            derivatives = Vstack(derivatives) if any(isspmatrix(derivatives)) else vstack(derivatives)
            if ind is None:
                p.nEvals[derivativesType] += 1
            else:
                #derivatives = derivatives[ind]
                p.nEvals[derivativesType] = p.nEvals[derivativesType] + float(len(ind)) / nFuncs

            if funcType=='f':
                if p.invertObjFunc: derivatives = -derivatives
                if p.isObjFunValueASingleNumber: 
                    if not isinstance(derivatives, ndarray): derivatives = derivatives.toarray()
                    derivatives = derivatives.flatten()
        
        else:
        #if not getattr(p.userProvided, derivativesType) or p.isFDmodel:
            #                                            x, IND, userFunctionType, ignorePrev, getDerivative
            derivatives = p.wrapped_func(x, ind, funcType, True, True)
            
            if ind is None:
                p.nEvals[derivativesType] -= 1
            else:
                p.nEvals[derivativesType] = p.nEvals[derivativesType] - float(len(ind)) / nFuncs
        #else:
        
        
        
        
        if useSparse is False or not scipyInstalled or not hasattr(p, 'solver') or not p.solver._canHandleScipySparse: 
            # p can has no attr 'solver' if it is called from checkdf, checkdc, checkdh
            if not isinstance(derivatives, ndarray): 
                derivatives = derivatives.toarray()

#        if min(derivatives.shape) == 1: 
#            if isspmatrix(derivatives): derivatives = derivatives.A
#            derivatives = derivatives.flatten()
        if type(derivatives) != ndarray and isinstance(derivatives, ndarray): # dense numpy matrix
            derivatives = derivatives.A
            
        if ind is None and not ignorePrev: p.prevVal[derivativesType]['val'] = derivatives

        if funcType=='f':
            if hasattr(p, 'solver') and not p.solver.iterfcnConnected  and p.solver.funcForIterFcnConnection=='df':
                if p.df_iter is True: p.iterfcn(x)
                elif p.nEvals[derivativesType]%p.df_iter == 0: p.iterfcn(x) # call iterfcn each {p.df_iter}-th df call
            if p.isObjFunValueASingleNumber and type(derivatives) == ndarray and derivatives.ndim > 1:
                derivatives = derivatives.flatten()
        
        return derivatives
Пример #13
0
    def wrapped_func(p, x, IND, userFunctionType, ignorePrev, getDerivative):#, _linePointDescriptor = None):
        if isinstance(x, dict):
            if not p.isFDmodel: p.err('calling the function with argument of type dict is allowed for FuncDesigner models only')
            x = p._point2vector(x)
        if not getattr(p.userProvided, userFunctionType): return array([])
        if p.istop == USER_DEMAND_EXIT:
            if p.solver.useStopByException:
                raise killThread
            else:
                return nan                
                
        if getDerivative and not p.isFDmodel and not DerApproximatorIsInstalled:
            p.err('For the problem you should have DerApproximator installed, see http://openopt.org/DerApproximator')

        #userFunctionType should be 'f', 'c', 'h'
        funcs = getattr(p.user, userFunctionType)
        #funcs_num = getattr(p, 'n'+userFunctionType)
        if IND is not None:
            ind = p.getCorrectInd(IND)
        else: ind = None

        # this line had been added because some solvers pass tuple instead of
        # x being vector p.n x 1 or matrix X=[x1 x2 x3...xk], size(X)=[p.n, k]
        if not isspmatrix(x): 
            x = atleast_1d(x)
#            if not str(x.dtype).startswith('float'):
#                x = asfarray(x)
        else:
            if p.debug:
                p.pWarn('[oo debug] sparse matrix x in nonlinfuncs.py has been encountered')
        
#        if not ignorePrev: 
#            prevKey = p.prevVal[userFunctionType]['key']
#        else:
#            prevKey = None
#            
#        # TODO: move it into runprobsolver or baseproblem
#        if p.prevVal[userFunctionType]['val'] is None:
#            p.prevVal[userFunctionType]['val'] = zeros(getattr(p, 'n'+userFunctionType))
#
#        if prevKey is not None and p.iter > 0 and array_equal(x,  prevKey) and ind is None and not ignorePrev:
#            #TODO: add counter of the situations
#            if not getDerivative:
#                r = copy(p.prevVal[userFunctionType]['val'])
#                #if p.debug: assert array_equal(r,  p.wrapped_func(x, IND, userFunctionType, True, getDerivative))
#                if ind is not None: r = r[ind]
#                
#                if userFunctionType == 'f':
#                    if p.isObjFunValueASingleNumber: r = r.sum(0)
#                    if p.invertObjFunc: r = -r
#                    if  p.solver.funcForIterFcnConnection=='f' and any(isnan(x)):
#                        p.nEvals['f'] += 1
#
#                        if p.nEvals['f']%p.f_iter == 0:
#                            p.iterfcn(x, fk = r)
#                return r

        args = getattr(p.args, userFunctionType)

        # TODO: handle it in prob prepare
        if not hasattr(p, 'n'+userFunctionType): setNonLinFuncsNumber(p,  userFunctionType)

#        if ind is None:
#            nFuncsToObtain = getattr(p, 'n'+ userFunctionType)
#        else:
#            nFuncsToObtain = len(ind)

        if x.shape[0] != p.n and (x.ndim<2 or x.shape[1] != p.n): 
            p.err('x with incorrect shape passed to non-linear function')

        #TODO: code cleanup (below)
        if getDerivative or x.ndim <= 1 or x.shape[0] == 1:
            nXvectors = 1
            x_0 = copy(x)
        else:
            nXvectors = x.shape[0]

        # TODO: use certificate instead 
        if p.isFDmodel:
            if getDerivative:
                if p.freeVars is None or (p.fixedVars is not None and len(p.freeVars) < len(p.fixedVars)):
                    funcs2 = [(lambda x, i=i: \
                      p._pointDerivative2array(
                                               funcs[i].D(x, Vars = p.freeVars, useSparse=p.useSparse, fixedVarsScheduleID=p._FDVarsID, exactShape=True), 
                                               useSparse=p.useSparse, func=funcs[i], point=x)) \
                      for i in range(len(funcs))]
                else:
                    funcs2 = [(lambda x, i=i: \
                      p._pointDerivative2array(
                                               funcs[i].D(x, fixedVars = p.fixedVars, useSparse=p.useSparse, fixedVarsScheduleID=p._FDVarsID, exactShape=True), 
                                               useSparse=p.useSparse, func=funcs[i], point=x)) \
                      for i in range(len(funcs))]
            else:
                if p.freeVars is None or (p.fixedVars is not None and len(p.freeVars) < len(p.fixedVars)):
                    funcs2 = [(lambda x, i=i: \
                               funcs[i]._getFuncCalcEngine(x, Vars = p.freeVars, fixedVarsScheduleID=p._FDVarsID))\
                      for i in range(len(funcs))]
                else:
                    funcs2 = [(lambda x, i=i: \
                               funcs[i]._getFuncCalcEngine(x, fixedVars = p.fixedVars, fixedVarsScheduleID=p._FDVarsID))\
                      for i in range(len(funcs))]
        else:
            funcs2 = funcs
            
        if ind is None: 
            Funcs = funcs2
        elif ind is not None and p.functype[userFunctionType] == 'some funcs R^nvars -> R':
            Funcs = [funcs2[i] for i in ind]
        else:
            Funcs = getFuncsAndExtractIndexes(p, funcs2, ind, userFunctionType)

#        agregate_counter = 0
        
        Args = () if p.isFDmodel else args
            
        if nXvectors == 1:
            if p.isFDmodel:
                X = p._vector2point(x) 
                X._p = p
                #X._linePointDescriptor = _linePointDescriptor
            else:
                X = x
        
        if nXvectors > 1: # and hence getDerivative isn't involved
            #temporary, to be fixed
            if userFunctionType == 'f':
               assert p.isObjFunValueASingleNumber
            

            if p.isFDmodel:
                assert ind is None
                if isPyPy or p.hasVectorizableFuncs: # TODO: get rid of box-bound constraints
                    from FuncDesigner.ooPoint import ooPoint as oopoint
                    from FuncDesigner.multiarray import multiarray
                    
                    # TODO: new
                    xx = []
                    counter = 0
                    #xT = x.T
                    for i, oov in enumerate(p._freeVarsList):
                        s = p._optVarSizes[oov]
                        xx.append((oov, (x[:, counter: counter + s].flatten() if s == 1 else x[:, counter: counter + s]).view(multiarray)))
#                        xx.append((oov, multiarray(x[:, counter: counter + s].flatten() if s == 1 else x[:, counter: counter + s])))
                        counter += s
                    X = oopoint(xx)
                    X.update(p.dictOfFixedFuncs)
                    X.maxDistributionSize = p.maxDistributionSize
                    X._p = p
                if len(p.unvectorizableFuncs) != 0:
                    XX = [p._vector2point(x[i]) for i in range(nXvectors)]
                    for _X in XX: 
                        _X._p = p
                        _X.update(p.dictOfFixedFuncs)

                r = vstack([[fun(xx) for xx in XX] if funcs[i] in p.unvectorizableFuncs else fun(X).T for i, fun in enumerate(Funcs)]).T
                
                
#                X = [p._vector2point(x[i]) for i in range(nXvectors)]
#                r = hstack([[fun(xx) for xx in X] for fun in Funcs]).reshape(1, -1)

                #new 
#                if p.vectorizable:
#                    from FuncDesigner.ooPoint import ooPoint as oopoint, multiarray
#                    
#                    X = dict([(oovar, x[:, i].view(multiarray)) for i, oovar in enumerate(p._freeVarsList)])
#                    X = oopoint(X, skipArrayCast = True)
#                    X.N = nXvectors
#                    X.isMultiPoint = True
#                    X.update(p.dictOfFixedFuncs)
#                    r = hstack([fun(X) for fun in Funcs]).reshape(1, -1)
#                
#                #old
#                else:
#                    X = [p._vector2point(x[i]) for i in range(nXvectors)]
#                    r = hstack([[fun(xx) for xx in X] for fun in Funcs]).reshape(1, -1)
            else:
                X = [(x[i],) + Args for i in range(nXvectors)] 
                
                #r = hstack([[fun(*xx) for xx in X] for fun in Funcs])
                R = []
                for xx in X:
                    tmp = [fun(*xx) for fun in Funcs]
                    r_ = hstack(tmp[0]) if len(tmp) == 1 and isinstance(tmp[0], (list, tuple)) else hstack(tmp) if len(tmp) > 1 else tmp[0]
                    R.append(r_)
                
                r = hstack(R)#.T
                #print(r.shape, userFunctionType)
                
                
        elif not getDerivative:
            tmp = [fun(*(X, )+Args) for fun in Funcs]
            r = hstack(tmp[0]) if len(tmp) == 1 and isinstance(tmp[0], (list, tuple)) else hstack(tmp) if len(tmp) > 1 else tmp[0]
                
            #print(x.shape, r.shape, x, r)
#            if not ignorePrev and ind is None:
#                p.prevVal[userFunctionType]['key'] = copy(x_0)
#                p.prevVal[userFunctionType]['val'] = r.copy()                
        elif getDerivative and p.isFDmodel:
            rr = [fun(X) for fun in Funcs]
            r = Vstack(rr) if scipyInstalled and any([isspmatrix(elem) for elem in rr]) else vstack(rr)
        else:
            r = []
            if getDerivative:
                #r = zeros((nFuncsToObtain, p.n))
                diffInt = p.diffInt
                abs_x = abs(x)
                finiteDiffNumbers = 1e-10 * abs_x
                if p.diffInt.size == 1:
                    finiteDiffNumbers[finiteDiffNumbers < diffInt] = diffInt
                else:
                    finiteDiffNumbers[finiteDiffNumbers < diffInt] = diffInt[finiteDiffNumbers < diffInt]
            else:
                #r = zeros((nFuncsToObtain, nXvectors))
                r = []
            
            for index, fun in enumerate(Funcs):
                # OLD
#                v = ravel(fun(*((X,) + Args)))
#                if  (ind is None or funcs_num == 1) and not ignorePrev:
#                    #TODO: ADD COUNTER OF THE CASE
#                    if index == 0: p.prevVal[userFunctionType]['key'] = copy(x_0)
#                    p.prevVal[userFunctionType]['val'][agregate_counter:agregate_counter+v.size] = v.copy()                
#                r[agregate_counter:agregate_counter+v.size,0] = v
                
                #NEW
                
                if not getDerivative:
                    r.append(fun(*((X,) + Args)))
#                    v = r[-1]
                    #r[agregate_counter:agregate_counter+v.size,0] = fun(*((X,) + Args))
                    
#                if (ind is None or funcs_num == 1) and not ignorePrev:
#                    #TODO: ADD COUNTER OF THE CASE
#                    if index == 0: p.prevVal[userFunctionType]['key'] = copy(x_0)
#                    p.prevVal[userFunctionType]['val'][agregate_counter:agregate_counter+v.size] = v.copy()                
                
                

                """                                                 getting derivatives                                                 """
                if getDerivative:
                    def func(x):
                        r = fun(*((x,) + Args))
                        return r if type(r) not in (list, tuple) or len(r)!=1 else r[0]
                    d1 = get_d1(func, x, pointVal = None, diffInt = finiteDiffNumbers, stencil=p.JacobianApproximationStencil, exactShape=True)
                    #r[agregate_counter:agregate_counter+d1.size] = d1
                    r.append(d1)
#                    v = r[-1]
                    
#                agregate_counter += atleast_1d(v).shape[0]
            r = hstack(r) if not getDerivative else vstack(r)
            #assert r.size != 30
        #if type(r) == matrix: r = r.A

        if type(r) != ndarray and not isscalar(r): # multiarray
            r = r.view(ndarray).flatten() if userFunctionType == 'f' else r.view(ndarray)
        #elif userFunctionType == 'f' and p.isObjFunValueASingleNumber and prod(r.shape) > 1 and (type(r) == ndarray or min(r.shape) > 1): 
            #r = r.sum(0)
        elif userFunctionType == 'f' and p.isObjFunValueASingleNumber and not isscalar(r):
            if prod(r.shape) > 1 and not getDerivative and nXvectors == 1:
                p.err('implicit summation in objective is no longer available to prevent possibly hidden bugs')
#            if r.size == 1:
#                r = r.item()
        
        if userFunctionType == 'f' and p.isObjFunValueASingleNumber:
            if getDerivative and r.ndim > 1:
                if min(r.shape) > 1:
                    p.err('incorrect shape of objective func derivative')
                
                # TODO: omit cast to dense array. Somewhere bug triggers?
                if hasattr(r, 'toarray'):
                    r=r.toarray()
                r = r.flatten()

        if userFunctionType != 'f' and nXvectors != 1:
            r = r.reshape(nXvectors, int(r.size/nXvectors))
#        if type(r) == matrix: 
#            raise 0
#            r = r.A # if _dense_numpy_matrix !

        if nXvectors == 1 and (not getDerivative or prod(r.shape) == 1): # DO NOT REPLACE BY r.size - r may be sparse!
            r = r.flatten() if type(r) == ndarray else r.toarray().flatten() if not isscalar(r) else atleast_1d(r)
        
        if p.invertObjFunc and userFunctionType=='f':
            r = -r

        if not getDerivative:
            if ind is None:
                p.nEvals[userFunctionType] += nXvectors
            else:
                p.nEvals[userFunctionType] = p.nEvals[userFunctionType] + float(nXvectors * len(ind)) / getattr(p, 'n'+ userFunctionType)

        if getDerivative:
            assert x.size == p.n#TODO: add python list possibility here
            x = x_0 # for to suppress numerical instability effects while x +/- delta_x
        
        #if userFunctionType == 'f' and p.isObjFunValueASingleNumber and r.size == 1:
            #r = r.item()
        
        if userFunctionType == 'f' and hasattr(p, 'solver') and p.solver.funcForIterFcnConnection=='f' and hasattr(p, 'f_iter') and not getDerivative:
            if p.nEvals['f']%p.f_iter == 0 or nXvectors > 1:
                p.iterfcn(x, r)

        return r