守卫城墙的士兵 - 家庭作业

时间:2014-01-10 13:47:08

标签: r algorithm genetic-algorithm

我的人工智能课程中有一项任务。

这是我们必须使用R中的遗传算法(使用GA库)来解决的问题。我正在寻找一些如何处理这个问题的想法。

描述

野蛮人围攻一座城市。将军下令在一天中每小时有多少士兵必须守卫城墙。这是他的表:

Time of the day | Number of soldiers
00:00 - 01:00   150
01:00 - 02:00   160
02:00 - 03:00   160
03:00 - 04:00   170
04:00 - 05:00   350
05:00 - 06:00   380
06:00 - 07:00   400
07:00 - 08:00   420
08:00 - 09:00   450
09:00 - 10:00   470
10:00 - 11:00   500
11:00 - 12:00   500
12:00 - 13:00   450
13:00 - 14:00   350
14:00 - 15:00   300
15:00 - 16:00   300
16:00 - 17:00   310
17:00 - 18:00   350
18:00 - 19:00   350
19:00 - 20:00   330
20:00 - 21:00   300
21:00 - 22:00   250
22:00 - 23:00   200
23:00 - 24:00   170

国防指挥官希望士兵在巡逻时完全专注,所以他给出了这个命令:

  • 每个士兵在一天(24小时)内守卫墙壁正好6个小时:在墙上停留4个小时,然后他休息2个小时然后再回到墙上2个小时
  • 在午夜之前开始的焊料,在第二天的早晨继续 - 算法必须考虑日子的连续性。 需要多少士兵守卫墙壁?

到目前为止我的想法

两种可能的方法(到目前为止):

第一种方法

GA的适应度函数将接受许多焊料,然后进行模拟:

  • 将初始分数设为0.
  • 如果在模拟过程中,城市中的士兵将缺少或超过,则从分数中减去。
  • 最佳解决方案是当得分为零时(所需士兵的数量最佳)。

第二种方法

创建一个初始种群(焊接者)并在健身功能中应用指挥官的规则(我真的不知道如何在这里定义上述规则),然后运行GA直到我们得到一些有用的分数。

4 个答案:

答案 0 :(得分:1)

我的方法是让人口中的个人代表一些士兵并将这些士兵分配给轮班。因此,对于300名士兵来说,染色体在0到23之间需要300个数字(假设每个士兵每天都采取相同的班次),标记他开始6个小时的时间,但不是每个人都有相同的染色体长度。有些人将分配300名士兵,其他人将是500名士兵。我不熟悉R中的GA库,但这是他们应该能够处理的。

现在,考虑到一个人并将每个士兵分配到轮班,你可以使用问题规则轻松计算每小时有多少士兵在守卫墙壁。您的目标是使此计划尽可能接近一般订单,因此您的适应度函数(GA将最大化)应与结果计划和一般订单之间的差异成反比。当差值为0时,您已找到最佳解决方案。

您可以添加其他偏差和约束。比方说,如果你不想要任何有防护墙的解决方案,你可以给这些人特别低的适应性。

答案 1 :(得分:1)

由于作业结束了(是的,我和OP一样去了同一个班级)这是一个实际上有趣的问题,我在这里发布我的解决方案:

library(GA)

Fitness <- function(x) {
    x <- as.integer(x)
    # z represents required soldiers at each hour
    z <- c(150,160,160,170,350,380,400,420,450,470,500,500,450,350,300,300,310,350,350,330,300,250,200,170)
    y <- rep(0,31)
    for (i in 1:length(x)) {
        y[i] <- y[i] + x[i]
        y[i+1] <- y[i+1] + x[i]
        y[i+2] <- y[i+2] + x[i]
        y[i+3] <- y[i+3] + x[i]
        #resting 4, 5
        y[i+6] <- y[i+6] + x[i]
        y[i+7] <- y[i+7] + x[i]
    }
    for (i in 1:7) {
        y[i] <- y[i]+y[24+i]
    }
    y <- y[1:24]
    p <- y >= z
    if (FALSE %in% p) { return(-3000) }
return(-sum(x))
}

GA <- ga(type = "real-valued", fitness = Fitness, min = rep(0, 24), max = rep(150, 24), popSize = 24, suggestions = sol, maxiter = 5000, run = 5000, pmutation=0.9)

summary(GA)
sol <- (as.integer(GA@solution[1, ]))
sol
sum(sol)

GA生成一组士兵数量,每小时开始观察(有24小时,这就是为什么24个零和24倍150),并用所述向量调用Fitness函数。

Fitness函数首先将实数转换为整数(R as.integer函数只是在小数点后删除任何数字,不进行舍入),并将士兵分配给它的6小时工作。它是通过在士兵休息的两个小时内添加从x[i]y[i, i+1, ... i+7]开始的士兵数量来实现的。

由于士兵全天候守卫,y中的最后7个小时会被添加到y的前7个小时,然后才会考虑y的前24个值。

然后我们将手表上生成的士兵矢量与所需的矢量进行比较,如果矢量中有FALSE个,Fitness会返回一个非常大的负数(GA总是需要更大数字是一个更好的)。

最后,我们希望尽可能“雇用”小兵,这就是为什么我们否定结果(需要更少的士兵数量=更高的否定数量),以便GA找到最佳结果。

其余部分非常自我解释,我们称之为GA功能,我们调整其设置并显示结果。

答案 2 :(得分:0)

以下是我们每小时需要的士兵

soldiers
#  150 160 160 170 350 380 400 420 450 470 500 500 450 350 300 300 310 350 350
# 330 300 250 200 170

所以我们需要:

sum(soldiers)
# 7770

但每个士兵在墙上工作6个小时,所以:

sum(soldiers)/6
# 1295

现在问题是如何适应规则:我会说2小时休息是最小的而不是必须的。我没有看到它的重点,它会导致问题(我们需要更多的士兵而不是1295) 这是一个起点,而不是0从1295开始。所以我会选择第一种方法,即使我对GA库一无所知。

答案 3 :(得分:0)

我认为第一种方法不是遗传算法。据我所知,GA从一些初始人口开始,健身功能用于选择人口中最好的个体。

但是,我会以不同于你的方式定义初始人口。它应该是一个数字集合,其中每个数字表示城市中的士兵数量。例如,个人1代表10名士兵,个人2代表120名士兵,个人N代表680名士兵。

然后在GA的每个步骤中,您应该选择(基于适应度函数)最佳个体,即最佳的数字。这些人将被用于使用交叉和变异等遗传算子创造新一代。例如,交叉可以定义为计算两个数字的平均值。

关于健身功能。它应该确定给定数量的士兵是否是最佳的。最佳,我的意思是如果有太多(一些士兵无聊)或太少(城墙上没有足够的士兵)士兵的信息。

你应该运行GA,直到最好的个人从你的角度来看足够好。

请注意,这是一项功课,如果没有遗传算法,这个问题就可以解决。