Skip to content

Commit

Permalink
1.0.607
Browse files Browse the repository at this point in the history
  • Loading branch information
vlkong committed Oct 24, 2016
1 parent 6d6cabb commit 5852a1a
Show file tree
Hide file tree
Showing 13 changed files with 120 additions and 118 deletions.
2 changes: 1 addition & 1 deletion examples/cp/jupyter/golomb_ruler.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@
"outputs": [],
"source": [
"# Create model object\n",
"mdl = CpoModel()"
"mdl = CpoModel(name=\"GolombRuler\")"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion examples/cp/jupyter/house_building.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@
},
"outputs": [],
"source": [
"mdl = CpoModel()"
"mdl = CpoModel(name=\"HouseBuilding\")"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion examples/cp/jupyter/n_queen.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@
},
"outputs": [],
"source": [
"mdl = CpoModel()"
"mdl = CpoModel(name=\"NQueen\")"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion examples/cp/jupyter/sched_square.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@
},
"outputs": [],
"source": [
"mdl = CpoModel()"
"mdl = CpoModel(name=\"SchedSquare\")"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion examples/cp/jupyter/sports_scheduling.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@
},
"outputs": [],
"source": [
"mdl = CpoModel(sfile=\"Sports_scheduling\")\n",
"mdl = CpoModel(name=\"SportsScheduling\")\n",
"\n",
"# Variables of the model\n",
"plays = {}\n",
Expand Down
2 changes: 1 addition & 1 deletion examples/cp/jupyter/sudoku.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@
},
"outputs": [],
"source": [
"mdl = CpoModel()"
"mdl = CpoModel(name=\"Sudoku\")"
]
},
{
Expand Down
11 changes: 6 additions & 5 deletions examples/mp/modeling/diet.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,23 +47,24 @@
("Hotdog", 242.1, 23.5, 2.3, 0, 0, 18, 10.4)
]

Food = namedtuple("Food", ["name", "unit_cost", "qmin", "qmax"])
Nutrient = namedtuple("Nutrient", ["name", "qmin", "qmax"])


def build_diet_model(**kwargs):
# Create tuples with named fields for foods and nutrients
Food = namedtuple("Food", ["name", "unit_cost", "qmin", "qmax"])
food = [Food(*f) for f in FOODS]

Nutrient = namedtuple("Nutrient", ["name", "qmin", "qmax"])
food = [Food(*f) for f in FOODS]
nutrients = [Nutrient(*row) for row in NUTRIENTS]

food_nutrients = {(fn[0], nutrients[n].name):
fn[1 + n] for fn in FOOD_NUTRIENTS for n in range(len(NUTRIENTS))}

# Model
mdl = Model("diet", **kwargs)
mdl = Model(name='diet', **kwargs)

# Decision variables, limited to be >= Food.qmin and <= Food.qmax
qty = dict((f, mdl.continuous_var(f.qmin, f.qmax, f.name)) for f in food)
qty = {f: mdl.continuous_var(lb=f.qmin, ub=f.qmax, name=f.name) for f in food}

# Limit range of nutrients, and mark them as KPIs
for n in nutrients:
Expand Down
8 changes: 4 additions & 4 deletions examples/mp/modeling/nurses.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
from docplex.mp.model import Model
from docplex.util.environment import get_environment



# utility to convert a weekday string to an index in 0..6
_all_days = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"]

Expand All @@ -33,7 +31,9 @@ def __str__(self):


# specialized namedtuple to redefine its str() method
class TShift(namedtuple("TShift", ["department", "day", "start_time", "end_time", "min_requirement", "max_requirement"])):
class TShift(namedtuple("TShift",
["department", "day", "start_time", "end_time", "min_requirement", "max_requirement"])):

def __str__(self):
# keep first two characters in department, uppercase
dept2 = self.department[0:4].upper()
Expand Down Expand Up @@ -524,4 +524,4 @@ def build(context=None, **kwargs):

# Save the CPLEX solution as "solution.json" program output
with get_environment().get_output_stream("solution.json") as fp:
model.solution.export(fp, "json")
model.solution.export(fp, "json")
4 changes: 3 additions & 1 deletion examples/mp/modeling/production.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,16 @@ def build_production_problem(products, resources, consumptions, **kwargs):
mdl.add_constraints((mdl.inside_vars[prod] + mdl.outside_vars[prod] >= prod[1], 'ct_demand_%s' % prod[0]) for prod in products)

# --- resource capacity ---
mdl.add_constraints((mdl.sum(mdl.inside_vars[p] * consumptions[p[0], res[0]] for p in products) <= res[1], 'ct_res_%s' %res[0]) for res in resources)
mdl.add_constraints((mdl.sum(mdl.inside_vars[p] * consumptions[p[0], res[0]] for p in products) <= res[1],
'ct_res_%s' % res[0]) for res in resources)

# --- objective ---
mdl.total_inside_cost = mdl.sum(mdl.inside_vars[p] * p[2] for p in products)
mdl.total_outside_cost = mdl.sum(mdl.outside_vars[p] * p[3] for p in products)
mdl.minimize(mdl.total_inside_cost + mdl.total_outside_cost)
return mdl


def print_production_solution(mdl, products):
obj = mdl.objective_value
print("* Production model solved with objective: {:g}".format(obj))
Expand Down
13 changes: 7 additions & 6 deletions examples/mp/modeling/sport_scheduling.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,19 @@ def build_sports(context=None):
nb_play = {m: nb_intra_divisional if m.is_divisional == 1 else nb_inter_divisional for m in matches}

plays = mdl.binary_var_matrix(keys1=matches, keys2=weeks,
name=lambda mw: "play_%d_%d_w%d" % (mw[0].team1, mw[0].team2, mw[1]))
name=lambda mw: "play_%d_%d_w%d" % (mw[0].team1, mw[0].team2, mw[1]))
mdl.plays = plays

for m in matches:
mdl.add_constraint(mdl.sum(plays[m, w] for w in weeks) == nb_play[m],
"correct_nb_games_%d_%d" % (m.team1, m.team2))
"correct_nb_games_%d_%d" % (m.team1, m.team2))

for w in weeks:
# Each team must play exactly once in a week.
for t in team_range:
max_teams_in_division = (plays[m, w] for m in matches if m.team1 == t or m.team2 == t)
mdl.add_constraint(mdl.sum(max_teams_in_division) == 1,
"plays_exactly_once_%d_%s" % (w, t))
"plays_exactly_once_%d_%s" % (w, t))

# Games between the same teams cannot be on successive weeks.
mdl.add_constraints(plays[m, w] + plays[m, w + 1] <= 1
Expand All @@ -84,17 +84,18 @@ def build_sports(context=None):
m.is_divisional == 1 and (m.team1 == t or m.team2 == t)]

mdl.add_constraint(mdl.sum(max_teams_in_division) >= nb_first_half_games,
"in_division_first_half_%s" % t)
"in_division_first_half_%s" % t)

# postpone divisional matches as much as possible
# we weight each play variable with the square of w.
mdl.maximize(mdl.sum(plays[m, w] * w * w for w in weeks for m in matches if m.is_divisional))
return mdl

# a named tuple to store solution
TSolution = namedtuple("TSolution", ["week", "is_divisional", "team1", "team2"])

def print_sports_solution(mdl):
TSolution = namedtuple("TSolution", ["week", "is_divisional", "team1", "team2"])

def print_sports_solution(mdl):
# iterate with weeks first
solution = [TSolution(w, m.is_divisional, mdl.teams[m.team1], mdl.teams[m.team2])
for w in mdl.weeks for m in mdl.matches
Expand Down
10 changes: 5 additions & 5 deletions examples/mp/workflow/cutstock.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,17 +169,17 @@ def print_information(self):
AbstractModel.print_information(self)

def print_solution(self):
print("| Nb of cuts | Pattern | Detail of pattern (nb of item1, ..., nb of item5) |")
print("| {} |".format("-" * 75))
print("| Nb of cuts | Pattern | Pattern's detail (# of item1,..., # of item5) |")
print("| {} |".format("-" * 70))
for p in self.patterns:
if self.cut_vars[p].solution_value >= 1e-3:
pattern_detail = {b.id: self.pattern_item_filled[(a, b)] for (a, b) in self.pattern_item_filled if
a == p}
print(
"| {:<10g} | {!s:9} | {!s:50} |".format(self.cut_vars[p].solution_value,
"| {:<10g} | {!s:9} | {!s:45} |".format(self.cut_vars[p].solution_value,
p,
pattern_detail))
print("| {} |".format("-" * 75))
print("| {} |".format("-" * 70))

def save_solution_as_json(self, file):
solution = []
Expand Down Expand Up @@ -224,7 +224,7 @@ def run(self, **kwargs):
curr = self.objective_value
print('{}> new column generation iteration, best={:g}, curr={:g}'.format(loop_count, best, curr))
duals = self.get_fill_dual_values()
print('{0}> moving duals from master to sub model: {1!s}'.format(loop_count, duals))
print('{0}> moving duals from master to sub model: {1}'.format(loop_count, map (lambda x: float('%0.2f' % x), duals)))
gen_model.update_duals(duals)
status = gen_model.solve(**kwargs)
if not status:
Expand Down
155 changes: 77 additions & 78 deletions examples/mp/workflow/lagrangian_relaxation.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,89 +33,88 @@


def run_GAP_model(As, Bs, Cs, **kwargs):
mdl = Model('GAP per Wolsey -without- Lagrangian Relaxation', **kwargs)
print("#As={}, #Bs={}, #Cs={}".format(len(As), len(Bs), len(Cs)))
number_of_cs = len(C)
# variables
x_vars = [mdl.binary_var_list(c, name=None) for c in Cs]

# constraints
mdl.add_constraints(mdl.sum(xv) <= 1
for xv in x_vars)

mdl.add_constraints(mdl.sum(x_vars[ii][j] * As[ii][j] for ii in range(number_of_cs)) <= bs
for j, bs in enumerate(Bs))

# objective
total_profit = mdl.sum(mdl.sum(c_ij * x_ij for c_ij, x_ij in zip(c_i, x_i))
for c_i, x_i in zip(Cs, x_vars))
mdl.maximize(total_profit)
mdl.print_information()
assert mdl.solve(**kwargs)
obj = mdl.objective_value
mdl.print_information()
print("* GAP with no relaxation run OK, best objective is: {:g}".format(obj))
mdl.end()
with Model('GAP per Wolsey -without- Lagrangian Relaxation', **kwargs) as mdl:
print("#As={}, #Bs={}, #Cs={}".format(len(As), len(Bs), len(Cs)))
number_of_cs = len(C)
# variables
x_vars = [mdl.binary_var_list(c, name=None) for c in Cs]

# constraints
mdl.add_constraints(mdl.sum(xv) <= 1
for xv in x_vars)

mdl.add_constraints(mdl.sum(x_vars[ii][j] * As[ii][j] for ii in range(number_of_cs)) <= bs
for j, bs in enumerate(Bs))

# objective
total_profit = mdl.sum(mdl.sum(c_ij * x_ij for c_ij, x_ij in zip(c_i, x_i))
for c_i, x_i in zip(Cs, x_vars))
mdl.maximize(total_profit)
mdl.print_information()
assert mdl.solve(**kwargs)
obj = mdl.objective_value
mdl.print_information()
print("* GAP with no relaxation run OK, best objective is: {:g}".format(obj))
return obj


def run_GAP_model_with_Lagrangian_relaxation(As, Bs, Cs, max_iters=101, **kwargs):
mdl = Model('GAP per Wolsey -with- Lagrangian Relaxation', **kwargs)
print("#As={}, #Bs={}, #Cs={}".format(len(As), len(Bs), len(Cs)))
c_range = range(len(Cs))
# variables
x_vars = [mdl.binary_var_list(c, name=None) for c in Cs]
p_vars = [mdl.continuous_var(lb=0) for _ in Cs] # new for relaxation


# was mdl.add_constraint(mdl.sum(xVars[i]) <= 1)
mdl.add_constraints(mdl.sum(xv) == 1 - pv for (xv, pv) in izip(x_vars, p_vars))


mdl.add_constraints(mdl.sum(x_vars[ii][j] * As[ii][j] for ii in c_range) <= bs
for j, bs in enumerate(Bs))

# lagrangian relaxation loop
eps = 1e-6
loop_count = 0
best = 0
initial_multiplier = 1
multipliers = [initial_multiplier] * len(Cs)

total_profit = mdl.sum(mdl.sum(c_ij * x_ij for c_ij, x_ij in zip(c_i, x_i)) for c_i, x_i in zip(Cs, x_vars))
mdl.add_kpi(total_profit, "Total profit")

while loop_count <= max_iters:
loop_count += 1
# rebuilt at each loop iteration
total_penalty = mdl.sum(p_vars[i] * multipliers[i] for i in c_range)
mdl.maximize(total_profit + total_penalty)
ok = mdl.solve(**kwargs)
if not ok:
print("*** solve fails, stopping at iteration: %d" % loop_count)
break
best = mdl.objective_value
penalties = [pv.solution_value for pv in p_vars]
print('%d> new lagrangian iteration, obj=%g, m=%s, p=%s' % (loop_count, best, str(multipliers), str(penalties)))

do_stop = True
justifier = 0
for k in c_range:
penalized_violation = penalties[k] * multipliers[k]
if penalized_violation >= eps:
do_stop = False
justifier = penalized_violation
with Model('GAP per Wolsey -with- Lagrangian Relaxation', **kwargs) as mdl:
print("#As={}, #Bs={}, #Cs={}".format(len(As), len(Bs), len(Cs)))
c_range = range(len(Cs))
# variables
x_vars = [mdl.binary_var_list(c, name=None) for c in Cs]
p_vars = [mdl.continuous_var(lb=0) for _ in Cs] # new for relaxation


# was mdl.add_constraint(mdl.sum(xVars[i]) <= 1)
mdl.add_constraints(mdl.sum(xv) == 1 - pv for (xv, pv) in izip(x_vars, p_vars))


mdl.add_constraints(mdl.sum(x_vars[ii][j] * As[ii][j] for ii in c_range) <= bs
for j, bs in enumerate(Bs))

# lagrangian relaxation loop
eps = 1e-6
loop_count = 0
best = 0
initial_multiplier = 1
multipliers = [initial_multiplier] * len(Cs)

total_profit = mdl.sum(mdl.sum(c_ij * x_ij for c_ij, x_ij in zip(c_i, x_i)) for c_i, x_i in zip(Cs, x_vars))
mdl.add_kpi(total_profit, "Total profit")

while loop_count <= max_iters:
loop_count += 1
# rebuilt at each loop iteration
total_penalty = mdl.sum(p_vars[i] * multipliers[i] for i in c_range)
mdl.maximize(total_profit + total_penalty)
ok = mdl.solve(**kwargs)
if not ok:
print("*** solve fails, stopping at iteration: %d" % loop_count)
break

if do_stop:
print("* Lagrangian relaxation succeeds, best={:g}, penalty={:g}, #iterations={}"
.format(best, total_penalty.solution_value, loop_count))
break
else:
# update multipliers and start loop again.
scale_factor = 1.0 / float(loop_count)
multipliers = [max(multipliers[i] - scale_factor * penalties[i], 0.) for i in c_range]
print('{}> -- loop continues, m={}, justifier={:g}'.format(loop_count, str(multipliers), justifier))
best = mdl.objective_value
penalties = [pv.solution_value for pv in p_vars]
print('%d> new lagrangian iteration:\n\t obj=%g, m=%s, p=%s' % (loop_count, best, str(multipliers), str(penalties)))

do_stop = True
justifier = 0
for k in c_range:
penalized_violation = penalties[k] * multipliers[k]
if penalized_violation >= eps:
do_stop = False
justifier = penalized_violation
break

if do_stop:
print("* Lagrangian relaxation succeeds, best={:g}, penalty={:g}, #iterations={}"
.format(best, total_penalty.solution_value, loop_count))
break
else:
# update multipliers and start loop again.
scale_factor = 1.0 / float(loop_count)
multipliers = [max(multipliers[i] - scale_factor * penalties[i], 0.) for i in c_range]
print('{}> -- loop continues, m={}, justifier={:g}'.format(loop_count, str(multipliers), justifier))

return best

Expand Down
Loading

0 comments on commit 5852a1a

Please sign in to comment.