private void appendProblems(DVRPProblemInstance instance, int i, DVRPPartialProblemInstance schema,
                                    ref List <DVRPPartialProblemInstance> partialProblemInstances)
        {
            int k = Math.Max(1, instance.VehicleNumber * (i + 1) - instance.Visits.Count);
            int e = instance.VehicleNumber - 1;

            while (k <= e)
            {
                var ignoredList = new List <int> {
                    k
                };

                if (k != e)
                {
                    ignoredList.Add(e);
                }

                var newProblem = new DVRPPartialProblemInstance();
                solutionCopyTo(schema, ref newProblem);
                newProblem.IgnoredSets = ignoredList.ToArray();
                partialProblemInstances.Add(newProblem);
                k++;
                e--;
            }
        }
        private void minimizeSolution(DVRPProblemInstance instance, ref DVRPPartialProblemInstance solution,
                                      List <int>[] currVisits)
        {
            double newCost     = 0f;
            var    newSolution = new List <int> [instance.VehicleNumber];

            for (var j = 0; j < instance.VehicleNumber; j++)
            {
                newSolution[j] = new List <int>();
                for (int e = 0; e < currVisits[j].Count; e++)
                {
                    newSolution[j].Add(currVisits[j][e]);
                }

                var cvref    = newSolution[j].ToArray();
                var currCost = minimizePermutation(instance, ref cvref);
                if (currCost < 0f)
                {
                    return;
                }
                newCost += currCost;
            }
            if (newCost < solution.PartialResult)
            {
                solution.VisitIds = new int[instance.VehicleNumber][];
                for (int u = 0; u < instance.VehicleNumber; u++)
                {
                    solution.VisitIds[u] = newSolution[u].ToArray();
                }
                solution.PartialResult  = newCost;
                solution.SolutionResult = SolutionResult.Successful;
            }
        }
        private void generatePartialProblems(DVRPProblemInstance instance, int i,
                                             ref List <DVRPPartialProblemInstance> partialProblemInstances)
        {
            if (i == 0)
            {
                var schema = new DVRPPartialProblemInstance()
                {
                    MinimalSetCount = 0,
                    PartialResult   = double.MaxValue,
                    SolutionResult  = SolutionResult.Impossible
                };
                appendProblems(instance, i, schema, ref partialProblemInstances);
                return;
            }
            var schemas = solvePossibleMinCountSets(instance, i);

            foreach (var schema in schemas)
            {
                if (instance.VehicleNumber * i == instance.Visits.Count)
                {
                    var partial = new DVRPPartialProblemInstance();
                    solutionCopyTo(schema, ref partial);
                    partial.IgnoredSets = new[] { instance.VehicleNumber };
                    partialProblemInstances.Add(partial);
                }
                else
                {
                    appendProblems(instance, i, schema, ref partialProblemInstances);
                }
            }
        }
        private void solvePossibleMinCountSetsRec(DVRPProblemInstance instance, int i, int set, int j,
                                                  ref List <DVRPPartialProblemInstance> solutions, List <int>[] currVisits, int[] lastIds)
        {
            if (j > i)
            {
                throw new Exception("Something went wrong");
            }
            if (j == i)
            {
                if (set < instance.VehicleNumber - 1)
                {
                    solvePossibleMinCountSetsRec(instance, i, set + 1, 0, ref solutions, currVisits, lastIds);
                    return;
                }
                else
                {
                    var newSol = new DVRPPartialProblemInstance();
                    newSol.PartialResult   = double.MaxValue;
                    newSol.SolutionResult  = SolutionResult.Impossible;
                    newSol.MinimalSetCount = i;
                    //uzyskaliśmy podział, przepisanie do szkieletu zadania
                    newSol.VisitIds = new int[currVisits.Length][];
                    for (var k = 0; k < currVisits.Length; k++)
                    {
                        newSol.VisitIds[k] = new int[currVisits[k].Count];
                        for (var s = 0; s < currVisits[k].Count; s++)
                        {
                            newSol.VisitIds[k][s] = currVisits[k][s];
                        }
                    }
                    solutions.Add(newSol);
                    return;
                }
            }

            for (var k = 0; k < lastIds.Length; k++)
            {
                if (lastIds[k] != -1)
                {
                    if ((set > 0 && j == 0 && currVisits[set - 1].Last() > lastIds[k]) ||
                        (!(set == 0 && j == 0) && (instance.Visits[k].Id < currVisits[0][0] ||
                                                   (currVisits[set].Count > 0 && currVisits[set].Last() > instance.Visits[k].Id) ||
                                                   (currVisits[0].Count > 0 && currVisits[0][0] > instance.Visits[k].Id))))
                    {
                        continue;
                    }
                    var id = lastIds[k];
                    currVisits[set].Add(id);
                    lastIds[k] = -1;
                    solvePossibleMinCountSetsRec(instance, i, set, j + 1, ref solutions, currVisits, lastIds);
                    lastIds[k] = id;
                    currVisits[set].Remove(id);
                }
            }
        }
        private void generateSetsRec(DVRPProblemInstance instance, ref DVRPPartialProblemInstance solution,
                                     int i, List <int>[] currVisits, int clast, int cunign, int[] unignoredSets,
                                     int[] lastIds, int minSet, int unignoredCount)
        {
            if (clast < unignoredCount - cunign)
            {
                return;
            }
            if (clast == 0 && cunign < unignoredCount)
            {
                return;
            }
            if (clast == 0)
            {
                minimizeSolution(instance, ref solution, currVisits);
                return;
            }

            for (var k = minSet; k < unignoredSets.Length; k++)
            {
                if (currVisits[unignoredSets[k]].Count == i && cunign == unignoredCount)
                {
                    continue;
                }
                if (k > 0 && currVisits[unignoredSets[k - 1]].Count == i)
                {
                    return;
                }

                for (var t = 0; t < lastIds.Length; t++)
                {
                    if (lastIds[t] == -1)
                    {
                        continue;
                    }
                    if (currVisits[unignoredSets[k]].Count > i && currVisits[unignoredSets[k]].Last() > lastIds[t])
                    {
                        continue;
                    }
                    if (k > 0 && currVisits[unignoredSets[k - 1]][0] > lastIds[t])
                    {
                        break;
                    }
                    var add = currVisits[unignoredSets[k]].Count == i ? (byte)1 : (byte)0;
                    currVisits[unignoredSets[k]].Add(lastIds[t]);
                    var tmp = lastIds[t];
                    lastIds[t] = -1;
                    generateSetsRec(instance, ref solution, i, currVisits,
                                    clast - 1, cunign + add, unignoredSets, lastIds, k, unignoredCount);
                    lastIds[t] = tmp;
                    currVisits[unignoredSets[k]].Remove(lastIds[t]);
                }
            }
        }
        private void solveInParallel(DVRPProblemInstance instance, ref DVRPPartialProblemInstance finalSolution)
        {
            var solQueue = new ConcurrentQueue <DVRPPartialProblemInstance>();
            //dwa wątki - lub jeden
            List <Thread> threads = new List <Thread>();

            foreach (var number in finalSolution.IgnoredSets)
            {
                var currSolution = new DVRPPartialProblemInstance();
                int i            = finalSolution.MinimalSetCount;
                solutionCopyTo(finalSolution, ref currSolution);
                currSolution.IgnoredSets = new[] { number };
                var thread =
                    new Thread(t =>
                {
                    if (i == 0)
                    {    //different behaviour (generate sets in loop)
                        solveForZero(instance, ref currSolution, number);
                    }
                    else if (i * instance.VehicleNumber == instance.Visits.Count)
                    {
                        instantMinimization(instance, ref currSolution);
                    }     //nothing to do, but generate sets:
                    else
                    {
                        generateIgnoredSets(instance, ref currSolution, i, number);
                    }

                    solQueue.Enqueue(currSolution);
                });

                threads.Add(thread);
                thread.Start();
            }
            foreach (var thread in threads)
            {
                thread.Join();
            }
            int k   = 0;
            int min = 0;

            foreach (var sol in solQueue)
            {
                if (sol.PartialResult < finalSolution.PartialResult)
                {
                    min = k;
                }
                k++;
            }
            solutionCopyTo(solQueue.ElementAt(min), ref finalSolution);
        }
        private void solveForZeroRec(DVRPProblemInstance instance, ref DVRPPartialProblemInstance solution,
                                     List <int>[] currVisits, int[] lastIds, int i, int number, int visitsToAssign, int setsToAssign,
                                     int minSet, int assigned)
        {
            if (setsToAssign > visitsToAssign)
            {
                return;
            }
            if (visitsToAssign == 0)
            {
                minimizeSolution(instance, ref solution, currVisits);
                return;
            }

            for (var k = minSet; k < number; k++)
            {
                assigned = 0;
                if (k > 0 && currVisits[k - 1].Count == i)
                {
                    return;
                }
                if (setsToAssign == visitsToAssign && currVisits[k].Count != i)
                {
                    continue;
                }

                for (var t = assigned; t < lastIds.Length; t++)
                {
                    if (lastIds[t] == -1)
                    {
                        continue;
                    }
                    if (currVisits[k].Count > i && currVisits[k].Last() > lastIds[t])
                    {
                        continue;
                    }
                    if (k > 0 && currVisits[k - 1][0] > lastIds[t])
                    {
                        break;
                    }
                    var add = currVisits[k].Count == i ? (byte)1 : (byte)0;
                    currVisits[k].Add(lastIds[t]);
                    var tmp = lastIds[t];
                    lastIds[t] = -1;
                    solveForZeroRec(instance, ref solution, currVisits, lastIds, i,
                                    number, visitsToAssign - 1, setsToAssign - add, k, t);
                    lastIds[t] = tmp;
                    currVisits[k].Remove(lastIds[t]);
                }
            }
        }
        private void instantMinimization(DVRPProblemInstance instance, ref DVRPPartialProblemInstance solution)
        {
            double newCost = 0f;

            for (var j = 0; j < instance.VehicleNumber; j++)
            {
                var cvref    = solution.VisitIds[j];
                var currCost = minimizePermutation(instance, ref cvref);
                if (currCost < 0f)
                {
                    var s = solutionImpossible();
                    solutionCopyTo(s, ref solution);
                    return;
                }
                newCost += currCost;
            }
            solution.PartialResult  = newCost;
            solution.SolutionResult = SolutionResult.Successful;
        }
 private void generateIgnoredSetsRec(DVRPProblemInstance instance,
                                     ref DVRPPartialProblemInstance solution, int i, int ignoredCount, int[] ignoredSets, int howmany)
 {
     if (howmany == ignoredCount)
     {
         generateSets(instance, i, ref solution, ignoredSets);
     }
     else
     {
         for (var j = 0; j < instance.VehicleNumber; j++)
         {
             if (howmany > 0 && ignoredSets[howmany - 1] > j)
             {
                 return;
             }
             ignoredSets[howmany] = j;
             generateIgnoredSetsRec(instance, ref solution, i, ignoredCount, ignoredSets, howmany + 1);
         }
     }
 }
 private void solutionCopyTo(DVRPPartialProblemInstance a, ref DVRPPartialProblemInstance b)
 {
     if (a.IgnoredSets != null)
     {
         b.IgnoredSets = new int[a.IgnoredSets.Length];
         a.IgnoredSets.CopyTo(b.IgnoredSets, 0);
     }
     b.MinimalSetCount = a.MinimalSetCount;
     b.SolutionResult  = a.SolutionResult;
     b.PartialResult   = a.PartialResult;
     if (a.VisitIds == null)
     {
         return;
     }
     b.VisitIds = new int[a.VisitIds.GetLength(0)][];
     for (int i = 0; i < a.VisitIds.GetLength(0); i++)
     {
         b.VisitIds[i] = new int[a.VisitIds[i].Length];
         a.VisitIds[i].CopyTo(b.VisitIds[i], 0);
     }
 }
        private void solveForZero(DVRPProblemInstance instance, ref DVRPPartialProblemInstance currSolution,
                                  int number)
        {
            var clast = instance.Visits.Count;

            var currVisits = new List <int> [instance.VehicleNumber];

            for (int e = 0; e < instance.VehicleNumber; e++)
            {
                currVisits[e] = new List <int>();
            }

            var lastIds = new int[instance.Visits.Count];

            for (var s = 0; s < instance.Visits.Count; s++)
            {
                lastIds[s] = instance.Visits[s].Id;
            }

            solveForZeroRec(instance, ref currSolution, currVisits, lastIds, currSolution.MinimalSetCount,
                            number, clast, number, 0, 0);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="instance">instance</param>
        /// <param name="i">minimal set count</param>
        /// <param name="solution">reference with visit ids permuted</param>
        /// <param name="ignoredCount">number of sets to ignore</param>
        private void generateSets(DVRPProblemInstance instance, int i, ref DVRPPartialProblemInstance solution,
                                  int[] ignoredSets)
        {
            //dodawaj klientów z nawrotami do zbiorów currVisits takich, że nie należą do y-greków
            //uważaj na powtórzenia
            var clast         = instance.Visits.Count - i * instance.VehicleNumber;
            var cval          = 0;
            var unignoredSets = Enumerable.Range(0, instance.VehicleNumber)
                                .Where(x => !ignoredSets.Contains(x)).ToArray();
            var currVisits = new List <int> [instance.VehicleNumber];

            for (int e = 0; e < instance.VehicleNumber; e++)
            {
                currVisits[e] = new List <int>();
                for (int f = 0; f < solution.VisitIds[e].Length; f++)
                {
                    currVisits[e].Add(solution.VisitIds[e][f]);
                }
            }
            var lastIds = new int[instance.Visits.Count];

            for (var s = 0; s < instance.Visits.Count; s++)
            {
                if (currVisits.Any(x => x.Contains(instance.Visits[s].Id)))
                {
                    lastIds[s] = -1;
                }
                else
                {
                    lastIds[s] = instance.Visits[s].Id;
                }
            }

            generateSetsRec(instance, ref solution, i, currVisits, clast, cval, unignoredSets,
                            lastIds, 0, unignoredSets.Count());
        }
 private void generateIgnoredSets(DVRPProblemInstance instance, ref DVRPPartialProblemInstance solution,
                                  int i, int ignoredCount)
 {
     int[] ignoredSets = Enumerable.Repeat(-1, instance.VehicleNumber).ToArray();
     generateIgnoredSetsRec(instance, ref solution, i, ignoredCount, ignoredSets, 0);
 }