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> sonTreeMap = new Dictionary>(); private Dictionary tabuTreeMap = new Dictionary(); public List initGhh;//初始顺序 public List bestGh;//最佳顺序 public List LocalGh;//当前最好顺序 public List 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 squareList) { Solution solution = new Solution(); solution.instance = instance; solution.squareList = squareList.ToList(); List placeSquareList = new List(); // 创建初始可放置角点 List placePointList = new List(); 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 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 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 squareList) { if (tabuTreeMap == null) { tabuTreeMap = new Dictionary(); } 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 generateNewGh(List localGh, List 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 generateNewGh1(List localGh, List 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 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); } } }