public Resource(Task task, Workpiece workpiece) { Task = task; Workpiece = workpiece; }
private IEnumerable<Tuple<Agent, Capability[]>> Convert(Task task, int[] path) { var previous = -1; var usedCarts = new List<Agent>(); for (var i = 0; i < path.Length;) { var current = path[i]; if (previous != -1) { // Find a cart that connects both robots, the path matrix contains the next robot we have to go to foreach (var nextRobot in GetShortestPath(previous, current)) { yield return Transport(previous, nextRobot, usedCarts); if (nextRobot != current) yield return Tuple.Create(Agents[path[i]], new Capability[0]); previous = nextRobot; } } // Collect the capabilities that this robot should apply var capabilities = path .Skip(i) .TakeWhile(robot => robot == current) .Select((_, index) => task.Capabilities[i + index]) .ToArray(); yield return Tuple.Create(Agents[path[i]], capabilities); previous = current; i += capabilities.Length; } }
/// <summary> /// Recursively checks if there is a valid path with the given prefix for the task. /// If so, returns true and <param name="path" /> contains the path. Otherwise, returns false. /// </summary> private bool FindPath(Task task, int[] path, int prefixLength) { // termination case: the path is already complete if (prefixLength == task.Capabilities.Length) return true; var last = path[prefixLength - 1]; // special handling: see if the last robot can't do the next capability as well if (CanSatisfyNext(task, prefixLength, last)) { path[prefixLength] = last; if (FindPath(task, path, prefixLength + 1)) return true; } else // otherwise check connected robots { for (int next = 0; next < _availableRobots.Length; ++next) // go through all stations { // if connected to last robot and can fulfill next capability if (_pathMatrix[last, next] != -1 && CanSatisfyNext(task, prefixLength, next) && next != last) { path[prefixLength] = next; // try a path over next if (FindPath(task, path, prefixLength + 1)) // if there is such a path, return true return true; } } } return false; // there is no valid path with the given prefix }
/// <summary> /// Checks if the given robot can satisfy all the demanded capabilities. /// </summary> /// <param name="task">The task for which a path is searched.</param> /// <param name="capability">The zero-based index of the task's capability that should be applied next.</param> /// <param name="robot">The robot which should be next on the path.</param> /// <returns>True if choosing station as next path entry would not exceed its capabilities.</returns> private bool CanSatisfyNext(Task task, int capability, int robot) { return _availableRobots[robot].AvailableCapabilities.Any(c => c.IsEquivalentTo(task.Capabilities[capability])); }
/// <summary> /// Finds a sequence of connected robots that are able to fulfill the /// <param name="task" />'s capabilities. /// </summary> /// <returns> /// An array of robot identifiers, one for each capability. /// </returns> private int[] FindPath(Task task) { var path = new int[task.Capabilities.Length]; for (var first = 0; first < _availableRobots.Length; ++first) { if (CanSatisfyNext(task, 0, first)) { path[0] = first; if (FindPath(task, path, 1)) return path; } } return null; }