/** * This function minimizes the given automaton. Note * that it must be deterministic. For more information, * see comments in this library's .h file. */ void elag_minimize(SingleGraph automaton,int level) { struct list_int* initials=get_initial_states(automaton); if (initials==NULL) { /* No initial state should mean 'empty automaton' */ if (automaton->number_of_states!=0) { /* If not, we fail */ fatal_error("No initial state in non empty automaton in elag_minimize\n"); } return; } if (initials->next!=NULL) { fatal_error("Non-deterministic automaton in elag_minimize\n"); } free_list_int(initials); if (level>0) { /* If necessary, we remove transitions that are included in the * default ones */ compact_default_transitions(automaton); } SymbolAlphabet* alph=build_symbol_alphabet(automaton); TransitionCollection** transitions=build_transition_collections(automaton,alph); /* Now that we have numbered transitions, we don't need the symbol * alphabet anymore */ free_SymbolAlphabet(alph); int nbColors; int nbShades; int* color=(int*)calloc(automaton->number_of_states,sizeof(int)); if (color==NULL) { fatal_alloc_error("elag_minimize"); } int* shade=init_colors(automaton,&nbShades); do { int s; /* We copy the shades into the color array */ for (s=0;s<automaton->number_of_states;s++) { color[s]=shade[s]; } nbColors=nbShades; nbShades=0; /* We update the colors of the transitions' destination states */ update_colors(transitions,color,automaton->number_of_states); /* Now, for each state #s, we look for its shade, comparing it with * all the states #i so that i<s */ for (s=0;s<automaton->number_of_states;s++) { shade[s]=get_shade(s,transitions,color,shade,&nbShades); } /* We stop when no more shades have been introduced */ } while (nbColors!=nbShades); int* chosen=choose_states(color,nbColors,automaton->number_of_states); for (int i=0;i<automaton->number_of_states;i++) { free_TransitionCollection(transitions[i]); } free(transitions); free(shade); /* We allocate the resulting automaton */ SingleGraph result=new_SingleGraph(nbColors,PTR_TAGS); for (int c=0;c<nbColors;c++) { SingleGraphState state=add_state(result); SingleGraphState original=automaton->states[chosen[c]]; /* We set the initiality and finality of the state */ state->control=original->control; state->outgoing_transitions=original->outgoing_transitions; original->outgoing_transitions=NULL; /* We renumber the transitions' destination states */ for (Transition* t1=state->outgoing_transitions;t1!=NULL;t1=t1->next) { t1->state_number=color[t1->state_number]; } state->default_state=original->default_state; } /* Now we have to replace the old automaton by the new one */ move_SingleGraph(automaton,&result,free_symbol); /* And we don't need these arrays anymore */ free(color); free(chosen); }
int test_palette(struct pldraw *pldraw, char * const *opts, int opts_n) { struct plep *plep; static const int greys = 256; struct plep_rect rect; struct plep_rect area; int ret = 0; int cur_rotation; int xres; int yres; float x_grid, y_grid; int width; int tmp; int i; assert(pldraw != NULL); assert(g_initialised); plep = pldraw_get_plep(pldraw); plep_set_opt(plep, PLEP_SYNC_UPDATE, 1); xres = pldraw_get_xres(pldraw); yres = pldraw_get_yres(pldraw); cur_rotation = pldraw_get_rotation(pldraw); if (yres > xres) { const int new_rotation = cur_rotation + ((cur_rotation % 180) ? -90 : 90); pldraw_set_rotation(pldraw, new_rotation); xres = pldraw_get_xres(pldraw); yres = pldraw_get_yres(pldraw); } x_grid = xres / 24.0; y_grid = yres / 18.0; LOG("greyscale palettes"); area.a.x = x_grid * 0.5; area.a.y = y_grid * 0.5; area.b.x = x_grid * 23.5; area.b.y = y_grid * 3.0; width = area.b.x - area.a.x; memcpy(&rect, &area, sizeof rect); rect.b.x = rect.a.x; --rect.b.y; for (i = 0; i < width; ++i) { const int grey = i * greys / width; const pldraw_color_t col = pldraw_get_grey(pldraw, grey); pldraw_draw_line(pldraw, col, &rect); ++rect.a.x; ++rect.b.x; } draw_border(pldraw, g_black, &area); area.a.y = y_grid * 3.5; area.b.y = y_grid * 6.0; memcpy(&rect, &area, sizeof rect); for (i = 0; i < 16; ++i) { const int grey = pldraw_grey_16[i]; const pldraw_color_t col = pldraw_get_grey(pldraw, grey); rect.b.x = area.a.x + (width * (i + 1)) / 16; pldraw_fill_rect(pldraw, col, &rect); rect.a.x = rect.b.x; } draw_border(pldraw, g_black, &area); if (plep_update_screen(plep, g_clear_wf) < 0) ret = -1; LOG("primary and secondary colours"); width = x_grid * 24; width /= 90; width /= 2; width += 1; width *= 90; tmp = (x_grid * 21.5 - width) / 2; rect.a.x = x_grid * 0.5; rect.a.y = y_grid * 6.5; rect.b.x = x_grid * 0.5 + tmp; rect.b.y = y_grid * 9.5; pldraw_fill_rect(pldraw, g_red, &rect); rect.a.y = y_grid * 10.5; rect.b.y = y_grid * 13.5; pldraw_fill_rect(pldraw, g_green, &rect); rect.a.y = y_grid * 14.5; rect.b.y = y_grid * 17.5; pldraw_fill_rect(pldraw, g_blue, &rect); rect.a.x = x_grid * 1.5 + tmp; rect.a.y = y_grid * 6.5; rect.b.x = x_grid * 1.5 + (2 * tmp); rect.b.y = y_grid * 9.5; pldraw_fill_rect(pldraw, g_cyan, &rect); rect.a.y = y_grid * 10.5; rect.b.y = y_grid * 13.5; pldraw_fill_rect(pldraw, g_magenta, &rect); rect.a.y = y_grid * 14.5; rect.b.y = y_grid * 17.5; pldraw_fill_rect(pldraw, g_yellow, &rect); area.a.x = x_grid * 0.5; area.a.y = y_grid * 6.5; area.b.x = rect.b.x; area.b.y = y_grid * 17.5; if (plep_update(plep, &area, g_clear_wf) < 0) ret = -1; LOG("colour shades"); area.a.x = x_grid * 23.5 - width; area.a.y = y_grid * 6.5; area.b.x = x_grid * 23.5; area.b.y = y_grid * 17.5; i = 0; rect.a.x = area.a.x; rect.a.y = area.a.y; rect.b.y = area.b.y; for (i = 1; i <= 90; ++i) { const int r = pldraw_grey_16[get_shade(0, i)]; const int g = pldraw_grey_16[get_shade(30, i)]; const int b = pldraw_grey_16[get_shade(60, i)]; const pldraw_color_t col = pldraw_get_color(pldraw, r, g, b); rect.b.x = area.a.x + (width * i / 90); pldraw_fill_rect(pldraw, col, &rect); rect.a.x = rect.b.x; } if (plep_update(plep, &area, g_clear_wf) < 0) ret = -1; pldraw_set_rotation(pldraw, cur_rotation); return ret; }