📄 base.py
字号:
def minimize(obj): if is1x1(obj): return minimizeobjective(obj) else: raise TypeError('cannot minimize non-scalar expression')class maximizeobjective(objective): def __init__(self, arg): self.arg = arg self.rows = rows(arg) self.cols = cols(arg) def __str__(self): return "maximize %s" % str(self.arg) def cvx(self): return "maximize(%s)" % cvx(self.arg) def latex(self): return r"\mbox{maximize} & %s" % latex(self.arg) def gettype(self): return "maximization" def _getconvex(self): return isconcave(self.arg) convex = property(_getconvex) def minarg(self): return -self.argclass findobjective(objective): convex = True def __init__(self, optvars): if iterable(optvars): self.arg = set(optvars) else: # ensure that self.arg is type set. self.arg = set((optvars,)) def __str__(self): return "find %s" % stroptvars(self) def gettype(self): return 'feasibility'def find(optvars): return findobjective(optvars) def maximize(obj): if is1x1(obj): return maximizeobjective(obj) else: raise TypeError('cannot maximize non-scalar expression')class function(object): def __repr__(self): return "<%sx%s expression %s; optvars: %s>" % (str(self.rows), str(self.cols), str(self), stroptvars(self)) def __str__(self): try: return self.name + '(%s)' % ", ".join([str(x) for x in self.args]) except AttributeError: return self.name + '(%s)' % str(self.arg) def __mul__(self, other): return multiply(self, other) def __rmul__(self, other): return multiply(other, self) def __add__(self, other): return addup(self, other) def __radd__(self, other): return addup(self, other) def __sub__(self, other): return addup(self, -other) def __rsub__(self, other): return addup(other, -self) def __neg__(self): return multiply(-1, self) def __pos__(self): return self def __lt__(self, other): return relation(self, other, '<') def __le__(self, other): return relation(self, other, '<=') def __gt__(self, other): return relation(self, other, '>') def __ge__(self, other): return relation(self, other, '>=') def __eq__(self, other): return relation(self, other, '==') def __rdiv__(self, other): return other*(self**-1) def getoptvars(self): if hasattr(self, 'arg'): return getoptvars(self.arg) else: return getoptvars(self.args) def getassertions(self): return getassertions(self.arg) def replacevars(self, d): if hasattr(self, 'arg'): if isoptvar(self.arg) and self.arg in set(d.keys()): self.arg = d[self.arg] else: replacevars(self.arg, d) elif hasattr(self, 'args'): for i in range(len(self.args)): if isoptvar(self.args[i]) and self.args[i] in set(d.keys()): self.args[i] = d[self.args[i]] else: replacevars(self.args[i], d) else: raise NotImplementedError def getstdforms(self): try: s = self._stdforms except AttributeError: s = set() try: s |= getstdforms(self.arg) except AttributeError: s |= getstdforms(self.args) return s def getparams(self): if hasattr(self, 'args'): s = set() for x in self.args: s |= getparams(x) return s else: return getparams(self.arg) def getdims(self): if hasattr(self, 'args'): s = set() for x in self.args: s |= getdims(x) return s else: return getdims(self.arg) def _getvalue(self): return self.func.eval(value(self.arg)) value = property(_getvalue) def _getincreasing(self): return (hasattr(self, 'incfn') and self.incfn and isincreasing(self.arg)) or \ (hasattr(self, 'decfn') and self.decfn and isdecreasing(self.arg)) increasing = property(_getincreasing) def _getdecreasing(self): return (hasattr(self, 'decfn') and self.decfn and isincreasing(self.arg)) or \ (hasattr(self, 'incfn') and self.incfn and isdecreasing(self.arg)) decreasing = property(_getdecreasing) # jemjemjem: (and for _getconcave, too) should isincreasing refer to the # extended value extension, or to the function with active domain? i.e. can # we always create an arbitrary extension with appropriate monotonicity if # the function is known monotonic over domain? def _getconvex(self): try: arg = self.arg except AttributeError: arg = self.args if hasattr(self, 'convfn') and self.convfn: if isaffine(arg): return True else: return (hasattr(self, 'incfn') and self.incfn and isconvex(arg)) or \ (hasattr(self, 'decfn') and self.decfn and isconcave(arg)) else: return False convex = property(_getconvex) def _getconcave(self): if hasattr(self, 'concfn') and self.concfn: if isaffine(self.arg): return True else: return (hasattr(self, 'incfn') and self.incfn and \ isconcave(self.arg)) or \ (hasattr(self, 'decfn') and self.decfn and \ isconvex(self.arg)) else: return False concave = property(_getconcave) # jem. somewhat overkill as a property. def _getpos(self): return hasattr(self, 'posfn') and self.posfn pos = property(_getpos) # jem. somewhat overkill as a property. def _getneg(self): return hasattr(self, 'negfn') and self.negfn neg = property(_getneg) # jemjemjem: (and for _getconcave, too) should isincreasing refer to the # extended value extension, or to the function with active domain? i.e. can # we always create an arbitrary extension with appropriate monotonicity if # the function is known monotonic over domain? def epiorhypo(self): repl = [] # for relaxations / replacements. if not (hasattr(self, 'multiarg') and self.multiarg): constr = [] t1 = dummyvar(size(self)) # epigraph (hypograph) variable. if isoptvar(self.arg): t2 = self.arg else: t2 = dummyvar(size(self.arg)) # replacement argument. repl.append((self.arg, t2)) ps = [t2] else: # Multiple argument functions. # Possibly should handle different monotonicity patterns? constr = [] t1 = dummyvar(size(self)) # epigraph (hypograph) variable. ps = [] # for calling functions. for x in self.args: # replace live optvars with dummy optvars. Don't touch # params. if getoptvars(x): if isoptvar(x): t = x else: t = dummyvar(size(x)) repl.append((x, t)) ps.append(t) else: ps.append(x) if isconvex(self.func(*ps) <= t1): # function is convex. stdform = [self.func(*ps) <= t1] conv = True elif isconvex(self.func(*ps) >= t1): # function is concave. stdform = [self.func(*ps) >= t1] conv = False else: raise ConvexityError for a in repl: (x, t) = a if isaffine(x): constr.append(x == t) elif hasattr(self, 'incfn') and self.incfn and conv or \ hasattr(self, 'decfn') and self.decfn and not conv: constr.append(x <= t) elif hasattr(self, 'decfn') and self.decfn: constr.append(x >= t) else: raise ConvexityError s = stdstruct(stdform) for x in constr: s += x.split() return (t1, s) def cvx(self): try: return self.name + '(%s)' % ", ".join([cvx(x) for x in self.args]) except AttributeError: return self.name + '(%s)' % cvx(self.arg)class elementwise(object): elementwise = Trueclass multiarg(object): multiarg = Trueclass matrixfunction(function): # jem not implemented. passclass transposefunction(function): def __init__(self, arg): self.arg = arg self.rows = cols(arg) self.cols = rows(arg) def __str__(self): return "tp(%s)" % self.arg def cvx(self): return "transpose(%s)" % self.arg def _getconvex(self): return isconvex(self.arg) convex = property(_getconvex) def _getconcave(self): return isconcave(self.arg) concave = property(_getconcave) def _getvalue(self): if is1x1(self): return v else: # Uses cvxopt representation. return transpose(value(self.arg)) value = property(_getvalue) def getvarmult(self, var): if var in getoptvars(self): raise TransposedVarError else: return 0 def getvecmult(self, var): if var in getoptvars(self): return trobj(size(var)) else: return 0 def expandtr(obj): return etranspose(obj.arg) def nzentries(obj): d = {} dobj = nzentries(obj.arg) for (i,j) in dobj.keys(): d[j,i] = dobj[i,j] return ddef transpose(obj): # Numeric function transpose doesn't ever give errors, it seems. if is1x1(obj): return obj elif isinstance(obj, (matrix, spmatrix)): return obj.trans() elif hasattr(obj, 'transpose'): return obj.transpose() elif issymm(obj): return obj else: if isinstance(obj, transposefunction): return obj.arg else: return transposefunction(obj)tp = transposedef etranspose(obj): # Transpose and expand. try: return obj.etranspose() except AttributeError: return transpose(obj)etp = etransposedef expandtr(obj): # Expand transposes. try: return obj.expandtr() except AttributeError: return objdef issymm(obj): if isinstance(obj, (int, float, matrix, spmatrix)): return value(relation(obj, transpose(obj), '==')) return is1x1(obj) or hasattr(obj, 'symm') and obj.symmclass addormultfunction(lhsrhs): def __mul__(self, other): return multiply(self, other) def __rmul__(self, other): return multiply(other, self) # Handle all inequalities the same way. def __lt__(self, other): return relation(self, other, '<') def __le__(self, other): return relation(self, other, '<=') def __gt__(self, other): return relation(self, other, '>') def __ge__(self, other): return relation(self, other, '>=') def __eq__(self, other): return relation(self, other, '==') def __int__(self): return int(value(self)) def __float__(self): return float(value(self)) def __repr__(self): return "<%sx%s expression %s; optvars: %s>" % \ (str(self.rows), str(self.cols), str(self), stroptvars(self)) def __add__(self, other): return addup(self, other) def __radd__(self, other):
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -