private void ALNSRepair(COSolution solution) { // Decide randomly for now RepairStrategy repairStrategy = Randomizer.NextDouble() > 0.5 ? RepairStrategy.RandomOrientationOrder : RepairStrategy.RandomPieceOrder; switch (repairStrategy) { case RepairStrategy.RandomPieceOrder: { // Only order the offload pieces randomly ExtremePointInsertion(solution, solution.ConstructionContainerOrder, solution.OffloadPieces.OrderBy(p => Randomizer.NextDouble()).ToList(), solution.ConstructionOrientationOrder); } break; case RepairStrategy.RandomOrientationOrder: { // Order orientations randomly int[][] randomOrientations = solution.ConstructionOrientationOrder.Select(p => p.OrderBy(r => Randomizer.NextDouble()).ToArray()).ToArray(); ExtremePointInsertion(solution, solution.ConstructionContainerOrder, solution.OffloadPieces.ToList(), randomOrientations); } break; default: throw new ArgumentException("Unknown repair strategy: " + repairStrategy.ToString()); } }
/// <summary> /// Logs the visuals of the current solution /// </summary> /// <param name="solution">The solution to log</param> /// <param name="overrideTime">Overrides the timeout and logs anyway</param> protected void LogVisuals(COSolution solution, bool overrideTime) { if (Config.SubmitSolution != null && (overrideTime || DateTime.Now.Ticks - LogOldVisualMillis > 150000000)) { LogOldVisualMillis = DateTime.Now.Ticks; Config.SubmitSolution(solution, true, ExportationConstants.ExportDir, Instance.GetIdent()); } }
private void DestroyContainerExploitedVolumeBased(COSolution solution, double relativeContainerIndex) { // Remove all pieces from the container with the index matching the given relative position when ordered by exploited relative volume IEnumerable <Container> usedContainers = Instance.Containers.Where(c => solution.ExploitedVolumeOfContainers[c.VolatileID] > 0); int containerIndex = (int)(relativeContainerIndex * usedContainers.Count()); Container containerToDestroy = usedContainers.OrderByDescending(c => solution.ExploitedVolumeOfContainers[c.VolatileID] / c.Mesh.Volume).ElementAt(containerIndex); solution.RemoveContainer(containerToDestroy); }
/// <summary> /// Logs basic information about the progress /// </summary> /// <param name="piece">The currently added piece</param> /// <param name="container">The container to which the piece is added</param> protected void LogProgress(COSolution solution, Piece piece, Container container) { if (Config.Log != null && DateTime.Now.Ticks - LogOldMillis > 10000000) { LogOldMillis = DateTime.Now.Ticks; Config.Log(solution.ExploitedVolume.ToString(ExportationConstants.EXPORT_FORMAT_SHORT, ExportationConstants.FORMATTER) + " / " + VolumeOfContainers.ToString(ExportationConstants.EXPORT_FORMAT_SHORT, ExportationConstants.FORMATTER) + " - Piece " + piece.ID + " -> Container " + container.ID + "\n"); } }
/// <summary> /// Creates a new solution and registers it to the instance /// </summary> /// <param name="unofficial">Indicates whether to keep track of the created solution or not</param> /// <param name="tetris">Indicates whether the solution shall be capable of keeping track of tetris based information about itself</param> /// <param name="meritType">The merit type to use</param> /// <returns>The newly created solution</returns> public COSolution CreateSolution(bool tetris, MeritFunctionType meritType, bool unofficial = false) { COSolution solution = new COSolution(this, tetris, meritType); if (!unofficial) { solution.ID = ++_solutionCounter; Solutions.Add(solution); } return(solution); }
/// <summary> /// Reads an instance file from the given path. /// </summary> /// <param name="path">The path to the instance file</param> /// <returns>The read instance</returns> public static Instance ReadXML(string path) { // Prepare XML data XmlDocument document = new XmlDocument(); document.Load(path); Instance instance = new Instance(); // Name if (document.SelectSingleNode("//Instance").Attributes["Name"] != null) { instance.Name = document.SelectSingleNode("//Instance").Attributes["Name"].Value; } else { instance.Name = "Default"; } // Read containers XmlNode containersRoot = document.SelectSingleNode("//Instance/Containers"); List <Container> containers = new List <Container>(); if (containersRoot != null) { foreach (var childNode in containersRoot.ChildNodes.OfType <XmlNode>()) { Container container = new Container(); container.LoadXML(childNode); containers.Add(container); } } // Read pieces XmlNode piecesRoot = document.SelectSingleNode("//Instance/Pieces"); List <VariablePiece> pieces = new List <VariablePiece>(); if (piecesRoot != null) { foreach (var childNode in piecesRoot.ChildNodes.OfType <XmlNode>()) { VariablePiece piece = new VariablePiece(); piece.LoadXML(childNode); pieces.Add(piece); } } // Add all items instance.Containers.AddRange(containers); instance.Pieces.AddRange(pieces); // Read solutions XmlNode solutionsRoot = document.SelectSingleNode("//Instance/Solutions"); List <COSolution> solutions = new List <COSolution>(); if (solutionsRoot != null) { foreach (var childNode in solutionsRoot.ChildNodes.OfType <XmlNode>()) { COSolution solution = instance.CreateSolution(false, MeritFunctionType.None); solution.LoadXML(childNode); solutions.Add(solution); } } // Return return(instance); }
protected override void Solve() { // --> Initialization // Initialize meta-info VolumeOfContainers = Instance.Containers.Sum(c => c.Mesh.Volume); // Init ordering List <VariablePiece> pieces = null; Init(out Solution.ConstructionContainerOrder, out pieces, out Solution.ConstructionOrientationOrder); // --> Construction part // Log Config.Log?.Invoke("Starting construction ... " + Environment.NewLine); // Generate initial solution ExtremePointInsertion(Solution, Solution.ConstructionContainerOrder, pieces, Solution.ConstructionOrientationOrder); // --> Improvement part // Log Config.Log?.Invoke("Starting improvement ... " + Environment.NewLine); // Measure performance compared to given solution double initialExploitedVolume = Solution.ExploitedVolume; // TODO move the following into the config int intervalIterationCountMax = 100; double alpha = 0.9; // Init counters int currentIteration = 0; int lastImprovement = 0; double currentTemperature = 1000; int currentIntervalIteration = 0; // Init solutions COSolution acceptedSolution = Solution.Clone(); // Main loop do { // Init solution for this turn COSolution currentSolution = acceptedSolution.Clone(); // Destroy the solution ALNSDestroy(currentSolution); // Repair the solution ALNSRepair(currentSolution); // Check whether we want to accept the solution or discard it if (ALNSAccept(acceptedSolution.ExploitedVolume, currentSolution.ExploitedVolume, Solution.ExploitedVolume, currentTemperature)) { acceptedSolution = currentSolution; } // Lower temperature if iteration limit is reached if (currentIntervalIteration >= intervalIterationCountMax) { currentIntervalIteration = 0; currentTemperature *= alpha; } // Store every new best solution if (acceptedSolution.ExploitedVolume > Solution.ExploitedVolume) { Solution = acceptedSolution; } // Log visuals LogVisuals(Solution, false); // Log if (DateTime.Now.Ticks - LogOldMillis > 1000000) { LogOldMillis = DateTime.Now.Ticks; Config.Log?.Invoke(currentIteration + ". " + Solution.ExploitedVolume.ToString(ExportationConstants.EXPORT_FORMAT_SHORT, ExportationConstants.FORMATTER) + " / " + VolumeOfContainers.ToString(ExportationConstants.EXPORT_FORMAT_SHORT, ExportationConstants.FORMATTER) + " (" + (Solution.ExploitedVolume / VolumeOfContainers * 100).ToString(ExportationConstants.EXPORT_FORMAT_SHORT, ExportationConstants.FORMATTER) + " %) - Current: " + acceptedSolution.ExploitedVolume.ToString(ExportationConstants.EXPORT_FORMAT_SHORT, ExportationConstants.FORMATTER) + " / " + VolumeOfContainers.ToString(ExportationConstants.EXPORT_FORMAT_SHORT, ExportationConstants.FORMATTER) + " (" + ((Solution.ExploitedVolume / VolumeOfContainers - initialExploitedVolume / VolumeOfContainers) * 100).ToString(ExportationConstants.EXPORT_FORMAT_SHORT, ExportationConstants.FORMATTER) + " %)" + " Time: " + (DateTime.Now - Config.StartTimeStamp).TotalSeconds + " \n"); Config.LogSolutionStatus?.Invoke((DateTime.Now - Config.StartTimeStamp).TotalSeconds, Solution.ExploitedVolume); } // Update counters currentIteration++; currentIntervalIteration++; } while (currentIteration - lastImprovement < Config.StagnationDistance && !Cancelled && !TimeUp); }
private void ALNSDestroyRandomContainer(COSolution solution) { // Remove all pieces from a random container solution.RemoveContainer(Instance.Containers.OrderBy(c => Randomizer.Next(Instance.Containers.Count)).First()); }
private void ALNSDestroy(COSolution solution) { ALNSDestroyRandomContainer(solution); }