Advertisement
SpaceRiver

Untitled

Feb 22nd, 2023
30
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.72 KB | None | 0 0
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using SimpleDb;
  5. using System;
  6. using Scenes;
  7. using System.Linq;
  8.  
  9. namespace Algorithms {
  10.  
  11. public class AlgorithmFactory {
  12. public Algorithm GetAlgorithm() {
  13. Profile profile = StaticValues.profile;
  14. if (profile == null) {
  15. throw new Exception("Profile is null");
  16. }
  17. switch (profile.Algorithm) {
  18. case "Uniform":
  19. return new UniformAlgorithm(profile);
  20. case "UniformOrdered":
  21. return new UniformOrderedAlgorithm(profile);
  22. case "Greedy":
  23. return new GreedyAlgorithm(profile);
  24. default:
  25. throw new Exception("Algorithm not found");
  26. }
  27. }
  28. }
  29.  
  30. public abstract class Algorithm {
  31. protected Profile Profile;
  32.  
  33. protected List<Box> Boxes;
  34. protected Dimensions ContainerDimensions;
  35. protected string? ExtraPreferences;
  36. protected int ProblemId;
  37.  
  38. protected Solution Solution;
  39.  
  40.  
  41. public Algorithm(Profile profile) {
  42. Boxes = null;
  43. ContainerDimensions = null;
  44. ExtraPreferences = null;
  45. Solution = null;
  46. Profile = profile;
  47. }
  48.  
  49. protected bool Fits(List<BoxPlacement> boxPlacements, BoxPlacement boxPlacement) {
  50. foreach (BoxPlacement placedBox in boxPlacements) {
  51. float x1Min = placedBox.Position.x;
  52. float x1Max = placedBox.Position.x + placedBox.Box.Dimensions.Width;
  53. float y1Min = placedBox.Position.y;
  54. float y1Max = placedBox.Position.y + placedBox.Box.Dimensions.Height;
  55. float z1Min = placedBox.Position.z;
  56. float z1Max = placedBox.Position.z + placedBox.Box.Dimensions.Length;
  57.  
  58. float x2Min = boxPlacement.Position.x;
  59. float x2Max = boxPlacement.Position.x + boxPlacement.Box.Dimensions.Width;
  60. float y2Min = boxPlacement.Position.y;
  61. float y2Max = boxPlacement.Position.y + boxPlacement.Box.Dimensions.Height;
  62. float z2Min = boxPlacement.Position.z;
  63. float z2Max = boxPlacement.Position.z + boxPlacement.Box.Dimensions.Length;
  64.  
  65. // if intersecting the container return false
  66. if (x2Min < 0 || x2Max > ContainerDimensions.Width || y2Min < 0 || y2Max > ContainerDimensions.Height || z2Min < 0 || z2Max > ContainerDimensions.Length) {
  67. return false;
  68. }
  69. // if not intersecting then coninue
  70. if (x1Max <= x2Min || x2Max <= x1Min || y1Max <= y2Min || y2Max <= y1Min || z1Max <= z2Min || z2Max <= z1Min) {
  71. continue;
  72. } else {
  73. return false;
  74. }
  75. }
  76. return true;
  77. }
  78.  
  79. protected Box GetRandomOrientation(Box box, float heat) {
  80. Box newBox = new Box(box.Description, box.Dimensions, box.Restrictions, box.OrderInList, box.Preferences);
  81. // get number between 0 and 1
  82. float random = UnityEngine.Random.Range(0f, 1f);
  83. // if random is more than heat then return the box
  84. if (random >= heat) {
  85. return newBox;
  86. }
  87. // get random orientation
  88. int orientation = UnityEngine.Random.Range(0, 5);
  89. switch (orientation) {
  90. case 0:
  91. newBox.Dimensions = box.Dimensions;
  92. break;
  93. case 1:
  94. newBox.Dimensions = new Dimensions(box.Dimensions.Length, box.Dimensions.Width, box.Dimensions.Height);
  95. break;
  96. case 2:
  97. newBox.Dimensions = new Dimensions(box.Dimensions.Height, box.Dimensions.Length, box.Dimensions.Width);
  98. break;
  99. case 3:
  100. newBox.Dimensions = new Dimensions(box.Dimensions.Width, box.Dimensions.Height, box.Dimensions.Length);
  101. break;
  102. case 4:
  103. newBox.Dimensions = new Dimensions(box.Dimensions.Height, box.Dimensions.Width, box.Dimensions.Length);
  104. break;
  105. case 5:
  106. newBox.Dimensions = new Dimensions(box.Dimensions.Length, box.Dimensions.Height, box.Dimensions.Width);
  107. break;
  108. }
  109. return newBox;
  110. }
  111. protected List<List<Box>> GetRandomBoxeOrientations(List<Box> currentOrientation, int num_of_similar, int num_of_normal, int num_of_differnet) {
  112. List<List<Box>> boxOrientations = new List<List<Box>>();
  113. // always have the default one
  114. boxOrientations.Add(Boxes);
  115.  
  116. // add the similar ones
  117. for (int i = 0; i < num_of_similar; i++) {
  118. List<Box> boxes = new List<Box>();
  119. foreach (Box box in currentOrientation) {
  120. boxes.Add(GetRandomOrientation(box, 0.02f));
  121. }
  122. boxOrientations.Add(boxes);
  123. }
  124. // add the normal ones
  125. for (int i = 0; i < num_of_normal; i++) {
  126. List<Box> boxes = new List<Box>();
  127. foreach (Box box in currentOrientation) {
  128. boxes.Add(GetRandomOrientation(box, 0.1f));
  129. }
  130. boxOrientations.Add(boxes);
  131. }
  132. // add the different ones
  133. for (int i = 0; i < num_of_differnet; i++) {
  134. List<Box> boxes = new List<Box>();
  135. foreach (Box box in currentOrientation) {
  136. boxes.Add(GetRandomOrientation(box, 0.3f));
  137. }
  138. boxOrientations.Add(boxes);
  139. }
  140. // add 1 random
  141. List<Box> boxes = new List<Box>();
  142. foreach (Box box in currentOrientation) {
  143. boxes.Add(GetRandomOrientation(box, 1f));
  144. }
  145. boxOrientations.Add(boxes);
  146.  
  147. return boxOrientations;
  148. }
  149.  
  150. protected BoxPlacement getFirstAvailableBoxPlacement(List<BoxPlacement> boxPlacements, Box box) {
  151. Position position = new Position();
  152. position.x = 0;
  153. position.y = 0;
  154. position.z = 0;
  155. List<float> allPossibleX = new List<float>();
  156. List<float> allPossibleY = new List<float>();
  157. List<float> allPossibleZ = new List<float>();
  158. foreach (BoxPlacement boxPlacement in boxPlacements) {
  159. //Debug.Log("BoxPlacement: " + boxPlacement.Position.x + " " + boxPlacement.Position.y + " " + boxPlacement.Position.z);
  160. // debug the sizes
  161. //Debug.Log("BoxPlacement: " + boxPlacement.Box.Dimensions.Width + " " + boxPlacement.Box.Dimensions.Height + " " + boxPlacement.Box.Dimensions.Length);
  162. allPossibleX.Add(boxPlacement.Position.x + boxPlacement.Box.Dimensions.Width);
  163. allPossibleY.Add(boxPlacement.Position.y + boxPlacement.Box.Dimensions.Height);
  164. allPossibleZ.Add(boxPlacement.Position.z + boxPlacement.Box.Dimensions.Length);
  165. }
  166. // add 0,0,0
  167. allPossibleX.Add(0);
  168. allPossibleY.Add(0);
  169. allPossibleZ.Add(0);
  170.  
  171. // remove duplicates
  172. allPossibleX = allPossibleX.Distinct().ToList();
  173. allPossibleY = allPossibleY.Distinct().ToList();
  174. allPossibleZ = allPossibleZ.Distinct().ToList();
  175. // sort so that the smallest values are first
  176. allPossibleX.Sort();
  177. allPossibleY.Sort();
  178. allPossibleZ.Sort();
  179.  
  180.  
  181. // find the first available position
  182. foreach (float x in allPossibleX) {
  183. foreach (float y in allPossibleY) {
  184. foreach (float z in allPossibleZ) {
  185. position = new Position();
  186. position.x = x;
  187. position.y = y;
  188. position.z = z;
  189. BoxPlacement boxPlacement = new BoxPlacement();
  190. boxPlacement.Box = box;
  191. boxPlacement.Position = position;
  192. if (Fits(boxPlacements, boxPlacement)) {
  193. return boxPlacement;
  194. }
  195. }
  196. }
  197. }
  198. return null;
  199. }
  200.  
  201. public abstract Solution Solve(Problem problem);
  202.  
  203. protected List<Dimensions> GetRotations(Dimensions dimensions) {
  204. List<Dimensions> rotations = new List<Dimensions>();
  205. rotations.Add(dimensions);
  206. rotations.Add(new Dimensions(dimensions.Height, dimensions.Width, dimensions.Length));
  207. rotations.Add(new Dimensions(dimensions.Length, dimensions.Height, dimensions.Width));
  208. return rotations;
  209. }
  210.  
  211. public Solution GetSolution(Problem problem) {
  212. if (Boxes == null || ContainerDimensions == null) {
  213. throw new Exception("Boxes or ContainerDimensions not set");
  214. } else {
  215. if (Solution == null) {
  216. Solution = Solve(problem);
  217. }
  218. return Solution;
  219. }
  220. }
  221. }
  222.  
  223. public class UniformAlgorithm : Algorithm {
  224. public UniformAlgorithm(Profile profile) : base(profile) { }
  225.  
  226.  
  227. public override Solution Solve(Problem Problem) {
  228. Boxes = Problem.Boxes;
  229. ContainerDimensions = Problem.ContainerDimensions;
  230. ExtraPreferences = Problem.ExtraPreferences;
  231. ProblemId = Problem.Id;
  232. if (!CheckUniform()) {
  233. throw new Exception("Boxes are not uniform");
  234. }
  235. // try fit boxes in container without rotation
  236. Dimensions firstBoxDimensions = Boxes[0].Dimensions;
  237. List<Dimensions> rotations = GetRotations(firstBoxDimensions);
  238. foreach (Dimensions rotation in rotations) {
  239. if(OniformFits(rotation)) {
  240. return ArrangeBoxes(rotation);
  241. }
  242. }
  243. throw new Exception("Boxes do not fit in container");
  244. }
  245.  
  246. private Solution ArrangeBoxes(Dimensions boxDimensions) {
  247. int x = Convert.ToInt32(ContainerDimensions.Width / boxDimensions.Width);
  248. int y = Convert.ToInt32(ContainerDimensions.Height / boxDimensions.Height);
  249. int z = Convert.ToInt32(ContainerDimensions.Length / boxDimensions.Length);
  250. int boxCount = Boxes.Count;
  251. List<BoxPlacement> boxPlacements = new List<BoxPlacement>();
  252. for (int i = 0; i < boxCount; i++) {
  253. int xIndex = i % x;
  254. int yIndex = (i / x) % y;
  255. int zIndex = i / (x * y);
  256. Position position = new Position();
  257. position.x = xIndex * boxDimensions.Width;
  258. position.y = yIndex * boxDimensions.Height;
  259. position.z = zIndex * boxDimensions.Length;
  260. BoxPlacement boxPlacement = new BoxPlacement();
  261. Box box = Boxes[i];
  262. box.Dimensions = boxDimensions;
  263. boxPlacement.Box = box;
  264. boxPlacement.Position = position;
  265. boxPlacements.Add(boxPlacement);
  266. }
  267. Solution solution = new Solution();
  268. solution.Placements = boxPlacements;
  269. solution.ProblemId = ProblemId;
  270. solution.ProfileId = Profile.Id;
  271. return solution;
  272. }
  273. private bool OniformFits(Dimensions boxDimensions) {
  274. int x = Convert.ToInt32(ContainerDimensions.Width / boxDimensions.Width);
  275. int y = Convert.ToInt32(ContainerDimensions.Height / boxDimensions.Height);
  276. int z = Convert.ToInt32(ContainerDimensions.Length / boxDimensions.Length);
  277. int maxBoxes = x * y * z;
  278. int boxCount = Boxes.Count;
  279. return maxBoxes >= boxCount;
  280. }
  281.  
  282. // checks all the boxes are the same size
  283. private bool CheckUniform() {
  284. if (Boxes.Count == 0) {
  285. return false;
  286. }
  287. Dimensions firstBoxDimensions = Boxes[0].Dimensions;
  288. foreach (Box box in Boxes) {
  289. if (box.Dimensions.Height != firstBoxDimensions.Height || box.Dimensions.Width != firstBoxDimensions.Width || box.Dimensions.Length != firstBoxDimensions.Length) {
  290. return false;
  291. }
  292. }
  293. return true;
  294. }
  295. }
  296.  
  297. public class UniformOrderedAlgorithm : Algorithm {
  298. public UniformOrderedAlgorithm(Profile profile) : base(profile) { }
  299.  
  300. public override Solution Solve(Problem problem) {
  301. Algorithm algorithm = new UniformAlgorithm(Profile);
  302. // order boxes based on ORderInList, where the biggest numbers will be first
  303. problem.Boxes.Sort((x, y) => y.OrderInList.CompareTo(x.OrderInList));
  304. Solution solution = algorithm.Solve(problem);
  305. return solution;
  306. }
  307. }
  308.  
  309. public class GreedyAlgorithm : Algorithm {
  310. private List<BoxPlacement> boxPlacements;
  311. private int mostBoxesPlaced = 0;
  312. private List<Box> bestOrientation;
  313. public GreedyAlgorithm(Profile profile) : base(profile) {
  314. boxPlacements = new List<BoxPlacement>();
  315. }
  316.  
  317. private Solution SolveForOrientation(Problem problem, List<Box> boxes) {
  318. boxes.Sort((x, y) => x.Dimensions.Height.CompareTo(y.Dimensions.Height));
  319. boxes.Sort((x, y) => x.Dimensions.Width.CompareTo(y.Dimensions.Width));
  320. boxes.Sort((x, y) => x.Dimensions.Length.CompareTo(y.Dimensions.Length));
  321.  
  322.  
  323. // our current position in the container
  324. int counter = 0;
  325. foreach (Box box in boxes) {
  326. BoxPlacement boxPlacement = getFirstAvailableBoxPlacement(boxPlacements,box);
  327. if (boxPlacement == null) {
  328. Debug.Log(counter);
  329. boxPlacements = new List<BoxPlacement>();
  330. if (counter >= mostBoxesPlaced) {
  331. mostBoxesPlaced = counter;
  332. bestOrientation = boxes;
  333. }
  334. return null;
  335. }
  336. boxPlacements.Add(boxPlacement);
  337. counter++;
  338. }
  339. Solution solution = new Solution();
  340. solution.Placements = boxPlacements;
  341. solution.ProblemId = ProblemId;
  342. solution.ProfileId = Profile.Id;
  343. return solution;
  344.  
  345.  
  346. }
  347.  
  348. public override Solution Solve(Problem problem) {
  349. Boxes = problem.Boxes;
  350. ContainerDimensions = problem.ContainerDimensions;
  351. ExtraPreferences = problem.ExtraPreferences;
  352. ProblemId = problem.Id;
  353.  
  354. bestOrientation = Boxes;
  355.  
  356. for (int i = 0; i <50; i++) {
  357. List<List<Box>> boxOrientations = GetRandomBoxeOrientations(bestOrientation, 100, 50, 25);
  358. foreach (List<Box> boxOrientation in boxOrientations) {
  359. Solution solution = SolveForOrientation(problem, boxOrientation);
  360. if (solution != null) {
  361. return solution;
  362. }
  363. }
  364. }
  365. throw new Exception("Boxes do not fit in container");
  366. }
  367. }
  368. }
  369.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement