static Solution Schedule(TimeTableData problemData, int week, 
            WeeklyEventAssignment[] guidingAssignments = null)
        {
            TimeTableData timeTable = problemData;
            problemData.PrepareSuitableTimeSlots(false);

            MMASData mmasData = new MMASData(timeTable, week, EVAPORATION, MIN_PHERAMONE);
            bool secondWeek = guidingAssignments != null;

            if (secondWeek)
                mmasData.SetPheromoneFromExistingAssignments(guidingAssignments);
            else
                mmasData.ResetPheromone();

            Solution bestSoFarSolution = new Solution(problemData, week);

            bestSoFarSolution.RandomInitialSolution();
            bestSoFarSolution.ComputeFeasibility();
            bestSoFarSolution.ComputeHcv();

            int currIter = 0;
            int lastImprIter = 0;
            while (currIter - lastImprIter < 200)
            {
                Solution bestIterSolution = Enumerable.Range(0, ANTS_NUMBER)
                                                      .AsParallel()
                                                      .Select(_ =>
                                                      {
                                                          var ant = new Ant(timeTable, mmasData, week);
                                                          return !secondWeek ?
                                                              ant.GetSolution() :
                                                              ant.GetSolution(guidingAssignments);
                                                      })
                                                      .Min();

                // apply local search until local optimum is reached or a steps limit reached
                if (secondWeek)
                {
                    DEFAULT_MAX_STEPS = Math.Min(DEFAULT_MAX_STEPS + 50, 5000);
                    bestIterSolution.ResolveOnlyWeekSpecificConflicts = true;
                }
                bestIterSolution.LocalSearch(bestIterSolution.IsFeasible ? 3000 : DEFAULT_MAX_STEPS);

                // output the new best solution, if found
                if (bestIterSolution.CompareTo(bestSoFarSolution) < 0)
                {
                    bestIterSolution.CopyTo(bestSoFarSolution);
                    lastImprIter = currIter;
                }

                // update pheromones
                mmasData.EvaporatePheromone();
                mmasData.SetPheromoneLimits();
                if (bestIterSolution.ResolveOnlyWeekSpecificConflicts)
                    mmasData.DepositPheromone(bestIterSolution);
                else
                    mmasData.DepositPheromone(bestSoFarSolution);

                currIter++;
                Console.WriteLine("iter: {0}, HCV: {1}, SCV: {2}", currIter, bestSoFarSolution.Hcv, bestSoFarSolution.Scv);
            }

            bestSoFarSolution.ComputeHcv();
            bestSoFarSolution.ComputeScv();
            Console.WriteLine("RAW: HCV: {0}, SCV: {1}", bestSoFarSolution.Hcv, bestSoFarSolution.Scv);

            problemData.PrepareSuitableTimeSlots(true);

            bestSoFarSolution.TryResolveHcv();
            bestSoFarSolution.ComputeHcv();
            bestSoFarSolution.ComputeScv();
            Console.WriteLine("RESOLVE: HCV: {0}, SCV: {1}", bestSoFarSolution.Hcv, bestSoFarSolution.Scv);

            bestSoFarSolution.LocalSearch(10000, 1, 1); //try to resolve scv
            bestSoFarSolution.ComputeHcv();
            bestSoFarSolution.ComputeScv();
            Console.WriteLine("RESULT: HCV: {0}, SCV: {1}", bestSoFarSolution.Hcv, bestSoFarSolution.Scv);

            return bestSoFarSolution;
        }