int solve_rec(struct shape *board, const struct puzzle *p, int current_tile) { int x, y; const struct shape *current_shape; if (current_tile == p->no_tiles) { /* * Found solution */ printf("Solution:\n"); dump_board(board, 0); dump_board_svg(board); printf("\n"); return (0); } current_shape = &p->tiles[current_tile]; for (y = 0; y < board->height - current_shape->height + 1; y++) { for (x = 0; x < board->width - current_shape->width + 1; x++) { if (can_insert_tile(board, &p->tiles[current_tile], x, y)) { insert_tile(board, current_tile + 1, &p->tiles[current_tile], x, y); solve_rec(board, p, current_tile + 1); remove_tile(board, current_tile + 1); } } } return (0); }
int solve_seq(problem* problem) { int res; int map[problem->size]; volatile int best = 1<<30; // #pragma omp parallel { // #pragma omp single res = solve_rec(problem, map, 0, 0, 0, &best); } return res; }
int solve_rec(problem* problem, int* partial, int plant, int used_mask, int cur_cost, volatile int* best_known) { // terminal case if (plant >= problem->size) { return cur_cost; } if (cur_cost >= *best_known) { return *best_known; } // fix current position for(int i=0; i<problem->size; i++) { // check whether current spot is a free spot // #pragma omp task if(!(1<<i & used_mask)) { // extend solution int tmp[problem->size]; memcpy(tmp, partial, problem->size*sizeof(int)); tmp[plant] = i; // compute additional cost of current assignment int new_cost = 0; for(int j=0; j<plant; j++) { int other_pos = tmp[j]; // add costs between current pair of plants new_cost += getA(problem, plant, j) * getB(problem, i, other_pos); new_cost += getA(problem, j, plant) * getB(problem, other_pos, i); } // compute recursive rest int cur_best = solve_rec(problem, tmp, plant+1, used_mask | (1<<i), cur_cost + new_cost, best_known); // update best known solution if (cur_best < *best_known) { int best; // |--- read best ---| |--- check ---| |------------ update if cur_best is better ------------| do { best = *best_known; } while (cur_best < best && __sync_bool_compare_and_swap(best_known, best, cur_best)); } } } // #pragma omp taskwait return *best_known; }
double solve_rec(solution* partial, int level) { // terminal case if(level == 0) { return 0.0; } // fix current position double res[N]; solution tmps[N]; for(int i = 0; i < N; i++) { #pragma omp task firstprivate(i) if(!contains(partial, i)) { // tmps[i] = (solution){partial,i}; res[i] = solve_rec(&tmps[i], level - 1); } } return 0.0; }
int solve_omp(problem* problem) { // get upper boundary for number of sub-problems int max_problems = powl(problem->size, OMP_CUT); // create array of activation records call_record* sub_problems = malloc(sizeof(call_record) * max_problems); call_record* pos = sub_problems; // create store for partial solutions int* block = malloc(sizeof(int) * max_problems * problem->size); int used = 0; // fill up sub-problem array volatile int best = 1<<30; int partial[problem->size]; initActivationRecord(problem, partial, 0, 0, 0, &best, &pos, block, &used, OMP_CUT); unsigned num_sub_problems = pos - sub_problems; printf("Sub-problem list filled %d/%d\n", num_sub_problems, max_problems); // solve sub-problem list within a loop #pragma omp parallel for schedule(dynamic, 1) for(int i=0; i<num_sub_problems; i++) { solve_rec( problem, &block[sub_problems[i].partial_index], sub_problems[i].plant, sub_problems[i].used_mask, sub_problems[i].cur_cost, &best ); } // free temporary arrays free(sub_problems); free(block); // return result return best; }
int solve(const struct puzzle *p) { struct shape board; int x, y; for (y = 0; y < p->board.height; y++) { for (x = 0; x < p->board.width; x++) { if (p->board.shape[y][x] == ' ') { board.shape[y][x] = WALL; } else { board.shape[y][x] = 0; } } } board.width = p->board.width; board.height = p->board.height; solve_rec(&board, p, 0); return (0); }
int main() { solution* map; solve_rec(map, 10); }