Beispiel #1
0
        public bool Shift(double ctrlPM)
        {
            int rndStartIndex;
            Tuple <int, int> rndStart, rndTarget;

            rndStart  = SelectRandomRoute();
            rndTarget = SelectRandomRoute();

            //Get a random start and target route.
            Day   tarDay     = week.GetWeek[rndTarget.Item1];
            Day   startDay   = week.GetWeek[rndStart.Item1];
            Route startRoute = startDay.GetRoutes[rndStart.Item2];
            Route tarRoute   = tarDay.GetRoutes[rndTarget.Item2];

            if (tarRoute.GetRoute.Count == 0 || startRoute.GetRoute.Count == 0)
            {
                return(true);
            }

            //Choose a random order from the startroute
            rndStartIndex = random.Next(startRoute.GetRoute.Count);
            Order order = startRoute.GetRoute[rndStartIndex];

            if (order.frequency > 1)
            {
                if (tarDay.DayNumber != startDay.DayNumber)
                {
                    if (order.frequency == 4)
                    {
                        return(true);

                        //An order with frequency 4 should not be swapped to another day that has the order
                        if (order.GetBit(tarDay.DayNumber))
                        {
                            return(true);
                        }
                    }
                    else if (order.frequency == 2)
                    {
                        #region freq2
                        int sDay1, sDay2, sRoute1, sRoute2, index1, index2, unprocessedDay = 0, processedDay = 0;
                        Tuple <int, int, int> indices;

                        //This gets which day, of mon and tue, is processed and unprocessed (from this we can glean the other day)
                        for (int i = 1; i < 3; i++)
                        {
                            if (!order.GetBit(i))
                            {
                                unprocessedDay = i;
                            }
                            else
                            {
                                processedDay = i;
                            }
                        }

                        //startday can be mon, tue, thur, fri
                        //can be in the first or latter part of the week
                        //then, it can be bigger or smaller than the unprocessedDay
                        if (startDay.DayNumber > 2)
                        {
                            if (startDay.DayNumber - 3 > unprocessedDay) //unprocessed is mon (startday is friday: 5 - 3 = 2; 2 > 1)
                            {
                                //other call should shift tue to mon, need to find out which truck does the order
                                indices = FindOccurence(2, order); //this method finds out which day exactly contains the order
                                //In this case, we have to obtain the truck that does the order on tuesday, we know of the truck on friday
                            }
                            else  //Startday is thursday, unprocessed is tuesday
                            {
                                //other call should shift mon to tue, need to find out which truck does the order
                                indices = FindOccurence(1, order); //this method finds out which day exactly contains the order
                            }

                            //Set the parameters, start day is in the latter half of the week. That means we had to use FindOccurence to find the earlier weekday, hence the indices use
                            sDay1 = indices.Item1; sDay2 = rndStart.Item1; sRoute1 = indices.Item2; sRoute2 = rndStart.Item2; index1 = indices.Item3; index2 = rndStartIndex;
                        }
                        else //startDay is in the first half of the week
                        {
                            if (startDay.DayNumber > unprocessedDay) //Starting day is tuesday, unprocessed is monday
                            {
                                indices = FindOccurence(5, order);  //Find the day in the latter half of the week (on friday)
                            }
                            else
                            {
                                indices = FindOccurence(4, order);
                            }

                            //Set the parameters, start day is in the latter half of the week. Note how indices is now used for the different day!
                            sDay1 = rndStart.Item1; sDay2 = indices.Item1; sRoute1 = rndStart.Item2; sRoute2 = indices.Item2; index1 = rndStartIndex; index2 = indices.Item3;
                        }

                        if (indices.Item1 == -1 || indices.Item2 == -1 || indices.Item3 == -1)
                        {
                            return(true);
                        }

                        return(DoubleShift(ctrlPM, sDay1, sDay2, sRoute1, sRoute2, index1, index2, order));

                        #endregion
                    }
                    else
                    {
                        return(true);
                    }
                }

                //All orders should be allowed to be swapped to the same day
            }

            #region shiftBody
            //Original time of target route; original time of target day (to be calculated); new time of rout (tbc); value of best improvement
            double oTime = tarRoute.TotalTime(), oDayTime = 0, nTime = 0, best = double.MaxValue;
            int    bestPos = -1, totalLoad = tarRoute.TotalLoad();

            //Calc total time of the target day
            foreach (Route r in tarDay.GetRoutes)
            {
                oDayTime += r.TotalTime();
            }

            //Calculate the time difference of removing the route from the starting route
            double sTime, nSTime, timeDiff;
            sTime = startRoute.TotalTime();
            startRoute.Remove(rndStartIndex);
            nSTime   = startRoute.TotalTime();
            timeDiff = sTime - nSTime;

            //Go over the target route, figure out the best location to shift to
            for (int i = 0; i < tarRoute.GetRoute.Count; i++)
            {
                tarRoute.GetRoute.Insert(i, order);
                nTime = tarRoute.TotalTime();

                //Check if it's valid (time and load wise) and whether it's better
                if (oDayTime + nTime - oTime < WORKINGDAY && totalLoad + order.numberOfContainers * order.volumeOfOneContainer < MAXLOAD && nTime < best)
                {
                    bestPos = i;
                    best    = nTime;
                }

                tarRoute.Remove(i);
            }
            #endregion

            bool accept = false;
            if (bestPos != -1)
            {
                //Check wether it is a net gain in time or not
                //TimeDiff is positive, because this much time is gained from the removal
                //best - oTime, the increase in route time
                //The total thing should be increase in new route measured against decrease in the other
                if (timeDiff - (best - oTime) > 0)
                {
                    //In case of this occuring, the shift was a net gain (more went out of the old route then came into the new route)
                    tarRoute.GetRoute.Insert(bestPos, order);

                    //Update Routes
                    tarDay.UpdateRoutes();
                    startDay.UpdateRoutes();

                    //Change some bits if necessary
                    if (order.frequency == 4 && startDay.DayNumber != tarDay.DayNumber)
                    {
                        order.SetBit(startDay.DayNumber, false);
                        order.SetBit(tarDay.DayNumber, true);
                    }
                    return(true);
                }
                else //Order is not an improvement
                {
                    accept = AcceptOperation(ctrlPM, timeDiff - (best - oTime));

                    if (accept)
                    {
                        //We accepted a deterioration
                        tarRoute.GetRoute.Insert(bestPos, order);

                        //Update Routes
                        tarDay.UpdateRoutes();
                        startDay.UpdateRoutes();
                        bShifts++;

                        //Change some bits if necessary
                        if (order.frequency == 4 && startDay.DayNumber != tarDay.DayNumber)
                        {
                            order.SetBit(startDay.DayNumber, false);
                            order.SetBit(tarDay.DayNumber, true);
                        }
                        return(false);
                    }
                    else
                    {
                        //Put the order back in its original spot when we fail to shift
                        startRoute.GetRoute.Insert(rndStartIndex, order);
                        return(true);
                    }
                }
            }
            else
            {
                //Put the order back in its original spot when we fail to shift
                startRoute.GetRoute.Insert(rndStartIndex, order);
                return(true);
            }
        }