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));
        }
Example #2
0
        public static SinglePlan[] GetSinglePlans(WorldState goalState) // FIXME: Duplication with other methods.
        {
            LinkedList <Move>[] allroutes = new LinkedList <Move> [goalState.allAgentsState.Length];
            for (int i = 0; i < allroutes.Length; i++)
            {
                allroutes[i] = new LinkedList <Move>();
            }

            WorldState currentNode = goalState;

            while (currentNode != null)
            {
                for (int i = 0; i < allroutes.Length; i++)
                {
                    allroutes[i].AddFirst(currentNode.GetSingleAgentMove(i));
                }
                currentNode = currentNode.prevStep;
            }

            SinglePlan[] ans = new SinglePlan[goalState.allAgentsState.Length];
            for (int i = 0; i < ans.Length; i++)
            {
                ans[i] = new SinglePlan(allroutes[i], goalState.allAgentsState[i].agent.agentNum);
            }
            return(ans);
        }
Example #3
0
        private SinglePlan[] GetAnswer(MDDStep finish)
        {
            // TODO: Move the construction of the SinglePlans to a static method in SinglePlan
            var routes = new LinkedList <Move> [problem.Length];

            for (int i = 0; i < routes.Length; i++)
            {
                routes[i] = new LinkedList <Move>();
            }

            MDDStep current = finish;

            while (current != null)
            {
                for (int i = 0; i < problem.Length; i++)
                {
                    routes[i].AddFirst(new Move(current.allSteps[i].move));
                }
                current = current.prevStep;
            }

            var ans = new SinglePlan[problem.Length];

            for (int i = 0; i < ans.Length; i++)
            {
                ans[i] = new SinglePlan(routes[i], i);
            }
            return(ans);
        }
Example #4
0
 /// <summary>
 /// Set the optimal solution of this node as a problem instance.
 /// </summary>
 /// <param name="solution"></param>
 public virtual void SetSolution(SinglePlan[] solution)
 {
     this.singlePlans = SinglePlan.GetSinglePlans(this); // This node may be a partial solution itself, need to start from the real root.
     for (int i = 0; i < solution.Length; ++i)
     {
         this.singlePlans[i].ContinueWith(solution[i]);
     }
 }
Example #5
0
 /// <summary>
 /// Creates SinglePlans with agentIndex as agentNum. Not suitable for subproblems.
 /// </summary>
 /// <param name="allRoutes"></param>
 /// <returns></returns>
 public static SinglePlan[] GetSinglePlans(LinkedList <Move>[] allRoutes)
 {
     SinglePlan[] ans = new SinglePlan[allRoutes.Length];
     for (int i = 0; i < ans.Length; i++)
     {
         ans[i] = new SinglePlan(allRoutes[i], i);
     }
     return(ans);
 }
Example #6
0
        // TODO: Add GetCost and GetMakespan methods!

        public SinglePlan[] GetSinglePlans()
        {
            SinglePlan[] ans = new SinglePlan[this.locationsAtTimes.First().Count];
            for (int i = 0; i < ans.Length; i++)
            {
                ans[i] = new SinglePlan(this, i);
            }
            return(ans);
        }
Example #7
0
 public SinglePlan[] GetSinglePlans()
 {
     if (this.singlePlans != null)
     {
         return(this.singlePlans);
     }
     else
     {
         return(SinglePlan.GetSinglePlans(this));
     }
 }
Example #8
0
        /// <summary>
        /// Check if this plan collides with another plan at a given time
        /// </summary>
        /// <param name="time">The time at which to check if the collision occured</param>
        /// <param name="otherPlan">The plan to check against</param>
        public bool IsColliding(int time, SinglePlan otherPlan)
        {
            Move thisLocation  = this.GetLocationAt(time);
            Move otherLocation = otherPlan.GetLocationAt(time);

            if (thisLocation.IsColliding(otherLocation) == true) // IsColliding isn't virtual,
                                                                 // so it doesn't matter whether the moves are actually TimedMoves
                                                                 // with incorrect time
            {
                return(true);
            }

            return(false);
        }
Example #9
0
        /// <summary>
        /// Add actions of other plan after actions of plan.
        /// If this plan ends where the other starts,
        /// the first timestep of the other plan is skipped
        /// </summary>
        /// <param name="other"></param>
        public void ContinueWith(SinglePlan other)
        {
            bool first = true;

            foreach (Move newLocationAtTime in other.locationAtTimes)
            {
                if (first)
                {
                    first = false;
                    if (this.locationAtTimes[this.locationAtTimes.Count - 1].Equals(newLocationAtTime))
                    {
                        continue;
                    }
                }
                this.locationAtTimes.Add(newLocationAtTime);
            }
        }
Example #10
0
        /// <summary>
        /// Set the optimal solution of this node as a problem instance.
        /// </summary>
        /// <param name="solution"></param>
        public override void SetSolution(SinglePlan[] solution)
        {
            if (this.agentTurn == 0)
            {
                this.singlePlans = SinglePlan.GetSinglePlans(this);
            }
            else
            {
                this.singlePlans = SinglePlan.GetSinglePlans(this.prevStep);
            }
            // ToProblemInstance gives the last proper state as the problem to solve,
            // with must constraints to make the solution go through the steps already
            // taken from there.

            for (int i = 0; i < solution.Length; ++i)
            {
                this.singlePlans[i].ContinueWith(solution[i]);
            }
        }
Example #11
0
        /// <summary>
        /// Add actions of other plan after actions of plan.
        /// If this plan ends where the other starts,
        /// the first timestep of the other plan is skipped
        /// </summary>
        /// <param name="other"></param>
        public void ContinueWith(SinglePlan other)
        {
            bool first = true;

            foreach (Move newLocationAtTime in other.locationAtTimes)
            {
                if (first)
                {
                    first = false;
                    if (this.locationAtTimes[this.locationAtTimes.Count - 1].Equals(newLocationAtTime))
                    {
                        continue;
                    }
                    else
                    {
                        Debug.Assert(false, "Continuing a plan doesn't start from the same state");
                    }
                }
                this.locationAtTimes.Add(newLocationAtTime);
            }
        }
Example #12
0
        /// <summary>
        /// Solves a given problem according to given constraints, sets the plans array (plan per agent).
        /// This method ignores the agentsGroupAssignment and solves for each agent separately using the low level solver,
        /// which is OK because it's only called for the root node.
        /// But on the other hand, it makes merging the method with Replan more difficult.
        /// Can this just call Replan consecutively please?
        /// </summary>
        /// <param name="depthToReplan"></param>
        /// <returns></returns>
        public bool Solve(int depthToReplan)
        {
            this.totalCost = 0;
            var newInternalCAT = new Dictionary <TimedMove, List <int> >();
            HashSet <CbsConstraint> newConstraints = this.GetConstraints(); // Probably empty as this is probably the root of the CT.
            var  internalCAT         = (Dictionary_U <TimedMove, int>)problem.parameters[CBS_LocalConflicts.INTERNAL_CAT];
            var  constraints         = (HashSet_U <CbsConstraint>)problem.parameters[CBS_LocalConflicts.CONSTRAINTS];
            bool haveMustConstraints = problem.parameters.ContainsKey(CBS_LocalConflicts.MUST_CONSTRAINTS) == true &&
                                       ((List <CbsConstraint>)problem.parameters[CBS_LocalConflicts.MUST_CONSTRAINTS]).Count > 0;
            Dictionary <int, int> agentsWithMustConstraints = null; // To quiet the compiler

            if (haveMustConstraints)
            {
                agentsWithMustConstraints = ((List <CbsConstraint>)problem.parameters[CBS_LocalConflicts.MUST_CONSTRAINTS]).Select <CbsConstraint, int>(constraint => constraint.agent).Distinct().ToDictionary <int, int>(x => x); // ToDictionary because there's no ToSet...
            }
            Dictionary <int, int> agentsWithConstraints = null;                                                                                                                                                                     // To quiet the compiler

            constraints.Join(newConstraints);
            internalCAT.Join(newInternalCAT);
            // This mechanism of adding the constraints to the possibly pre-existing constraints allows having
            // layers of CBS solvers, each one adding its own constraints and respecting those of the solvers above it.

            bool haveConstraints = (constraints.Count != 0);

            if (haveConstraints)
            {
                int maxConstraintTimeStep = constraints.Max <CbsConstraint>(constraint => constraint.time);
                depthToReplan         = Math.Max(depthToReplan, maxConstraintTimeStep);                                                                     // Give all constraints a chance to affect the plan
                agentsWithConstraints = constraints.Select <CbsConstraint, int>(constraint => constraint.agent).Distinct().ToDictionary <int, int>(x => x); // ToDictionary because there's no ToSet...
            }
            bool success = true;

            for (int i = 0; i < problem.m_vAgents.Length; i++)
            {
                if (i > 0)
                {
                    // Add existing plans to CAT
                    newInternalCAT.Clear();
                    int maxPlanSize = allSingleAgentPlans.Take <SinglePlan>(i).Max <SinglePlan>(singlePlan => singlePlan.GetSize());
                    for (int j = 0; j < i; j++)
                    {
                        allSingleAgentPlans[j].AddPlanToCAT(newInternalCAT, maxPlanSize);
                    }
                }

                // Solve for a single agent:
                if ((haveConstraints == false ||
                     agentsWithConstraints.ContainsKey(i) == false) &&
                    (haveMustConstraints == false ||
                     agentsWithMustConstraints.ContainsKey(i) == false))           // Top-most CBS with no must constraints on this agent. Shortcut available (ignoring the CAT though)
                {
                    allSingleAgentPlans[i] = new SinglePlan(problem.m_vAgents[i]); // All moves up to starting pos
                    allSingleAgentPlans[i].ContinueWith(this.problem.GetSingleAgentOptimalPlan(problem.m_vAgents[i]));
                    allSingleAgentCosts[i] = problem.m_vAgents[i].g + this.problem.GetSingleAgentOptimalCost(problem.m_vAgents[i]);
                    totalCost += (ushort)allSingleAgentCosts[i];
                }
                else
                {
                    var subGroup = new List <AgentState>();
                    subGroup.Add(problem.m_vAgents[i]);

                    success = this.Replan(i, depthToReplan, newInternalCAT, subGroup);

                    if (!success) // Usually means a timeout occured.
                    {
                        break;
                    }
                }
            }

            internalCAT.Seperate(newInternalCAT);
            constraints.Seperate(newConstraints);

            if (!success)
            {
                return(false);
            }

            this.FindConflict();
            return(true);
        }
Example #13
0
        public override bool Equals(object obj) // TODO: Implement GetHashCode!
        {
            SinglePlan other = (SinglePlan)obj;

            return(this.agentNum == other.agentNum && this.locationAtTimes.SequenceEqual <Move>(other.locationAtTimes));
        }
Example #14
0
 public SinglePlan(SinglePlan cpy)
 {
     this.locationAtTimes = cpy.locationAtTimes.ToList <Move>(); // Behavior change: used to do a deep copy, with cloned moves.
     this.agentNum        = cpy.agentNum;
 }
Example #15
0
        public override bool Equals(object obj)
        {
            SinglePlan other = (SinglePlan)obj;

            return(this.agentIndex == other.agentIndex && this.locationAtTimes.SequenceEqual <Move>(other.locationAtTimes));
        }
Example #16
0
 public SinglePlan[] GetSinglePlans()
 {
     return(SinglePlan.GetSinglePlans(solution));
 }