[译]像素自动机:不断发展的代码
By robot-v1.0
本文链接 https://www.kyfws.com/ai/pixel-automaton-evolving-code-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 17 分钟阅读 - 8369 个词 阅读量 0像素自动机:不断发展的代码(译文)
原文地址:https://www.codeproject.com/Articles/1258532/Pixel-Automaton-Evolving-Code
原文作者:Viktor Kovács
译文由本站 robot-v1.0 翻译
前言
Experiment with Darwinian evolution
体验达尔文进化论
- 下载PixelEvolutionDeploy.zip-2.1 MB(Download PixelEvolutionDeploy.zip - 2.1 MB)
- 下载源代码(RAR)-1.8 MB(Download source code (RAR) - 1.8 MB)
介绍(Introduction)
大家好消息!您不必当教授,也不需要实验室就达尔文进化论进行有趣的实验.您只需要下载此高级蜂窝自动机即可亲身体验自然选择的原始功能.(Good news everyone! You don’t have to be a professor and you don’t need a laboratory to make interesting experiments with Darwinian evolution. You only need to download this advanced cellular automaton to experience the raw power of natural selection first-hand.)
尽管有许多使用遗传算法的模拟,但我想创建一个模型,该模型不具有任意适应度函数,并且不尝试达到预定的目标结果,而是-就像现实世界中的真实进化一样-仅依靠成功的复制品.建立一个足够复杂的模型以研究进化的不同方面并让具有不同复杂性的生物相互竞争也很重要.同时,它必须具有高效的计算能力,以允许用户在合理的时间范围内模拟数百万个生物和数十万个世代.好消息是我认为我已经成功创建了这样一个模型.(Although there are many simulations which use genetic algorithms, I wanted to make a model that doesn’t operate with arbitrary fitness functions and doesn’t try to approach a pre-defined target outcome, but instead - just like real evolution in the living world - relies merely on successful reproductions. It was also important to make a model that is complex enough to make it possible to study different aspects of evolution and let organisms with different complexity compete against each other. At the same time, it had to be computation efficient to allow the user to simulate millions of organisms and hundreds of thousands of generations over a reasonable time frame. The good news is I think I’ve managed to create such a model.)
该模型(The Model)
总览(Overview)
该模拟的主要参与者是(The main actors of this simulation are the)像素生物(pixel-organisms).它们是可编程的生物,就像真实的生物一样:争夺资源,消耗它们能消耗的东西,消化(某种),感知它们的环境,移动,繁殖以及当它们的时间到来时最终死亡.更重要的是,它们也在进化!(. These are programmable creatures, that just like real organisms: compete for resources, consume what they can, digest (sort of), sense their environment, move, reproduce and when their time comes, eventually die. More importantly, they also evolve!)
列出的所有活动及其生存策略/行为完全由其基因决定,因此也容易发生突变.(All of the listed activities and their surviving strategy/behavior is determined purely by their genes and as such also subject to mutation.)
图1:来自SMV021物种的像素生物在模拟字段上用黑色矩形表示(Figure 1: The pixel organism from the species SMV021 is represented by a black rectangle on the simulation field)资源以彩色矩形表示.有8000种可能的资源类型,并且每个生物只有在具有相应消化的情况下才允许消耗这些资源中的任何一种(The resources are represented as colored rectangles. There are 8000 possible types of resources, and each organism is only allowed to consume any of these resources if it has a corresponding digesting)酵素(enzyme). (此机制的详细信息在体系结构部分中进行了详细说明.)(. (The details of this mechanism are elaborated in the architecture section.))
自然选择(Natural Selection)
除非用户干预,否则模拟场(也称为试管)是封闭的生态系统.在这里,生物相互竞争以争夺有限数量的资源,当它们消耗足够的资源时,它们实质上就是将资源转化为后代.另一方面,当生物死亡时,它会转化回大块的资源.这是试管中的生命周期.很容易看出,那些无法收集足够资源来留下后代的人被自然选择淘汰了,他们的DNA被历史遗忘了. (或更准确地说,被垃圾收集器刷卡).(The simulation field (aka test tube) is a closed eco-system, unless the user intervenes. Here, organisms are competing against each-other for the finite amount of resources, and when they consume enough, they are essentially converting resources to offspring. On the other hand, when an organism dies, it is converted back into chunks of resources. This is the cycle of life in the test tube. It’s easy to see that those individuals who can’t gather enough resources to leave offspring are weeded out by natural selection and their DNA is lost in history. (Or more precisely swiped by the garbage collector).)
随机突变(Random Mutation)
如前所述,像素生物所做的一切都取决于其基因.即使是移动,有害的点突变也可能导致一种生物站在一个地方等待其不可避免的厄运,或者另一种可能导致该生物直接进入管壁(这也意味着死亡).使用了三种类型的突变:点突变,基因重复/缺失和基因组重复.(As I mentioned, everything that a pixel-organism does is determined by its genes. Even movement, so a detrimental point mutation can cause a creature to stand in one spot waiting for its inevitable doom, or another one can cause it to run directly into the wall of the tube (which also means death). 3 types of mutations are used: point mutation, gene duplication/deletion and genome duplication.)
选择压力(Selective Pressures)
有很多方法可以为像素生物创建或更改选择压力.最明显的是调整电子管的设置:(There are many ways to create or change selective pressures for our pixel creatures. The most obvious one is to tweak the settings of the Tube:)
图2:电子管设置(Figure 2: Tube settings)例如,我们可以通过增加出行成本来向更复杂的决策施加压力.运动是一项成本很高的活动,在我们的模型中,运动花费了更多的处理周期,并且由于每种生物在每次迭代中都具有相同的处理周期(可以通过"(For example, we can pressure the need for more complex decisions by increasing the cost of movement. Movement is a costly activity, in our model, it costs more processing cycle, and since each organism has equal processing cycles in every iteration (can be set by the “) Cycles
“(如图2所示),他们必须尽可能高效地使用它.在现实生活中,实际移动到位的成本要比环顾四周还要多.如果移动的成本远比感知环境或分析的成本高感觉输入,然后我们的生物在移动之前更好地"思考”.(” property as seen in figure 2), they have to use it as efficiently as possible. In real life, it also costs more energy to actually move around in place than just looking around. If movement costs way more than sensing the environment or analyzing the sensory input, then our creatures better “think” before they move.)
您还可以在图2中看到定义了3个不同的区域.这些区域旨在代表不同地区气候之间的差异.通过为这些区域设置不同类型的资源,可以创建具有多个生活在同一管中的物种的局部生态系统(不同的选择压力).如果专门研究消化完全不同的资源,也有可能看到不同物种共生.(You can also see in figure 2 that there are 3 different regions defined. These regions are meant to represent differences between different local climates. By setting different types of resources for these regions, it’s possible to create localized eco-systems (different selective pressures) with multiple species living in the same tube. It’s also possible to see different species live in symbiosis if they are specialized in digesting completely different resources.)
遗传漂移(Genetic Drift)
遗传漂移(Genetic Drift) 可以通过从种群中选择特定个体进行模拟,然后使用"保存基因组"功能(如图1所示),然后可以在新试管中产生这些个体的实例.(can be emulated by choosing specific individuals from a population, then using the “save genome” feature (as seen in figure 1), then you can spawn instances of these in a new tube.)
建筑-像素生物的解剖(Architecture - The Anatomy of a Pixel-organism)
设计此仿真的最大挑战之一是创建一个可处理可变机器代码的体系结构(虚拟处理器+机器代码).传统的Van Neumann体系结构不适合此挑战.随机复制或删除已编译机器代码中的指令几乎不可避免地导致程序不稳定和各种异常.这主要是因为分支和跳转指令指向已定义的内存地址,并且复制或删除操作会移位这些地址上的所有值,从而破坏程序的分支结构.因此,我设计了一个基于基因的架构.(One of the greatest challenges in designing this simulation was to create an architecture (virtual processor + machine code) which can handle mutable machine code. The traditional Van Neumann architecture is not suitable for this challenge. Random duplication or deletion of an instruction in a compiled machine code almost inevitably leads to unstable program and various exceptions. This is mainly because branching and jumping instructions point to defined memory addresses and duplication or deletion can shift all the values on those addresses, thus collapsing the branching structure of the program. For this reason, I designed a Gene based architecture.)
基因,酶和资源(Genes, Enzymes and Resources)
基因本质上是具有3个元素的字节数组.这些元素称为密码子.这些基因是多用途实体:它们可以为消化酶编码,为指令编码或存储数据值.它们的目的取决于上下文.为了理解消化酶,最好知道资源也是由3个字节的密码子编码的.每个密码子代表RGB颜色通道之一,尽管可能的值受到限制.如果每个密码子可以得到0到255之间的任何值,那么将有超过1600万个可能的结果256 * 256 * 256.我的目标是使有机体能够在给定环境中随机发现其所需的酶,并在1600万种可能的选择中随机变异为可用的酶,这似乎有些无望,因此我将问题空间缩小为25 * 25 * 25 (每个密码子25个范围)15625个选项. (出于GUI上的可视化目的,每个值都乘以10,以呈现漂亮的,易于区分的颜色).基因的基本结构如图3所示.(Genes are essentially byte arrays with 3 elements. These elements are referred as codons. These genes are multi purpose entities: they can code for a digesting enzyme, code for instruction, or store data values. Their purpose is dependent on the context. In order to understand digesting enzymes, it’s good to know that resources are also encoded by 3 byte codons. Each codon represents one of the RGB color channels, although the possible values are restricted. If each codon could get any value from 0 to 255, there would be more than 16 million possible outcomes 256256256. My goal was to make it feasible for an organism to randomly discover the enzyme it needs in a given environment and randomly mutating into a usable enzyme in 16 million possible options seemed a bit hopeless, so I reduced the problem space to 252525 (25 range for each codon) 15625 options. (For the visualization purposes on the GUI, each value is multiplied by 10, to present nice, easily distinguishable colors). The basic structure of a Gene is illustrated in figure 3.)
图3:基因的结构(Figure 3: Structure of a gene)
图4:在GUI上选择的资源(Figure 4: A resource selected on the GUI)
考虑到酶的下一个问题是生物体基因组中基因的第一个密码子专用于寻址,因此资源中的3个密码子(红色密码子,绿色密码子和蓝色密码子)必须仅由2个密码子编码.基因组基因.那怎么可能?由于前面提到的值限制,所以有可能. 2个字节可以表示65536个不同的值,这些值足以编码15625个可能的资源.首先,将2个密码子解释为基数为125的密码,然后将其转换为基数为25的密码,从而得到所需的3个资源密码子.(The next problem considering the enzymes was that the first codon in a gene in an organism’s genome is dedicated for addressing, so the 3 codons of a resource (Red codon, Green codon and Blue codon) had to be encoded by only 2 codons in a genomic gene. How is that possible? Thanks to the previously mentioned value restriction, it is possible. 2 bytes can represent 65536 different values which is more than enough to encode the 15625 possible resources. First, the 2 codons are interpreted as a base 125 number, then it is converted to a base 25 number thus we get the 3 resource codons we need.)
当新生物诞生时,其基因型将转换为表型.这意味着(除其他事项外)所有可以解释为消化酶的基因都被转换为25个碱基的密码子(如前所述),并被添加到酶表中.当给定的有机体尝试消耗资源时,将在此酶表中检查相应的值,如果匹配,则(When a new organism is born, its genotype is converted to a phenotype. This means (among other things) that all the genes that can be interpreted as a digesting enzymes is converted to base 25 codons - as described previously - and are added to an enzyme table. When this given organism tries to consume a resource, this enzyme table is checked for the corresponding values, and if there is a match, the)**大众(mass)**资源的一半被添加到我们生物的能量中,该资源从模拟场中消失(被消耗).(of the resource is added to the energy of our creature and the resource disappears from the simulation field (it is consumed).)
处理器(The Processor)
创建表型时发生的另一件事是将基因编译为"机器代码".在机器代码中,地址字节只是存储指令和数据的数组中的索引,因此二维字节数组足以存储我们需要的所有基因值.但是,如果我们看一下(The other thing that happens when the phenotype is created is that the genes are compiled to “machine code”. In the machine code, the address byte becomes simply the index in the array holding the instructions and data, so a 2 dimensional byte array would be enough to store all the values we need from the genes. However, if we take a look at the) Processor
在类中,我们看到该表型是3维锯齿状数组.其背后的原因是,使用字节类型寻址指令存在问题,即通过这种方式,程序长度不能超过256个指令.为了解决此问题,我必须实现分页机制.我想出的一个简单解决方案是,所有子例程和方法都放在专用的不同数组上,因此它们每个都使用单独的寻址空间.这些分离的阵列在模型中称为染色体.也许值得注意的是,到目前为止,除处理器外,每个引入的概念(包括染色体)都是基于其生物学对应的.最接近的事情是将其与核糖体进行比较,因为它还可以处理基因,但是它仍然不很准确,因此我们继续使用术语"处理器".(class, we see that the phenotype is a 3 dimensional jagged array. The reason behind this is that there is a problem with using a byte type for addressing instructions, namely that this way, no program could be more than 256 instructions long. To solve this issue, I had to implement a paging mechanism. The simple solution I’ve come up with was that all subroutines and methods are placed on dedicated different arrays so they each use separate addressing space. These separate arrays are called chromosomes in the model. Maybe it’s worth noting that every concept so far introduced (including chromosomes) was based on its biological counterpart, except the processor. The closest thing would be comparing it to ribosomes since it also processes genes but it’s still far from being accurate so let’s stick with the term processor.)
这个虚拟处理器的工作原理与真实处理器非常相似(至少是非常原始的处理器),它具有一个堆栈,一个堆栈指针,一个程序指针,3个寄存器((This virtual processor works very similar to real processors (the very primitive ones at least), It has a stack, a stack pointer, a program pointer, 3 registers ()Reg A(Reg A),(,)B区(Reg B,)****C区(Reg C)),通常的操作(不包括乘法和除法):加,减,比较,调用,推入堆栈,从堆栈弹出.除此之外,还有3种特定于仿真的操作:(), the usual operations (excluding multiplication and division): Add, Subtract, Compare, Call, Push to stack, Pop from stack. Besides these, there are 3 simulation specific operations:) Move()
,(,) Sense()
和(and) Consume()
.我不打算深入了解实现的每个方面,但是共享有关这些模拟特定功能的信息非常重要,因为如果您想使用模拟中最有趣的功能,它们将派上用场:(. I’m not planning to get into the nitty-gritty details of every aspect of the implementation, but it’s important to share some information about these simulation specific functions, because they come in handy if you want to use the most interesting feature of the simulation:)物种创造者(the species creator). (图6)(. (Figure 6))
移动(Move)
运动基于与生物体的相对位置.基本上,我们告诉他们在Y轴上向上或向下移动,在X轴上向右或左移动.直观地向左移动应该由负值发出,并且通常计算机图形工作时,Y轴上的向上(Up)也将是负值.但是,在我们的模型中,代码仅使用无符号字节值,因此我不得不做出另一种折衷.如图5所示,(-)1由101编码.(Movement is based on relative position to the organism. Basically, we are telling them to move up or down on the Y axis and right or left on the X axis. Intuitively movement to the left should be issued by negative values, and as usually computer graphics work, upwards on the Y axis (Up) would also be a negative value. In our model however, the code uses only unsigned byte values, so I had to make another compromise. As figure 5 shows (-)1 is coded by 101. When the) Move()
调用操作时,中的值(operation is called, the value in)**Reg A(Reg A)**作为运动的X轴分量的参数加载,并且(is loaded as a parameter for the X axis component of the movement, and the value of)**C区(Reg C)**加载为Y轴部分(也如图5所示).(is loaded as the Y axis part (illustrated in figure 5 as well).)
图5:调用Move()函数时,所选生物将向上移动一级.(Figure 5: The selected organism will move one step upwards when the Move() function is called.)#### 感(Sense)
Sense()
就定位而言,其工作方式与运动完全相同.它可用于调查相邻小区的资源内容.它还从本质上检查酶表:如果无法消耗资源,则将值0加载到(works in exactly the same way as movement as far as positioning is concerned. It can be used to survey neighboring cells for their resource content. It inherently checks the enzyme table as well: if the resource can’t be consumed, the value 0 is loaded to)Reg A(Reg A).如果可以消耗,则将资源的质量值加载到(. if it can be consumed, the mass value of the resource is loaded to)Reg A(Reg A).这使生物体能够对哪种移动方式做出明智的决定.(. This allows the organism to make an informed decision on which way to move.)
消耗(Consume)
的(The) Consume()
操作使生物体试图"消耗"当前站立的细胞上的资源.截至目前,如果(operation makes the organism try to “eat” the resource on the cell it is currently standing on. As of now, there is no punishment if) Consume()
在没有资源或没有资源的细胞上被称为"白细胞",尽管这是一个浪费的循环,但我们的有机体却无法因缺乏特定的酶而无法进食.为了鼓励更少的贪婪行为,将来可能会更改它.(is called on a cell that has no resource or has resource, that our organism can’t eat for the lack of a specific enzyme, although it is a wasted cycle. It may be changed in the future, to encourage less greedy behavior.)
Lexer,解析器和编译器(Lexer, Parser and Compiler)
在一开始,我提到生物是可编程的,当然,我并不是说您必须使用基于任意基因的机器代码才能做到这一点.我设计了一种低级的编程语言(At the beginning, I mentioned that organisms are programmable, and of course I didn’t mean that you must use this arbitrary gene-based machine code to be able to do that. I’ve designed a low level programming language)**字节(Pbyte)**它易于使用,并具有为这些生物编写程序或您所说的基本功能:创建物种!因此,我必须实现一个词法分析器,一个递归的体面解析器(链接)和一个编译器,以便可以将可读的Pbye程序编译为Genes.我是第一个承认处理器和编译器都没有优化的人,但这不是错误!认真地讲,整个系统被设计为易于变异的,其中包括处理器本身.寄存器,堆栈和程序指针都存储在表型数组中,因此基因型中引入的突变会影响它们的工作方式.我不会详细介绍模拟成千上万代产品后得到的实际测试结果,但是我不得不说,我亲眼目睹的通过自然选择进行的优化水平超出了我的所有期望.我创建的一个非常简单的物种最初被编译为134个基因,经过约45000代的发展,仅使用55个基因即可进化出更具活力的生物.(which is easy to use and has the basic features you’ll need to write programs for these organisms or as I referred to: create species! For this reason, I had to implement a lexer, a recursive decent parser(link) and a compiler so readable Pbye programs can be compiled to Genes. I’m the first to admit, that neither the processor or the compiler is optimized, but this is a feature not a bug! Seriously, the whole system is designed to be subject to mutation and this includes the processor itself. The registers, the stack, the program pointer are all stored in the phenotype array so mutations introduced in the genotype can affect how they work. I won’t get into the details of the actual test results I got from simulating millions of generations, but I have to say that the level of optimization through natural selection I witnessed surpassed all my expectations. A very simple species I created was compiled originally to 134 genes, after ~45000 generations faster and more viable organisms evolved with using only 55 genes.)
使用应用程序(Using the Application)
我已尽力创建一个简单高效的UI并在必要时提供工具提示,因此弄清主要功能应该不是问题.要运行模拟,您要做的就是在模拟字段中选择一个单元格,然后点击(I’ve tried my best to create a simple and efficient UI and provide tooltips when necessary, so figuring out the main functions shouldn’t be an issue. To run a simulation, all you have to do is to select a cell on the simulation field, then hit)F2(F2)(这会将默认生物插入试管中),然后按((this inserts a default organism into the test tube), then hit)F10(F10)开始模拟.您可以通过调整试管设置并尝试不同的酶和种群设置来运行一些有趣的实验,但是该程序的主要功能是创建和测试自己的代码/自己的物种.(to start the simulation. You can run some interesting experiments by tweaking the tube settings and trying out different enzyme and population setups, but the main feature of this program is creating and testing your own code/your own species.)
图6:物种创造者(Figure 6: Species creator)如果将以下代码复制到物种创建者文本框中,然后按F5键(编译),则应该在模板下拉菜单中获得一个新的,可行的物种.此演示代码用作教程,向您介绍物种创建的过程.我建议在继续本文之前先对自己的行为进行测试.(If you copy the following code to the species creator textbox, and hit F5 (compile) you should get a new, viable species in the templates dropdown menu. This demo code serves as a tutorial to introduce you to the process of species creation. I suggest to first test for yourself how it behaves before you continue with this article.)
STR40 var v, x, y
{
x:=rega
y:=regc
v:=1
while(true)
{
if(y<3)
{
v:=1
}
if(y>37)
{
v:=101
}
rega:=1
regc:=0
while(x<37)
{
x:=x+1
Move()
Consume()
}
if(v==1)
{
y:=y+1
}
else
{
y:=y-1
}
rega:=0
regc:=v
Move()
rega:=101
regc:=0
while(x>2)
{
x:=x-1
Move()
Consume()
}
if(v==1)
{
y:=y+1
}
else
{
y:=y-1
}
rega:=0
regc:=v
Move()
}
}
完成后,我们可以讨论如何编码此行为:(When it’s done, we can discuss how this behavior is encoded:)
STR40 var v, x, y
x:=rega
y:=regc
v:=1
第一部分是初始化,第一部分(The first part is the initialization, the first) string
将成为我们物种的名字.名字(is going to be the name of our species. The name) string
当然是完全任意的,我命名了(is completely arbitrary of course, I named it) STR40
因为这种生物被设计为在40 * 40的试管中工作,并且以直线运动.(because this organism is designed to work in a 40 * 40 tube, and it moves in a straight line.)
接下来是我们将要使用的变量. X和y是我们必须跟踪生物体位置的坐标,(This is followed by the variables we are going to use. X, and y are the coordinates we have to keep track of the position of our organism, the) v
变量决定它是向上还是向下.如前所述,所有有机体的实际坐标都在reg a和reg c中加载,因此我们可以将这些值传递给x,y变量(因为命名寄存器用于其他目的).(variable decides if it is going upwards or downwards. As mentioned before, all organisms are born with their actual coordinates loaded in reg a, and reg c, so we can pass these values to the x, y variables (as named registers are used for other purposes).)
while(true)
{
在我们上面有我们的主要循环,即生命周期,它将一直持续到生物死亡.(Above we have our main loop, the life cycle, this will run until the organism dies.)
if(y<3)
{
v:=1
}
if(y>37)
{
v:=101
}
在这里,我们有一个主循环,即生命周期,它将一直持续到生物死亡.(Here we have our main loop, the life cycle, this will run until the organism dies.)
rega:=1
regc:=0
在这里我们设置(Here we setup)Reg A(Reg A)和(and)C区(Reg C)运动.这些值代表右侧的一步.(for movement. These values represent one step to the right.)
while(x<37
{
x:=x+1
Move()
Consume()
}
这是一个内部循环,它首先调整x坐标,然后使有机体移动并吃掉每个步骤中发现的东西,直到它太靠近试管的右边缘为止.(This is the inner loop that first adjusts the x coordinate then makes the organism move and eat what it finds in each step, until it is too close to the right edge of the tube.)
if(v==1)
{
y:=y+1
}
else
{
y:=y-1
}
rega:=0
regc:=v
Move()
当到达管的右侧时,我们必须更改y轴上的线(因为我们不希望只是在同一条线中来回移动),这由之前的设置决定(When the right side of the tube reached, we have to change lines on the y axis (because we don’t want to just move in the same line back and forth), which is determined by the previously setup) v
变量.该代码首先调整y坐标,然后根据的值向上或向下移动一级(variable. This code first adjusts the y coordinate, then makes one step upwards or one step downwards, depending on the value of) v
.请记住:我们仍然离试管的右侧太近.(. Remember: we are still too close to the right side of the tube.)
rega:=101
regc:=0
while(x>2)
{
x:=x-1
Move()
Consume()
}
在这里,我们准备(Here, we prepare)Reg A(Reg A)和(and)C区(Reg C)向左移动.接下来的内部循环与上面的内部循环非常相似,不同的是结果将在每次迭代中向左移一步.因为我们以这种方式设置寄存器.(for movement to the left. The inner loop that follows is very similar to the one above, except the result will be one step to the left in each iteration. because we setup the registers that way.)
if(v==1)
{
y:=y+1
}
else
{
y:=y-1
}
rega:=0
regc:=v
Move()
当到达左侧时,我们再次换行,然后主循环(生命周期)可以重新开始.(When the left side is reached, we change lines once again, and then the main loop (life cycle) can start all over again.)
我在此平台上发布此应用的主要原因是,我希望这里的某些程序员能够接受挑战,并创造出比我所分享的物种更可行的物种.如果您设法做到这一点,建议您在注释部分分享您的代码.然后,让这些物种相互竞争,就像在实际生物学中一样!(The main reason I publishing this app on this platform is, that I hope some of the programmers here take up the challenge and make some more viable species than the ones I’ve shared. If you have managed to do that, I encourage you to share your code in the comment section. Then, let the species compete against each other, just like in actual biology!)
技术兴趣点(Technical POI)
GUI是使用WPF技术实现的,因此,我同时使用了MVVM设计模式.对于文本编辑器元素,我使用了(The GUI is implemented using WPF technology and accordingly I used the MVVM design pattern along with it. For the text editor element, I used) AvalonEdit-WPF-文本编辑器(AvalonEdit-WPF-Text-Editor) .(.)
对于并行处理,我想出了一个解决方案,使该应用程序快了大约10倍:(For parallel processing, I came up with a solution, that made the application approximately 10 times faster:)
- 我的自定义并行foreach(My custom parallel foreach) 解决方案需要实现词法分析器,解析器和编译器.解析器的算法是递归的体面解析器.(The solutions required the implementation of a lexer, a parser and compiler. The algorithm for the parser is a recursive decent parser.)
历史(History)
- 1个(1)圣(st)2018年9月:初始版本(September, 2018: Initial version)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
C# .NET WPF Architect 新闻 翻译