more work on steel_mill_slab_sat

This commit is contained in:
Laurent Perron
2017-10-26 11:49:22 +02:00
parent 157d360ecf
commit 6cf95ec0e7
2 changed files with 55 additions and 47 deletions

View File

@@ -458,7 +458,7 @@ def CollectValidSlabs(capacities, colors, widths, loss_array, all_colors):
return collector.AllSolutions()
def SteelMillSlabWithColumns(problem, break_symmetries):
def SteelMillSlabWithValidSlabs(problem, break_symmetries):
"""Solves the Steel Mill Slab Problem."""
### Load problem.
(num_slabs, capacities, num_colors, orders) = BuildProblem(problem)
@@ -515,59 +515,67 @@ def SteelMillSlabWithColumns(problem, break_symmetries):
model.Add(loads[s] >= loads[s + 1])
# Collect equivalent orders.
width_to_unique_color_order = {}
ordered_equivalent_orders = []
orders_per_color = [[o for o in all_orders if colors[o] == c + 1]
if break_symmetries:
print('Breaking symmetries')
width_to_unique_color_order = {}
ordered_equivalent_orders = []
orders_per_color = [[o for o in all_orders if colors[o] == c + 1]
for c in all_colors]
for c in all_colors:
colored_orders = orders_per_color[c]
if not colored_orders:
continue
if len(colored_orders) == 1:
o = colored_orders[0]
w = widths[o]
if w not in width_to_unique_color_order:
width_to_unique_color_order[w] = [o]
else:
width_to_unique_color_order[w].append(o)
else:
local_width_to_order = {}
for o in colored_orders:
for c in all_colors:
colored_orders = orders_per_color[c]
if not colored_orders:
continue
if len(colored_orders) == 1:
o = colored_orders[0]
w = widths[o]
if w not in local_width_to_order:
local_width_to_order[w] = []
local_width_to_order[w].append(o)
for w, os in local_width_to_order.items():
if len(os) > 1:
for p in range(len(os) - 1):
ordered_equivalent_orders.append((os[p], os[p + 1]))
for w, os in width_to_unique_color_order.items():
if len(os) > 1:
for p in range(len(os) - 1):
ordered_equivalent_orders.append((os[p], os[p + 1]))
if w not in width_to_unique_color_order:
width_to_unique_color_order[w] = [o]
else:
width_to_unique_color_order[w].append(o)
else:
local_width_to_order = {}
for o in colored_orders:
w = widths[o]
if w not in local_width_to_order:
local_width_to_order[w] = []
local_width_to_order[w].append(o)
for w, os in local_width_to_order.items():
if len(os) > 1:
for p in range(len(os) - 1):
ordered_equivalent_orders.append((os[p], os[p + 1]))
for w, os in width_to_unique_color_order.items():
if len(os) > 1:
for p in range(len(os) - 1):
ordered_equivalent_orders.append((os[p], os[p + 1]))
# Create position variables if there are symmetries to be broken.
if break_symmetries and ordered_equivalent_orders:
print(' - creating %i symmetry breaking constraints' %
len(ordered_equivalent_orders))
positions = {}
for p in ordered_equivalent_orders:
if p[0] not in positions:
positions[p[0]] = model.NewIntVar(0, num_slabs - 1,
'position_of_slab_%i' % p[0])
model.AddMapDomain(positions[p[0]], assign[p[0]])
if p[1] not in positions:
positions[p[1]] = model.NewIntVar(0, num_slabs - 1,
'position_of_slab_%i' % p[1])
model.AddMapDomain(positions[p[1]], assign[p[1]])
# Finally add the symmetry breaking constraint.
model.Add(positions[p[0]] <= positions[p[1]])
# Create position variables if there are symmetries to be broken.
if ordered_equivalent_orders:
print(' - creating %i symmetry breaking constraints' %
len(ordered_equivalent_orders))
positions = {}
for p in ordered_equivalent_orders:
if p[0] not in positions:
positions[p[0]] = model.NewIntVar(0, num_slabs - 1,
'position_of_slab_%i' % p[0])
model.AddMapDomain(positions[p[0]], assign[p[0]])
if p[1] not in positions:
positions[p[1]] = model.NewIntVar(0, num_slabs - 1,
'position_of_slab_%i' % p[1])
model.AddMapDomain(positions[p[1]], assign[p[1]])
# Finally add the symmetry breaking constraint.
model.Add(positions[p[0]] <= positions[p[1]])
# Objective.
obj = model.NewIntVar(0, num_slabs * max_loss, 'obj')
model.Add(obj == sum(losses))
model.Minimize(obj)
print('Model created')
f = open('/tmp/steel.pbtxt', 'w')
f.write(str(model.ModelProto()))
f.close()
### Solve model.
solver = cp_model.CpSolver()
solution_printer = SteelMillSlabSolutionPrinter(orders, assign, loads, losses)
@@ -583,7 +591,7 @@ def SteelMillSlabWithColumns(problem, break_symmetries):
def main(args):
if args.precompute_valid_slabs:
SteelMillSlabWithColumns(args.problem, args.break_symmetries)
SteelMillSlabWithValidSlabs(args.problem, args.break_symmetries)
else:
SteelMillSlab(args.problem, args.break_symmetries)