def buildSolverModel(self, lp, inf=1e20): """Translate the problem into a Mosek task object.""" self.cons = lp.constraints self.numcons = len(self.cons) self.cons_dict = {} i = 0 for c in self.cons: self.cons_dict[c] = i i = i+1 self.vars = list(lp.variables()) self.numvars = len(self.vars) self.var_dict = {} #Checking for repeated names lp.checkDuplicateVars() #Creating a MOSEK environment self.env = mosek.Env() self.task = self.env.Task() self.task.appendcons(self.numcons) self.task.appendvars(self.numvars) if self.msg: self.task.set_Stream(mosek.streamtype.log,self.setOutStream) #Adding variables for i in range(self.numvars): vname = self.vars[i].name self.var_dict[vname] = i self.task.putvarname(i,vname) #Variable type (Default: Continuous) if self.mip & (self.vars[i].cat == constants.LpInteger): self.task.putvartype(i,mosek.variabletype.type_int) self.solution_type = mosek.soltype.itg #Variable bounds vbkey = mosek.boundkey.fr vup = inf vlow = -inf if self.vars[i].lowBound != None: vlow = self.vars[i].lowBound if self.vars[i].upBound != None: vup = self.vars[i].upBound vbkey = mosek.boundkey.ra else: vbkey = mosek.boundkey.lo elif self.vars[i].upBound != None: vup = self.vars[i].upBound vbkey = mosek.boundkey.up self.task.putvarbound(i,vbkey,vlow,vup) #Objective coefficient for the current variable. self.task.putcj(i,lp.objective.get(self.vars[i],0.0)) #Coefficient matrix self.A_rows,self.A_cols,self.A_vals = zip(*[[self.cons_dict[row],self.var_dict[col],coeff] for col,row,coeff in lp.coefficients()]) self.task.putaijlist(self.A_rows,self.A_cols,self.A_vals) #Constraints self.constraint_data_list = [] for c in self.cons: cname = self.cons[c].name if cname != None: self.task.putconname(self.cons_dict[c],cname) else: self.task.putconname(self.cons_dict[c],c) csense = self.cons[c].sense cconst = -self.cons[c].constant clow = -inf cup = inf #Constraint bounds if csense == constants.LpConstraintEQ: cbkey = mosek.boundkey.fx clow = cconst cup = cconst elif csense == constants.LpConstraintGE: cbkey = mosek.boundkey.lo clow = cconst elif csense == constants.LpConstraintLE: cbkey = mosek.boundkey.up cup = cconst else: raise PulpSolverError('Invalid constraint type.') self.constraint_data_list.append([self.cons_dict[c],cbkey,clow,cup]) self.cons_id_list,self.cbkey_list,self.clow_list,self.cup_list = zip(*self.constraint_data_list) self.task.putconboundlist(self.cons_id_list,self.cbkey_list,self.clow_list,self.cup_list) #Objective sense if lp.sense == constants.LpMaximize: self.task.putobjsense(mosek.objsense.maximize) else: self.task.putobjsense(mosek.objsense.minimize)
def main(): # Make mosek environment env = mosek.Env() # Create a task object and attach log stream printer task = env.Task(0, 0) task.set_Stream(mosek.streamtype.log, streamprinter) # Bound keys for constraints bkc = [mosek.boundkey.fx, mosek.boundkey.fx] # Bound values for constraints blc = [1.0, 0.5] buc = [1.0, 0.5] # Below is the sparse representation of the A # matrix stored by row. asub = [array([0]), array([1, 2])] aval = [array([1.0]), array([1.0, 1.0])] conesub = [0, 1, 2] barci = [0, 1, 1, 2, 2] barcj = [0, 0, 1, 1, 2] barcval = [2.0, 1.0, 2.0, 1.0, 2.0] barai = [array([0, 1, 2]), array([0, 1, 2, 1, 2, 2])] baraj = [array([0, 1, 2]), array([0, 0, 0, 1, 1, 2])] baraval = [array([1.0, 1.0, 1.0]), array([1.0, 1.0, 1.0, 1.0, 1.0, 1.0])] numvar = 3 numcon = len(bkc) BARVARDIM = [3] # Append 'numvar' variables. # The variables will initially be fixed at zero (x=0). task.appendvars(numvar) # Append 'numcon' empty constraints. # The constraints will initially have no bounds. task.appendcons(numcon) # Append matrix variables of sizes in 'BARVARDIM'. # The variables will initially be fixed at zero. task.appendbarvars(BARVARDIM) # Set the linear term c_0 in the objective. task.putcj(0, 1.0) for j in range(numvar): # Set the bounds on variable j # blx[j] <= x_j <= bux[j] task.putvarbound(j, mosek.boundkey.fr, -inf, +inf) for i in range(numcon): # Set the bounds on constraints. # blc[i] <= constraint_i <= buc[i] task.putconbound(i, bkc[i], blc[i], buc[i]) # Input row i of A task.putarow( i, # Constraint (row) index. asub[i], # Column index of non-zeros in constraint j. aval[i]) # Non-zero values of row j. task.appendcone(mosek.conetype.quad, 0.0, conesub) symc = \ task.appendsparsesymmat(BARVARDIM[0], barci, barcj, barcval) syma0 = \ task.appendsparsesymmat(BARVARDIM[0], barai[0], baraj[0], baraval[0]) syma1 = \ task.appendsparsesymmat(BARVARDIM[0], barai[1], baraj[1], baraval[1]) task.putbarcj(0, [symc], [1.0]) task.putbaraij(0, 0, [syma0], [1.0]) task.putbaraij(1, 0, [syma1], [1.0]) # Input the objective sense (minimize/maximize) task.putobjsense(mosek.objsense.minimize) task.writedata("sdo1.task") # Solve the problem and print summary task.optimize() task.solutionsummary(mosek.streamtype.msg) # Get status information about the solution prosta = task.getprosta(mosek.soltype.itr) solsta = task.getsolsta(mosek.soltype.itr) if (solsta == mosek.solsta.optimal or solsta == mosek.solsta.near_optimal): xx = zeros(numvar, float) task.getxx(mosek.soltype.itr, xx) lenbarvar = BARVARDIM[0] * (BARVARDIM[0] + 1) / 2 barx = zeros(int(lenbarvar), float) task.getbarxj(mosek.soltype.itr, 0, barx) print("Optimal solution:\nx=%s\nbarx=%s" % (xx, barx)) elif (solsta == mosek.solsta.dual_infeas_cer or solsta == mosek.solsta.prim_infeas_cer or solsta == mosek.solsta.near_dual_infeas_cer or solsta == mosek.solsta.near_prim_infeas_cer): print("Primal or dual infeasibility certificate found.\n") elif solsta == mosek.solsta.unknown: print("Unknown solution status") else: print("Other solution status")
def mixed_integer_linear_programming(c, Aeq=None, beq=None, A=None, b=None, xmin=None, xmax=None, vtypes=None, opt=None): nx = c.shape[0] # number of decision variables if A is not None: if A.shape[0] != None: nineq = A.shape[0] # number of equality constraints else: nineq = 0 else: nineq = 0 if Aeq is not None: if Aeq.shape[0] != None: neq = Aeq.shape[0] # number of inequality constraints else: neq = 0 else: neq = 0 # Fulfilling the missing informations if beq is None or len(beq) == 0: beq = -Inf * ones(neq) if b is None or len(b) == 0: b = Inf * ones(nineq) if xmin is None or len(xmin) == 0: xmin = -Inf * ones(nx) if xmax is None or len(xmax) == 0: xmax = Inf * ones(nx) # Make a MOSEK environment with mosek.Env() as env: # Create a task with env.Task(0, 0) as task: bkc = [] blc = [] buc = [] for i in range(neq): bkc.append(mosek.boundkey.ra) blc.append(beq[i]) buc.append(beq[i]) for i in range(nineq): bkc.append(mosek.boundkey.up) blc.append(-Inf) buc.append(b[i]) bkx = [] blx = [] bux = [] for i in range(nx): bkx.append(mosek.boundkey.ra) blx.append(xmin[i]) bux.append(xmax[i]) if neq != 0: if neq != 0 and nineq != 0: A = vstack([Aeq, A]) elif neq != 0 and nineq == 0: A = Aeq # Generate the sparse matrix numcon = neq + nineq asub = [] aval = [] if numcon != 0: for i in range(nx): index = [] val = [] for j in range(numcon): if A[j, i] != 0: index.append(j) val.append(A[j, i]) asub.append(index) aval.append(val) # Append 'numcon' empty constraints. # The constraints will initially have no bounds. task.appendcons(numcon) # Append 'numvar' variables. # The variables will initially be fixed at zero (x=0). task.appendvars(nx) for j in range(nx): # Set the linear term c_j in the objective. task.putcj(j, c[j]) # Set the bounds on variable j # blx[j] <= x_j <= bux[j] # Input column j of A task.putacol( j, # Variable (column) index. # Row index of non-zeros in column j. asub[j], aval[j]) # Non-zero Values of column j. if vtypes[j] == "b" or vtypes[j] == "B": task.putvartypelist([j], [mosek.variabletype.type_int]) task.putvarbound(j, mosek.boundkey.ra, 0, 1) elif vtypes[j] == "c" or vtypes[j] == "C": task.putvartypelist([j], [mosek.variabletype.type_int]) task.putvarbound(j, bkx[j], blx[j], bux[j]) else: task.putvartypelist([j], [mosek.variabletype.type_cont]) task.putvarbound(j, bkx[j], blx[j], bux[j]) task.putconboundlist(range(numcon), bkc, blc, buc) # Input the objective sense (minimize/maximize) task.putobjsense(mosek.objsense.minimize) # Optimize the task task.optimize() prosta = task.getprosta(mosek.soltype.itg) solsta = task.getsolsta(mosek.soltype.itg) # Output a solution xx = [0.] * nx task.getxx(mosek.soltype.itg, xx) success = 1 if solsta in [ mosek.solsta.integer_optimal, mosek.solsta.near_integer_optimal ]: print("Optimal solution: %s" % xx) elif solsta == mosek.solsta.dual_infeas_cer: print("Primal or dual infeasibility.\n") elif solsta == mosek.solsta.prim_infeas_cer: print("Primal or dual infeasibility.\n") elif solsta == mosek.solsta.near_dual_infeas_cer: print("Primal or dual infeasibility.\n") elif solsta == mosek.solsta.near_prim_infeas_cer: print("Primal or dual infeasibility.\n") elif mosek.solsta.unknown: if prosta == mosek.prosta.prim_infeas_or_unbounded: print("Problem status Infeasible or unbounded.\n") elif prosta == mosek.prosta.prim_infeas: print("Problem status Infeasible.\n") elif prosta == mosek.prosta.unkown: print("Problem status unkown.\n") else: print("Other problem status.\n") success = 0 else: print("Other solution status") success = 0 # if solsta in [mosek.solsta.integer_optimal, mosek.solsta.near_integer_optimal]: # pass # elif solsta == mosek.solsta.dual_infeas_cer: # pass # elif solsta == mosek.solsta.prim_infeas_cer: # pass # elif solsta == mosek.solsta.near_dual_infeas_cer: # pass # elif solsta == mosek.solsta.near_prim_infeas_cer: # pass # elif mosek.solsta.unknown: # if prosta == mosek.prosta.prim_infeas_or_unbounded: # pass # elif prosta == mosek.prosta.prim_infeas: # pass # elif prosta == mosek.prosta.unkown: # pass # else: # print("Other problem status.\n") # success = 0 # else: # pass # success = 0 return xx, solsta, success
def main(): numcon = 2 numvar = 2 # Since the value infinity is never used, we define # 'infinity' symbolic purposes only infinity = 0 c = [1.0, 1.0] ptrb = [0, 2] ptre = [2, 3] asub = [0, 1, 0, 1] aval = [1.0, 1.0, 2.0, 1.0] bkc = [mosek.boundkey.up, mosek.boundkey.up] blc = [-infinity, -infinity] buc = [2.0, 6.0] bkx = [mosek.boundkey.lo, mosek.boundkey.lo] blx = [0.0, 0.0] bux = [+infinity, +infinity] w1 = [2.0, 6.0] w2 = [1.0, 0.0] try: with mosek.Env() as env: with env.Task(0, 0) as task: task.set_Stream(mosek.streamtype.log, streamprinter) task.inputdata(numcon, numvar, c, 0.0, ptrb, ptre, asub, aval, bkc, blc, buc, bkx, blx, bux) task.putobjsense(mosek.objsense.maximize) r = task.optimize() if r != mosek.rescode.ok: print("Mosek warning:", r) basis = [0] * numcon task.initbasissolve(basis) #List basis variables corresponding to columns of B varsub = [0, 1] for i in range(numcon): if basis[varsub[i]] < numcon: print("Basis variable no %d is xc%d" % (i, basis[i])) else: print("Basis variable no %d is x%d" % (i, basis[i] - numcon)) # solve Bx = w1 # varsub contains index of non-zeros in b. # On return b contains the solution x and # varsub the index of the non-zeros in x. nz = 2 nz = task.solvewithbasis(0, nz, varsub, w1) print("nz = %s" % nz) print("Solution to Bx = w1:") for i in range(nz): if basis[varsub[i]] < numcon: print("xc %s = %s" % (basis[varsub[i]], w1[varsub[i]])) else: print("x%s = %s" % (basis[varsub[i]] - numcon, w1[varsub[i]])) # Solve B^Tx = w2 nz = 1 varsub[0] = 0 nz = task.solvewithbasis(1, nz, varsub, w2) print("Solution to B^Tx = w2:") for i in range(nz): if basis[varsub[i]] < numcon: print("xc %s = %s" % (basis[varsub[i]], w2[varsub[i]])) else: print("x %s = %s" % (basis[varsub[i]] - numcon, w2[varsub[i]])) except Exception as e: print(e)
if __name__ == '__main__': n = 3 gamma = 0.05 mu = [0.1073, 0.0737, 0.0627] GT = [[0.1667, 0.0232, 0.0013], [0.0000, 0.1033, -0.0022], [0.0000, 0.0000, 0.0338]] x0 = [0.0, 0.0, 0.0] w = 1.0 m = [0.01, 0.01, 0.01] # This value has no significance. inf = 0.0 with mosek.Env() as env: with env.Task(0, 0) as task: task.set_Stream(mosek.streamtype.log, streamprinter) rtemp = w for j in range(0, n): rtemp += x0[j] # Constraints. task.appendcons(1 + 9 * n) task.putconbound(0, mosek.boundkey.fx, rtemp, rtemp) task.putconname(0, "budget") task.putconboundlist(range(1 + 0, 1 + n), n * [mosek.boundkey.fx], n * [0.0], n * [0.0]) for j in range(1, 1 + n):
def qp(P, q, G=None, h=None, A=None, b=None, taskfile=None): """ Solves a quadratic program minimize (1/2)*x'*P*x + q'*x subject to G*x <= h A*x = b. using MOSEK 8.0. solsta, x, z, y = qp(P, q, G=None, h=None, A=None, b=None, taskfile=None) Return values solsta is a MOSEK solution status key. If solsta is mosek.solsta.optimal, then (x, y, z) contains the primal-dual solution. If solsta is mosek.solsta.prim_infeas_cer, then (x, y, z) is a certificate of primal infeasibility. If solsta is mosek.solsta.dual_infeas_cer, then (x, y, z) is a certificate of dual infeasibility. If solsta is mosek.solsta.unknown, then (x, y, z) are all None. Other return values for solsta include: mosek.solsta.dual_feas mosek.solsta.near_dual_feas mosek.solsta.near_optimal mosek.solsta.near_prim_and_dual_feas mosek.solsta.near_prim_feas mosek.solsta.prim_and_dual_feas mosek.solsta.prim_feas in which case the (x,y,z) value may not be well-defined. x, z, y the primal-dual solution. Options are passed to MOSEK solvers via the msk.options dictionary, e.g., the following turns off output from the MOSEK solvers >>> msk.options = {mosek.iparam.log: 0} see the MOSEK Python API manual. Optionally, the interface can write a .task file, required for support questions on the MOSEK solver. """ with mosek.Env() as env: if (type(P) is not matrix and type(P) is not spmatrix) or \ P.typecode != 'd' or P.size[0] != P.size[1]: raise TypeError("'P' must be a square dense or sparse 'd' matrix ") n = P.size[0] if n < 1: raise ValueError("number of variables must be at least 1") if type(q) is not matrix or q.typecode != 'd' or q.size != (n, 1): raise TypeError("'q' must be a 'd' matrix of size (%d,1)" % n) if G is None: G = spmatrix([], [], [], (0, n), 'd') if (type(G) is not matrix and type(G) is not spmatrix) or \ G.typecode != 'd' or G.size[1] != n: raise TypeError("'G' must be a dense or sparse 'd' matrix "\ "with %d columns" %n) m = G.size[0] if h is None: h = matrix(0.0, (0, 1)) if type(h) is not matrix or h.typecode != 'd' or h.size != (m, 1): raise TypeError("'h' must be a 'd' matrix of size (%d,1)" % m) if A is None: A = spmatrix([], [], [], (0, n), 'd') if (type(A) is not matrix and type(A) is not spmatrix) or \ A.typecode != 'd' or A.size[1] != n: raise TypeError("'A' must be a dense or sparse 'd' matrix "\ "with %d columns" %n) p = A.size[0] if b is None: b = matrix(0.0, (0, 1)) if type(b) is not matrix or b.typecode != 'd' or b.size != (p, 1): raise TypeError("'b' must be a dense matrix of size (%d,1)" % p) if m + p is 0: raise ValueError("m + p must be greater than 0") c = list(q) bkc = m * [mosek.boundkey.up] + p * [mosek.boundkey.fx] blc = m * [-inf] + [bi for bi in b] buc = list(h) + list(b) bkx = n * [mosek.boundkey.fr] blx = n * [-inf] bux = n * [+inf] colptr, asub, acof = sparse([G, A]).CCS aptrb, aptre = colptr[:-1], colptr[1:] with env.Task(0, 0) as task: task.set_Stream(mosek.streamtype.log, streamprinter) # set MOSEK options for (param, val) in options.items(): if str(param)[:6] == "iparam": task.putintparam(param, val) elif str(param)[:6] == "dparam": task.putdouparam(param, val) elif str(param)[:6] == "sparam": task.putstrparam(param, val) else: raise ValueError("invalid MOSEK parameter: " + str(param)) task.inputdata( m + p, # number of constraints n, # number of variables c, # linear objective coefficients 0.0, # objective fixed value list(aptrb), list(aptre), list(asub), list(acof), bkc, blc, buc, bkx, blx, bux) Ps = sparse(P) I, J = Ps.I, Ps.J tril = [k for k in range(len(I)) if I[k] >= J[k]] task.putqobj(list(I[tril]), list(J[tril]), list(Ps.V[tril])) task.putobjsense(mosek.objsense.minimize) if taskfile: task.writetask(taskfile) task.optimize() task.solutionsummary(mosek.streamtype.msg) solsta = task.getsolsta(mosek.soltype.itr) x = n * [0.0] task.getsolutionslice(mosek.soltype.itr, mosek.solitem.xx, 0, n, x) x = matrix(x) if m is not 0: z = m * [0.0] task.getsolutionslice(mosek.soltype.itr, mosek.solitem.suc, 0, m, z) z = matrix(z) else: z = matrix(0.0, (0, 1)) if p is not 0: yu, yl = p * [0.0], p * [0.0] task.getsolutionslice(mosek.soltype.itr, mosek.solitem.suc, m, m + p, yu) task.getsolutionslice(mosek.soltype.itr, mosek.solitem.slc, m, m + p, yl) y = matrix(yu) - matrix(yl) else: y = matrix(0.0, (0, 1)) if (solsta is mosek.solsta.unknown): return (solsta, None, None, None) else: return (solsta, x, z, y)
def solve_via_data(self, data, warm_start, verbose, solver_opts, solver_cache=None): import mosek env = mosek.Env() task = env.Task(0, 0) # If verbose, then set default logging parameters. if verbose: import sys def streamprinter(text): sys.stdout.write(text) sys.stdout.flush() print('\n') env.set_Stream(mosek.streamtype.log, streamprinter) task.set_Stream(mosek.streamtype.log, streamprinter) task.putintparam(mosek.iparam.infeas_report_auto, mosek.onoffkey.on) task.putintparam(mosek.iparam.log_presolve, 0) # Parse all user-specified parameters (override default logging # parameters if applicable). kwargs = sorted(solver_opts.keys()) save_file = None bfs = False if 'mosek_params' in kwargs: self._handle_mosek_params(task, solver_opts['mosek_params']) kwargs.remove('mosek_params') if 'save_file' in kwargs: save_file = solver_opts['save_file'] kwargs.remove('save_file') if 'bfs' in kwargs: bfs = solver_opts['bfs'] kwargs.remove('bfs') if kwargs: raise ValueError("Invalid keyword-argument '%s'" % kwargs[0]) # Decide whether basis identification is needed for intpnt solver # This is only required if solve() was called with bfs=True if bfs: task.putintparam(mosek.iparam.intpnt_basis, mosek.basindtype.always) else: task.putintparam(mosek.iparam.intpnt_basis, mosek.basindtype.never) # Check if the cvxpy standard form has zero variables. If so, # return a trivial solution. This is necessary because MOSEK # will crash if handed a problem with zero variables. if len(data[s.C]) == 0: return { s.STATUS: s.OPTIMAL, s.PRIMAL: [], s.VALUE: data[s.OFFSET], s.EQ_DUAL: [], s.INEQ_DUAL: [] } # The following lines recover problem parameters, and define helper constants. # # The problem's objective is "min c.T * z". # The problem's constraint set is "G * z <=_K h." # The rows in (G, h) are formatted in order of # (1) linear inequalities, # (2) linear equations, # (3) soc constraints, # (4) exponential cone constraints, # (5) vectorized linear matrix inequalities. # The parameter "dims" indicates the exact # dimensions of each of these cones. # # MOSEK's standard form requires that we replace generalized # inequalities with slack variables and linear equations. # The parameter "n" is the size of the column-vector variable # after adding slacks for SOC and EXP constraints. To be # consistent with MOSEK documentation, subsequent comments # refer to this variable as "x". c = data[s.C] G, h = data[s.G], data[s.H] dims = data[s.DIMS] n0 = len(c) n = n0 + sum(dims[s.SOC_DIM]) + 3 * dims[s.EXP_DIM] psd_total_dims = sum(el**2 for el in dims[s.PSD_DIM]) m = len(h) num_bool = len(data[s.BOOL_IDX]) num_int = len(data[s.INT_IDX]) # Define variables, cone constraints, and integrality constraints. # # The variable "x" is a length-n block vector, with # Block 1: "z" from "G * z <=_K h", # Block 2: slacks for SOC constraints, and # Block 3: slacks for EXP cone constraints. # # Once we declare x in the MOSEK model, we add the necessary # conic constraints for slack variables (Blocks 2 and 3). # The last step is to add integrality constraints. # # Note that the API call for PSD variables contains the word "bar". # MOSEK documentation consistently uses "bar" as a sort of flag, # indicating that a function deals with PSD variables. task.appendvars(n) task.putvarboundlist(np.arange(n, dtype=int64), [mosek.boundkey.fr] * n, np.zeros(n), np.zeros(n)) if psd_total_dims > 0: task.appendbarvars(dims[s.PSD_DIM]) running_idx = n0 for size_cone in dims[s.SOC_DIM]: task.appendcone( mosek.conetype.quad, 0.0, # unused np.arange(running_idx, running_idx + size_cone)) running_idx += size_cone for k in range(dims[s.EXP_DIM]): task.appendcone( mosek.conetype.pexp, 0.0, # unused np.arange(running_idx, running_idx + 3)) running_idx += 3 if num_bool + num_int > 0: task.putvartypelist(data[s.BOOL_IDX], [mosek.variabletype.type_int] * num_bool) task.putvarboundlist(data[s.BOOL_IDX], [mosek.boundkey.ra] * num_bool, [0] * num_bool, [1] * num_bool) task.putvartypelist(data[s.INT_IDX], [mosek.variabletype.type_int] * num_int) # Define linear inequality and equality constraints. # # Mosek will see a total of m linear expressions, which must # define linear inequalities and equalities. The variable x # contributes to these linear expressions by standard # matrix-vector multiplication; the matrix in question is # referred to as "A" in the mosek documentation. The PSD # variables have a different means of contributing to the # linear expressions. Specifically, a PSD variable Xj contributes # "+tr( \bar{A}_{ij} * Xj )" to the i-th linear expression, # where \bar{A}_{ij} is specified by a call to putbaraij. # # The following code has three phases. # (1) Build the matrix A. # (2) Specify the \bar{A}_{ij} for PSD variables. # (3) Specify the RHS of the m linear (in)equalities. # # Remark : The parameter G gives every row in the first # n0 columns of A. The remaining columns of A are for SOC # and EXP slack variables. We can actually account for all # of these slack variables at once by specifying a giant # identity matrix in the appropriate position in A. task.appendcons(m) row, col, vals = sp.sparse.find(G) task.putaijlist(row.tolist(), col.tolist(), vals.tolist()) total_soc_exp_slacks = sum(dims[s.SOC_DIM]) + 3 * dims[s.EXP_DIM] if total_soc_exp_slacks > 0: i = dims[s.LEQ_DIM] + dims[ s.EQ_DIM] # constraint index in {0, ..., m - 1} j = len( c ) # index of the first slack variable in the block vector "x". rows = np.arange(i, i + total_soc_exp_slacks).tolist() cols = np.arange(j, j + total_soc_exp_slacks).tolist() task.putaijlist(rows, cols, [1] * total_soc_exp_slacks) # constraint index; start of LMIs. i = dims[s.LEQ_DIM] + dims[s.EQ_DIM] + total_soc_exp_slacks for j, dim in enumerate(dims[s.PSD_DIM]): # SDP slack variable "Xj" for row_idx in range(dim): for col_idx in range(dim): val = 1. if row_idx == col_idx else 0.5 row = max(row_idx, col_idx) col = min(row_idx, col_idx) mat = task.appendsparsesymmat(dim, [row], [col], [val]) task.putbaraij(i, j, [mat], [1.0]) i += 1 num_eq = len(h) - dims[s.LEQ_DIM] type_constraint = [mosek.boundkey.up] * dims[s.LEQ_DIM] + \ [mosek.boundkey.fx] * num_eq task.putconboundlist(np.arange(m, dtype=int), type_constraint, h, h) # Define the objective, and optimize the mosek task. task.putclist(np.arange(len(c)), c) task.putobjsense(mosek.objsense.minimize) if save_file: task.writedata(save_file) task.optimize() if verbose: task.solutionsummary(mosek.streamtype.msg) return {'env': env, 'task': task, 'solver_options': solver_opts}
def main(): # Make a MOSEK environment env = mosek.Env() # Attach a printer to the environment env.set_Stream(mosek.streamtype.log, streamprinter) # Create a task task = env.Task(0, 0) # Attach a printer to the task task.set_Stream(mosek.streamtype.log, streamprinter) # Bound keys for constraints bkc = [mosek.boundkey.fx, mosek.boundkey.lo, mosek.boundkey.up] # Bound values for constraints blc = [30.0, 15.0, -inf] buc = [30.0, +inf, 25.0] # Bound keys for variables bkx = [ mosek.boundkey.lo, mosek.boundkey.ra, mosek.boundkey.lo, mosek.boundkey.lo ] # Bound values for variables blx = [0.0, 0.0, 0.0, 0.0] bux = [+inf, 10.0, +inf, +inf] # Objective coefficients c = [3.0, 1.0, 5.0, 1.0] # Below is the sparse representation of the A # matrix stored by column. asub = [array([0, 1]), array([0, 1, 2]), array([0, 1]), array([1, 2])] aval = [ array([3.0, 2.0]), array([1.0, 1.0, 2.0]), array([2.0, 3.0]), array([1.0, 3.0]) ] NUMVAR = len(bkx) NUMCON = len(bkc) NUMANZ = 9 # Give MOSEK an estimate of the size of the input data. # This is done to increase the speed of inputting data. # However, it is optional. task.putmaxnumvar(NUMVAR) task.putmaxnumcon(NUMCON) task.putmaxnumanz(NUMANZ) # Append 'NUMCON' empty constraints. # The constraints will initially have no bounds. task.append(mosek.accmode.con, NUMCON) #Append 'NUMVAR' variables. # The variables will initially be fixed at zero (x=0). task.append(mosek.accmode.var, NUMVAR) #Optionally add a constant term to the objective. task.putcfix(0.0) for j in range(NUMVAR): # Set the linear term c_j in the objective. task.putcj(j, c[j]) # Set the bounds on variable j # blx[j] <= x_j <= bux[j] task.putbound(mosek.accmode.var, j, bkx[j], blx[j], bux[j]) # Input column j of A task.putavec( mosek.accmode.var, # Input columns of A. j, # Variable (column) index. asub[j], # Row index of non-zeros in column j. aval[j]) # Non-zero Values of column j. for i in range(NUMCON): task.putbound(mosek.accmode.con, i, bkc[i], blc[i], buc[i]) # Input the objective sense (minimize/maximize) task.putobjsense(mosek.objsense.maximize) # Optimize the task task.optimize() # Print a summary containing information # about the solution for debugging purposes task.solutionsummary(mosek.streamtype.msg) prosta = [] solsta = [] [prosta, solsta] = task.getsolutionstatus(mosek.soltype.bas) # Output a solution xx = zeros(NUMVAR, float) task.getsolutionslice(mosek.soltype.bas, mosek.solitem.xx, 0, NUMVAR, xx) if solsta == mosek.solsta.optimal or solsta == mosek.solsta.near_optimal: print("Optimal solution: %s" % xx) elif solsta == mosek.solsta.dual_infeas_cer: print("Primal or dual infeasibility.\n") elif solsta == mosek.solsta.prim_infeas_cer: print("Primal or dual infeasibility.\n") elif solsta == mosek.solsta.near_dual_infeas_cer: print("Primal or dual infeasibility.\n") elif solsta == mosek.solsta.near_prim_infeas_cer: print("Primal or dual infeasibility.\n") elif mosek.solsta.unknown: print("Unknown solution status") else: print("Other solution status")
def optimize(*, c, A, k, p_idxs, **kwargs): # pylint: disable=too-many-locals,too-many-statements,too-many-branches """ Definitions ----------- "[a,b] array of floats" indicates array-like data with shape [a,b] n is the number of monomials in the gp m is the number of variables in the gp p is the number of posynomial constraints in the gp Arguments --------- c : floats array of shape n Coefficients of each monomial A : gpkit.small_classes.CootMatrix, of shape (n, m) Exponents of the various free variables for each monomial. k : ints array of shape p+1 k[0] is the number of monomials (rows of A) present in the objective k[1:] is the number of monomials (rows of A) present in each constraint p_idxs : ints array of shape n. sel = p_idxs == i selects rows of A and entries of c of the i-th posynomial fi(x) = c[sel] @ exp(A[sel,:] @ x). The 0-th posynomial gives the objective function, and the remaining posynomials should be constrained to be <= 1. Returns ------- dict Contains the following keys "status": string "optimal", "infeasible", "unbounded", or "unknown". "primal" np.ndarray or None The values of the ``m`` primal variables. "la": np.ndarray or None The dual variables to the ``p`` posynomial constraints, when those constraints are represented in log-sum-exp ("LSE") form. """ # # Initial transformations of problem data. # # separate monomial constraints (call them "lin"), # from those which require # an LSE representation (call those "lse"). # # NOTE: the epigraph of the objective function always gets an "lse" # representation, even if the objective is a monomial. # log_c = np.log(np.array(c)) lse_posys = [0] lin_posys = [] for i, val in enumerate(k[1:]): if val > 1: lse_posys.append(i + 1) else: lin_posys.append(i + 1) if lin_posys: A = A.tocsr() lin_posys_set = frozenset(lin_posys) lin_idxs = [i for i, p in enumerate(p_idxs) if p in lin_posys_set] lse_idxs = np.ones(A.shape[0], dtype=bool) lse_idxs[lin_idxs] = False A_lse = A[lse_idxs, :].tocoo() log_c_lse = log_c[lse_idxs] A_lin = A[lin_idxs, :].tocoo() log_c_lin = log_c[lin_idxs] else: log_c_lin = None # A_lin won't be referenced later, A_lse = A # so no need to define it. log_c_lse = log_c k_lse = [k[i] for i in lse_posys] n_lse = sum(k_lse) p_lse = len(k_lse) lse_p_idx = [] for i, ki in enumerate(k_lse): lse_p_idx.extend([i] * ki) lse_p_idx = np.array(lse_p_idx) # # Create MOSEK task. Add variables, bound constraints, and conic # constraints. # # Say that MOSEK's optimization variable is a block vector, # [x;t;z], where ... # x is the user-defined primal variable (length m), # t is an aux variable for exponential cones (length 3 * n_lse), # z is an epigraph variable for LSE terms (length p_lse). # # The variable z[0] is special, # because it's the epigraph of the objective function # in LSE form. The sign of this variable is not constrained. # # The variables z[1:] are epigraph terms for "log", # in constraints that naturally write as # LSE(Ai @ x + log_ci) <= 0. These variables need to be <= 0. # # The main constraints on (x, t, z) are described # in next comment block. # env = mosek.Env() task = env.Task(0, 0) m = A.shape[1] msk_nvars = m + 3 * n_lse + p_lse task.appendvars(msk_nvars) # "x" is free task.putvarboundlist(np.arange(m), [mosek.boundkey.fr] * m, np.zeros(m), np.zeros(m)) # t[3 * i + i] == 1, other components are free. bound_types = [mosek.boundkey.fr, mosek.boundkey.fx, mosek.boundkey.fr] task.putvarboundlist(np.arange(m, m + 3 * n_lse), bound_types * n_lse, np.ones(3 * n_lse), np.ones(3 * n_lse)) # z[0] is free; z[1:] <= 0. bound_types = [mosek.boundkey.fr] + [mosek.boundkey.up] * (p_lse - 1) task.putvarboundlist(np.arange(m + 3 * n_lse, msk_nvars), bound_types, np.zeros(p_lse), np.zeros(p_lse)) # t[3*i], t[3*i + 1], t[3*i + 2] belongs to the exponential cone task.appendconesseq([mosek.conetype.pexp] * n_lse, [0.0] * n_lse, [3] * n_lse, m) # # Exponential cone affine constraints (other than t[3*i + 1] == 1). # # For each i in {0, ..., n_lse - 1}, we need # t[3*i + 2] == A_lse[i, :] @ x + log_c_lse[i] - z[lse_p_idx[i]]. # # For each j from {0, ..., p_lse - 1}, the "t" should also satisfy # sum(t[3*i] for i where i == lse_p_idx[j]) <= 1. # # When combined with bound constraints ``t[3*i + 1] == 1``, the # above constraints imply # LSE(A_lse[sel, :] @ x + log_c_lse[sel]) <= z[i] # for ``sel = lse_p_idx == i``. # task.appendcons(n_lse + p_lse) # Linear equations between (x,t,z). # start with coefficients on "x" rows = list(A_lse.row) cols = list(A_lse.col) vals = list(A_lse.data) # add coefficients on "t" rows += list(range(n_lse)) cols += (m + 3 * np.arange(n_lse) + 2).tolist() vals += [-1.0] * n_lse # add coefficients on "z" rows += list(range(n_lse)) cols += [m + 3 * n_lse + lse_p_idx[i] for i in range(n_lse)] vals += [-1.0] * n_lse task.putaijlist(rows, cols, vals) cur_con_idx = n_lse # Linear inequalities on certain sums of "t". rows, cols, vals = [], [], [] for i in range(p_lse): sels = np.nonzero(lse_p_idx == i)[0] rows.extend([cur_con_idx] * sels.size) cols.extend(m + 3 * sels) vals.extend([1] * sels.size) cur_con_idx += 1 task.putaijlist(rows, cols, vals) # Build the right-hand-sides of the [in]equality constraints type_constraint = [mosek.boundkey.fx] * n_lse + [mosek.boundkey.up] * p_lse h = np.concatenate([-log_c_lse, np.ones(p_lse)]) task.putconboundlist(np.arange(h.size, dtype=int), type_constraint, h, h) # # Affine constraints, not needing the exponential cone # # Require A_lin @ x <= -log_c_lin. # if log_c_lin is not None: task.appendcons(log_c_lin.size) rows = cur_con_idx + np.array(A_lin.row) task.putaijlist(rows, A_lin.col, A_lin.data) type_constraint = [mosek.boundkey.up] * log_c_lin.size con_indices = np.arange(cur_con_idx, cur_con_idx + log_c_lin.size) h = -log_c_lin #pylint: disable=invalid-unary-operand-type task.putconboundlist(con_indices, type_constraint, h, h) cur_con_idx += log_c_lin.size # # Set the objective function # task.putclist([int(m + 3 * n_lse)], [1]) task.putobjsense(mosek.objsense.minimize) # # Set solver parameters, and call .solve(). # verbose = kwargs.get("verbose", True) if verbose: def streamprinter(text): "Stream printer for output from mosek." print(text) env.set_Stream(mosek.streamtype.log, streamprinter) task.set_Stream(mosek.streamtype.log, streamprinter) task.putintparam(mosek.iparam.infeas_report_auto, mosek.onoffkey.on) task.putintparam(mosek.iparam.log_presolve, 0) try: task.optimize() except mosek.Error as e: # pragma: no cover if e.errno in [ mosek.rescode.err_missing_license_file, mosek.rescode.err_license_version, mosek.rescode.err_license_expired ]: raise InvalidLicense() from e raise e if verbose: task.solutionsummary(mosek.streamtype.msg) # # Recover the solution # msk_solsta = task.getsolsta(mosek.soltype.itr) if msk_solsta == mosek.solsta.prim_infeas_cer: raise PrimalInfeasible() if msk_solsta == mosek.solsta.dual_infeas_cer: raise DualInfeasible() if msk_solsta != mosek.solsta.optimal: # pragma: no cover raise UnknownInfeasible("solution status: ", msk_solsta) # recover primal variables x = [0.] * m task.getxxslice(mosek.soltype.itr, 0, m, x) # recover dual variables for log-sum-exp epigraph constraints # (skip epigraph of the objective function). z_duals = [0.] * (p_lse - 1) task.getsuxslice(mosek.soltype.itr, m + 3 * n_lse + 1, msk_nvars, z_duals) z_duals = np.array(z_duals) z_duals[z_duals < 0] = 0 # recover dual variables for the remaining user-provided constraints if log_c_lin is not None: aff_duals = [0.] * log_c_lin.size task.getsucslice(mosek.soltype.itr, n_lse + p_lse, cur_con_idx, aff_duals) aff_duals = np.array(aff_duals) aff_duals[aff_duals < 0] = 0 # merge z_duals with aff_duals merged_duals = np.zeros(len(k)) merged_duals[lse_posys[1:]] = z_duals # skipping the cost merged_duals[lin_posys] = aff_duals merged_duals = merged_duals[1:] else: merged_duals = z_duals # wrap things up in a dictionary solution = { "status": "optimal", "primal": np.array(x), "la": merged_duals, "objective": np.exp(task.getprimalobj(mosek.soltype.itr)) } task.__exit__(None, None, None) env.__exit__(None, None, None) return solution
class MOSEK(LpSolver): """Mosek lp and mip solver (via Mosek Optimizer API).""" name = "MOSEK" try: global mosek import mosek env = mosek.Env() except ImportError: def available(self): """True if Mosek is available.""" return False def actualSolve(self, lp, callback=None): """Solves a well-formulated lp problem.""" raise PulpSolverError("MOSEK : Not Available") else: def __init__( self, mip=True, msg=True, options={}, task_file_name="", sol_type=mosek.soltype.bas, ): """Initializes the Mosek solver. Keyword arguments: @param mip: If False, then solve MIP as LP. @param msg: Enable Mosek log output. @param options: Accepts a dictionary of Mosek solver parameters. Ignore to use default parameter values. Eg: options = {mosek.dparam.mio_max_time:30} sets the maximum time spent by the Mixed Integer optimizer to 30 seconds. Equivalently, one could also write: options = {"MSK_DPAR_MIO_MAX_TIME":30} which uses the generic parameter name as used within the solver, instead of using an object from the Mosek Optimizer API (Python), as before. @param task_file_name: Writes a Mosek task file of the given name. By default, no task file will be written. Eg: task_file_name = "eg1.opf". @param sol_type: Mosek supports three types of solutions: mosek.soltype.bas (Basic solution, default), mosek.soltype.itr (Interior-point solution) and mosek.soltype.itg (Integer solution). For a full list of Mosek parameters (for the Mosek Optimizer API) and supported task file formats, please see https://docs.mosek.com/9.1/pythonapi/parameters.html#doc-all-parameter-list. """ self.mip = mip self.msg = msg self.task_file_name = task_file_name self.solution_type = sol_type self.options = options def available(self): """True if Mosek is available.""" return True def setOutStream(self, text): """Sets the log-output stream.""" sys.stdout.write(text) sys.stdout.flush() def buildSolverModel(self, lp, inf=1e20): """Translate the problem into a Mosek task object.""" self.cons = lp.constraints self.numcons = len(self.cons) self.cons_dict = {} i = 0 for c in self.cons: self.cons_dict[c] = i i = i + 1 self.vars = list(lp.variables()) self.numvars = len(self.vars) self.var_dict = {} # Checking for repeated names lp.checkDuplicateVars() self.task = MOSEK.env.Task() self.task.appendcons(self.numcons) self.task.appendvars(self.numvars) if self.msg: self.task.set_Stream(mosek.streamtype.log, self.setOutStream) # Adding variables for i in range(self.numvars): vname = self.vars[i].name self.var_dict[vname] = i self.task.putvarname(i, vname) # Variable type (Default: Continuous) if self.mip & (self.vars[i].cat == constants.LpInteger): self.task.putvartype(i, mosek.variabletype.type_int) self.solution_type = mosek.soltype.itg # Variable bounds vbkey = mosek.boundkey.fr vup = inf vlow = -inf if self.vars[i].lowBound != None: vlow = self.vars[i].lowBound if self.vars[i].upBound != None: vup = self.vars[i].upBound vbkey = mosek.boundkey.ra else: vbkey = mosek.boundkey.lo elif self.vars[i].upBound != None: vup = self.vars[i].upBound vbkey = mosek.boundkey.up self.task.putvarbound(i, vbkey, vlow, vup) # Objective coefficient for the current variable. self.task.putcj(i, lp.objective.get(self.vars[i], 0.0)) # Coefficient matrix self.A_rows, self.A_cols, self.A_vals = zip( *[ [self.cons_dict[row], self.var_dict[col], coeff] for col, row, coeff in lp.coefficients() ] ) self.task.putaijlist(self.A_rows, self.A_cols, self.A_vals) # Constraints self.constraint_data_list = [] for c in self.cons: cname = self.cons[c].name if cname != None: self.task.putconname(self.cons_dict[c], cname) else: self.task.putconname(self.cons_dict[c], c) csense = self.cons[c].sense cconst = -self.cons[c].constant clow = -inf cup = inf # Constraint bounds if csense == constants.LpConstraintEQ: cbkey = mosek.boundkey.fx clow = cconst cup = cconst elif csense == constants.LpConstraintGE: cbkey = mosek.boundkey.lo clow = cconst elif csense == constants.LpConstraintLE: cbkey = mosek.boundkey.up cup = cconst else: raise PulpSolverError("Invalid constraint type.") self.constraint_data_list.append([self.cons_dict[c], cbkey, clow, cup]) self.cons_id_list, self.cbkey_list, self.clow_list, self.cup_list = zip( *self.constraint_data_list ) self.task.putconboundlist( self.cons_id_list, self.cbkey_list, self.clow_list, self.cup_list ) # Objective sense if lp.sense == constants.LpMaximize: self.task.putobjsense(mosek.objsense.maximize) else: self.task.putobjsense(mosek.objsense.minimize) def findSolutionValues(self, lp): """ Read the solution values and status from the Mosek task object. Note: Since the status map from mosek.solsta to LpStatus is not exact, it is recommended that one enables the log output and then refer to Mosek documentation for a better understanding of the solution (especially in the case of mip problems). """ self.solsta = self.task.getsolsta(self.solution_type) self.solution_status_dict = { mosek.solsta.optimal: constants.LpStatusOptimal, mosek.solsta.prim_infeas_cer: constants.LpStatusInfeasible, mosek.solsta.dual_infeas_cer: constants.LpStatusUnbounded, mosek.solsta.unknown: constants.LpStatusUndefined, mosek.solsta.integer_optimal: constants.LpStatusOptimal, mosek.solsta.prim_illposed_cer: constants.LpStatusNotSolved, mosek.solsta.dual_illposed_cer: constants.LpStatusNotSolved, mosek.solsta.prim_feas: constants.LpStatusNotSolved, mosek.solsta.dual_feas: constants.LpStatusNotSolved, mosek.solsta.prim_and_dual_feas: constants.LpStatusNotSolved, } # Variable values. try: self.xx = [0.0] * self.numvars self.task.getxx(self.solution_type, self.xx) for var in lp.variables(): var.varValue = self.xx[self.var_dict[var.name]] except mosek.Error: pass # Constraint slack variables. try: self.xc = [0.0] * self.numcons self.task.getxc(self.solution_type, self.xc) for con in lp.constraints: lp.constraints[con].slack = -( self.cons[con].constant + self.xc[self.cons_dict[con]] ) except mosek.Error: pass # Reduced costs. if self.solution_type != mosek.soltype.itg: try: self.x_rc = [0.0] * self.numvars self.task.getreducedcosts( self.solution_type, 0, self.numvars, self.x_rc ) for var in lp.variables(): var.dj = self.x_rc[self.var_dict[var.name]] except mosek.Error: pass # Constraint Pi variables. try: self.y = [0.0] * self.numcons self.task.gety(self.solution_type, self.y) for con in lp.constraints: lp.constraints[con].pi = self.y[self.cons_dict[con]] except mosek.Error: pass def putparam(self, par, val): """ Pass the values of valid parameters to Mosek. """ if isinstance(par, mosek.dparam): self.task.putdouparam(par, val) elif isinstance(par, mosek.iparam): self.task.putintparam(par, val) elif isinstance(par, mosek.sparam): self.task.putstrparam(par, val) elif isinstance(par, str): if par.startswith("MSK_DPAR_"): self.task.putnadouparam(par, val) elif par.startswith("MSK_IPAR_"): self.task.putnaintparam(par, val) elif par.startswith("MSK_SPAR_"): self.task.putnastrparam(par, val) else: raise PulpSolverError( "Invalid MOSEK parameter: '{}'. Check MOSEK documentation for a list of valid parameters.".format( par ) ) def actualSolve(self, lp): """ Solve a well-formulated lp problem. """ self.buildSolverModel(lp) # Set solver parameters for msk_par in self.options: self.putparam(msk_par, self.options[msk_par]) # Task file if self.task_file_name: self.task.writedata(self.task_file_name) # Optimize self.task.optimize() # Mosek solver log (default: standard output stream) if self.msg: self.task.solutionsummary(mosek.streamtype.msg) self.findSolutionValues(lp) lp.assignStatus(self.solution_status_dict[self.solsta]) for var in lp.variables(): var.modified = False for con in lp.constraints.values(): con.modified = False return lp.status def actualResolve(self, lp, inf=1e20, **kwargs): """ Modify constraints and re-solve an lp. The Mosek task object created in the first solve is used. """ for c in self.cons: if self.cons[c].modified: csense = self.cons[c].sense cconst = -self.cons[c].constant clow = -inf cup = inf # Constraint bounds if csense == constants.LpConstraintEQ: cbkey = mosek.boundkey.fx clow = cconst cup = cconst elif csense == constants.LpConstraintGE: cbkey = mosek.boundkey.lo clow = cconst elif csense == constants.LpConstraintLE: cbkey = mosek.boundkey.up cup = cconst else: raise PulpSolverError("Invalid constraint type.") self.task.putconbound(self.cons_dict[c], cbkey, clow, cup) # Re-solve self.task.optimize() self.findSolutionValues(lp) lp.assignStatus(self.solution_status_dict[self.solsta]) for var in lp.variables(): var.modified = False for con in lp.constraints.values(): con.modified = False return lp.status
def solve(self, p): # Get problem dimensions n = p.P.shape[0] m = p.A.shape[0] ''' Load problem ''' # Create environment env = mosek.Env() # Create optimization task task = env.Task() if self.options['verbose']: # Define a stream printer to grab output from MOSEK def streamprinter(text): import sys sys.stdout.write(text) sys.stdout.flush() env.set_Stream(mosek.streamtype.log, streamprinter) task.set_Stream(mosek.streamtype.log, streamprinter) # Load problem into task object # Append 'm' empty constraints. # The constraints will initially have no bounds. task.appendcons(m) # Append 'n' variables. # The variables will initially be fixed at zero (x=0). task.appendvars(n) # Add linear cost by iterating over all variables for j in range(n): task.putcj(j, p.q[j]) task.putvarbound(j, mosek.boundkey.fr, -np.inf, np.inf) # Constrain integer variables if present if p.i_idx is not None: int_types = [mosek.variabletype.type_int] * len(p.i_idx) int_idx = p.i_idx.tolist() task.putvartypelist(int_idx, int_types) for i in range(len(p.i_idx)): if p.i_l is None and p.i_u is not None: task.putvarbound(p.i_idx[i], mosek.boundkey.up, 0, p.i_u[i]) elif p.i_l is not None and p.i_u is None: task.putvarbound(p.i_idx[i], mosek.boundkey.lo, p.i_l[i], 0) elif p.i_l is not None and p.i_u is not None: task.putvarbound(p.i_idx[i], mosek.boundkey.ra, p.i_l[i], p.i_u[i]) # Add constraints if p.A is not None: row_A, col_A, el_A = spa.find(p.A) task.putaijlist(row_A, col_A, el_A) for j in range(m): # Get bounds and keys u_temp = p.u[j] if p.u[j] < 1e20 else np.inf l_temp = p.l[j] if p.l[j] > -1e20 else -np.inf # Divide 5 cases if (np.abs(l_temp - u_temp) < 1e-08): bound_key = mosek.boundkey.fx elif l_temp == -np.inf and u_temp == np.inf: bound_key = mosek.boundkey.fr elif l_temp != -np.inf and u_temp == np.inf: bound_key = mosek.boundkey.lo elif l_temp != -np.inf and u_temp != np.inf: bound_key = mosek.boundkey.ra elif l_temp == -np.inf and u_temp != np.inf: bound_key = mosek.boundkey.up # Add bound task.putconbound(j, bound_key, l_temp, u_temp) # Add quadratic cost if p.P.count_nonzero(): # If there are any nonzero elms in P P = spa.tril(p.P, format='coo') task.putqobj(P.row, P.col, P.data) # Set problem minimization task.putobjsense(mosek.objsense.minimize) ''' Set parameters ''' for param, value in self.options.items(): if param == 'verbose': if value is False: self._handle_str_param(task, 'MSK_IPAR_LOG'.strip(), 0) else: if isinstance(param, str): self._handle_str_param(task, param.strip(), value) else: self._handle_enum_param(task, param, value) ''' Solve problem ''' try: # Optimization and check termination code trmcode = task.optimize() except: if self.options['verbose']: print("Error in MOSEK solution\n") return QuadprogResults(qp.SOLVER_ERROR, None, None, None, np.inf, None) if self.options['verbose']: task.solutionsummary(mosek.streamtype.msg) ''' Extract results ''' # Get solution type and status soltype, solsta = self.choose_solution(task) # Map status using statusmap status = self.STATUS_MAP.get(solsta, qp.SOLVER_ERROR) # Get statistics cputime = task.getdouinf(mosek.dinfitem.optimizer_time) + \ task.getdouinf(mosek.dinfitem.presolve_time) total_iter = task.getintinf(mosek.iinfitem.intpnt_iter) if status in qp.SOLUTION_PRESENT: # get primal variables values sol = np.zeros(task.getnumvar()) task.getxx(soltype, sol) # get obj value objval = task.getprimalobj(soltype) # get dual if p.i_idx is None: dual = np.zeros(task.getnumcon()) task.gety(soltype, dual) # it appears signs are inverted dual = -dual else: dual = None return QuadprogResults(status, objval, sol, dual, cputime, total_iter) else: return QuadprogResults(status, None, None, None, cputime, None)
def get_safe_action(self, observation, action, environment): flag = True landmark_near = [] for i, landmark in enumerate(environment.world.landmarks[0:-1]): dist = np.sqrt(np.sum(np.square(environment.world.policy_agents[0].state.p_pos - landmark.state.p_pos))) \ - (environment.world.policy_agents[0].size + landmark.size) - 0.044 if dist <= 0: landmark_near.append(landmark) flag = False if flag: return action, False x = observation[1] y = observation[2] V = observation[0] theta = observation[3] omega = observation[4] # print(theta) d_omega = action[3] - action[4] dt = environment.world.dt a1 = x + V * np.cos(theta) * dt + theta * V * np.sin(theta) * dt b1 = -V * np.sin(theta) * dt a2 = y + V * np.sin(theta) * dt - theta * V * np.cos(theta) * dt b2 = V * np.cos(theta) * dt c1 = a1 + b1 * theta d1 = b1 * dt c2 = a2 + b2 * theta d2 = b2 * dt e1 = -2 * x * c1 f1 = -2 * x * d1 e2 = -2 * y * c2 f2 = -2 * y * d2 flag = True for _, landmark in enumerate(landmark_near): self.R = landmark.size + 0.5 * environment.world.policy_agents[ 0].size x0 = landmark.state.p_pos[0] y0 = landmark.state.p_pos[1] landmark0 = landmark g = d1 * d1 + d2 * d2 h = 2 * c1 * d1 + 2 * c2 * d2 + f1 + f2 i = c1 * c1 + c2 * c2 + e1 + e2 + np.square(landmark0.state.p_pos[0]) + \ np.square(landmark0.state.p_pos[1]) lower_c = np.square(landmark0.size + 0.01) upper_c = inf A = landmark0.state.p_pos[0] - x B = landmark0.state.p_pos[1] - y C = - (landmark0.state.p_pos[0]) * x \ + np.square(x) \ - (landmark0.state.p_pos[1]) * y \ + np.square(y) # solve x3 self.x0 = np.array([x, y]) self.x1 = np.array([x0, y0]) args = [ np.square(self.x1[1] - self.x0[1]) + np.square(self.x1[0] - self.x0[0]), 2 * (self.x1[1] - self.x0[1]) * np.square(self.R), np.square(np.square(self.R)) - np.square(self.R) * np.square(self.x1[0] - self.x0[0]) ] root = np.roots(args) y3_0 = root[0] + self.x1[1] y3_1 = root[1] + self.x1[1] x3_0 = (-(y3_0 - self.x1[1]) * (self.x1[1] - self.x0[1]) - np.square(self.R))/(self.x1[0] - self.x0[0]) + \ self.x1[0] x3_1 = (-(y3_1 - self.x1[1]) * (self.x1[1] - self.x0[1]) - np.square(self.R)) / (self.x1[0] - self.x0[0]) + \ self.x1[0] x3 = np.array([x3_0, y3_0]) temp1 = ((y - y0) * c1 - (x - x0) * c2 - y * x0 + y0 * x) \ * ((y - y0) * x3[0] - (x - x0) * x3[1] - y * x0 + y0 * x) x3 = np.array([x3_1, y3_1]) x3 = np.array([x3_0, y3_0]) if temp1 > 0 else np.array( [x3_1, y3_1]) x3[0] = 1.1 * x3[0] - 0.1 * self.x1[0] x3[1] = 1.1 * x3[1] - 0.1 * self.x1[1] '''print(((y - y0) * c1 - (x - x0) * d1 - y * x0 + y0 * x) * ((y - y0) * x3[0] - (x - x0) * x3[1] - y * x0 + y0 * x)) print((x3[0] - self.x0[0]) * (x3[0] - self.x1[0]) + (x3[1] - self.x0[1]) * (x3[1] - self.x1[1])) print((x3[0] - self.x1[0]) * (x3[0] - self.x1[0]) + (x3[1] - self.x1[1]) * (x3[1] - self.x1[1]) - self.R * self.R)''' temp2 = ((x3[1] - self.x0[1]) * self.x1[0] - (x3[0] - self.x0[0]) * self.x1[1] + self.x0[1] * x3[0] - self.x0[0] * x3[1]) \ * ((x3[1] - self.x0[1]) * c1 - (x3[0] - self.x0[0]) * c2 + self.x0[1] * x3[0] - self.x0[0] * x3[1]) k1 = temp2 * (x3[1] - self.x0[1]) k2 = temp2 * (x3[0] - self.x0[0]) k3 = temp2 * (self.x0[1] * x3[0] - self.x0[0] * x3[1]) dist = np.sqrt(np.sum(np.square(environment.world.landmarks[-1].state.p_pos - landmark.state.p_pos))) \ - (environment.world.landmarks[-1].size + 1.2 * landmark.size) if temp2 > 0: flag = False break if flag: return action, False self.num_call = self.num_call + 1 # Make a MOSEK environment with mosek.Env() as env: # Attach a printer to the environment # env.set_Stream(mosek.streamtype.log, streamprinter) # Create a task with env.Task(0, 0) as task: # task.set_Stream(mosek.streamtype.log, streamprinter) # Set up and input bounds and linear coefficients bkc = [mosek.boundkey.up] blc = [-inf] buc = [-k3 - k1 * c1 + k2 * c2] numvar = 1 bkx = [mosek.boundkey.fr] * numvar blx = [-inf] * numvar bux = [inf] * numvar temp = 0.12 c = [-2.0 * omega - 2 * dt * d_omega] asub = [[0]] aval = [[k1 * d1 - k2 * d2]] numvar = len(bkx) numcon = len(bkc) # Append 'numcon' empty constraints. # The constraints will initially have no bounds. task.appendcons(numcon) # Append 'numvar' variables. # The variables will initially be fixed at zero (x=0). task.appendvars(numvar) for j in range(numvar): # Set the linear term c_j in the objective. task.putcj(j, c[j]) # Set the bounds on variable j # blx[j] <= x_j <= bux[j] task.putvarbound(j, bkx[j], blx[j], bux[j]) # Input column j of A task.putacol( j, # Variable (column) index. # Row index of non-zeros in column j. asub[j], aval[j]) # Non-zero Values of column j. for i in range(numcon): task.putconbound(i, bkc[i], blc[i], buc[i]) # Set up and input quadratic objective qsubi = [0] qsubj = [0] qval = [2.0] task.putqobj(qsubi, qsubj, qval) # Input the objective sense (minimize/maximize) task.putobjsense(mosek.objsense.minimize) # Optimize task.optimize() # Print a summary containing information # about the solution for debugging purposes # task.solutionsummary(mosek.streamtype.msg) prosta = task.getprosta(mosek.soltype.itr) solsta = task.getsolsta(mosek.soltype.itr) # Output a solution xx = [0.] * numvar task.getxx(mosek.soltype.itr, xx) '''if solsta == mosek.solsta.optimal: print("Optimal solution: %s" % xx) elif solsta == mosek.solsta.dual_infeas_cer: print("Primal or dual infeasibility.\n") elif solsta == mosek.solsta.prim_infeas_cer: print("Primal or dual infeasibility.\n") elif mosek.solsta.unknown: print("Unknown solution status") else: print("Other solution status")''' xx = (xx[0] - omega) / dt if xx > temp: xx = temp if xx < -temp: xx = -temp if np.abs(xx / 0.12 - d_omega) < 0.02: return action, False delta_action = xx / 0.12 - d_omega action[3] = action[3] + delta_action / 2 action[4] = action[4] - delta_action / 2 # temp = action[3] - action[4] '''action[3] = + xx[0]/2 action[4] = - xx[0]/2''' return action, True
def dualSDP(self,d,presolveTol=1.0e-30,split=False,outputFlag=False): dat, mrsp, srsp, numPnt = self.checkIfSplit() # Make mosek environment with mosek.Env() as env: # Create a task object and attach log stream printer with env.Task(0,0) as task: task.putdouparam(mosek.dparam.presolve_tol_x,presolveTol) if outputFlag: task.set_Stream(mosek.streamtype.msg, streamprinter) c = [srsp[i]/sum(srsp)+(1-srsp[i])/sum(1-srsp) for i in range(numPnt)] M = self.M # Bound keys for constraints bkc = [mosek.boundkey.lo]*(3*numPnt) + [mosek.boundkey.ra, mosek.boundkey.fx, mosek.boundkey.fx] # Bound values for constraints blc = [1.0]*numPnt + c + [0.0]*numPnt + [-d, 0.0, 1.0] buc = [+math.inf]*(3*numPnt) + [d, 0.0, 1.0] # Below is the sparse representation of the A # matrix stored by row. asub = [[2*numPnt+i] for i in range(numPnt)] + [[numPnt+i] for i in range(numPnt)]\ + [[i] for i in range(numPnt)] + [list(range(2*numPnt)), [], []] aval = [[1.0]]*(3*numPnt) + [[M]*numPnt + [1.0]*numPnt, [], []] barci = list(range(self.numFields)) barcj = list(range(self.numFields)) barcval = [1.0]*self.numFields barai = [[self.numFields+numPnt]*self.numFields]*numPnt + [[self.numFields+numPnt]]*(2*numPnt)\ + [[self.numFields+i for i in range(numPnt) for j in range(self.numFields)], [self.numFields+numPnt]*numPnt, [self.numFields+numPnt]] baraj = [list(range(self.numFields))]*numPnt + [[self.numFields+i] for i in range(numPnt)]*2\ + [[j for i in range(numPnt) for j in range(self.numFields)], [self.numFields+i for i in range(numPnt)], [self.numFields+numPnt]] baraval = [list(0.5*mrsp[i]*dat[i]) for i in range(numPnt)] + [[0.5*M]]*numPnt + [[-0.5]]*numPnt\ + [[0.5*dat[i,j] for i in range(numPnt) for j in range(self.numFields)], [0.5]*numPnt, [1.0]] numvar = 3*numPnt numcon = len(bkc) BARVARDIM = [self.numFields+numPnt+1] # Append 'numvar' variables. # The variables will initially be fixed at zero (x=0). task.appendvars(numvar) # Append 'numcon' empty constraints. # The constraints will initially have no bounds. task.appendcons(numcon) # Append matrix variables of sizes in 'BARVARDIM'. # The variables will initially be fixed at zero. task.appendbarvars(BARVARDIM) # Set the linear term c_0 in the objective. task.putclist([2*numPnt+i for i in range(numPnt)], [1.0]*numPnt) symc = task.appendsparsesymmat(BARVARDIM[0], barci, barcj, barcval) task.putbarcj(0, [symc], [1.0]) for j in range(numvar): # Set the bounds on variable j # blx[j] <= x_j <= bux[j] task.putvarbound(j, mosek.boundkey.lo, 0, +math.inf) syma = [] for i in range(numcon): # Set the bounds on constraints. task.putconbound(i, bkc[i], blc[i], buc[i]) # Input row i of A task.putarow(i, asub[i], aval[i]) # add coefficient matrix of PSD variables syma.append(task.appendsparsesymmat(BARVARDIM[0], barai[i], baraj[i], baraval[i])) task.putbaraij(i, 0, [syma[i]], [1.0]) # Input the objective sense (minimize/maximize) task.putobjsense(mosek.objsense.minimize) # Solve the problem and print summary task.optimize() task.solutionsummary(mosek.streamtype.msg) # Get status information about the solution prosta = task.getprosta(mosek.soltype.itr) solsta = task.getsolsta(mosek.soltype.itr) if (solsta == mosek.solsta.optimal or solsta == mosek.solsta.near_optimal): xx = [0.]*numvar task.getxx(mosek.soltype.itr, xx) lenbarvar = BARVARDIM[0] * (BARVARDIM[0]+1) / 2 barx = [0.]*int(lenbarvar) task.getbarxj(mosek.soltype.itr, 0, barx) barxx = [barx[(self.numFields+numPnt+1)*(i+1)-1-sum(list(range(i+1)))]\ for i in range(self.numFields+numPnt)] alpha = xx[:numPnt] beta = np.array(barxx[:self.numFields]).reshape((self.numFields,1)) gamma = barxx[-numPnt:] lam = xx[numPnt:2*numPnt] eps = xx[-numPnt:] Gamma21 = np.array([[barx[self.numFields+i+(self.numFields+numPnt+1)*j-sum(list(range(j+1)))]\ for j in range(self.numFields)] for i in range(numPnt)]) time = task.getdouinf(mosek.dinfitem.optimizer_time) print("Optimal solution = %s\nruntime = %s seconds" % (beta.T.dot(beta)[0,0]+sum(eps),time)) return beta, alpha, gamma, lam, eps, Gamma21 elif (solsta == mosek.solsta.dual_infeas_cer or solsta == mosek.solsta.prim_infeas_cer or solsta == mosek.solsta.near_dual_infeas_cer or solsta == mosek.solsta.near_prim_infeas_cer): print("Primal or dual infeasibility certificate found.\n") return None, None, None, None, None, None elif solsta == mosek.solsta.unknown: print("Unknown solution status") return None, None, None, None, None, None else: print("Other solution status") return None, None, None, None, None, None
def mosek_intf(A, b, G, h, c, dims, offset, solver_opts, verbose = False): data = {s.A : A, s.B : b, s.G : G, s.H : h, s.C : c, s.OFFSET : offset, s.DIMS : dims} with mosek.Env() as env: with env.Task(0, 0) as task: kwargs = sorted(solver_opts.keys()) if "mosek_params" in kwargs: self._handle_mosek_params(task, solver_opts["mosek_params"]) kwargs.remove("mosek_params") if kwargs: raise ValueError("Invalid keyword-argument '%s'" % kwargs[0]) if verbose: # Define a stream printer to grab output from MOSEK def streamprinter(text): import sys sys.stdout.write(text) sys.stdout.flush() env.set_Stream(mosek.streamtype.log, streamprinter) task.set_Stream(mosek.streamtype.log, streamprinter) # size of problem numvar = len(c) + sum(dims[s.SOC_DIM]) numcon = len(b) + dims[s.LEQ_DIM] + sum(dims[s.SOC_DIM]) + \ sum([el**2 for el in dims[s.SDP_DIM]]) # otherwise it crashes on empty probl. if numvar == 0: result_dict = {s.STATUS: s.OPTIMAL} result_dict[s.PRIMAL] = [] result_dict[s.VALUE] = 0. + data[s.OFFSET] result_dict[s.EQ_DUAL] = [] result_dict[s.INEQ_DUAL] = [] return result_dict # objective task.appendvars(numvar) task.putclist(np.arange(len(c)), c) task.putvarboundlist(np.arange(numvar, dtype=int), [mosek.boundkey.fr]*numvar, np.zeros(numvar), np.zeros(numvar)) # SDP variables if sum(dims[s.SDP_DIM]) > 0: task.appendbarvars(dims[s.SDP_DIM]) # linear equality and linear inequality constraints task.appendcons(numcon) if A.shape[0] and G.shape[0]: constraints_matrix = sp.bmat([[A], [G]]) else: constraints_matrix = A if A.shape[0] else G coefficients = np.concatenate([b, h]) row, col, el = sp.find(constraints_matrix) task.putaijlist(row, col, el) type_constraint = [mosek.boundkey.fx] * len(b) type_constraint += [mosek.boundkey.up] * dims[s.LEQ_DIM] sdp_total_dims = sum([cdim**2 for cdim in dims[s.SDP_DIM]]) type_constraint += [mosek.boundkey.fx] * \ (sum(dims[s.SOC_DIM]) + sdp_total_dims) task.putconboundlist(np.arange(numcon, dtype=int), type_constraint, coefficients, coefficients) # cones current_var_index = len(c) current_con_index = len(b) + dims[s.LEQ_DIM] for size_cone in dims[s.SOC_DIM]: row, col, el = sp.find(sp.eye(size_cone)) row += current_con_index col += current_var_index task.putaijlist(row, col, el) # add a identity for each cone # add a cone constraint task.appendcone(mosek.conetype.quad, 0.0, # unused np.arange(current_var_index, current_var_index + size_cone)) current_con_index += size_cone current_var_index += size_cone # SDP for num_sdp_var, size_matrix in enumerate(dims[s.SDP_DIM]): for i_sdp_matrix in range(size_matrix): for j_sdp_matrix in range(size_matrix): coeff = 1. if i_sdp_matrix == j_sdp_matrix else .5 task.putbaraij(current_con_index, num_sdp_var, [task.appendsparsesymmat(size_matrix, [max(i_sdp_matrix, j_sdp_matrix)], [min(i_sdp_matrix, j_sdp_matrix)], [coeff])], [1.0]) current_con_index += 1 # solve task.putobjsense(mosek.objsense.minimize) task.optimize() if verbose: task.solutionsummary(mosek.streamtype.msg) return format_results(task, data)
def lp(c, G, h, A=None, b=None, taskfile=None): """ Solves a pair of primal and dual LPs minimize c'*x maximize -h'*z - b'*y subject to G*x + s = h subject to G'*z + A'*y + c = 0 A*x = b z >= 0. s >= 0 using MOSEK 8.0. (solsta, x, z, y) = lp(c, G, h, A=None, b=None). Input arguments c is n x 1, G is m x n, h is m x 1, A is p x n, b is p x 1. G and A must be dense or sparse 'd' matrices. c, h and b are dense 'd' matrices with one column. The default values for A and b are empty matrices with zero rows. Optionally, the interface can write a .task file, required for support questions on the MOSEK solver. Return values solsta is a MOSEK solution status key. If solsta is mosek.solsta.optimal, then (x, y, z) contains the primal-dual solution. If solsta is mosek.solsta.prim_infeas_cer, then (x, y, z) is a certificate of primal infeasibility. If solsta is mosek.solsta.dual_infeas_cer, then (x, y, z) is a certificate of dual infeasibility. If solsta is mosek.solsta.unknown, then (x, y, z) are all None. Other return values for solsta include: mosek.solsta.dual_feas mosek.solsta.near_dual_feas mosek.solsta.near_optimal mosek.solsta.near_prim_and_dual_feas mosek.solsta.near_prim_feas mosek.solsta.prim_and_dual_feas mosek.solsta.prim_feas in which case the (x,y,z) value may not be well-defined. x, y, z the primal-dual solution. Options are passed to MOSEK solvers via the msk.options dictionary. For example, the following turns off output from the MOSEK solvers >>> msk.options = {mosek.iparam.log: 0} see the MOSEK Python API manual. """ with mosek.Env() as env: if type(c) is not matrix or c.typecode != 'd' or c.size[1] != 1: raise TypeError("'c' must be a dense column matrix") n = c.size[0] if n < 1: raise ValueError("number of variables must be at least 1") if (type(G) is not matrix and type(G) is not spmatrix) or \ G.typecode != 'd' or G.size[1] != n: raise TypeError("'G' must be a dense or sparse 'd' matrix "\ "with %d columns" %n) m = G.size[0] if m is 0: raise ValueError("m cannot be 0") if type(h) is not matrix or h.typecode != 'd' or h.size != (m, 1): raise TypeError("'h' must be a 'd' matrix of size (%d,1)" % m) if A is None: A = spmatrix([], [], [], (0, n), 'd') if (type(A) is not matrix and type(A) is not spmatrix) or \ A.typecode != 'd' or A.size[1] != n: raise TypeError("'A' must be a dense or sparse 'd' matrix "\ "with %d columns" %n) p = A.size[0] if b is None: b = matrix(0.0, (0, 1)) if type(b) is not matrix or b.typecode != 'd' or b.size != (p, 1): raise TypeError("'b' must be a dense matrix of size (%d,1)" % p) bkc = m * [mosek.boundkey.up] + p * [mosek.boundkey.fx] blc = m * [-inf] + [bi for bi in b] buc = list(h) + list(b) bkx = n * [mosek.boundkey.fr] blx = n * [-inf] bux = n * [+inf] colptr, asub, acof = sparse([G, A]).CCS aptrb, aptre = colptr[:-1], colptr[1:] with env.Task(0, 0) as task: task.set_Stream(mosek.streamtype.log, streamprinter) # set MOSEK options for (param, val) in options.items(): if str(param)[:6] == "iparam": task.putintparam(param, val) elif str(param)[:6] == "dparam": task.putdouparam(param, val) elif str(param)[:6] == "sparam": task.putstrparam(param, val) else: raise ValueError("invalid MOSEK parameter: " + str(param)) task.inputdata( m + p, # number of constraints n, # number of variables list(c), # linear objective coefficients 0.0, # objective fixed value list(aptrb), list(aptre), list(asub), list(acof), bkc, blc, buc, bkx, blx, bux) task.putobjsense(mosek.objsense.minimize) if taskfile: task.writetask(taskfile) task.optimize() task.solutionsummary(mosek.streamtype.msg) solsta = task.getsolsta(mosek.soltype.bas) x, z = n * [0.0], m * [0.0] task.getsolutionslice(mosek.soltype.bas, mosek.solitem.xx, 0, n, x) task.getsolutionslice(mosek.soltype.bas, mosek.solitem.suc, 0, m, z) x, z = matrix(x), matrix(z) if p is not 0: yu, yl = p * [0.0], p * [0.0] task.getsolutionslice(mosek.soltype.bas, mosek.solitem.suc, m, m + p, yu) task.getsolutionslice(mosek.soltype.bas, mosek.solitem.slc, m, m + p, yl) y = matrix(yu) - matrix(yl) else: y = matrix(0.0, (0, 1)) if (solsta is mosek.solsta.unknown): return (solsta, None, None, None) else: return (solsta, x, z, y)
def main(): # Create a MOSEK environment with mosek.Env() as env: # Create a task with env.Task(0, 0) as task: # Bound keys for constraints bkc = [mosek.boundkey.up, mosek.boundkey.up, mosek.boundkey.up] # Bound values for constraints blc = [-inf, -inf, -inf] buc = [100000.0, 50000.0, 60000.0] # Bound keys for variables bkx = [mosek.boundkey.lo, mosek.boundkey.lo, mosek.boundkey.lo] # Bound values for variables blx = [0.0, 0.0, 0.0] bux = [+inf, +inf, +inf] # Objective coefficients csub = [0, 1, 2] cval = [1.5, 2.5, 3.0] # We input the A matrix column-wise # asub contains row indexes asub = [0, 1, 2, 0, 1, 2, 0, 1, 2] # acof contains coefficients acof = [2.0, 3.0, 2.0, 4.0, 2.0, 3.0, 3.0, 3.0, 2.0] # aptrb and aptre contains the offsets into asub and acof where # columns start and end respectively aptrb = [0, 3, 6] aptre = [3, 6, 9] numvar = len(bkx) numcon = len(bkc) # Append the constraints task.appendcons(numcon) # Append the variables. task.appendvars(numvar) # Input objective task.putcfix(0.0) task.putclist(csub, cval) # Put constraint bounds task.putconboundslice(0, numcon, bkc, blc, buc) # Put variable bounds task.putvarboundslice(0, numvar, bkx, blx, bux) # Input A non-zeros by columns for j in range(numvar): ptrb, ptre = aptrb[j], aptre[j] task.putacol(j, asub[ptrb:ptre], acof[ptrb:ptre]) # Input the objective sense (minimize/maximize) task.putobjsense(mosek.objsense.maximize) # Optimize the task task.optimize() # Output a solution xx = [0.] * numvar task.getsolutionslice(mosek.soltype.bas, mosek.solitem.xx, 0, numvar, xx) print("xx = {}".format(xx)) ################# Make a change to the A matrix ############# task.putaij(0, 0, 3.0) task.optimize() # Output a solution xx = [0.] * numvar task.getsolutionslice(mosek.soltype.bas, mosek.solitem.xx, 0, numvar, xx) print("xx = {}".format(xx)) ################### Add a new variable ###################### task.appendvars(1) numvar+=1 # Set bounds on new varaible task.putbound(mosek.accmode.var, task.getnumvar() - 1, mosek.boundkey.lo, 0, +inf) # Change objective task.putcj(task.getnumvar() - 1, 1.0) # Put new values in the A matrix acolsub = [0, 2] acolval = [4.0, 1.0] task.putacol(task.getnumvar() - 1, # column index acolsub, acolval) # Change optimizer to simplex free and reoptimize task.putintparam(mosek.iparam.optimizer, mosek.optimizertype.free_simplex) task.optimize() # Output a solution xx = [0.] * numvar task.getsolutionslice(mosek.soltype.bas, mosek.solitem.xx, 0, numvar, xx) print("xx = {}".format(xx)) ############# Add a new constraint ####################### task.appendcons(1) numcon+=1 # Set bounds on new constraint task.putconbound(task.getnumcon() - 1, mosek.boundkey.up, -inf, 30000) # Put new values in the A matrix arowsub = [0, 1, 2, 3] arowval = [1.0, 2.0, 1.0, 1.0] task.putarow(task.getnumcon() - 1, # row index arowsub, arowval) task.optimize() # Output a solution xx = [0.] * numvar task.getsolutionslice(mosek.soltype.bas, mosek.solitem.xx, 0, numvar, xx) print("xx = {}".format(xx))
def socp(c, Gl=None, hl=None, Gq=None, hq=None, taskfile=None): """ Solves a pair of primal and dual SOCPs minimize c'*x subject to Gl*x + sl = hl Gq[k]*x + sq[k] = hq[k], k = 0, ..., N-1 sl >= 0, sq[k] >= 0, k = 0, ..., N-1 maximize -hl'*zl - sum_k hq[k]'*zq[k] subject to Gl'*zl + sum_k Gq[k]'*zq[k] + c = 0 zl >= 0, zq[k] >= 0, k = 0, ..., N-1. using MOSEK 8.0. solsta, x, zl, zq = socp(c, Gl = None, hl = None, Gq = None, hq = None, taskfile=None) Return values solsta is a MOSEK solution status key. If solsta is mosek.solsta.optimal, then (x, zl, zq) contains the primal-dual solution. If solsta is mosek.solsta.prim_infeas_cer, then (x, zl, zq) is a certificate of dual infeasibility. If solsta is mosek.solsta.dual_infeas_cer, then (x, zl, zq) is a certificate of primal infeasibility. If solsta is mosek.solsta.unknown, then (x, zl, zq) are all None Other return values for solsta include: mosek.solsta.dual_feas mosek.solsta.near_dual_feas mosek.solsta.near_optimal mosek.solsta.near_prim_and_dual_feas mosek.solsta.near_prim_feas mosek.solsta.prim_and_dual_feas mosek.solsta.prim_feas in which case the (x,y,z) value may not be well-defined. x, zl, zq the primal-dual solution. Options are passed to MOSEK solvers via the msk.options dictionary, e.g., the following turns off output from the MOSEK solvers >>> msk.options = {mosek.iparam.log: 0} see the MOSEK Python API manual. Optionally, the interface can write a .task file, required for support questions on the MOSEK solver. """ with mosek.Env() as env: if type(c) is not matrix or c.typecode != 'd' or c.size[1] != 1: raise TypeError("'c' must be a dense column matrix") n = c.size[0] if n < 1: raise ValueError("number of variables must be at least 1") if Gl is None: Gl = spmatrix([], [], [], (0, n), tc='d') if (type(Gl) is not matrix and type(Gl) is not spmatrix) or \ Gl.typecode != 'd' or Gl.size[1] != n: raise TypeError("'Gl' must be a dense or sparse 'd' matrix "\ "with %d columns" %n) ml = Gl.size[0] if hl is None: hl = matrix(0.0, (0, 1)) if type(hl) is not matrix or hl.typecode != 'd' or \ hl.size != (ml,1): raise TypeError("'hl' must be a dense 'd' matrix of " \ "size (%d,1)" %ml) if Gq is None: Gq = [] if type(Gq) is not list or [ G for G in Gq if (type(G) is not matrix and type(G) is not spmatrix) or G.typecode != 'd' or G.size[1] != n ]: raise TypeError("'Gq' must be a list of sparse or dense 'd' "\ "matrices with %d columns" %n) mq = [G.size[0] for G in Gq] a = [k for k in range(len(mq)) if mq[k] == 0] if a: raise TypeError("the number of rows of Gq[%d] is zero" % a[0]) if hq is None: hq = [] if type(hq) is not list or len(hq) != len(mq) or [ h for h in hq if (type(h) is not matrix and type(h) is not spmatrix) or h.typecode != 'd' ]: raise TypeError("'hq' must be a list of %d dense or sparse "\ "'d' matrices" %len(mq)) a = [k for k in range(len(mq)) if hq[k].size != (mq[k], 1)] if a: k = a[0] raise TypeError("'hq[%d]' has size (%d,%d). Expected size "\ "is (%d,1)." %(k, hq[k].size[0], hq[k].size[1], mq[k])) N = ml + sum(mq) h = matrix(0.0, (N, 1)) if type(Gl) is matrix or [Gk for Gk in Gq if type(Gk) is matrix]: G = matrix(0.0, (N, n)) else: G = spmatrix([], [], [], (N, n), 'd') h[:ml] = hl G[:ml, :] = Gl ind = ml for k in range(len(mq)): h[ind:ind + mq[k]] = hq[k] G[ind:ind + mq[k], :] = Gq[k] ind += mq[k] bkc = n * [mosek.boundkey.fx] blc = list(-c) buc = list(-c) bkx = ml * [mosek.boundkey.lo] + sum(mq) * [mosek.boundkey.fr] blx = ml * [0.0] + sum(mq) * [-inf] bux = N * [+inf] c = -h colptr, asub, acof = sparse([G.T]).CCS aptrb, aptre = colptr[:-1], colptr[1:] with env.Task(0, 0) as task: task.set_Stream(mosek.streamtype.log, streamprinter) # set MOSEK options for (param, val) in options.items(): if str(param)[:6] == "iparam": task.putintparam(param, val) elif str(param)[:6] == "dparam": task.putdouparam(param, val) elif str(param)[:6] == "sparam": task.putstrparam(param, val) else: raise ValueError("invalid MOSEK parameter: " + str(param)) task.inputdata( n, # number of constraints N, # number of variables list(c), # linear objective coefficients 0.0, # objective fixed value list(aptrb), list(aptre), list(asub), list(acof), bkc, blc, buc, bkx, blx, bux) task.putobjsense(mosek.objsense.maximize) for k in range(len(mq)): task.appendcone( mosek.conetype.quad, 0.0, list(range(ml + sum(mq[:k]), ml + sum(mq[:k + 1])))) if taskfile: task.writetask(taskfile) task.optimize() task.solutionsummary(mosek.streamtype.msg) solsta = task.getsolsta(mosek.soltype.itr) xu, xl, zq = n * [0.0], n * [0.0], sum(mq) * [0.0] task.getsolutionslice(mosek.soltype.itr, mosek.solitem.slc, 0, n, xl) task.getsolutionslice(mosek.soltype.itr, mosek.solitem.suc, 0, n, xu) task.getsolutionslice(mosek.soltype.itr, mosek.solitem.xx, ml, N, zq) x = matrix(xu) - matrix(xl) zq = [ matrix(zq[sum(mq[:k]):sum(mq[:k + 1])]) for k in range(len(mq)) ] if ml: zl = ml * [0.0] task.getsolutionslice(mosek.soltype.itr, mosek.solitem.xx, 0, ml, zl) zl = matrix(zl) else: zl = matrix(0.0, (0, 1)) if (solsta is mosek.solsta.unknown): return (solsta, None, None, None) else: return (solsta, x, zl, zq)
def busOpt(userGraph, busMax, time): ''' Using quadratic optimiaxation with integer objectives, this function returns a good estimate for any bus. Params: userGraph - This is the graph of the remaining students. we dont know how many exist however there must be at least one or it WILL return an error busMax - Caculated beforehand, it should either be the size of the bus, or how many students could be put on the bus such that a feasable solution still exists. Used as a constraint on the objective time - This is so larger sets can be calcualted in a more feasable amount of space. puts constraints on the solver so it does not take to long. ''' ''' create a mapping for the nodes of the bus so calculations are a bit less intense each time ''' #maps each to a specific num mapping = dict(zip(userGraph.nodes(),list(range(nx.number_of_nodes(userGraph))))) #reversMap is for the return value. reverseMap = dict(zip(list(range(nx.number_of_nodes(userGraph))),userGraph.nodes())) #copies and does not modify inputs G = nx.relabel_nodes(userGraph,mapping, copy=True) H = np.array(nx.to_numpy_matrix(G)) n = len(H) for i in range(n): H[i][i] = -n*2 with mosek.Env() as env: # Attach a printer to the environment #env.set_Stream(mosek.streamtype.log, streamprinter) # Create a task object with env.Task() as task: # Attach a log stream printer to the task #task.set_Stream (mosek.streamtype.log, streamprinter) # numvar is equal to n in the nxn matrix H numvar = n ''' For each bound, we need to define it in the array. each begins with mosek.boundkey.(insert postfix here) the endings are as follows: ra -- at position i in the array if ra is the postfix, than blc[i] <= Ax[i] <= buc[i] fx -- at position i in the array if fx is the postfix, than Ax[i] = blc[i] fr -- at position i in the array if fr is the postfix, than -inf <= Ax[i] <= inf lo -- at position i in the array if fr is the postfix, than blc[i] <= Ax[i] <= inf up -- at position i in the array if fr is the postfix, than -inf <= Ax[i] <= buc[i] Note that we define A later. In the following case A is a 1xn matrix with lowerbound 1.0 and upperbound 5.0 ''' bkc = [mosek.boundkey.ra] blc = [1.0] #At least 1 kid on the bus buc = [busMax] #bus size ''' This is where the matrix A is created, it must follow the constriants in order as provided above. Note in this case: A = [1, 1, ... , 1, 1] This is becase on asub each sub-array is a list, and on that list is the places below the column where there exists variables. Each corresponding aval is the value of that item. I assume this is so mosek can optimize sparce data. ''' asub = [[0] for i in range(n)] aval = [[1.0] for i in range(n)] ''' This should be a little more straigtforward. We set the constriants on the variable itself, saying any xi is such that 0.0 <= xi <= 1.0 for all x. When we declare it an integer func this ensures each xi is either 0 or 1. Not much modification should happen here unless we decide to do two busses at once ''' bkx = [mosek.boundkey.ra] * numvar blx = [0.0] * numvar bux = [1.0] * numvar ''' Our objective function is as follows: (0.5)x.T*H*x + c.T*x To ensure negative semidefinate, we needed to make the diagonal of H -2*n for each entry. This way we could maximize the problem, however the results needed to be fixed so adding a linear objective which adds the values back which otherwise would have been subtracted off. Making each value of c[i] == n fixed this issue. ''' c = [n for i in range(n)] ''' now we need to add the number of constraints to the problem. ''' numcon = len(bkc) # Append 'numcon' empty constraints. # The constraints will initially have no bounds. task.appendcons(numcon) # Append 'numvar' variables. # The variables will initially be fixed at zero (x=0). task.appendvars(numvar) for j in range(numvar): # Set the linear term c_j in the objective. task.putcj(j, c[j]) # Set the bounds on variable j # blx[j] <= x_j <= bux[j] task.putbound(mosek.accmode.var, j, bkx[j], blx[j], bux[j]) # Input column j of A # Variable (column) index. # Row index of non-zeros in column j. task.putacol(j, asub[j], aval[j]) # Non-zero Values of column j. for i in range(numcon): task.putbound(mosek.accmode.con, i, bkc[i], blc[i], buc[i]) # Set up and input quadratic objective qsubi = [] qsubj = [] qval = [] for i in range(n): for j in range(0, i+1): if H[i][j] != 0: qsubi.append(i) qsubj.append(j) qval.append(H[i][j]) #print(qsubi) #print(qsubj) #print(qval) task.putqobj(qsubi, qsubj, qval) # Input the objective sense (minimize/maximize) task.putobjsense(mosek.objsense.maximize) # Define variables to be integers task.putvartypelist([i for i in range(n)],[mosek.variabletype.type_int for i in range(n)]) # Set max solution time task.putdouparam(mosek.dparam.mio_max_time, time); # Optimize task.optimize() # Print a summary containing information # about the solution for debugging purposes task.solutionsummary(mosek.streamtype.msg) prosta = task.getprosta(mosek.soltype.itg) solsta = task.getsolsta(mosek.soltype.itg) # Output a solution xx = [0.] * numvar task.getxx(mosek.soltype.itg, xx) solSet = [] # tempSol = [] ''' This is what we will return for each bus, fixed and all ''' for i in range(len(xx)): if xx[i] > 0.5: solSet += [reverseMap[i]] # print(solSet) # print(tempSol) if solsta in [mosek.solsta.integer_optimal, mosek.solsta.near_integer_optimal]: print("Optimal solution: %s" % xx) elif solsta == mosek.solsta.dual_infeas_cer: print("Primal or dual infeasibility.\n") elif solsta == mosek.solsta.prim_infeas_cer: print("Primal or dual infeasibility.\n") elif solsta == mosek.solsta.near_dual_infeas_cer: print("Primal or dual infeasibility.\n") elif solsta == mosek.solsta.near_prim_infeas_cer: print("Primal or dual infeasibility.\n") elif mosek.solsta.unknown: if prosta == mosek.prosta.prim_infeas_or_unbounded: print("Problem status Infeasible or unbounded.\n") elif prosta == mosek.prosta.prim_infeas: print("Problem status Infeasible.\n") elif prosta == mosek.prosta.unkown: print("Problem status unkown.\n") else: print("Other problem status.\n") else: print("Other solution status (good)") v = np.array(xx) print(v.dot(H).dot(v)*.5 + v.dot(c)) return solSet
def ilp(c, G, h, A=None, b=None, I=None, taskfile=None): """ Solves the mixed integer LP minimize c'*x subject to G*x + s = h A*x = b s >= 0 xi integer, forall i in I using MOSEK 8.0. solsta, x = ilp(c, G, h, A=None, b=None, I=None, taskfile=None). Input arguments G is m x n, h is m x 1, A is p x n, b is p x 1. G and A must be dense or sparse 'd' matrices. h and b are dense 'd' matrices with one column. The default values for A and b are empty matrices with zero rows. I is a Python set with indices of integer elements of x. By default all elements in x are constrained to be integer, i.e., the default value of I is I = set(range(n)) Dual variables are not returned for MOSEK. Optionally, the interface can write a .task file, required for support questions on the MOSEK solver. Return values solsta is a MOSEK solution status key. If solsta is mosek.solsta.integer_optimal, then x contains the solution. If solsta is mosek.solsta.unknown, then x is None. Other return values for solsta include: mosek.solsta.near_integer_optimal in which case the x value may not be well-defined, c.f., section 17.48 of the MOSEK Python API manual. x is the solution Options are passed to MOSEK solvers via the msk.options dictionary, e.g., the following turns off output from the MOSEK solvers >>> msk.options = {mosek.iparam.log: 0} see the MOSEK Python API manual. """ with mosek.Env() as env: if type(c) is not matrix or c.typecode != 'd' or c.size[1] != 1: raise TypeError("'c' must be a dense column matrix") n = c.size[0] if n < 1: raise ValueError("number of variables must be at least 1") if (type(G) is not matrix and type(G) is not spmatrix) or \ G.typecode != 'd' or G.size[1] != n: raise TypeError("'G' must be a dense or sparse 'd' matrix "\ "with %d columns" %n) m = G.size[0] if m is 0: raise ValueError("m cannot be 0") if type(h) is not matrix or h.typecode != 'd' or h.size != (m, 1): raise TypeError("'h' must be a 'd' matrix of size (%d,1)" % m) if A is None: A = spmatrix([], [], [], (0, n), 'd') if (type(A) is not matrix and type(A) is not spmatrix) or \ A.typecode != 'd' or A.size[1] != n: raise TypeError("'A' must be a dense or sparse 'd' matrix "\ "with %d columns" %n) p = A.size[0] if b is None: b = matrix(0.0, (0, 1)) if type(b) is not matrix or b.typecode != 'd' or b.size != (p, 1): raise TypeError("'b' must be a dense matrix of size (%d,1)" % p) if I is None: I = set(range(n)) if type(I) is not set: raise TypeError("invalid argument for integer index set") for i in I: if type(i) is not int: raise TypeError("invalid integer index set I") if len(I) > 0 and min(I) < 0: raise IndexError("negative element in integer index set I") if len(I) > 0 and max(I) > n - 1: raise IndexError( "maximum element in in integer index set I is larger than n-1") bkc = m * [mosek.boundkey.up] + p * [mosek.boundkey.fx] blc = m * [-inf] + [bi for bi in b] buc = list(h) + list(b) bkx = n * [mosek.boundkey.fr] blx = n * [-inf] bux = n * [+inf] colptr, asub, acof = sparse([G, A]).CCS aptrb, aptre = colptr[:-1], colptr[1:] with env.Task(0, 0) as task: task.set_Stream(mosek.streamtype.log, streamprinter) # set MOSEK options for (param, val) in options.items(): if str(param)[:6] == "iparam": task.putintparam(param, val) elif str(param)[:6] == "dparam": task.putdouparam(param, val) elif str(param)[:6] == "sparam": task.putstrparam(param, val) else: raise ValueError("invalid MOSEK parameter: " + str(param)) task.inputdata( m + p, # number of constraints n, # number of variables list(c), # linear objective coefficients 0.0, # objective fixed value list(aptrb), list(aptre), list(asub), list(acof), bkc, blc, buc, bkx, blx, bux) task.putobjsense(mosek.objsense.minimize) # Define integer variables if len(I) > 0: task.putvartypelist(list(I), len(I) * [mosek.variabletype.type_int]) task.putintparam(mosek.iparam.mio_mode, mosek.miomode.satisfied) if taskfile: task.writetask(taskfile) task.optimize() task.solutionsummary(mosek.streamtype.msg) if len(I) > 0: solsta = task.getsolsta(mosek.soltype.itg) else: solsta = task.getsolsta(mosek.soltype.bas) x = n * [0.0] if len(I) > 0: task.getsolutionslice(mosek.soltype.itg, mosek.solitem.xx, 0, n, x) else: task.getsolutionslice(mosek.soltype.bas, mosek.solitem.xx, 0, n, x) x = matrix(x) if (solsta is mosek.solsta.unknown): return (solsta, None) else: return (solsta, x)
def main(): # Make a MOSEK environment with mosek.Env() as env: # Attach a printer to the environment env.set_Stream(mosek.streamtype.log, streamprinter) # Create a task with env.Task(0, 0) as task: # Attach a printer to the task task.set_Stream(mosek.streamtype.log, streamprinter) bkc = [mosek.boundkey.fx] blc = [1.0] buc = [1.0] c = [0.0, 0.0, 0.0, 1.0, 1.0, 1.0] bkx = [mosek.boundkey.lo, mosek.boundkey.lo, mosek.boundkey.lo, mosek.boundkey.fr, mosek.boundkey.fr, mosek.boundkey.fr] blx = [0.0, 0.0, 0.0, -inf, -inf, -inf] bux = [inf, inf, inf, inf, inf, inf] asub = [[0], [0], [0]] aval = [[1.0], [1.0], [2.0]] numvar = len(bkx) numcon = len(bkc) NUMANZ = 4 # Append 'numcon' empty constraints. # The constraints will initially have no bounds. task.appendcons(numcon) #Append 'numvar' variables. # The variables will initially be fixed at zero (x=0). task.appendvars(numvar) for j in range(numvar): # Set the linear term c_j in the objective. task.putcj(j, c[j]) # Set the bounds on variable j # blx[j] <= x_j <= bux[j] task.putvarbound(j, bkx[j], blx[j], bux[j]) for j in range(len(aval)): # Input column j of A task.putacol(j, # Variable (column) index. # Row index of non-zeros in column j. asub[j], aval[j]) # Non-zero Values of column j. for i in range(numcon): task.putconbound(i, bkc[i], blc[i], buc[i]) # Input the cones task.appendcone(mosek.conetype.quad, 0.0, [3, 0, 1]) task.appendcone(mosek.conetype.rquad, 0.0, [4, 5, 2]) # Input the objective sense (minimize/maximize) task.putobjsense(mosek.objsense.minimize) # Optimize the task task.optimize() # Print a summary containing information # about the solution for debugging purposes task.solutionsummary(mosek.streamtype.msg) prosta = task.getprosta(mosek.soltype.itr) solsta = task.getsolsta(mosek.soltype.itr) # Output a solution xx = [0.] * numvar task.getxx(mosek.soltype.itr, xx) if solsta == mosek.solsta.optimal: print("Optimal solution: %s" % xx) elif solsta == mosek.solsta.dual_infeas_cer: print("Primal or dual infeasibility.\n") elif solsta == mosek.solsta.prim_infeas_cer: print("Primal or dual infeasibility.\n") elif mosek.solsta.unknown: print("Unknown solution status") else: print("Other solution status")
def solve(form, display=True, export=False): numlc, numvar = form.linear.shape if isinstance(form, SOCProg): qmat = form.qmat else: qmat = [] ind_int = np.where(form.vtype == 'I')[0] ind_bin = np.where(form.vtype == 'B')[0] if ind_bin.size: form.ub[ind_bin] = 1 form.lb[ind_bin] = 0 ind_ub = np.where((form.ub != np.inf) & (form.lb == -np.inf))[0] ind_lb = np.where((form.lb != -np.inf) & (form.ub == np.inf))[0] ind_ra = np.where((form.lb != -np.inf) & (form.ub != np.inf))[0] ind_fr = np.where((form.lb == -np.inf) & (form.ub == np.inf))[0] ind_eq = np.where(form.sense)[0] ind_ineq = np.where(form.sense == 0)[0] with mosek.Env() as env: with env.Task(0, 0) as task: task.appendvars(numvar) task.appendcons(numlc) if ind_ub.size: task.putvarboundlist(ind_ub, [mosek.boundkey.up] * len(ind_ub), form.lb[ind_ub], form.ub[ind_ub]) if ind_lb.size: task.putvarboundlist(ind_lb, [mosek.boundkey.lo] * len(ind_lb), form.lb[ind_lb], form.ub[ind_lb]) if ind_ra.size: task.putvarboundlist(ind_ra, [mosek.boundkey.ra] * len(ind_ra), form.lb[ind_ra], form.ub[ind_ra]) if ind_fr.size: task.putvarboundlist(ind_fr, [mosek.boundkey.fr] * len(ind_fr), form.lb[ind_fr], form.ub[ind_fr]) if ind_int.size: task.putvartypelist(ind_int, [mosek.variabletype.type_int] * len(ind_int)) if ind_bin.size: task.putvartypelist(ind_bin, [mosek.variabletype.type_int] * len(ind_bin)) task.putcslice(0, numvar, form.obj.flatten()) task.putobjsense(mosek.objsense.minimize) coo = coo_matrix(form.linear) task.putaijlist(coo.row, coo.col, coo.data) if ind_eq.size: task.putconboundlist(ind_eq, [mosek.boundkey.fx] * len(ind_eq), form.const[ind_eq], form.const[ind_eq]) if ind_ineq.size: task.putconboundlist(ind_ineq, [mosek.boundkey.up] * len(ind_ineq), [-np.inf] * len(ind_ineq), form.const[ind_ineq]) for cone in qmat: task.appendcone(mosek.conetype.quad, 0.0, cone) if display: print('Being solved by Mosek...') t0 = time.process_time() task.optimize() stime = time.process_time() - t0 soltype = mosek.soltype solsta = None for stype in [soltype.bas, soltype.itr, soltype.itg]: try: solsta = task.getsolsta(stype) if display: print('Solution status: {0}'.format(solsta.__repr__())) print('Running time: {0:0.4f}s'.format(stime)) break except: pass xx = [0.] * numvar task.getxx(stype, xx) if export: task.writedata("out.mps") if solsta in [mosek.solsta.optimal, mosek.solsta.integer_optimal]: solution = Solution(xx[0], xx, solsta) else: warnings.warn('No feasible solution can be found.') solution = None return solution
def ALIGNF(km_list, ky, centering=True): """ Parameters: ----------- km_list, a list of kernel matrices, list of 2d array ky, target kernel, 2d array Returns: -------- xx, the weight for each kernels """ n_feat = len(km_list) km_list_copy = [] # center the kernel first for i in range(n_feat): if centering: km_list_copy.append(center(km_list[i].copy())) else: km_list_copy.append(km_list[i].copy()) if centering: ky_copy = center(ky.copy()) else: ky_copy = ky.copy() a = np.zeros(n_feat) for i in range(n_feat): a[i] = f_dot(km_list_copy[i], ky_copy) M = np.zeros((n_feat, n_feat)) for i in range(n_feat): for j in range(i,n_feat): M[i,j] = f_dot(km_list_copy[i],km_list_copy[j]) M[j,i] = M[i,j] Q = 2*M C = -2*a Q = Q + np.diag(np.ones(n_feat)*1e-10) ################################################ # Using mosek to solve the quadratice programming # Set upper diagonal element to zeros, mosek only accept lower triangle iu = np.triu_indices(n_feat,1) Q[iu] = 0 # start solving with mosek inf = 0.0 env = mosek.Env() env.set_Stream(mosek.streamtype.log, streamprinter) # Create a task task = env.Task() task.set_Stream(mosek.streamtype.log, streamprinter) # Set up bound for variables bkx = [mosek.boundkey.lo]* n_feat blx = [0.0] * n_feat bux = [+inf]* n_feat numvar = len(bkx) task.appendvars(numvar) for j in range(numvar): task.putcj(j,C[j]) task.putvarbound(j,bkx[j],blx[j],bux[j]) # Set up quadratic objective inds = np.nonzero(Q) qsubi = inds[0].tolist() qsubj = inds[1].tolist() qval = Q[inds].tolist() # Input quadratic objective task.putqobj(qsubi,qsubj,qval) # Input objective sense (minimize/mximize) task.putobjsense(mosek.objsense.minimize) task.optimize() # Print a summary containing information # about the solution for debugging purposes task.solutionsummary(mosek.streamtype.msg) solsta = task.getsolsta(mosek.soltype.itr) if (solsta == mosek.solsta.optimal or solsta == mosek.solsta.near_optimal): # Output a solution xx = np.zeros(numvar, float) task.getxx(mosek.soltype.itr, xx) #xx = xx/np.linalg.norm(xx) return xx else: print "Solution not optimal or near optimal" print solsta return None
def main(): # Make a MOSEK environment env = mosek.Env() # Attach a printer to the environment env.set_Stream(mosek.streamtype.log, streamprinter) # Create a task task = env.Task(0, 0) # Attach a printer to the task task.set_Stream(mosek.streamtype.log, streamprinter) bkc = [mosek.boundkey.up, mosek.boundkey.lo] blc = [-inf, -4.0] buc = [250.0, inf] bkx = [mosek.boundkey.lo, mosek.boundkey.lo] blx = [0.0, 0.0] bux = [inf, inf] c = [1.0, 0.64] asub = [array([0, 1]), array([0, 1])] aval = [array([50.0, 3.0]), array([31.0, -2.0])] numvar = len(bkx) numcon = len(bkc) # Append 'numcon' empty constraints. # The constraints will initially have no bounds. task.appendcons(numcon) #Append 'numvar' variables. # The variables will initially be fixed at zero (x=0). task.appendvars(numvar) for j in range(numvar): # Set the linear term c_j in the objective. task.putcj(j, c[j]) # Set the bounds on variable j # blx[j] <= x_j <= bux[j] task.putvarbound(j, bkx[j], blx[j], bux[j]) # Input column j of A task.putacol( j, # Variable (column) index. asub[j], # Row index of non-zeros in column j. aval[j]) # Non-zero Values of column j. task.putconboundlist(range(numcon), bkc, blc, buc) # Input the objective sense (minimize/maximize) task.putobjsense(mosek.objsense.maximize) # Define variables to be integers task.putvartypelist( [0, 1], [mosek.variabletype.type_int, mosek.variabletype.type_int]) # Optimize the task task.optimize() # Print a summary containing information # about the solution for debugging purposes task.solutionsummary(mosek.streamtype.msg) prosta = task.getprosta(mosek.soltype.itg) solsta = task.getsolsta(mosek.soltype.itg) # X # Output a solution xx = zeros(numvar, float) task.getxx(mosek.soltype.itg, xx) if solsta in [ mosek.solsta.integer_optimal, mosek.solsta.near_integer_optimal ]: print("Optimal solution: %s" % xx) elif solsta == mosek.solsta.dual_infeas_cer: print("Primal or dual infeasibility.\n") elif solsta == mosek.solsta.prim_infeas_cer: print("Primal or dual infeasibility.\n") elif solsta == mosek.solsta.near_dual_infeas_cer: print("Primal or dual infeasibility.\n") elif solsta == mosek.solsta.near_prim_infeas_cer: print("Primal or dual infeasibility.\n") elif mosek.solsta.unknown: if prosta == mosek.prosta.prim_infeas_or_unbounded: print("Problem status Infeasible or unbounded.\n") elif prosta == mosek.prosta.prim_infeas: print("Problem status Infeasible.\n") elif prosta == mosek.prosta.unkown: print("Problem status unkown.\n") else: print("Other problem status.\n") else: print("Other solution status")
def main(): # Open MOSEK and create an environment and task # Make a MOSEK environment with mosek.Env() as env: # Attach a printer to the environment env.set_Stream(mosek.streamtype.log, streamprinter) # Create a task with env.Task() as task: task.set_Stream(mosek.streamtype.log, streamprinter) # Bound keys for variables numvar = numvars bkx = [mosek.boundkey.ra] * numvar # bkx = [mosek.boundkey.fr] * numvar # Bound values for variables temppricelow = initial*0.9 temppricehigh = initial*1.1 blx = [] bux = [] # blx = [inf] * numvar # bux = [inf] * numvar for i in range(numvar): blx.append(temppricelow[i]) bux.append(temppricehigh[i]) # Objective linear coefficients c = linearpart # Append 'numcon' empty constraints. # The constraints will initially have no bounds. task.appendcons(0) # Append 'numvar' variables. # The variables will initially be fixed at zero (x=0). task.appendvars(numvar) for j in range(numvar): # Set the linear term c_j in the objective. task.putcj(j, c[j]) # Set the bounds on variable j # blx[j] <= x_j <= bux[j] task.putvarbound(j, bkx[j], blx[j], bux[j]) # Set up and input quadratic objective qsubi = [] for i in range(numvar): qsubi.append(i) qsubj = qsubi qval = 2*quadpart task.putqobj(qsubi, qsubj, qval) # Input the objective sense (minimize/maximize) task.putobjsense(mosek.objsense.maximize) # Optimize task.optimize() # Print a summary containing information # about the solution for debugging purposes # task.solutionsummary(mosek.streamtype.msg) # Output a solution xx = [0.] * numvar task.getxx(mosek.soltype.itr, xx) return xx
def mosek_solve(): # LOAD VARIABLES n_utxo = len(tx.utxo_set) n_out = len(tx.outputs) U = tx.utxo_set O = tx.outputs Vu = [int(U[j]['value']) for j in range(n_utxo)] Vo = [int(O[j]['value']) for j in range(n_out)] Su = [int(U[j]['size']) for j in range(n_utxo)] So = [int(O[j]['size']) for j in range(n_out)] Ms = int(tx.params['max_size']) alpha = float(tx.params['fee_rate']) T = int(tx.params['dust_threshold']) eps = int(tx.params['min_change_output']) beta = int(tx.params['change_output_size']) # Sum of input values sum_Vu = sum(Vu[j] for j in range(n_utxo)) # Sum of output values sum_Vo = sum(Vo[j] for j in range(n_out)) # Sum of output size sum_So = sum(So[j] for j in range(n_out)) # Maximum change value = sum_Vu - sum_Vo Mc = sum_Vu - sum_Vo # Minimum utxo # Mc = min(Vu) # SOLVE # Make mosek environment with mosek.Env() as env: # Create a task object with env.Task(0, 0) as task: # Attach a log stream printer to the task task.set_Stream(mosek.streamtype.log, streamprinter) # Bound keys for constraints bkc = [ mosek.boundkey.ra, mosek.boundkey.fx, mosek.boundkey.up ] # Bound values for constraints blc = [0.0, sum_Vo + alpha * sum_So, -inf] buc = [Ms - sum_So, sum_Vo + alpha * sum_So, eps] # Bound keys for variables bkx = [mosek.boundkey.ra for j in range(n_utxo)] # l <= x <= u bkx.append(mosek.boundkey.ra) bkx.append(mosek.boundkey.ra) # Bound values for variables blx = [0.0 for j in range(n_utxo)] # x_i blx.append(0.0) # t blx.append(0.0) # z_v bux = [1.0 for j in range(n_utxo)] bux.append(1.0) bux.append(Mc) # Objective coefficients c = [Su[j] for j in range(n_utxo)] c.append(beta) c.append(0.0) # Below is the sparse representation of the A # matrix stored by column. asub = [ [0, 1] for j in range(n_utxo) ] asub.append([0, 1, 2]) asub.append([1, 2]) aval = [ [Su[j], Vu[j] - alpha * Su[j]] for j in range(n_utxo) ] aval.append([beta, -alpha * beta, -Mc]) aval.append([-1.0, 1.0]) # numcon and numvar numcon = len(bkc) numvar = len(bkx) assert numvar == n_utxo + 2 assert numcon == 3 # Append 'numcon' empty constraints. # The constraints will initially have no bounds. task.appendcons(numcon) # Append 'numvar' variables. # The variables will initially be fixed at zero (x=0). task.appendvars(numvar) for j in range(numvar): # Set the linear term c_j in the objective. task.putcj(j, c[j]) # Set the bounds on variable j # blx[j] <= x_j <= bux[j] task.putvarbound(j, bkx[j], blx[j], bux[j]) # Input column j of A task.putacol( j, # Variable (column) index. asub[j], # Row index of non-zeros in column j. aval[j] # Non-zero Values of column j. ) task.putconboundlist(range(numcon), bkc, blc, buc) # Input the objective sense (minimize/maximize) task.putobjsense(mosek.objsense.minimize) # Define variables to be integers task.putvartypelist( [j for j in range(n_utxo + 1)], [mosek.variabletype.type_int for j in range(n_utxo + 1)] ) # Set max solution time task.putdouparam(mosek.dparam.mio_max_time, 200.0); # Solve the problem task.optimize() # Print a summary containing information # about the solution for debugging purposes task.solutionsummary(mosek.streamtype.msg) prosta = task.getprosta(mosek.soltype.itg) solsta = task.getsolsta(mosek.soltype.itg) # Output a solution xx = [0.] * numvar task.getxx(mosek.soltype.itg, xx) if solsta in [mosek.solsta.integer_optimal]: print("Optimal solution: %s" % xx) return xx elif solsta == mosek.solsta.prim_feas: print("Feasible solution: %s" % xx) elif mosek.solsta.unknown: if prosta == mosek.prosta.prim_infeas_or_unbounded: print("Problem status Infeasible or unbounded.\n") elif prosta == mosek.prosta.prim_infeas: print("Problem status Infeasible.\n") elif prosta == mosek.prosta.unkown: print("Problem status unkown.\n") else: print("Other problem status.\n") else: print("Other solution status")
def run(self, *args, **kwargs): import mosek import random # define CPU = 0 MEM = 1 DISK = 2 TS = 3 # amount of PRI + STD PRI = 4 STD = 5 WEIGHT = 6 inf = 0.0 # TEMPLATE_DEFINE = [CPU, MEM, DISK, TS, PRI, STD, WEIGHT] templates_id, templates, server_id, servers = [], [], [], [] re = [] for server_info in kwargs["servers"]: if server_info[1][0] > 0 and server_info[1][1] > 0 and server_info[ 1][2] > 0: server_id.append(server_info[0]) servers.append(server_info[1]) for template_info in kwargs["templates"]: if template_info[1][0] > 0 and template_info[1][ 1] > 0 and template_info[1][2] > 0: templates_id.append(template_info[0]) templates.append(template_info[1]) if not templates_id or not server_id: for i in range(len(templates_id)): re.append(dict(id=templates_id[i], plan=[])) return ErrorCode.success, re # templates_id, templates = [x[0] for x in kwargs["templates"]], [x[1] for x in kwargs["templates"]] # server_id, servers = [x[0] for x in kwargs["servers"]], [x[1] for x in kwargs["servers"]] numserver = len(servers) numtemplate = len(templates) # c = [x[WEIGHT] for x in templates] * numserver c = [x[WEIGHT] * (x[CPU] + x[MEM] + x[DISK]) for x in templates] * numserver # 注意浅拷贝 clause = [ numtemplate * numserver * [0] for _ in range(3 * numserver + numserver * numtemplate) ] # set constraints functions for i in range(numserver): j = i clause[j][i * numtemplate:(i * numtemplate + numtemplate)] = [ t[CPU] for t in templates ] j += numserver clause[j][i * numtemplate:(i * numtemplate + numtemplate)] = [ t[MEM] for t in templates ] j += numserver clause[j][i * numtemplate:(i * numtemplate + numtemplate)] = [ t[DISK] for t in templates ] j += numserver for k in range(numtemplate): for s in range(numserver): clause[j][s * numtemplate + k] = (1 - templates[k][TS]) if s == i else 1 j += numserver # Bound keys for constraints 3 * count(server) + count(template) * count(server) = (3 + 4) * 5 bkc = 3 * numserver * [mosek.boundkey.ra] + numserver * numtemplate * [ mosek.boundkey.lo ] blc = (3 * numserver + numtemplate * numserver) * [0] buc = [x[CPU] for x in servers] + [x[MEM] for x in servers] + [x[DISK] for x in servers] \ + numserver * numtemplate * [+inf] bkx = numserver * numtemplate * [mosek.boundkey.lo] blx = numserver * numtemplate * [0] bux = numserver * numtemplate * [+inf] # 条件做矩阵转置 clause_T = [[r[col] for r in clause] for col in range(len(clause[0]))] asub = [[i for i in range(len(col)) if col[i]] for col in clause_T] aval = [[i for i in col if i] for col in clause_T] numvar = len(bkx) numcon = len(bkc) with mosek.Env() as env: with env.Task(0, 0) as task: task.appendcons(numcon) task.appendvars(numvar) for j in range(numvar): task.putcj(j, c[j]) task.putvarbound(j, bkx[j], blx[j], bux[j]) task.putacol(j, asub[j], aval[j]) task.putconboundlist(range(numcon), bkc, blc, buc) task.putobjsense(mosek.objsense.maximize) task.putvartypelist([x for x in range(len(c))], len(c) * [mosek.variabletype.type_int]) task.putdouparam(mosek.dparam.mio_max_time, 60.0) task.optimize() task.solutionsummary(mosek.streamtype.msg) prosta = task.getprosta(mosek.soltype.itg) solsta = task.getsolsta(mosek.soltype.itg) xx = [0.] * numvar task.getxx(mosek.soltype.itg, xx) # print(xx) xx = [int(x) for x in xx] result = [ xx[i:i + numtemplate] for i in range(0, len(xx), numtemplate) ] result = [(server_id[r], result[r]) for r in range(len(result))] for i in range(len(templates_id)): flag = [] re_by_template = [x[1][i] for x in result] # if plan exists init_re = [[] for _ in range((sum(re_by_template) // templates[i][TS]))] if init_re: for r in range(len(init_re)): for _ in re_by_template: if max(re_by_template) == 0: init_re[r].append(-1) else: idx = re_by_template.index( max(re_by_template)) if idx in flag: for xx in range(len(re_by_template)): if xx in flag: continue else: if re_by_template[xx] == 0: continue else: idx = xx break init_re[r].append(server_id[idx]) re_by_template[idx] -= 1 flag.append(idx) if len(init_re[r]) == templates[i][TS]: flag = [] random.shuffle(init_re[r]) random.shuffle(init_re[r]) break re.append(dict(id=templates_id[i], plan=init_re)) return ErrorCode.success, re
import pyutilib.th as unittest from pyomo.opt import (TerminationCondition, SolutionStatus, SolverStatus) import pyomo.environ as pyo import pyomo.kernel as pmo import sys try: import mosek mosek_available = True mosek_version = mosek.Env().getversion() except ImportError: mosek_available = False modek_version = None diff_tol = 1e-3 @unittest.skipIf(not mosek_available, "MOSEK's python bindings are missing.") class MOSEKPersistentTests(unittest.TestCase): def setUp(self): self.stderr = sys.stderr sys.stderr = None def tearDown(self): sys.stderr = self.stderr def test_interface_call(self): interface_instance = type(pyo.SolverFactory('mosek_persistent')) alt_1 = pyo.SolverFactory('mosek', solver_io='persistent')
def conelp(c, G, h, dims=None, taskfile=None): """ Solves a pair of primal and dual SOCPs minimize c'*x subject to G*x + s = h s >= 0 maximize -h'*z subject to G'*z + c = 0 z >= 0 using MOSEK 8.0. The inequalities are with respect to a cone C defined as the Cartesian product of N + M + 1 cones: C = C_0 x C_1 x .... x C_N x C_{N+1} x ... x C_{N+M}. The first cone C_0 is the nonnegative orthant of dimension ml. The next N cones are second order cones of dimension mq[0], ..., mq[N-1]. The second order cone of dimension m is defined as { (u0, u1) in R x R^{m-1} | u0 >= ||u1||_2 }. The next M cones are positive semidefinite cones of order ms[0], ..., ms[M-1] >= 0. The formats of G and h are identical to that used in solvers.conelp(). Input arguments. c is a dense 'd' matrix of size (n,1). dims is a dictionary with the dimensions of the components of C. It has three fields. - dims['l'] = ml, the dimension of the nonnegative orthant C_0. (ml >= 0.) - dims['q'] = mq = [ mq[0], mq[1], ..., mq[N-1] ], a list of N integers with the dimensions of the second order cones C_1, ..., C_N. (N >= 0 and mq[k] >= 1.) - dims['s'] = ms = [ ms[0], ms[1], ..., ms[M-1] ], a list of M integers with the orders of the semidefinite cones C_{N+1}, ..., C_{N+M}. (M >= 0 and ms[k] >= 0.) The default value of dims is {'l': G.size[0], 'q': [], 's': []}. G is a dense or sparse 'd' matrix of size (K,n), where K = ml + mq[0] + ... + mq[N-1] + ms[0]**2 + ... + ms[M-1]**2. Each column of G describes a vector v = ( v_0, v_1, ..., v_N, vec(v_{N+1}), ..., vec(v_{N+M}) ) in V = R^ml x R^mq[0] x ... x R^mq[N-1] x S^ms[0] x ... x S^ms[M-1] stored as a column vector [ v_0; v_1; ...; v_N; vec(v_{N+1}); ...; vec(v_{N+M}) ]. Here, if u is a symmetric matrix of order m, then vec(u) is the matrix u stored in column major order as a vector of length m**2. We use BLAS unpacked 'L' storage, i.e., the entries in vec(u) corresponding to the strictly upper triangular entries of u are not referenced. h is a dense 'd' matrix of size (K,1), representing a vector in V, in the same format as the columns of G. A is a dense or sparse 'd' matrix of size (p,n). The default value is a sparse 'd' matrix of size (0,n). b is a dense 'd' matrix of size (p,1). The default value is a dense 'd' matrix of size (0,1). Optionally, the interface can write a .task file, required for support questions on the MOSEK solver. Return values solsta is a MOSEK solution status key. If solsta is mosek.solsta.optimal, then (x, zl, zq, zs) contains the primal-dual solution. If solsta is moseksolsta.prim_infeas_cer, then (x, zl, zq, zs) is a certificate of dual infeasibility. If solsta is moseksolsta.dual_infeas_cer, then (x, zl, zq, zs) is a certificate of primal infeasibility. If solsta is mosek.solsta.unknown, then (x, zl, zq, zs) are all None Other return values for solsta include: mosek.solsta.dual_feas mosek.solsta.near_dual_feas mosek.solsta.near_optimal mosek.solsta.near_prim_and_dual_feas mosek.solsta.near_prim_feas mosek.solsta.prim_and_dual_feas mosek.solsta.prim_feas in which case the (x,y,z) value may not be well-defined. x, z the primal-dual solution. Options are passed to MOSEK solvers via the msk.options dictionary, e.g., the following turns off output from the MOSEK solvers >>> msk.options = {mosek.iparam.log:0} see the MOSEK Python API manual. """ with mosek.Env() as env: if dims is None: (solsta, x, y, z) = lp(c, G, h) return (solsta, x, z, None) N, n = G.size ml, mq, ms = dims['l'], dims['q'], [k * k for k in dims['s']] cdim = ml + sum(mq) + sum(ms) if cdim is 0: raise ValueError("ml+mq+ms cannot be 0") # Data for kth 'q' constraint are found in rows indq[k]:indq[k+1] of G. indq = [dims['l']] for k in dims['q']: indq = indq + [indq[-1] + k] # Data for the kth 's' constraint are found in rows indq[-1] + (inds[k]:inds[k+1]) of G. inds = [0] for k in dims['s']: inds = inds + [inds[-1] + k * k] if type(h) is not matrix or h.typecode != 'd' or h.size[1] != 1: raise TypeError("'h' must be a 'd' matrix with 1 column") if type(G) is matrix or type(G) is spmatrix: if G.typecode != 'd' or G.size[0] != cdim: raise TypeError("'G' must be a 'd' matrix with %d rows " % cdim) if h.size[0] != cdim: raise TypeError("'h' must have %d rows" % cdim) else: raise TypeError("'G' must be a matrix") if len(dims['q']) and min(dims['q']) < 1: raise TypeError("dimensions of quadratic cones must be positive") if len(dims['s']) and min(dims['s']) < 1: raise TypeError( "dimensions of semidefinite cones must be positive") bkc = n * [mosek.boundkey.fx] blc = list(-c) buc = list(-c) dimx = ml + sum(mq) bkx = ml * [mosek.boundkey.lo] + sum(mq) * [mosek.boundkey.fr] blx = ml * [0.0] + sum(mq) * [-inf] bux = dimx * [+inf] c = list(-h) cl, cs = c[:dimx], sparse(c[dimx:]) Gl, Gs = sparse(G[:dimx, :]), sparse(G[dimx:, :]) colptr, asub, acof = Gl.T.CCS aptrb, aptre = colptr[:-1], colptr[1:] with env.Task(0, 0) as task: task.set_Stream(mosek.streamtype.log, streamprinter) # set MOSEK options for (param, val) in options.items(): if str(param)[:6] == "iparam": task.putintparam(param, val) elif str(param)[:6] == "dparam": task.putdouparam(param, val) elif str(param)[:6] == "sparam": task.putstrparam(param, val) else: raise ValueError("invalid MOSEK parameter: " + str(param)) task.inputdata( n, # number of constraints dimx, # number of variables cl, # linear objective coefficients 0.0, # objective fixed value list(aptrb), list(aptre), list(asub), list(acof), bkc, blc, buc, bkx, blx, bux) task.putobjsense(mosek.objsense.maximize) numbarvar = len(dims['s']) task.appendbarvars(dims['s']) barcsubj, barcsubk, barcsubl = (inds[-1]) * [0], ( inds[-1]) * [0], (inds[-1]) * [0] barcval = [-h[indq[-1] + k] for k in range(inds[0], inds[-1])] for s in range(numbarvar): for (k, idx) in enumerate(range(inds[s], inds[s + 1])): barcsubk[idx] = k / dims['s'][s] barcsubl[idx] = k % dims['s'][s] barcsubj[idx] = s # filter out upper triangular part trilidx = [ idx for idx in range(len(barcsubk)) if barcsubk[idx] >= barcsubl[idx] ] barcsubj = [barcsubj[k] for k in trilidx] barcsubk = [barcsubk[k] for k in trilidx] barcsubl = [barcsubl[k] for k in trilidx] barcval = [barcval[k] for k in trilidx] task.putbarcblocktriplet(len(trilidx), barcsubj, barcsubk, barcsubl, barcval) Gst = Gs.T barasubi = len(Gst) * [0] barasubj = len(Gst) * [0] barasubk = len(Gst) * [0] barasubl = len(Gst) * [0] baraval = len(Gst) * [0.0] colptr, row, val = Gst.CCS for s in range(numbarvar): for j in range(ms[s]): for idx in range(colptr[inds[s] + j], colptr[inds[s] + j + 1]): barasubi[idx] = row[idx] barasubj[idx] = s barasubk[idx] = j / dims['s'][s] barasubl[idx] = j % dims['s'][s] baraval[idx] = val[idx] # filter out upper triangular part trilidx = [ idx for (idx, (k, l)) in enumerate(zip(barasubk, barasubl)) if k >= l ] barasubi = [barasubi[k] for k in trilidx] barasubj = [barasubj[k] for k in trilidx] barasubk = [barasubk[k] for k in trilidx] barasubl = [barasubl[k] for k in trilidx] baraval = [baraval[k] for k in trilidx] task.putbarablocktriplet(len(trilidx), barasubi, barasubj, barasubk, barasubl, baraval) for k in range(len(mq)): task.appendcone(mosek.conetype.quad, 0.0, range(ml + sum(mq[:k]), ml + sum(mq[:k + 1]))) if taskfile: task.writetask(taskfile) task.optimize() task.solutionsummary(mosek.streamtype.msg) solsta = task.getsolsta(mosek.soltype.itr) xu, xl, zq = n * [0.0], n * [0.0], sum(mq) * [0.0] task.getsolutionslice(mosek.soltype.itr, mosek.solitem.slc, 0, n, xl) task.getsolutionslice(mosek.soltype.itr, mosek.solitem.suc, 0, n, xu) task.getsolutionslice(mosek.soltype.itr, mosek.solitem.xx, ml, dimx, zq) x = matrix(xu) - matrix(xl) zq = matrix(zq) for s in range(numbarvar): xx = (dims['s'][s] * (dims['s'][s] + 1) >> 1) * [0.0] task.getbarxj(mosek.soltype.itr, s, xx) xs = matrix(0.0, (dims['s'][s], dims['s'][s])) idx = 0 for j in range(dims['s'][s]): for i in range(j, dims['s'][s]): xs[i, j] = xx[idx] if i != j: xs[j, i] = xx[idx] idx += 1 zq = matrix([zq, xs[:]]) if ml: zl = ml * [0.0] task.getsolutionslice(mosek.soltype.itr, mosek.solitem.xx, 0, ml, zl) zl = matrix(zl) else: zl = matrix(0.0, (0, 1)) if (solsta is mosek.solsta.unknown): return (solsta, None, None) else: return (solsta, x, matrix([zl, zq]))
######################################################### # Global variables and initialization def msk_write_log(text): sys.stdout.write(text) sys.stdout.flush() if logfile: logfile.write(text) logfile.flush() def msk_print(text): msk_write_log(text + '\n') env = mosek.Env() task = env.Task() env.set_Stream(mosek.streamtype.log, msk_write_log) task.set_Stream(mosek.streamtype.log, msk_write_log) lastFile = None logfile = None welcometext = """ MOSEK Python Console MOSEK version {0} Type help for list of commands Full documentation in the user manual """.format('.'.join([str(_) for _ in mosek.Env.getversion()])) helptext = [ ('help [command]',
def solve(self, objective, constraints, cached_data, warm_start, verbose, solver_opts): """Returns the result of the call to the solver. Parameters ---------- objective : LinOp The canonicalized objective. constraints : list The list of canonicalized cosntraints. cached_data : dict A map of solver name to cached problem data. warm_start : bool Not used. verbose : bool Should the solver print output? solver_opts : dict Additional arguments for the solver. Returns ------- tuple (status, optimal value, primal, equality dual, inequality dual) """ import mosek env = mosek.Env() task = env.Task(0, 0) if verbose: # Define a stream printer to grab output from MOSEK def streamprinter(text): import sys sys.stdout.write(text) sys.stdout.flush() env.set_Stream(mosek.streamtype.log, streamprinter) task.set_Stream(mosek.streamtype.log, streamprinter) data = self.get_problem_data(objective, constraints, cached_data) A = data[s.A] b = data[s.B] G = data[s.G] h = data[s.H] c = data[s.C] dims = data[s.DIMS] # size of problem numvar = len(c) + sum(dims[s.SOC_DIM]) numcon = len(b) + dims[s.LEQ_DIM] + sum(dims[s.SOC_DIM]) + \ sum([el**2 for el in dims[s.SDP_DIM]]) # otherwise it crashes on empty probl. if numvar == 0: result_dict = {s.STATUS: s.OPTIMAL} result_dict[s.PRIMAL] = [] result_dict[s.VALUE] = 0. + data[s.OFFSET] result_dict[s.EQ_DUAL] = [] result_dict[s.INEQ_DUAL] = [] return result_dict # objective task.appendvars(numvar) task.putclist(np.arange(len(c)), c) task.putvarboundlist(np.arange(numvar, dtype=int), [mosek.boundkey.fr] * numvar, np.zeros(numvar), np.zeros(numvar)) # SDP variables if sum(dims[s.SDP_DIM]) > 0: task.appendbarvars(dims[s.SDP_DIM]) # linear equality and linear inequality constraints task.appendcons(numcon) if A.shape[0] and G.shape[0]: constraints_matrix = sp.bmat([[A], [G]]) else: constraints_matrix = A if A.shape[0] else G coefficients = np.concatenate([b, h]) row, col, el = sp.find(constraints_matrix) task.putaijlist(row, col, el) type_constraint = [mosek.boundkey.fx] * len(b) type_constraint += [mosek.boundkey.up] * dims[s.LEQ_DIM] type_constraint += [mosek.boundkey.fx] * (sum(dims[s.SOC_DIM])+ \ sum([el**2 for el in dims[s.SDP_DIM]])) task.putconboundlist(np.arange(numcon, dtype=int), type_constraint, coefficients, coefficients) # cones current_var_index = len(c) current_con_index = len(b) + dims[s.LEQ_DIM] for size_cone in dims[s.SOC_DIM]: row, col, el = sp.find(sp.eye(size_cone)) row += current_con_index col += current_var_index task.putaijlist(row, col, el) # add a identity for each cone # add a cone constraint task.appendcone( mosek.conetype.quad, 0.0, #unused np.arange(current_var_index, current_var_index + size_cone)) current_con_index += size_cone current_var_index += size_cone #SDP for num_sdp_var, size_matrix in enumerate(dims[s.SDP_DIM]): for i_sdp_matrix in range(size_matrix): for j_sdp_matrix in range(size_matrix): task.putbaraij(current_con_index, num_sdp_var, [ task.appendsparsesymmat( size_matrix, [max(i_sdp_matrix, j_sdp_matrix)], [min(i_sdp_matrix, j_sdp_matrix)], [1. if (i_sdp_matrix == j_sdp_matrix) else .5]) ], [1.0]) current_con_index += 1 # solve task.putobjsense(mosek.objsense.minimize) task.optimize() if verbose: task.solutionsummary(mosek.streamtype.msg) return self.format_results(task, data, cached_data)