์ ์ ์๊ณ ๋ฆฌ์ฆ : Meta Heuristic ๊ณ์ด์ ์๊ณ ๋ฆฌ์ฆ
๋ค์ํ ๋ฌธ์ ์ ๋ํด ๊ฒฝํ์ ์ผ๋ก ์๋ฃจ์ ์ ์ ์ํ๋ ์๊ณ ๋ฆฌ์ฆ
๋ชฉ์
์ฃผ์ด์ง ๋ฌธ์ ์ ๋ํด์ ์ต์ ์ ์๋ฃจ์ ์ ์ฐพ๋ ๊ฒ (์ฆ, ์ต์ ํด๋ฅผ ์ฐพ๋ ๊ฒ)
- ์ ์ ์๊ณ ๋ฆฌ์ฆ์ ์๊ณ ๋ฆฌ์ฆ ํน์ฑ์ ๊ณผ์ ๊ณผ ๊ฒฐ๊ณผ ์ค๋ช ์ด ๊ต์ฅํ ์ด๋ ค์. ๋ฌด์์์ฑ์ด ์กด์ฌํจ
์๋ฌผํ์์ ์๋ฌผ๋ค์ ์์กด ๋ฒ์น์ธ ์ ์์์กด์ ๊ธฐ๋ฐ์ผ๋ก ํ ์๊ณ ๋ฆฌ์ฆ
- ํ๊ฒฝ์ ์ ํฉํ ๊ฐ์ฒด๊ฐ ์ด์๋จ๋๋ค.
- ์ด์๋จ์ ๊ฐ์ฒด๋ ๋ฒ์์ ํ๋ค.
- ์ด์๋จ์ ๊ฐ์ฒด๋ ๊ฐ๊ฐ ๋ถ๋ชจ๊ฐ ๋์ด ์์์ ์์ฑํ๋๋ฐ, ์์์ ๋ถ์ ๋ชจ์ ์ ์ ์๋ฅผ ๋ฐ๊ณ
๋๋๋ก ๋์ฐ๋ณ์ด ์ ์ ์๋ฅผ ๋ฐ์ ๋ค์ ์ธ๋๋ฅผ ์ด์๊ฐ๋ค.
→ ์์ ์ธ ๊ฐ์ง๋ฅผ ๋ฐ๋ณตํ๋ฉด ํ๊ฒฝ์ ์ ํฉํ ๊ฐ์ฒด๋ค์ด ์ด์๋จ๊ณ ๊ทธ ๊ฐ์ฒด๋ค์ด ์ข์ ์๋ฃจ์ ์ ์ ์ํ๋ค.
์๊ณ ๋ฆฌ์ฆ์ ์ฐ์ด๋ ์ฉ์ด์ ํํ
- ๊ฐ์ฒด : individual
- ๋จ์ฒด : population
- ์ ํฉ๋ ํจ์ : fitness function f (๋ฌธ์ ๋ง๋ค ๋ค๋ฅด๋ค. ์ข์ ํด๋ต์ ์ฃผ๋ฉด ์ ํฉ๋๊ฐ ๋๊ฒ ์ ์)
individual ์ ํ ๋ฐฉ๋ฒ
1. ํ ๋๋จผํธ ์ ํ
2. ์ ๋จ ์ ํ
3. ์ ํฉ๋ ๋น๋ก ์ ํ
- ํจ์์ ์ ํฉ๋ ๊ฐ์ sampling ๋ ํ๋ฅ ๊ฐ์ผ๋ก ๋ณํํด์ ์ ํฉ๋๊ฐ ๋์ผ๋ฉด ์ฝ๊ฒ ์ ํํจ
4. ์ ์์ฃผ์
- 3๋จ๊ณ๋ฅผ ๊ฑฐ์น์ง ์๊ณ ์ฐ์ํ individual์ด ๊ทธ๋ฅ ์ง์ถ
์ ์ ์ฐ์ฐ ๋ฐฉ๋ฒ
1. ๊ต๋ฐฐ (crossover)
DNA์ผ์์ฒด๊ฐ ๊ผฌ์ฌ ์ด๋จธ๋, ์๋ฒ์ง ์ ์ ํ์ง์ ๋ฐ๋ฐ ๊ฐ์ง๊ฒ ๋๋ ๊ฒ๊ณผ ๋น์ทํ๋ค.
2. ๋์ฐ๋ณ์ด
๋ฌธ์ ์ ๋ฐ๋ผ์ ๋์ฐ๋ณ์ด๋ ์ข์ ์ํฅ์ ์ฃผ๊ธฐ๋ ํ๊ณ ๋์ ์ํฅ์ ์ฃผ๊ธฐ๋ ํ๋ค.
๋์ฐ๋ณ์ด๊ฐ ์ธ์ ๋ํ๋๋์ง ์ ์ ์๋ค.
์ ์ ์๊ณ ๋ฆฌ์ฆ์ pseudo code
T = 0
initialize population
//์ ํฉ๋ ๊ณ์ฐ
while (์ ํฉ๋ ์ฐพ์ง ๋ชปํจ) {
T += 1
population์์ ์ ํ (selection)
์ ์ ์ฐ์ฐ (์ ํ๋ individuals)
์ ํฉ๋ ๊ณ์ฐ
}
์ ์ ์๊ณ ๋ฆฌ์ฆ ์์ ๋ฌธ์
1. ๊ธ๊ดด ๋ด๊ธฐ
10kg์ ๋ด์ ์ ์๋ ๊ฐ๋ฐฉ์ด ์๋ค. ๋ค์๊ณผ ๊ฐ์ด 6๊ฐ์ ๊ธ๊ดด๊ฐ ์กด์ฌํ ๋, ๊ธ๊ดด๋ค์ด 10kg์ ๋์ง ์์ผ๋ฉด์ ๊ฐ์ฅ ๊ฐ์ด์น๊ฐ ๋๋๋ก ๊ธ๊ดด๋ค์ ์ ํํ์ฌ ๊ฐ๋ฐฉ์ ๋ด์์ผ ํ๋ค.
gold 1 : (4kg, $6)
gold 2 : (4kg, $7)
gold 3 : (3kg, $5)
gold 4 : (2kg, $4)
gold 5 : (1kg, $3)
gold 6 : (6kg, $9)
๊ฐ์ฒด (individuals) : size๊ฐ 6์ธ ๋ฐฐ์ด. ๊ฐ index๋ ๊ธ๊ดด๋ฒํธ, ๋ฐฐ์ด์ ๊ฐ์ 1(์ ํ) ๋๋ 0(์ ํX)
์ ํฉ๋ ๊ณ์ฐ : ๊ฐ์ฒด๊ฐ ์ ํํ ๊ธ๊ดด๋ค์ ๋ฌด๊ฒ ์ดํฉ์ด 10 ์ดํ์ฌ์ผ ํ๋ฉฐ, ๊ฐ์ด์น๊ฐ ํด์๋ก ์ข์
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define select_ratio 0.5f
#define population_size 12
#define mutation_ratio 0.05f
#define max_w 10
#define max_unchanged 40
typedef struct {
int w; // ๊ธ๊ดด์ ๋ฌด๊ฒ
int v; // ๊ธ๊ดด์ ๊ฐ์ด์น
} Gold;
typedef struct {
int sum; // ์ ํํ ๊ธ๊ดด์ ๋ฌด๊ฒ ํฉ๊ณ
int val; // ์ ํํ ๊ธ๊ดด์ ๊ฐ์ด์น ์ดํฉ
int* code; // ๊ธ๊ดด ์ ํ ์ฌ๋ถ๋ฅผ ๋ํ๋ด๋ ์ด์ง ์ฝ๋ (0 : ์ ํํ์ง ์์ / 1 : ์ ํํจ)
} Chromosome;
// ๊ธ๊ดด์ ๋ฌด๊ฒ์ ๊ฐ์น๋ฅผ ํฌํจํ์ฌ ๊ธ๊ดด๋ฅผ ์์ฑ
void makeGold(Gold** golds) {
*golds = (Gold*)malloc(6 * sizeof(Gold));
(*golds)[0].w = 4;
(*golds)[0].v = 6;
// ๋๋จธ์ง ๊ธ๊ดด์ ๋ฌด๊ฒ์ ๊ฐ์น๋ฅผ ์ด๊ธฐํํด์ผ ํจ
}
// ์ด๊ธฐ ์ผ์์ฒด(population)๋ฅผ ์์ฑํ๋ ํจ์
// ๊ฐ ๊ธ๊ดด์ ๋ํด ๋ฌด์์ ํ๋ฅ ์ ์ฌ์ฉํ์ฌ ์ ํ ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ๋ฉฐ, ์ ํ๋ ๊ธ๊ดด์ ๋ฌด๊ฒ ๋ฐ ๊ฐ์น์ ํฉ๊ณ ๊ณ์ฐ
void makeChromosomes(Gold* golds, Chromosome* population) {
int cnt = 0;
while (cnt < population_size) {
Chromosome c;
c.sum = 0;
c.val = 0;
c.code = (int*)malloc(6 * sizeof(int));
for (int i = 0; i < 6; i++) {
double rand_v = (double)rand() / RAND_MAX;
if (rand_v > 0.5) {
c.code[i] = 1; // ๊ธ๊ดด ์ ํ
c.sum += golds[i].w;
c.val += golds[i].v;
} else {
c.code[i] = 0; // ๊ธ๊ดด ๋ฏธ์ ํ
}
}
if (c.sum <= max_w) {
population[cnt++] = c; // ์ผ์์ฒด๋ฅผ ์ผ์์ฒด ์ง๋จ(population)์ ์ถ๊ฐ
} else {
free(c.code); // ๋ฌด๊ฒ๊ฐ ์ต๋๊ฐ์ ์ด๊ณผํ๋ ๊ฒฝ์ฐ ์ผ์์ฒด๋ฅผ ๋ฒ๋ฆผ
}
}
}
// ์ผ์์ฒด์ ๊ฐ์ด์น๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ ๋ ฌํ๊ธฐ ์ํ ๋น๊ต ํจ์
int compare(const void* a, const void* b) {
Chromosome* ch1 = (Chromosome*)a;
Chromosome* ch2 = (Chromosome*)b;
return ch2->val - ch1->val;
}
// ์ผ์์ฒด์ ์ ํฉ๋๋ฅผ ํ๊ฐํ๊ณ ์ง๊ธ๊น์ง ์ฐพ์ ์ต์ ํด๋ฅผ ์
๋ฐ์ดํธํ๋ ํจ์
void test(Chromosome* population, int* best_unchange_cnt, Chromosome* best_chr) {
qsort(population, population_size, sizeof(Chromosome), compare); //population ๋ฐฐ์ด์ ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ ๋ ฌํ๊ธฐ ์ํด qsort ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํจ์ ์ฌ์ฉ
if (best_chr->val < population[0].val) {
*best_chr = population[0]; // ์ต์ ํด๋ฅผ ์
๋ฐ์ดํธ
*best_unchange_cnt = 0;
} else {
(*best_unchange_cnt)++;
}
// best_chr: ํ์ฌ๊น์ง ์ฐพ์ ์ต์ ํด
// best_unchange_cnt: ์ต์ ํด๊ฐ ๋ณ๊ฒฝ๋์ง ์์ ์ธ๋ ์
}
// ๊ฐ์ฅ ์ ํฉํ ๊ฐ์ฒด๋ค์ ์ ํํ๊ณ ๋๋จธ์ง ๊ฐ์ฒด๋ฅผ ์ผ์์ฒด ์ง๋จ์์ ์ ๊ฑฐํ์ฌ ์ ํ๋ ๊ฐ์ฒด๋ค๋ง ๋จ๊ฒํ๋ ํจ์
void select(Chromosome* population) {
for (int i = (int)(population_size * select_ratio); i < population_size; i++) {
free(population[i].code); // ์ ํ๋์ง ์์ ์ผ์์ฒด์ ๋ฉ๋ชจ๋ฆฌ ํด์
population[i].code = NULL;
}
}
// ์ ํ๋ ์ผ์์ฒด๋ค ๊ฐ์ ๊ต๋ฐฐ๋ฅผ ์ํํ๋ ํจ์
// ์ ์ ์๊ณ ๋ฆฌ์ฆ ์ฐ์ฐ ๋ฐฉ๋ฒ 1 ๊ต๋ฐฐ
void crossover(Chromosome* population) {
for (int i = (int)(population_size * select_ratio); i < population_size; i++) {
int p1 = rand() % (int)(population_size * select_ratio); //๋ฌด์์๋ก ์ ํ๋ ์ธ๋ฑ์ค p1
int p2 = rand() % (int)(population_size * select_ratio);
//population ๋ฐฐ์ด์์ select_ratio ๋น์จ์ ๋ฐ๋ผ ๋ฌด์์๋ก ์ ํ๋ ๋ ๋ฒ์งธ ๋ถ๋ชจ ์ผ์์ฒด์ ์ธ๋ฑ์ค๋ฅผ ๊ฒฐ์
while (p1 == p2) {
p2 = rand() % (int)(population_size * select_ratio);
}
Chromosome* parent1 = &population[p1];
Chromosome* parent2 = &population[p2];
Chromosome* child = &population[i];
child->sum = 0;
child->val = 0;
child->code = (int*)malloc(6 * sizeof(int));
for (int j = 0; j < 6; j++) {
if (j < 2) {
child->code[j] = parent1->code[j];
} else {
child->code[j] = parent2->code[j];
}
child->sum += child->code[j] * parent1->code[j];
child->val += child->code[j] * parent2->code[j];
}
}
// ์ ํ๋ ๋ถ๋ชจ๋ก๋ถํฐ ๊ต๋ฐฐํ์ฌ ์๋ก์ด ์์ ์ผ์์ฒด๋ฅผ ์์ฑ
}
// ์ผ์์ฒด ์ง๋จ์ ๋ฌด์์ ๋์ฐ๋ณ์ด๋ฅผ ๋์
ํ๋ ํจ์
// ์ ์ ์๊ณ ๋ฆฌ์ฆ ์ฐ์ฐ ๋ฐฉ๋ฒ 2 ๋์ฐ๋ณ์ด
void mutation(Chromosome* population) {
for (int i = 0; i < population_size; i++) {
double rand_v = (double)rand() / RAND_MAX;
if (rand_v < mutation_ratio) {
int idx = rand() % 6;
population[i].code[idx] = (population[i].code[idx] == 1) ? 0 : 1;
}
}
// ์ผ์์ฒด์ ๋ฌด์์ ๋์ฐ๋ณ์ด๋ฅผ ๋์
}
// ์ผ์์ฒด ์ง๋จ์ด ์ฌ์ฉํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํด์ ํ๋ ํจ์
void cleanup(Chromosome* population) {
for (int i = 0; i < population_size; i++) {
free(population[i].code);
}
}
int main() {
srand((unsigned int)time(NULL)); // ๋์ ์๋ ์ด๊ธฐํ
Gold* golds;
makeGold(&golds); // ๊ธ๊ดด ์์ฑ
Chromosome* population = (Chromosome*)malloc(population_size * sizeof(Chromosome));
makeChromosomes(golds, population); // ์ด๊ธฐ ์ผ์์ฒด ์์ฑ
int t = 0; // ์ธ๋ ์นด์ดํฐ
int best_unchange_cnt = 0; // ์ต์ ํด๊ฐ ๋ณ๊ฒฝ๋์ง ์์ ์ธ๋ ์ ์นด์ดํฐ
Chromosome best_chr = population[0]; // ์ต์ ํด๋ฅผ ์ฒซ ๋ฒ์งธ ์ผ์์ฒด๋ก ์ด๊ธฐํ
while (best_unchange_cnt <= max_unchanged) {
t++; // ์ธ๋ ์นด์ดํฐ ์ฆ๊ฐ
test(population, &best_unchange_cnt, &best_chr); // ์ ํฉ๋ ํ๊ฐ ๋ฐ ์ต์ ํด ์
๋ฐ์ดํธ
select(population); // ๊ฐ์ฅ ์ ํฉํ ๊ฐ์ฒด ์ ํ
crossover(population); // ์ ํ๋ ๋ถ๋ชจ๋ค ๊ฐ์ ๊ต๋ฐฐ ์ํ
mutation(population); // ์ผ์์ฒด ์ง๋จ์ ๋ฌด์์ ๋์ฐ๋ณ์ด ๋์
}
printf("best sum : %d best value : %d\n", best_chr.sum, best_chr.val); // ์ต์ ํด ์ถ๋ ฅ
cleanup(population); // ๋ฉ๋ชจ๋ฆฌ ์ ๋ฆฌ
free(population);
free(golds);
return 0;
}