예제 #1
0
        private void NBS(object sender, EventArgs e)
        {
            totalDistance = 0;
            Station[] ss = new Station[stations.Length];
            stations.CopyTo(ss, 0);
            Array.Sort(ss);
            //找出不需要用送的站點作為補給站之用
            List <Station> supplyStation = new List <Station>();

            Priority_Queue.SimplePriorityQueue <Station> pq = new Priority_Queue.SimplePriorityQueue <Station>();

            for (int i = 0; i < ss.Length; i++)
            {
                if (ss[i].Rate != 0)
                {
                    pq.Enqueue(ss[i], 1);
                }
                if (ss[i].Rate == 0)
                {
                    supplyStation.Add(ss[i]);
                }
            }

            int[] Sequence = new int[totalStation];
            for (int i = 0; i < Sequence.Length; i++)
            {
                Sequence[i] = -1;
            }
            //確定第一站為最需要先被服務的並且直接先決定卡車上的貨物數量
            //直接先決定到的時間點剛好為最需要被服務的剛好缺的時點
            int[]  temp  = new int[totalStation];
            double time  = 0;
            double cost  = 0;
            Truck  truck = null;

            for (int k = ss.Length - 1; k > -1; k--)
            {
                if (ss[k].Rate != 0)
                {
                    if (ss[k].Rate < 0) //rate < 0 => need to delivery
                    {
                        truck   = new Truck(truckcapacity, truckcapacity);
                        temp[0] = truckcapacity / 2;
                        //cost = HoldingShortageSurplus(time, Sequence[0], truck.PickupDelivery(14));
                    }
                    else if (ss[k].Rate > 0)
                    {
                        truck   = new Truck(truckcapacity, 0);
                        temp[0] = -truckcapacity / 2;
                        //cost = HoldingShortageSurplus(time, Sequence[0], truck.PickupDelivery(-14));
                    }
                    time        = startTOvertex[ss[k].StationID] / speed;
                    Sequence[0] = ss[k].StationID;
                    temp[0]     = truck.PickupDelivery(temp[0]);
                    cost       += HoldingShortageSurplus(time, Sequence[0], temp[0], ref truck);
                    break;
                }
            }


            Station s = null;
            //開始建構解
            int    a = 1; bool flag = false;
            double min = double.MaxValue; double m = 0; int selected = -1;

            while (time <= timehorizon && a < totalStation)
            {
                while (pq.Count != 0)
                {
                    s = pq.Max();
                    pq.Remove(s); flag = false;
                    //s = pq.Dequeue();
                    if (Sequence.Contains(s.StationID) == false)
                    {
                        Sequence[a] = s.StationID;
                        break;
                    }
                    if (pq.Count == 0)
                    {
                        if (supplyStation.Count != 0)
                        {
                            s = supplyStation.Max();
                            supplyStation.Remove(s);
                        }
                        break;
                    }
                }
                min = double.MaxValue;
                //下一站是需要貨物的可是你卻沒有貨ㄌ
                if (s.Declinebymin < 0)
                {
                    //find truck lack of goods
                    if (truck.CurrentGoods == 0 && supplyStation.Count != 0)
                    {
                        min = double.MaxValue;
                        //find the nearest supply station
                        for (int i = 0; i < supplyStation.Count; i++)
                        {
                            m = distanceMatrix[Sequence[a - 1], supplyStation.ElementAt(i).StationID];
                            if (min > m)
                            {
                                min = m; selected = i;
                            }
                        }
                        temp[a]     = truck.SupplyTruck(supplyStation.ElementAt(selected));
                        flag        = true;
                        Sequence[a] = supplyStation.ElementAt(selected).StationID;
                        supplyStation.RemoveAt(selected);
                        if (a != stations.Length - 1)
                        {
                            Sequence[a + 1] = s.StationID;
                        }
                    }
                    if (flag == true)
                    {
                        time          += distanceMatrix[Sequence[a - 1], Sequence[a]] / speed;//到下一站的時間點
                        totalDistance += distanceMatrix[Sequence[a - 1], Sequence[a]];
                        if (a != stations.Length - 1)
                        {
                            time          += distanceMatrix[Sequence[a], Sequence[a + 1]] / speed;//到下一站的時間點
                            totalDistance += distanceMatrix[Sequence[a], Sequence[a + 1]];
                            temp[a + 1]    = truck.PickupDelivery(truckcapacity / 2);
                            cost          += HoldingShortageSurplus(time, Sequence[a + 1], temp[a + 1], ref truck);
                        }
                        a += 2;
                    }
                    else
                    {
                        temp[a] = truck.PickupDelivery(truckcapacity / 2);
                        cost   += HoldingShortageSurplus(time, Sequence[a], temp[a], ref truck);
                    }
                }
                else
                {
                    //find truck full of goods
                    if (truck.CurrentSpace == 0 && supplyStation.Count != 0)
                    {
                        //find the nearest supply station
                        min = double.MaxValue;
                        for (int i = 0; i < supplyStation.Count; i++)
                        {
                            m = distanceMatrix[Sequence[a - 1], supplyStation.ElementAt(i).StationID];
                            if (min > m)
                            {
                                min = m; selected = i;
                            }
                        }
                        temp[a]     = truck.SupplyTruck(supplyStation.ElementAt(selected));
                        flag        = true;
                        Sequence[a] = supplyStation.ElementAt(selected).StationID;
                        supplyStation.RemoveAt(selected);
                        if (a != stations.Length - 1)
                        {
                            Sequence[a + 1] = s.StationID;
                        }
                    }
                    if (flag == true)
                    {
                        time          += distanceMatrix[Sequence[a - 1], Sequence[a]] / speed;//到下一站的時間點
                        totalDistance += distanceMatrix[Sequence[a - 1], Sequence[a]];
                        if (a != stations.Length - 1)
                        {
                            time          += distanceMatrix[Sequence[a], Sequence[a + 1]] / speed;//到下一站的時間點
                            totalDistance += distanceMatrix[Sequence[a], Sequence[a + 1]];
                            temp[a + 1]    = truck.PickupDelivery(-truckcapacity / 2);
                            cost          += HoldingShortageSurplus(time, Sequence[a + 1], temp[a + 1], ref truck);
                        }
                        a += 2;
                    }
                    else
                    {
                        temp[a] = truck.PickupDelivery(-truckcapacity / 2);
                        cost   += HoldingShortageSurplus(time, Sequence[a], temp[a], ref truck);
                    }
                }
                if (flag == false)
                {
                    time          += distanceMatrix[Sequence[a - 1], Sequence[a]] / speed;//到下一站的時間點
                    totalDistance += distanceMatrix[Sequence[a - 1], Sequence[a]];
                    a++;
                }
            }
            if (a >= totalStation)
            {
                a = totalStation - 1;
            }
            //因為上面最後一次部會做所以...
            if (flag == false && stations[Sequence[a - 1]].Declinebymin < 0 && time <= timehorizon)
            {
                temp[a - 1] = truck.PickupDelivery(truckcapacity / 2);
                cost       += HoldingShortageSurplus(time, Sequence[a - 1], temp[a - 1], ref truck);
            }
            else if (flag == false && stations[Sequence[a - 1]].Surplusbymin > 0 && time <= timehorizon)
            {
                temp[a - 1] = truck.PickupDelivery(-truckcapacity / 2);
                cost       += HoldingShortageSurplus(time, Sequence[a - 1], temp[a - 1], ref truck);
            }
            else
            {
                a--;
            }

            //全部跑完要回去depot
            if (a == totalStation - 1)
            {
                totalDistance += startTOvertex[Sequence[a]];
            }
            else
            {
                //沒有跑完的車站繼續算成本
                for (int b = 0; b < pq.Count; b++)
                {
                    cost += HoldingShortageSurplus(timehorizon, pq.ElementAt(b).StationID, 0, ref truck);
                }
            }
            richTextBox.Text = "routing path is depot ";
            for (int i = 0; i < a + 1; i++)
            {
                richTextBox.Text += (Sequence[i] + " ");
            }

            double totalPandD = 0;

            richTextBox.Text += "\n" + "pickup & delivery amount: ";
            for (int i = 0; i < temp.Length; i++)
            {
                richTextBox.Text += temp[i].ToString() + "  ";
                totalPandD       += Math.Abs(temp[i]);
            }
            richTextBox.Text += "\n" + "********performance********";
            richTextBox.Text += "\n" + "unsatisfied amount :" + cost;
            richTextBox.Text += ("\n" + "total distance is " + totalDistance);
            richTextBox.Text += "\n" + "Total pickup & delivery : " + totalPandD;
        }