/// <summary> /// Builds an MDD by first performing a BFS from start_pos to the agent's goal, /// then deleting all nodes which don't lead to the goal at the given cost. /// </summary> /// <param name="mddNum"></param> /// <param name="agentNum"></param> /// <param name="start_pos"></param> /// <param name="cost">The MDD must be of this cost</param> /// <param name="numOfLevels"> /// The MDD must be of this number of levels, not counting level zero. /// If higher than cost, the extra levels will be WAITs at the goal. /// </param> /// <param name="numOfAgents">Used for initializng coexistence lists</param> /// <param name="instance"></param> /// <param name="ignoreConstraints"></param> /// <param name="supportPruning"></param> public MDD(int mddNum, int agentNum, Move start_pos, int cost, int numOfLevels, int numOfAgents, ProblemInstance instance, bool ignoreConstraints = false, bool supportPruning = true, ISet <TimedMove> reserved = null) { // numOfLevels >= cost this.problem = instance; this.mddNum = mddNum; this.agentNum = agentNum; this.numOfAgents = numOfAgents; this.cost = cost; this.levels = new LinkedList <MDDNode> [numOfLevels + 1]; this.supportPruning = supportPruning; ISet <CbsConstraint> constraints = null; Dictionary <int, TimedMove>[] mustConstraints = null; if (ignoreConstraints == false && instance.parameters.ContainsKey(CBS.CONSTRAINTS) && ((HashSet_U <CbsConstraint>)instance.parameters[CBS.CONSTRAINTS]).Count != 0) { this.queryConstraint = new CbsConstraint(); this.queryConstraint.queryInstance = true; constraints = (ISet <CbsConstraint>)instance.parameters[CBS.CONSTRAINTS]; } if (ignoreConstraints == false && instance.parameters.ContainsKey(CBS.MUST_CONSTRAINTS) && ((HashSet_U <CbsConstraint>)instance.parameters[CBS.MUST_CONSTRAINTS]).Count != 0) { // TODO: Code dup with A_Star's constructor var musts = (HashSet_U <CbsConstraint>)instance.parameters[CBS.MUST_CONSTRAINTS]; mustConstraints = new Dictionary <int, TimedMove> [musts.Max(con => con.GetTimeStep()) + 1]; // To have index MAX, array needs MAX + 1 places. foreach (CbsConstraint con in musts) { int timeStep = con.GetTimeStep(); if (mustConstraints[timeStep] == null) { mustConstraints[timeStep] = new Dictionary <int, TimedMove>(); } mustConstraints[timeStep][con.agentNum] = con.move; } } var perLevelClosedList = new Dictionary <MDDNode, MDDNode>(); var toDelete = new List <MDDNode>(); for (int i = 0; i < levels.Length; i++) { levels[i] = new LinkedList <MDDNode>(); } MDDNode root = new MDDNode(new TimedMove(start_pos, 0), numOfAgents, this, supportPruning); // Root LinkedListNode <MDDNode> llNode = new LinkedListNode <MDDNode>(root); root.setMyNode(llNode); llNode.Value.startOrGoal = true; levels[0].AddFirst(llNode); for (int i = 0; i < numOfLevels; i++) // For each level, populate the _next_ level { int heuristicBound = cost - i - 1; // We want g+h <= cost, so h <= cost-g. -1 because it's the bound of the _children_. if (heuristicBound < 0) { heuristicBound = 0; } // Go over each MDDNode in this level foreach (MDDNode currentMddNode in levels[i]) // Since we're not deleting nodes in this method, we can use the simpler iteration method :) { List <MDDNode> children = this.GetAllChildren(currentMddNode, heuristicBound, numOfAgents, constraints, mustConstraints, reserved); if (children.Count == 0) // Heuristic wasn't perfect because of constraints, illegal moves or other reasons { toDelete.Add(currentMddNode); } foreach (MDDNode child in children) { MDDNode toAdd = child; // The compiler won't let me assign to the foreach variable... if (perLevelClosedList.ContainsKey(child)) { toAdd = perLevelClosedList[child]; } else { perLevelClosedList.Add(toAdd, toAdd); llNode = new LinkedListNode <MDDNode>(toAdd); toAdd.setMyNode(llNode); levels[i + 1].AddLast(llNode); } currentMddNode.addChild(toAdd); // forward edge toAdd.addParent(currentMddNode); // backward edge } } perLevelClosedList.Clear(); } foreach (MDDNode goal in levels[numOfLevels]) // The goal may be reached in more than one direction { goal.startOrGoal = true; } foreach (MDDNode remove in toDelete) { remove.delete(); } }
public MDD(MDD other) { this.problem = other.problem; this.mddNum = other.mddNum; this.agentNum = other.agentNum; this.numOfAgents = other.numOfAgents; this.cost = other.cost; this.supportPruning = other.supportPruning; if (other.levels == null) { this.levels = null; return; } this.levels = new LinkedList <MDDNode> [other.levels.Length]; int numOfLevels = other.levels.Length - 1; // Level zero not counted for (int i = 0; i < levels.Length; i++) { levels[i] = new LinkedList <MDDNode>(); } Dictionary <MDDNode, MDDNode> originals = new Dictionary <MDDNode, MDDNode>(); Dictionary <MDDNode, MDDNode> copies = new Dictionary <MDDNode, MDDNode>(); MDDNode copiedRoot = new MDDNode(new TimedMove(other.levels[0].First.Value.move), numOfAgents, this, supportPruning); // Root LinkedListNode <MDDNode> llNode = new LinkedListNode <MDDNode>(copiedRoot); copiedRoot.setMyNode(llNode); llNode.Value.startOrGoal = true; levels[0].AddFirst(llNode); originals.Add(copiedRoot, other.levels[0].First.Value); copies.Add(other.levels[0].First.Value, copiedRoot); for (int i = 0; i < numOfLevels; i++) // For each level, populate the _next_ level { foreach (MDDNode copiedNode in levels[i]) { foreach (MDDNode originalChildNode in originals[copiedNode].children) { MDDNode copiedChild; if (copies.ContainsKey(originalChildNode) == false) { copiedChild = new MDDNode(originalChildNode.move, numOfLevels, this, supportPruning); originals.Add(copiedChild, originalChildNode); copies.Add(originalChildNode, copiedChild); llNode = new LinkedListNode <MDDNode>(copiedChild); copiedChild.setMyNode(llNode); levels[i + 1].AddLast(llNode); } else { copiedChild = copies[originalChildNode]; } copiedNode.addChild(copiedChild); // forward edge copiedChild.addParent(copiedNode); // backward edge } } } originals.Clear(); copies.Clear(); foreach (MDDNode goal in levels[numOfLevels]) // The goal may be reached in more than one direction { goal.startOrGoal = true; } }