private static void SplitTask(QueenTask baseTask, int numQueens, int levels, Queue <QueenTask> taskQueue) { // Base case for recursion. if (levels == 1) { baseTask.id = taskQueue.Count; taskQueue.Enqueue(baseTask); return; } for (int i = 0; i < numQueens; i++) { long queen = 1 << i; var subTask = baseTask; subTask.id = 0; // Will be set later. // No need to set masks[] as it is scratch for the task code. subTask.solutions = 0; subTask.step = Step.Place; subTask.col = (byte)(baseTask.col + 1); subTask.startCol = (byte)(baseTask.col + 1); subTask.rook = subTask.rook | queen; subTask.add |= queen << baseTask.col; subTask.sub |= queen << (numQueens - 1 - baseTask.col); subTask.mask = ((1 << numQueens) - 1) & ~(subTask.rook | (subTask.add >> subTask.col) | (subTask.sub >> ((NumQueens - 1) - subTask.col))); if (Pop(subTask.rook) == subTask.col && Pop(subTask.add) == subTask.col && Pop(subTask.sub) == subTask.col) { SplitTask(subTask, numQueens, levels - 1, taskQueue); } } }
// For an instnace of the N-Queens problem of size n, get a list of QueenTask // tasks that covers the entire problem. That is, when each task is complete // the number of solutions found by each task can be summed to determine the // total number of solutions. private static Queue <QueenTask> GetQueenTaskPartition(int numQueens, int splitDepth) { var wholeProblemTask = new QueenTask(); wholeProblemTask.mask = (1 << numQueens) - 1; var taskQueue = new Queue <QueenTask>(); SplitTask(wholeProblemTask, numQueens, splitDepth, taskQueue); return(taskQueue); }
// For an instnace of the N-Queens problem of size n, get a list of QueenTask // tasks that covers the entire problem. That is, when each task is complete // the number of solutions found by each task can be summed to determine the // total number of solutions. private static Queue<QueenTask> GetQueenTaskPartition(int numQueens, int splitDepth) { var wholeProblemTask = new QueenTask(); wholeProblemTask.mask = (1 << numQueens) - 1; var taskQueue = new Queue<QueenTask>(); SplitTask(wholeProblemTask, numQueens, splitDepth, taskQueue); return taskQueue; }
private static void SplitTask(QueenTask baseTask, int numQueens, int levels, Queue<QueenTask> taskQueue) { // Base case for recursion. if (levels == 1) { baseTask.id = taskQueue.Count; taskQueue.Enqueue(baseTask); return; } for (int i = 0; i < numQueens; i++) { long queen = 1 << i; var subTask = baseTask; subTask.id = 0; // Will be set later. // No need to set masks[] as it is scratch for the task code. subTask.solutions = 0; subTask.step = Step.Place; subTask.col = (byte)(baseTask.col + 1); subTask.startCol = (byte)(baseTask.col + 1); subTask.rook = subTask.rook | queen; subTask.add |= queen << baseTask.col; subTask.sub |= queen << (numQueens - 1 - baseTask.col); subTask.mask = ((1 << numQueens) - 1) & ~(subTask.rook | (subTask.add >> subTask.col) | (subTask.sub >> ((NumQueens - 1) - subTask.col))); if (Pop(subTask.rook) == subTask.col && Pop(subTask.add) == subTask.col && Pop(subTask.sub) == subTask.col) { SplitTask(subTask, numQueens, levels - 1, taskQueue); } } }
private static QueenTask[] GetNextAssignment(QueenTask[] inProgress, Queue<QueenTask> todos, IList<QueenTask> done) { var nextAssignment = new List<QueenTask>(); foreach (var task in inProgress) { if (task.step == Step.Done) { done.Add(task); } else { nextAssignment.Add(task); } } while (nextAssignment.Count < Spread && todos.Any()) nextAssignment.Add(todos.Dequeue()); return nextAssignment.ToArray(); }