def initialize_model(cost_matrix, cutoff, model=None): #Add dummy detection cost_matrix = np.insert(cost_matrix, 0, np.ones(cost_matrix.shape[0]) * cutoff, axis=1) M, N = cost_matrix.shape if model is None: model = Model() else: model.remove(model.getVars()) model.remove(model.getConstrs()) model.setParam('OutputFlag', False) # y = [] # for i in range(M): # y.append([]) # for j in range(N): # y[i].append(m.addVar(vtype=GRB.BINARY, name = 'y_%d%d'%(i,j))) y = model.addVars(M, N, vtype=GRB.BINARY, name='y') model.setObjective( quicksum( quicksum([y[i, j] * cost_matrix[i][j] for j in range(N)]) for i in range(M)), GRB.MINIMIZE) # for i in range(M): model.addConstrs( (quicksum(y[i, j] for j in range(N)) == 1 for i in range(M)), name='constraint for track') # for j in range(1,N): model.addConstrs( (quicksum(y[i, j] for i in range(M)) <= 1 for j in range(1, N)), name='constraint for detection') y = list(y.values()) return model, M, N, y
class Master: """ Master Object for initialising, solving, updating, and column creation of the tail assignment master problem""" def __init__(self, Data): """Formulate the master problem. INPUTS Data :: object, classes.Data; problem data. """ self.Data = Data self.duals = [] self.master = Model("master LP") # Init master model self.master.Params.OutputFlag = 0 # No output self._formulate_master() def _formulate_master(self): """ Formulate set partitioning model for tail assignment""" # Variable dicts # a_dict = {(s_label[1], s): s.cost for s_label, s in self.Data.scheds.items()} dum_dict = { f: 20000 + 20000 * (f.arrival - f.departure) for f in self.Data.flights } # VARIABLES # a = self.master.addVars(a_dict.keys(), name="a", vtype="B") dummy = self.master.addVars(dum_dict.keys(), name="dummy", vtype="B") # OBJECTIVE FUNCTION # self.master.setObjective(dummy.prod(dum_dict)) # FLIGHT CONSTRAINTS # self.master.addConstrs((dummy[key] >= 1 for key in dum_dict), name='flight') # AIRCRAFT CONSTRAINTS # self.master.addConstrs( (a.sum(k, '*') <= 1 for k in self.Data.aircraft), name='aircraft_schedule') self.master.update() # write to file self.master.write("./output/init.lp") def _solve_relax(self): """ Relaxes and solves the master problem. INPUTS master :: object, gurobipy.Model; master problem. RETURNS duals :: list of tuples, (dual, classes.Flight) relax :: object, gurobipy.Model; relaxed master problem. """ self.relax = self.master.relax() self.relax.update() self.relax.optimize() duals = [(float(c.Pi), [ f for f in self.Data.flights if f.i_d == self._split(c.ConstrName) ][0]) for c in self.relax.getConstrs() if "flight" in c.ConstrName] duals = sorted(duals, key=lambda x: x[1].i_d) self.duals.append([d[0] for d in duals]) return self.relax, duals def _generate_column(self, k, it, path): """ Adds column using shortest path from extended TSN. Parameters ---------- k : str, aircraft in subproblem it : int, iteration number path : list, edges in shortest path [(edge_dict, edge_weight), ..] Returns ------- master : object, gurobipy.Model; updated master problem with new column """ col = Column() # Init Column flights = self.Data.flights cost_col = 0 # count number of dummy edges for column obj coeff for p in path: # for each flight in the path if any(f._full_dict() == p[0] for f in flights): flight = [f for f in flights if f._full_dict() == p[0]][0] # Get constraints associated with flight constrs = [ c for c in self.master.getConstrs() if "flight" in c.ConstrName and self._split(c.ConstrName) == flight.i_d ] # Add terms to column for each constraint col.addTerms([1] * len(constrs), constrs) else: cost_col += p[1] # Get constraints associated with aircraft k constr = [ c for c in self.master.getConstrs() if "aircraft_schedule" in c.ConstrName and k in c.ConstrName ][0] col.addTerms(1, constr) # Get aircraft dual for cost lambda_k = [ float(c.Pi) for c in self.relax.getConstrs() if "aircraft_schedule" in c.ConstrName and k in c.ConstrName ][0] # cost of path + 2 due to first edge initialisation cost = 2 + sum(p[1] for p in path) - lambda_k if cost < 0: self.master.addVar(obj=cost_col, vtype="B", name="a[%s,s_%s_%s]" % (k, it, k), column=col) self.master.update() return self, cost @staticmethod def _split(string): """ Split integers in string and return last occurrence""" import re return list(map(int, re.findall(r'\d+', string)))[-1]
for k in K: prt.print_aggregated_fs_aircraft_schedule(airports, N, A, last_hour, k, n, y, instance, images_dir) print("\n########### SECOND STAGE SCHEDULE ##########") for s in S: print("###### Scenario {} #####".format(s)) for k in K: prt.print_aggregated_ss_aircraft_schedule( airports, N, A, last_hour, k, n, y, s, instance, images_dir) if write_cargo_routing: wrt.write_cargo_schedule(ods_dir, "Schedule ODs i-{}.txt".format(instance), A, S, Cargo, OD, ex, x) if write_retimings: wrt.write_retimings(retimings_dir, "Retimings i-{}.txt".format(instance), S, AF, V, K, y, r, zplus, zminus) else: print('Optimization was stopped with status {}'.format(status)) # compute Irreducible Inconsistent Subsystem model.computeIIS() for constr in model.getConstrs(): if constr.IISConstr: print('Infeasible constraint: {}'.format(constr.constrName))
from gurobipy import Model, GRB m = Model("hw51") x1 = m.addVar(name="x1") x2 = m.addVar(name="x2") m.update() m.setObjective(5 * x1 + 4 * x2, GRB.MAXIMIZE) m.addConstr(6 * x1 + 4 * x2 <= 24, 'constraint1') m.addConstr(x1 + 2 * x2 <= 6, 'constraint2') m.addConstr(-x1 + x2 <= 1, 'constraint3') m.addConstr(x2 <= 2, ' constraint4') m.optimize() for v in m.getVars(): print('%s: %f' % (v.varName, v.x)) print('Obj: %f' % m.objVal) print 'reduced costs: ' print ' ', m.getAttr('rc', m.getVars()) print 'shadow prices: ' print ' ', m.getAttr('pi', m.getConstrs())
obj = quicksum( quicksum(p[i] * quicksum(v[i, j, t] for j in j_c[:u[i]]) + P[i] * quicksum(v[i, j, t] for j in j_c[u[i]:U[i]]) - Q[i] * w[i, t] - C[i] * n[i, t] - Z[i] * Gamma[i, t] for i in i_c) - E * Beta[t] - k * Lambda[t] for t in t_c[1:]) model.setObjective(obj, GRB.MAXIMIZE) model.write("model.lp") # optimizar model.optimize() # resultados # model.printAttr("X") vars = [(i, var) for i, var in enumerate(model.getVars())] with open("holguras.txt", "w") as file: with open("antiholguras.txt", "w") as antifile: for x in model.getConstrs(): if round(x.slack, 10) == 0: if x.sense != "=": file.write(f"{x.ConstrName} {x.slack}\n") else: antifile.write(f"{x.ConstrName} {x.slack}\n") with open("resultados.txt", "w") as file: file.write(f"{model.objVal}\n") for var in vars: if ("Beta" in var[1].varName or "Gamma" in var[1].varName) or "Lambda" in var[1].varName: file.write('%s %g' % (var[1].varName, var[1].x) + "\n") if "total" in var[1].varName: print('%s %g' % (var[1].varName, var[1].x) + "\n")
def generate_multi_dim_sample(bounds, directory, num_teams, num_md_per_cycle, numSam, numCycle, theoretical): # the list of sample dimensions, the +1 cycle = list(range(numCycle)) day = list(range(num_md_per_cycle)) days = list(range(num_md_per_cycle + 1)) home = away = list(range(num_teams)) constrList = [ [(0, ), (1, )], [(0, ), (2, )], [(0, ), (3, )], [(0, ), (1, 2)], [(0, ), (1, 3)], [(0, ), (2, 3)], [(0, ), (1, 2, 3)], [(1, ), (0, )], [(1, ), (2, )], [(1, ), (3, )], [(1, ), (0, 2)], [(1, ), (0, 3)], [(1, ), (2, 3)], [(1, ), (0, 2, 3)], [(2, ), (0, )], [(2, ), (1, )], [(2, ), (3, )], [(2, ), (0, 1)], [(2, ), (0, 3)], [(2, ), (1, 3)], [(2, ), (0, 1, 3)], [(3, ), (0, )], [(3, ), (1, )], [(3, ), (2, )], [(3, ), (0, 1)], [(3, ), (0, 2)], [(3, ), (1, 2)], [(3, ), (0, 1, 2)], [(0, 1), (2, )], [(0, 1), (3, )], [(0, 1), (2, 3)], # cons away = 31 [(0, 2), (1, )], [(0, 2), (3, )], [(0, 2), (1, 3)], # cons home = 34 [(0, 3), (1, )], [(0, 3), (2, )], [(0, 3), (1, 2)], [(1, 2), (0, )], [(1, 2), (3, )], [(1, 2), (0, 3)], [(1, 3), (0, )], [(1, 3), (2, )], [(1, 3), (0, 2)], [(2, 3), (0, )], [(2, 3), (1, )], [(2, 3), (0, 1)], [(0, 1, 2), (3, )], [(0, 1, 3), (2, )], [(0, 2, 3), (1, )], [(1, 2, 3), (0, )] ] try: model = Model("sspSolver") # give verbose logging when 1, otherwise 0 model.setParam(GRB.param.OutputFlag, 1) ### Decision Variables ### # 0 = cycles, 1 = days, 2 = away, 3 = home # regular combinations over the 4 dimensions x = model.addVars(cycle, day, home, away, vtype=GRB.BINARY, name="base") n = model.addVars(cycle, day, home, vtype=GRB.BINARY, name="n") o = model.addVars(cycle, day, away, vtype=GRB.BINARY, name="o") p = model.addVars(cycle, home, away, vtype=GRB.BINARY, name="p") q = model.addVars(day, home, away, vtype=GRB.BINARY, name="q") r = model.addVars(cycle, day, vtype=GRB.BINARY, name="r") s = model.addVars(cycle, home, vtype=GRB.BINARY, name="s") t = model.addVars(cycle, away, vtype=GRB.BINARY, name="t") u = model.addVars(day, home, vtype=GRB.BINARY, name="u") v = model.addVars(day, away, vtype=GRB.BINARY, name="v") w = model.addVars(home, away, vtype=GRB.BINARY, name="w") #y = model.addVars(cycle, day, home, away, vtype=GRB.BINARY, name="basetrans") #yn = model.addVars(cycle, day, home, vtype=GRB.BINARY, name="trans_n") cNA = model.addVars(cycle, day, day, away, vtype=GRB.BINARY, name="cons") cNAs = model.addVars(cycle, days, day, away, vtype=GRB.BINARY, name="cons_min") cNH = model.addVars(cycle, day, day, home, vtype=GRB.BINARY, name="consHome") cNHs = model.addVars(cycle, days, day, home, vtype=GRB.BINARY, name="consHomes") cZy = model.addVars(cycle, day, day, home, vtype=GRB.BINARY, name="days_betw_games") cZys = model.addVars(cycle, days, day, home, vtype=GRB.BINARY, name="days_btw_gamess") # transpose function #model.addConstrs( # y[c, d, h, a] == x[c, d, h, a] + x[c, d, a, h] for c in cycle for d in day for a in away for h in home) #model.addConstrs((y.sum(c, d, h, '*') == yn[c, d, h] for c in cycle for d in day for h in home), "yn_y") model.addConstrs((x.sum(c, d, '*', a) == o[c, d, a] for c in cycle for d in day for a in away), "xo") model.addConstrs((x.sum(c, d, h, '*') == n[c, d, h] for c in cycle for d in day for h in home), "xn") model.addConstrs((x.sum(c, '*', h, a) == p[c, h, a] for c in cycle for h in home for a in away), "xp") model.addConstrs((x.sum('*', d, h, a) == q[d, h, a] for d in day for h in home for a in away), "xq") model.addConstrs( (r[c, d] <= n.sum(c, d, '*') for c in cycle for d in day), "rn") model.addConstrs( (t[c, a] <= n.sum(c, '*', a) for c in cycle for a in away), "tn") model.addConstrs( (v[d, a] <= n.sum('*', d, a) for d in day for a in away), "vn") model.addConstrs( (r[c, d] <= o.sum(c, d, '*') for c in cycle for d in day), "ro") model.addConstrs( (s[c, h] <= o.sum(c, '*', h) for c in cycle for h in home), "so") model.addConstrs( (u[d, h] <= o.sum('*', d, h) for d in day for h in home), "uo") model.addConstrs( (s[c, h] <= p.sum(c, h, '*') for c in cycle for h in home), "sp") model.addConstrs( (t[c, a] <= p.sum(c, '*', a) for c in cycle for a in away), "tp") model.addConstrs( (w[h, a] <= p.sum('*', h, a) for h in home for a in away), "wp") model.addConstrs( (u[d, h] <= q.sum(d, h, '*') for d in day for h in home), "uq") model.addConstrs( (v[d, a] <= q.sum(d, '*', a) for d in day for a in away), "vq") model.addConstrs( (w[h, a] <= q.sum('*', h, a) for h in home for a in away), "wq") if theoretical: ### Hard constraints -- not yet in bounds ### # never play yourself model.addConstrs(x[c, d, i, i] == 0 for c in cycle for d in day for i in home) # only play one game per day model.addConstrs((x.sum(c, d, i, '*') + x.sum(c, d, '*', i) <= 1 for c in cycle for d in day for i in home), "1gamePerDay") # Hard constraints from bounds files ### # bounds 0 = countLowerbound # bounds 1 = countUpperBound # bounds 2 = minConsZero # bounds 3 = maxConsZero # bounds 4 = minConsNonZero # bounds 5 = maxConsNonZero for i in range(len(bounds)): ### SEED COUNT BOUNDS: bounds[i,0] is the lowerbound, bounds[i,1] is the upperbound if bounds[i, 0] > 0: # this part covers count lowerbound if constrList[i] == [(0, ), (1, )]: model.addConstrs((r.sum(c, '*') >= bounds[i, 0] for c in cycle), "LWR_constr-(0,), (1,)") elif constrList[i] == [(0, ), (2, )]: model.addConstrs((t.sum(c, '*') >= bounds[i, 0] for c in cycle), "LWR_constr-(0,), (2,)") elif constrList[i] == [(0, ), (3, )]: model.addConstrs((s.sum(c, '*') >= bounds[i, 0] for c in cycle), "LWR_constr-(0,), (3,)") elif constrList[i] == [(0, ), (1, 2)]: model.addConstrs( (o.sum(c, '*', '*') >= bounds[i, 0] for c in cycle), "LWR_constr-(0,), (1,2)") elif constrList[i] == [(0, ), (1, 3)]: model.addConstrs( (n.sum(c, '*', '*') >= bounds[i, 0] for c in cycle), "LWR_constr-(0,), (1,3)") elif constrList[i] == [(0, ), (2, 3)]: model.addConstrs( (p.sum(c, '*', '*') >= bounds[i, 0] for c in cycle), "LWR_constr-(0,), (2,3)") elif constrList[i] == [(0, ), (1, 2, 3)]: model.addConstrs((x.sum(c, '*', '*', '*') >= bounds[i, 0] for c in cycle), "LWR_constr-(0,), (1,2,3)") elif constrList[i] == [(1, ), (0, )]: model.addConstrs((r.sum('*', d) >= bounds[i, 0] for d in day), "LWR_constr-(1,), (0,)") elif constrList[i] == [(1, ), (2, )]: model.addConstrs((v.sum(d, '*') >= bounds[i, 0] for d in day), "LWR_constr-(1,), (2,)") elif constrList[i] == [(1, ), (3, )]: model.addConstrs((u.sum(d, '*') >= bounds[i, 0] for d in day), "LWR_constr-(1,), (3,)") elif constrList[i] == [(1, ), (0, 2)]: model.addConstrs((o.sum('*', d, '*') >= bounds[i, 0] for d in day), "LWR_constr-(1,), (0,2)") elif constrList[i] == [(1, ), (0, 3)]: model.addConstrs((n.sum('*', d, '*') >= bounds[i, 0] for d in day), "LWR_constr-(1,), (0,3)") elif constrList[i] == [(1, ), (2, 3)]: model.addConstrs((q.sum(d, '*', '*') >= bounds[i, 0] for d in day), "LWR_constr-(1,), (2,3)") elif constrList[i] == [(1, ), (0, 2, 3)]: model.addConstrs( (x.sum('*', d, '*', '*') >= bounds[i, 0] for d in day), "LWR_constr-(1,), (0,2,3)") elif constrList[i] == [(2, ), (0, )]: model.addConstrs((t.sum('*', h) >= bounds[i, 0] for h in home), "LWR_constr-(2,), (0,)") elif constrList[i] == [(2, ), (1, )]: model.addConstrs((v.sum('*', h) >= bounds[i, 0] for h in home), "LWR_constr-(2,), (1,)") elif constrList[i] == [(2, ), (3, )]: model.addConstrs((w.sum(h, '*') >= bounds[i, 0] for h in home), "LWR_constr--(2,), (3,)") elif constrList[i] == [(2, ), (0, 1)]: model.addConstrs( (o.sum('*', '*', h) >= bounds[i, 0] for h in home), "LWR_constr--(2,), (0,1)") elif constrList[i] == [(2, ), (0, 3)]: model.addConstrs( (p.sum('*', h, '*') >= bounds[i, 0] for h in home), "LWR_constr--(2,), (0,3)") elif constrList[i] == [(2, ), (1, 3)]: model.addConstrs((q.sum('*', h, '*') >= bounds[i, 0] for h in home), "LWR_constr-(2,), (1,3)") elif constrList[i] == [(2, ), (0, 1, 3)]: model.addConstrs((x.sum('*', '*', h, '*') >= bounds[i, 0] for h in home), "LWR_constr-(2,), (0,1,3)") elif constrList[i] == [(3, ), (0, )]: model.addConstrs((s.sum('*', a) >= bounds[i, 0] for a in away), "LWR_constr-(3,), (0,)") elif constrList[i] == [(3, ), (1, )]: model.addConstrs((u.sum('*', a) >= bounds[i, 0] for a in away), "LWR_constr-(3,), (1,)") elif constrList[i] == [(3, ), (2, )]: model.addConstrs((w.sum('*', a) >= bounds[i, 0] for a in away), "LWR_constr-(3,), (2,)") elif constrList[i] == [(3, ), (0, 1)]: model.addConstrs((n.sum('*', '*', a) >= bounds[i, 0] for a in away), "LWR_constr-(3,), (0,1)") elif constrList[i] == [(3, ), (0, 2)]: model.addConstrs((p.sum('*', '*', a) >= bounds[i, 0] for a in away), "LWR_constr-(3,), (0,2)") elif constrList[i] == [(3, ), (1, 2)]: model.addConstrs((q.sum('*', '*', a) >= bounds[i, 0] for a in away), "LWR_constr-(3,), (1,2)") elif constrList[i] == [(3, ), (0, 1, 2)]: model.addConstrs((x.sum('*', '*', '*', a) >= bounds[i, 0] for a in away), "LWR_constr-(3,), (0,1,2)") elif constrList[i] == [(0, 1), (2, )]: model.addConstrs((o.sum(c, d, '*') >= bounds[i, 0] for c in cycle for d in day), "LWR_constr-(0,1), (2,)") elif constrList[i] == [(0, 1), (3, )]: model.addConstrs((n.sum(c, d, '*') >= bounds[i, 0] for c in cycle for d in day), "LWR_constr-(0,1), (3,)") elif constrList[i] == [(0, 1), (2, 3)]: model.addConstrs((x.sum(c, d, '*', '*') >= bounds[i, 0] for c in cycle for d in day), "LWR_constr-(0,1), (2,3)") elif constrList[i] == [(0, 2), (1, )]: bound = bounds[i, 0] model.addConstrs((o.sum(c, '*', a) >= bounds[i, 0] for c in cycle for a in away), "LWR_constr-(0,2), (1,)") elif constrList[i] == [(0, 2), (3, )]: model.addConstrs((p.sum(c, '*', a) >= bounds[i, 0] for c in cycle for a in away), "LWR_constr-(0,2), (3,)") elif constrList[i] == [(0, 2), (1, 3)]: model.addConstrs((x.sum(c, '*', a) >= bounds[i, 0] for c in cycle for a in away), "LWR_constr-(0,2), (1,3)") elif constrList[i] == [(0, 3), (1, )]: model.addConstrs((n.sum(c, '*', h) >= bounds[i, 0] for c in cycle for h in home), "LWR_constr-(0,3), (1,)") elif constrList[i] == [(0, 3), (2, )]: model.addConstrs((p.sum(c, '*', h) >= bounds[i, 0] for c in cycle for h in home), "LWR_constr-(0,3), (2,)") elif constrList[i] == [(0, 3), (1, 2)]: model.addConstrs((x.sum(c, '*', '*', h) >= bounds[i, 0] for c in cycle for h in home), "LWR_constr-(0,3), (1,2)") elif constrList[i] == [(1, 2), (0, )]: model.addConstrs((o.sum('*', d, a) >= bounds[i, 0] for d in day for a in away), "LWR_constr-(1,2), (0,)") elif constrList[i] == [(1, 2), (3, )]: model.addConstrs((q.sum(d, a, '*') >= bounds[i, 0] for d in day for a in away), "LWR_constr-(1,2), (3,)") elif constrList[i] == [(1, 2), (0, 3)]: model.addConstrs((x.sum('*', d, a, '*') >= bounds[i, 0] for d in day for a in away), "LWR_constr-(1,2), (0,3)") elif constrList[i] == [(1, 3), (0, )]: model.addConstrs((n.sum('*', d, h) >= bounds[i, 0] for d in day for h in home), "LWR_constr-(1,3), (0,)") elif constrList[i] == [(1, 3), (2, )]: model.addConstrs((q.sum(d, '*', h) >= bounds[i, 0] for d in day for h in home), "LWR_constr-(1,3), (2,)") elif constrList[i] == [(1, 3), (0, 2)]: model.addConstrs((x.sum('*', d, '*', h) >= bounds[i, 0] for d in day for h in home), "LWR_constr-(1,3), (0,2)") elif constrList[i] == [(2, 3), (0, )]: model.addConstrs((p.sum('*', h, a) >= bounds[i, 0] for h in home for a in away), "LWR_constr-(2,3), (0,)") elif constrList[i] == [(2, 3), (1, )]: model.addConstrs((q.sum('*', h, a) >= bounds[i, 0] for h in home for a in away), "LWR_constr-(2,3), (1,)") elif constrList[i] == [(2, 3), (0, 1)]: model.addConstrs((x.sum('*', '*', h, a) >= bounds[i, 0] for h in home for a in away), "LWR_constr-(2,3), (0,1)") elif constrList[i] == [(0, 1, 2), (3, )]: model.addConstrs((x.sum(c, d, a, '*') >= bounds[i, 0] for c in cycle for d in day for a in away), "LWR_constr-(0,1,2), (3,)") elif constrList[i] == [(0, 1, 3), (2, )]: model.addConstrs((x.sum(c, d, '*', h) >= bounds[i, 0] for c in cycle for d in day for h in home), "LWR_constr-(0,1,3), (2,)") elif constrList[i] == [(0, 2, 3), (1, )]: model.addConstrs((x.sum(c, '*', a, h) >= bounds[i, 0] for c in cycle for a in away for h in home), "LWR_constr-(0,2,3), (1,)") elif constrList[i] == [(1, 2, 3), (0, )]: model.addConstrs((x.sum('*', d, a, h) >= bounds[i, 0] for d in day for a in away for h in home), "LWR_constr-(1,2,3), (0,)") if bounds[i, 1] > 0: # this part covers count lowerbound if constrList[i] == [(0, ), (1, )]: model.addConstrs((r.sum(c, '*') <= bounds[i, 1] for c in cycle), "constr-(0,), (1,)") elif constrList[i] == [(0, ), (2, )]: model.addConstrs((t.sum(c, '*') <= bounds[i, 1] for c in cycle), "constr-(0,), (2,)") elif constrList[i] == [(0, ), (3, )]: model.addConstrs((s.sum(c, '*') <= bounds[i, 1] for c in cycle), "constr-(0,), (3,)") elif constrList[i] == [(0, ), (1, 2)]: model.addConstrs((o.sum(c, '*', '*') <= bounds[i, 1] for c in cycle), "constr-(0,), (1,2)") elif constrList[i] == [(0, ), (1, 3)]: model.addConstrs((n.sum(c, '*', '*') <= bounds[i, 1] for c in cycle), "constr-(0,), (1,3)") elif constrList[i] == [(0, ), (2, 3)]: model.addConstrs((p.sum(c, '*', '*') <= bounds[i, 1] for c in cycle), "constr-(0,), (2,3)") elif constrList[i] == [(0, ), (1, 2, 3)]: model.addConstrs((x.sum(c, '*', '*', '*') <= bounds[i, 1] for c in cycle), "constr-(0,), (1,2,3)") elif constrList[i] == [(1, ), (0, )]: model.addConstrs((r.sum('*', d) <= bounds[i, 1] for d in day), "LWR_constr-(1,), (0,)") elif constrList[i] == [(1, ), (2, )]: model.addConstrs((v.sum(d, '*') <= bounds[i, 1] for d in day), "LWR_constr-(1,), (2,)") elif constrList[i] == [(1, ), (3, )]: model.addConstrs((u.sum(d, '*') <= bounds[i, 1] for d in day), "LWR_constr-(1,), (3,)") elif constrList[i] == [(1, ), (0, 2)]: model.addConstrs((o.sum('*', d, '*') <= bounds[i, 1] for d in day), "LWR_constr-(1,), (0,2)") elif constrList[i] == [(1, ), (0, 3)]: model.addConstrs((n.sum('*', d, '*') <= bounds[i, 1] for d in day), "LWR_constr-(1,), (0,3)") elif constrList[i] == [(1, ), (2, 3)]: model.addConstrs((q.sum(d, '*', '*') <= bounds[i, 1] for d in day), "LWR_constr-(1,), (2,3)") elif constrList[i] == [(1, ), (0, 2, 3)]: model.addConstrs( (x.sum('*', d, '*', '*') <= bounds[i, 1] for d in day), "LWR_constr-(1,), (0,2,3)") elif constrList[i] == [(2, ), (0, )]: model.addConstrs((t.sum('*', h) <= bounds[i, 1] for h in home), "constr-(2,), (0,)") elif constrList[i] == [(2, ), (1, )]: model.addConstrs((v.sum('*', h) <= bounds[i, 1] for h in home), "constr-(2,), (1,)") elif constrList[i] == [(2, ), (3, )]: model.addConstrs((w.sum(h, '*') <= bounds[i, 1] for h in home), "constr--(2,), (3,)") elif constrList[i] == [(2, ), (0, 1)]: model.addConstrs((o.sum('*', '*', h) <= bounds[i, 1] for h in home), "constr--(2,), (0,1)") elif constrList[i] == [(2, ), (0, 3)]: model.addConstrs((p.sum('*', h, '*') <= bounds[i, 1] for h in home), "constr--(2,), (0,3)") elif constrList[i] == [(2, ), (1, 3)]: model.addConstrs((q.sum('*', h, '*') <= bounds[i, 1] for h in home), "constr-(2,), (1,3)") elif constrList[i] == [(2, ), (0, 1, 3)]: model.addConstrs((x.sum('*', '*', h, '*') <= bounds[i, 1] for h in home), "LWR_constr-(2,), (0,1,3)") elif constrList[i] == [(3, ), (0, )]: model.addConstrs((s.sum('*', a) <= bounds[i, 1] for a in away), "constr-(3,), (0,)") elif constrList[i] == [(3, ), (1, )]: model.addConstrs((u.sum('*', a) <= bounds[i, 1] for a in away), "constr-(3,), (1,)") elif constrList[i] == [(3, ), (2, )]: model.addConstrs((w.sum('*', a) <= bounds[i, 1] for a in away), "constr-(3,), (2,)") elif constrList[i] == [(3, ), (0, 1)]: model.addConstrs((n.sum('*', '*', a) <= bounds[i, 1] for a in away), "constr-(3,), (0,1)") elif constrList[i] == [(3, ), (0, 2)]: model.addConstrs((p.sum('*', '*', a) <= bounds[i, 1] for a in away), "constr-(3,), (0,2)") elif constrList[i] == [(3, ), (1, 2)]: model.addConstrs((q.sum('*', '*', a) <= bounds[i, 1] for a in away), "constr-(3,), (1,2)") elif constrList[i] == [(3, ), (0, 1, 2)]: model.addConstrs((x.sum('*', '*', '*', a) <= bounds[i, 1] for a in away), "constr-(3,), (0,1,2)") elif constrList[i] == [(0, 1), (2, )]: model.addConstrs((o.sum(c, d, '*') <= bounds[i, 1] for c in cycle for d in day), "constr-(0,1), (2,)") elif constrList[i] == [(0, 1), (3, )]: model.addConstrs((n.sum(c, d, '*') <= bounds[i, 1] for c in cycle for d in day), "constr-(0,1), (3,)") elif constrList[i] == [(0, 1), (2, 3)]: model.addConstrs((x.sum(c, d, '*', '*') <= bounds[i, 1] for c in cycle for d in day), "constr-(0,1), (2,3)") elif constrList[i] == [(0, 2), (1, )]: model.addConstrs((o.sum(c, '*', a) <= bounds[i, 1] for c in cycle for a in away), "constr-(0,2), (1,)") elif constrList[i] == [(0, 2), (3, )]: model.addConstrs((p.sum(c, '*', a) <= bounds[i, 1] for c in cycle for a in away), "constr-(0,2), (3,)") elif constrList[i] == [(0, 2), (1, 3)]: model.addConstrs((x.sum(c, '*', a) <= bounds[i, 1] for c in cycle for a in away), "constr-(0,2), (1,3)") elif constrList[i] == [(0, 3), (1, )]: model.addConstrs((n.sum(c, '*', h) <= bounds[i, 1] for c in cycle for h in home), "constr-(0,3), (1,)") elif constrList[i] == [(0, 3), (2, )]: model.addConstrs((p.sum(c, '*', h) <= bounds[i, 1] for c in cycle for h in home), "constr-(0,3), (2,)") elif constrList[i] == [(0, 3), (1, 2)]: model.addConstrs((x.sum(c, '*', '*', h) <= bounds[i, 1] for c in cycle for h in home), "constr-(0,3), (1,2)") elif constrList[i] == [(1, 2), (0, )]: model.addConstrs((o.sum('*', d, a) <= bounds[i, 1] for d in day for a in away), "constr-(1,2), (0,)") elif constrList[i] == [(1, 2), (3, )]: model.addConstrs((q.sum(d, a, '*') <= bounds[i, 1] for d in day for a in away), "constr-(1,2), (3,)") elif constrList[i] == [(1, 2), (0, 3)]: model.addConstrs((x.sum('*', d, a, '*') <= bounds[i, 1] for d in day for a in away), "constr-(1,2), (0,3)") elif constrList[i] == [(1, 3), (0, )]: model.addConstrs((n.sum('*', d, h) <= bounds[i, 1] for d in day for h in home), "constr-(1,3), (0,)") elif constrList[i] == [(1, 3), (2, )]: model.addConstrs((q.sum(d, '*', h) <= bounds[i, 1] for d in day for h in home), "constr-(1,3), (2,)") elif constrList[i] == [(1, 3), (0, 2)]: model.addConstrs((x.sum('*', d, '*', h) <= bounds[i, 1] for d in day for h in home), "constr-(1,3), (0,2)") elif constrList[i] == [(2, 3), (0, )]: model.addConstrs((p.sum('*', h, a) <= bounds[i, 1] for h in home for a in away), "constr-(2,3), (0,)") elif constrList[i] == [(2, 3), (1, )]: model.addConstrs((q.sum('*', h, a) <= bounds[i, 1] for h in home for a in away), "constr-(2,3), (1,)") elif constrList[i] == [(2, 3), (0, 1)]: model.addConstrs((x.sum('*', '*', h, a) <= bounds[i, 1] for h in home for a in away), "constr-(2,3), (0,1)") elif constrList[i] == [(0, 1, 2), (3, )]: model.addConstrs((x.sum(c, d, a, '*') <= bounds[i, 1] for c in cycle for d in day for a in away), "constr-(0,1,2), (3,)") elif constrList[i] == [(0, 1, 3), (2, )]: model.addConstrs((x.sum(c, d, '*', h) <= bounds[i, 1] for c in cycle for d in day for h in home), "constr-(0,1,3), (2,)") elif constrList[i] == [(0, 2, 3), (1, )]: model.addConstrs((x.sum(c, '*', a, h) <= bounds[i, 1] for c in cycle for a in away for h in home), "constr-(0,2,3), (1,)") elif constrList[i] == [(1, 2, 3), (0, )]: model.addConstrs((x.sum('*', d, a, h) <= bounds[i, 1] for d in day for a in away for h in home), "constr-(1,2,3), (0,)") if bounds[34, 5] + bounds[34, 4] > 0: # definition for the first day model.addConstrs((cNH[c, 0, 0, h] == n[c, 0, h] for c in cycle for h in home), "cNH1") model.addConstrs((cNH[c, d1 + 1, 0, h] <= n[c, d1 + 1, h] for c in cycle for h in home for d1 in day if d1 < len(day) - 1), "cNA2") model.addConstrs((cNH[c, d1 + 1, 0, h] <= 1 - n[c, d1, h] for c in cycle for h in home for d1 in day if d1 < len(day) - 1), "cNA3") model.addConstrs( (cNH[c, d1 + 1, 0, h] >= n[c, d1 + 1, h] - n[c, d1, h] for c in cycle for d1 in day for h in home if d1 < len(day) - 1), "cNA4") # # definition for the second day and the third, fourth, etc... model.addConstrs((cNH[c, 0, d2, h] == 0 for c in cycle for d2 in day for h in home if d2 > 0), "2cNA1") model.addConstrs((cNH[c, d1, d2, h] <= cNH[c, d1 - 1, d2 - 1, h] for c in cycle for h in home for d1 in day for d2 in day if d1 > 0 if d2 > 0)) model.addConstrs((cNH[c, d1, d2, h] <= n[c, d1, h] for c in cycle for d1 in day for d2 in day for h in home if d1 > 0 if d2 > 0)) model.addConstrs((cNH[c, d1, d2, h] >= n[c, d1, h] + cNH[c, d1 - 1, d2 - 1, h] - 1 for c in cycle for d1 in day for d2 in day for h in home if d1 > 0 if d2 > 0)) if bounds[34, 5] > 0: model.addConstr((quicksum( cNH[c, d1, d2, a] for c in cycle for d1 in day for a in away for d2 in range(bounds[34, 5].astype(int), len(day))) == 0), "cnASum") if bounds[34, 4] > 0: model.addConstrs((cNHs[c, 0, d2, h] == 0 for c in cycle for d2 in day for h in home), "minConsPlay") model.addConstrs((cNHs[c, d1, d2, h] <= cNH[c, d1 - 1, d2, h] for c in cycle for h in home for d1 in day for d2 in day if d1 > 0)) model.addConstrs((cNHs[c, d1, d2, h] <= 1 - n[c, d1, h] for c in cycle for d1 in day for d2 in day for h in home if d1 > 0)) model.addConstrs( (cNHs[c, d1, d2, h] >= cNH[c, d1 - 1, d2, h] - n[c, d1, h] for c in cycle for d1 in day for d2 in day for h in home if d1 > 0)) model.addConstrs((cNHs[c, num_md_per_cycle, d2, h] >= cNH[c, num_md_per_cycle - 1, d2, h] for c in cycle for d2 in day for h in home)) model.addConstr((quicksum( cNHs[c, d1, d2, a] * (bounds[34, 4] - 1 - d2) for c in cycle for a in away for d1 in days for d2 in range(bounds[34, 4].astype(int) - 1)) == 0)) if bounds[31, 5] + bounds[31, 4] > 0: # definition for the first day model.addConstrs((cNA[c, 0, 0, a] == o[c, 0, a] for c in cycle for a in away), "cNA1") model.addConstrs((cNA[c, d1 + 1, 0, a] <= o[c, d1 + 1, a] for c in cycle for a in away for d1 in day if d1 < len(day) - 1), "cNA2") model.addConstrs((cNA[c, d1 + 1, 0, a] <= 1 - o[c, d1, a] for c in cycle for a in away for d1 in day if d1 < len(day) - 1), "cNA3") model.addConstrs( (cNA[c, d1 + 1, 0, a] >= o[c, d1 + 1, a] - o[c, d1, a] for c in cycle for d1 in day for a in away if d1 < len(day) - 1), "cNA4") # # definition for the second day and the third, fourth, etc... model.addConstrs((cNA[c, 0, d2, a] == 0 for c in cycle for d2 in day for a in away if d2 > 0), "2cNA1") model.addConstrs((cNA[c, d1, d2, a] <= cNA[c, d1 - 1, d2 - 1, a] for c in cycle for a in away for d1 in day for d2 in day if d1 > 0 if d2 > 0)) model.addConstrs((cNA[c, d1, d2, a] <= o[c, d1, a] for c in cycle for d1 in day for d2 in day for a in away if d1 > 0 if d2 > 0)) model.addConstrs((cNA[c, d1, d2, a] >= o[c, d1, a] + cNA[c, d1 - 1, d2 - 1, a] - 1 for c in cycle for d1 in day for d2 in day for a in away if d1 > 0 if d2 > 0)) if bounds[31, 5] > 0: model.addConstr((quicksum( cNA[c, d1, d2, a] for c in cycle for d1 in day for a in away for d2 in range(bounds[31, 5].astype(int), len(day))) == 0), "cnASum") if bounds[31, 4] > 0: model.addConstrs((cNAs[c, 0, d2, a] == 0 for c in cycle for d2 in day for a in away), "minConsPlay") model.addConstrs((cNAs[c, d1, d2, a] <= cNA[c, d1 - 1, d2, a] for c in cycle for a in away for d1 in day for d2 in day if d1 > 0)) model.addConstrs((cNAs[c, d1, d2, a] <= 1 - o[c, d1, a] for c in cycle for d1 in day for d2 in day for a in away if d1 > 0)) model.addConstrs( (cNAs[c, d1, d2, a] >= cNA[c, d1 - 1, d2, a] - o[c, d1, a] for c in cycle for d1 in day for d2 in day for a in away if d1 > 0)) model.addConstrs((cNAs[c, num_md_per_cycle, d2, a] >= cNA[c, num_md_per_cycle - 1, d2, a] for c in cycle for d2 in day for a in away)) model.addConstr((quicksum( cNAs[c, d1, d2, a] * (bounds[31, 4] - 1 - d2) for c in cycle for a in away for d1 in days for d2 in range(bounds[31, 4].astype(int) - 1)) == 0)) # Sets the number of solutions to be generated model.setParam(GRB.Param.PoolSolutions, numSam) # grab the most optimal solutions model.setParam(GRB.Param.PoolSearchMode, 2) model.optimize() numSol = model.SolCount print("Number of solutions found for the model: " + str(numSol)) if model.status == GRB.Status.INFEASIBLE: model.computeIIS() print("Following constraints are infeasible: ") for c in model.getConstrs(): if c.IISConstr: print(c.constrName) if model.status == GRB.Status.OPTIMAL: model.write('m.sol') for i in range(numSol): model.setParam(GRB.Param.SolutionNumber, i) # get value from subobtimal MIP sol (might change this in X if we dont do soft constraints) solution = model.getAttr('xn', x) tmp = np.zeros([numCycle, num_md_per_cycle, num_teams, num_teams]) for key in solution: tmp[key] = round(solution[key]) tmp_sol = tmp.astype(np.int64) with open(os.path.join(directory, "sol" + str(i) + ".csv"), "w+", newline='') as sol_csv: csv_writer = csv.writer(sol_csv, delimiter=',') # writes cycle row row = [''] for c in range(numCycle): row.extend(['C' + str(c)] * num_md_per_cycle * num_teams) csv_writer.writerow(row) # writes round row row = [''] for c in range(numCycle): for d in range(num_md_per_cycle): row.extend(['R' + str(d)] * num_teams) csv_writer.writerow(row) # writes awayteam row row = [''] for c in range(numCycle): for d in range(num_md_per_cycle): for t in range(num_teams): row.append('T' + str(t)) csv_writer.writerow(row) # write the actual solution per team tmp_sol.astype(int) for t in range(num_teams): row = ['T' + str(t)] for c in range(numCycle): for r in range(num_md_per_cycle): for team in range(num_teams): row.append(tmp_sol[c][r][t][team]) csv_writer.writerow(row) except GurobiError as e: raise e
def _optimize_gurobi(cobra_model, new_objective=None, objective_sense='maximize', min_norm=0, the_problem=None, tolerance_optimality=1e-6, tolerance_feasibility=1e-6, tolerance_barrier=None, tolerance_integer=1e-9, error_reporting=None, print_solver_time=False, copy_problem=False, lp_method=0, relax_b=None, quad_precision=False, quadratic_component=None, reuse_basis=True, lp_parallel=None, update_problem_reaction_bounds=True): """Uses the gurobi (http://gurobi.com) optimizer to perform an optimization on cobra_model for the objective_coefficients in cobra_model._objective_coefficients based on objective sense. cobra_model: A cobra.Model object new_objective: Reaction, String, or Integer referring to a reaction in cobra_model.reactions to set as the objective. Currently, only supports single objective coeffients. Will expand to include mixed objectives. objective_sense: 'maximize' or 'minimize' min_norm: not implemented the_problem: None or a problem object for the specific solver that can be used to hot start the next solution. tolerance_optimality: Solver tolerance for optimality. tolerance_feasibility: Solver tolerance for feasibility. quad_precision: Boolean. Whether or not to used quad precision in calculations error_reporting: None or True to disable or enable printing errors encountered when trying to find the optimal solution. print_solver_time: False or True. Indicates if the time to calculate the solution should be displayed. quadratic_component: None or scipy.sparse.dok of dim(len(cobra_model.reactions),len(cobra_model.reactions)) If not None: Solves quadratic programming problems for cobra_models of the form: minimize: 0.5 * x' * quadratic_component * x + cobra_model._objective_coefficients' * x such that, cobra_model._lower_bounds <= x <= cobra_model._upper_bounds cobra_model._S * x (cobra_model._constraint_sense) cobra_model._b NOTE: When solving quadratic problems it may be necessary to disable quad_precision and use lp_method = 0 for gurobi. reuse_basis: Boolean. If True and the_problem is a model object for the solver, attempt to hot start the solution. update_problem_reaction_bounds: Boolean. Set to True if you're providing the_problem and you've modified reaction bounds on your cobra_model since creating the_problem. Only necessary for CPLEX lp_parallel: Not implemented lp.optimize() with Salmonella model: cold start: 0.063 seconds hot start: 0.057 seconds (Slow due to copying the LP) """ if relax_b is not None: raise Exception('Need to reimplement constraint relaxation') from numpy import array, nan, zeros #TODO: speed this up if objective_sense == 'maximize': objective_sense = -1 else: objective_sense = 1 from gurobipy import Model, LinExpr, GRB, QuadExpr sense_dict = {'E': GRB.EQUAL, 'L': GRB.LESS_EQUAL, 'G': GRB.GREATER_EQUAL} from cobra.flux_analysis.objective import update_objective from cobra.solvers.legacy import status_dict, variable_kind_dict variable_kind_dict = eval(variable_kind_dict['gurobi']) status_dict = eval(status_dict['gurobi']) #Update objectives if they are new. if new_objective and new_objective != 'update problem': update_objective(cobra_model, new_objective) #Create a new problem if not the_problem or the_problem in ['return', 'setup'] or \ not isinstance(the_problem, Model): lp = Model("cobra") lp.Params.OutputFlag = 0 lp.Params.LogFile = '' # Create variables #TODO: Speed this up variable_list = [ lp.addVar(lb=float(x.lower_bound), ub=float(x.upper_bound), obj=objective_sense * float(x.objective_coefficient), name=x.id, vtype=variable_kind_dict[x.variable_kind]) for x in cobra_model.reactions ] reaction_to_variable = dict(zip(cobra_model.reactions, variable_list)) # Integrate new variables lp.update() #Set objective to quadratic program if quadratic_component is not None: if not hasattr(quadratic_component, 'todok'): raise Exception( 'quadratic component must be a scipy.sparse type array') quadratic_objective = QuadExpr() for (index_0, index_1), the_value in quadratic_component.todok().items(): quadratic_objective.addTerms(the_value, variable_list[index_0], variable_list[index_1]) lp.setObjective(quadratic_objective, sense=objective_sense) #Constraints are based on mass balance #Construct the lin expression lists and then add #TODO: Speed this up as it takes about .18 seconds #HERE for the_metabolite in cobra_model.metabolites: constraint_coefficients = [] constraint_variables = [] for the_reaction in the_metabolite._reaction: constraint_coefficients.append( the_reaction._metabolites[the_metabolite]) constraint_variables.append(reaction_to_variable[the_reaction]) #Add the metabolite to the problem lp.addConstr( LinExpr(constraint_coefficients, constraint_variables), sense_dict[the_metabolite._constraint_sense.upper()], the_metabolite._bound, the_metabolite.id) else: #When reusing the basis only assume that the objective coefficients or bounds can change if copy_problem: lp = the_problem.copy() else: lp = the_problem if not reuse_basis: lp.reset() for the_variable, the_reaction in zip(lp.getVars(), cobra_model.reactions): the_variable.lb = float(the_reaction.lower_bound) the_variable.ub = float(the_reaction.upper_bound) the_variable.obj = float(objective_sense * the_reaction.objective_coefficient) if the_problem == 'setup': return lp if print_solver_time: start_time = time() lp.update() lp.setParam("FeasibilityTol", tolerance_feasibility) lp.setParam("OptimalityTol", tolerance_optimality) if tolerance_barrier: lp.setParam("BarConvTol", tolerance_barrier) if quad_precision: lp.setParam("Quad", 1) lp.setParam("Method", lp_method) #Different methods to try if lp_method fails the_methods = [0, 2, 1] if lp_method in the_methods: the_methods.remove(lp_method) if not isinstance(the_problem, Model): lp.optimize() if lp.status in status_dict: status = status_dict[lp.status] else: status = 'failed' if status != 'optimal': #Try to find a solution using a different method lp.setParam("MarkowitzTol", 1e-2) for lp_method in the_methods: lp.setParam("Method", lp_method) lp.optimize() if status_dict[lp.status] == 'optimal': break else: lp.setParam("TimeLimit", 0.6) lp.optimize() lp.setParam("TimeLimit", "default") if lp.status in status_dict: status = status_dict[lp.status] else: status = 'failed' if status != 'optimal': lp.setParam("MarkowitzTol", 1e-2) #Try to find a solution using a different method for lp_method in the_methods: lp.setParam("Method", lp_method) lp.optimize() if status_dict[lp.status] == 'optimal': break if status_dict[lp.status] != 'optimal': lp = optimize_gurobi( cobra_model, new_objective=new_objective, objective_sense=objective_sense, min_norm=min_norm, the_problem=None, print_solver_time=print_solver_time)['the_problem'] if print_solver_time: print 'optimize time: %f' % (time() - start_time) x_dict = {} y_dict = {} y = None if lp.status in status_dict: status = status_dict[lp.status] else: status = 'failed' if status == 'optimal': objective_value = objective_sense * lp.ObjVal [x_dict.update({v.VarName: v.X}) for v in lp.getVars()] x = array([x_dict[v.id] for v in cobra_model.reactions]) if lp.isMIP: y = y_dict = None #MIP's don't have duals else: [y_dict.update({c.ConstrName: c.Pi}) for c in lp.getConstrs()] y = array([y_dict[v.id] for v in cobra_model.metabolites]) else: y = y_dict = x = x_dict = None objective_value = None if error_reporting: print 'gurobi failed: %s' % lp.status cobra_model.solution = the_solution = Solution(objective_value, x=x, x_dict=x_dict, y=y, y_dict=y_dict, status=status) solution = {'the_problem': lp, 'the_solution': the_solution} return solution
def from_gurobipy(model: Model) -> QuadraticProgram: """Translate a gurobipy model into a quadratic program. Note that this supports only basic functions of gurobipy as follows: - quadratic objective function - linear / quadratic constraints - binary / integer / continuous variables Args: model: The gurobipy model to be loaded. Returns: The quadratic program corresponding to the model. Raises: QiskitOptimizationError: if the model contains unsupported elements. MissingOptionalLibraryError: if gurobipy is not installed. """ _check_gurobipy_is_installed("from_gurobipy") if not isinstance(model, Model): raise QiskitOptimizationError(f"The model is not compatible: {model}") quadratic_program = QuadraticProgram() # Update the model to make sure everything works as expected model.update() # get name quadratic_program.name = model.ModelName # get variables # keep track of names separately, since gurobipy allows to have None names. var_names = {} for x in model.getVars(): if x.vtype == gp.GRB.CONTINUOUS: x_new = quadratic_program.continuous_var(x.lb, x.ub, x.VarName) elif x.vtype == gp.GRB.BINARY: x_new = quadratic_program.binary_var(x.VarName) elif x.vtype == gp.GRB.INTEGER: x_new = quadratic_program.integer_var(x.lb, x.ub, x.VarName) else: raise QiskitOptimizationError( f"Unsupported variable type: {x.VarName} {x.vtype}") var_names[x] = x_new.name # objective sense minimize = model.ModelSense == gp.GRB.MINIMIZE # Retrieve the objective objective = model.getObjective() has_quadratic_objective = False # Retrieve the linear part in case it is a quadratic objective if isinstance(objective, gp.QuadExpr): linear_part = objective.getLinExpr() has_quadratic_objective = True else: linear_part = objective # Get the constant constant = linear_part.getConstant() # get linear part of objective linear = {} for i in range(linear_part.size()): linear[var_names[linear_part.getVar(i)]] = linear_part.getCoeff(i) # get quadratic part of objective quadratic = {} if has_quadratic_objective: for i in range(objective.size()): x = var_names[objective.getVar1(i)] y = var_names[objective.getVar2(i)] v = objective.getCoeff(i) quadratic[x, y] = v # set objective if minimize: quadratic_program.minimize(constant, linear, quadratic) else: quadratic_program.maximize(constant, linear, quadratic) # check whether there are any general constraints if model.NumSOS > 0 or model.NumGenConstrs > 0: raise QiskitOptimizationError( "Unsupported constraint: SOS or General Constraint") # get linear constraints for constraint in model.getConstrs(): name = constraint.ConstrName sense = constraint.Sense left_expr = model.getRow(constraint) rhs = constraint.RHS lhs = {} for i in range(left_expr.size()): lhs[var_names[left_expr.getVar(i)]] = left_expr.getCoeff(i) if sense == gp.GRB.EQUAL: quadratic_program.linear_constraint(lhs, "==", rhs, name) elif sense == gp.GRB.GREATER_EQUAL: quadratic_program.linear_constraint(lhs, ">=", rhs, name) elif sense == gp.GRB.LESS_EQUAL: quadratic_program.linear_constraint(lhs, "<=", rhs, name) else: raise QiskitOptimizationError( f"Unsupported constraint sense: {constraint}") # get quadratic constraints for constraint in model.getQConstrs(): name = constraint.QCName sense = constraint.QCSense left_expr = model.getQCRow(constraint) rhs = constraint.QCRHS linear = {} quadratic = {} linear_part = left_expr.getLinExpr() for i in range(linear_part.size()): linear[var_names[linear_part.getVar(i)]] = linear_part.getCoeff(i) for i in range(left_expr.size()): x = var_names[left_expr.getVar1(i)] y = var_names[left_expr.getVar2(i)] v = left_expr.getCoeff(i) quadratic[x, y] = v if sense == gp.GRB.EQUAL: quadratic_program.quadratic_constraint(linear, quadratic, "==", rhs, name) elif sense == gp.GRB.GREATER_EQUAL: quadratic_program.quadratic_constraint(linear, quadratic, ">=", rhs, name) elif sense == gp.GRB.LESS_EQUAL: quadratic_program.quadratic_constraint(linear, quadratic, "<=", rhs, name) else: raise QiskitOptimizationError( f"Unsupported constraint sense: {constraint}") return quadratic_program
def _optimize_gurobi(cobra_model, new_objective=None, objective_sense='maximize', min_norm=0, the_problem=None, tolerance_optimality=1e-6, tolerance_feasibility=1e-6, tolerance_barrier=None, tolerance_integer=1e-9, error_reporting=None, print_solver_time=False, copy_problem=False, lp_method=0, relax_b=None, quad_precision=False, quadratic_component=None, reuse_basis=True, lp_parallel=None, update_problem_reaction_bounds=True): """Uses the gurobi (http://gurobi.com) optimizer to perform an optimization on cobra_model for the objective_coefficients in cobra_model._objective_coefficients based on objective sense. cobra_model: A cobra.Model object new_objective: Reaction, String, or Integer referring to a reaction in cobra_model.reactions to set as the objective. Currently, only supports single objective coeffients. Will expand to include mixed objectives. objective_sense: 'maximize' or 'minimize' min_norm: not implemented the_problem: None or a problem object for the specific solver that can be used to hot start the next solution. tolerance_optimality: Solver tolerance for optimality. tolerance_feasibility: Solver tolerance for feasibility. quad_precision: Boolean. Whether or not to used quad precision in calculations error_reporting: None or True to disable or enable printing errors encountered when trying to find the optimal solution. print_solver_time: False or True. Indicates if the time to calculate the solution should be displayed. quadratic_component: None or scipy.sparse.dok of dim(len(cobra_model.reactions),len(cobra_model.reactions)) If not None: Solves quadratic programming problems for cobra_models of the form: minimize: 0.5 * x' * quadratic_component * x + cobra_model._objective_coefficients' * x such that, cobra_model._lower_bounds <= x <= cobra_model._upper_bounds cobra_model._S * x (cobra_model._constraint_sense) cobra_model._b NOTE: When solving quadratic problems it may be necessary to disable quad_precision and use lp_method = 0 for gurobi. reuse_basis: Boolean. If True and the_problem is a model object for the solver, attempt to hot start the solution. update_problem_reaction_bounds: Boolean. Set to True if you're providing the_problem and you've modified reaction bounds on your cobra_model since creating the_problem. Only necessary for CPLEX lp_parallel: Not implemented lp.optimize() with Salmonella model: cold start: 0.063 seconds hot start: 0.057 seconds (Slow due to copying the LP) """ if relax_b is not None: raise Exception('Need to reimplement constraint relaxation') from numpy import array, nan, zeros #TODO: speed this up if objective_sense == 'maximize': objective_sense = -1 else: objective_sense = 1 from gurobipy import Model, LinExpr, GRB, QuadExpr sense_dict = {'E': GRB.EQUAL, 'L': GRB.LESS_EQUAL, 'G': GRB.GREATER_EQUAL} from cobra.flux_analysis.objective import update_objective from cobra.solvers.legacy import status_dict, variable_kind_dict variable_kind_dict = eval(variable_kind_dict['gurobi']) status_dict = eval(status_dict['gurobi']) #Update objectives if they are new. if new_objective and new_objective != 'update problem': update_objective(cobra_model, new_objective) #Create a new problem if not the_problem or the_problem in ['return', 'setup'] or \ not isinstance(the_problem, Model): lp = Model("cobra") lp.Params.OutputFlag = 0 lp.Params.LogFile = '' # Create variables #TODO: Speed this up variable_list = [lp.addVar(lb=float(x.lower_bound), ub=float(x.upper_bound), obj=objective_sense*float(x.objective_coefficient), name=x.id, vtype=variable_kind_dict[x.variable_kind]) for x in cobra_model.reactions] reaction_to_variable = dict(zip(cobra_model.reactions, variable_list)) # Integrate new variables lp.update() #Set objective to quadratic program if quadratic_component is not None: if not hasattr(quadratic_component, 'todok'): raise Exception('quadratic component must be a scipy.sparse type array') quadratic_objective = QuadExpr() for (index_0, index_1), the_value in quadratic_component.todok().items(): quadratic_objective.addTerms(the_value, variable_list[index_0], variable_list[index_1]) lp.setObjective(quadratic_objective, sense=objective_sense) #Constraints are based on mass balance #Construct the lin expression lists and then add #TODO: Speed this up as it takes about .18 seconds #HERE for the_metabolite in cobra_model.metabolites: constraint_coefficients = [] constraint_variables = [] for the_reaction in the_metabolite._reaction: constraint_coefficients.append(the_reaction._metabolites[the_metabolite]) constraint_variables.append(reaction_to_variable[the_reaction]) #Add the metabolite to the problem lp.addConstr(LinExpr(constraint_coefficients, constraint_variables), sense_dict[the_metabolite._constraint_sense.upper()], the_metabolite._bound, the_metabolite.id) else: #When reusing the basis only assume that the objective coefficients or bounds can change if copy_problem: lp = the_problem.copy() else: lp = the_problem if not reuse_basis: lp.reset() for the_variable, the_reaction in zip(lp.getVars(), cobra_model.reactions): the_variable.lb = float(the_reaction.lower_bound) the_variable.ub = float(the_reaction.upper_bound) the_variable.obj = float(objective_sense*the_reaction.objective_coefficient) if the_problem == 'setup': return lp if print_solver_time: start_time = time() lp.update() lp.setParam("FeasibilityTol", tolerance_feasibility) lp.setParam("OptimalityTol", tolerance_optimality) if tolerance_barrier: lp.setParam("BarConvTol", tolerance_barrier) if quad_precision: lp.setParam("Quad", 1) lp.setParam("Method", lp_method) #Different methods to try if lp_method fails the_methods = [0, 2, 1] if lp_method in the_methods: the_methods.remove(lp_method) if not isinstance(the_problem, Model): lp.optimize() if lp.status in status_dict: status = status_dict[lp.status] else: status = 'failed' if status != 'optimal': #Try to find a solution using a different method lp.setParam("MarkowitzTol", 1e-2) for lp_method in the_methods: lp.setParam("Method", lp_method) lp.optimize() if status_dict[lp.status] == 'optimal': break else: lp.setParam("TimeLimit", 0.6) lp.optimize() lp.setParam("TimeLimit", "default") if lp.status in status_dict: status = status_dict[lp.status] else: status = 'failed' if status != 'optimal': lp.setParam("MarkowitzTol", 1e-2) #Try to find a solution using a different method for lp_method in the_methods: lp.setParam("Method", lp_method) lp.optimize() if status_dict[lp.status] == 'optimal': break if status_dict[lp.status] != 'optimal': lp = optimize_gurobi(cobra_model, new_objective=new_objective, objective_sense=objective_sense, min_norm=min_norm, the_problem=None, print_solver_time=print_solver_time)['the_problem'] if print_solver_time: print 'optimize time: %f'%(time() - start_time) x_dict = {} y_dict = {} y = None if lp.status in status_dict: status = status_dict[lp.status] else: status = 'failed' if status == 'optimal': objective_value = objective_sense*lp.ObjVal [x_dict.update({v.VarName: v.X}) for v in lp.getVars()] x = array([x_dict[v.id] for v in cobra_model.reactions]) if lp.isMIP: y = y_dict = None #MIP's don't have duals else: [y_dict.update({c.ConstrName: c.Pi}) for c in lp.getConstrs()] y = array([y_dict[v.id] for v in cobra_model.metabolites]) else: y = y_dict = x = x_dict = None objective_value = None if error_reporting: print 'gurobi failed: %s'%lp.status the_solution = Solution(objective_value, x=x, x_dict=x_dict, y=y, y_dict=y_dict, status=status) solution = {'the_problem': lp, 'the_solution': the_solution} return solution
def _sensitivity_for_constraints(AT, j, project, y_, project_activity, M): global _round, _pa_dataset m = Model("SingleProject_%d_for_sensitivity" % j) m.setParam('OutputFlag', False) # m.params.IntFeasTol = 1e-7 ## Project complete data,Project Tadeness,construction completion time CT = m.addVar(obj=0, vtype=GRB.CONTINUOUS, name="CT_%d" % j) ## Activity start time ST = {} project_activities = project_activity[project] for row in project_activities.nodes(): ST[row] = m.addVar(obj=0, vtype=GRB.CONTINUOUS, name="ST_%d_%s" % (j, row)) ## Review sequence z_ij ## move to annealing objective function m.update() ## Constrain 8: activity starting constrain # equation 20 for a in project_activities.nodes(): for r in project_activities.node[a]['resources']: m.addConstr(ST[a], GRB.GREATER_EQUAL, AT[j, r], name="constraint_8_project_%d_activity_%s_resource_%s" % (j, a, r)) ## Constrain 9 activity sequence constrain # equation 21 for row1, row2 in project_activities.edges(): m.addConstr(ST[row1] + project_activities.node[row1]['duration'], GRB.LESS_EQUAL, ST[row2], name="constraint_9_project_%d_activity_%s_activity_%s" % (j, row1, row2)) ## Constrain 10,11 for row1 in project_activities.nodes(): for row2 in project_activities.nodes(): if row1 != row2 and len(list( set(project_activities.node[row1]['rk_resources']).intersection( project_activities.node[row2]['rk_resources']))) > 0: # equation 22 m.addConstr(ST[row1] + project_activities.node[row1]['duration'] - M * ( 1 - _get_y_for_activities(y_, row1, row2)), GRB.LESS_EQUAL, ST[row2], name="constraint_10_project_%d_activity_%s_activity_%s" % (j, row1, row2)) # equation 23 m.addConstr( ST[row2] + project_activities.node[row2]['duration'] - M * _get_y_for_activities(y_, row1, row2), GRB.LESS_EQUAL, ST[row1], name="constraint_11_project_%d_activity_%s_activity_%s" % (j, row1, row2)) # m.addConstr(y[j,row1,row2]+y[j,row2,row1],GRB.LESS_EQUAL,1) ## Constrain 12 # equation 24 for row in project_activities.nodes(): m.addConstr(CT, GRB.GREATER_EQUAL, ST[row] + project_activities.node[row]['duration'], name="constraint_12_project_%d_activity_%s" % (j, row)) m.update() # Set optimization objective - minimize completion time expr = LinExpr() expr.add(CT) m.setObjective(expr, GRB.MINIMIZE) m.update() ########################################## # m.params.presolve = 1 m.update() m.setParam(GRB.Param.Method, 0) m.update() # Solve # m.params.presolve=0 m.optimize() _skja = {} for c in m.getConstrs(): if c.ConstrName.startswith('constraint_8_project'): splits = c.ConstrName.split('_') r = splits[7] if r not in _skja: _skja[r] = [] _skja[r].append(c.Pi) # if c.Pi != 0: # logging.debug('project %d binding resource:%s Pi:%.4g' % (j, splits[-1], c.Pi)) # else: # logging.debug('project %d not binding resource:%s Pi:%.4g' % (j, splits[-1], c.Pi)) _pa_dataset.loc[_pa_dataset.shape[0]] = [_round, j, r, splits[5], c.Pi] _skj = {} for r in _skja: _skj[j, r] = max(_skja[r]) _pa_max_dataset.loc[_pa_max_dataset.shape[0]] = [_round, j, r, max(_skja[r])] return _skj
def _sensitivity_analysis_for_tardiness(z, CT, D): m = Model("model_for_sensitivity_analysis_for_tardiness") m.setParam('OutputFlag', False) # m.params.IntFeasTol = 1e-7 DT = {} TD = {} for j in range(D.project_n): ## Project Tadeness,construction completion time DT[j] = m.addVar(obj=0, vtype=GRB.CONTINUOUS, name="DT_%d" % j) TD[j] = m.addVar(obj=0, vtype=GRB.CONTINUOUS, name="TD_%d" % j) DT[-1] = m.addVar(obj=0, vtype=GRB.CONTINUOUS, name="DT_-1") m.update(); #### Add Constraint #### ## Constrain 2: project complete data>due data ## # equation 17 for j in range(D.project_n): m.addConstr(DT[j] - TD[j], GRB.LESS_EQUAL, D.DD[j], name="constraint_2_project_%d" % j) ## Constraint 13 # equation 12 for j in range(D.project_n): m.addConstr(DT[j], GRB.GREATER_EQUAL, CT[j] + D.review_duration[j], name="constraint_13_project_%d" % j) ## Constraint 14 # equation 13 for i in range(-1, D.project_n): for j in range(D.project_n): if i != j: m.addConstr(DT[j], GRB.GREATER_EQUAL, DT[i] - D.M * (1 - z[i, j]) + D.review_duration[j], name="constraint_14_project_%d_project_%d" % (i, j)) m.update() # Set optimization objective - minimize sum of expr = LinExpr() for j in range(D.project_n): expr.add(D.w[j] * TD[j]) m.setObjective(expr, GRB.MINIMIZE) m.update() # m.params.presolve = 1 m.update() m.optimize() # _logger.info("mm binding info:") sj = {} for c in m.getConstrs(): if c.ConstrName.startswith('constraint_13'): j = int(c.ConstrName.split('_')[-1]) # if c.Pi != 0: # sj[j] = 1 # _logger.info('%s binding Pi:%.4g' % (c.ConstrName, c.Pi)) # pass # else: # sj[j] = 0 # _logger.info('%s not binding Pi:%.4g' % (c.ConstrName, c.Pi)) # pass sj[j] = c.Pi return sj
def optmize_single_project(AT, j, project_list, project_activity, M): m = Model("SingleProject_%d" % j) m.setParam(GRB.Param.Method, 0) m.update() #### Create variables #### project = project_list[j] ## Project complete data,Project Tadeness,construction completion time CT = m.addVar(obj=0, vtype=GRB.CONTINUOUS, name="(CT%d)" % j) ## Activity start time ST = {} project_activities = project_activity[project] # print(project_activities.nodes()) for row in project_activities.nodes(): ST[row] = m.addVar(obj=0, vtype=GRB.CONTINUOUS, name="(ST%d,%s)" % (j, row)) ## Review sequence z_ij ## move to annealing objective function # y y = {} for activity_i in project_activities.nodes(): for activity_j in project_activities.nodes(): # print(project_activities.node[activity_i]) # print(dir(project_activities.node[activity_i])) if activity_i != activity_j and len(list( set(project_activities.node[activity_i]['rk_resources']).intersection( project_activities.node[activity_j]['rk_resources']))) > 0: y[activity_i, activity_j] = m.addVar(obj=0, vtype=GRB.BINARY, name="(y%d,%s,%s)" % (j, activity_i, activity_j)) m.update() #### Create constrains #### ## Constrain 2: project complete data>due data ## move to annealing objective function ## Constrain 3: supplier capacity limit ## move to annealing neighbor & random generator ## Constrain 4,6: project demand require; each project receive from one supplier for each resource ## move to annealing neighbor & random generator ## constrain 5: shipping constrain ## move to annealing neighbor & random generator ## Constrain 7:budget limit ## move to annealing constraint valid ## Constrain 8: activity starting constrain for a in project_activities.nodes(): for r in project_activities.node[a]['resources']: m.addConstr(AT[j, r], GRB.LESS_EQUAL, ST[a], name="constraint_8_project_%d_activity_%s_resource_%s" % (j, a, r)) ## Constrain 9 activity sequence constrain for row1, row2 in project_activities.edges(): m.addConstr(ST[row1] + project_activities.node[row1]['duration'], GRB.LESS_EQUAL, ST[row2], name="constraint_9_project_%d_activity_%s_activity_%s" % (j, row1, row2)) ## Constrain 10,11 for row1 in project_activities.nodes(): for row2 in project_activities.nodes(): if row1 != row2 and len(list( set(project_activities.node[row1]['rk_resources']).intersection( project_activities.node[row2]['rk_resources']))) > 0: m.addConstr(ST[row1] + project_activities.node[row1]['duration'] - M * ( 1 - y[row1, row2]), GRB.LESS_EQUAL, ST[row2], name="constraint_10_project_%d_activity_%s_activity_%s" % (j, row1, row2)) m.addConstr( ST[row2] + project_activities.node[row2]['duration'] - M * (y[row1, row2]), GRB.LESS_EQUAL, ST[row1], name="constraint_11_project_%d_activity_%s_activity_%s" % (j, row1, row2)) # m.addConstr(y[j,row1,row2]+y[j,row2,row1],GRB.LESS_EQUAL,1) ## Constrain 12 for row in project_activities.nodes(): m.addConstr(CT, GRB.GREATER_EQUAL, ST[row] + project_activities.node[row]['duration'], name="constraint_12_project_%d_activity_%s" % (j, row)) ## Constrain 13 ## move to anealing objective function ## Constrain 14 ## move to anealing objective function ## Constrain 15 ## move to anealing objective function ## Constrain 16 ## move to anealing objective function ## Constrain 17 ## move to anealing objective function m.update() # Set optimization objective - minimize completion time expr = LinExpr() expr.add(CT) m.setObjective(expr, GRB.MINIMIZE) m.update() ########################################## m.params.presolve = 1 m.update() # Solve # m.params.presolve=0 m.optimize() # m.write(join(output_dir, "heuristic_%d.lp" % j)) # m.write(join(output_dir, "heuristic_%d.sol" % j)) # logging.info("project %d with optimalVal %r" % (j, m.objVal)) print(m.status == GRB.OPTIMAL) for c in m.getConstrs(): if c.ConstrName.startswith('constraint_8_project'): c.getAttr(GRB.Attr.SARHSLow) logging.info('%s shadow price (%f,%f)' % (c.ConstrName, c.SARHSLow, c.SARHSUp)) return m.objVal
def generatesSample( num_days, num_shifts, num_nurses, numSam, bounds, constrList, partial_sol, x_mapping, y_mapping, gid, ): N = list(range(num_nurses)) D = list(range(num_days)) Ds = list(range(num_days + 1)) S = list(range(num_shifts)) Ss = list(range(num_shifts + 1)) # Sk=list(range(2)) # constrList=[[(0,),(1,)],[(0,),(2,)],[(0,),(1,2)],[(1,),(0,)],[(1,),(2,)],[(1,),(0,2)],[(2,),(0,)],[(2,),(1,)],[(2,),(0,1)],[(0,1),(2,)],[(0,2),(1,)],[(1,2),(0,)]] try: sys.stdout = open(os.devnull, "w") m = Model("nspSolver") sys.stdout = sys.__stdout__ m.setParam(GRB.Param.OutputFlag, 0) ########### Decision Variables ############# # x = m.addVars(N,D,S,Sk, vtype=GRB.BINARY, name="x") o = m.addVars(N, D, S, vtype=GRB.BINARY, name="o") p = m.addVars(N, D, vtype=GRB.BINARY, name="p") q = m.addVars(N, S, vtype=GRB.BINARY, name="q") r = m.addVars(S, D, vtype=GRB.BINARY, name="r") tw = m.addVars(N, D, D, vtype=GRB.BINARY, name="tw") sw = m.addVars(N, Ds, D, vtype=GRB.BINARY, name="sw") tw1 = m.addVars(N, D, S, D, vtype=GRB.BINARY, name="tw1") sw1 = m.addVars(N, Ds, S, D, vtype=GRB.BINARY, name="sw1") tws = m.addVars(N, S, S, vtype=GRB.BINARY, name="tws") sws = m.addVars(N, Ss, S, vtype=GRB.BINARY, name="sws") tfs = m.addVars(N, S, S, vtype=GRB.BINARY, name="tfs") sfs = m.addVars(N, Ss, S, vtype=GRB.BINARY, name="sfs") tf = m.addVars(N, D, D, vtype=GRB.BINARY, name="tf") sf = m.addVars(N, Ds, D, vtype=GRB.BINARY, name="sf") tw1f = m.addVars(N, D, S, D, vtype=GRB.BINARY, name="tw1f") sw1f = m.addVars(N, Ds, S, D, vtype=GRB.BINARY, name="sw1f") ########### Required Constraints ############# for n in N: for d in D: for s in S: if not np.isnan(partial_sol[n, d, s]): m.addConstr((o[n, d, s] == partial_sol[n, d, s]), "partial solution") m.addConstrs((o.sum(n, d, "*") == p[n, d] for n in N for d in D), "po") # m.addConstrs((x.sum(n,d,s,'*')==o[n,d,s] for n in N for d in D for s in S),"xo") # m.addConstrs((x[n,d,s,sk]==o[n,d,s] for n in N for d in D for s in S for sk in Sk if nurse_skill[n]==sk),"xo") # m.addConstrs((x[n,d,s,sk]==0 for n in N for d in D for s in S for sk in Sk if nurse_skill[n]!=sk),"xo") m.addConstrs((q[n, s] <= o.sum(n, "*", s) for n in N for s in S), "qo") m.addConstrs((q[n, s] * o.sum(n, "*", s) == o.sum(n, "*", s) for n in N for s in S), "qo") m.addConstrs((r[s, d] <= o.sum("*", d, s) for d in D for s in S), "ro") m.addConstrs((r[s, d] * o.sum("*", d, s) == o.sum("*", d, s) for d in D for s in S), "ro") ########### Hard Constraints ############# # print(bounds) for i in range(len(bounds)): if bounds[i, 0] > 0: # print(bounds[i,0]) if constrList[i] == "0:1": m.addConstrs((r.sum("*", d) >= bounds[i, 0] for d in D), "constr") elif constrList[i] == "0:2": m.addConstrs((p.sum("*", d) >= bounds[i, 0] for d in D), "constr") elif constrList[i] == "0:1,2": m.addConstrs((o.sum("*", d, "*") >= bounds[i, 0] for d in D), "constr") elif constrList[i] == "1:0": m.addConstrs((r.sum(s, "*") >= bounds[i, 0] for s in S), "constr") elif constrList[i] == "1:2": m.addConstrs((q.sum("*", s) >= bounds[i, 0] for s in S), "constr") elif constrList[i] == "1:0,2": m.addConstrs((o.sum("*", "*", s) >= bounds[i, 0] for s in S), "constr") elif constrList[i] == "2:0": m.addConstrs((p.sum(n, "*") >= bounds[i, 0] for n in N), "constr") elif constrList[i] == "2:1": m.addConstrs((q.sum(n, "*") >= bounds[i, 0] for n in N), "constr") elif constrList[i] == "2:0,1": m.addConstrs((o.sum(n, "*", "*") >= bounds[i, 0] for n in N), "constr") elif constrList[i] == "0,1:2": m.addConstrs( (o.sum("*", d, s) >= bounds[i, 0] for d in D for s in S), "constr", ) elif constrList[i] == "0,2:1": m.addConstrs( (o.sum(n, d, "*") >= bounds[i, 0] for d in D for n in N), "constr", ) elif constrList[i] == "1,2:0": m.addConstrs( (o.sum(n, "*", s) >= bounds[i, 0] for n in N for s in S), "constr", ) if bounds[i, 1] > 0: # print(bounds[i,1]) if constrList[i] == "0:1": m.addConstrs((r.sum("*", d) <= bounds[i, 1] for d in D), "constr") elif constrList[i] == "0:2": m.addConstrs((p.sum("*", d) <= bounds[i, 1] for d in D), "constr") elif constrList[i] == "0:1,2": m.addConstrs((o.sum("*", d, "*") <= bounds[i, 1] for d in D), "constr") elif constrList[i] == "1:0": m.addConstrs((r.sum(s, "*") <= bounds[i, 1] for s in S), "constr") elif constrList[i] == "1:2": m.addConstrs((q.sum("*", s) <= bounds[i, 1] for s in S), "constr") elif constrList[i] == "1:0,2": m.addConstrs((o.sum("*", "*", s) <= bounds[i, 1] for s in S), "constr") elif constrList[i] == "2:0": m.addConstrs((p.sum(n, "*") <= bounds[i, 1] for n in N), "constr") elif constrList[i] == "2:1": m.addConstrs((q.sum(n, "*") <= bounds[i, 1] for n in N), "constr") elif constrList[i] == "2:0,1": m.addConstrs((o.sum(n, "*", "*") <= bounds[i, 1] for n in N), "constr") elif constrList[i] == "0,1:2": m.addConstrs( (o.sum("*", d, s) <= bounds[i, 1] for d in D for s in S), "constr", ) elif constrList[i] == "0,2:1": m.addConstrs( (o.sum(n, d, "*") <= bounds[i, 1] for d in D for n in N), "constr", ) elif constrList[i] == "1,2:0": m.addConstrs( (o.sum(n, "*", s) <= bounds[i, 1] for n in N for s in S), "constr", ) # if mt==1: # for i in range(len(nurse_preference)): # m.addConstr((o[i,nurse_preference[i][0],nurse_preference[i][1]] == 0),"nursePref") if constrList[i] == "2:0" and bounds[i, 5] + bounds[i, 4] > 0: m.addConstrs((tw[n, 0, 0] == p[n, 0] for n in N), "MaxConsWork") m.addConstrs( (tw[n, d1 + 1, 0] <= p[n, d1 + 1] for n in N for d1 in D if d1 < len(D) - 1), "MaxConsWork", ) m.addConstrs( (tw[n, d1 + 1, 0] <= 1 - p[n, d1] for n in N for d1 in D if d1 < len(D) - 1), "MaxConsWork", ) m.addConstrs( (tw[n, d1 + 1, 0] >= p[n, d1 + 1] - p[n, d1] for n in N for d1 in D if d1 < len(D) - 1), "MaxConsWork", ) m.addConstrs((tw[n, 0, d2] == 0 for n in N for d2 in D if d2 > 0), "MaxConsWork") m.addConstrs( (tw[n, d1, d2] <= tw[n, d1 - 1, d2 - 1] for n in N for d1 in D for d2 in D if d1 > 0 if d2 > 0), "MaxConsWork", ) m.addConstrs( (tw[n, d1, d2] <= p[n, d1] for n in N for d1 in D for d2 in D if d1 > 0 if d2 > 0), "MaxConsWork", ) m.addConstrs( (tw[n, d1, d2] >= p[n, d1] + tw[n, d1 - 1, d2 - 1] - 1 for n in N for d1 in D for d2 in D if d1 > 0 if d2 > 0), "MaxConsWork", ) if bounds[i, 5] > 0: m.addConstr( (quicksum(tw[n, d1, d2] for n in N for d1 in D for d2 in range(bounds[i, 5], len(D))) == 0), "maxconswork", ) if bounds[i, 4] > 0: m.addConstrs((sw[n, 0, d2] == 0 for n in N for d2 in D), "MinConsWork") m.addConstrs( (sw[n, d1, d2] <= tw[n, d1 - 1, d2] for n in N for d1 in D for d2 in D if d1 > 0), "MinConsWork", ) m.addConstrs( (sw[n, d1, d2] <= 1 - p[n, d1] for n in N for d1 in D for d2 in D if d1 > 0), "MinConsWork", ) m.addConstrs( (sw[n, d1, d2] >= tw[n, d1 - 1, d2] - p[n, d1] for n in N for d1 in D for d2 in D if d1 > 0), "MinConsWork", ) m.addConstrs( (sw[n, num_days, d2] == tw[n, num_days - 1, d2] for n in N for d2 in D), "MinConsWork", ) m.addConstr( (quicksum(sw[n, d1, d2] * (bounds[i, 4] - 1 - d2) for n in N for d1 in Ds for d2 in range(bounds[i, 4] - 1)) == 0), "minconswork", ) if constrList[i] == [(2, ), (0, )] and bounds[i, 3] + bounds[i, 2] > 0: m.addConstrs((tf[n, 0, 0] == 1 - p[n, 0] for n in N), "MaxConsFree") m.addConstrs( (tf[n, d1 + 1, 0] <= p[n, d1] for n in N for d1 in D if d1 < len(D) - 1), "MaxConsFree", ) m.addConstrs( (tf[n, d1 + 1, 0] <= 1 - p[n, d1 + 1] for n in N for d1 in D if d1 < len(D) - 1), "MaxConsFree", ) m.addConstrs( (tf[n, d1 + 1, 0] >= p[n, d1] - p[n, d1 + 1] for n in N for d1 in D if d1 < len(D) - 1), "MaxConsFree", ) m.addConstrs((tf[n, 0, d2] == 0 for n in N for d2 in D if d2 > 0), "MaxConsFree") m.addConstrs( (tf[n, d1, d2] <= tf[n, d1 - 1, d2 - 1] for n in N for d1 in D for d2 in D if d1 > 0 if d2 > 0), "MaxConsFree", ) m.addConstrs( (tf[n, d1, d2] <= 1 - p[n, d1] for n in N for d1 in D for d2 in D if d1 > 0 if d2 > 0), "MaxConsFree", ) m.addConstrs( (tf[n, d1, d2] >= tf[n, d1 - 1, d2 - 1] - p[n, d1] for n in N for d1 in D for d2 in D if d1 > 0 if d2 > 0), "MaxConsFree", ) if bounds[i, 3] > 0: m.addConstr( (quicksum(tf[n, d1, d2] for n in N for d1 in D for d2 in range(bounds[i, 3], len(D))) == 0), "maxconsfree", ) if bounds[i, 2] > 0: m.addConstrs((sf[n, 0, d2] == 0 for n in N for d2 in D), "MinConsFree") m.addConstrs( (sf[n, d1, d2] <= tf[n, d1 - 1, d2] for n in N for d1 in D for d2 in D if d1 > 0), "MinConsFree", ) m.addConstrs( (sf[n, d1, d2] <= p[n, d1] for n in N for d1 in D for d2 in D if d1 > 0), "MinConsFree", ) m.addConstrs( (sf[n, d1, d2] >= tf[n, d1 - 1, d2] + p[n, d1] - 1 for n in N for d1 in D for d2 in D if d1 > 0), "MinConsFree", ) m.addConstrs( (sf[n, num_days, d2] == tf[n, num_days - 1, d2] for n in N for d2 in D), "MinConsFree", ) m.addConstr( (quicksum(sf[n, d1, d2] * (bounds[i, 2] - 1 - d2) for n in N for d1 in Ds for d2 in range(bounds[i, 2] - 1)) == 0), "minconsfree", ) if constrList[i] == [(2, ), (1, )] and bounds[i, 5] + bounds[i, 4] > 0: m.addConstrs((tws[n, 0, 0] == q[n, 0] for n in N), "MaxConsWork") m.addConstrs( (tws[n, s1 + 1, 0] <= q[n, s1 + 1] for n in N for s1 in S if s1 < len(S) - 1), "MaxConsWork", ) m.addConstrs( (tws[n, s1 + 1, 0] <= 1 - q[n, s1] for n in N for s1 in S if s1 < len(S) - 1), "MaxConsWork", ) m.addConstrs( (tws[n, s1 + 1, 0] >= q[n, s1 + 1] - q[n, s1] for n in N for s1 in S if s1 < len(S) - 1), "MaxConsWork", ) m.addConstrs((tws[n, 0, s2] == 0 for n in N for s2 in S if s2 > 0), "MaxConsWork") m.addConstrs( (tws[n, s1, s2] <= tws[n, s1 - 1, s2 - 1] for n in N for s1 in S for s2 in S if s1 > 0 if s2 > 0), "MaxConsWork", ) m.addConstrs( (tws[n, s1, s2] <= q[n, s1] for n in N for s1 in S for s2 in S if s1 > 0 if s2 > 0), "MaxConsWork", ) m.addConstrs( (tws[n, s1, s2] >= q[n, s1] + tws[n, s1 - 1, s2 - 1] - 1 for n in N for s1 in S for s2 in S if s1 > 0 if s2 > 0), "MaxConsWork", ) if bounds[i, 5] > 0: m.addConstr( (quicksum(tws[n, s1, s2] for n in N for s1 in S for s2 in range(bounds[i, 5], len(S))) == 0), "maxconswork", ) if bounds[i, 4] > 0: m.addConstrs((sws[n, 0, s2] == 0 for n in N for s2 in S), "MinConsWork") m.addConstrs( (sws[n, s1, s2] <= tws[n, s1 - 1, s2] for n in N for s1 in S for s2 in S if s1 > 0), "MinConsWork", ) m.addConstrs( (sws[n, s1, s2] <= 1 - q[n, s1] for n in N for s1 in S for s2 in S if s1 > 0), "MinConsWork", ) m.addConstrs( (sws[n, s1, s2] >= tws[n, s1 - 1, s2] - q[n, s1] for n in N for s1 in S for s2 in S if s1 > 0), "MinConsWork", ) m.addConstrs( (sws[n, num_shifts, s2] == tws[n, num_shifts - 1, s2] for n in N for s2 in S), "MinConsWork", ) m.addConstr( (quicksum(sws[n, s1, s2] * (bounds[i, 4] - 1 - s2) for n in N for s1 in Ss for s2 in range(bounds[i, 4] - 1)) == 0), "minconswork", ) if constrList[i] == [(2, ), (1, )] and bounds[i, 3] + bounds[i, 2] > 0: m.addConstrs((tfs[n, 0, 0] == 1 - q[n, 0] for n in N), "MaxConsFree") m.addConstrs( (tfs[n, s1 + 1, 0] <= q[n, s1] for n in N for s1 in S if s1 < len(S) - 1), "MaxConsFree", ) m.addConstrs( (tfs[n, s1 + 1, 0] <= 1 - q[n, s1 + 1] for n in N for s1 in S if s1 < len(S) - 1), "MaxConsFree", ) m.addConstrs( (tfs[n, s1 + 1, 0] >= q[n, s1] - q[n, s1 + 1] for n in N for s1 in S if s1 < len(S) - 1), "MaxConsFree", ) m.addConstrs((tfs[n, 0, s2] == 0 for n in N for s2 in S if s2 > 0), "MaxConsFree") m.addConstrs( (tfs[n, s1, s2] <= tfs[n, s1 - 1, s2 - 1] for n in N for s1 in S for s2 in S if s1 > 0 if s2 > 0), "MaxConsFree", ) m.addConstrs( (tfs[n, s1, s2] <= 1 - q[n, s1] for n in N for s1 in S for s2 in S if s1 > 0 if s2 > 0), "MaxConsFree", ) m.addConstrs( (tfs[n, s1, s2] >= tfs[n, s1 - 1, s2 - 1] - q[n, s1] for n in N for s1 in S for s2 in S if s1 > 0 if s2 > 0), "MaxConsFree", ) if bounds[i, 3] > 0: m.addConstr( (quicksum(tfs[n, s1, s2] for n in N for s1 in S for s2 in range(bounds[i, 3], len(S))) == 0), "maxconsfree", ) if bounds[i, 2] > 0: m.addConstrs((sfs[n, 0, s2] == 0 for n in N for s2 in S), "MinConsFree") m.addConstrs( (sfs[n, s1, s2] <= tfs[n, s1 - 1, s2] for n in N for s1 in S for s2 in S if s1 > 0), "MinConsFree", ) m.addConstrs( (sfs[n, s1, s2] <= q[n, s1] for n in N for s1 in S for s2 in S if s1 > 0), "MinConsFree", ) m.addConstrs( (sfs[n, s1, s2] >= tfs[n, s1 - 1, s2] + q[n, s1] - 1 for n in N for s1 in S for s2 in S if s1 > 0), "MinConsFree", ) m.addConstrs( (sfs[n, num_shifts, s2] == tfs[n, num_shifts - 1, s2] for n in N for s2 in S), "MinConsWork", ) m.addConstr( (quicksum(sfs[n, s1, s2] * (bounds[i, 2] - 1 - s2) for n in N for s1 in Ss for s2 in range(bounds[i, 2] - 1)) == 0), "minconsfree", ) if constrList[i] == [(1, 2), (0, )] and bounds[i, 5] + bounds[i, 4] > 0: m.addConstrs( (tw1[n, 0, s, 0] == o[n, 0, s] for n in N for s in S), "MaxConsSameShift", ) m.addConstrs( (tw1[n, d1 + 1, s, 0] <= o[n, d1 + 1, s] for s in S for n in N for d1 in D if d1 < len(D) - 1), "MaxConsSameShift", ) m.addConstrs( (tw1[n, d1 + 1, s, 0] <= 1 - o[n, d1, s] for s in S for n in N for d1 in D if d1 < len(D) - 1), "MaxConsSameShift", ) m.addConstrs( (tw1[n, d1 + 1, s, 0] >= o[n, d1 + 1, s] - o[n, d1, s] for s in S for n in N for d1 in D if d1 < len(D) - 1), "MaxConsSameShift", ) m.addConstrs( (tw1[n, 0, s, d2] == 0 for s in S for n in N for d2 in D if d2 > 0), "MaxConsSameShift", ) m.addConstrs( (tw1[n, d1, s, d2] <= tw1[n, d1 - 1, s, d2 - 1] for s in S for n in N for d1 in D for d2 in D if d1 > 0 if d2 > 0), "MaxConsSameShift", ) m.addConstrs( (tw1[n, d1, s, d2] <= o[n, d1, s] for s in S for n in N for d1 in D for d2 in D if d1 > 0 if d2 > 0), "MaxConsSameShift", ) m.addConstrs( (tw1[n, d1, s, d2] >= o[n, d1, s] + tw1[n, d1 - 1, s, d2 - 1] - 1 for s in S for n in N for d1 in D for d2 in D if d1 > 0 if d2 > 0), "MaxConsSameShift", ) if bounds[i, 5] > 0: m.addConstr( (quicksum(tw1[n, d1, s, d2] for s in S for n in N for d1 in D for d2 in range(bounds[i, 5], len(D))) == 0), "maxconssameshift", ) if bounds[i, 4] > 0: m.addConstrs( (sw1[n, 0, s, d2] == 0 for s in S for n in N for d2 in D), "MinConsSameShift", ) m.addConstrs( (sw1[n, d1, s, d2] <= tw1[n, d1 - 1, s, d2] for s in S for n in N for d1 in D for d2 in D if d1 > 0), "MinConsSameShift", ) m.addConstrs( (sw1[n, d1, s, d2] <= 1 - o[n, d1, s] for s in S for n in N for d1 in D for d2 in D if d1 > 0), "MinConsSameShift", ) m.addConstrs( (sw1[n, d1, s, d2] >= tw1[n, d1 - 1, s, d2] - o[n, d1, s] for s in S for n in N for d1 in D for d2 in D if d1 > 0), "MinConsSameShift", ) m.addConstrs( (sw1[n, num_days, s, d2] == tw1[n, num_days - 1, s, d2] for n in N for s in S for d2 in D), "MinConsWork", ) m.addConstr( (quicksum(sw1[n, d1, s, d2] * (bounds[i, 4] - 1 - d2) for s in S for n in N for d1 in Ds for d2 in range(bounds[i, 4] - 1)) == 0), "minconssameshift", ) if constrList[i] == [(1, 2), (0, )] and bounds[i, 3] + bounds[i, 2] > 0: m.addConstrs( (tw1f[n, 0, s, 0] == 1 - o[n, 0, s] for n in N for s in S), "MaxConsFree", ) m.addConstrs( (tw1f[n, d1 + 1, s, 0] <= o[n, d1, s] for n in N for s in S for d1 in D if d1 < len(D) - 1), "MaxConsFree", ) m.addConstrs( (tw1f[n, d1 + 1, s, 0] <= 1 - o[n, d1 + 1, s] for n in N for s in S for d1 in D if d1 < len(D) - 1), "MaxConsFree", ) m.addConstrs( (tw1f[n, d1 + 1, s, 0] >= o[n, d1, s] - o[n, d1 + 1, s] for n in N for s in S for d1 in D if d1 < len(D) - 1), "MaxConsFree", ) m.addConstrs( (tw1f[n, 0, s, d2] == 0 for n in N for s in S for d2 in D if d2 > 0), "MaxConsFree", ) m.addConstrs( (tw1f[n, d1, s, d2] <= tw1f[n, d1 - 1, s, d2 - 1] for n in N for s in S for d1 in D for d2 in D if d1 > 0 if d2 > 0), "MaxConsFree", ) m.addConstrs( (tw1f[n, d1, s, d2] <= 1 - o[n, d1, s] for n in N for s in S for d1 in D for d2 in D if d1 > 0 if d2 > 0), "MaxConsFree", ) m.addConstrs( (tw1f[n, d1, s, d2] >= tw1f[n, d1 - 1, s, d2 - 1] - o[n, d1, s] for n in N for s in S for d1 in D for d2 in D if d1 > 0 if d2 > 0), "MaxConsFree", ) if bounds[i, 3] > 0: m.addConstr( (quicksum(tw1f[n, d1, s, d2] for n in N for s in S for d1 in D for d2 in range(bounds[i, 3], len(D))) == 0), "maxconsfree", ) if bounds[i, 2] > 0: m.addConstrs( (sw1f[n, 0, s, d2] == 0 for n in N for s in S for d2 in D), "MinConsw1free", ) m.addConstrs( (sw1f[n, d1, s, d2] <= tw1f[n, d1 - 1, s, d2] for n in N for s in S for d1 in D for d2 in D if d1 > 0), "MinConsw1free", ) m.addConstrs( (sw1f[n, d1, s, d2] <= o[n, d1, s] for n in N for s in S for d1 in D for d2 in D if d1 > 0), "MinConsw1free", ) m.addConstrs( (sw1f[n, d1, s, d2] >= tw1f[n, d1 - 1, s, d2] + o[n, d1, s] - 1 for n in N for s in S for d1 in D for d2 in D if d1 > 0), "MinConsw1free", ) m.addConstrs( (sw1f[n, num_days, s, d2] == tw1f[n, num_days - 1, s, d2] for n in N for s in S for d2 in D), "MinConsWork", ) m.addConstr( (quicksum(sw1f[n, d1, s, d2] * (bounds[i, 2] - 1 - d2) for n in N for s in S for d1 in Ds for d2 in range(bounds[i, 2] - 1)) == 0), "minconsw1free", ) m.setParam(GRB.Param.PoolSolutions, numSam) m.setParam(GRB.Param.PoolSearchMode, 2) m.optimize() nSolutions = m.SolCount # print("Number of solutions found: " + str(nSolutions)) if m.status == GRB.Status.INFEASIBLE: m.computeIIS() # print("\nThe following constraint(s) cannot be satisfied:") for c in m.getConstrs(): if c.IISConstr: # print("%s" % c.constrName) pass # if m.status == GRB.Status.OPTIMAL: # m.write("m.sol") # print(nSolutions) # print(partial_sol) multi_predictions = [] for i in range(nSolutions): provenance = ("countor", gid + "-" + str(uuid4())) m.setParam(GRB.Param.SolutionNumber, i) solution = m.getAttr("xn", o) # print(m.getAttr("xn", p)) tmp = np.zeros([num_nurses, num_days, num_shifts]) for key in solution: tmp[key] = round(solution[key]) # tSample=np.swapaxes(np.swapaxes(tmp,0,1),1,2) tmp_sol = tmp.astype(int) # print(partial_sol) for n in N: for d in D: for s in S: # print(x_mapping[n,d,s],y_mapping[n,d,s]) if np.isnan(partial_sol[n, d, s]): # print("geer") multi_predictions.append( Prediction( Coordinate( y_mapping[n, d, s].item(), x_mapping[n, d, s].item(), ), tmp_sol[n, d, s].item(), 1, provenance, )) return multi_predictions except GurobiError as e: print("Error code " + str(e.errno) + ": " + str(e)) except AttributeError: print("Encountered an attribute error")
def trajectory_model(s, T): model = Model("polytopic trajectory of PWA systems") x = {} u = {} theta = {} z = {} G = {} G_bound = 10 for t in range(T): x[t] = np.empty((s.n, 1), dtype='object') # n*1 u[t] = np.empty((s.m, 1), dtype='object') # m*1 theta[t] = np.empty((s.m, s.n), dtype='object') # n*m for row in range(s.n): x[t][row, 0] = model.addVar(lb=-G_bound, ub=G_bound) for row in range(s.m): u[t][row, 0] = model.addVar(lb=-G_bound, ub=G_bound) for row in range(s.m): for column in range(s.n): theta[t][row, column] = model.addVar(lb=-G_bound, ub=G_bound) for t in range(T + 1): for i in s.modes: z[t, i] = model.addVar(vtype=GRB.BINARY) x[T] = np.empty((s.n, 1), dtype='object') # Final state in Mode i for row in range(s.n): x[T][row, 0] = model.addVar(lb=-G_bound, ub=G_bound) for t in range(T + 1): G[t] = np.empty((s.n, s.n), dtype='object') for row in range(s.n): for column in range(s.n): G[t][row, column] = model.addVar(lb=-G_bound, ub=G_bound) # Trajectory Constraints: bigM = G_bound * 2 for t in range(T): for i in s.modes: for row in range(s.n): Ax = LinExpr() for k in range(s.n): Ax.add(s.A[i][row, k] * x[t][k, 0]) for k in range(s.m): Ax.add(s.B[i][row, k] * u[t][k, 0]) model.addConstr(x[t + 1][row, 0] <= Ax + s.c[i][row] + bigM - bigM * z[t, i]) model.addConstr(x[t + 1][row, 0] >= Ax + s.c[i][row] - bigM + bigM * z[t, i]) # Generator Dynamics Constraints: for t in range(T): for i in s.modes: for row in range(s.n): for column in range(s.n): AG = LinExpr() for k in range(s.n): AG.add(s.A[i][row, k] * G[t][k, column]) for k in range(s.m): AG.add(s.B[i][row, k] * theta[t][k, column]) model.addConstr( G[t + 1][row, column] <= AG + bigM - bigM * z[t, i]) model.addConstr( G[t + 1][row, column] >= AG - bigM + bigM * z[t, i]) # Constraints of mode subsets for t in range(T): for i in s.modes: subset_MILP(model, G[t], s.Pi, s.H[i], s.h[i], x[t], z[t, i]) subset_MILP(model, theta[t], s.Pi, s.F[i], s.f[i], u[t], z[t, i]) # Constraints of modes: for t in range(T + 1): sum_z = LinExpr() for i in s.modes: sum_z.add(z[t, i]) model.addConstr(sum_z == 1, name="sadra%d" % T) model.update() s.core_constraints[T] = model.getConstrs() s.core_Vars[T] = model.getVars() s.library[T] = (model, x, u, G, theta, z)
m.addConstrs((X_coedta[cancha, equipoO, equipoE, deporte, bloque, dia] == X_coedta[cancha, equipoE, equipoO, deporte, bloque, dia] for cancha in C for deporte in D for bloque in T for equipoE in E for equipoO in E if equipoE != equipoO for dia in A), "C10") # m.addConstrs((quicksum(a_rpt[punto, producto, tiempo] for punto in R for producto in S) >= 1 for tiempo in T), "c9") # m.addConstrs((X_coedta[cancha, equipo, equipo, deporte, bloque, dia] == 0 for cancha in C for equipo in E for bloque in T for dia in A for deporte in D), "C10") print("R10 lista") # Optimizar m.optimize() print("Num Vars: ", len(m.getVars())) print("Num Restricciones: ", len(m.getConstrs())) status = m.status print('Status:', status) if status != GRB.Status.OPTIMAL: print('Optimization was stopped with status %d' % status) # exit(0) if status == GRB.Status.INF_OR_UNBD: print( 'The model cannot be solved because it is infeasible or unbounded') if status == GRB.Status.INFEASIBLE: print("Model is INFEASIBLE")
from gurobipy import GRB, Model m = Model() m.addVar() x = m.addVar(vtype=GRB.BINARY, name="x") y = m.addVar(vtype=GRB.BINARY, name="y") z = m.addVar(vtype=GRB.BINARY, name="z") m.update() m.setObjective(x + y + 2 * z, GRB.MAXIMIZE) m.addConstr(x + 2 * y + 3 * z <= 6, name="c0") m.addConstr(x + y >= 1, name="c1") m.optimize() m.printAttr("X") for constr in m.getConstrs(): print(constr, constr.getAttr("slack"))