int Solver::Solve(KociembaCube& scrambledCube) { int iteration = 1; int result = NOT_FOUND; // Make a copy of the scrambled cube for use later on cube = scrambledCube; // Establish initial cost estimate to goal state threshold1 = Phase1Cost(cube.Twist(), cube.Flip(), cube.Choice()); nodes1 = 1; // Count root node here solutionLength1 = 0; do { cout << "threshold(" << iteration << ") = " << threshold1 << endl; newThreshold1 = Huge; // Any cost will be less than this // Perform the phase 1 recursive IDA* search result = Search1(cube.Twist(), cube.Flip(), cube.Choice(), 0); // Establish a new threshold for a deeper search threshold1 = newThreshold1; // Count interative deepenings iteration++; } while (result == NOT_FOUND); cout << "Phase 1 nodes = " << nodes1 << endl; return result; }
/* --- TABEL DENGAN ELEMEN TERURUT MEMBESAR --- */ IdxType SearchUrut (TabInt T, ElType X) { /* Kamus */ /* Algoritma */ if ((IsEmpty(T))||(!SearchB(T,X))) { return IdxUndef; } else { return Search1(T,X); } }
void Del1Urut (TabInt *T, ElType X) { /* Kamus */ IdxType i; /* Algoritma */ if (SearchB(*T,X)) { i=Search1(*T,X); while (i<GetLastIdx(*T)) { SetEl(T,i,GetElmt(*T,i+1)); i++; } SetEl(T,i,ValUndef); } }
int Solver::Solve(KociembaCube& scrambledCube) { int iteration = 1; int result = NOT_FOUND; stopped = false; Window->ProgressInit(0); cube = scrambledCube; threshold1 = Phase1Cost(cube.Twist(), cube.Flip(), cube.Choice()); nodes = 1; solutionLength1 = 0; do { Window->SetInfo("Обработка глубины _%d / %d_", iteration, nodes); newThreshold1 = Huge; result = Search1(cube.Twist(), cube.Flip(), cube.Choice(), 0); if(stopped) { Window->SetInfo("_Готово_"); return ABORT; } threshold1 = newThreshold1; iteration++; Application->processEvents(); } while (result == NOT_FOUND); Window->SetInfo("_Найдено оптимальное решение_"); return result; }
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; }