def minimum_variance(matrix): # Given the matrix of returns a (each column is a series of returns) this method # computes the weights for a minimum variance portfolio, e.g. # min 2-Norm[a*w]^2 # s.t. # w >= 0 # sum[w] = 1 # This is the left-most point on the efficiency frontier in the classic Markowitz theory # build the model with Model("Minimum Variance") as model: # introduce the weight variable weights = model.variable("weights", matrix.shape[1], Domain.inRange(0.0, 1.0)) # sum of weights has to be 1 model.constraint(Expr.sum(weights), Domain.equalsTo(1.0)) # returns r = Expr.mul(Matrix.dense(matrix), weights) # compute l2_norm squared of those returns # minimize this l2_norm model.objective(ObjectiveSense.Minimize, __l2_norm_squared(model, "2-norm^2(r)", expr=r)) # solve the problem model.solve() # return the series of weights return np.array(weights.level())
def lsq_pos(matrix, rhs): """ min 2-norm (matrix*w - rhs)^2 s.t. e'w = 1 w >= 0 """ # define model with Model('lsqPos') as model: # introduce n non-negative weight variables weights = model.variable("weights", matrix.shape[1], Domain.inRange(0.0, +np.infty)) # e'*w = 1 model.constraint(Expr.sum(weights), Domain.equalsTo(1.0)) v = __l2_norm(model, "2-norm(res)", expr=__residual(matrix, rhs, weights)) # minimization of the residual model.objective(ObjectiveSense.Minimize, v) # solve the problem model.solve() return np.array(weights.level())
def lsq_pos_l1_penalty(matrix, rhs, cost_multiplier, weights_0): """ min 2-norm (matrix*w - rhs)** + 1-norm(cost_multiplier*(w-w0)) s.t. e'w = 1 w >= 0 """ # define model with Model('lsqSparse') as model: # introduce n non-negative weight variables weights = model.variable("weights", matrix.shape[1], Domain.inRange(0.0, +np.infty)) # e'*w = 1 model.constraint(Expr.sum(weights), Domain.equalsTo(1.0)) # sum of squared residuals v = __l2_norm_squared(model, "2-norm(res)**", __residual(matrix, rhs, weights)) # \Gamma*(w - w0), p is an expression p = Expr.mulElm(cost_multiplier, Expr.sub(weights, weights_0)) cost = model.variable("cost", matrix.shape[1], Domain.unbounded()) model.constraint(Expr.sub(cost, p), Domain.equalsTo(0.0)) t = __l1_norm(model, 'abs(weights)', cost) # Minimise v + t model.objective(ObjectiveSense.Minimize, __sum_weighted(1.0, v, 1.0, t)) # solve the problem model.solve() return np.array(weights.level())
def _update(self, clique_data, parent=None): for c in clique_data['cliques']: self.cliques[c['name']] = v = self.model.variable( c['name'], Domain.inRange(0.0, 1.0), Domain.isInteger() ) for img, cmd in product(c['images'], c['commands']): self.by_img_cmd[img,cmd].append(v) self._obj.append(Expr.mul(float(c['time']), v)) if parent is not None: self.model.constraint( 'c-%s-%s' % (c['name'], parent['name']), Expr.sub(v, self.cliques[parent['name']]), Domain.lessThan(0.0) ) for child in c['children']: self._update(child, c) for inter in clique_data['intersections']: self.model.constraint( 'iter-%d' % self._inter, Expr.add([self.cliques[i] for i in inter]), Domain.lessThan(1.0) ) self._inter += 1
def solve_sdp_program(A): assert A.ndim == 2 assert A.shape[0] == A.shape[1] A = A.copy() n = A.shape[0] with Model('theta_2') as M: # variable X = M.variable('X', Domain.inPSDCone(n + 1)) t = M.variable() # objective function M.objective(ObjectiveSense.Maximize, t) # constraints for i in range(n + 1): M.constraint(f'c{i}{i}', X.index(i, i), Domain.equalsTo(1.)) if i == 0: continue M.constraint(f'c0,{i}', Expr.sub(X.index(0, i), t), Domain.greaterThan(0.)) for j in range(i + 1, n + 1): if A[i - 1, j - 1] == 0: M.constraint(f'c{i},{j}', X.index(i, j), Domain.equalsTo(0.)) # solution M.solve() X_sol = X.level() t_sol = t.level() t_sol = t_sol[0] theta = 1. / t_sol**2 return theta
def solve(self, problem, saver): # Construct model. self.problem = problem # Do recursive maximal clique detection. self.clique_data = clique_data = problem.cliques() self.model = model = Model() if self.time is not None: model.setSolverParam('mioMaxTime', 60.0 * int(self.time)) # Each image needs to run all its commands. This keep track of # what variables run each command for each image. self.by_img_cmd = by_img_cmd = defaultdict(list) # Objective is the total cost of all the commands we run. self._obj = [] # x[i,c] = 1 if image i incurs the cost of command c directly self.x = x = {} for img, cmds in problem.images.items(): for cmd in cmds: name = 'x[%s,%s]' % (img, cmd) x[name] = v = self.model.variable( name, Domain.inRange(0.0, 1.0), Domain.isInteger() ) self._obj.append(Expr.mul(float(problem.commands[cmd]), v)) by_img_cmd[img,cmd].append(v) # cliques[i] = 1 if clique i is used, 0 otherwise self.cliques = {} self._inter = 1 self._update(clique_data) # Each image has to run each of its commands. for img_cmd, vlist in by_img_cmd.items(): name = 'img-cmd-%s-%s' % img_cmd self.model.constraint( name, Expr.add(vlist), Domain.equalsTo(1.0) ) model.objective('z', ObjectiveSense.Minimize, Expr.add(self._obj)) model.setLogHandler(sys.stdout) model.acceptedSolutionStatus(AccSolutionStatus.Feasible) model.solve() # Translate the output of this to a schedule. schedule = defaultdict(list) self._translate(schedule, clique_data) for name, v in x.items(): img, cmd = name.replace('x[','').replace(']','').split(',') if v.level()[0] > 0.5: schedule[img].append(cmd) saver(schedule)
def Update_Z_Constr(self): self.Remove_Z_Constr() Z = self.model.getVariable('Z') if len(self.constr) == 1: for key, value in self.constr.items(): # only one iteration self.model.constraint('BB', Z.index(key), Domain.equalsTo(value)) if len(self.constr) >= 2: expression = Expr.vstack( [Z.index(key) for key in self.constr.keys()]) values = [value for key, value in self.constr.items()] self.model.constraint('BB', expression, Domain.equalsTo(values))
def __Update_Z_Constr(pure_model: Model, constr_z: Dict[int, int]) -> Model: Z = pure_model.getVariable('Z') if len(constr_z) == 1: for key, value in constr_z.items(): # only one iteration pure_model.constraint('BB', Z.index(key), Domain.equalsTo(value)) if len(constr_z) >= 2: expression = Expr.vstack([Z.index(key) for key in constr_z.keys()]) values = [value for key, value in constr_z.items()] pure_model.constraint('BB', expression, Domain.equalsTo(values)) return pure_model
def optimize_with_mosek(self, predicted, today): """ 使用Mosek来优化构建组合。在测试中Mosek比scipy的单纯形法快约18倍,如果可能请尽量使用Mosek。 但是Mosek是一个商业软件,因此你需要一份授权。如果没有授权的话请使用scipy或optlang。 """ from mosek.fusion import Expr, Model, ObjectiveSense, Domain, SolutionError index_weight = self.index_weights.loc[today].fillna(0) index_weight = index_weight / index_weight.sum() stocks = list(predicted.index) with Model("portfolio") as M: x = M.variable("x", len(stocks), Domain.inRange(0, self.constraint_config['stocks'])) # 权重总和等于一 M.constraint("sum", Expr.sum(x), Domain.equalsTo(1.0)) # 控制风格暴露 for factor_name, limit in self.constraint_config['factors'].items( ): factor_data = self.factor_data[factor_name].loc[today] factor_data = factor_data.fillna(factor_data.mean()) index_exposure = (index_weight * factor_data).sum() stocks_exposure = factor_data.loc[stocks].values M.constraint( factor_name, Expr.dot(stocks_exposure.tolist(), x), Domain.inRange(index_exposure - limit, index_exposure + limit)) # 控制行业暴露 for industry_name, limit in self.constraint_config[ 'industries'].items(): industry_data = self.industry_data[industry_name].loc[ today].fillna(0) index_exposure = (index_weight * industry_data).sum() stocks_exposure = industry_data.loc[stocks].values M.constraint( industry_name, Expr.dot(stocks_exposure.tolist(), x), Domain.inRange(index_exposure - limit, index_exposure + limit)) # 最大化期望收益率 M.objective("MaxRtn", ObjectiveSense.Maximize, Expr.dot(predicted.tolist(), x)) M.solve() weights = pd.Series(list(x.level()), index=stocks) # try: # weights = pd.Series(list(x.level()), index=stocks) # except SolutionError: # raise RuntimeError("Mosek fail to find a feasible solution @ {}".format(str(today))) return weights[weights > 0]
def solve(self, problem, saver): # Construct model. self.problem = problem # Do recursive maximal clique detection. self.clique_data = clique_data = problem.cliques() self.model = model = Model() if self.time is not None: model.setSolverParam('mioMaxTime', 60.0 * int(self.time)) # Each image needs to run all its commands. This keep track of # what variables run each command for each image. self.by_img_cmd = by_img_cmd = defaultdict(list) # Objective is the total cost of all the commands we run. self._obj = [] # x[i,c] = 1 if image i incurs the cost of command c directly self.x = x = {} for img, cmds in problem.images.items(): for cmd in cmds: name = 'x[%s,%s]' % (img, cmd) x[name] = v = self.model.variable(name, Domain.inRange(0.0, 1.0), Domain.isInteger()) self._obj.append(Expr.mul(float(problem.commands[cmd]), v)) by_img_cmd[img, cmd].append(v) # cliques[i] = 1 if clique i is used, 0 otherwise self.cliques = {} self._inter = 1 self._update(clique_data) # Each image has to run each of its commands. for img_cmd, vlist in by_img_cmd.items(): name = 'img-cmd-%s-%s' % img_cmd self.model.constraint(name, Expr.add(vlist), Domain.equalsTo(1.0)) model.objective('z', ObjectiveSense.Minimize, Expr.add(self._obj)) model.setLogHandler(sys.stdout) model.acceptedSolutionStatus(AccSolutionStatus.Feasible) model.solve() # Translate the output of this to a schedule. schedule = defaultdict(list) self._translate(schedule, clique_data) for name, v in x.items(): img, cmd = name.replace('x[', '').replace(']', '').split(',') if v.level()[0] > 0.5: schedule[img].append(cmd) saver(schedule)
def markowitz(exp_ret, covariance_mat, aversion): # define model with Model("mean var") as model: # set of n weights (unconstrained) weights = model.variable("weights", len(exp_ret), Domain.inRange(-np.infty, +np.infty)) model.constraint(Expr.sum(weights), Domain.equalsTo(1.0)) # standard deviation induced by covariance matrix var = __variance(model, "var", weights, covariance_mat) model.objective(ObjectiveSense.Maximize, Expr.sub(Expr.dot(exp_ret, weights), Expr.mul(aversion, var))) model.solve() #mModel.maximise(model=model, expr=Expr.sub(Expr.dot(exp_ret, weights), Expr.mul(aversion, var))) return np.array(weights.level())
def __linfty_norm(model, name, expr): t = model.variable(name, 1, Domain.unbounded()) # (t, w_i) \in Q2 for i in range(0, expr.size()): __quad_cone(model, t, expr.index(i)) return t
def __absolute(model, name, expr): t = model.variable(name, expr.size(), Domain.unbounded()) # (t_i, w_i) \in Q2 for i in range(0, int(expr.size())): __quad_cone(model, t.index(i), expr.index(i)) return t
def _solve_cvxopt_mosek(self): from mosek.fusion import Model, Domain, ObjectiveSense, Expr n, r = self.A with Model('L1 lp formulation') as model: model.variable('x', r, Domain.greaterThan(0.0)) model.objective('l1 norm', ObjectiveSense.Minimize, Expr.dot()) raise NotImplementedError
def markowitz(exp_ret, covariance_mat, aversion): # define model with Model("mean var") as model: # set of n weights (unconstrained) weights = model.variable("weights", len(exp_ret), Domain.inRange(-np.infty, +np.infty)) model.constraint(Expr.sum(weights), Domain.equalsTo(1.0)) # standard deviation induced by covariance matrix var = __variance(model, "var", weights, covariance_mat) model.objective( ObjectiveSense.Maximize, Expr.sub(Expr.dot(exp_ret, weights), Expr.mul(aversion, var))) model.solve() #mModel.maximise(model=model, expr=Expr.sub(Expr.dot(exp_ret, weights), Expr.mul(aversion, var))) return np.array(weights.level())
def __l2_norm_squared(model, name, expr): """ Given an expression (e.g. a vector) this returns the squared L2-norm of this vector as an expression. It also introduces an auxiliary variables. Mosek requires a name for any variable that is added to a model. The user has to specify this name explicitly. This requirement may disappear in future version of this API. """ t = model.variable(name, 1, Domain.unbounded()) __rotated_quad_cone(model, 0.5, t, expr) return t
def markowitz_riskobjective(exp_ret, covariance_mat, bound): # define model with Model("mean var") as model: # set of n weights (unconstrained) weights = model.variable("weights", len(exp_ret), Domain.inRange(0.0, 1.0)) # standard deviation induced by covariance matrix stdev = __stdev(model, "std", weights, covariance_mat) # impose a bound on this standard deviation #mBound.upper(model, stdev, bound) model.constraint(stdev, Domain.lessThan(bound)) #mModel.maximise(model=model, expr=Expr.dot(exp_ret, weights)) model.objective(ObjectiveSense.Maximize, Expr.dot(exp_ret, weights)) # solve the problem model.solve() return np.array(weights.level())
def solve_sdp_program(W): assert W.ndim == 2 assert W.shape[0] == W.shape[1] W = W.copy() n = W.shape[0] with Model('gw_max_cut') as M: W = Matrix.dense(W / 4.) J = Matrix.ones(n, n) # variable Y = M.variable('Y', Domain.inPSDCone(n)) # objective function M.objective(ObjectiveSense.Maximize, Expr.dot(W, Expr.sub(J, Y))) # constraints for i in range(n): M.constraint(f'c_{i}', Y.index(i, i), Domain.equalsTo(1.)) # solve M.solve() # solution Y_opt = Y.level() return np.reshape(Y_opt, (n, n))
def lsq_ls(matrix, rhs): """ min 2-norm (matrix*w - rhs)^2 s.t. e'w = 1 """ # define model with Model('lsqPos') as model: weights = model.variable("weights", matrix.shape[1], Domain.inRange(-np.infty, +np.infty)) # e'*w = 1 model.constraint(Expr.sum(weights), Domain.equalsTo(1.0)) v = __l2_norm(model, "2-norm(res)", expr=__residual(matrix, rhs, weights)) # minimization of the residual model.objective(ObjectiveSense.Minimize, v) # solve the problem model.solve() return np.array(weights.level())
def solve_sdp_program(A): assert A.ndim == 2 assert A.shape[0] == A.shape[1] A = A.copy() n = A.shape[0] with Model('theta_1') as M: A = Matrix.dense(A) # variable X = M.variable('X', Domain.inPSDCone(n)) # objective function M.objective(ObjectiveSense.Maximize, Expr.sum(Expr.dot(Matrix.ones(n, n), X))) # constraints M.constraint(f'c1', Expr.sum(Expr.dot(X, A)), Domain.equalsTo(0.)) M.constraint(f'c2', Expr.sum(Expr.dot(X, Matrix.eye(n))), Domain.equalsTo(1.)) # solution M.solve() sol = X.level() return sum(sol)
def solve_sdp_program(W): assert W.ndim == 2 assert W.shape[0] == W.shape[1] W = W.copy() n = W.shape[0] W = expand_matrix(W) with Model('gw_max_3_cut') as M: W = Matrix.dense(W / 3.) J = Matrix.ones(3*n, 3*n) # variable Y = M.variable('Y', Domain.inPSDCone(3*n)) # objective function M.objective(ObjectiveSense.Maximize, Expr.dot(W, Expr.sub(J, Y))) # constraints for i in range(3*n): M.constraint(f'c_{i}{i}', Y.index(i, i), Domain.equalsTo(1.)) for i in range(n): M.constraint(f'c_{i}^01', Y.index(i*3, i*3+1), Domain.equalsTo(-1/2.)) M.constraint(f'c_{i}^02', Y.index(i*3, i*3+2), Domain.equalsTo(-1/2.)) M.constraint(f'c_{i}^12', Y.index(i*3+1, i*3+2), Domain.equalsTo(-1/2.)) for j in range(i+1, n): for a, b in product(range(3), repeat=2): M.constraint(f'c_{i}{j}^{a}{b}-0', Y.index(i*3 + a, j*3 + b), Domain.greaterThan(-1/2.)) M.constraint(f'c_{i}{j}^{a}{b}-1', Expr.sub(Y.index(i*3 + a, j*3 + b), Y.index(i*3 + (a + 1) % 3, j*3 + (b + 1) % 3)), Domain.equalsTo(0.)) M.constraint(f'c_{i}{j}^{a}{b}-2', Expr.sub(Y.index(i*3 + a, j*3 + b), Y.index(i*3 + (a + 2) % 3, j*3 + (b + 2) % 3)), Domain.equalsTo(0.)) # solution M.solve() Y_opt = Y.level() return np.reshape(Y_opt, (3*n,3*n))
def solve_sdp_program(W, k): assert W.ndim == 2 assert W.shape[0] == W.shape[1] W = W.copy() n = W.shape[0] with Model('fj_max_k_cut') as M: W = Matrix.dense((k - 1) / (2 * k) * W) J = Matrix.ones(n, n) # variable Y = M.variable('Y', Domain.inPSDCone(n)) # objective function M.objective(ObjectiveSense.Maximize, Expr.dot(W, Expr.sub(J, Y))) # constraints for i in range(n): M.constraint(f'c_{i}', Y.index(i, i), Domain.equalsTo(1.)) for j in range(i + 1, n): M.constraint(f'c_{i},{j}', Y.index(i, j), Domain.greaterThan(-1 / (k - 1))) # solution M.solve() Y_opt = Y.level() return np.reshape(Y_opt, (n, n))
def __init__(self,name, foods, nutrients, daily_allowance, nutritive_value): Model.__init__(self,name) finished = False try: self.foods = [ str(f) for f in foods ] self.nutrients = [ str(n) for n in nutrients ] self.dailyAllowance = array.array(daily_allowance, float) self.nutrientValue = DenseMatrix(nutritive_value).transpose() M = len(self.foods) N = len(self.nutrients) if len(self.dailyAllowance) != N: raise ValueError("Length of daily_allowance does not match " "the number of nutrients") if self.nutrientValue.numColumns() != M: raise ValueError("Number of rows in nutrient_value does not " "match the number of foods") if self.nutrientValue.numRows() != N: raise ValueError("Number of columns in nutrient_value does " "not match the number of nutrients") self.__dailyPurchase = self.variable('Daily Purchase', StringSet(self.foods), Domain.greaterThan(0.0)) self.__dailyNutrients = \ self.constraint('Nutrient Balance', StringSet(nutrients), Expr.mul(self.nutrientValue,self.__dailyPurchase), Domain.greaterThan(self.dailyAllowance)) self.objective(ObjectiveSense.Minimize, Expr.sum(self.__dailyPurchase)) finished = True finally: if not finished: self.__del__()
def __init__(self,name, foods, nutrients, daily_allowance, nutritive_value): Model.__init__(self,name) finished = False try: self.foods = [ str(f) for f in foods ] self.nutrients = [ str(n) for n in nutrients ] self.dailyAllowance = numpy.array(daily_allowance, float) self.nutrientValue = Matrix.dense(nutritive_value).transpose() M = len(self.foods) N = len(self.nutrients) if len(self.dailyAllowance) != N: raise ValueError("Length of daily_allowance does not match " "the number of nutrients") if self.nutrientValue.numColumns() != M: raise ValueError("Number of rows in nutrient_value does not " "match the number of foods") if self.nutrientValue.numRows() != N: raise ValueError("Number of columns in nutrient_value does " "not match the number of nutrients") self.__dailyPurchase = self.variable('Daily Purchase', StringSet(self.foods), Domain.greaterThan(0.0)) self.__dailyNutrients = \ self.constraint('Nutrient Balance', StringSet(nutrients), Expr.mul(self.nutrientValue,self.__dailyPurchase), Domain.greaterThan(self.dailyAllowance)) self.objective(ObjectiveSense.Minimize, Expr.sum(self.__dailyPurchase)) finished = True finally: if not finished: self.__del__()
def _update(self, clique_data, parent=None): for c in clique_data['cliques']: self.cliques[c['name']] = v = self.model.variable( c['name'], Domain.inRange(0.0, 1.0), Domain.isInteger()) for img, cmd in product(c['images'], c['commands']): self.by_img_cmd[img, cmd].append(v) self._obj.append(Expr.mul(float(c['time']), v)) if parent is not None: self.model.constraint( 'c-%s-%s' % (c['name'], parent['name']), Expr.sub(v, self.cliques[parent['name']]), Domain.lessThan(0.0)) for child in c['children']: self._update(child, c) for inter in clique_data['intersections']: self.model.constraint('iter-%d' % self._inter, Expr.add([self.cliques[i] for i in inter]), Domain.lessThan(1.0)) self._inter += 1
def __Declare_SpeedUp_Vars(self, COModel): n, N = self.n, 2 * self.m + 2 * self.n + len(self.roads) if self.co_params['speedup']['Tau'] is True: Tau = COModel.variable('Tau', 1, Domain.greaterThan(0.0)) # scalar else: Tau = COModel.variable('Tau', 1, Domain.unbounded()) # scalar if self.co_params['speedup']['Eta'] is True: Eta = COModel.variable('Eta', [n, n], Domain.inPSDCone(n)) # n by n matrix else: Eta = COModel.variable('Eta', [n, n], Domain.unbounded()) # n by n matrix if self.co_params['speedup']['W'] is True: W = COModel.variable('W', [N, N], Domain.inPSDCone(N)) # N by N matrix else: W = COModel.variable('W', [N, N], Domain.unbounded()) # N by N matrix return Tau, Eta, W
def __quad_cone(model, expr1, expr2): model.constraint(Expr.vstack(expr1, expr2), Domain.inQCone())
import json import numpy as np from mosek.fusion import Model, Domain, Expr, ObjectiveSense A = np.array([[-1., 3.], [4., -1.]]) b = np.array([4., 6.]) c = np.array([1., 1.]) with Model('ex2') as M: # variable y y = M.variable('y', 2, Domain.greaterThan(0.)) # constraints M.constraint('c1', Expr.dot(A.T[0, :], y), Domain.greaterThan(c[0])) M.constraint('c2', Expr.dot(A.T[1, :], y), Domain.greaterThan(c[1])) # objective function M.objective('obj', ObjectiveSense.Minimize, Expr.dot(b, y)) # solve M.solve() # solution sol = y.level() # report to json with open('ex2_output.json', 'w') as f: json.dump( { 'solution': {f'y[{i+1}]': yi for i, yi in enumerate(sol)}, 'cost': np.dot(b, sol), }, f)
def solve(self, problem, saver): # Construct model. self.problem = problem self.model = model = Model() if self.time is not None: model.setSolverParam('mioMaxTime', 60.0 * int(self.time)) # x[1,c] = 1 if the master schedule has (null, c) in its first stage # x[s,c1,c2] = 1 if the master schedule has (c1, c2) in stage s > 1 x = {} for s in problem.all_stages: if s == 1: # First arc in the individual image path. for c in problem.commands: x[1,c] = model.variable( 'x[1,%s]' % c, 1, Domain.inRange(0.0, 1.0), Domain.isInteger() ) else: # Other arcs. for c1, c2 in product(problem.commands, problem.commands): if c1 == c2: continue x[s,c1,c2] = model.variable( 'x[%s,%s,%s]' % (s,c1,c2), 1, Domain.inRange(0.0, 1.0), Domain.isInteger() ) smax = max(problem.all_stages) obj = [0.0] # TODO: deal with images that do not have the same number of commands. # t[s,c] is the total time incurred at command c in stage s t = {} for s in problem.all_stages: for c in problem.commands: t[s,c] = model.variable( 't[%s,%s]' % (c,s), 1, Domain.greaterThan(0.0) ) if s == 1: model.constraint('t[1,%s]' % c, Expr.sub(t[1,c], Expr.mul(float(problem.commands[c]), x[1,c])), Domain.greaterThan(0.0) ) else: rhs = [0.0] for c1, coeff in problem.commands.items(): if c1 == c: continue else: rhs = Expr.add(rhs, Expr.mulElm(t[s-1,c1], x[s,c1,c])) model.constraint('t[%s,%s]' % (s,c), Expr.sub(t[1,c], rhs), Domain.greaterThan(0.0) ) # Objective function = sum of aggregate comand times if s == smax: obj = Expr.add(obj, t[s,c]) # y[i,1,c] = 1 if image i starts by going to c # y[i,s,c1,c2] = 1 if image i goes from command c1 to c2 in stage s > 1 y = {} for i, cmds in problem.images.items(): for s in problem.stages[i]: if s == 1: # First arc in the individual image path. for c in cmds: y[i,1,c] = model.variable( 'y[%s,1,%s]' % (i,c), 1, Domain.inRange(0.0, 1.0), Domain.isInteger() ) model.constraint('x_y[i%s,1,c%s]' % (i,c), Expr.sub(x[1,c], y[i,1,c]), Domain.greaterThan(0.0) ) else: # Other arcs. for c1, c2 in product(cmds, cmds): if c1 == c2: continue y[i,s,c1,c2] = model.variable( 'y[%s,%s,%s,%s]' % (i,s,c1,c2), 1, Domain.inRange(0.0, 1.0), Domain.isInteger() ) model.constraint('x_y[i%s,s%s,c%s,c%s]' % (i,s,c1,c2), Expr.sub(x[s,c1,c2], y[i,s,c1,c2]), Domain.greaterThan(0.0) ) for c in cmds: # Each command is an arc destination exactly once. arcs = [y[i,1,c]] for c1 in cmds: if c1 == c: continue arcs.extend([y[i,s,c1,c] for s in problem.stages[i][1:]]) model.constraint('y[i%s,c%s]' % (i,c), Expr.add(arcs), Domain.equalsTo(1.0) ) # Network balance equations (stages 2 to |stages|-1). # Sum of arcs in = sum of arcs out. for s in problem.stages[i][:len(problem.stages[i])-1]: if s == 1: arcs_in = [y[i,1,c]] else: arcs_in = [y[i,s,c1,c] for c1 in cmds if c1 != c] arcs_out = [y[i,s+1,c,c2] for c2 in cmds if c2 != c] model.constraint('y[i%s,s%s,c%s]' % (i,s,c), Expr.sub(Expr.add(arcs_in), Expr.add(arcs_out)), Domain.equalsTo(0.0) ) model.objective('z', ObjectiveSense.Minimize, Expr.add(x.values())) # model.objective('z', ObjectiveSense.Minimize, obj) model.setLogHandler(sys.stdout) model.acceptedSolutionStatus(AccSolutionStatus.Feasible) model.solve() # Create optimal schedule. schedule = defaultdict(list) for i, cmds in problem.images.items(): for s in problem.stages[i]: if s == 1: # First stage starts our walk. for c in cmds: if y[i,s,c].level()[0] > 0.5: schedule[i].append(c) break else: # After that we know what our starting point is. for c2 in cmds: if c2 == c: continue if y[i,s,c,c2].level()[0] > 0.5: schedule[i].append(c2) c = c2 break saver(schedule)
def __rotated_quad_cone(model, expr1, expr2, expr3): model.constraint(Expr.vstack(expr1, expr2, expr3), Domain.inRotatedQCone())
# # Image 3: # x_3_b = 0 # x_3_c = 0 # x_3_d = 0 # # Cliques: # x_23_bcd = 0 # x_123_b = 1 # x_123_b_23_cd = 1 # x_12_a = 0 r = {'A': 5.0, 'B': 10.0, 'C': 7.0, 'D': 12.0} m = Model() binary = (Domain.inRange(0.0, 1.0), Domain.isInteger()) # Provide a variable for each image and command. This is 1 if the command # is not run as part of a clique for the image. x_1_a = m.variable('x_1_a', *binary) x_1_b = m.variable('x_1_b', *binary) x_2_a = m.variable('x_2_a', *binary) x_2_b = m.variable('x_2_b', *binary) x_2_c = m.variable('x_2_c', *binary) x_2_d = m.variable('x_2_d', *binary) x_3_b = m.variable('x_3_b', *binary) x_3_c = m.variable('x_3_c', *binary) x_3_d = m.variable('x_3_d', *binary)
def solve(self, problem, saver): # Construct model. self.problem = problem self.model = model = Model() if self.time is not None: model.setSolverParam('mioMaxTime', 60.0 * int(self.time)) # x[1,c] = 1 if the master schedule has (null, c) in its first stage # x[s,c1,c2] = 1 if the master schedule has (c1, c2) in stage s > 1 x = {} for s in problem.all_stages: if s == 1: # First arc in the individual image path. for c in problem.commands: x[1, c] = model.variable('x[1,%s]' % c, 1, Domain.inRange(0.0, 1.0), Domain.isInteger()) else: # Other arcs. for c1, c2 in product(problem.commands, problem.commands): if c1 == c2: continue x[s, c1, c2] = model.variable('x[%s,%s,%s]' % (s, c1, c2), 1, Domain.inRange(0.0, 1.0), Domain.isInteger()) smax = max(problem.all_stages) obj = [0.0] # TODO: deal with images that do not have the same number of commands. # t[s,c] is the total time incurred at command c in stage s t = {} for s in problem.all_stages: for c in problem.commands: t[s, c] = model.variable('t[%s,%s]' % (c, s), 1, Domain.greaterThan(0.0)) if s == 1: model.constraint( 't[1,%s]' % c, Expr.sub(t[1, c], Expr.mul(float(problem.commands[c]), x[1, c])), Domain.greaterThan(0.0)) else: rhs = [0.0] for c1, coeff in problem.commands.items(): if c1 == c: continue else: rhs = Expr.add( rhs, Expr.mulElm(t[s - 1, c1], x[s, c1, c])) model.constraint('t[%s,%s]' % (s, c), Expr.sub(t[1, c], rhs), Domain.greaterThan(0.0)) # Objective function = sum of aggregate comand times if s == smax: obj = Expr.add(obj, t[s, c]) # y[i,1,c] = 1 if image i starts by going to c # y[i,s,c1,c2] = 1 if image i goes from command c1 to c2 in stage s > 1 y = {} for i, cmds in problem.images.items(): for s in problem.stages[i]: if s == 1: # First arc in the individual image path. for c in cmds: y[i, 1, c] = model.variable('y[%s,1,%s]' % (i, c), 1, Domain.inRange(0.0, 1.0), Domain.isInteger()) model.constraint('x_y[i%s,1,c%s]' % (i, c), Expr.sub(x[1, c], y[i, 1, c]), Domain.greaterThan(0.0)) else: # Other arcs. for c1, c2 in product(cmds, cmds): if c1 == c2: continue y[i, s, c1, c2] = model.variable( 'y[%s,%s,%s,%s]' % (i, s, c1, c2), 1, Domain.inRange(0.0, 1.0), Domain.isInteger()) model.constraint( 'x_y[i%s,s%s,c%s,c%s]' % (i, s, c1, c2), Expr.sub(x[s, c1, c2], y[i, s, c1, c2]), Domain.greaterThan(0.0)) for c in cmds: # Each command is an arc destination exactly once. arcs = [y[i, 1, c]] for c1 in cmds: if c1 == c: continue arcs.extend( [y[i, s, c1, c] for s in problem.stages[i][1:]]) model.constraint('y[i%s,c%s]' % (i, c), Expr.add(arcs), Domain.equalsTo(1.0)) # Network balance equations (stages 2 to |stages|-1). # Sum of arcs in = sum of arcs out. for s in problem.stages[i][:len(problem.stages[i]) - 1]: if s == 1: arcs_in = [y[i, 1, c]] else: arcs_in = [y[i, s, c1, c] for c1 in cmds if c1 != c] arcs_out = [y[i, s + 1, c, c2] for c2 in cmds if c2 != c] model.constraint( 'y[i%s,s%s,c%s]' % (i, s, c), Expr.sub(Expr.add(arcs_in), Expr.add(arcs_out)), Domain.equalsTo(0.0)) model.objective('z', ObjectiveSense.Minimize, Expr.add(x.values())) # model.objective('z', ObjectiveSense.Minimize, obj) model.setLogHandler(sys.stdout) model.acceptedSolutionStatus(AccSolutionStatus.Feasible) model.solve() # Create optimal schedule. schedule = defaultdict(list) for i, cmds in problem.images.items(): for s in problem.stages[i]: if s == 1: # First stage starts our walk. for c in cmds: if y[i, s, c].level()[0] > 0.5: schedule[i].append(c) break else: # After that we know what our starting point is. for c2 in cmds: if c2 == c: continue if y[i, s, c, c2].level()[0] > 0.5: schedule[i].append(c2) c = c2 break saver(schedule)
# x_2_b = 0 # x_2_c = 0 # x_2_d = 0 # # Image 3: # x_3_b = 0 # x_3_c = 0 # x_3_d = 0 # # Cliques: # x_23_bcd = 1 r = {'A': 5.0, 'B': 10.0, 'C': 7.0, 'D': 12.0} m = Model() binary = (Domain.inRange(0.0, 1.0), Domain.isInteger()) # Provide a variable for each image and command. This is 1 if the command # is not run as part of a clique for the image. x_1_a = m.variable('x_1_a', *binary) x_1_b = m.variable('x_1_b', *binary) x_2_a = m.variable('x_2_a', *binary) x_2_b = m.variable('x_2_b', *binary) x_2_c = m.variable('x_2_c', *binary) x_2_d = m.variable('x_2_d', *binary) x_3_b = m.variable('x_3_b', *binary) x_3_c = m.variable('x_3_c', *binary) x_3_d = m.variable('x_3_d', *binary)
import json import numpy as np from mosek.fusion import Model, Domain, Expr, ObjectiveSense A = np.array([[-1., 3.], [4., -1.]]) b = np.array([4., 6.]) c = np.array([1., 1.]) with Model('ex1') as M: # variable x x = M.variable('x', 2, Domain.greaterThan(0.)) # constraints M.constraint('c1', Expr.dot(A[0, :], x), Domain.lessThan(b[0])) M.constraint('c2', Expr.dot(A[1, :], x), Domain.lessThan(b[1])) # objective function M.objective('obj', ObjectiveSense.Maximize, Expr.dot(c, x)) # solve M.solve() # solution sol = x.level() # report to json with open('ex1_output.json', 'w') as f: json.dump({ 'solution': {f'x[{i+1}]': xi for i, xi in enumerate(sol)}, 'cost': np.dot(sol, c), }, f)
# y_a = 0 # y_b = 1 # y_c = 0 # y_d = 0 # # Interactions: # m_2 = 0 # m_3 = 0 # n_b = 1 # n_c = 0 # n_d = 0 r = {'A': 5.0, 'B': 10.0, 'C': 7.0, 'D': 12.0} m = Model() binary = (Domain.inRange(0.0, 1.0), Domain.isInteger()) # Variables to determine if we include commands in the clique. y_a = m.variable('y_a', *binary) y_b = m.variable('y_b', *binary) y_c = m.variable('y_c', *binary) y_d = m.variable('y_d', *binary) # Variables to determine if we include images in the clique. w_1 = m.variable('w_1', *binary) w_2 = m.variable('w_2', *binary) w_3 = m.variable('w_3', *binary) # Variables to enforce relationships between y and w decisions. z_1_a = m.variable('z_1_a', *binary) z_1_b = m.variable('z_1_b', *binary)
def solve(x0, risk_alphas, loadings, srisk, cost_per_trade=DEFAULT_COST, max_risk=0.01): N = len(x0) # don't hold no risk data (likely dead) lim = np.where(srisk.isnull(), 0.0, 1.0) loadings = loadings.fillna(0) srisk = srisk.fillna(0) risk_alphas = risk_alphas.fillna(0) with Model() as m: w = m.variable(N, Domain.inRange(-lim, lim)) longs = m.variable(N, Domain.greaterThan(0)) shorts = m.variable(N, Domain.greaterThan(0)) gross = m.variable(N, Domain.greaterThan(0)) m.constraint( "leverage_consistent", Expr.sub(gross, Expr.add(longs, shorts)), Domain.equalsTo(0), ) m.constraint("net_consistent", Expr.sub(w, Expr.sub(longs, shorts)), Domain.equalsTo(0.0)) m.constraint("leverage_long", Expr.sum(longs), Domain.lessThan(1.0)) m.constraint("leverage_short", Expr.sum(shorts), Domain.lessThan(1.0)) buys = m.variable(N, Domain.greaterThan(0)) sells = m.variable(N, Domain.greaterThan(0)) gross_trade = Expr.add(buys, sells) net_trade = Expr.sub(buys, sells) total_gross_trade = Expr.sum(gross_trade) m.constraint( "net_trade", Expr.sub(w, net_trade), Domain.equalsTo(np.asarray(x0)), # cannot handle series ) # add risk constraint vol = m.variable(1, Domain.lessThan(max_risk)) stacked = Expr.vstack(vol.asExpr(), Expr.mulElm(w, srisk.values)) stacked = Expr.vstack(stacked, Expr.mul(loadings.values.T, w)) m.constraint("vol-cons", stacked, Domain.inQCone()) alphas = risk_alphas.dot(np.vstack([loadings.T, np.diag(srisk)])) gain = Expr.dot(alphas, net_trade) loss = Expr.mul(cost_per_trade, total_gross_trade) m.objective(ObjectiveSense.Maximize, Expr.sub(gain, loss)) m.solve() result = pd.Series(w.level(), srisk.index) return result
def solve(self, problem, saver): # Construct model. self.problem = problem self.model = model = Model() if self.time is not None: model.setSolverParam('mioMaxTime', 60.0 * int(self.time)) # x[i,s,c] = 1 if image i runs command c during stage s, 0 otherwise. self.x = x = {} for i, cmds in problem.images.items(): for s, c in product(problem.stages[i], cmds): x[i,s,c] = model.variable( 'x[%s,%s,%s]' % (i,s,c), 1, Domain.inRange(0.0, 1.0), Domain.isInteger() ) # y[ip,iq,s,c] = 1 if images ip & iq have a shared path through stage # s by running command c during s, 0 otherwise. y = {} for (ip, iq), cmds in problem.shared_cmds.items(): for s, c in product(problem.shared_stages[ip, iq], cmds): y[ip,iq,s,c] = model.variable( 'y[%s,%s,%s,%s]' % (ip,iq,s,c), 1, Domain.inRange(0.0, 1.0), Domain.isInteger() # Domain.inRange(0.0, 1.0) ) # TODO: need to remove presolved commands so the heuristic doesn't try them. # TODO: Add a heuristic initial solution. # TODO: Presolving # Each image one command per stage, and each command once. for i in problem.images: for s in problem.stages[i]: model.constraint('c1[%s,%s]' % (i,s), Expr.add([x[i,s,c] for c in problem.images[i]]), Domain.equalsTo(1.0) ) for c in problem.images[i]: model.constraint('c2[%s,%s]' % (i,c), Expr.add([x[i,s,c] for s in problem.stages[i]]), Domain.equalsTo(1.0) ) # Find shared paths among image pairs. for (ip, iq), cmds in problem.shared_cmds.items(): for s in problem.shared_stages[ip,iq]: for c in cmds: model.constraint('c3[%s,%s,%s,%s]' % (ip,iq,s,c), Expr.sub(y[ip,iq,s,c], x[ip,s,c]), Domain.lessThan(0.0) ) model.constraint('c4[%s,%s,%s,%s]' % (ip,iq,s,c), Expr.sub(y[ip,iq,s,c], x[iq,s,c]), Domain.lessThan(0.0) ) if s > 1: lhs = Expr.add([y[ip,iq,s,c] for c in cmds]) rhs = Expr.add([y[ip,iq,s-1,c] for c in cmds]) model.constraint('c5[%s,%s,%s,%s]' % (ip,iq,s,c), Expr.sub(lhs, rhs), Domain.lessThan(0.0) ) if y: obj = Expr.add(y.values()) else: obj = 0.0 model.objective('z', ObjectiveSense.Maximize, obj) model.setLogHandler(sys.stdout) model.acceptedSolutionStatus(AccSolutionStatus.Feasible) model.solve() # Create optimal schedule. schedule = defaultdict(list) for i, stages in problem.stages.items(): for s in stages: for c in problem.images[i]: if x[i,s,c].level()[0] > 0.5: schedule[i].append(c) break saver(schedule)
# # Images: # w_1 = 0 # w_2 = 1 # w_3 = 1 # # Commands: # y_a = 0 # y_b = 1 # y_c = 1 # y_d = 1 r = {'A': 5.0, 'B': 10.0, 'C': 7.0, 'D': 12.0} m = Model() binary = (Domain.inRange(0.0, 1.0), Domain.isInteger()) # Variables to determine if we include commands in the clique. y_a = m.variable('y_a', *binary) y_b = m.variable('y_b', *binary) y_c = m.variable('y_c', *binary) y_d = m.variable('y_d', *binary) # Variables to determine if we include images in the clique. w_1 = m.variable('w_1', *binary) w_2 = m.variable('w_2', *binary) w_3 = m.variable('w_3', *binary) # Variables to enforce relationships between y and w decisions. z_1_a = m.variable('z_1_a', *binary) z_1_b = m.variable('z_1_b', *binary)
# # Image 2: # x_2_a = 1 # x_2_b = 1 # x_2_c = 1 # x_2_d = 1 # # Image 3: # x_3_b = 1 # x_3_c = 1 # x_3_d = 1 r = {'A': 5.0, 'B': 10.0, 'C': 7.0, 'D': 12.0} m = Model() binary = (Domain.inRange(0.0, 1.0), Domain.isInteger()) # Provide a variable for each image and command. This is 1 if the command # is not run as part of a clique for the image. x_1_a = m.variable('x_1_a', *binary) x_1_b = m.variable('x_1_b', *binary) x_2_a = m.variable('x_2_a', *binary) x_2_b = m.variable('x_2_b', *binary) x_2_c = m.variable('x_2_c', *binary) x_2_d = m.variable('x_2_d', *binary) x_3_b = m.variable('x_3_b', *binary) x_3_c = m.variable('x_3_c', *binary) x_3_d = m.variable('x_3_d', *binary)
# x_2_d = 0 # # Image 3: # x_3_b = 0 # x_3_c = 0 # x_3_d = 0 # # Cliques: # x_23_bcd = 0 # x_123_b = 1 # x_123_b_23_cd = 1 r = {'A': 5.0, 'B': 10.0, 'C': 7.0, 'D': 12.0} m = Model() binary = (Domain.inRange(0.0, 1.0), Domain.isInteger()) # Provide a variable for each image and command. This is 1 if the command # is not run as part of a clique for the image. x_1_a = m.variable('x_1_a', *binary) x_1_b = m.variable('x_1_b', *binary) x_2_a = m.variable('x_2_a', *binary) x_2_b = m.variable('x_2_b', *binary) x_2_c = m.variable('x_2_c', *binary) x_2_d = m.variable('x_2_d', *binary) x_3_b = m.variable('x_3_b', *binary) x_3_c = m.variable('x_3_c', *binary) x_3_d = m.variable('x_3_d', *binary)