// gets the best position for the rect on the board // the rect given to this method does not have to be initialized on 0/0 public void GetValidPositions(List<Rect> rectList, Rect rect, Boolean evolution) { // position = position of rect 0/0 Position position = new Position(); position.edgeLeftUp.x = 0; position.edgeLeftUp.y = rect.height; position.edgeRightDown.x = rect.width; position.edgeRightDown.y = 0; // largest part of this method, recursive ManagePosition(rectList, rect, position, evolution); }
// returns the position numbers of the rects in RectListBoard where collisions where detected // RectListBoard = list of the board where the collision is searched (and where the rect should be placed) // rect = the rect to be placed public List<int> GetCollisions(List<Rect> rectListBoard, Rect rect) { List<int> collisionList = new List<int>(); // coordinates of the existing rect float x1; float x2; float y1; float y2; // coordinates of the new rect float u1; float u2; float v1; float v2; for(int i = 0; i < rectListBoard.Count; i++) { x1 = rectListBoard[i].edgeLeftUp.x; x2 = rectListBoard[i].edgeRightDown.x; y1 = rectListBoard[i].edgeRightDown.y; y2 = rectListBoard[i].edgeLeftUp.y; u1 = rect.edgeLeftUp.x; u2 = rect.edgeRightDown.x; v1 = rect.edgeRightDown.y; v2 = rect.edgeLeftUp.y; // collision detection if(( (u1 < x1 && x1 < u2) || (u1 < x2 && x2 < u2) || (x1 < u1 && u1 < x2) || (x1 < u2 && u2 < x2) || (x1 == u1 && x2 == u2)) && ( (v1 < y1 && y1 < v2) || (v1 < y2 && y2 < v2) || (y1 < v1 && v1 < y2) || (y1 < v2 && v2 < y2) || (y1 == v1 && y2 == v2)) ) { collisionList.Add(i); } } return collisionList; }
public void CreateRects(int minRects, int maxRects, Benchmark benchmark) { int rectID = 1; Random random = new Random(); for (int i = 0; i < benchmark.boardList.Count; i++) { int numberOfRequiredRects = random.Next(minRects, maxRects + 1); // "convert" the board to a rect, meaning adding a rect to the board with the size of the board Rect rect = new Rect(); rect.height = benchmark.boardList[i].height; rect.width = benchmark.boardList[i].width; rect.size = rect.height * rect.width; rect.edgeLeftUp = new MyPoint(0, rect.height); rect.edgeRightDown = new MyPoint(rect.width, 0); benchmark.boardList[i].RectList.Add(rect); // split the largest rect of the rectList until number of rects = required number of rects for (int j = 1; j < numberOfRequiredRects; j++) { Rect largestRect = new Rect(); Rect rectOne = new Rect(); Rect rectTwo = new Rect(); Boolean nullCoordsOccured = true; while(nullCoordsOccured == true) { // 1. find largest rect largestRect = benchmark.boardList[i].RectList[0]; for (int k = 0; k < benchmark.boardList[i].RectList.Count; k++) { if (benchmark.boardList[i].RectList[k].size > largestRect.size) { largestRect = benchmark.boardList[i].RectList[k]; } } // 2. decide if to split horizontal or vertical Boolean splitVertical; if (random.Next(0, 2) == 0) { splitVertical = false; } else { splitVertical = true; } // 3. create two new rects out of the largest one and add them to the rect list rectOne = new Rect(); rectTwo = new Rect(); if (splitVertical) { double largestRectWidthDouble = Convert.ToDouble(largestRect.width); // new width between 10% and 90% of largestRect's width // several conversions have to be done to use Ceiling and random for integer int newWidth = Convert.ToInt32(Math.Ceiling(largestRectWidthDouble * (Convert.ToDouble(random.Next(1, 10)) / 10))); if (newWidth == largestRect.width) { // this would not create 2 new rects. retry nullCoordsOccured = true; } else { rectOne.height = largestRect.height; rectTwo.height = largestRect.height; rectOne.width = newWidth; rectTwo.width = largestRect.width - newWidth; rectOne.edgeLeftUp = largestRect.edgeLeftUp; rectOne.edgeRightDown = new MyPoint(largestRect.edgeLeftUp.x + rectOne.width, largestRect.edgeRightDown.y); rectTwo.edgeLeftUp = new MyPoint(rectOne.edgeRightDown.x, rectOne.edgeLeftUp.y); rectTwo.edgeRightDown = largestRect.edgeRightDown; nullCoordsOccured = false; } } // if split horizontal else { double largestRectHeightDouble = Convert.ToDouble(largestRect.height); // new height between 10% and 90% of largestRect's height // several conversions have to be done to use Ceiling and random for integer int newHeight = Convert.ToInt32(Math.Ceiling(largestRectHeightDouble * (Convert.ToDouble(random.Next(1, 10)) / 10))); if (newHeight == largestRect.height) { // this would not create 2 new rects. retry nullCoordsOccured = true; } else { rectOne.height = newHeight; rectTwo.height = largestRect.height - newHeight; rectOne.width = largestRect.width; rectTwo.width = largestRect.width; rectOne.edgeLeftUp = largestRect.edgeLeftUp; rectOne.edgeRightDown = new MyPoint(largestRect.edgeRightDown.x, largestRect.edgeLeftUp.y - rectOne.height); rectTwo.edgeLeftUp = new MyPoint(rectOne.edgeLeftUp.x, rectOne.edgeRightDown.y); rectTwo.edgeRightDown = largestRect.edgeRightDown; nullCoordsOccured = false; } } } // add rect data rectOne.size = rectOne.height * rectOne.width; rectTwo.size = rectTwo.height * rectTwo.width; // add rects to list benchmark.boardList[i].RectList.Add(rectOne); benchmark.boardList[i].RectList.Add(rectTwo); // 4. remove the largest rect from the rect list benchmark.boardList[i].RectList.Remove(largestRect); } // add rectIDs for (int j = 0; j < benchmark.boardList[i].RectList.Count; j++) { benchmark.boardList[i].RectList[j].rectID = rectID; rectID++; } // add number of rects and number of boards benchmark.numberOfRects = 0; for(int l = 0; l < benchmark.boardList.Count; l++) { benchmark.numberOfRects += benchmark.boardList[i].RectList.Count; } benchmark.numberOfBoards = benchmark.boardList.Count; } // for testing: //1. size test String success = "success"; for (int i = 0; i < benchmark.boardList.Count; i++) { int size = benchmark.boardList[i].size; for (int j = 0; j < benchmark.boardList[i].RectList.Count; j++) { size -= benchmark.boardList[i].RectList[j].size; } if (size != 0) { success = "fail"; } } // 2. > 236 test for (int i = 0; i < benchmark.boardList.Count; i++) { for (int j = 0; j < benchmark.boardList[i].RectList.Count; j++) { /* if (benchmark.boardList[i].RectList[j].edgeLeftUp.y > 236) { int s = 1; } */ } } }
// creates a basic solution without rects placed, according to the benchmark public void CreateBasicSolution(Base global, Benchmark benchmark) { Solution solution = new Solution(); // set solution ID string path = Environment.CurrentDirectory; // without bin\Debug path = path.Substring(0, path.Length - 9) + "Resources\\SolutionNr.txt"; solution.SolutionID = Convert.ToInt32(System.IO.File.ReadAllText(path)); // set creationTime solution.creationTime = DateTime.Now; // set Benchmark to solution solution.benchmark = benchmark; solution.usedBenchmarkID = benchmark.benchmarkID; // add boards solution.BoardList = new List<Board>(); for (int i = 0; i < benchmark.boardList.Count; i++) { Board board = new Board(); board.boardID = i + 1; board.height = benchmark.boardList[0].height; board.width = benchmark.boardList[0].width; board.isCollectionBoard = false; board.size = board.height * board.width; solution.BoardList.Add(board); } // add collection board Board collectionBoard = new Board(); collectionBoard.boardID = solution.BoardList.Count + 1; collectionBoard.height = benchmark.boardList[0].height; collectionBoard.width = benchmark.boardList[0].width * 2; collectionBoard.isCollectionBoard = true; collectionBoard.size = collectionBoard.height * collectionBoard.width; solution.BoardList.Add(collectionBoard); // add rects to collection board, sorted from largest to smallest and height > width (change these parameters if necessary) // also remove the coordinates from the rects for(int i = 0; i < benchmark.boardList.Count; i++) { for(int j = 0; j < benchmark.boardList[i].RectList.Count; j++) { Rect rect = new Rect(); rect.rectID = benchmark.boardList[i].RectList[j].rectID; rect.size = benchmark.boardList[i].RectList[j].size; if(benchmark.boardList[i].RectList[j].height < benchmark.boardList[i].RectList[j].width) { rect.height = benchmark.boardList[i].RectList[j].width; rect.width = benchmark.boardList[i].RectList[j].height; } else { rect.height = benchmark.boardList[i].RectList[j].height; rect.width = benchmark.boardList[i].RectList[j].width; } rect.edgeLeftUp = new MyPoint(0,0); rect.edgeRightDown = new MyPoint(0,0); collectionBoard.RectList.Add(rect); } } // sort the rects in rect list from largest size to smallest size (new version; old version below) Tools tools = new Tools(); tools.QuickSortRectBySizeDec(0, collectionBoard.RectList.Count - 1, collectionBoard.RectList); // old version, new version = using quicksort /* // sort the rect list List<Rect> rectList = new List<Rect>(); // as long as rects exist while (collectionBoard.RectList.Count > 0) { // search the largest rect (by size), then add to rectList and remove from collectionBoard List Rect largestRect = collectionBoard.RectList[0]; for (int i = 1; i < collectionBoard.RectList.Count; i++) { if(collectionBoard.RectList[i].size > largestRect.size) { largestRect = collectionBoard.RectList[i]; } } rectList.Add(largestRect); collectionBoard.RectList.Remove(largestRect); } collectionBoard.RectList = rectList; */ // add the remaining parameters to solution solution.numberOfRects = collectionBoard.RectList.Count; solution.percentageFilledArea = 0; global.solution = solution; global.emptySolution = tools.CloneSolution(solution); // cl values ClassificationNumbers clNumbers = new ClassificationNumbers(global); clNumbers.GetAndShowAllClassificationNumbers(); }
public Solution Greedy(Boolean evolution, Solution solutionEvo) { Base global = Base.GetInstance(); Solution solution; if(evolution) { solution = solutionEvo; } else { solution = global.solution; } ClassificationNumbers classificationNumbers = new ClassificationNumbers(global); // preparations if(!evolution) { global.runningProcess.state = 1; } Tools tools = new Tools(); // START one time: if (evolution || global.runningProcess.firstStep) { // next rect to pick of the list: the first one (default) if(!evolution) { global.runningProcess.nextStep = 0; } else { global.nextStepGreedyEvo = 0; } global.positionsManaged = new List<Position>(); global.positionsValid = new List<Position>(); if((global.Verschnittoptimierung.radioButton_largestSideInc.Checked && !evolution) || (evolution && global.selectedGreedy == 1) || (evolution && global.selectedGreedy == 2) || (evolution && global.selectedGreedy == 9) || (evolution && global.selectedGreedy == 10) ) { // sort rects from min largest side to max largest side tools.QuickSortRectByLargestSizeInc(0, solution.BoardList[solution.BoardList.Count - 1].RectList.Count - 1, solution.BoardList[solution.BoardList.Count - 1].RectList); } else if((global.Verschnittoptimierung.radioButton_largestSideDec.Checked && !evolution) || (evolution && global.selectedGreedy == 3) || (evolution && global.selectedGreedy == 4) || (evolution && global.selectedGreedy == 11) || (evolution && global.selectedGreedy == 12) ) { // sort rects from min largest side to max largest side tools.QuickSortRectByLargestSideDec(0, solution.BoardList[solution.BoardList.Count - 1].RectList.Count - 1, solution.BoardList[solution.BoardList.Count - 1].RectList); } else if((global.Verschnittoptimierung.radioButton_sizeInc.Checked) || (evolution && global.selectedGreedy == 5) || (evolution && global.selectedGreedy == 6) || (evolution && global.selectedGreedy == 13) || (evolution && global.selectedGreedy == 14) ) { // sort rects from min size to max size tools.QuickSortRectBySizeInc(0, solution.BoardList[solution.BoardList.Count - 1].RectList.Count - 1, solution.BoardList[solution.BoardList.Count - 1].RectList); } else if((global.Verschnittoptimierung.radioButton_sizeDec.Checked) || (evolution && global.selectedGreedy == 7) || (evolution && global.selectedGreedy == 8) || (evolution && global.selectedGreedy == 15) || (evolution && global.selectedGreedy == 16) ) { // sort rects from max size to min size tools.QuickSortRectBySizeDec(0, solution.BoardList[solution.BoardList.Count - 1].RectList.Count - 1, solution.BoardList[solution.BoardList.Count - 1].RectList); } if(!evolution) { global.runningProcess.firstStep = false; } } // END one time // for each rect on collectionBoard for (int i = (evolution ? global.nextStepGreedyEvo : global.runningProcess.nextStep); i < solution.BoardList[solution.BoardList.Count - 1].RectList.Count;) { if(!evolution) { global.runningProcess.state = 1; } // sort boards from max free space to least free space List<int> boardNrSorted = tools.SortBoardsBySize(solution.BoardList); // for each board try to place the rect for (int j = 0; j < boardNrSorted.Count - 1; j++) { // try place the rect // 1. is the space as area enough for the board? (without finding a specific place) // calculate boardSizeEffective int boardSizeEffective = solution.BoardList[boardNrSorted[j]].size; for (int k = 0; k < solution.BoardList[boardNrSorted[j]].RectList.Count; k++) { boardSizeEffective -= solution.BoardList[boardNrSorted[j]].RectList[k].size; } if (boardSizeEffective < solution.BoardList[solution.BoardList.Count - 1].RectList[i].size) { // rect is too large, cannot be placed on any of the boards. // has to remain on the collectionBoard if(!evolution) { classificationNumbers.GetAndShowAllClassificationNumbers(); } break; } // 2. try to place the rect in the selected board // clone the rect Rect rect = new Rect(); rect.edgeLeftUp = new MyPoint(); rect.edgeRightDown = new MyPoint(); rect.rectID = solution.BoardList[solution.BoardList.Count - 1].RectList[i].rectID; rect.size = solution.BoardList[solution.BoardList.Count - 1].RectList[i].size; rect.width = solution.BoardList[solution.BoardList.Count - 1].RectList[i].width; rect.height = solution.BoardList[solution.BoardList.Count - 1].RectList[i].height; /* rect.edgeLeftUp.x = solution.BoardList[solution.BoardList.Count - 1].RectList[i].edgeLeftUp.x; rect.edgeLeftUp.y = solution.BoardList[solution.BoardList.Count - 1].RectList[i].edgeLeftUp.y; rect.edgeRightDown.x = solution.BoardList[solution.BoardList.Count - 1].RectList[i].edgeRightDown.x; rect.edgeRightDown.y = solution.BoardList[solution.BoardList.Count - 1].RectList[i].edgeRightDown.y; */ // reset values in global global.positionsManaged = new List<Position>(); global.positionsValid = new List<Position>(); global.bestPositionSet = false; // TODO: this part(vertical, then horizontal / or only one if equal) should be moved to GetValidPos() // first vertical, then horizontal if (rect.width == rect.height) { rect.edgeLeftUp.x = 0; rect.edgeLeftUp.y = rect.height; rect.edgeRightDown.x = rect.width; rect.edgeRightDown.y = 0; GetValidPositions(solution.BoardList[boardNrSorted[j]].RectList, rect, evolution); } else { // 1. vertical if (rect.width > rect.height) { int helper = rect.width; rect.width = rect.height; rect.height = helper; } rect.edgeLeftUp.x = 0; rect.edgeLeftUp.y = rect.height; rect.edgeRightDown.x = rect.width; rect.edgeRightDown.y = 0; GetValidPositions(solution.BoardList[boardNrSorted[j]].RectList, rect, evolution); // 2. horizontal if (rect.height > rect.width) { int helper = rect.width; rect.width = rect.height; rect.height = helper; } rect.edgeLeftUp.x = 0; rect.edgeLeftUp.y = rect.height; rect.edgeRightDown.x = rect.width; rect.edgeRightDown.y = 0; GetValidPositions(solution.BoardList[boardNrSorted[j]].RectList, rect, evolution); } // select the best position of the valid ones SelectBestPosition(evolution); Boolean rectPlaced = false; if (global.bestPositionSet == true) { // 1. show valid positions // 2. show best position // 3. place best position rect.edgeLeftUp.x = global.bestPosition.edgeLeftUp.x; rect.edgeLeftUp.y = global.bestPosition.edgeLeftUp.y; rect.edgeRightDown.x = global.bestPosition.edgeRightDown.x; rect.edgeRightDown.y = global.bestPosition.edgeRightDown.y; solution.BoardList[boardNrSorted[j]].RectList.Add(rect); //solution.BoardList[solution.BoardList.Count - 1].RectList.Remove(rect); solution.BoardList[solution.BoardList.Count - 1].RectList.RemoveAt(i); // .... rectPlaced = true; // show can't be called from here if(!evolution) { // check for best solution and set if necessary tools.CheckForBestSolution(); // show solution Show show = new Show(global); show.ShowSolution(global.solution); } } // last rect tried? if (solution.BoardList[solution.BoardList.Count - 1].RectList.Count == 0 || (solution.BoardList[solution.BoardList.Count - 1].RectList.Count - 1) < (evolution ? global.nextStepGreedyEvo : global.runningProcess.nextStep)) { if(!evolution) { global.runningProcess.existing = false; global.runningProcess.state = 0; classificationNumbers.GetAndShowAllClassificationNumbers(); } break; } if (rectPlaced) { if(!evolution) { global.runningProcess.state = 0; classificationNumbers.GetAndShowAllClassificationNumbers(); } break; } if (!rectPlaced) { if(!evolution) { global.runningProcess.nextStep++; } else { global.nextStepGreedyEvo++; } i++; if ((solution.BoardList[solution.BoardList.Count - 1].RectList.Count - 1) < (evolution ? global.nextStepGreedyEvo : global.runningProcess.nextStep)) { if(!evolution) { global.runningProcess.existing = false; global.runningProcess.state = 0; classificationNumbers.GetAndShowAllClassificationNumbers(); } break; } } } if(!evolution && global.runningProcess.stepType == 0) { global.runningProcess.state = 0; classificationNumbers.GetAndShowAllClassificationNumbers(); break; } } if(!evolution) { global.runningProcess.state = 0; classificationNumbers.GetAndShowAllClassificationNumbers(); } return solution; }
// one step for a single position public void ManagePosition(List<Rect> rectList, Rect rect, Position position, Boolean evolution) { Base global = Base.GetInstance(); // 1.1 position out of borders? (boardHeight<rectY etc.) // TODO: general board width/height not set, therefore using height/width of the first board in the solution if (position.edgeLeftUp.y > global.solution.BoardList[0].height || position.edgeRightDown.x > global.solution.BoardList[0].width) { return; } // 1.2 position already managed? (already tried in another recursive call) for(int i = 0; i < global.positionsManaged.Count; i++) { // if yes, stop this method if (position.IsEqualPositionAs(global.positionsManaged[i])) { return; } } // if no (then the method reaches this point), add to positions managed global.positionsManaged.Add(position); // 2. collision? Collision collision = new Collision(); Rect rectCopy = new Rect(); rectCopy.edgeLeftUp.x = position.edgeLeftUp.x; rectCopy.edgeLeftUp.y = position.edgeLeftUp.y; rectCopy.edgeRightDown.x = position.edgeRightDown.x; rectCopy.edgeRightDown.y = position.edgeRightDown.y; rectCopy.height = rect.height; rectCopy.width = rect.width; rectCopy.rectID = rect.rectID; List<int> collisionListNr = collision.GetCollisions(rectList, rectCopy); if(collisionListNr.Count == 0) { // 3. add to valid positions global.positionsValid.Add(position); if(!evolution && global.Verschnittoptimierung.radioButton_FirstFitFilling.Checked || global.selectedGreedy <= 8 ) { return; } } else { // for all collisions for (int i = 0; i < collisionListNr.Count; i++) { // move up and try again // 1. move up Position positionUp = new Position(); positionUp.SetToPosition(position); positionUp.edgeRightDown.y = rectList[collisionListNr[i]].edgeLeftUp.y; float height = position.edgeLeftUp.y - position.edgeRightDown.y; positionUp.edgeLeftUp.y = positionUp.edgeRightDown.y + height; // 2. try again this.ManagePosition(rectList, rect, positionUp, evolution); // move right and try again // 1. move right Position positionRight = new Position(); positionRight.SetToPosition(position); positionRight.edgeLeftUp.x = rectList[collisionListNr[i]].edgeRightDown.x; float width = position.edgeRightDown.x - position.edgeLeftUp.x; positionRight.edgeRightDown.x = positionRight.edgeLeftUp.x + width; // 2. try again this.ManagePosition(rectList, rect, positionRight, evolution); } } }
public Solution CloneSolution(Solution solution) { Solution solutionClone = new Solution(); solutionClone.SolutionID = solution.SolutionID; solutionClone.usedBenchmarkID = solution.usedBenchmarkID; solutionClone.numberOfBoards = solution.numberOfBoards; solutionClone.numberOfRects = solution.numberOfRects; solutionClone.creationTime = solution.creationTime; solutionClone.percentageFilledArea = solution.percentageFilledArea; solutionClone.numberRectsPlaced = solution.numberRectsPlaced; solutionClone.numberRectsLeft = solution.numberRectsLeft; solutionClone.benchmark = solution.benchmark; solutionClone.BoardList = new List<Board>(); for (int i = 0; i < solution.BoardList.Count; i++) { Board board = new Board(); board.boardID = solution.BoardList[i].boardID; board.height = solution.BoardList[i].height; board.width = solution.BoardList[i].width; board.size = solution.BoardList[i].size; board.isCollectionBoard = solution.BoardList[i].isCollectionBoard; board.edgeLeftUp = new MyPoint(); board.edgeLeftUp.x = (solution.BoardList[i].edgeLeftUp != null)? solution.BoardList[i].edgeLeftUp.x : 0; board.edgeLeftUp.y = (solution.BoardList[i].edgeLeftUp != null)? solution.BoardList[i].edgeLeftUp.y : 0; board.edgeRightDown = new MyPoint(); board.edgeRightDown.x = (solution.BoardList[i].edgeRightDown != null) ? solution.BoardList[i].edgeRightDown.x : 0; board.edgeRightDown.y = (solution.BoardList[i].edgeRightDown != null) ? solution.BoardList[i].edgeRightDown.y : 0; for (int j = 0; j < solution.BoardList[i].RectList.Count; j++) { Rect rect = new Rect(); rect.rectID = solution.BoardList[i].RectList[j].rectID; rect.width = solution.BoardList[i].RectList[j].width; rect.height = solution.BoardList[i].RectList[j].height; rect.size = solution.BoardList[i].RectList[j].size; rect.edgeLeftUp = new MyPoint(); rect.edgeLeftUp.x = (solution.BoardList[i].RectList[j].edgeLeftUp != null)? solution.BoardList[i].RectList[j].edgeLeftUp.x : 0; rect.edgeLeftUp.y = (solution.BoardList[i].RectList[j].edgeLeftUp != null)? solution.BoardList[i].RectList[j].edgeLeftUp.y : 0; rect.edgeRightDown = new MyPoint(); rect.edgeRightDown.x = (solution.BoardList[i].RectList[j].edgeRightDown != null)? solution.BoardList[i].RectList[j].edgeRightDown.x : 0; rect.edgeRightDown.y = (solution.BoardList[i].RectList[j].edgeRightDown != null)? solution.BoardList[i].RectList[j].edgeRightDown.y : 0; board.RectList.Add(rect); } solutionClone.BoardList.Add(board); } return solutionClone; }