class UnitCommitment: def __init__(self, generators, demand): self.generators = generators self.demand = demand self.period = range(1, len(self.demand) + 1) self.model = Model(name='UnitCommitment') self.p, self.u = {}, {} def build_model(self, fixed=False, u_fixed=None): for t in self.period: for g in self.generators.index: if fixed: self.u[t, g] = self.model.add_var(lb=u_fixed[t, g], ub=u_fixed[t, g]) else: self.u[t, g] = self.model.add_var(var_type=BINARY) self.p[t, g] = self.model.add_var() # Max/min power for t in self.period: for g in self.generators.index: self.model.add_constr( self.p[t, g] <= self.generators.loc[g, 'p_max'] * self.u[t, g], name=f'pmax_constr[{t},{g}]') self.model.add_constr( self.p[t, g] >= self.generators.loc[g, 'p_min'] * self.u[t, g], name=f'pmin_constr[{t},{g}]') # Power balance for t in self.period: self.model.add_constr(xsum( self.p[t, g] for g in self.generators.index) == self.demand.loc[t, 'demand'], name=f'power_bal_constr[{t}]') # Min on for t in self.period[1:]: for g in self.generators.index: min_on_time = min(t + self.generators.loc[g, 'min_on'] - 1, len(self.period)) for tau in range(t, min_on_time + 1): self.model.add_constr( self.u[tau, g] >= self.u[t, g] - self.u[t - 1, g], name=f'min_on_constr[{t},{g}]') # Min off for t in self.period[1:]: for g in self.generators.index: min_off_time = min(t + self.generators.loc[g, 'min_off'] - 1, len(self.period)) for tau in range(t, min_off_time + 1): self.model.add_constr( 1 - self.u[tau, g] >= self.u[t - 1, g] - self.u[t, g], name=f'min_off_constr[{t},{g}]') # Objective function self.model.objective = minimize( xsum( xsum(self.p[t, g] * self.generators.loc[g, 'c_var'] + self.u[t, g] * self.generators.loc[g, 'c_fix'] for g in self.generators.index) for t in self.period)) def optimize(self): self.model.optimize() return self.u, self.p, self.model.objective.x, self.model.status.name def get_prices(self): u_fixed = {(t, g): self.u[t, g].x for g in self.generators.index for t in self.period} self.model.clear() self.build_model(fixed=True, u_fixed=u_fixed) self.optimize() return [ self.model.constr_by_name(f'power_bal_constr[{t}]').pi for t in self.period ]
def test_tsp_mipstart(solver: str): """tsp related tests""" announce_test("TSP - MIPStart", solver) N = ['a', 'b', 'c', 'd', 'e', 'f', 'g'] n = len(N) i0 = N[0] A = { ('a', 'd'): 56, ('d', 'a'): 67, ('a', 'b'): 49, ('b', 'a'): 50, ('d', 'b'): 39, ('b', 'd'): 37, ('c', 'f'): 35, ('f', 'c'): 35, ('g', 'b'): 35, ('b', 'g'): 25, ('a', 'c'): 80, ('c', 'a'): 99, ('e', 'f'): 20, ('f', 'e'): 20, ('g', 'e'): 38, ('e', 'g'): 49, ('g', 'f'): 37, ('f', 'g'): 32, ('b', 'e'): 21, ('e', 'b'): 30, ('a', 'g'): 47, ('g', 'a'): 68, ('d', 'c'): 37, ('c', 'd'): 52, ('d', 'e'): 15, ('e', 'd'): 20 } # input and output arcs per node Aout = {n: [a for a in A if a[0] == n] for n in N} Ain = {n: [a for a in A if a[1] == n] for n in N} m = Model(solver_name=solver) m.verbose = 0 x = { a: m.add_var(name='x({},{})'.format(a[0], a[1]), var_type=BINARY) for a in A } m.objective = xsum(c * x[a] for a, c in A.items()) for i in N: m += xsum(x[a] for a in Aout[i]) == 1, 'out({})'.format(i) m += xsum(x[a] for a in Ain[i]) == 1, 'in({})'.format(i) # continuous variable to prevent subtours: each # city will have a different "identifier" in the planned route y = {i: m.add_var(name='y({})'.format(i), lb=0.0) for i in N} # subtour elimination for (i, j) in A: if i0 not in [i, j]: m.add_constr(y[i] - (n + 1) * x[(i, j)] >= y[j] - n) route = ['a', 'g', 'f', 'c', 'd', 'e', 'b', 'a'] m.start = [(x[route[i - 1], route[i]], 1.0) for i in range(1, len(route))] m.optimize() check_result("mip model status", m.status == OptimizationStatus.OPTIMAL) check_result("mip model objective", (abs(m.objective_value - 262)) <= 0.0001) print('')
n chess queens should be placed in a n x n chess board so that no queen can attack another, i.e., just one queen per line, column and diagonal. """ from sys import stdout from mip.model import Model, xsum from mip.constants import MAXIMIZE, BINARY # number of queens n = 75 queens = Model('queens', MAXIMIZE) x = [[ queens.add_var('x({},{})'.format(i, j), var_type=BINARY) for j in range(n) ] for i in range(n)] # one per row for i in range(n): queens += xsum(x[i][j] for j in range(n)) == 1, 'row({})'.format(i) # one per column for j in range(n): queens += xsum(x[i][j] for i in range(n)) == 1, 'col({})'.format(j) # diagonal \ for p, k in enumerate(range(2 - n, n - 2 + 1)): queens += xsum(x[i][j] for i in range(n) for j in range(n) if i - j == k) <= 1, 'diag1({})'.format(p)
IN = defaultdict(set) # an arbitrary initial point n0 = min(i for i in N) for a in A: OUT[a[0]].add(a) IN[a[1]].add(a) print('solving TSP with {} cities'.format(len(N))) model = Model() # binary variables indicating if arc (i,j) is used on the route or not x = { a: model.add_var('x({},{})'.format(a[0], a[1]), var_type=BINARY) for a in A.keys() } # continuous variable to prevent subtours: each # city will have a different "identifier" in the planned route y = {i: model.add_var(name='y({})') for i in N} # objective function: minimize the distance model.objective = minimize(xsum(A[a] * x[a] for a in A.keys())) # constraint : enter each city coming from another city for i in N: model += xsum(x[a] for a in OUT[i]) == 1 # constraint : leave each city coming from another city
def cg(): """ Simple column generation implementation for a Cutting Stock Problem """ L = 250 # bar length m = 4 # number of requests w = [187, 119, 74, 90] # size of each item b = [1, 2, 2, 1] # demand for each item # creating models and auxiliary lists master = Model() lambdas = [] constraints = [] # creating an initial pattern (which cut one item per bar) # to provide the restricted master problem with a feasible solution for i in range(m): lambdas.append( master.add_var(obj=1, name='lambda_%d' % (len(lambdas) + 1))) # creating constraints for i in range(m): constraints.append( master.add_constr(lambdas[i] >= b[i], name='i_%d' % (i + 1))) new_vars = True while new_vars: ########## # STEP 1: solving restricted master problem ########## master.optimize() # printing dual values print_solution(master) print('pi = ', end='') print([constraints[i].pi for i in range(m)]) print('') ########## # STEP 2: updating pricing objective with dual values from master ########## a, pricing = get_pricing(m, w, L) pricing.objective = 1 for i in range(m): a[i].obj = -constraints[i].pi # solving pricing problem pricing.optimize() # printing pricing solution z_val = pricing.objective_value print('Pricing:') print(' z = {z_val}'.format(**locals())) print(' a = ', end='') print([v.x for v in pricing.vars]) print('') ########## # STEP 3: adding the new columns ########## # checking if columns with negative reduced cost were produced and # adding them into the restricted master problem if 1 + pricing.objective_value < -EPS: coeffs = [a[i].x for i in range(m)] column = Column(constraints, coeffs) lambdas.append( master.add_var(obj=1, column=column, name='lambda_%d' % (len(lambdas) + 1))) print('new pattern = {coeffs}'.format(**locals())) # if no column with negative reduced cost was produced, then linear # relaxation of the restricted master problem is solved else: new_vars = False pricing.write('pricing.lp') print_solution(master)
p = [0, 3, 2, 5, 4, 2, 3, 4, 2, 4, 6, 0] u = [[0, 0], [5, 1], [0, 4], [1, 4], [1, 3], [3, 2], [3, 1], [2, 4], [4, 0], [5, 2], [2, 5], [0, 0]] c = [6, 8] S = [[0, 1], [0, 2], [0, 3], [1, 4], [1, 5], [2, 9], [2, 10], [3, 8], [4, 6], [4, 7], [5, 9], [5, 10], [6, 8], [6, 9], [7, 8], [8, 11], [9, 11], [10, 11]] (R, J, T) = (range(len(c)), range(len(p)), range(sum(p))) model = Model() x = [[model.add_var(name='x({},{})'.format(j, t), var_type=BINARY) for t in T] for j in J] model.objective = xsum(x[len(J) - 1][t] * t for t in T) for j in J: model += xsum(x[j][t] for t in T) == 1 for (r, t) in product(R, T): model += xsum(u[j][r] * x[j][t2] for j in J for t2 in range(max(0, t - p[j] + 1), t + 1)) <= c[r] for (j, s) in S: model += xsum(t * x[s][t] - t * x[j][t] for t in T) >= p[j] model.optimize()
""" from itertools import product import bmcp_data import bmcp_greedy from mip.model import Model, xsum, minimize from mip.constants import MINIMIZE, BINARY data = bmcp_data.read('P1.col') N, r, d = data.N, data.r, data.d S = bmcp_greedy.build(data) C, U = S.C, [i for i in range(S.u_max + 1)] m = Model(sense=MINIMIZE) x = [[m.add_var('x({},{})'.format(i, c), var_type=BINARY) for c in U] for i in N] z = m.add_var('z') m.objective = minimize(z) for i in N: m += xsum(x[i][c] for c in U) == r[i] for i, j, c1, c2 in product(N, N, U, U): if i != j and c1 <= c2 < c1 + d[i][j]: m += x[i][c1] + x[j][c2] <= 1 for i, c1, c2 in product(N, U, U): if c1 < c2 < c1 + d[i][i]: m += x[i][c1] + x[i][c2] <= 1
if len(cp.cuts) > 256: for cut in cp.cuts: model.add_cut(cut) return for cut in cp.cuts: model.add_cut(cut) return inst = TSPData(argv[1]) n, d = inst.n, inst.d model = Model() x = [[ model.add_var(name='x({},{})'.format(i, j), var_type=BINARY) for j in range(n) ] for i in range(n)] y = [model.add_var(name='y({})'.format(i), lb=0.0, ub=n) for i in range(n)] model.objective = xsum(d[i][j] * x[i][j] for j in range(n) for i in range(n)) for i in range(n): model += xsum(x[j][i] for j in range(n) if j != i) == 1 model += xsum(x[i][j] for j in range(n) if j != i) == 1 for (i, j) in [(i, j) for (i, j) in product(range(1, n), range(1, n)) if i != j]: model += y[i] - (n + 1) * x[i][j] >= y[j] - n F = [] for i in range(n):