示例#1
0
 public AgentState(AgentState copy)
 {
     this.agent       = copy.agent;
     this.h           = copy.h;
     this.arrivalTime = copy.arrivalTime;
     this.lastMove    = new TimedMove(copy.lastMove); // Can we just do this.lastMove = copy.lastMove? I think we can now, since MoveTo replaces the move
 }
示例#2
0
        public HashSet <CFMCbsConstraint> GetConstraints()
        {
            var              constraints       = new HashSet <CFMCbsConstraint>();
            CFMCbsNode       current           = this;
            CFMCbsConstraint currentConstraint = null;

            while (current.depth > 0)                                              // The root has no constraints
            {
                if (current.constraint != null &&                                  // Next check not enough if "surprise merges" happen (merges taken from adopted child)
                    current.prev.conflict != null &&                               // Can only happen for temporary lookahead nodes the were created and then later the parent adopted a goal node
                    this.agentsGroupAssignment[current.prev.conflict.agentAIndex] !=
                    this.agentsGroupAssignment[current.prev.conflict.agentBIndex]) // Ignore constraints that deal with conflicts between
                // agents that were later merged. They're irrelevant
                // since merging fixes all conflicts between merged agents.
                // Nodes that only differ in such irrelevant conflicts will have the same single agent paths.
                // Dereferencing current.prev is safe because current isn't the root.
                // Also, merging creates a non-root node with a null constraint, and this helps avoid adding the null to the answer.

                {
                    currentConstraint = current.constraint;
                }
                TimedMove        currentMove   = current.constraint.move;
                CFMCbsConstraint newConstraint = new CFMCbsConstraint(currentConstraint.agentNum, currentMove.x, currentMove.y, currentMove.direction, currentMove.time);
                constraints.Add(newConstraint);

                current = current.prev;
            }
            return(constraints);
        }
        // Summary:
        //     Gets the element that has the specified key in the read-only dictionary.
        //
        // Parameters:
        //   key:
        //     The key to locate.
        //
        // Returns:
        //     The element that has the specified key in the read-only dictionary.
        //
        // Exceptions:
        //   System.ArgumentNullException:
        //     key is null.
        //
        //   System.Collections.Generic.KeyNotFoundException:
        //     The property is retrieved and key is not found.
        public List <int> this[TimedMove key]
        {
            get
            {
                List <int> ans = null;
                if (this.timedMovesToAgentNumList.ContainsKey(key))
                {
                    ans = new List <int>(this.timedMovesToAgentNumList[key].Count + 1);
                    ans.AddRange(this.timedMovesToAgentNumList[key]);
                }

                queryMove.setup(key);
                if (this.atGoalWaitsToTimeAndAgentNum.ContainsKey(queryMove))
                {
                    var timeAndAgentNum = this.atGoalWaitsToTimeAndAgentNum[queryMove];
                    if (key.time >= timeAndAgentNum.Item1)
                    {
                        if (ans == null)
                        {
                            ans = new List <int>(1);
                        }
                        ans.Add(timeAndAgentNum.Item2);
                    }
                }

                if (ans != null)
                {
                    return(ans);
                }
                else
                {
                    return(ConflictAvoidanceTable.emptyList);
                }
            }
        }
        Dictionary <Move, Tuple <int, int> > atGoalWaitsToTimeAndAgentNum   = new Dictionary <Move, Tuple <int, int> >(); // No need for a list of agent nums because goals can't collide :)

        public void AddPlan(SinglePlan plan)
        {
            int planSize = plan.GetSize();

            for (int i = 0; i < planSize; i++)
            {
                Move      temp = plan.GetLocationAt(i);
                TimedMove step;
                if (temp.GetType() == typeof(TimedMove))
                {
                    step = (TimedMove)temp;
                }
                else
                {
                    step = new TimedMove(temp, i); // TODO: Avoid creating new objects when possible. Make the method return correctly timed moves.
                }
                if (this.timedMovesToAgentNumList.ContainsKey(step) == false)
                {
                    this.timedMovesToAgentNumList[step] = new List <int>(1); // THIS IS ON THE HOT PATH! ~11% of time is passed on this line!
                }
                this.timedMovesToAgentNumList[step].Add(plan.agentNum);
            }

            Move lastMove = plan.GetLocationAt(planSize - 1);
            Move goal     = new Move(lastMove.x, lastMove.y, Move.Direction.Wait);

            this.atGoalWaitsToTimeAndAgentNum.Add(goal, new Tuple <int, int>(planSize, plan.agentNum));
        }
示例#5
0
        private bool closed
        (
            MAM_AgentState child
        )
        {
            TimedMove timedChildMove = child.lastMove;
            Move      childMove      = new Move(timedChildMove.x, timedChildMove.y, Move.Direction.NO_DIRECTION);

            if (!closedList.ContainsKey(childMove)) // Child is not in the closed list
            {
                closedList.Add(childMove, new Dictionary <int, Dictionary <int, MAM_AgentState> >());
                Dictionary <int, MAM_AgentState> moveAgentDiffTimes = new Dictionary <int, MAM_AgentState>();
                moveAgentDiffTimes.Add(timedChildMove.time, child);
                closedList[childMove].Add(child.agentIndex, moveAgentDiffTimes);
                return(false);
            }
            else if (!closedList[childMove].Keys.Contains(child.agentIndex)) // Child is not in the closed list for this agent
            {
                Dictionary <int, MAM_AgentState> moveAgentDiffTimes = new Dictionary <int, MAM_AgentState>();
                moveAgentDiffTimes.Add(timedChildMove.time, child);
                closedList[childMove].Add(child.agentIndex, moveAgentDiffTimes);
                return(false);
            }
            else if (!closedList[childMove][child.agentIndex].Keys.Contains(timedChildMove.time)) // Child is in the closed list for this agent, but not for this time
            {
                Dictionary <int, MAM_AgentState> moveAgentDiffTimes = closedList[childMove][child.agentIndex];
                moveAgentDiffTimes.Add(timedChildMove.time, child);
                //closedList[childMove].Add(child.agentIndex, moveAgentDiffTimes);
                return(false);
            }
            return(true);
        }
示例#6
0
        /// <summary>
        /// Updates the conflicts member according to given CATs. Both tables may be null.
        /// </summary>
        /// <param name="ID_CAT"></param>
        /// <param name="CBS_CAT"></param>
        public void SetConflicts(Dictionary <TimedMove, List <int> > ID_CAT, Dictionary <TimedMove, List <int> > CBS_CAT)
        {
            TimedMove queryMove = new TimedMove();

            if (this.prevStep == null)
            {
                return;
            }
            for (int i = 0; i < allSteps.Length; i++)
            {
                // TODO: Kill this code dup. The ConflictAvoidanceTable class takes care of it.
                queryMove.setup(allSteps[i].move.x, allSteps[i].move.y, Move.Direction.NO_DIRECTION, allSteps[i].move.time);
                if (ID_CAT != null && ID_CAT.ContainsKey(queryMove))
                {
                    conflicts++;
                }
                if (CBS_CAT != null && CBS_CAT.ContainsKey(queryMove))
                {
                    conflicts++;
                }
                queryMove.direction = allSteps[i].move.direction;
                queryMove.setOppositeMove();
                if (ID_CAT != null && ID_CAT.ContainsKey(queryMove))
                {
                    conflicts++;
                }
                if (CBS_CAT != null && CBS_CAT.ContainsKey(queryMove))
                {
                    conflicts++;
                }
            }
        }
示例#7
0
        public new TimedMove GetMoveWithoutDirection()
        {
            TimedMove copy = new TimedMove(this);

            copy.direction = Direction.NO_DIRECTION;
            return(copy);
        }
示例#8
0
        /// <summary>
        /// Updates the agent's last move with the given move and sets arrivalTime (at goal) if necessary.
        /// </summary>
        public void MoveTo(TimedMove move)
        {
            this.lastMove = move;

            bool isWait = move.direction == Move.Direction.Wait;
            bool atGoal = this.AtGoal();

            // If performed a non WAIT move and reached the agent's goal - store the arrival time
            if (atGoal && (isWait == false))
            {
                this.arrivalTime = move.time;
            }

            if (Constants.Variant == Constants.ProblemVariant.ORIG)
            {
                if (this.AtGoal())
                {
                    this.g = this.arrivalTime;
                }
                else
                {
                    this.g = this.lastMove.time;
                }
            }
            else if (Constants.Variant == Constants.ProblemVariant.NEW)
            {
                if ((atGoal && isWait) == false)
                {
                    this.g += 1;
                }
            }
        }
示例#9
0
        public void setConflicts(HashSet <TimedMove> ID_CAT, HashSet_U <TimedMove> CBS_CAT)
        {
            TimedMove m2 = new TimedMove();

            if (this.prevStep == null)
            {
                return;
            }
            for (int i = 0; i < allSteps.Length; i++)
            {
                m2.setup(allSteps[i].getX(), allSteps[i].getY(), Move.Direction.NO_DIRECTION, getDepth());
                if (ID_CAT != null && ID_CAT.Contains(m2))
                {
                    conflicts++;
                }
                if (CBS_CAT != null && CBS_CAT.Contains(m2))
                {
                    conflicts++;
                }
                m2.direction = Move.getDirection(allSteps[i].getX(), allSteps[i].getY(), prevStep.allSteps[i].getX(), prevStep.allSteps[i].getY());
                m2.setOppositeMove();
                if (ID_CAT != null && ID_CAT.Contains(m2))
                {
                    conflicts++;
                }
                if (CBS_CAT != null && CBS_CAT.Contains(m2))
                {
                    conflicts++;
                }
            }
        }
示例#10
0
 private bool compareTimedMoves(TimedMove A, TimedMove B)
 {
     if (A.x == B.x && A.y == B.y && A.time == B.time)
     {
         return(true);
     }
     return(false);
 }
示例#11
0
 public bool ViolatesMustConstraint(byte agent, TimedMove move)
 {
     if (this.agentNum != agent)
     {
         return(false);
     }
     return(this.move.Equals(move) == false);
 }
示例#12
0
        /// <summary>
        /// Updates the agent's last move with the given move and sets arrivalTime (at goal) if necessary.
        /// </summary>
        public void MoveTo(TimedMove move)
        {
            this.lastMove = move;

            // If performed a non WAIT move and reached the agent's goal - store the arrival time
            if ((move.direction != Move.Direction.Wait) && (this.AtGoal()))
            {
                this.arrivalTime = move.time;
            }
        }
示例#13
0
        /// <summary>
        /// The returned plan wasn't constructed considering a CAT, so it's possible there's an alternative plan with the same cost and less collisions.
        /// </summary>
        /// <param name="agentState"></param>
        /// <returns></returns>
        public SinglePlan GetSingleAgentOptimalPlan(AgentState agentState,
                                                    out Dictionary <int, int> conflictCountPerAgent, out Dictionary <int, List <int> > conflictTimesPerAgent, out Dictionary <int, List <int> > conflictTimesBiasPerAgent, int conflictRange = 0)
        {
            LinkedList <Move> moves = new LinkedList <Move>();
            int agentNum            = agentState.agent.agentNum;
            var conflictCounts      = new Dictionary <int, int>();
            var conflictTimes       = new Dictionary <int, List <int> >();
            var conflictTimesBias   = new Dictionary <int, List <int> >();
            var conflictProbability = new Dictionary <int, List <double> >();
            IReadOnlyDictionary <TimedMove, List <int> > CAT;

            if (this.parameters.ContainsKey(CBS_LocalConflicts.CAT)) // TODO: Add support for IndependenceDetection's CAT
            {
                CAT = ((IReadOnlyDictionary <TimedMove, List <int> >) this.parameters[CBS_LocalConflicts.CAT]);
            }
            else
            {
                CAT = new Dictionary <TimedMove, List <int> >();
            }

            //for(int tempTime = 0 ; tempTime < agentState.)

            TimedMove current           = agentState.lastMove; // The starting position
            int       time              = current.time;
            int       timeWithoutDelays = 0;

            while (true)
            {
                moves.AddLast(current);
                if (current.direction != Move.Direction.NO_DIRECTION &&
                    current.direction != Move.Direction.Wait)
                {
                    timeWithoutDelays++;
                }
                // Count conflicts:
                current.UpdateConflictCounts(CAT, conflictCounts, conflictTimes, conflictTimesBias, conflictRange);

                if (agentState.agent.Goal.Equals(current))
                {
                    break;
                }

                // Get next optimal move
                time++;
                Move optimal = this.singleAgentOptimalMoves[agentNum][this.GetCardinality(current)];
                current = new TimedMove(optimal, time);
            }

            conflictCountPerAgent     = conflictCounts;
            conflictTimesPerAgent     = conflictTimes;
            conflictTimesBiasPerAgent = conflictTimesBias;
            return(new SinglePlan(moves, agentNum));
        }
示例#14
0
 public MAM_AgentState
 (
     int pos_X,
     int pos_Y,
     int agentIndex,
     int time
 )
 {
     this.lastMove   = new TimedMove(pos_X, pos_Y, Move.Direction.NO_DIRECTION, time);
     this.agentIndex = agentIndex;
     this.heuristics = new List <double>();
 }
 //
 // Summary:
 //     Gets the value that is associated with the specified key.
 //
 // Parameters:
 //   key:
 //     The key to locate.
 //
 //   value:
 //     When this method returns, the value associated with the specified key, if
 //     the key is found; otherwise, the default value for the type of the value
 //     parameter. This parameter is passed uninitialized.
 //
 // Returns:
 //     true if the object that implements the System.Collections.Generic.IReadOnlyDictionary<TKey,TValue>
 //     interface contains an element that has the specified key; otherwise, false.
 //
 // Exceptions:
 //   System.ArgumentNullException:
 //     key is null.
 public bool TryGetValue(TimedMove key, out List <int> value)
 {
     if (this.ContainsKey(key))
     {
         value = this[key];
         return(true);
     }
     else
     {
         value = null;
         return(false);
     }
 }
示例#16
0
文件: MDD.cs 项目: shimritproj/cbs
 public MDDNode(TimedMove move, int numOfAgents, MDD father)
 {
     this.move         = move;
     this.father       = father;
     setUntil          = 0;
     children          = new LinkedList <MDDNode>();
     parents           = new LinkedList <MDDNode>();
     coexistLinkedList = new LinkedList <MDDNode> [numOfAgents];
     for (int i = 0; i < numOfAgents; i++)
     {
         coexistLinkedList[i] = new LinkedList <MDDNode>();
     }
 }
 public MMStarConstraint(int agentNum, int posX, int posY, Move.Direction direction, int timeStep)
 {
     this.move     = new TimedMove(posX, posY, direction, timeStep);
     this.agentNum = agentNum;
     if (direction == Move.Direction.NO_DIRECTION)
     {
         this.vertexConflict = true;
     }
     else
     {
         this.vertexConflict = false;
     }
 }
示例#18
0
 /// <summary>
 /// TODO: Get rid of the else
 /// </summary>
 /// <param name="time"></param>
 /// <returns></returns>
 public Move GetLocationAt(int time)
 {
     if (time < this.locationAtTimes.Count)
     {
         return(this.locationAtTimes[time]);
     }
     else
     {
         var rest = new TimedMove(this.locationAtTimes[this.locationAtTimes.Count - 1], time);
         rest.direction = Move.Direction.Wait;
         return(rest);
     }
 }
示例#19
0
 public MAM_AgentState
 (
     MAM_AgentState copy
 )
 {
     this.agentIndex = copy.agentIndex;
     this.lastMove   = copy.lastMove;
     this.g          = copy.g;
     this.h          = copy.h;
     this.f          = copy.f;
     this.prev       = copy.prev;
     this.heuristics = new List <double>(copy.heuristics);
     this.numOfAgentsInBestHeuristic = copy.numOfAgentsInBestHeuristic;
 }
示例#20
0
 public MDDNode(TimedMove move, int numOfAgents, MDD mdd, bool supportPruning = true)
 {
     this.move = move;
     this.mdd  = mdd;
     children  = new LinkedList <MDDNode>();
     parents   = new LinkedList <MDDNode>();
     if (supportPruning)
     {
         coexistLinkedList = new LinkedList <MDDNode> [numOfAgents];
         for (int i = 0; i < numOfAgents; i++)
         {
             coexistLinkedList[i] = new LinkedList <MDDNode>();
         }
     }
 }
示例#21
0
 private void printTimedMove(TimedMove mv1, TimedMove mv2, int Agent)
 {
     if (mv1 == null)
     {
         Console.WriteLine("Agent: " + Agent + ", At A: null, At B: " + timedMoveString(mv2));
     }
     else if (mv2 == null)
     {
         Console.WriteLine("Agent: " + Agent + ", At A: " + timedMoveString(mv1) + ", At B: null");
     }
     else if (!compareTimedMoves(mv1, mv2))
     {
         Console.WriteLine("Agent: " + Agent + ", At A: " + timedMoveString(mv1) + ", At B: " + timedMoveString(mv2));
     }
 }
示例#22
0
        private Dictionary <int, Dictionary <int, TimedMove> > conflictAvoidanceToDictionary(IReadOnlyDictionary <TimedMove, List <int> > conflictAvoidance, int maxPlan)
        {
            int count = 0;
            Dictionary <int, Dictionary <int, TimedMove> > newDic = new Dictionary <int, Dictionary <int, TimedMove> >();

            foreach (KeyValuePair <TimedMove, List <int> > t in conflictAvoidance)
            {
                count++;
            }
            //if (count > 29)
            //    Console.WriteLine("");
            if (conflictAvoidance.Keys == null)
            {
                return(newDic);
            }
            foreach (KeyValuePair <TimedMove, List <int> > t in conflictAvoidance)
            {
                foreach (int agentIndex in t.Value)
                {
                    if (!newDic.Keys.Contains(agentIndex))
                    {
                        newDic[agentIndex] = new Dictionary <int, TimedMove>();
                    }
                    if (!newDic[agentIndex].Keys.Contains(t.Key.time))
                    {
                        newDic[agentIndex].Add(t.Key.time, t.Key);
                    }
                }
            }
            foreach (int agent in newDic.Keys)
            {
                int       currentMax = 0;
                TimedMove lastMove   = null;
                foreach (int time in newDic[agent].Keys)
                {
                    if (currentMax <= time)
                    {
                        currentMax = time;
                        lastMove   = newDic[agent][time];
                    }
                }
                for (int i = currentMax + 1; i < maxPlan; i++)
                {
                    newDic[agent].Add(i, new TimedMove(lastMove));
                }
            }
            return(newDic);
        }
示例#23
0
        /// <summary>
        /// Also checks if the move is illegal
        /// </summary>
        /// <param name="toCheck"></param>
        /// <returns></returns>
        public bool IsValid(TimedMove toCheck)
        {
            if (IsValidTile(toCheck.x, toCheck.y) == false)
            {
                return(false);
            }

            if (parameters.ContainsKey("ID-reserved"))
            {
                var reserved = (HashSet <TimedMove>)parameters["ID-reserved"];

                return(toCheck.IsColliding(reserved) == false);
            }

            return(true);
        }
示例#24
0
        /// <summary>
        /// Also checks if the move is illegal
        /// </summary>
        /// <param name="toCheck"></param>
        /// <returns></returns>
        public bool IsValid(TimedMove toCheck)
        {
            if (IsValidTile(toCheck.x, toCheck.y) == false)
            {
                return(false);
            }

            if (parameters.ContainsKey(IndependenceDetection.ILLEGAL_MOVES_KEY))
            {
                var reserved = (HashSet <TimedMove>)parameters[IndependenceDetection.ILLEGAL_MOVES_KEY];

                return(toCheck.IsColliding(reserved) == false);
            } // FIXME: Should this be here?

            return(true);
        }
示例#25
0
        }                                                                             // Nonsense values until Init, just allocate move

        public CbsConstraint(CbsConflict conflict, ProblemInstance instance, bool agentA, Run.ConstraintPolicy constraintPolicy = Run.ConstraintPolicy.Single, int constraintRange = 0)
        {
            Move move;
            int  agentNum;
            int  minTime;

            this.constaintRange = Math.Abs(conflict.timeStepAgentB - conflict.timeStepAgentA);
            if (constraintPolicy == Run.ConstraintPolicy.Range)
            {
                minTime = Math.Min(conflict.timeStepAgentA, conflict.timeStepAgentB);
            }
            else if (constraintPolicy == Run.ConstraintPolicy.DoubleRange)
            {
                minTime = conflict.timeStepAgentA;
            }
            else
            {
                if (agentA)
                {
                    minTime = conflict.timeStepAgentA;
                }
                else
                {
                    minTime = conflict.timeStepAgentB;
                }
            }
            if (agentA)
            {
                move      = conflict.agentAmove;
                agentNum  = instance.m_vAgents[conflict.agentAIndex].agent.agentNum;
                this.move = new TimedMove(move, minTime);
            }
            else
            {
                move      = conflict.agentBmove;
                agentNum  = instance.m_vAgents[conflict.agentBIndex].agent.agentNum;
                this.move = new TimedMove(move, minTime);
            }

            this.agentNum = (byte)agentNum;


            if (conflict.vertex)
            {
                this.move.direction = Move.Direction.NO_DIRECTION;
            }
        }
示例#26
0
文件: Plan.cs 项目: shimritproj/cbs
 public void AddPlanToCAT(IDictionary <TimedMove, List <int> > addTo, int until)
 {
     for (int i = 0; i <= until; i++)
     {
         TimedMove step = new TimedMove(this.GetLocationAt(i), i); // TODO: Avoid creating new objects. Make the method return correctly timed moves.
         if (addTo.ContainsKey(step))
         {
             addTo[step].Add(this.agentIndex);
         }
         else
         {
             var agentList = new List <int>();
             agentList.Add(this.agentIndex);
             addTo.Add(step, agentList);
         }
     }
 }
示例#27
0
        private LinkedList <List <Move> > copyLinkedList(LinkedList <List <Move> > toCopy)
        {
            LinkedList <List <Move> >     newLinkedList = new LinkedList <List <Move> >();
            LinkedListNode <List <Move> > node          = toCopy.First;

            while (node != null)
            {
                List <Move> newList = new List <Move>();
                foreach (Move mv in node.Value)
                {
                    Move newMove = new TimedMove((TimedMove)mv);
                    newList.Add(newMove);
                }
                newLinkedList.AddLast(newList);
                node = node.Next;
            }
            return(newLinkedList);
        }
        // Summary:
        //     Determines whether the read-only dictionary contains an element that has
        //     the specified key.
        //
        // Parameters:
        //   key:
        //     The key to locate.
        //
        // Returns:
        //     true if the read-only dictionary contains an element that has the specified
        //     key; otherwise, false.
        //
        // Exceptions:
        //   System.ArgumentNullException:
        //     key is null.
        public bool ContainsKey(TimedMove key)
        {
            if (this.timedMovesToAgentNumList.ContainsKey(key))
            {
                return(true);
            }

            queryMove.setup(key);
            if (this.atGoalWaitsToTimeAndAgentNum.ContainsKey(queryMove))
            {
                var timeAndAgentNum = this.atGoalWaitsToTimeAndAgentNum[queryMove];
                if (key.time >= timeAndAgentNum.Item1)
                {
                    return(true);
                }
            }
            return(false);
        }
示例#29
0
        /// <summary>
        /// The returned plan wasn't constructed considering a CAT, so it's possible there's an alternative plan with the same cost and less collisions.
        /// </summary>
        /// <param name="agentState"></param>
        /// <returns></returns>
        public SinglePlan GetSingleAgentOptimalPlan(AgentState agentState,
                                                    out Dictionary <int, int> conflictCountPerAgent, out Dictionary <int, List <int> > conflictTimesPerAgent)
        {
            LinkedList <Move> moves = new LinkedList <Move>();
            int agentNum            = agentState.agent.agentNum;
            var conflictCounts      = new Dictionary <int, int>();
            var conflictTimes       = new Dictionary <int, List <int> >();
            IReadOnlyDictionary <TimedMove, List <int> > CAT;

            if (this.parameters.ContainsKey(CBS.CAT)) // TODO: Add support for IndependenceDetection's CAT
            {
                CAT = ((IReadOnlyDictionary <TimedMove, List <int> >) this.parameters[CBS.CAT]);
            }
            else
            {
                CAT = new Dictionary <TimedMove, List <int> >();
            }

            TimedMove current = agentState.lastMove; // The starting position
            int       time    = current.time;

            while (true)
            {
                moves.AddLast(current);
                // Count conflicts:
                current.UpdateConflictCounts(CAT, conflictCounts, conflictTimes);

                if (agentState.agent.Goal.Equals(current))
                {
                    break;
                }

                // Get next optimal move
                time++;
                Move optimal = this.singleAgentOptimalMoves[agentNum][this.GetCardinality(current)];
                current = new TimedMove(optimal, time);
            }

            conflictCountPerAgent = conflictCounts;
            conflictTimesPerAgent = conflictTimes;
            return(new SinglePlan(moves, agentNum));
        }
示例#30
0
        /// <summary>
        /// Check if the move is valid, i.e. not colliding into walls or other agents.
        /// This method is here instead of in ProblemInstance to enable algorithmic tweaks.
        /// </summary>
        /// <param name="possibleMove">The move to check if possible</param>
        /// <returns>true, if the move is possible.</returns>
        protected bool IsValid(TimedMove possibleMove, HashSet <TimedMove> currentMoves, int makespan, int agentNum)
        {
            // Check if the proposed move is reserved in the plan of another agent.
            // This is used in Trevor's IndependenceDetection.
            if (this.illegalMoves != null)
            {
                if (possibleMove.IsColliding(illegalMoves))
                {
                    return(false);
                }
            } // FIXME: Also checked in instance.IsValid later.

            if (this.constraintList != null)
            {
                queryConstraint.Init(agentNum, possibleMove);

                if (this.constraintList.Contains(queryConstraint))
                {
                    return(false);
                }
            }

            if (this.mustConstraints != null && makespan < this.mustConstraints.Length && // There may be a constraint on the timestep of the generated node
                this.mustConstraints[makespan] != null)
            {
                if (this.mustConstraints[makespan].Any <CbsConstraint>(
                        con => con.ViolatesMustConstraint((byte)agentNum, possibleMove)))
                {
                    return(false);
                }
            }

            // If the tile is not free (out of the grid or with an obstacle)
            if (this.instance.IsValid(possibleMove) == false)
            {
                return(false);
            }

            // Check against all the agents that have already moved to see if current move collides with their move
            return(possibleMove.IsColliding(currentMoves) == false);
        }