public void Generate(List<Task> remainingTasks, int nbTasksInSequence, TaskSequence sequence)
        {
            var orderedTasks = new List<Task>(nbTasksInSequence);

            if (nbTasksInSequence > remainingTasks.Count)
            {
                throw new Exception("Not enough tasks to generate the specified sequence length");
            }

            if (remainingTasks.Count > 0)
            {
                var task = FindAlmostNearestTask(null, remainingTasks, 1.0);
                remainingTasks.Remove(task);
                orderedTasks.Add(task);

                if (remainingTasks.Count > 0)
                {
                    task = FindAlmostNearestTask(task, remainingTasks, 1.0);
                    remainingTasks.Remove(task);
                    orderedTasks.Add(task);

                    orderedTasks.Add(null);

                    for (int t = 0; t < nbTasksInSequence - 2; t++)
                    {
                        int minCost = Int32.MaxValue;
                        Task minTask = null;
                        int minInsertPos = -1;

                        for (int t1 = 0; t1 < orderedTasks.Count - 1; t1++)
                        {
                            int cost = FindCheapestInsert(orderedTasks[t1], orderedTasks[t1 + 1], remainingTasks, out task);
                            if (cost < minCost)
                            {
                                minCost = cost;
                                minTask = task;
                                minInsertPos = t1;
                            }
                        }

                        remainingTasks.Remove(minTask);
                        orderedTasks.Insert(minInsertPos + 1, minTask);
                    }

                    orderedTasks.RemoveAt(orderedTasks.Count - 1);
                }
            }

            sequence.Tasks = orderedTasks;
        }
        public TaskSequence Generate(List<Task> remainingTasks, int nbTasksInSequence, Worker worker)
        {
            var sequence = new TaskSequence{ Worker = worker};

            Generate(remainingTasks, nbTasksInSequence, sequence);

            return sequence;
        }
        private void ComputeEdgeRecombinaisonCrossover(TaskSequence p1, TaskSequence p2)
        {
            // use the Edge recombination operator
            // see: http://en.wikipedia.org/wiki/Edge_recombination_operator
            //_rand = new Random(11);
            for (int t = 0; t < TaskSequencer.GetOriginalTasks().Count; t++)
            {
                for (int t2 = 0; t2 < TaskSequencer.GetOriginalTasks().Count; t2++)
                {
                    _crossoverTaskNeighborMatrix[t][t2] = false;
                }
                _crossoverAddedTasks[t] = false;
                _crossoverTaskNeighborCount[t] = 0;

                _crossoverTaskNeighbors[t][0] = null;
                _crossoverTaskNeighbors[t][1] = null;
                _crossoverTaskNeighbors[t][2] = null;
                _crossoverTaskNeighbors[t][3] = null;
            }

            Tasks.Clear();

            AddNeighborsToCrossoverList(p1);
            AddNeighborsToCrossoverList(p2);
            Task task = null;

            if (_rand.Next(2) == 0)
            {
                task = p1.Tasks[0];
            }
            else
            {
                task = p2.Tasks[0];
            }

            for (int i = 0; i < TaskSequencer.GetOriginalTasks().Count; i++)
            {
                Tasks.Add(task);
                _crossoverAddedTasks[task.UserId] = true;

                int nbNeighbors = _crossoverTaskNeighborCount[task.UserId];

                if (nbNeighbors > 0)
                {
                    // find the neighbor with the fewest neighbors...

                    Task minTask = null;
                    int minTaskNeighbors = 99999;

                    // remove the task from its neighbors...
                    for (int t = 0; t < 4; t++)
                    {
                        Task neighbor = _crossoverTaskNeighbors[task.UserId][t];

                        if (neighbor != null && _crossoverTaskNeighborMatrix[task.UserId][neighbor.UserId])
                        {
                            _crossoverTaskNeighborMatrix[neighbor.UserId][task.UserId] = false;
                            _crossoverTaskNeighborMatrix[task.UserId][neighbor.UserId] = false;
                            _crossoverTaskNeighborCount[neighbor.UserId]--;

                            if (_crossoverTaskNeighborCount[neighbor.UserId] < minTaskNeighbors ||
                                (_crossoverTaskNeighborCount[neighbor.UserId] == minTaskNeighbors &&
                                 _rand.Next(2) == 0))
                            {
                                minTask = neighbor;
                                minTaskNeighbors = _crossoverTaskNeighborCount[neighbor.UserId];
                            }
                        }
                    }

                    task = minTask;

                    if (task == null)
                    {
                        throw new Exception("null task");
                    }
                }
                else
                {
                    // find a task not already added...

                    for (int notAddedTaskIndex = 0;
                         notAddedTaskIndex < TaskSequencer.GetOriginalTasks().Count;
                         notAddedTaskIndex++)
                    {
                        if (_crossoverAddedTasks[notAddedTaskIndex] == false)
                        {
                            task = TaskSequencer.GetOriginalTasks()[notAddedTaskIndex];
                            if (task == null)
                            {
                                throw new Exception("null task");
                            }

                            break;
                        }
                    }
                }
            }

            UpdateFitness();
        }
        private void AddNeighborsToCrossoverList(TaskSequence sequence)
        {
            Task prevTask = null;
            foreach (Task task in sequence.Tasks)
            {
                if (prevTask != null)
                {
                    if (_crossoverTaskNeighborMatrix[task.UserId][prevTask.UserId] == false)
                    {
                        _crossoverTaskNeighborMatrix[task.UserId][prevTask.UserId] = true;
                        _crossoverTaskNeighbors[task.UserId][_crossoverTaskNeighborCount[task.UserId]] = prevTask;
                        _crossoverTaskNeighborCount[task.UserId]++;
                    }

                    if (_crossoverTaskNeighborMatrix[prevTask.UserId][task.UserId] == false)
                    {
                        _crossoverTaskNeighborMatrix[prevTask.UserId][task.UserId] = true;
                        _crossoverTaskNeighbors[prevTask.UserId][_crossoverTaskNeighborCount[prevTask.UserId]] = task;
                        _crossoverTaskNeighborCount[prevTask.UserId]++;
                    }
                }

                prevTask = task;
            }
        }