/// <summary>
        /// Prunes the individual agent MDDs and prepares data for matching them
        /// </summary>
        /// <returns>Whether everything was pruned</returns>
        public bool Prune()
        {
            for (int i = allMDDs.Length - 1; i >= 0; i--)
            {
                for (int j = i + 1; j < allMDDs.Length; j++)
                {
                    MDD.PruningDone pruningDone = MDD.PruningDone.NOTHING;
                    pruningDone = allMDDs[i].SyncMDDs(allMDDs[j], this.syncSize == 3);

                    if (pruningDone == MDD.PruningDone.EVERYTHING)
                    {
                        return(true);
                    }
                }
            }
            if (allMDDs[0].levels == null)
            {
                return(true);
            }
            return(false);
        }
        public override SinglePlan[] Solve(ConflictAvoidanceTable CAT)
        {
            MDD[] match      = new MDD[2];
            bool  Converging = true;

            int[] changed          = new int[allMDDs.Length];
            int   currentIteration = 0;

            MDD.PruningDone conflictStatus = MDD.PruningDone.NOTHING;

            while (Converging)
            {
                currentIteration++;
                Converging = false;

                for (int i = allMDDs.Length - 1; i >= 0; i--)
                {
                    for (int j = i + 1; j < allMDDs.Length; j++)
                    {
                        if (changed[i] >= currentIteration - 1 || changed[j] >= currentIteration - 1) // If at least one of the two MDDs was changed during the last iteration
                        {
                            int matchCounterIncrement;
                            (conflictStatus, matchCounterIncrement) = allMDDs[i].SyncMDDs(allMDDs[j], this.syncSize == 3);
                            this.matchCounter += matchCounterIncrement;

                            if (conflictStatus == MDD.PruningDone.EVERYTHING)
                            {
                                return(null);
                            }

                            else if (conflictStatus == MDD.PruningDone.SOME)
                            {
                                changed[i] = currentIteration;
                                Converging = true;
                            }

                            (conflictStatus, matchCounterIncrement) = allMDDs[i].SyncMDDs(allMDDs[j], this.syncSize == 3);
                            this.matchCounter += matchCounterIncrement;

                            if (conflictStatus == MDD.PruningDone.EVERYTHING)
                            {
                                return(null);
                            }

                            else if (conflictStatus == MDD.PruningDone.SOME)
                            {
                                changed[i] = currentIteration;
                                Converging = true;
                            }
                        }
                    }
                }
            }
            this.solver.survivedPruningHL++;
            if (allMDDs[0].levels == null)
            {
                return(null);
            }
            A_Star_MDDs findSolution = new A_Star_MDDs(allMDDs, runner, CAT);

            SinglePlan[] ans = findSolution.Solve();
            generated           = findSolution.generated;
            expanded            = findSolution.expanded;
            conflictsNotAvoided = findSolution.conflictCount;
            return(ans);
        }
        public override SinglePlan[] Solve(Dictionary <TimedMove, List <int> > conflictTable, Dictionary <TimedMove, List <int> > CBS_CAT)
        {
            MDD[] match      = new MDD[2];
            bool  Converging = true;

            int[] changed          = new int[allMDDs.Length];
            int   currentIteration = 0;

            MDD.PruningDone conflictStatus = MDD.PruningDone.NOTHING;

            while (Converging)
            {
                currentIteration++;
                Converging = false;

                for (int i = allMDDs.Length - 1; i >= 0; i--)
                {
                    for (int j = i + 1; j < allMDDs.Length; j++)
                    {
                        if (changed[i] >= currentIteration - 1 || changed[j] >= currentIteration - 1) // If at least one of the two MDDs was changed during the last iteration
                        {
                            conflictStatus = allMDDs[i].SyncMDDs(allMDDs[j], this.syncSize == 3);

                            if (conflictStatus == MDD.PruningDone.EVERYTHING)
                            {
                                return(null);
                            }

                            else if (conflictStatus == MDD.PruningDone.SOME)
                            {
                                changed[i] = currentIteration;
                                Converging = true;
                            }

                            conflictStatus = allMDDs[i].SyncMDDs(allMDDs[j], this.syncSize == 3);

                            if (conflictStatus == MDD.PruningDone.EVERYTHING)
                            {
                                return(null);
                            }

                            else if (conflictStatus == MDD.PruningDone.SOME)
                            {
                                changed[i] = currentIteration;
                                Converging = true;
                            }
                        }
                    }
                }
            }
            CostTreeSearchSolver.passed++;
            if (allMDDs[0].levels == null)
            {
                return(null);
            }
            AStarMDD findSolution = new AStarMDD(allMDDs, runner, conflictTable, CBS_CAT);

            SinglePlan[] ans = findSolution.Solve();
            generated    = findSolution.generated;
            expanded     = findSolution.expanded;
            caViolations = findSolution.conflictAvoidanceViolations;
            return(ans);
        }