small polish

This commit is contained in:
Laurent Perron
2018-12-30 18:12:26 +01:00
parent 68b35112b7
commit f0f65fee9a

View File

@@ -10,6 +10,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Solves the Stell Mill Slab problem with 4 different techniques."""
from __future__ import print_function
import argparse
@@ -291,22 +292,6 @@ class SteelMillSlabSolutionPrinter(cp_model.CpSolverSolutionCallback):
print(line)
class SolutionPrinterWithObjective(cp_model.CpSolverSolutionCallback):
"""Print intermediate solutions."""
def __init__(self):
cp_model.CpSolverSolutionCallback.__init__(self)
self.__solution_count = 0
self.__start_time = time.time()
def on_solution_callback(self):
current_time = time.time()
print('Solution %i, time = %f s, objective = %i' %
(self.__solution_count, current_time - self.__start_time,
self.ObjectiveValue()))
self.__solution_count += 1
def steel_mill_slab(problem, break_symmetries, output_proto):
"""Solves the Steel Mill Slab Problem."""
### Load problem.
@@ -347,12 +332,14 @@ def steel_mill_slab(problem, break_symmetries, output_proto):
for s in all_slabs
]
color_is_in_slab = [[
model.NewBoolVar('color_%i_in_slab_%i' % (c + 1, s)) for c in all_colors
model.NewBoolVar('color_%i_in_slab_%i' % (c + 1, s))
for c in all_colors
] for s in all_slabs]
# Compute load of all slabs.
for s in all_slabs:
model.Add(sum(assign[o][s] * widths[o] for o in all_orders) == loads[s])
model.Add(
sum(assign[o][s] * widths[o] for o in all_orders) == loads[s])
# Orders are assigned to one slab.
for o in all_orders:
@@ -438,13 +425,14 @@ def steel_mill_slab(problem, break_symmetries, output_proto):
### Solve model.
solver = cp_model.CpSolver()
status = solver.Solve(model)
solver.parameters.num_search_workers = 8
objective_printer = cp_model.ObjectiveSolutionPrinter()
status = solver.SolveWithSolutionCallback(model, objective_printer)
### Output the solution.
if status == cp_model.OPTIMAL:
print('Loss = %i, time = %f s, %i conflicts' %
(solver.ObjectiveValue(), solver.WallTime(),
solver.NumConflicts()))
print('Loss = %i, time = %f s, %i conflicts' % (
solver.ObjectiveValue(), solver.WallTime(), solver.NumConflicts()))
else:
print('No solution')
@@ -476,7 +464,9 @@ def collect_valid_slabs(capacities, colors, widths, loss_array, all_colors):
assign = [model.NewBoolVar('assign_%i' % o) for o in all_orders]
load = model.NewIntVar(0, max_capacity, 'load')
color_in_slab = [model.NewBoolVar('color_%i' % (c + 1)) for c in all_colors]
color_in_slab = [
model.NewBoolVar('color_%i' % (c + 1)) for c in all_colors
]
# Compute load.
model.Add(sum(assign[o] * widths[o] for o in all_orders) == load)
@@ -496,12 +486,24 @@ def collect_valid_slabs(capacities, colors, widths, loss_array, all_colors):
loss = model.NewIntVar(0, max(loss_array), 'loss')
model.AddElement(load, loss_array, loss)
model.AddDecisionStrategy(assign, cp_model.CHOOSE_FIRST,
cp_model.SELECT_MAX_VALUE)
### Solve model and collect columns.
print('Collect Valid Slabs...DONE')
print('Collect Valid Slabs...START')
start_time = time.time()
solver = cp_model.CpSolver()
# Add solution callback to store all possible slab templates.
collector = AllSolutionsCollector(assign + [loss, load])
# Force solver to follow the decision strategy exactly.
solver.parameters.search_branching = cp_model.FIXED_SEARCH
solver.SearchForAllSolutions(model, collector)
print('Collect Valid Slabs...DONE')
run_time = time.time() - start_time
print('Collect Valid Slabs...DONE in %.2f s' % run_time)
return collector.all_solutions()
@@ -535,7 +537,9 @@ def steel_mill_slab_with_valid_slabs(problem, break_symmetries, output_proto):
assign = [[
model.NewBoolVar('assign_%i_to_slab_%i' % (o, s)) for s in all_slabs
] for o in all_orders]
loads = [model.NewIntVar(0, max_capacity, 'load_%i' % s) for s in all_slabs]
loads = [
model.NewIntVar(0, max_capacity, 'load_%i' % s) for s in all_slabs
]
losses = [model.NewIntVar(0, max_loss, 'loss_%i' % s) for s in all_slabs]
unsorted_valid_slabs = collect_valid_slabs(capacities, colors, widths,
@@ -548,8 +552,8 @@ def steel_mill_slab_with_valid_slabs(problem, break_symmetries, output_proto):
for s in all_slabs:
model.AddAllowedAssignments(
[assign[o][s]
for o in all_orders] + [losses[s], loads[s]], valid_slabs)
[assign[o][s] for o in all_orders] + [losses[s], loads[s]],
valid_slabs)
# Orders are assigned to one slab.
for o in all_orders:
@@ -590,7 +594,8 @@ def steel_mill_slab_with_valid_slabs(problem, break_symmetries, output_proto):
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]))
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):
@@ -628,15 +633,15 @@ def steel_mill_slab_with_valid_slabs(problem, break_symmetries, output_proto):
### Solve model.
solver = cp_model.CpSolver()
solver.num_search_workers = 8
solution_printer = SteelMillSlabSolutionPrinter(orders, assign, loads,
losses)
status = solver.SolveWithSolutionCallback(model, solution_printer)
### Output the solution.
if status == cp_model.OPTIMAL:
print('Loss = %i, time = %f s, %i conflicts' %
(solver.ObjectiveValue(), solver.WallTime(),
solver.NumConflicts()))
print('Loss = %i, time = %.2f s, %i conflicts' % (
solver.ObjectiveValue(), solver.WallTime(), solver.NumConflicts()))
else:
print('No solution')
@@ -680,7 +685,8 @@ def steel_mill_slab_with_column_generation(problem, output_proto):
for o in all_orders:
model.Add(
sum(selected[i] for i in all_valid_slabs if valid_slabs[i][o]) == 1)
sum(selected[i] for i in all_valid_slabs
if valid_slabs[i][o]) == 1)
# Redundant constraint (sum of loads == sum of widths).
model.Add(
@@ -690,8 +696,8 @@ def steel_mill_slab_with_column_generation(problem, output_proto):
# Objective.
max_loss = max(valid_slabs[i][-2] for i in all_valid_slabs)
obj = model.NewIntVar(0, num_slabs * max_loss, 'obj')
model.Add(
obj == sum(selected[i] * valid_slabs[i][-2] for i in all_valid_slabs))
model.Add(obj == sum(
selected[i] * valid_slabs[i][-2] for i in all_valid_slabs))
model.Minimize(obj)
print('Model created')
@@ -704,14 +710,14 @@ def steel_mill_slab_with_column_generation(problem, output_proto):
### Solve model.
solver = cp_model.CpSolver()
solution_printer = SolutionPrinterWithObjective()
solver.parameters.num_search_workers = 8
solution_printer = cp_model.ObjectiveSolutionPrinter()
status = solver.SolveWithSolutionCallback(model, solution_printer)
### Output the solution.
if status == cp_model.OPTIMAL:
print('Loss = %i, time = %f s, %i conflicts' %
(solver.ObjectiveValue(), solver.WallTime(),
solver.NumConflicts()))
if status in (cp_model.OPTIMAL, cp_model.FEASIBLE):
print('Loss = %i, time = %.2f s, %i conflicts' % (
solver.ObjectiveValue(), solver.WallTime(), solver.NumConflicts()))
else:
print('No solution')
@@ -753,7 +759,8 @@ def steel_mill_slab_with_mip_column_generation(problem):
(num_valid_slabs, generate - start))
# create model and decision variables.
solver = pywraplp.Solver('Steel', pywraplp.Solver.BOP_INTEGER_PROGRAMMING)
solver = pywraplp.Solver('Steel',
pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING)
selected = [
solver.IntVar(0.0, 1.0, 'selected_%i' % i) for i in all_valid_slabs
]
@@ -776,7 +783,7 @@ def steel_mill_slab_with_mip_column_generation(problem):
### Output the solution.
if status == pywraplp.Solver.OPTIMAL:
print('Objective value = %f found in %f s' %
print('Objective value = %f found in %.2f s' %
(solver.Objective().Value(), time.time() - generate))
else:
print('No solution')