【问题标题】:structs and arrays结构体和数组
【发布时间】:2012-01-03 16:22:53
【问题描述】:

我目前正在看这个:

some Genetic Algorithm

这是一些改编的代码:

struct Chromosome
{
    public bool[] genes;
    public int fitness;
}

我从未在我的进化算法/遗传算法中使用过结构体。在结构中使用数组是不是有点毫无意义——尤其是当我必须进行深拷贝时?在这种情况下使用结构体有什么好处吗?

谢谢。

【问题讨论】:

  • 您可以使用结构数组,但请记住一个可能遇到的可变不可变问题。也知道何时以及何时不使用结构与类。看看结构和类之间的差异在 C# 中只是一个建议
  • 实际上,我只是担心bool[] - 听起来你真的应该将它包装成某种位掩码。我们在这里谈论多少个基因?
  • 请解释一下您对 EA 和 GA 的含义。我认为 GA 是遗传算法。
  • GA = 遗传算法,EA = 进化算法 - 抱歉认为链接会揭示这一点。
  • @csetzkorn,我们讨厌点击链接。 ;) 一般来说,我们喜欢我们的问题和答案在很大程度上是独立的。

标签: c# arrays struct


【解决方案1】:

我认为这没有任何问题... 在 GA 中,一切都是为了验证候选人的适合性。该结构只是封装了候选人的所有信息。因此,适合度与您的基因直接相关。将它存储在同一个类/结构中非常有意义。

如果您不使用基因存储适应度,则必须以某种方式对其进行映射。这将是不必要的麻烦。或者,如果您根本不想存储适应度,则每次比较两个候选者时都必须重新计算它。不会是明智的。特别是在适应度评估相当复杂的情况下(例如在 GA 中评估模拟的最佳参数)。

我会使用一个实现接口 IComparable 的类。两个候选人将比那里的适合度进行比较。然后,您只需对候选人列表进行排序,然后挑选出下一代的最佳 10 个候选人(始终取决于您使用的 GA 类型)。

关于 bool 数组...我也没有看到任何问题。如果这是你的基因最好的表现方式......完美:)。表示为整数也很好,但在某些情况下,它可能会使 x-over 操作有点复杂......总是取决于情况......

【讨论】:

  • 对不起,您的回答并没有说太多。我对结构感兴趣,因为它们更容易(深度)复制/克隆(参见 GA 选择过程)并且重量更轻。然而,在结构中有一个对象(堆上的东西)似乎违背了目标......
  • 是的......对不起。我有点误解了这个问题。我认为问题是关于一般使用结构/类而不是使用结构而不是类。我的错
【解决方案2】:

通常,我们使用struct 来表示可以被认为非常原始的东西。 According to MSDN,应该是表示单个“值”的类型,大小不超过 16 字节,以此类推。

struct 要记住的主要内容是值类型语义,因此将其传入和传出函数将创建一个副本。成本明智,这不会太糟糕,因为您要复制的是 1 个引用(到 bool 数组)和 1 个 int,但是如果您尝试以其他方法或从复制。

许多人认为struct 总是比class 更有效,但情况并非总是如此,通常这种微优化比有用更危险,因为它引入了使用值类型的副作用.

对于bool 的数组,您可以在int 中创建和设置位,也可以在BCL 中使用BitArray 专用类。

所以,总而言之,如果这是遗留代码并且您想保留 struct,它会起作用,但如果您希望它像 class通过/复制时。但是,看看它所持有的内容,它不符合 MSDN 指南中关于 struct 最适合的内容。

【讨论】:

  • 我认为这个 Q 应该在其上下文中回答,即根据 CodeProject 上的 GA 代码,作者提供了链接。正如您在代码中看到的那样,所有结构都在 List 中使用,并且它的所有参数传递都由 ref 执行。
  • 他问使用结构数组是否毫无意义,以及结构在这种情况下是否有效。我回答了结构通常用于什么,并说在我看来它不太适合上下文。
【解决方案3】:

在这种情况下,bool 数组不会被自动深度复制。因此,您并没有真正从结构中受益,因为当您将 Chromosome 分配给新结构时,两者中的引用将指向同一个 bool[ ]

你可以只使用一个数字而不是使用 bool[]:比如说int。基因= 3的染色体代表基因:0000 0000 0000 0000 0000 0011。基因= 42134的染色体代表基因:0000 0000 1010 0100 1001 0110。int是32位,这意味着您可以用232 基因这样。 您不必担心深度复制数组,这在内存消耗方面也更快、更有效。如果您需要更多基因,请使用 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);

【讨论】:

  • 谢谢。当然你可以使用 int 来代替 bool 数组,但是如果你有约束(例如 [x ... y] 之间的可能值)怎么办?
  • 这是一个很酷的问题。我假设存在约束的情况,并且我在上面的答案中添加了一种解决此问题的方法,因为我需要用代码进行说明。希望对您有所帮助!
  • 谢谢,我会看看这个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多