You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
492 lines
20 KiB
C#
492 lines
20 KiB
C#
|
|
using log4net;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using SOA.Persistent;
|
|
using SlabHandle;
|
|
namespace MES.Interface
|
|
{
|
|
public class Search
|
|
{
|
|
public int MAX_GEN = 20;//最大的迭代次数(提高这个值可以稳定地提高解质量,但是会增加求解时间)
|
|
public int N = 20;//每次搜索领域的个数(这个值不要太大,太大的话搜索效率会降低)
|
|
|
|
//public int sqNum;//矩形数量
|
|
//Dictionary<String, List<Square>> sonTreeMap = new Dictionary<String, List<Square>>();
|
|
private Dictionary<String, TabuMapTree> tabuTreeMap = new Dictionary<String, TabuMapTree>();
|
|
|
|
public List<BP_ORDER_ITEM> initGhh;//初始顺序
|
|
public List<BP_ORDER_ITEM> bestGh;//最佳顺序
|
|
public List<BP_ORDER_ITEM> LocalGh;//当前最好顺序
|
|
public List<BP_ORDER_ITEM> tempGh;//存放临时顺序
|
|
public int bestT;//最佳的迭代次数
|
|
public Solution bestSolution;//最优解
|
|
public Solution LocalSolution;//每次领域搜索的最优解(领域最优解)
|
|
public Solution tempSolution;//临时解
|
|
public int t;//当前迭代
|
|
public Random random;//随机函数对象
|
|
|
|
// 问题实例
|
|
public Instance instance;
|
|
|
|
private double L, W;
|
|
private static readonly ILog logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
|
|
|
//private static readonly int Jan1st1970 = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
|
|
|
|
public Search(Instance instance)
|
|
{
|
|
this.instance = instance;
|
|
this.initGhh = instance.squareList;
|
|
L = instance.l;
|
|
W = instance.w;
|
|
//sqNum = initGhh.Count();
|
|
}
|
|
|
|
public Solution search()
|
|
{
|
|
// long start = (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
|
|
// 获取初始解
|
|
getInitSolution();
|
|
if (initGhh.Count <= 20)
|
|
{
|
|
MAX_GEN = 15; N = 15;
|
|
}
|
|
if (initGhh.Count <= 10)
|
|
{
|
|
MAX_GEN = 10; N = 10;
|
|
}
|
|
else if (initGhh.Count <= 5)
|
|
{
|
|
MAX_GEN = 5; N = 5;
|
|
}
|
|
while (t <= MAX_GEN)
|
|
{
|
|
//当前领域搜索次数
|
|
int n = 0;
|
|
LocalSolution = new Solution();
|
|
LocalSolution.rate = 0;
|
|
while (n <= N)
|
|
{
|
|
// 打乱顺序
|
|
tempGh = generateNewGh(initGhh, tempGh);
|
|
// 判断其是否在禁忌表中
|
|
if (!judge(tempGh))
|
|
{
|
|
// 如果不在
|
|
// 加入禁忌表
|
|
enterTabooList(tempGh);
|
|
tempSolution = evaluate(tempGh);
|
|
if (tempSolution.rate > LocalSolution.rate)
|
|
{
|
|
// 如果临时解优于本次领域搜索的最优解
|
|
// 那么就将临时解替换本次领域搜索的最优解
|
|
LocalGh = tempGh;
|
|
LocalSolution = tempSolution;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//throw new Exception("重复");
|
|
}
|
|
n++;
|
|
}
|
|
if (LocalSolution.rate >= bestSolution.rate)
|
|
{
|
|
//如果本次搜索的最优解优于全局最优解
|
|
//那么领域最优解替换全局最优解
|
|
bestT = t;
|
|
bestGh = LocalGh;
|
|
bestSolution = LocalSolution;
|
|
}
|
|
initGhh = LocalGh;
|
|
t++;
|
|
}
|
|
logger.InfoFormat("*组合匹配*---匹配订单数【{0}】==>>匹配到的订单数【{1}】==>>钢板号【{2}】==>>利用率【{3}】", bestSolution.squareList.Count, bestSolution.placeSquareList.Count, bestSolution.instance.plate_no, bestSolution.rate);
|
|
//Solution solution = new Solution();
|
|
return bestSolution;
|
|
}
|
|
|
|
public Solution search1()
|
|
{
|
|
// long start = (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
|
|
// 获取初始解
|
|
getInitSolution1();
|
|
|
|
for (int i = 0; i < initGhh.Count; i++)
|
|
{
|
|
//当前领域搜索次数
|
|
//int n = 0;
|
|
LocalSolution = new Solution();
|
|
LocalSolution.rate = 0;
|
|
|
|
// 打乱顺序
|
|
tempGh = generateNewGh1(initGhh, tempGh);
|
|
|
|
tempSolution = evaluate(tempGh);
|
|
//if (tempSolution.rate > LocalSolution.rate)
|
|
//{
|
|
// // 如果临时解优于本次领域搜索的最优解
|
|
// // 那么就将临时解替换本次领域搜索的最优解
|
|
// LocalGh = tempGh;
|
|
// LocalSolution = tempSolution;
|
|
|
|
//}
|
|
|
|
if (tempSolution.rate > bestSolution.rate)
|
|
{
|
|
//如果本次搜索的最优解优于全局最优解
|
|
//那么领域最优解替换全局最优解
|
|
//bestT = t;
|
|
bestGh = tempGh;
|
|
bestSolution = tempSolution;
|
|
}
|
|
//initGhh = LocalGh;
|
|
//t++;
|
|
}
|
|
logger.InfoFormat("*组合匹配*---匹配订单数【{0}】==>>匹配到的订单数【{1}】==>>钢板号【{2}】==>>利用率【{3}】", bestSolution.squareList.Count, bestSolution.placeSquareList.Count, bestSolution.instance.plate_no, bestSolution.rate);
|
|
//Solution solution = new Solution();
|
|
return bestSolution;
|
|
}
|
|
|
|
//评价函数
|
|
public Solution evaluate(List<BP_ORDER_ITEM> squareList)
|
|
{
|
|
Solution solution = new Solution();
|
|
solution.instance = instance;
|
|
solution.squareList = squareList.ToList();
|
|
List<PlaceSquare> placeSquareList = new List<PlaceSquare>();
|
|
// 创建初始可放置角点
|
|
List<PlacePoint> placePointList = new List<PlacePoint>();
|
|
placePointList.Add(new PlacePoint(0, 0));
|
|
// 开始按照顺序和规则放置
|
|
for (int i = 0; i < squareList.Count; i++)
|
|
{
|
|
PlacePoint placePoint = null;
|
|
bool b = false;
|
|
BP_ORDER_ITEM square = squareList[i];
|
|
for (int j = 0; j < placePointList.Count; j++)
|
|
{
|
|
placePoint = placePointList[j];
|
|
//PlaceSquare placeSquare = new PlaceSquare(placePoint.x, placePoint.y, square.ORD_LEN, square.ORD_WID);
|
|
PlaceSquare placeSquare = new PlaceSquare();
|
|
placeSquare.x = placePoint.x;
|
|
placeSquare.y = placePoint.y;
|
|
placeSquare.l = Convert.ToDouble(square.ORD_LEN);
|
|
placeSquare.w = Convert.ToDouble(square.ORD_WID);
|
|
placeSquare.Ord_no = square.ORD_NO;
|
|
placeSquare.ORD_ITEM = square.ORD_ITEM;
|
|
placeSquare.BOI = square;
|
|
//placeSquareList.Add(placeSquare);
|
|
if (!isOverlap(placeSquareList, placeSquare))
|
|
{
|
|
b = true;
|
|
// 移除当前角点
|
|
placePointList.RemoveAt(j);
|
|
//新增已放置的square
|
|
placeSquare = new PlaceSquare();
|
|
placeSquare.x = placePoint.x;
|
|
placeSquare.y = placePoint.y;
|
|
placeSquare.l = Convert.ToDouble(square.ORD_LEN);
|
|
placeSquare.w = Convert.ToDouble(square.ORD_WID);
|
|
placeSquare.Ord_no = square.ORD_NO;
|
|
placeSquare.ORD_ITEM = square.ORD_ITEM;
|
|
placeSquare.BOI = square;
|
|
placeSquareList.Add(placeSquare);
|
|
// 新增两个可行角点
|
|
//placePointList.Add(new PlacePoint(placePoint.getX(), placePoint.getY(), square.getL(), square.getW()));
|
|
placePointList.Add(new PlacePoint(placePoint.x + Convert.ToDouble(square.ORD_LEN), placePoint.y));
|
|
placePointList.Add(new PlacePoint(placePoint.x, placePoint.y + Convert.ToDouble(square.ORD_WID)));
|
|
// 重新排序
|
|
placePointList = placePointList.OrderBy(p => Guid.NewGuid().ToString()).ToList();
|
|
// 跳出内层循环
|
|
j = placePointList.Count;
|
|
}
|
|
}
|
|
if (!b && instance.isRotateEnable)
|
|
{
|
|
double l = Convert.ToDouble(square.ORD_LEN);
|
|
double w = Convert.ToDouble(square.ORD_WID);
|
|
square.ORD_LEN = (decimal)w;
|
|
square.ORD_WID = (decimal)l;
|
|
for (int j = 0; j < placePointList.Count; j++)
|
|
{
|
|
placePoint = placePointList[j];
|
|
PlaceSquare placeSquare = new PlaceSquare();
|
|
placeSquare.x = placePoint.x;
|
|
placeSquare.y = placePoint.y;
|
|
placeSquare.l = Convert.ToDouble(square.ORD_LEN);
|
|
placeSquare.w = Convert.ToDouble(square.ORD_WID);
|
|
placeSquare.Ord_no = square.ORD_NO;
|
|
placeSquare.ORD_ITEM = square.ORD_ITEM;
|
|
placeSquare.BOI = square;
|
|
if (!isOverlap(placeSquareList, placeSquare))
|
|
{
|
|
b = true;
|
|
// 移除当前角点
|
|
placePointList.RemoveAt(j);
|
|
//新增已放置的square
|
|
placeSquare = new PlaceSquare();
|
|
placeSquare.x = placePoint.x;
|
|
placeSquare.y = placePoint.y;
|
|
placeSquare.l = Convert.ToDouble(square.ORD_LEN);
|
|
placeSquare.w = Convert.ToDouble(square.ORD_WID);
|
|
placeSquare.Ord_no = square.ORD_NO;
|
|
placeSquare.ORD_ITEM = square.ORD_ITEM;
|
|
placeSquare.BOI = square;
|
|
placeSquareList.Add(placeSquare);
|
|
// 新增两个可行角点
|
|
|
|
placePointList.Add(new PlacePoint(placePoint.x + Convert.ToDouble(square.ORD_LEN), placePoint.y));
|
|
placePointList.Add(new PlacePoint(placePoint.x, placePoint.y + Convert.ToDouble(square.ORD_WID)));
|
|
// 重新排序
|
|
placePointList = placePointList.OrderBy(p => Guid.NewGuid().ToString()).ToList();
|
|
// 跳出内层循环
|
|
j = placePointList.Count;
|
|
}
|
|
}
|
|
square.ORD_LEN = (decimal)l;
|
|
square.ORD_WID = (decimal)w;
|
|
}
|
|
}
|
|
// 设置已经放置的矩形列表
|
|
solution.placeSquareList = placeSquareList;
|
|
// 计算利用率
|
|
double rate = 0.0f;
|
|
double s = 0.0f;
|
|
foreach (PlaceSquare placeSquare in placeSquareList)
|
|
{
|
|
s += (placeSquare.l * placeSquare.w);
|
|
}
|
|
rate = s / (L * W);
|
|
solution.rate = rate;
|
|
|
|
return solution;
|
|
}
|
|
|
|
//评价函数(弃用了)
|
|
private double[] getMarks(PlacePoint placePoint, BP_ORDER_ITEM square, List<PlaceSquare> placeSquareList)
|
|
{
|
|
// 返回{是否旋转,分数}
|
|
double delta = 0, mark1 = -1d, mark2 = -1d;
|
|
PlaceSquare placeSquare = new PlaceSquare();
|
|
//placePoint.getX(), placePoint.getY(), square.getL(), square.getW()
|
|
placeSquare.x = placePoint.x;
|
|
placeSquare.y = placePoint.y;
|
|
placeSquare.l = Convert.ToDouble(square.ORD_LEN);
|
|
placeSquare.w = Convert.ToDouble(square.ORD_WID);
|
|
placeSquareList.Add(placeSquare);
|
|
if (isOverlap(placeSquareList, placeSquare))
|
|
{
|
|
mark1 = -1.0d;
|
|
}
|
|
else
|
|
{
|
|
delta = Math.Abs(placePoint.len - Convert.ToDouble(square.ORD_LEN));
|
|
mark1 = 1 - delta / placePoint.len;
|
|
}
|
|
mark2 = -1.0d;
|
|
if (instance.isRotateEnable)
|
|
{
|
|
//placeSquare = new PlaceSquare(placePoint.getX(), placePoint.getY(), square.getW(), square.getL());
|
|
placeSquare = new PlaceSquare();
|
|
placeSquare.x = placePoint.x;
|
|
placeSquare.y = placePoint.y;
|
|
placeSquare.l = Convert.ToDouble(square.ORD_WID);
|
|
placeSquare.w = Convert.ToDouble(square.ORD_LEN);
|
|
placeSquareList.Add(placeSquare);
|
|
if (!isOverlap(placeSquareList, placeSquare))
|
|
{
|
|
delta = Math.Abs(placePoint.len - Convert.ToDouble(square.ORD_WID));
|
|
mark2 = 1 - delta / placePoint.len;
|
|
}
|
|
}
|
|
if (mark1 >= mark2)
|
|
{
|
|
return new double[] { -1d, (int)(mark1 * 10) };
|
|
}
|
|
return new double[] { 1d, (int)(mark2 * 10) };
|
|
}
|
|
|
|
// 判断放置在该位置是否超出边界或者和其他矩形重叠
|
|
public bool isOverlap(List<PlaceSquare> placeSquareList, PlaceSquare tempPlaceSquare)
|
|
{
|
|
// 出界
|
|
if (tempPlaceSquare.l > L || tempPlaceSquare.w > W)
|
|
{
|
|
return true;
|
|
}
|
|
// 出界
|
|
if (tempPlaceSquare.x + tempPlaceSquare.l > L || tempPlaceSquare.y + tempPlaceSquare.w > W)
|
|
{
|
|
return true;
|
|
}
|
|
//PlaceSquare placeSquare2 = placeSquareList.Where(p => p.x > tempPlaceSquare.x).OrderByDescending(p => p.y + p.w).FirstOrDefault();
|
|
//if (placeSquare2 != null)
|
|
//{
|
|
// if (tempPlaceSquare.y + tempPlaceSquare.w < placeSquare2.y + placeSquare2.w)
|
|
// {
|
|
// return true;
|
|
// }
|
|
//}
|
|
//PlaceSquare placeSquare3 = placeSquareList.Where(p => p.x <= tempPlaceSquare.x).OrderByDescending(p => p.y + p.w).FirstOrDefault();
|
|
//if (placeSquare3 != null)
|
|
//{
|
|
// if (tempPlaceSquare.y + tempPlaceSquare.w > placeSquare3.y + placeSquare3.w)
|
|
// {
|
|
// return true;
|
|
// }
|
|
//}
|
|
|
|
foreach (PlaceSquare placeSquare in placeSquareList)
|
|
{
|
|
// 角点重合
|
|
if (placeSquare.x == tempPlaceSquare.x && placeSquare.y == tempPlaceSquare.y)
|
|
{
|
|
placeSquareList.Remove(placeSquare);
|
|
return true;
|
|
}
|
|
// 判断即将要放置的块是否与之前放置的块有重叠
|
|
if (isOverlap2(placeSquare, tempPlaceSquare))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// 判断即将要放置的块是否与之前放置的块有重叠
|
|
public bool isOverlap2(PlaceSquare placeSquare, PlaceSquare tempPlaceSquare)
|
|
{
|
|
double x1 = Math.Max(placeSquare.x, tempPlaceSquare.x);
|
|
double y1 = Math.Max(placeSquare.y, tempPlaceSquare.y);
|
|
double x2 = Math.Min(placeSquare.x + placeSquare.l, tempPlaceSquare.x + tempPlaceSquare.l);
|
|
double y2 = Math.Min(placeSquare.y + placeSquare.w, tempPlaceSquare.y + tempPlaceSquare.w);
|
|
if (x1 >= x2 || y1 >= y2)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// 生成初始解
|
|
public void getInitSolution()
|
|
{
|
|
//initGhh = initGhh.OrderBy(p => Guid.NewGuid().ToString()).ToList();
|
|
initGhh = initGhh.OrderByDescending(p => p.ORD_WID).ToList();
|
|
bestSolution = evaluate(initGhh);
|
|
tempSolution = bestSolution;
|
|
bestGh = initGhh;
|
|
tempGh = initGhh;
|
|
LocalGh = initGhh;
|
|
}
|
|
|
|
public void getInitSolution1()
|
|
{
|
|
//initGhh = initGhh.OrderBy(p => Guid.NewGuid().ToString()).ToList();
|
|
initGhh = initGhh.OrderByDescending(p=>p.ORD_WID).ToList();
|
|
bestSolution = evaluate(initGhh);
|
|
tempSolution = bestSolution;
|
|
bestGh = initGhh;
|
|
tempGh = initGhh;
|
|
LocalGh = initGhh;
|
|
}
|
|
|
|
//加入禁忌队列
|
|
public void enterTabooList(IList<BP_ORDER_ITEM> squareList)
|
|
{
|
|
if (tabuTreeMap == null)
|
|
{
|
|
tabuTreeMap = new Dictionary<string, TabuMapTree>();
|
|
}
|
|
BP_ORDER_ITEM square = squareList[0];
|
|
String id = square.ORD_NO + square.ORD_ITEM;
|
|
if (tabuTreeMap.Keys.Contains(id))
|
|
{
|
|
tabuTreeMap[id].add((squareList), 1);
|
|
}
|
|
else
|
|
{
|
|
TabuMapTree tabuMapTree = new TabuMapTree();
|
|
tabuMapTree.nodeSquare = square;
|
|
tabuMapTree.add((squareList), 1);
|
|
tabuTreeMap.Add(id, tabuMapTree);
|
|
}
|
|
}
|
|
|
|
public List<BP_ORDER_ITEM> generateNewGh(List<BP_ORDER_ITEM> localGh, List<BP_ORDER_ITEM> tempGh)
|
|
{
|
|
//BP_ORDER_ITEM temp1 = new BP_ORDER_ITEM();
|
|
//BP_ORDER_ITEM temp2 = new BP_ORDER_ITEM();
|
|
////将Gh复制到tempGh
|
|
//tempGh = localGh;
|
|
|
|
//for (int i = 0; i < localGh.Count; i++)
|
|
//{
|
|
// r1 = i;
|
|
// r2 = i+1;
|
|
|
|
//
|
|
// //交换
|
|
// temp1 = tempGh[r1];
|
|
// temp2 = tempGh[r2];
|
|
// tempGh[r1] = temp2;
|
|
// tempGh[r2] = temp1;
|
|
|
|
//}
|
|
//initGhh = tempGh;
|
|
//return tempGh;
|
|
tempGh = localGh;
|
|
tempGh = tempGh.OrderBy(p => Guid.NewGuid().ToString()).ToList();
|
|
return tempGh;
|
|
}
|
|
|
|
public List<BP_ORDER_ITEM> generateNewGh1(List<BP_ORDER_ITEM> localGh, List<BP_ORDER_ITEM> tempGh)
|
|
{
|
|
BP_ORDER_ITEM temp1 = new BP_ORDER_ITEM();
|
|
BP_ORDER_ITEM temp2 = new BP_ORDER_ITEM();
|
|
//将Gh复制到tempGh
|
|
tempGh = localGh;
|
|
|
|
for (int i = 0; i < localGh.Count - 1; i++)
|
|
{
|
|
int r1 = i;
|
|
int r2 = i + 1;
|
|
|
|
//交换
|
|
temp1 = tempGh[r1];
|
|
temp2 = tempGh[r2];
|
|
tempGh[r1] = temp2;
|
|
tempGh[r2] = temp1;
|
|
}
|
|
initGhh = tempGh;
|
|
return tempGh;
|
|
//tempGh = localGh;
|
|
//tempGh = tempGh.OrderBy(p => Guid.NewGuid().ToString()).ToList();
|
|
//return tempGh;
|
|
}
|
|
|
|
//判断路径编码是否存在于禁忌表中
|
|
public bool judge(IList<BP_ORDER_ITEM> Gh)
|
|
{
|
|
BP_ORDER_ITEM square = Gh[0];
|
|
string id = square.ORD_NO + square.ORD_ITEM;
|
|
if (tabuTreeMap.Keys.Contains(id))
|
|
{
|
|
return tabuTreeMap[id].contains(Gh, 1);
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// 判断两个Squre是否相等
|
|
public bool isEq(Square square1, Square square2)
|
|
{
|
|
return square1.id.Equals(square2.id);
|
|
}
|
|
}
|
|
} |