我目前正在看这个:
这是一些改编的代码:
struct Chromosome
{
public bool[] genes;
public int fitness;
}
我从未在我的进化算法/遗传算法中使用过结构体。在结构中使用数组是不是没有意义 - 特别是当我必须制作深拷贝时?在这种情况下使用结构有什么好处吗?
感谢。
答案 0 :(得分:2)
我没有看到任何问题...... 在GAs中,它的全部内容都是为了验证候选人的健康状况。结构只是封装候选人的所有信息。因此,适应性与您的基因直接相关。将它存储在同一个类/结构中是完全合理的。
如果你没有用你的基因存储健康,你必须以某种方式映射它。这将是一个不必要的麻烦。或者,如果你根本不想存储健身,你必须重新计算它,你将两个候选人相互比较。不明智。特别是如果适应度评估相当复杂(例如在GA中评估模拟的最佳参数)。
我会使用一个实现IComparable接口的类。两个候选人将被比较健身。然后你只需要对你的候选人名单进行排序,然后选择下一代最好的10个候选人(总是取决于你正在使用的GA类型)。
关于bool阵列......我也没有看到任何问题。如果这是你的基因最好的代表...完美:)。表示为整数也很好,但在某些情况下,它可能会使x-over操作有点复杂......总是取决于案例......
答案 1 :(得分:1)
在这种情况下,bool数组不会自动深度复制。所以你并没有真正受益于结构,因为当你将染色体分配给一个新结构时,两者中的引用将是相同的bool []
而不是使用bool []你可以使用一个数字:让我们说int
。基因= 3的染色体代表基因:0000 0000 0000 0000 0000 0011.具有基因= 42134的染色体代表基因:0000 0000 1010 0100 1001 0110.int是32位,这意味着您可以用2 32 <代表染色体/ sup>基因这种方式。
您可以避免担心深度复制数组,这在内存消耗方面也更快,更高效。如果您需要更多基因,请使用Int64。
<强>更新强> 你的问题真是太酷了。如果您对某些段中可能的基因组合有限制,则需要根据限制逐字节构造Int32。为了说明,我假设了一个关于染色体的一些限制并随机突变染色体但关于限制的例子。
//The following creates a random chromosome with restrictions
//to the genes as described in the following:
//Let's say that the following pattern must be adhered to:
//byte 1 = xxxx xxxx (anything)
//byte 2 = 1011 xxxx (restricted)
//byte 3 = [0000 or 1111] xxxx (restricted)
//byte 4 = 0000 1111 (fixed value)
Random rnd = new Random();
byte[] randomByte = new byte[1]; //xxxx xxxx xxxx xxxx
byte restrictedByte2 =
(byte)(Math.Pow(2,7) * 1 + Math.Pow(2,6) * 0 +
Math.Pow(2,5) * 1 + Math.Pow(2,4) * 1 +
rnd.Next(0, 16)); //1011 xxxx
//in byte 3, the first (most significant) for bits are restricted to either 0000 or 1111.
//That's either number 0 * 16 = 0 or number 15 * 16 = 240. I multiplied by 2^4 because it's shifted
//4 bytes to the left.
byte higherBits = (byte)(rnd.Next(0, 2/*upper bound exclusive*/) == 1?240:0);
//random lower bits (xxxx).
byte lowerBits = (byte)(Math.Pow(2,0) * rnd.Next(0, 2) + Math.Pow(2,1) * rnd.Next(0, 2) +
Math.Pow(2,2) * rnd.Next(0, 2) + Math.Pow(2,3) * rnd.Next(0, 2) +
rnd.Next(0, 16));
byte restrictedByte3 = (byte)(lowerBits + higherBits);
byte restrictedByte4 = 143; //constant
//Create an Int32 from the four bytes.
int randomMutation = BitConverter.ToInt32(
new byte[] { randomByte[1], restrictedByte2, restrictedByte3, restrictedByte4 }, 0);
答案 2 :(得分:1)
通常,我们使用struct
来表示可以被认为非常原始的东西。 According to MSDN,它应该是一个表示单个“值”的类型,大小为16个字节或更小,依此类推。
使用struct
时要记住的主要内容是值类型语义,因此将此函数传入和传出函数将创建副本。成本方面这不会太糟糕,因为您复制的是1个引用(对于bool数组)和1个int,但如果您尝试在另一个方法中修改数组引用或从副本。
许多人认为struct
总是比class
更有效率,但情况并非总是如此,通常这种微观优化比有用更危险,因为它引入了工作的副作用使用值类型。
对于bool
数组,您可以在int
中创建和设置位,也可以在BCL中使用BitArray
专用类。
所以,它的长短是,如果这是遗留代码并且你想保留struct
,它会起作用,但是如果你希望它像{{{{{{ 1}}在传递/复制时执行。但是,看看它持有什么,它不符合MSDN对class
最适合的指导。