Two-Dimensional Bin Packing Under Multiple Constraints — Code Analysis for Finding the Optimal Layout of Cairo Ramen Shop (Part 1)
Introduction This code is implemented in C#. Before starting the code analysis, let's first post the data we'll be using: | Store ID | Store Width | Store Height | Entrance Position | | ------ | -------- | -------- | -------- | | 1 | 9 | 6 | (5, 6) | | 2 | 5 | 6 | (1, 6) | | 3
目录8 个章节
Introduction
This code is implemented in C#. Before starting the code analysis, let's first post the data we'll be using:
| Store ID | Store Width | Store Height | Entrance Position |
|---|---|---|---|
| 1 | 9 | 6 | (5, 6) |
| 2 | 5 | 6 | (1, 6) |
| 3 | 5 | 6 | (1, 6) |
| 4 | 4 | 5 | (1, 5) |
| 5 | 4 | 5 | (1, 5) |
| 6 | 4 | 5 | (1, 5) |
| 7 | 4 | 5 | (1, 5) |
| 8 | 4 | 4 | (1, 4) |
| 9 | 4 | 4 | (1, 4) |
| 10 | 4 | 4 | (1, 4) |
| 11 | 4 | 4 | (1, 4) |
| 12 | 4 | 4 | (1, 4) |
In Cairo Ramen Shop, the positive x-axis points left and the positive y-axis points down. To make our calculations easier, we can rotate the values 180° clockwise into the coordinate system we're familiar with, and then just rotate them back after processing. The entrance position here is relative to the cell at the store's bottom-left corner (that is, the direction closest to the origin). For example:

Relative to the bottom-left cell, this store's entrance is 1 cell to the left and 4 cells up, so the entrance position is (1, 4).
It's easy to calculate that there are a total of
arrangements, and our task is to find the optimal solution among them! Quite a daunting task, isn't it?
Store Class: Store
Properties
In addition to id, width, height, and entrance position, the Store class also needs to record its own position. For convenience, we use the coordinates of the bottom-left cell as the store's position; for ease of calculation, we also store the rectangle obtained by expanding the store by one row and one column.
/// <summary>
/// 拉面店ID
/// </summary>
public int id;
/// <summary>
/// 拉面店左下角坐标
/// </summary>
public Point point;
/// <summary>
/// 拉面店高度
/// </summary>
public int height;
/// <summary>
/// 拉面店宽度
/// </summary>
public int width;
/// <summary>
/// 拉面店门的位置
/// </summary>
public Point door;
/// <summary>
/// 拉面店覆盖区域
/// </summary>
public Rectangle area;
Methods
1. Checking Whether Stores Overlap
This is the method corresponding to constraint 2. When arranging stores with the BL algorithm, we need to check whether the expanded stores overlap; after placing the expanded stores, we also need to check whether the unexpanded stores overlap. Therefore, we need to write multiple member functions to check these separately.
/// <summary>
/// 判断自己与另一个拉面店(扩大后的)是否会重叠
/// </summary>
/// <param name="box">另一个拉面店</param>
/// <returns>若重叠则返回false,不重叠则返回true</returns>
public bool overlap(Store box)
{
if ((point.X + area.Width-1 < box.point.X || point.X > box.point.X + box.area.Width-1) ||
(point.Y + area.Height-1 < box.point.Y || point.Y > box.point.Y + box.area.Height-1))
{
return true;
}
return false;
}
/// <summary>
/// 判断自己与另一个拉面店是否会重叠
/// </summary>
/// <param name="box">另一个拉面店</param>
/// <returns>若重叠则返回false,不重叠则返回true</returns>
public bool overlap_pro(Store box)
{
if ((point.X + width-1 < box.point.X || point.X > box.point.X + box.width-1) ||
(point.Y + height-1 < box.point.Y || point.Y > box.point.Y + box.height-1))
{
return true;
}
return false;
}
/// <summary>
/// 判断本店与其他所有店是否有重叠
/// </summary>
/// <param name="ans">其他所有店</param>
/// <returns>有一个重叠就返回false,全部不重叠返回true</returns>
public bool if_available(List<Store> ans)
{
bool flag = true;
for (int i = 0; i < ans.Count; i++)
{
if (!overlap(ans[i]))
{
flag = false;
break;
}
}
return flag;
}
2. Deep Copy
In C#, custom classes are passed by reference by default when used as parameters, but some later functions need pass-by-value when processing (this will be explained in detail later), so we need to write a deep copy function.
/// <summary>
/// 深复制
/// </summary>
/// <returns>本店深复制后得到的新店</returns>
public Store Clone()
{
Store ans = new Store(id, new Point(point.X, point.Y), width, height, new Point(door.X, door.Y));
return ans;
}
3. Rotation
A member function corresponding to constraint 7.
/// <summary>
/// 旋转
/// </summary>
public void rotate()
{
int t = height;
height = width;
width = t;
door = new Point(door.Y, door.X);
area = new Rectangle(new Point(0, 0), new Size(width + 1, height + 1));
}
4. The BL Algorithm and Its Improvement
The first step in implementing the BL algorithm is to place the store at the top-right boundary, so we need to check whether that top-right boundary position can fit the store and whether it would overlap with other stores. If it can be placed, we can start playing “Tetris.” For the BL algorithm, the store needs to determine how many cells it can move down and how many cells it can move left; for the improved BL algorithm, moving down and moving left can be combined into a single action.
/// <summary>
/// 判断本店能否在当前位置填充
/// </summary>
/// <param name="W">当前位置横坐标</param>
/// <param name="H">当前位置纵坐标</param>
/// <param name="ans">已填充的拉面店</param>
/// <returns>可以填充返回true,不能填充返回false</returns>
public bool set(int W, int H, List<Store> ans)
{
point.X = W - area.Width;
point.Y = H - area.Height;
return if_available(ans);
}
/// <summary>
/// 向下移动
/// </summary>
/// <param name="store">当前已填充的拉面店</param>
/// <returns>可以移动的最大步数</returns>
public int go_down(List<Store> store)
{
int move = 0;
for (int i = 0; i < store.Count; i++)
{
if (area.Width + point.X > store[i].point.X && point.X < store[i].area.Width + store[i].point.X &&
point.Y >= store[i].point.Y + store[i].area.Height)
{
int l = store[i].point.Y + store[i].area.Height;
if (move < l)
{
move = l;
}
}
}
move = point.Y - move;
point.Y -= move;
return move;
}
/// <summary>
/// 向左移动
/// </summary>
/// <param name="store">当前已填充的拉面店</param>
/// <returns>可以移动的最大步数</returns>
public int go_left(List<Store> store)
{
int move = 0;
for (int i = 0; i < store.Count; i++)
{
if (area.Height + point.Y > store[i].point.Y && point.Y < store[i].area.Height + store[i].point.Y &&
point.X >= store[i].point.X + store[i].area.Width)
{
int l = store[i].point.X + store[i].area.Width;
if (move < l)
{
move = l;
}
}
}
move = point.X - move;
point.X -= move;
return move;
}
/// <summary>
/// BL算法加强版
/// </summary>
/// <param name="store">当前已填充的拉面店</param>
/// <returns>可以移动的最大步数</returns>
public Point BL_plus_move(List<Store> store)
{
int down = 0;
int left = 0;
for (int i = 0; i < store.Count; i++)
{
if (point.X + area.Width > store[i].point.X && point.X < store[i].point.X + store[i].area.Width &&
point.Y >= store[i].point.Y + store[i].area.Height)
{
int l = store[i].point.Y + store[i].area.Height;
if (down < l)
{
down = l;
left = store[i].point.X;
}
}
}
down = point.Y - down;
point.Y -= down;
int move = 0;
for (int i = 0; i < store.Count; i++)
{
if (point.Y + area.Height > store[i].point.Y && point.Y < store[i].point.Y + store[i].area.Height &&
point.X >= store[i].point.X + store[i].area.Width)
{
int l = store[i].point.X + store[i].area.Width;
if (move < l)
{
move = l;
}
}
}
left = Math.Min(point.X + area.Width - left, point.X - move);
point.X -= left;
return new Point(down, left);
}
At this point, a simple Store class is basically implemented. Next comes the implementation of the Individual class.
_EOF_
Two-Dimensional Bin Packing Under Multiple Constraints — Code Analysis for Finding the Optimal Layout of Cairo Ramen Shop (Part 1)
- 本文作者:
- 程序设计实验室
- 版权声明:
- 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
相关文章
LittleWhiteOne基本设计
LittleWhite One 魔改chatterbot框架实现的新版小白~ 简介 core:核心框架,魔改版chatterbot corpus:英文和中文训练语料 nltk_data:需要用到的nltk数据集 文本相似度算法 LevenshteinDistance SpacySimilarity JaccardSimilarity Levenshtein Distance算法 中文名:莱文斯坦距
2021-12-18 · 算法/机器学习 · 约 1 分钟
推荐系统开发实践:Surprise库基本用法
首先是构建数据集 这里我使用了随机生成用户和项目,以及用户对项目的评价,喜欢(1)与不喜欢(0) import random import pandas import numpy as np def build_dataframe() - pandas.DataFrame: datasets = { 'userID': [], 'itemID': [],
2021-12-18 · 算法/机器学习 · 约 1 分钟
多个约束条件下的二维装箱问题——寻找《开罗拉面店》最优布局之代码解析(三)
种群类:Population 属性 种群类首先要储存的便是上一篇中提到的原始基因;其次为了应用精英保存策略、择伏分配等,需要记录最优个体的相关信息;同时在计算交叉变异概率的时候,需要用到求平均适应值的方法,所以为了简化计算,储存每个个体的适应值是很有必要的。 /// summary /// 个体列表 /// /summary public ListIndividual ind; /// summ
2021-12-18 · 算法/机器学习 · 约 1 分钟
多个约束条件下的二维装箱问题——寻找《开罗拉面店》最优布局之代码解析(二)
个体类:Individual 属性 一个个体在遗传算法中最关键的属性是基因编码和性状,为此还需要引出一个原始基因的定义(在敲代码的时候我把这玩意儿叫做基因库,但是后来查资料才发现,基因库是用来储存优秀个体,提高种群质量的,和我这里的作用并不相同,所以作出修正)。原始基因就是题目给定的这12个店铺,而在生成个体的基因的时候就只是单纯的在这条原始基因上进行随机重排序操作和随机旋转操作;性状则是进行这两
2021-12-18 · 算法/机器学习 · 约 1 分钟
讨论
共 0 条加载评论中…