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#

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);
}
}
}