예제 #1
0
        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());
            }
        }
예제 #2
0
 /// <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());
     }
 }
예제 #3
0
        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);
        }
예제 #4
0
 /// <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");
     }
 }
예제 #5
0
        /// <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);
        }
예제 #6
0
        /// <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);
        }
예제 #7
0
        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);
        }
예제 #8
0
 private void ALNSDestroyRandomContainer(COSolution solution)
 {
     // Remove all pieces from a random container
     solution.RemoveContainer(Instance.Containers.OrderBy(c => Randomizer.Next(Instance.Containers.Count)).First());
 }
예제 #9
0
 private void ALNSDestroy(COSolution solution)
 {
     ALNSDestroyRandomContainer(solution);
 }