Esempio n. 1
0
        public virtual void Expand(CbsNode node)
        {
            ushort          parentCost     = node.totalCost;
            ushort          parentH        = node.h;
            IList <CbsNode> children       = null;  // To quiet the compiler
            bool            reinsertParent = false; // To quiet the compiler


            this.ExpandImpl(node, out children, out reinsertParent);


            // Both children considered. None adopted. Add them to the open list, and re-insert the partially expanded parent too if necessary.
            if (reinsertParent)
            {
                this.openList.Add(node); // Re-insert node into open list with higher cost, don't re-increment global conflict counts
            }
            foreach (var child in children)
            {
                closedList.Add(child, child);

                if (child.totalCost == parentCost) // Total cost didn't increase (yet)
                {
                    child.h = parentH;
                }

                if (child.totalCost <= this.maxCost)
                {
                    this.highLevelGenerated++;
                    openList.Add(child);
                }
            }
        }
Esempio n. 2
0
        public virtual void Expand(CbsNode node)
        {
            CbsConflict conflict = node.GetConflict();
            CbsNode     child;

            if (this.mergeThreshold != -1 && ShouldMerge(node))
            {
                child = new CbsNode(node, node.agentsGroupAssignment[conflict.agentA], node.agentsGroupAssignment[conflict.agentB]);
                if (closedList.ContainsKey(child) == false) // We may have already merged these agents in the parent
                {
                    if (debug)
                    {
                        Debug.WriteLine("Merging agents {0} and {1}", conflict.agentA, conflict.agentB);
                    }
                    closedList.Add(child, child);
                    bool success = child.Replan(conflict.agentA, this.minDepth); // or agentB. Doesn't matter - they're in the same group.
                    if (debug)
                    {
                        Debug.WriteLine("New cost: " + child.totalCost);
                        var constraints = child.GetConstraints();
                        Debug.WriteLine(constraints.Count + " Remaining internal constraints:");
                        foreach (CbsConstraint constraint in constraints)
                        {
                            Debug.WriteLine(constraint);
                        }
                        var externalConstraints = (HashSet_U <CbsConstraint>) this.instance.parameters[CBS_LocalConflicts.CONSTRAINTS];
                        Debug.WriteLine(externalConstraints.Count.ToString() + " external constraints: ");
                        foreach (CbsConstraint constraint in externalConstraints)
                        {
                            Debug.WriteLine(constraint);
                        }
                        Debug.WriteLine("New conflict: " + child.GetConflict());
                        Debug.Write("New agent group assignments: ");
                        for (int i = 0; i < child.agentsGroupAssignment.Length; i++)
                        {
                            Debug.Write(" " + child.agentsGroupAssignment[i]);
                        }
                        Debug.WriteLine("");
                        Debug.Write("Single agent costs: ");
                        for (int i = 0; i < child.allSingleAgentCosts.Length; i++)
                        {
                            Debug.Write(" " + child.allSingleAgentCosts[i]);
                        }
                        Debug.WriteLine("");
                        child.CalculateJointPlan().PrintPlan();
                        Debug.WriteLine("");
                        Debug.WriteLine("");
                    }
                    this.maxSizeGroup = Math.Max(this.maxSizeGroup, child.replanSize);

                    if (success == false) // A timeout probably occured
                    {
                        return;
                    }

                    if (node.totalCost <= maxCost) // FIXME: Code dup with other new node creations
                    {
                        openList.Add(child);
                        this.highLevelGenerated++;
                        this.addToGlobalConflictCount(child.GetConflict());
                    }
                }
                else
                {
                    closedListHits++;
                }
                return;
            }

            // Expand node, possibly partially:
            // Generate left child:
            int agentAGroupSize = node.GetGroupSize(node.agentsGroupAssignment[conflict.agentA]);

            if (node.agentAExpansion == CbsNode.ExpansionState.NOT_EXPANDED && conflict.vertex == true &&
                conflict.timeStep >= node.allSingleAgentCosts[conflict.agentA] && // TODO: Consider checking directly whether at the time of the conflict the agent would be at its goal according to the node.singleAgentPlans. It may be more readable.
                agentAGroupSize == 1)
            // Conflict happens when or after agent A reaches its goal, and agent A is in a single agent group.
            // With multi-agent groups, banning the goal doesn't guarantee a higher cost solution,
            // since if an agent is forced to take a longer route it may enable another agent in the group
            // to take a shorter route, getting an alternative solution of the same cost
            // The left child would cost a lot because:
            // A) All WAIT moves in the goal before leaving it now add to the g.
            // B) We force the low level to compute a path longer than the optimal,
            //    and with a bad suprise towards the end in the form of a constraint,
            //    so the low-level's SIC heuristic performs poorly.
            // C) We're banning the GOAL from all directions (since this is a vertex conflict),
            //    so any alternative plan will at least cost 1 more.
            //    We're ignoring edge conflicts because they can only happen at the goal when reaching it,
            //    and aren't guaranteed to increase the cost because the goal can still be possibly reached from another edge.
            {
                if (debug)
                {
                    Debug.WriteLine("Skipping left child");
                }
                node.agentAExpansion = CbsNode.ExpansionState.DEFERRED;
                int agentAOldCost = node.allSingleAgentCosts[conflict.agentA];
                // Add the minimal delta in the child's cost:
                // since we're banning the goal at conflict.timeStep, it must at least do conflict.timeStep+1 steps
                node.totalCost += (ushort)(conflict.timeStep + 1 - agentAOldCost);
                openList.Add(node); // Re-insert node into open list with higher cost, don't re-increment global conflict counts
                this.partialExpansions++;
            }
            else if (node.agentAExpansion != CbsNode.ExpansionState.EXPANDED)
            // Agent A expansion already skipped in the past or not forcing A from its goal - finally generate the child:
            {
                if (debug)
                {
                    Debug.WriteLine("Generating left child");
                }
                var newConstraint = new CbsConstraint(conflict, instance, true);
                child = new CbsNode(node, newConstraint, conflict.agentA);

                if (closedList.ContainsKey(child) == false)
                {
                    closedList.Add(child, child);
                    if (child.Replan(conflict.agentA, this.minDepth)) // The node takes the max between minDepth and the max time over all constraints.
                    {
                        if (child.totalCost < node.totalCost && agentAGroupSize == 1)
                        {
                            Debug.WriteLine("");
                            Debug.Write("Single agent costs: ");
                            for (int i = 0; i < child.allSingleAgentCosts.Length; i++)
                            {
                                Debug.Write(" " + child.allSingleAgentCosts[i]);
                            }
                            Debug.WriteLine("");
                            //Debug.WriteLine("Offending plan:");
                            //child.CalculateJointPlan().PrintPlan();
                            Debug.WriteLine("Chlid plan: (cost {0})", child.allSingleAgentCosts[conflict.agentA]);
                            child.allSingleAgentPlans[conflict.agentA].PrintPlan();
                            Debug.WriteLine("Parent plan: (cost {0})", node.allSingleAgentCosts[conflict.agentA]);
                            node.allSingleAgentPlans[conflict.agentA].PrintPlan();
                            Debug.Assert(false, "Single agent node with lower cost than parent! " + child.totalCost + " < " + node.totalCost);
                        }
                        if (child.totalCost <= this.maxCost)
                        {
                            openList.Add(child);
                            this.highLevelGenerated++;
                            addToGlobalConflictCount(child.GetConflict());
                            if (debug)
                            {
                                Debug.WriteLine("Child cost: " + child.totalCost);
                                Debug.WriteLine("Child hash: " + child.GetHashCode());
                                Debug.WriteLine("");
                            }
                        }
                    }
                    else // A timeout probably occured
                    {
                        return;
                    }
                }
                else
                {
                    this.closedListHits++;
                }
                node.agentAExpansion = CbsNode.ExpansionState.EXPANDED;
            }

            // Generate right child:
            int agentBGroupSize = node.GetGroupSize(node.agentsGroupAssignment[conflict.agentB]);

            if (node.agentBExpansion == CbsNode.ExpansionState.NOT_EXPANDED && conflict.vertex == true &&
                conflict.timeStep >= node.allSingleAgentCosts[conflict.agentB] &&
                agentBGroupSize == 1) // Again, skip expansion
            {
                if (debug)
                {
                    Debug.WriteLine("Skipping right child");
                }
                if (node.agentAExpansion == CbsNode.ExpansionState.DEFERRED)
                {
                    throw new Exception("Unexpected: Expansion of both children differed, but this is a vertex conflict so that means the targets for the two agents are equal, which is illegal");
                }

                node.agentBExpansion = CbsNode.ExpansionState.DEFERRED;
                int agentBOldCost = node.allSingleAgentCosts[conflict.agentB];
                node.totalCost += (ushort)(conflict.timeStep + 1 - agentBOldCost);
                openList.Add(node); // Re-insert node into open list with higher cost, don't re-increment global conflict counts
                this.partialExpansions++;
                // TODO: Code duplication with agentA. Make this into a function.
            }
            else if (node.agentBExpansion != CbsNode.ExpansionState.EXPANDED)
            {
                if (debug)
                {
                    Debug.WriteLine("Generating right child");
                }
                var newConstraint = new CbsConstraint(conflict, instance, false);
                child = new CbsNode(node, newConstraint, conflict.agentB);

                if (closedList.ContainsKey(child) == false)
                {
                    closedList.Add(child, child);
                    if (child.Replan(conflict.agentB, this.minDepth)) // The node takes the max between minDepth and the max time over all constraints.
                    {
                        if (child.totalCost < node.totalCost && node.agentAExpansion == CbsNode.ExpansionState.EXPANDED &&
                            agentBGroupSize == 1)
                        {
                            Debug.WriteLine("");
                            Debug.Write("Single agent costs: ");
                            for (int i = 0; i < child.allSingleAgentCosts.Length; i++)
                            {
                                Debug.Write(" " + child.allSingleAgentCosts[i]);
                            }
                            Debug.WriteLine("");
                            //Debug.WriteLine("Offending plan:");
                            //child.CalculateJointPlan().PrintPlan();
                            Debug.WriteLine("Chlid plan: (cost {0})", child.allSingleAgentCosts[conflict.agentB]);
                            child.allSingleAgentPlans[conflict.agentB].PrintPlan();
                            Debug.WriteLine("Parent plan: (cost {0})", node.allSingleAgentCosts[conflict.agentB]);
                            node.allSingleAgentPlans[conflict.agentB].PrintPlan();
                            Debug.Assert(false, "Single agent node with lower cost than parent! " + child.totalCost + " < " + node.totalCost);
                        }
                        if (child.totalCost <= this.maxCost)
                        {
                            openList.Add(child);
                            this.highLevelGenerated++;
                            addToGlobalConflictCount(child.GetConflict());
                            if (debug)
                            {
                                Debug.WriteLine("Child cost: " + child.totalCost);
                                Debug.WriteLine("Child hash: " + child.GetHashCode());
                                Debug.WriteLine("");
                            }
                        }
                    }
                    else // A timeout probably occured
                    {
                        return;
                    }
                }
                else
                {
                    this.closedListHits++;
                }
                node.agentBExpansion = CbsNode.ExpansionState.EXPANDED;
            }
        }