Example #1
0
        private List <Member> Djikstra(List <Member> initMembers, int starterNum, int dinnerNum, int dessertNum, int numnerOfMembersPerDateAss1)
        {
            List <Node> OPEN  = new List <Node>();
            List <Node> CLOSE = new List <Node>();

            int groupsizeStarter = starterNum % numnerOfMembersPerDateAss1 == 0 ? 2 : (int)Math.Floor((double)((dinnerNum + dessertNum) / starterNum));
            int groupsizeDinner  = dinnerNum % numnerOfMembersPerDateAss1 == 0 ? 2 : (int)Math.Floor((double)((starterNum + dessertNum) / dinnerNum));
            int groupsizeDessert = dessertNum % numnerOfMembersPerDateAss1 == 0 ? 2 : (int)Math.Floor((double)((dinnerNum + starterNum) / dessertNum));

            int highestZ = 0;

            int  z           = 0;
            int  id          = 0;
            int  goal        = initMembers.Count * 2;
            int  backupcost  = 500;
            Node backupNode  = new Node(0, 0, z, initMembers, new List <Tuple <int, int> >(), 500);
            Node currentNode = new Node(0, 0, z, initMembers, new List <Tuple <int, int> >(), 500);

            OPEN.Add(currentNode);

            while (true)
            {
                if (OPEN.Count > 0 && currentNode.datesFound.Count != goal)
                {
                    currentNode = getNodeWithLowestCost(OPEN);
                    OPEN.Remove(currentNode);
                }
                else if (currentNode.datesFound.Count != goal)
                {
                    currentNode = getNodeWithLowestCost(CLOSE);
                    Debug.WriteLine("Ops");
                    currentNode.cost = 10000;
                }

                if (OPEN.Count > 8000)
                {
                    OPEN = new List <Node>();
                }
                List <Member> members = currentNode.members;

                if (currentNode.datesFound.Count == goal)
                {
                    Debug.WriteLine("Z: " + currentNode.z);
                    Debug.WriteLine("Allready met: " + currentNode.allreadyMet);
                    Debug.WriteLine("Association error: " + currentNode.associationCost);
                    Debug.WriteLine("Cost: " + currentNode.cost);
                    currentNode.members.ForEach(p => p.allReadyMet.ForEach(l => Debug.WriteLine(p.ID + ": " + l)));
                    return(currentNode.members);
                }

                OPEN.Remove(currentNode);

                int numerOfmembers = members.Count;
                for (int i = 0; i < numerOfmembers; i++)
                {
                    List <Member> membersClone = members.Clone();
                    if (membersClone[i].allDatesFound())
                    {
                        continue;
                    }

                    List <Tuple <int, int> > dates = new List <Tuple <int, int> >(currentNode.datesFound);
                    int cost            = 0;
                    int allreadyMet     = 0;
                    int associationcost = 0;
                    for (int j = 0; j < numerOfmembers; j++)
                    {
                        bool allreadyRegistered = currentNode.datesFound.FirstOrDefault(n => n.Item1 == i && n.Item2 == j) != null;
                        if (allreadyRegistered || membersClone[i].allDatesFound())
                        {
                            continue;
                        }

                        int groupsize = 2;
                        if (membersClone[j].duty == "starter")
                        {
                            groupsize = groupsizeStarter;
                        }
                        else if (membersClone[j].duty == "dinner")
                        {
                            groupsize = groupsizeDinner;
                        }
                        else if (membersClone[j].duty == "dessert")
                        {
                            groupsize = groupsizeDessert;
                        }

                        int release = 0;
                        int whenToIncreaseGroupsize = 2 * numerOfmembers - groupsizeDinner * dinnerNum - groupsizeDessert * dessertNum - groupsizeStarter * starterNum;
                        if (whenToIncreaseGroupsize == 0)
                        {
                            groupsize = (goal - dates.Count) <= (numerOfmembers % (groupsize + 1)) * 2 ? groupsize + 1 : groupsize;
                        }
                        else
                        {
                            groupsize = (goal - dates.Count) <= whenToIncreaseGroupsize + release ? groupsize + 1 : groupsize;
                        }

                        bool possibleMatch = findMatch(membersClone[i], membersClone[j], groupsize);
                        if (!possibleMatch)
                        {
                            continue;
                        }

                        Tuple <int, int> date = new Tuple <int, int>(i, j);
                        dates.Add(date);

                        int[] errorAndCost = calculateCost(membersClone[i], membersClone[j], goal, (goal - dates.Count), associationcost);
                        cost            = cost + errorAndCost[0];
                        allreadyMet     = allreadyMet + errorAndCost[3];
                        associationcost = associationcost + errorAndCost[2];
                        registerDate(membersClone[i], membersClone[j], membersClone);
                    }

                    int  datecount        = dates.Count;
                    Node currentNeighbour = new Node(i, datecount, id, membersClone, dates, cost + associationcost);
                    currentNeighbour.allreadyMet     = currentNode.allreadyMet + allreadyMet;
                    currentNeighbour.associationCost = currentNode.associationCost + associationcost;

                    if (cost < currentNode.cost)
                    {
                        OPEN.Insert(0, currentNeighbour);
                        //Debug.WriteLine("Cost: " + cost + ", Z: " + datecount);
                        id++;
                    }
                    else if (datecount >= highestZ && cost < backupcost)
                    {
                        if (datecount > highestZ)
                        {
                            //CLOSE = new List<Node>();
                            highestZ = datecount;
                        }
                        CLOSE.Add(currentNeighbour);
                        backupcost = cost;
                    }
                }
            }
        }