void read_basis (const char *filename, wfa_t *wfa) /* * Read WFA initial basis 'filename' and fill 'wfa' struct. * * No return value. * * Side effects: * wfa->into, wfa->weights, wfa->final_distribution, wfa->basis_states * wfa->domain_type wfa->wfainfo->basis_name, are filled with the * values of the WFA basis. */ { FILE *input; /* ASCII WFA initial basis file */ assert (filename && wfa); if (!wfa->wfainfo->basis_name || !streq (wfa->wfainfo->basis_name, filename)) { if (wfa->wfainfo->basis_name) Free (wfa->wfainfo->basis_name); wfa->wfainfo->basis_name = strdup (filename); } if (get_linked_basis (filename, wfa)) return; /* basis is linked with excecutable */ /* * Check whether 'wfa_name' is a regular ASCII WFA initial basis file */ { char magic [MAXSTRLEN]; /* WFA magic number */ if (!(input = open_file (filename, "FIASCO_DATA", READ_ACCESS))) file_error(filename); if (fscanf (input, MAXSTRLEN_SCANF, magic) != 1) error ("Format error: ASCII FIASCO initial basis file %s", filename); else if (strneq (FIASCO_BASIS_MAGIC, magic)) error ("Input file %s is not an ASCII FIASCO initial basis!", filename); } /* * WFA ASCII format: * * Note: State 0 is assumed to be the constant function f(x, y) = 128. * Don't define any transitions of state 0 in an initial basis. * * Header: * type |description * ----------------+----------- * string |MAGIC Number "Wfa" * int |Number of basis states 'N' * bool_t-array[N] |use vector in linear combinations, * |0: don't use vector (auxilliary state) * |1: use vector in linear combinations * float-array[N] |final distribution of every state * * Transitions: * * <state 1> current state * <label> <into> <weight> transition 1 of current state * <label> <into> <weight> transition 2 of current state * ... * <-1> last transition marker * <state 2> * ... * <-1> last transition marker * <state N> * ... * * <-1> last transition marker * <-1> last state marker */ { unsigned state; if (fscanf (input ,"%u", &wfa->basis_states) != 1) error ("Format error: ASCII FIASCO initial basis file %s", filename); /* * State 0 is assumed to be the constant function f(x, y) = 128. */ wfa->domain_type [0] = USE_DOMAIN_MASK; wfa->final_distribution [0] = 128; wfa->states = wfa->basis_states; wfa->basis_states++; append_edge (0, 0, 1.0, 0, wfa); append_edge (0, 0, 1.0, 1, wfa); for (state = 1; state < wfa->basis_states; state++) wfa->domain_type [state] = read_int (input) ? USE_DOMAIN_MASK : AUXILIARY_MASK; for (state = 1; state < wfa->basis_states; state++) wfa->final_distribution[state] = read_real (input); /* * Read transitions */ for (state = 1; state < wfa->basis_states; state++) { unsigned domain; int label; real_t weight; if (read_int (input) != (int) state) error ("Format error: ASCII FIASCO initial basis file %s", filename); while((label = read_int (input)) != -1) { domain = read_int (input); weight = read_real (input); append_edge (state, domain, weight, label, wfa); } } } fclose (input); }
int main(int argc, char **argv) { AllPoints all_points; EdgesPath path; all_points.number_of_points = 0; path.size = 0; #ifdef DRAW_RESULT { const int xBound = 800; const int yBound = 600; initializeWindow(argc, argv, xBound, yBound); } #endif // #ifdef DRAW_RESULT if (argc >= 2) { read_points_from_file(argv[1], &all_points); } else { #ifdef DRAW_RESULT read_from_screen(&all_points); #endif // #ifdef DRAW_RESULT } qsort(all_points.points, all_points.number_of_points, sizeof(Point), compare_points); { const int hk_subtasks_count = (all_points.number_of_points / MAX_HELD_KARP_POINTS) + (all_points.number_of_points % MAX_HELD_KARP_POINTS ? 1 : 0); Path *pathes = calloc(hk_subtasks_count, sizeof(Path)); int start_point = 0; int current_hk_part_index = 0; for (current_hk_part_index = 0; current_hk_part_index < hk_subtasks_count; ++current_hk_part_index) { int size = MAX_HELD_KARP_POINTS; int i = 0; Path partial_path; if (current_hk_part_index + 2 == hk_subtasks_count) { size = (all_points.number_of_points - start_point) / 2; } if (current_hk_part_index + 1 == hk_subtasks_count) { size = all_points.number_of_points - start_point; } partial_path = build_held_karp_path(all_points.points + start_point, size); for (i = 0; i < size; ++i) { partial_path.points[i] += start_point; } pathes[current_hk_part_index] = partial_path; start_point += size; } // sub optimally join partial pathes { // in first path we do not have any edges that are forbidden for removal to join HK-loops. int forbidden_endge_start = -1; for (current_hk_part_index = 1; current_hk_part_index < hk_subtasks_count; ++current_hk_part_index) { float best_cost = FLT_MAX; int prev = 0; int prev_loop_edge_start = -1; int curr_loop_edge_start = -1; Edge connecting_edge_1; Edge connecting_edge_2; // for each allowed edge from previous loop for (prev = 0; prev < pathes[current_hk_part_index - 1].size; ++prev) { int curr = 0; const int prev_start_index = pathes[current_hk_part_index - 1].points[prev]; const int prev_end_index = pathes[current_hk_part_index - 1].points[(prev + 1) % pathes[current_hk_part_index - 1].size]; const Point prev_start = all_points.points[prev_start_index]; const Point prev_end = all_points.points[prev_end_index]; if (forbidden_endge_start == prev) { continue; } // for each edge from current loop for (curr = 0; curr < pathes[current_hk_part_index].size; ++curr) { // check if removing both edges and connecting loops in this points will get optimal result const int curr_start_index = pathes[current_hk_part_index].points[curr]; const int curr_end_index = pathes[current_hk_part_index].points[(curr + 1) % pathes[current_hk_part_index].size]; const Point curr_start = all_points.points[curr_start_index]; const Point curr_end = all_points.points[curr_end_index]; const float removal_cost = distance(prev_start, prev_end) + distance(curr_start, curr_end); const float start_start_connect_cost = distance(prev_start, curr_start) + distance(prev_end, curr_end); const float start_end_connect_cost = distance(prev_start, curr_end) + distance(prev_end, curr_start); if (best_cost > start_start_connect_cost - removal_cost) { best_cost = start_start_connect_cost - removal_cost; prev_loop_edge_start = prev; curr_loop_edge_start = curr; connecting_edge_1.start = prev_start_index; connecting_edge_1.end = curr_start_index; connecting_edge_2.start = prev_end_index; connecting_edge_2.end = curr_end_index; } if (best_cost > start_end_connect_cost - removal_cost) { best_cost = start_end_connect_cost - removal_cost; prev_loop_edge_start = prev; curr_loop_edge_start = curr; connecting_edge_1.start = prev_start_index; connecting_edge_1.end = curr_end_index; connecting_edge_2.start = prev_end_index; connecting_edge_2.end = curr_start_index; } } } for (prev = 0; prev < pathes[current_hk_part_index - 1].size; ++prev) { // append all edges from previous loop except forbidden and selected for removal const int prev_start_index = pathes[current_hk_part_index - 1].points[prev]; const int prev_end_index = pathes[current_hk_part_index - 1].points[(prev + 1) % pathes[current_hk_part_index - 1].size]; if (forbidden_endge_start == prev || prev_loop_edge_start == prev) { continue; } append_edge(&path, prev_start_index, prev_end_index); } { // append two extra edges added instead of removed ones append_edge(&path, connecting_edge_1.start, connecting_edge_1.end); append_edge(&path, connecting_edge_2.start, connecting_edge_2.end); } forbidden_endge_start = curr_loop_edge_start; } { int prev = 0; for (prev = 0; prev < pathes[hk_subtasks_count - 1].size; ++prev) { // append all edges from last loop except forbidden one const int prev_start_index = pathes[hk_subtasks_count - 1].points[prev]; const int prev_end_index = pathes[hk_subtasks_count - 1].points[(prev + 1) % pathes[hk_subtasks_count - 1].size]; if (forbidden_endge_start == prev) { continue; } append_edge(&path, prev_start_index, prev_end_index); } } } free(pathes); } #ifdef DRAW_RESULT // run message loop with displaying points and found path display_results(&all_points, &path); #endif // #ifdef DRAW_RESULT }
static unsigned decode_nd_tree (wfa_t *wfa, bitfile_t *input) /* * Read 'wfa' prediction tree of given 'input' stream. * * No return value. * * Side effects: * 'wfa->into' is filled with the decoded values */ { lqueue_t *queue; /* queue of states */ int next, state; /* state and its current child */ unsigned total = 0; /* total number of predicted states */ u_word_t sum0, sum1; /* Probability model */ u_word_t code; /* The present input code value */ u_word_t low; /* Start of the current code range */ u_word_t high; /* End of the current code range */ /* * Initialize arithmetic decoder */ code = get_bits (input, 16); low = 0; high = 0xffff; sum0 = 1; sum1 = 11; queue = alloc_queue (sizeof (int)); state = wfa->root_state; queue_append (queue, &state); /* * Traverse the WFA tree in breadth first order (using a queue). */ while (queue_remove (queue, &next)) { unsigned label; if (wfa->level_of_state [next] > wfa->wfainfo->p_max_level + 1) { /* * Nondetermismn is not allowed at levels larger than * 'wfa->wfainfo->p_max_level'. */ for (label = 0; label < MAXLABELS; label++) if (ischild (state = wfa->tree [next][label])) queue_append (queue, &state); /* continue with childs */ } else if (wfa->level_of_state [next] > wfa->wfainfo->p_min_level) { for (label = 0; label < MAXLABELS; label++) if (ischild (state = wfa->tree [next][label])) { unsigned count; /* Current interval count */ unsigned range; /* Current interval range */ count = (((code - low) + 1) * sum1 - 1) / ((high - low) + 1); if (count < sum0) { /* * Decode a '0' symbol * First, the range is expanded to account for the * symbol removal. */ range = (high - low) + 1; high = low + (u_word_t) ((range * sum0) / sum1 - 1 ); RESCALE_INPUT_INTERVAL; /* * Update the frequency counts */ sum0++; sum1++; if (sum1 > 50) /* scale the symbol frequencies */ { sum0 >>= 1; sum1 >>= 1; if (!sum0) sum0 = 1; if (sum0 >= sum1) sum1 = sum0 + 1; } if (wfa->level_of_state [state] > wfa->wfainfo->p_min_level) queue_append (queue, &state); } else { /* * Decode a '1' symbol * First, the range is expanded to account for the * symbol removal. */ range = (high - low) + 1; high = low + (u_word_t) ((range * sum1) / sum1 - 1); low = low + (u_word_t) ((range * sum0) / sum1); RESCALE_INPUT_INTERVAL; /* * Update the frequency counts */ sum1++; if (sum1 > 50) /* scale the symbol frequencies */ { sum0 >>= 1; sum1 >>= 1; if (!sum0) sum0 = 1; if (sum0 >= sum1) sum1 = sum0 + 1; } append_edge (next, 0, -1, label, wfa); total++; }