2

我目前正在用 C 语言编写键盘布局优化算法(例如由 Peter Klausler 设计的算法),并且我想按照此处所述(PDF 链接)实现适合度成比例的选择:

通过轮盘赌选择,您可以根据轮盘赌模式选择人口成员。做一个饼图,其中成员切片的面积与整个圆圈的面积是成员适应度与总人口的比值。正如你所看到的,如果圆的圆周上的一个点被随机挑选,那些具有较高适应度的人口成员将有更高的概率被选中。这确保了自然选择的发生。

问题是,我看不到如何有效地实施它。我想到了两种方法:一种不可靠,另一种很慢。

首先,慢的:

对于长度为 N 的键盘池,创建一个长度为 N 的数组,其中数组的每个元素实际上包含两个元素,一个最小值和一个最大值。每个键盘都有对应的最小值和最大值,范围取决于键盘的适应度。例如,如果键盘 0 的适应度为 10,键盘 1 的适应度为 20,键盘 2 的适应度为 25,则如下所示: 代码:

array[0][0] = 0; // minimum
array[0][1] = 9; // maximum
array[1][0] = 10;
array[1][1] = 30;
array[2][0] = 31;
array[2][1] = 55;

(在这种情况下,适合度越低越好,因为这意味着需要更少的努力。)

然后生成一个随机数。无论该数字属于哪个范围,相应的键盘都会被“杀死”并替换为不同键盘的后代。根据需要重复此操作多次。

问题在于它非常慢。它需要 O(N^2) 次操作才能完成。

接下来是快速的:

首先弄清楚键盘的最低和最高适应度是什么。然后在(最低适应度)和(最高适应度)之间生成一个随机数,并杀死所有适应度高于生成数的键盘。这是有效的,但不能保证只杀死一半的键盘。它还具有与“轮盘赌”选择有些不同的机制,因此它甚至可能不适用。

所以问题是,什么是有效的实现?

这本书的第 36 页有一个有效的算法(链接),但问题是,只有当您只进行一次或几次轮盘选择时,它才有效。有什么有效的方法可以同时进行许多轮盘赌选择吗?

4

1 回答 1

1

一方面,如果您想“杀死”您的选择(可能是高分键盘,听起来您正在谈论不适合分数。

我认为不需要维护两个数组。我认为最简单的方法是维护一个分数数组,然后您对其进行迭代以做出选择:

/* These will need to be populated at the outset */
int scores[100];
int totalScore;

for (gen = 0; gen < nGenerations; ++gen) {
    /* Perform a selection and update */
    int r = rand() % totalScore;        /* HACK: using % introduces bias */
    int t = 0;
    for (i = 0; i < 100; ++i) {
        t += scores[i];
        if (r < t) {
            /* Bingo! */
            totalScore -= scores[i];
            keyboards[i] = generate_new_keyboard_somehow();
            scores[i] = score_keyboard(keyboards[i]);
            totalScore += scores[i];    /* Now totalScore is correct again */
        }
    }
}

对于 n 个键盘,每次选择/更新需要 O(n) 时间。

于 2009-08-14T06:50:15.450 回答