Index: cap.c =================================================================== --- cap.c (revision 7395) +++ cap.c (nonexistent) @@ -1,306 +0,0 @@ -#include -#include -#include -#include -#include -#include "c24lib/image/image.h" -#include "c24lib/image/draw.h" -#include "c24lib/image/pnm.h" - -#include "pcb_draw.h" -#include "gp.h" - -#define DUMPDIR "/tmp/gpstroke/" - -#define STROKE_PENALTY 150 -#define MAX_TH 12 -#define MIN_TH 8 - -#define MAX_STROKES 64 -int max_strokes = 16; -image_t *ref, *canvas; - -typedef struct { - int x1, y1, x2, y2, th; -} stroke_t; - -typedef struct { - int len; - stroke_t str[MAX_STROKES]; -} pcb_t; - - -long *black; -long black_len; -double stroke_penalty; - -/* Random value between from and to, inclusive */ -int myrand(int from, int to) -{ - return from + rand() % (to - from + 1); -} - -static inline void rand_stroke(stroke_t *s) -{ - s->x1 = myrand(0, ref->sx-1); - s->x2 = myrand(0, ref->sx-1); - s->y1 = myrand(0, ref->sy-1); - s->y2 = myrand(0, ref->sy-1); - s->th = myrand(1, MAX_TH); -} - -pcb_t *default_new = NULL; - -pcb_t *load_str(char *fn) -{ - char line[256]; - FILE *f = fopen(fn, "r"); - pcb_t *p; - if (f == NULL) - return 0; - p = calloc(sizeof(pcb_t), 1); - while(fgets(line, sizeof(line), f) != NULL) { - char *s = line; - int x1, y1, x2, y2, th; - if (strncmp(s, "stroke", 6) == 0) - s+=6; - - if (sscanf(s, "%d %d %d %d %d", &x1, &y1, &x2, &y2, &th) == 5) { - stroke_t *s = &p->str[p->len]; - s->x1 = x1; - s->y1 = y1; - s->x2 = x2; - s->y2 = y2; - s->th = th; - p->len++; - } - } - fclose(f); - return p; -} - -void *pcb_create(void) -{ - pcb_t *p = malloc(sizeof(pcb_t)); - int n; - - if (default_new != NULL) { - memcpy(p, default_new, sizeof(pcb_t)); - return p; - } - - p->len = myrand(1, max_strokes/2); - for(n = 0; n < p->len; n++) - rand_stroke(&p->str[n]); - - return p; -} - -static inline void pcb_clear(image_t *img) -{ - int n; - pixel_t *p = img->pixmap; - for(n = 0; n < img->sx * img->sy; n++,p++) { - *p = pixel_white; - } -} - -static inline long int pcb_diff(const image_t *img1, const image_t *img2) -{ - long int diff = 0; - int n; - const pixel_t *p1 = img1->pixmap; - const pixel_t *p2 = img2->pixmap; - for(n = 0; n < img1->sx * img1->sy; n++,p1++,p2++) { - if ((p1->r != p2->r) || (p1->g != p2->g) || (p1->b != p2->b)) - diff++; - } - return diff; -} - -static inline void pcb_shadow(image_t *dst, const image_t *src) -{ - int n; - pixel_t *d = dst->pixmap; - const pixel_t *s = src->pixmap; - for(n = 0; n < dst->sx * dst->sy; n++,d++,s++) { - if ((s->r != 255) && (s->g != 255) && (s->b != 255)) { - d->r = 200; - d->g = 240; - d->b = 240; - } - else - *d = pixel_white; - } -} - -static inline long pcb_list_black(const image_t *src, long *bl) -{ - long n, cnt = 0; - const pixel_t *s = src->pixmap; - for(n = 0; n < src->sx * src->sy; n++,s++) { - if ((s->r != 255) && (s->g != 255) && (s->b != 255)) { - if (bl != NULL) - bl[cnt] = n; - cnt++; - } - } - return cnt; -} - -#define clamp(v, min, max) ((v) < (min) ? (min) : ((v) > (max) ? (max) : (v))) - -static inline void pcb_draw(image_t *img, pcb_t *p) -{ - int n; - - draw_color(pixel_black); - for(n = 0; n < p->len; n++) - draw_pcb_line(img, p->str[n].x1, p->str[n].y1, p->str[n].x2, p->str[n].y2, clamp(p->str[n].th, MIN_TH, MAX_TH)); -} - -double pcb_score(void *data) -{ - pcb_t *p = data; - double scr; - - pcb_clear(canvas); - pcb_draw(canvas, data); - scr = pcb_diff(canvas, ref); - return scr + (p->len+1) * stroke_penalty; -} - -static inline void pcb_mutate_add(pcb_t *p) -{ - int loc, x, y; - if (p->len >= MAX_STROKES) - return; - - loc = myrand(0, black_len-1); - - x = image_x(ref, ref->pixmap+black[loc]); - y = image_y(ref, ref->pixmap+black[loc]); - - p->str[p->len].x1 = x; - p->str[p->len].y1 = y; - p->str[p->len].x2 = x + myrand(2, 20) - 10; - p->str[p->len].y2 = y + myrand(2, 20) - 10; - p->str[p->len].th = myrand(3, 10); - p->len++; -} - -static inline void pcb_mutate_del(pcb_t *p) -{ - int rem, idx; - - if (p->len < 2) - return; - - idx = myrand(0, p->len-1); - rem = p->len - idx - 1; - if (rem > 0) - memmove(p->str+idx, p->str+idx+1, rem*sizeof(stroke_t)); - p->len--; -} - -#define tune(dst, min, max, delta) \ - if ((dst + delta >= min) && (dst + delta <= max)) dst += delta; - -static inline void pcb_mutate_chg(pcb_t *p) -{ - int idx = myrand(0, p->len); - int fld = myrand(0, 5); - int dir = (rand() % 2) ? +1 : -1; - - switch(fld) { - case 0: tune(p->str[idx].x1, 0, ref->sx, dir); break; - case 1: tune(p->str[idx].x2, 0, ref->sx, dir); break; - case 2: tune(p->str[idx].y1, 0, ref->sy, dir); break; - case 3: tune(p->str[idx].y2, 0, ref->sy, dir); break; - case 4: tune(p->str[idx].th, 0, (ref->sx + ref->sy)/8, dir); break; - case 5: rand_stroke(&p->str[idx]); break; - } -} - -void pcb_mutate(void *data) -{ - int n=myrand(0, 100); - if (n > 65) - pcb_mutate_chg(data); - else if (n % 2) - pcb_mutate_add(data); - else - pcb_mutate_del(data); -} - -void pcb_clone(void *dst, void *src) -{ - memcpy(dst, src, sizeof(pcb_t)); -} - - - -const char *pcb_dump(void *data, int population_id, int individual_id) -{ - pcb_t *p = data; - image_t *img = canvas; - static char s[256]; - FILE *f; - int n; - - snprintf(s, sizeof(s), DUMPDIR "stroke_%04d_%02d.str", population_id, individual_id); - f = fopen(s, "w"); - for(n = 0; n < p->len; n++) - fprintf(f,"stroke %d %d %d %d %d\n", p->str[n].x1, p->str[n].y1, p->str[n].x2, p->str[n].y2, p->str[n].th); - fclose(f); - - pcb_shadow(img, ref); - pcb_draw(img, data); - snprintf(s, sizeof(s), DUMPDIR "stroke_%04d_%02d.pnm", population_id, individual_id); - pnm_save(img, s); - return s; -} - -gp_pop_t pop = { - .len = 16, - .weak_kill = 5, - .clone_times = 2, - .create = pcb_create, - .score = pcb_score, - .mutate = pcb_mutate, - .clone = pcb_clone, - .dump = pcb_dump -}; - -int main(int argc, char *argv[]) -{ - int n; - char *ref_fn = "l.pnm"; - - if (argv[1] != NULL) - ref_fn = argv[1]; - - if (argv[2] != NULL) - default_new = load_str(argv[2]); - - srand(time(NULL)); - ref = pnm_load(ref_fn); - - black_len = pcb_list_black(ref, NULL); - black = malloc(sizeof(long) * black_len); - black_len = pcb_list_black(ref, black); - - stroke_penalty = ref->sx * ref->sy / STROKE_PENALTY; - - canvas = image_new(ref->sx, ref->sy); - - gp_setup(&pop); - - for(n = 0; n < 10000; n++) { - gp_iterate(&pop); - if ((pop.pop_cnt % 20) == 0) - gp_dump(stdout, &pop, 1); - } - pnm_save(ref, DUMPDIR "ref.pnm"); - free(black); -} Index: Makefile =================================================================== --- Makefile (revision 7395) +++ Makefile (revision 7396) @@ -1,3 +1,5 @@ CFLAGS = -Wall -g -O3 LDFLAGS = -lm -cap: cap.o pcb_draw.o gp.o c24lib/image/draw.o c24lib/image/image.o c24lib/image/pnm.o \ No newline at end of file +find_line_indep: find_line_indep.o pcb_draw.o gp.o c24lib/image/draw.o c24lib/image/image.o c24lib/image/pnm.o + +find_line_indep.o: pcb_common.h gp.h Index: find_line_indep.c =================================================================== --- find_line_indep.c (nonexistent) +++ find_line_indep.c (revision 7396) @@ -0,0 +1,183 @@ +#include +#include +#include +#include +#include +#include "c24lib/image/image.h" +#include "c24lib/image/draw.h" +#include "c24lib/image/pnm.h" + +#include "pcb_draw.h" +#include "gp.h" + +#define DUMPDIR "/tmp/gpstroke/" + +#define STROKE_PENALTY 150 +#define MAX_TH 12 +#define MIN_TH 8 + +#define MAX_STROKES 64 +int max_strokes = 16; +image_t *ref, *canvas; + +typedef struct { + int x1, y1, x2, y2, th; +} stroke_t; + +typedef struct { + int len; + stroke_t str[MAX_STROKES]; +} pcb_t; + +#include "pcb_common.h" + +static inline void pcb_draw(image_t *img, pcb_t *p) +{ + int n; + + draw_color(pixel_black); + for(n = 0; n < p->len; n++) + draw_pcb_line(img, p->str[n].x1, p->str[n].y1, p->str[n].x2, p->str[n].y2, clamp(p->str[n].th, MIN_TH, MAX_TH)); +} + +static inline void rand_stroke(stroke_t *s) +{ + s->x1 = myrand(0, ref->sx-1); + s->x2 = myrand(0, ref->sx-1); + s->y1 = myrand(0, ref->sy-1); + s->y2 = myrand(0, ref->sy-1); + s->th = myrand(1, MAX_TH); +} + +static pcb_t *load_str(char *fn) +{ + char line[256]; + FILE *f = fopen(fn, "r"); + pcb_t *p; + if (f == NULL) + return 0; + p = calloc(sizeof(pcb_t), 1); + while(fgets(line, sizeof(line), f) != NULL) { + char *s = line; + int x1, y1, x2, y2, th; + if (strncmp(s, "stroke", 6) == 0) + s+=6; + + if (sscanf(s, "%d %d %d %d %d", &x1, &y1, &x2, &y2, &th) == 5) { + stroke_t *s = &p->str[p->len]; + s->x1 = x1; + s->y1 = y1; + s->x2 = x2; + s->y2 = y2; + s->th = th; + p->len++; + } + } + fclose(f); + return p; +} + +void *pcb_create(void) +{ + pcb_t *p = malloc(sizeof(pcb_t)); + int n; + + if (default_new != NULL) { + memcpy(p, default_new, sizeof(pcb_t)); + return p; + } + + p->len = myrand(1, max_strokes/2); + for(n = 0; n < p->len; n++) + rand_stroke(&p->str[n]); + + return p; +} + +static inline void pcb_mutate_add(pcb_t *p) +{ + int loc, x, y; + if (p->len >= MAX_STROKES) + return; + + loc = myrand(0, black_len-1); + + x = image_x(ref, ref->pixmap+black[loc]); + y = image_y(ref, ref->pixmap+black[loc]); + + p->str[p->len].x1 = x; + p->str[p->len].y1 = y; + p->str[p->len].x2 = x + myrand(2, 20) - 10; + p->str[p->len].y2 = y + myrand(2, 20) - 10; + p->str[p->len].th = myrand(3, 10); + p->len++; +} + +static inline void pcb_mutate_del(pcb_t *p) +{ + int rem, idx; + + if (p->len < 2) + return; + + idx = myrand(0, p->len-1); + rem = p->len - idx - 1; + if (rem > 0) + memmove(p->str+idx, p->str+idx+1, rem*sizeof(stroke_t)); + p->len--; +} + +static inline void pcb_mutate_chg(pcb_t *p) +{ + int idx = myrand(0, p->len); + int fld = myrand(0, 5); + int dir = (rand() % 2) ? +1 : -1; + + switch(fld) { + case 0: tune(p->str[idx].x1, 0, ref->sx, dir); break; + case 1: tune(p->str[idx].x2, 0, ref->sx, dir); break; + case 2: tune(p->str[idx].y1, 0, ref->sy, dir); break; + case 3: tune(p->str[idx].y2, 0, ref->sy, dir); break; + case 4: tune(p->str[idx].th, 0, (ref->sx + ref->sy)/8, dir); break; + case 5: rand_stroke(&p->str[idx]); break; + } +} + +void pcb_mutate(void *data) +{ + int n=myrand(0, 100); + if (n > 65) + pcb_mutate_chg(data); + else if (n % 2) + pcb_mutate_add(data); + else + pcb_mutate_del(data); +} + +gp_pop_t pop = { + .len = 16, + .weak_kill = 5, + .clone_times = 2, + .create = pcb_create, + .score = pcb_score, + .mutate = pcb_mutate, + .clone = pcb_clone, + .dump = pcb_dump +}; + +int main(int argc, char *argv[]) +{ + int n; + + common_init(argc, argv); + + gp_setup(&pop); + + for(n = 0; n < 10000; n++) { + gp_iterate(&pop); + if ((pop.pop_cnt % 20) == 0) + gp_dump(stdout, &pop, 1); + } + pnm_save(ref, DUMPDIR "ref.pnm"); + free(black); +} Index: pcb_common.h =================================================================== --- pcb_common.h (nonexistent) +++ pcb_common.h (revision 7396) @@ -0,0 +1,130 @@ +static inline void pcb_draw(image_t *img, pcb_t *p); +static pcb_t *load_str(char *fn); + +pcb_t *default_new = NULL; + +long *black; +long black_len; +double stroke_penalty; + +/* Random value between from and to, inclusive */ +static inline int myrand(int from, int to) +{ + return from + rand() % (to - from + 1); +} + +static inline void pcb_clear(image_t *img) +{ + int n; + pixel_t *p = img->pixmap; + for(n = 0; n < img->sx * img->sy; n++,p++) { + *p = pixel_white; + } +} + +static inline long int pcb_diff(const image_t *img1, const image_t *img2) +{ + long int diff = 0; + int n; + const pixel_t *p1 = img1->pixmap; + const pixel_t *p2 = img2->pixmap; + for(n = 0; n < img1->sx * img1->sy; n++,p1++,p2++) { + if ((p1->r != p2->r) || (p1->g != p2->g) || (p1->b != p2->b)) + diff++; + } + return diff; +} + +static inline void pcb_shadow(image_t *dst, const image_t *src) +{ + int n; + pixel_t *d = dst->pixmap; + const pixel_t *s = src->pixmap; + for(n = 0; n < dst->sx * dst->sy; n++,d++,s++) { + if ((s->r != 255) && (s->g != 255) && (s->b != 255)) { + d->r = 200; + d->g = 240; + d->b = 240; + } + else + *d = pixel_white; + } +} + +static inline long pcb_list_black(const image_t *src, long *bl) +{ + long n, cnt = 0; + const pixel_t *s = src->pixmap; + for(n = 0; n < src->sx * src->sy; n++,s++) { + if ((s->r != 255) && (s->g != 255) && (s->b != 255)) { + if (bl != NULL) + bl[cnt] = n; + cnt++; + } + } + return cnt; +} + +#define clamp(v, min, max) ((v) < (min) ? (min) : ((v) > (max) ? (max) : (v))) + +double pcb_score(void *data) +{ + pcb_t *p = data; + double scr; + + pcb_clear(canvas); + pcb_draw(canvas, data); + scr = pcb_diff(canvas, ref); + return scr + (p->len+1) * stroke_penalty; +} + +#define tune(dst, min, max, delta) \ + if ((dst + delta >= min) && (dst + delta <= max)) dst += delta; + +void pcb_clone(void *dst, void *src) +{ + memcpy(dst, src, sizeof(pcb_t)); +} + +const char *pcb_dump(void *data, int population_id, int individual_id) +{ + pcb_t *p = data; + image_t *img = canvas; + static char s[256]; + FILE *f; + int n; + + snprintf(s, sizeof(s), DUMPDIR "stroke_%04d_%02d.str", population_id, individual_id); + f = fopen(s, "w"); + for(n = 0; n < p->len; n++) + fprintf(f,"stroke %d %d %d %d %d\n", p->str[n].x1, p->str[n].y1, p->str[n].x2, p->str[n].y2, p->str[n].th); + fclose(f); + + pcb_shadow(img, ref); + pcb_draw(img, data); + snprintf(s, sizeof(s), DUMPDIR "stroke_%04d_%02d.pnm", population_id, individual_id); + pnm_save(img, s); + return s; +} + +static inline void common_init(int argc, char *argv[]) +{ + char *ref_fn = "l.pnm"; + + if (argv[1] != NULL) + ref_fn = argv[1]; + + if (argv[2] != NULL) + default_new = load_str(argv[2]); + + srand(time(NULL)); + ref = pnm_load(ref_fn); + + black_len = pcb_list_black(ref, NULL); + black = malloc(sizeof(long) * black_len); + black_len = pcb_list_black(ref, black); + + stroke_penalty = ref->sx * ref->sy / STROKE_PENALTY; + + canvas = image_new(ref->sx, ref->sy); +}