OR-Tools Python - AddNoOverlap2D 不工作 - 切料问题
OR-Tools Python - AddNoOverlap2D not working - Stock Cutting Problem
正在尝试从一个大矩形中切割给定的一组矩形。该程序 运行 很好,但它不遵守 AddNoOverlap2D
约束。
程序输出
0, 0 -> 2, 2
0, 0 -> 1, 3
0, 0 -> 4, 3
程序输出的所有矩形坐标都以(0,0)
为第一点,因此是重叠的。 我想要得到不重叠的矩形?
我正在使用model.AddNoOverlap2D
约束,我设置的objective是为了最小化大矩形的未使用区域。完整代码:
from __future__ import print_function
import collections
from ortools.sat.python import cp_model
def StockCutter():
"""Cutting Stock problem."""
# Create the model
model = cp_model.CpModel()
# rect = [width, height]
rects_data = [
[2, 2],
[1, 3],
[4, 3]
]
rect_ids = range(len(rects_data))
# parent rect (to cut from)
horizon = [6, 6]
print("Horizon: ", horizon)
# Named tuple to store information about created variables
rect_type = collections.namedtuple('rect_type', 'x1 y1 x2 y2 x_interval y_interval')
all_vars = {}
# to save area of all small rects, to cut from parent rect
total_area = 0
# x_intervals holds the widths of each rect
x_intervals = collections.defaultdict(list)
# y_intervals holds the lengths of each rect
y_intervals = collections.defaultdict(list)
for rect_id, rect in enumerate(rects_data):
width = rect[0]
height = rect[1]
area = width * height
total_area += area
print(f"Rect: {width}x{height}, Area: {area}")
suffix = '_%i_%i' % (width, height)
# interval to represent width
x1_var = model.NewIntVar(0, horizon[0], 'x1' + suffix)
x2_var = model.NewIntVar(0, horizon[0], 'x2' + suffix)
x_interval_var = model.NewIntervalVar(x1_var, width, x2_var, 'x_interval' + suffix)
# interval to represent height
y1_var = model.NewIntVar(0, horizon[1], 'y1' + suffix)
y2_var = model.NewIntVar(0, horizon[1], 'y2' + suffix)
y_interval_var = model.NewIntervalVar(y1_var, height, y2_var, 'y_interval' + suffix)
all_vars[rect_id] = rect_type(
x1=x1_var,
y1=y1_var,
x2=x2_var,
y2=y2_var,
x_interval=x_interval_var,
y_interval=y_interval_var
)
x_intervals[rect_id].append(x_interval_var)
y_intervals[rect_id].append(y_interval_var)
# NOT WORKING???
for rect_id in rect_ids:
model.AddNoOverlap2D(x_intervals[rect_id], y_intervals[rect_id])
# objective: Area of parent (horizon) is max that the sum of all the rectangles' areas can have
obj_var = model.NewIntVar(0, horizon[0]*horizon[1], 'area')
# minimize the area not used
model.Minimize(obj_var - total_area)
# Solve model
solver = cp_model.CpSolver()
status = solver.Solve(model)
if status == cp_model.OPTIMAL:
# print coords
for rect_id, rect in enumerate(rects_data):
x1=solver.Value(all_vars[rect_id].x1)
y1=solver.Value(all_vars[rect_id].y1)
x2=solver.Value(all_vars[rect_id].x2)
y2=solver.Value(all_vars[rect_id].y2)
print(f"{x1}, {y1} -> {x2}, {y2}")
StockCutter()
您只应使用 x_intervals 和 y_intervals 的列表调用一次 AddNoOverlap2D:
# x_intervals holds the widths of each rect
x_intervals = []
# y_intervals holds the lengths of each rect
y_intervals = []
for rect_id, rect in enumerate(rects_data):
...
x_intervals.append(x_interval_var)
y_intervals.append(y_interval_var)
model.AddNoOverlap2D(x_intervals, y_intervals)
正在尝试从一个大矩形中切割给定的一组矩形。该程序 运行 很好,但它不遵守 AddNoOverlap2D
约束。
程序输出
0, 0 -> 2, 2
0, 0 -> 1, 3
0, 0 -> 4, 3
程序输出的所有矩形坐标都以(0,0)
为第一点,因此是重叠的。 我想要得到不重叠的矩形?
我正在使用model.AddNoOverlap2D
约束,我设置的objective是为了最小化大矩形的未使用区域。完整代码:
from __future__ import print_function
import collections
from ortools.sat.python import cp_model
def StockCutter():
"""Cutting Stock problem."""
# Create the model
model = cp_model.CpModel()
# rect = [width, height]
rects_data = [
[2, 2],
[1, 3],
[4, 3]
]
rect_ids = range(len(rects_data))
# parent rect (to cut from)
horizon = [6, 6]
print("Horizon: ", horizon)
# Named tuple to store information about created variables
rect_type = collections.namedtuple('rect_type', 'x1 y1 x2 y2 x_interval y_interval')
all_vars = {}
# to save area of all small rects, to cut from parent rect
total_area = 0
# x_intervals holds the widths of each rect
x_intervals = collections.defaultdict(list)
# y_intervals holds the lengths of each rect
y_intervals = collections.defaultdict(list)
for rect_id, rect in enumerate(rects_data):
width = rect[0]
height = rect[1]
area = width * height
total_area += area
print(f"Rect: {width}x{height}, Area: {area}")
suffix = '_%i_%i' % (width, height)
# interval to represent width
x1_var = model.NewIntVar(0, horizon[0], 'x1' + suffix)
x2_var = model.NewIntVar(0, horizon[0], 'x2' + suffix)
x_interval_var = model.NewIntervalVar(x1_var, width, x2_var, 'x_interval' + suffix)
# interval to represent height
y1_var = model.NewIntVar(0, horizon[1], 'y1' + suffix)
y2_var = model.NewIntVar(0, horizon[1], 'y2' + suffix)
y_interval_var = model.NewIntervalVar(y1_var, height, y2_var, 'y_interval' + suffix)
all_vars[rect_id] = rect_type(
x1=x1_var,
y1=y1_var,
x2=x2_var,
y2=y2_var,
x_interval=x_interval_var,
y_interval=y_interval_var
)
x_intervals[rect_id].append(x_interval_var)
y_intervals[rect_id].append(y_interval_var)
# NOT WORKING???
for rect_id in rect_ids:
model.AddNoOverlap2D(x_intervals[rect_id], y_intervals[rect_id])
# objective: Area of parent (horizon) is max that the sum of all the rectangles' areas can have
obj_var = model.NewIntVar(0, horizon[0]*horizon[1], 'area')
# minimize the area not used
model.Minimize(obj_var - total_area)
# Solve model
solver = cp_model.CpSolver()
status = solver.Solve(model)
if status == cp_model.OPTIMAL:
# print coords
for rect_id, rect in enumerate(rects_data):
x1=solver.Value(all_vars[rect_id].x1)
y1=solver.Value(all_vars[rect_id].y1)
x2=solver.Value(all_vars[rect_id].x2)
y2=solver.Value(all_vars[rect_id].y2)
print(f"{x1}, {y1} -> {x2}, {y2}")
StockCutter()
您只应使用 x_intervals 和 y_intervals 的列表调用一次 AddNoOverlap2D:
# x_intervals holds the widths of each rect
x_intervals = []
# y_intervals holds the lengths of each rect
y_intervals = []
for rect_id, rect in enumerate(rects_data):
...
x_intervals.append(x_interval_var)
y_intervals.append(y_interval_var)
model.AddNoOverlap2D(x_intervals, y_intervals)