public QuadAssignment GenerateNeighbor(ISimAnSolution baseSolution)
        {
            if (!(baseSolution is QuadAssignment qaSol))
            {
                return(null);
            }
            // generate a copy of the existing assignment
            QuadAssignment neighbor = new QuadAssignment();

            foreach (var item in qaSol.AssignmentSolution)
            {
                neighbor.AssignmentSolution.Add(item.Key, item.Value);
            }
            // exchange one pair of unit-location assignments
            int unit1       = _rnd.Next(0, QuadAssignment.MaterialFlow.GetLength(0));
            int unit2       = _rnd.Next(0, QuadAssignment.MaterialFlow.GetLength(0));
            int assignment1 = qaSol.AssignmentSolution[unit1];
            int assignment2 = qaSol.AssignmentSolution[unit2];

            neighbor.AssignmentSolution[unit1] = assignment2;
            neighbor.AssignmentSolution[unit2] = assignment1;
            // calculate objective value and return neighbor
            neighbor.CalculateFitness();
            return(neighbor);
        }
        public void OptimizeAssignment(double[,] materialFlow, double[,] distances)
        {
            QuadAssignment.MaterialFlow = materialFlow;
            QuadAssignment.Distances    = distances;
            if (materialFlow.GetLength(0) > distances.GetLength(0))
            {
                throw new ArgumentException($"Not enough locations to assign all units!");
            }

            //setup the heuristic optimization
            SimAnHeurParams saParams = new SimAnHeurParams(defaultStepSize: 5, defaultCoolDown: 0.95, startTemp: 35);

            saParams.GenerateNeighborSolution = this.GenerateNeighbor;
            saParams.MaxIter = (int)Math.Pow(10, 4);
            //optimize
            ISimAnSolution startSolution = GenerateStartSolution();
            SimAnHeuristic heuristic     = new SimAnHeuristic(saParams, startSolution);
            SimAnOutput    output        = heuristic.Minimize();

            Console.WriteLine("**************");
            Console.WriteLine(output.ToString());
            Console.WriteLine("**************");
            foreach (var item in (output.BestSolution as QuadAssignment).AssignmentSolution)
            {
                Console.WriteLine($"  Unit {item.Key} assigned to location {item.Value}.");
            }
            Console.WriteLine("**************");
        }
 internal SimAnOutput(ISimAnSolution finalSol,
                      List <double> temperatureFitness,
                      List <double> iterFitness,
                      double initSolVal)
 {
     BestSolution             = finalSol;
     TemperatureFitnessLevels = temperatureFitness;
     IterationFitnessLevels   = iterFitness;
     Iterations       = iterFitness.Count;
     InitialObjective = initSolVal;
 }
예제 #4
0
        public SimAnOutput Minimize()
        {
            bool stop = false;

            _bestSolution = _startSolution;
            ISimAnSolution currentSolution = _startSolution;
            double         deltaFitness, curTemp = _params.StartTemp;
            int            iter = 0, iterCoolDown;

            iterCoolDown = iter + _params.CoolDownStepSize(curTemp);
            int           accepted                 = 0;
            List <double> temperatureFitnessLevels = new List <double>();
            List <double> iterationFitnessLevels   = new List <double>()
            {
                currentSolution.Fitness
            };

            while (!stop)
            {
                //generate neighbor solution
                ISimAnSolution neighbor = _params.GenerateNeighborSolution(currentSolution);
                deltaFitness = neighbor.Fitness - currentSolution.Fitness;
                //acceptance test
                if (AcceptNeighbor(deltaFitness, curTemp))
                {
                    currentSolution = neighbor;
                    accepted       += 1;
                }
                //improvement test
                if (currentSolution.Fitness < _bestSolution.Fitness)
                {
                    _bestSolution = currentSolution;
                }
                iterationFitnessLevels.Add(currentSolution.Fitness);
                iter++;
                //cooldown by annealing schedule
                if (iter == iterCoolDown)
                {
                    //record statistics for this temp-level (plateau)
                    temperatureFitnessLevels.Add(_bestSolution.Fitness);
                    //update temperature and set next cooldown iteration
                    curTemp       = _params.CoolDown(curTemp);
                    iterCoolDown += _params.CoolDownStepSize(curTemp);
                    //test abort criterion
                    stop = StopSearchAfterPlateau(accepted, temperatureFitnessLevels);
                    //reset number of accepted solutions within plateau
                    accepted = 0;
                }
                stop = stop | iter > _params.MaxIter;
            }
            return(new SimAnOutput(_bestSolution, temperatureFitnessLevels, iterationFitnessLevels, _startSolution.Fitness));
        }
예제 #5
0
        public SimAnHeuristic(SimAnHeurParams p, ISimAnSolution startSol, int randomSeed = 1)
        {
            if (p == null)
            {
                throw new ArgumentNullException(nameof(p));
            }
            if (p.CoolDown == null)
            {
                throw new ArgumentNullException(nameof(p), "CoolDown of the SimAnHeurParams is null.");
            }
            if (p.CoolDownStepSize == null)
            {
                throw new ArgumentNullException(nameof(p), "CoolDownStepSize of the SimAnHeurParams is null.");
            }
            if (p.GenerateNeighborSolution == null)
            {
                throw new ArgumentNullException(nameof(p), "GenerateNeighborSolution of the SimAnHeurParams is null.");
            }

            _params        = p;
            _startSolution = startSol;
            _rnd           = new Random(randomSeed);
        }