int Solver::Search2( int cornerPermutation, int nonMiddleSliceEdgePermutation, int middleSliceEdgePermutation, int depth) { int cost, totalCost; int move; int power, powerLimit; int cornerPermutation2; int nonMiddleSliceEdgePermutation2; int middleSliceEdgePermutation2; int result; // Compute cost estimate to goal state cost = Phase2Cost( cornerPermutation, nonMiddleSliceEdgePermutation, middleSliceEdgePermutation); // h if (cost == 0) // Solution found... { solutionLength2 = depth; // Save phase 2 solution length if (solutionLength1 + solutionLength2 < minSolutionLength) minSolutionLength = solutionLength1 + solutionLength2; PrintSolution(); return FOUND; } // See if node should be expanded totalCost = depth + cost; // g + h if (totalCost <= threshold2) // Expand node { // No point in continuing to search for solutions of equal or greater // length than the current best solution if (solutionLength1 + depth >= minSolutionLength-1) return ABORT; for (move = Cube::Move::R; move <= Cube::Move::B; move++) { if (Disallowed(move, solutionMoves2, depth)) continue; cornerPermutation2 = cornerPermutation; nonMiddleSliceEdgePermutation2 = nonMiddleSliceEdgePermutation; middleSliceEdgePermutation2 = middleSliceEdgePermutation; solutionMoves2[depth] = move; powerLimit = 4; if (move != Cube::Move::U && move != Cube::Move::D) powerLimit=2; for (power = 1; power < powerLimit; power++) { cornerPermutation2 = cornerPermutationMoveTable[cornerPermutation2][move]; nonMiddleSliceEdgePermutation2 = nonMiddleSliceEdgePermutationMoveTable[nonMiddleSliceEdgePermutation2][move]; middleSliceEdgePermutation2 = middleSliceEdgePermutationMoveTable[middleSliceEdgePermutation2][move]; solutionPowers2[depth] = power; nodes2++; // Apply the move if (result = Search2( cornerPermutation2, nonMiddleSliceEdgePermutation2, middleSliceEdgePermutation2, depth+1)) return result; } } } else // Maintain minimum cost exceeding threshold { if (totalCost < newThreshold2) newThreshold2 = totalCost; } return NOT_FOUND; }
int Solver::Search2( int cornerPermutation, int nonMiddleSliceEdgePermutation, int middleSliceEdgePermutation, int depth) { int cost, totalCost; int move; int power, powerLimit; int cornerPermutation2; int nonMiddleSliceEdgePermutation2; int middleSliceEdgePermutation2; int result; cost = Phase2Cost( cornerPermutation, nonMiddleSliceEdgePermutation, middleSliceEdgePermutation); if (cost == 0) { solutionLength2 = depth; if (solutionLength1 + solutionLength2 < minSolutionLength) minSolutionLength = solutionLength1 + solutionLength2; PrintSolution(); return FOUND; } if (cost < 2) Window->ProgressStep(1); totalCost = depth + cost; if (totalCost <= threshold2) { if (solutionLength1 + depth >= minSolutionLength-1) return ABORT; for (move = Cube::R; move <= Cube::B; move++) { if (Disallowed(move, solutionMoves2, depth)) continue; cornerPermutation2 = cornerPermutation; nonMiddleSliceEdgePermutation2 = nonMiddleSliceEdgePermutation; middleSliceEdgePermutation2 = middleSliceEdgePermutation; solutionMoves2[depth] = move; powerLimit = 4; if (move != Cube::U && move != Cube::D) powerLimit=2; for (power = 1; power < powerLimit; power++) { cornerPermutation2 = cornerPermutationMoveTable [cornerPermutation2][move]; nonMiddleSliceEdgePermutation2 = nonMiddleSliceEdgePermutationMoveTable [nonMiddleSliceEdgePermutation2][move]; middleSliceEdgePermutation2 = middleSliceEdgePermutationMoveTable [middleSliceEdgePermutation2][move]; solutionPowers2[depth] = power; nodes2++; if ((result = Search2( cornerPermutation2, nonMiddleSliceEdgePermutation2, middleSliceEdgePermutation2, depth+1))) return result; } } } else { if (totalCost < newThreshold2) newThreshold2 = totalCost; } return NOT_FOUND; }
int Solver::Search1(int twist, int flip, int choice, int depth) { int cost, totalCost; int move; int power; int twist2, flip2, choice2; int result; // Compute cost estimate to phase 1 goal state cost = Phase1Cost(twist, flip, choice); // h if (cost == 0) // Phase 1 solution found... { solutionLength1 = depth; // Save phase 1 solution length // We need an appropriately initialized cube in order // to begin phase 2. First, create a new cube that // is a copy of the initial scrambled cube. Then we // apply the phase 1 move sequence to that cube. The // phase 2 search can then determine the initial // phase 2 coordinates (corner, edge, and slice // permutation) from this cube. // // Note: No attempt is made to merge moves of the same // face adjacent to the phase 1 & phase 2 boundary since // the shorter sequence will quickly be found. KociembaCube phase2Cube = cube; for (int i = 0; i < solutionLength1; i++) { for (power = 0; power < solutionPowers1[i]; power++) phase2Cube.ApplyMove(solutionMoves1[i]); } // Invoke Phase 2 (void)Solve2(phase2Cube); } // See if node should be expanded totalCost = depth + cost; // g + h if (totalCost <= threshold1) // Expand node { // If this happens, we should have found the // optimal solution at this point, so we // can exit indicating such. Note: the first // complete solution found in phase1 is optimal // due to it being an addmissible IDA* search. if (depth >= minSolutionLength-1 || minSolutionLength < 24) return OPTIMUM_FOUND; for (move = Cube::Move::R; move <= Cube::Move::B; move++) { if (Disallowed(move, solutionMoves1, depth)) continue; twist2 = twist; flip2 = flip; choice2 = choice; solutionMoves1[depth] = move; for (power = 1; power < 4; power++) { solutionPowers1[depth] = power; twist2 = twistMoveTable[twist2][move]; flip2 = flipMoveTable[flip2][move]; choice2 = choiceMoveTable[choice2][move]; nodes1++; // Apply the move if (result = Search1(twist2, flip2, choice2, depth+1)) return result; } } } else // Maintain minimum cost exceeding threshold { if (totalCost < newThreshold1) newThreshold1 = totalCost; } return NOT_FOUND; }
int Solver::Search1(int twist, int flip, int choice, int depth) { int cost, totalCost; int move; int power; int twist2, flip2, choice2; int result; cost = Phase1Cost(twist, flip, choice); if (cost == 0) { solutionLength1 = depth; KociembaCube phase2Cube = cube; for (int i = 0; i < solutionLength1; i++) { for (power = 0; power < solutionPowers1[i]; power++) phase2Cube.ApplyMove(solutionMoves1[i]); } (void)Solve2(phase2Cube); if(stopped) return ABORT; } totalCost = depth + cost; if (totalCost <= threshold1) { if (depth >= minSolutionLength-1) return OPTIMUM_FOUND; for (move = Cube::R; move <= Cube::B; move++) { if (Disallowed(move, solutionMoves1, depth)) continue; twist2 = twist; flip2 = flip; choice2 = choice; solutionMoves1[depth] = move; for (power = 1; power < 4; power++) { solutionPowers1[depth] = power; twist2 = twistMoveTable[twist2][move]; flip2 = flipMoveTable[flip2][move]; choice2 = choiceMoveTable[choice2][move]; if ((result = Search1(twist2, flip2, choice2, depth+1))) return result; } } } else { if (totalCost < newThreshold1) newThreshold1 = totalCost; } return NOT_FOUND; }