/// <summary>
        /// Solve the group of agents together.
        /// </summary>
        /// <param name="runner"></param>
        /// <param name="CAT"></param>
        /// <param name="group1Cost"></param>
        /// <param name="group2Cost"></param>
        /// <param name="group1Size"></param>
        /// <param name="reserved"></param>
        /// <returns>true if optimal solution for the group of agents were found, false otherwise</returns>
        public bool Solve(Run runner, ConflictAvoidanceTable CAT,
                          int group1Cost = 0, int group2Cost = 0, int group1Size = 1
                          )
        {
            IIndependenceDetectionSolver relevantSolver = this.groupSolver;

            if (this.allAgentsState.Length == 1)
            {
                relevantSolver = this.singleAgentSolver; // TODO: Consider using CBS's root trick to really get single agent paths fast. Though it won't respect illegal moves or avoid conflicts.
            }
            relevantSolver.Setup(this.instance, runner, CAT, group1Cost, group2Cost, group1Size);
            bool solved = relevantSolver.Solve();

            this.solutionCost = relevantSolver.GetSolutionCost();
            if (solved == false)
            {
                return(false);
            }

            // Store the plan found by the solver
            this.plan           = relevantSolver.GetPlan();
            this.singleCosts    = relevantSolver.GetSingleCosts();
            this.expanded       = relevantSolver.GetExpanded();
            this.generated      = relevantSolver.GetGenerated();
            this.solutionDepth  = relevantSolver.GetSolutionDepth();
            this.conflictCounts = relevantSolver.GetExternalConflictCounts();
            this.conflictTimes  = relevantSolver.GetConflictTimes();

            // Clear memory
            relevantSolver.Clear();
            return(true);
        }
        /// <summary>
        /// Tries to find a plan for this group, that will not conflict with the given plan,
        /// and still has the same solution cost as the current solution cost.
        /// This is used in the ImprovedID() method.
        /// </summary>
        /// <param name="planToAvoid"></param>
        /// <param name="runner"></param>
        /// <returns></returns>
        public bool ReplanUnderConstraints(Plan planToAvoid, Run runner, ConflictAvoidanceTable CAT)
        {
            int  oldCost = this.solutionCost;
            Plan oldPlan = this.plan;
            HashSet <TimedMove> reserved = new HashSet <TimedMove>();

            planToAvoid.AddPlanToHashSet(reserved, Math.Max(planToAvoid.GetSize(), this.plan.GetSize()));

            IIndependenceDetectionSolver relevantSolver = this.groupSolver;

            if (this.allAgentsState.Length == 1)
            {
                relevantSolver = this.singleAgentSolver;
            }
            relevantSolver.Setup(this.instance, runner, CAT, oldCost, reserved);
            bool solved = relevantSolver.Solve();

            this.solutionCost = relevantSolver.GetSolutionCost();

            conflictCounts = relevantSolver.GetExternalConflictCounts();
            conflictTimes  = relevantSolver.GetConflictTimes();

            // Store the plan found by the solver
            this.plan           = relevantSolver.GetPlan();
            this.singleCosts    = relevantSolver.GetSingleCosts();
            this.expanded       = relevantSolver.GetExpanded();
            this.generated      = relevantSolver.GetGenerated();
            this.solutionDepth  = relevantSolver.GetSolutionDepth();
            this.conflictCounts = relevantSolver.GetExternalConflictCounts();
            this.conflictTimes  = relevantSolver.GetConflictTimes();

            // Clear memory
            relevantSolver.Clear();

            if (solved == false)
            {
                this.solutionCost = oldCost;
                this.plan         = oldPlan;
            }
            return(solved);
        }