Răsfoiți Sursa

population experiments

Kajetan Johannes Hammerle 4 ani în urmă
părinte
comite
be931b75bd
2 a modificat fișierele cu 146 adăugiri și 153 ștergeri
  1. 145 152
      Main.c
  2. 1 1
      Makefile

+ 145 - 152
Main.c

@@ -1,59 +1,108 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+typedef struct {
+    int fitness;
+    int* data;
+} Square;
+
+Square* squares;
+
 int size = 0;
-int *data = NULL;
-int (*fitness)() = NULL;
+int population = 0;
+int (*fitness)(int*) = NULL;
+
+int compare(const void* a, const void* b) {
+    int ia = ((Square*)a)->fitness;
+    int ib = ((Square*)b)->fitness;
+    return ia < ib ? -1 : (ia > ib ? 1 : 0);
+}
+
+void sort() {
+    qsort(squares, population, sizeof(Square), compare);
+}
+
+void mutate(int* data) {
+    int a = rand() % (size * size);
+    int b = rand() % (size * size);
+    while(b == a) {
+        b = rand() % (size * size);
+    }
+
+    int tmp = data[a];
+    data[a] = data[b];
+    data[b] = tmp;
+}
+
+void reproduce(const int* parent, Square* child) {
+    int end = size * size;
+    for(int i = 0; i < end; i++) {
+        child->data[i] = parent[i];
+    }
+    mutate(child->data);
+    child->fitness = fitness(child->data);
+}
 
-void init()
-{
+void init() {
+    squares = malloc(sizeof(Square) * population);
     int end = size * size;
-    data = malloc(sizeof(int) * end);
-    for (int i = 0; i < end; i++)
-    {
-        data[i] = i + 1;
+    for(int i = 0; i < population; i++) {
+        squares[i].data = malloc(sizeof(int) * end);
+        for(int k = 0; k < end; k++) {
+            squares[i].data[k] = k + 1;
+        }
+        for(int k = 0; k < end; k++) {
+            mutate(squares[i].data);
+        }
+        squares[i].fitness = fitness(squares[i].data);
+    }
+}
+
+void clear() {
+    for(int i = 0; i < population; i++) {
+        free(squares[i].data);
     }
+    free(squares);
 }
 
-int get(int x, int y) { return data[y * size + x]; }
+int get(int* data, int x, int y) {
+    return data[y * size + x];
+}
 
-int errorFactor(int e) { return e * e; }
+int errorFactor(int e) {
+    return e * e;
+}
 
-int getWanted() { return (size * (size * size + 1)) / 2; }
+int getWanted() {
+    return (size * (size * size + 1)) / 2;
+}
 
-int getSemiFitness()
-{
+int getSemiFitness(int* data) {
     int fitness = 0;
     int wanted = getWanted();
-    for (int y = 0; y < size; y++)
-    {
+    for(int y = 0; y < size; y++) {
         int sum = 0;
-        for (int x = 0; x < size; x++)
-        {
-            sum += get(x, y);
+        for(int x = 0; x < size; x++) {
+            sum += get(data, x, y);
         }
         fitness += errorFactor(sum - wanted);
     }
-    for (int x = 0; x < size; x++)
-    {
+    for(int x = 0; x < size; x++) {
         int sum = 0;
-        for (int y = 0; y < size; y++)
-        {
-            sum += get(x, y);
+        for(int y = 0; y < size; y++) {
+            sum += get(data, x, y);
         }
         fitness += errorFactor(sum - wanted);
     }
     return fitness;
 }
 
-int getDiagonalBase()
-{
+int getDiagonalBase(int* data) {
     int diaA = 0;
     int diaB = 0;
-    for (int i = 0; i < size; i++)
-    {
-        diaA += get(i, i);
-        diaB += get(i, (size - 1) - i);
+    for(int i = 0; i < size; i++) {
+        diaA += get(data, i, i);
+        diaB += get(data, i, (size - 1) - i);
     }
     int wanted = getWanted();
     int fitness = errorFactor(diaA - wanted);
@@ -61,20 +110,19 @@ int getDiagonalBase()
     return fitness;
 }
 
-int getNormalFitness() { return getSemiFitness() + getDiagonalBase(); }
+int getNormalFitness(int* data) {
+    return getSemiFitness(data) + getDiagonalBase(data);
+}
 
-int getPandiagonalBase()
-{
+int getPandiagonalBase(int* data) {
     int fitness = 0;
     int wanted = getWanted();
-    for (int x = 0; x < size; x++)
-    {
+    for(int x = 0; x < size; x++) {
         int sumA = 0;
         int sumB = 0;
-        for (int y = 0; y < size; y++)
-        {
-            sumA += get((x + y) % size, y);
-            sumB += get((x - y + size) % size, y);
+        for(int y = 0; y < size; y++) {
+            sumA += get(data, (x + y) % size, y);
+            sumB += get(data, (x - y + size) % size, y);
         }
         fitness += errorFactor(sumA - wanted);
         fitness += errorFactor(sumB - wanted);
@@ -82,162 +130,107 @@ int getPandiagonalBase()
     return fitness;
 }
 
-int getAssociativeBase()
-{
+int getAssociativeBase(int* data) {
     int fitness = 0;
     int wanted = size * size + 1;
-    for (int x = 0; x < size; x++)
-    {
-        for (int y = 0; y < size; y++)
-        {
-            int sum = get(x, y) + get(size - x - 1, size - y - 1);
+    for(int x = 0; x < size; x++) {
+        for(int y = 0; y < size; y++) {
+            int sum = get(data, x, y) + get(data, size - x - 1, size - y - 1);
             fitness += errorFactor(sum - wanted);
         }
     }
     return fitness;
 }
 
-int getUltraFitness()
-{
-    return getSemiFitness() + getPandiagonalBase() + getAssociativeBase();
+int getUltraFitness(int* data) {
+    return getSemiFitness(data) + getPandiagonalBase(data) +
+           getAssociativeBase(data);
 }
 
-int get2x2SquareBase()
-{
+int get2x2SquareBase(int* data) {
     int fitness = 0;
     int wanted = 2 * (size * size + 1);
-    for (int x = 0; x < size; x++)
-    {
-        for (int y = 0; y < size; y++)
-        {
-            if (x % 2 == 0 && y % 2 == 0)
-            {
-                int sum = get(x, y) + get(x + 1, y) + get(x, y + 1) +
-                          get(x + 1, y + 1);
+    for(int x = 0; x < size; x++) {
+        for(int y = 0; y < size; y++) {
+            if(x % 2 == 0 && y % 2 == 0) {
+                int sum = get(data, x, y) + get(data, x + 1, y) +
+                          get(data, x, y + 1) + get(data, x + 1, y + 1);
                 fitness += errorFactor(sum - wanted);
             }
         }
     }
     return fitness;
 }
-int getPerfectDiagonalBase()
-{
+
+int getPerfectDiagonalBase(int* data) {
     int fitness = 0;
     int wanted = size * size + 1;
-    for (int x = 0; x < size / 2; x++)
-    {
-        for (int y = 0; y < size; y++)
-        {
-            int sum =
-                get(x, y) + get((x + size / 2) % size, (y + size / 2) % size);
+    for(int x = 0; x < size / 2; x++) {
+        for(int y = 0; y < size; y++) {
+            int sum = get(data, x, y) +
+                      get(data, (x + size / 2) % size, (y + size / 2) % size);
             fitness += errorFactor(sum - wanted);
         }
     }
     return fitness;
 }
 
-int getMostPerfectFitness()
-{
-    // printf("ultra: %d\n", getUltraFitness());
-    // printf("square: %d\n", get2x2SquareBase());
-    // printf("diagonal: %d\n", getPerfectDiagonalBase());
-    return getSemiFitness() + getPandiagonalBase() + get2x2SquareBase() +
-           getPerfectDiagonalBase();
+int getMostPerfectFitness(int* data) {
+    return getSemiFitness(data) + getPandiagonalBase(data) +
+           get2x2SquareBase(data) + getPerfectDiagonalBase(data);
 }
 
-void print()
-{
-    printf("Fitness: %d\n", fitness());
-    for (int y = 0; y < size; y++)
-    {
-        for (int x = 0; x < size; x++)
-        {
-            printf("%2d ", get(x, y));
+void print(Square* s) {
+    printf("Fitness: %d\n", s->fitness);
+    for(int y = 0; y < size; y++) {
+        for(int x = 0; x < size; x++) {
+            printf("%2d ", get(s->data, x, y));
         }
         putchar('\n');
     }
     putchar('\n');
 }
 
-void swap(int a, int b)
-{
-    int tmp = data[a];
-    data[a] = data[b];
-    data[b] = tmp;
-}
-
-void randSwaps(int swaps)
-{
-    for (int i = 0; i < swaps; i++)
-    {
-        swap(rand() % (size * size), rand() % (size * size));
-    }
-}
-
-int main(int argAmount, char **args)
-{
-    if (argAmount < 5)
-    {
-        if (argAmount <= 0)
-        {
-            printf("... <type> <size> <tries> <generations>\n");
-        }
-        else
-        {
-            printf("%s <type> <size> <tries> <generations>\n", args[0]);
+int main(int argAmount, char** args) {
+    if(argAmount < 4) {
+        if(argAmount <= 0) {
+            printf("... <type> <size> <population>\n");
+        } else {
+            printf("%s <type> <size> <population>\n", args[0]);
         }
         return 0;
     }
     int type = atoi(args[1]);
     size = atoi(args[2]);
-    int tries = atoi(args[3]);
-    int generations = atoi(args[4]);
-
-    switch (type)
-    {
-    case 1:
-        fitness = getNormalFitness;
-        break;
-    case 2:
-        fitness = getUltraFitness;
-        break;
-    case 3:
-        fitness = getMostPerfectFitness;
-        break;
-    default:
-        puts("unknown type");
-        return 0;
+    population = atoi(args[3]);
+    if(population < 4) {
+        population = 4;
+    }
+    switch(type) {
+        case 1: fitness = getNormalFitness; break;
+        case 2: fitness = getUltraFitness; break;
+        case 3: fitness = getMostPerfectFitness; break;
+        default: puts("unknown type"); return 0;
     }
 
-    init();
-    for (int k = 0; k < tries; k++)
-    {
-        for (int i = 0; i < generations; i++)
-        {
-            int oldFitness = fitness();
-
-            int a = rand() % (size * size);
-            int b = rand() % (size * size);
-            swap(a, b);
-
-            int newFitness = fitness();
-            if (newFitness == 0)
-            {
-                break;
-            }
-
-            if (newFitness >= oldFitness)
-            {
-                swap(a, b);
+    for(int h = 0; h < 5; h++) {
+        init();
+        int half = population / 2;
+        int run = 1;
+        while(run) {
+            sort();
+            for(int k = half; k < population; k++) {
+                int parent = rand() % half;
+                reproduce(squares[parent].data, squares + k);
+                if(squares[k].fitness == 0) {
+                    run = 0;
+                    break;
+                }
             }
         }
-        // if (fitness() < 50)
-        if (fitness() == 0)
-        {
-            print();
-        }
-        randSwaps(100);
+        sort();
+        print(squares);
+        clear();
     }
-    free(data);
     return 0;
-}
+}

+ 1 - 1
Makefile

@@ -1,5 +1,5 @@
 run: build
-	./magic 2 9 500000 1000000
+	./magic 2 7 50000
 
 build: Main.c 
 	gcc -o magic Main.c -Wall -Wextra -pedantic -Werror -O3