Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using SimpleDb;
- using System;
- using Scenes;
- using System.Linq;
- namespace Algorithms {
- public class AlgorithmFactory {
- public Algorithm GetAlgorithm() {
- Profile profile = StaticValues.profile;
- if (profile == null) {
- throw new Exception("Profile is null");
- }
- switch (profile.Algorithm) {
- case "Uniform":
- return new UniformAlgorithm(profile);
- case "UniformOrdered":
- return new UniformOrderedAlgorithm(profile);
- case "Greedy":
- return new GreedyAlgorithm(profile);
- default:
- throw new Exception("Algorithm not found");
- }
- }
- }
- public abstract class Algorithm {
- protected Profile Profile;
- protected List<Box> Boxes;
- protected Dimensions ContainerDimensions;
- protected string? ExtraPreferences;
- protected int ProblemId;
- protected Solution Solution;
- public Algorithm(Profile profile) {
- Boxes = null;
- ContainerDimensions = null;
- ExtraPreferences = null;
- Solution = null;
- Profile = profile;
- }
- protected bool Fits(List<BoxPlacement> boxPlacements, BoxPlacement boxPlacement) {
- foreach (BoxPlacement placedBox in boxPlacements) {
- float x1Min = placedBox.Position.x;
- float x1Max = placedBox.Position.x + placedBox.Box.Dimensions.Width;
- float y1Min = placedBox.Position.y;
- float y1Max = placedBox.Position.y + placedBox.Box.Dimensions.Height;
- float z1Min = placedBox.Position.z;
- float z1Max = placedBox.Position.z + placedBox.Box.Dimensions.Length;
- float x2Min = boxPlacement.Position.x;
- float x2Max = boxPlacement.Position.x + boxPlacement.Box.Dimensions.Width;
- float y2Min = boxPlacement.Position.y;
- float y2Max = boxPlacement.Position.y + boxPlacement.Box.Dimensions.Height;
- float z2Min = boxPlacement.Position.z;
- float z2Max = boxPlacement.Position.z + boxPlacement.Box.Dimensions.Length;
- // if intersecting the container return false
- if (x2Min < 0 || x2Max > ContainerDimensions.Width || y2Min < 0 || y2Max > ContainerDimensions.Height || z2Min < 0 || z2Max > ContainerDimensions.Length) {
- return false;
- }
- // if not intersecting then coninue
- if (x1Max <= x2Min || x2Max <= x1Min || y1Max <= y2Min || y2Max <= y1Min || z1Max <= z2Min || z2Max <= z1Min) {
- continue;
- } else {
- return false;
- }
- }
- return true;
- }
- protected Box GetRandomOrientation(Box box, float heat) {
- Box newBox = new Box(box.Description, box.Dimensions, box.Restrictions, box.OrderInList, box.Preferences);
- // get number between 0 and 1
- float random = UnityEngine.Random.Range(0f, 1f);
- // if random is more than heat then return the box
- if (random >= heat) {
- return newBox;
- }
- // get random orientation
- int orientation = UnityEngine.Random.Range(0, 5);
- switch (orientation) {
- case 0:
- newBox.Dimensions = box.Dimensions;
- break;
- case 1:
- newBox.Dimensions = new Dimensions(box.Dimensions.Length, box.Dimensions.Width, box.Dimensions.Height);
- break;
- case 2:
- newBox.Dimensions = new Dimensions(box.Dimensions.Height, box.Dimensions.Length, box.Dimensions.Width);
- break;
- case 3:
- newBox.Dimensions = new Dimensions(box.Dimensions.Width, box.Dimensions.Height, box.Dimensions.Length);
- break;
- case 4:
- newBox.Dimensions = new Dimensions(box.Dimensions.Height, box.Dimensions.Width, box.Dimensions.Length);
- break;
- case 5:
- newBox.Dimensions = new Dimensions(box.Dimensions.Length, box.Dimensions.Height, box.Dimensions.Width);
- break;
- }
- return newBox;
- }
- protected List<List<Box>> GetRandomBoxeOrientations(List<Box> currentOrientation, int num_of_similar, int num_of_normal, int num_of_differnet) {
- List<List<Box>> boxOrientations = new List<List<Box>>();
- // always have the default one
- boxOrientations.Add(Boxes);
- // add the similar ones
- for (int i = 0; i < num_of_similar; i++) {
- List<Box> boxes = new List<Box>();
- foreach (Box box in currentOrientation) {
- boxes.Add(GetRandomOrientation(box, 0.02f));
- }
- boxOrientations.Add(boxes);
- }
- // add the normal ones
- for (int i = 0; i < num_of_normal; i++) {
- List<Box> boxes = new List<Box>();
- foreach (Box box in currentOrientation) {
- boxes.Add(GetRandomOrientation(box, 0.1f));
- }
- boxOrientations.Add(boxes);
- }
- // add the different ones
- for (int i = 0; i < num_of_differnet; i++) {
- List<Box> boxes = new List<Box>();
- foreach (Box box in currentOrientation) {
- boxes.Add(GetRandomOrientation(box, 0.3f));
- }
- boxOrientations.Add(boxes);
- }
- // add 1 random
- List<Box> boxes = new List<Box>();
- foreach (Box box in currentOrientation) {
- boxes.Add(GetRandomOrientation(box, 1f));
- }
- boxOrientations.Add(boxes);
- return boxOrientations;
- }
- protected BoxPlacement getFirstAvailableBoxPlacement(List<BoxPlacement> boxPlacements, Box box) {
- Position position = new Position();
- position.x = 0;
- position.y = 0;
- position.z = 0;
- List<float> allPossibleX = new List<float>();
- List<float> allPossibleY = new List<float>();
- List<float> allPossibleZ = new List<float>();
- foreach (BoxPlacement boxPlacement in boxPlacements) {
- //Debug.Log("BoxPlacement: " + boxPlacement.Position.x + " " + boxPlacement.Position.y + " " + boxPlacement.Position.z);
- // debug the sizes
- //Debug.Log("BoxPlacement: " + boxPlacement.Box.Dimensions.Width + " " + boxPlacement.Box.Dimensions.Height + " " + boxPlacement.Box.Dimensions.Length);
- allPossibleX.Add(boxPlacement.Position.x + boxPlacement.Box.Dimensions.Width);
- allPossibleY.Add(boxPlacement.Position.y + boxPlacement.Box.Dimensions.Height);
- allPossibleZ.Add(boxPlacement.Position.z + boxPlacement.Box.Dimensions.Length);
- }
- // add 0,0,0
- allPossibleX.Add(0);
- allPossibleY.Add(0);
- allPossibleZ.Add(0);
- // remove duplicates
- allPossibleX = allPossibleX.Distinct().ToList();
- allPossibleY = allPossibleY.Distinct().ToList();
- allPossibleZ = allPossibleZ.Distinct().ToList();
- // sort so that the smallest values are first
- allPossibleX.Sort();
- allPossibleY.Sort();
- allPossibleZ.Sort();
- // find the first available position
- foreach (float x in allPossibleX) {
- foreach (float y in allPossibleY) {
- foreach (float z in allPossibleZ) {
- position = new Position();
- position.x = x;
- position.y = y;
- position.z = z;
- BoxPlacement boxPlacement = new BoxPlacement();
- boxPlacement.Box = box;
- boxPlacement.Position = position;
- if (Fits(boxPlacements, boxPlacement)) {
- return boxPlacement;
- }
- }
- }
- }
- return null;
- }
- public abstract Solution Solve(Problem problem);
- protected List<Dimensions> GetRotations(Dimensions dimensions) {
- List<Dimensions> rotations = new List<Dimensions>();
- rotations.Add(dimensions);
- rotations.Add(new Dimensions(dimensions.Height, dimensions.Width, dimensions.Length));
- rotations.Add(new Dimensions(dimensions.Length, dimensions.Height, dimensions.Width));
- return rotations;
- }
- public Solution GetSolution(Problem problem) {
- if (Boxes == null || ContainerDimensions == null) {
- throw new Exception("Boxes or ContainerDimensions not set");
- } else {
- if (Solution == null) {
- Solution = Solve(problem);
- }
- return Solution;
- }
- }
- }
- public class UniformAlgorithm : Algorithm {
- public UniformAlgorithm(Profile profile) : base(profile) { }
- public override Solution Solve(Problem Problem) {
- Boxes = Problem.Boxes;
- ContainerDimensions = Problem.ContainerDimensions;
- ExtraPreferences = Problem.ExtraPreferences;
- ProblemId = Problem.Id;
- if (!CheckUniform()) {
- throw new Exception("Boxes are not uniform");
- }
- // try fit boxes in container without rotation
- Dimensions firstBoxDimensions = Boxes[0].Dimensions;
- List<Dimensions> rotations = GetRotations(firstBoxDimensions);
- foreach (Dimensions rotation in rotations) {
- if(OniformFits(rotation)) {
- return ArrangeBoxes(rotation);
- }
- }
- throw new Exception("Boxes do not fit in container");
- }
- private Solution ArrangeBoxes(Dimensions boxDimensions) {
- int x = Convert.ToInt32(ContainerDimensions.Width / boxDimensions.Width);
- int y = Convert.ToInt32(ContainerDimensions.Height / boxDimensions.Height);
- int z = Convert.ToInt32(ContainerDimensions.Length / boxDimensions.Length);
- int boxCount = Boxes.Count;
- List<BoxPlacement> boxPlacements = new List<BoxPlacement>();
- for (int i = 0; i < boxCount; i++) {
- int xIndex = i % x;
- int yIndex = (i / x) % y;
- int zIndex = i / (x * y);
- Position position = new Position();
- position.x = xIndex * boxDimensions.Width;
- position.y = yIndex * boxDimensions.Height;
- position.z = zIndex * boxDimensions.Length;
- BoxPlacement boxPlacement = new BoxPlacement();
- Box box = Boxes[i];
- box.Dimensions = boxDimensions;
- boxPlacement.Box = box;
- boxPlacement.Position = position;
- boxPlacements.Add(boxPlacement);
- }
- Solution solution = new Solution();
- solution.Placements = boxPlacements;
- solution.ProblemId = ProblemId;
- solution.ProfileId = Profile.Id;
- return solution;
- }
- private bool OniformFits(Dimensions boxDimensions) {
- int x = Convert.ToInt32(ContainerDimensions.Width / boxDimensions.Width);
- int y = Convert.ToInt32(ContainerDimensions.Height / boxDimensions.Height);
- int z = Convert.ToInt32(ContainerDimensions.Length / boxDimensions.Length);
- int maxBoxes = x * y * z;
- int boxCount = Boxes.Count;
- return maxBoxes >= boxCount;
- }
- // checks all the boxes are the same size
- private bool CheckUniform() {
- if (Boxes.Count == 0) {
- return false;
- }
- Dimensions firstBoxDimensions = Boxes[0].Dimensions;
- foreach (Box box in Boxes) {
- if (box.Dimensions.Height != firstBoxDimensions.Height || box.Dimensions.Width != firstBoxDimensions.Width || box.Dimensions.Length != firstBoxDimensions.Length) {
- return false;
- }
- }
- return true;
- }
- }
- public class UniformOrderedAlgorithm : Algorithm {
- public UniformOrderedAlgorithm(Profile profile) : base(profile) { }
- public override Solution Solve(Problem problem) {
- Algorithm algorithm = new UniformAlgorithm(Profile);
- // order boxes based on ORderInList, where the biggest numbers will be first
- problem.Boxes.Sort((x, y) => y.OrderInList.CompareTo(x.OrderInList));
- Solution solution = algorithm.Solve(problem);
- return solution;
- }
- }
- public class GreedyAlgorithm : Algorithm {
- private List<BoxPlacement> boxPlacements;
- private int mostBoxesPlaced = 0;
- private List<Box> bestOrientation;
- public GreedyAlgorithm(Profile profile) : base(profile) {
- boxPlacements = new List<BoxPlacement>();
- }
- private Solution SolveForOrientation(Problem problem, List<Box> boxes) {
- boxes.Sort((x, y) => x.Dimensions.Height.CompareTo(y.Dimensions.Height));
- boxes.Sort((x, y) => x.Dimensions.Width.CompareTo(y.Dimensions.Width));
- boxes.Sort((x, y) => x.Dimensions.Length.CompareTo(y.Dimensions.Length));
- // our current position in the container
- int counter = 0;
- foreach (Box box in boxes) {
- BoxPlacement boxPlacement = getFirstAvailableBoxPlacement(boxPlacements,box);
- if (boxPlacement == null) {
- Debug.Log(counter);
- boxPlacements = new List<BoxPlacement>();
- if (counter >= mostBoxesPlaced) {
- mostBoxesPlaced = counter;
- bestOrientation = boxes;
- }
- return null;
- }
- boxPlacements.Add(boxPlacement);
- counter++;
- }
- Solution solution = new Solution();
- solution.Placements = boxPlacements;
- solution.ProblemId = ProblemId;
- solution.ProfileId = Profile.Id;
- return solution;
- }
- public override Solution Solve(Problem problem) {
- Boxes = problem.Boxes;
- ContainerDimensions = problem.ContainerDimensions;
- ExtraPreferences = problem.ExtraPreferences;
- ProblemId = problem.Id;
- bestOrientation = Boxes;
- for (int i = 0; i <50; i++) {
- List<List<Box>> boxOrientations = GetRandomBoxeOrientations(bestOrientation, 100, 50, 25);
- foreach (List<Box> boxOrientation in boxOrientations) {
- Solution solution = SolveForOrientation(problem, boxOrientation);
- if (solution != null) {
- return solution;
- }
- }
- }
- throw new Exception("Boxes do not fit in container");
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement