diff --git a/README_EN.md b/README-EN.md similarity index 100% rename from README_EN.md rename to README-EN.md diff --git a/README.md b/README.md index 4aa73ad..b94f62e 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,7 @@ Frog: 这是人工生命的主体,目前起名叫青蛙(Frog),其实叫什 ![result6](https://gitee.com/drinkjava2/frog/raw/master/result6_letter.gif) 2019-11-26 优化了一下程序,用8个汉字来进行模式识别原理演示,但容错性依然没有,变形、变位后的文字识别率很差。以后要考虑借签算法中的侧抑制、卷积、分层等原理来提高它的容错性,这方面算法已经很成熟了,目前只需要拿来主义,用图形化模拟的方式来实现。但总体上算法和图形化模拟是两条路,算法通常可以用模拟的方式来表达,但不是所有模拟都可以归纳成算法,因为模拟(或者说软件本身)有时会非常复杂,不容易总结出规律。也就是说模拟的表现力比算法更强,但模拟的缺点是资源消耗大。 2019-12-27 在history\003a_legs目录下(依然是2维脑)尝试给青蛙加两条腿,看它能不能自动学会走路。一条腿位于下方,负责左右移动,一条腿位于右侧,负责上下移动,每条腿有抬腿、落腿、转动和相应的感觉细胞。只有当腿落下且转动,而且另一条脚抬起来时青蛙才会位移,具体什么时候抬腿、什么时候转动腿完全由随机数决定。经过一段时间的生存汰淘之后,青蛙会进化出会利用两条腿走路了,但需要的时间非常长,约几个小时之后才达到最高吃食率50%左右,走路风格也比较诡异,是小碎步而不是大踏步。但至少这是青蛙第一次利用两条腿来走路,还是有点意义的,这证明生命进化中就算神经元随机排布,进化出眼睛和腿也是非常简单自然的事。 +2020-05-04 在进行3维脑改造过程中,发现找食率很低,发现自己也看不懂以前的程序怎么编的了,所以又添加一个history\003b_simple目录,把2维脑简化一下,去掉不重要的器官,好仔细分析它的逻辑。 ## 运行方式 | Run 运行core或history各个子目录下的run.bat批处理文件即可启动运行,history下有多个子目录,按时间顺序按列,存放着这个项目演化过程中的主要历史版本供演示。 diff --git a/core/src/main/java/com/github/drinkjava2/frog/Env.java b/core/src/main/java/com/github/drinkjava2/frog/Env.java index daf0e28..63492cf 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/Env.java +++ b/core/src/main/java/com/github/drinkjava2/frog/Env.java @@ -30,11 +30,11 @@ public class Env extends JPanel { /** Delete eggs at beginning of each run */ public static final boolean DELETE_EGGS = true;// 每次运行是否先删除保存的蛋 - public static final int EGG_QTY = 50; // 每轮下n个蛋,可调,只有最优秀的前n个青蛙们才允许下蛋 + public static final int EGG_QTY = 25; // 每轮下n个蛋,可调,只有最优秀的前n个青蛙们才允许下蛋 public static final int FROG_PER_EGG = 4; // 每个蛋可以孵出几个青蛙 - public static final int SCREEN = 4; // 分几屏测完 + public static final int SCREEN = 1; // 分几屏测完 public static final int FROG_PER_SCREEN = EGG_QTY * FROG_PER_EGG / SCREEN; // 每屏上显示几个青蛙,这个数值由上面三个参数计算得来 @@ -59,10 +59,10 @@ public class Env extends JPanel { public static final int FROG_BRAIN_DISP_WIDTH = 600; // Frog的脑图在屏幕上的显示大小,可调 /** Steps of one test round */ - public static final int STEPS_PER_ROUND = 2000;// 每轮测试步数,可调 + public static final int STEPS_PER_ROUND = 4000;// 每轮测试步数,可调 public static int step;// 当前测试步数 - public static final int FOOD_QTY = 2000; // 食物数量, 可调 + public static final int FOOD_QTY = 1500; // 食物数量, 可调 // 以下是程序内部变量,不要手工修改它们 public static boolean pause = false; // 暂停按钮按下将暂停测试 diff --git a/core/src/main/java/com/github/drinkjava2/frog/Frog.java b/core/src/main/java/com/github/drinkjava2/frog/Frog.java index 1a6a208..df852a6 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/Frog.java +++ b/core/src/main/java/com/github/drinkjava2/frog/Frog.java @@ -24,6 +24,7 @@ import com.github.drinkjava2.frog.brain.Organ; import com.github.drinkjava2.frog.brain.organ.Line; import com.github.drinkjava2.frog.egg.Egg; import com.github.drinkjava2.frog.objects.Material; +import com.github.drinkjava2.frog.util.RandomUtils; /** * Frog = cells
@@ -34,6 +35,7 @@ import com.github.drinkjava2.frog.objects.Material; * 青蛙脑由一个cells三维数组组成,每个cell里可以存在多个行为,行为是由器官决定,同一个细胞可以存在多种行为。光子是信息的载体,永远不停留。 * * @author Yong Zhu + * * @since 1.0 */ public class Frog {// 这个程序大量用到public变量而不是getter/setter,主要是为了编程方便和简洁,但缺点是编程者需要小心维护各个变量 @@ -45,7 +47,7 @@ public class Frog {// 这个程序大量用到public变量而不是getter/setter public int x; // frog在Env中的x坐标 public int y; // frog在Env中的y坐标 - public long energy = 1000000; // 青蛙的能量为0则死掉 + public long energy = 100000; // 青蛙的能量为0则死掉 public boolean alive = true; // 设为false表示青蛙死掉了,将不参与计算和显示,以节省时间 public int ateFood = 0; // 青蛙曾吃过的食物总数,下蛋时如果两个青蛙能量相等,可以比数量 @@ -65,9 +67,26 @@ public class Frog {// 这个程序大量用到public变量而不是getter/setter organs.add(org); } - public void initFrog() { + public void initFrog() { // 初始化frog,通常只是调用每个organ的init方法 for (int orgNo = 0; orgNo < organs.size(); orgNo++) { organs.get(orgNo).init(this, orgNo); + // energy -= 1; // organ 增多需要消耗能量 + } + +// Cell c1 = this.findFirstCellByClass(Active.class); +// Cell c2 = this.findFirstCellByClass(MoveUp.class); +// organs.add(new Line(c1, c2)); + } + + public void addRandomLines() {// 有一定机率在器官间生成随机的神经连线 + if (RandomUtils.percent(0.2f)) { + Cell c1 = RandomUtils.getRandomCell(this); + if (c1 == null) + return; + Cell c2 = RandomUtils.getRandomCell(this); + if (c2 == null || c1 == c2) + return; + organs.add(new Line(c1, c2)); } } @@ -82,6 +101,7 @@ public class Frog {// 这个程序大量用到public变量而不是getter/setter // 依次调用每个器官的active方法,每个器官各自负责调用各自区域(通常是Cuboid)内的细胞的行为 for (Organ o : organs) o.active(this); + addRandomLines(); // 有一定机率在器官间生成随机的神经连线 return alive; } diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java b/core/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java index 3ae64dc..e8a78d3 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java +++ b/core/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java @@ -264,6 +264,10 @@ public class BrainPicture extends JPanel { } public void drawText(float px1, float py1, float pz1, String text) { + drawText(px1, py1, pz1, text, 1); + } + + public void drawText(float px1, float py1, float pz1, String text, float textSize) { double x1 = px1 - Env.FROG_BRAIN_XSIZE / 2; double y1 = -py1 + Env.FROG_BRAIN_YSIZE / 2;// 屏幕的y坐标是反的,显示时要正过来 double z1 = pz1 - Env.FROG_BRAIN_ZSIZE / 2; @@ -286,7 +290,8 @@ public class BrainPicture extends JPanel { x1 = x; y1 = y; - g.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, (int) round(scale * .3))); + g.setColor(picColor); + g.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, (int) round(textSize * scale * .3))); g.drawString(text, (int) round(x1) + Env.FROG_BRAIN_DISP_WIDTH / 2 + xOffset, (int) round(y1) + Env.FROG_BRAIN_DISP_WIDTH / 2 + yOffset); diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/Cell.java b/core/src/main/java/com/github/drinkjava2/frog/brain/Cell.java index c45e760..c0fc1ac 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/brain/Cell.java +++ b/core/src/main/java/com/github/drinkjava2/frog/brain/Cell.java @@ -39,7 +39,7 @@ public class Cell implements Serializable { public int x; public int y; public int z; - public float energy=0; + public float energy = 0; public Cell(int x, int y, int z) { this.x = x; @@ -59,10 +59,18 @@ public class Cell implements Serializable { organs[organs.length - 1] = orgNo; } + public boolean inActive() { + if (energy > 30) { + energy -= 30; + return true; + } + return false; + } + public void addEnergy(float e) { energy += e; - if (energy > 100) - energy = 100; + if (energy > 1000) + energy = 1000; } public void subEnergy(float e) { diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/Organ.java b/core/src/main/java/com/github/drinkjava2/frog/brain/Organ.java index 3323e6d..b90c71f 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/brain/Organ.java +++ b/core/src/main/java/com/github/drinkjava2/frog/brain/Organ.java @@ -15,8 +15,6 @@ import java.io.Serializable; import com.github.drinkjava2.frog.Env; import com.github.drinkjava2.frog.Frog; -import com.github.drinkjava2.frog.brain.organ.Line; -import com.github.drinkjava2.frog.brain.organ.Lines; import com.github.drinkjava2.frog.util.RandomUtils; /** @@ -70,8 +68,8 @@ public class Organ implements Serializable, Cloneable {// 因为要保存在蛋 /** each step will call Organ's active methodd */ public void active(Frog f) {// 每一步测试都会调用active方法,它通常遍历每个细胞,调用它们的cellAct方法 - // 这里是缺省的方法体,子类可以重写这个方法 - if (!f.alive || shape == null) + // 这里是缺省的方法体,只针对最常见的形状为长方体的器官,子类可以重写这个方法 + if (!f.alive || shape == null || shape.getClass() != Cuboid.class) return; Cuboid c = (Cuboid) shape; for (int px = 0; px < c.xe; px++) @@ -91,35 +89,26 @@ public class Organ implements Serializable, Cloneable {// 因为要保存在蛋 return; pic.setPicColor(Color.LIGHT_GRAY); // 缺省是灰色 shape.drawOnBrainPicture(pic); - pic.setPicColor(Color.RED); // 缺省是灰色 if (this.organName != null && this.shape.getClass() == Cuboid.class) { int x = ((Cuboid) shape).x; int y = ((Cuboid) shape).y; int z = ((Cuboid) shape).z; pic.drawText(x, y, z, this.organName); } - } - public boolean getLineEnergy(Frog f, Cell c) { - Lines ls = f.findOrganByClass(Lines.class); - for (Line l : ls.lines) { - if (l == null || l.energy < 30) - continue; - if (l.x2 == c.x && l.y2 == c.y && l.z2 == c.z) { - l.energy -= 30; - return true; - } + pic.setPicColor(Color.RED); + if (this.shape.getClass() == Cuboid.class) { // 显示每个细胞的能量 + Cuboid c = (Cuboid) shape; + for (int px = 0; px < c.xe; px++) + for (int py = 0; py < c.ye; py++) + for (int pz = 0; pz < c.ze; pz++) { + Cell cell = f.getCell(c.x + px, c.y + py, c.z + pz); + if (cell != null) { + pic.drawText(c.x + px, c.y + py, c.z + pz, "" + cell.energy, 1.5f); + } + } } - return false; - } - public static void addLineEnergy(Frog f, Cell c, float energy) { - Lines ls = f.findOrganByClass(Lines.class); - for (Line l : ls.lines) { - if (l == null || l.energy > 100) - continue; - if (l.x1 == c.x && l.y1 == c.y && l.z1 == c.z) // 如果线的输入端位于视网膜上,增加线的能量 - l.energy += energy; - } } + } diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Active.java b/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Active.java index c894935..5b3ed0e 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Active.java +++ b/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Active.java @@ -16,7 +16,6 @@ import com.github.drinkjava2.frog.Frog; import com.github.drinkjava2.frog.brain.Cell; import com.github.drinkjava2.frog.brain.Cuboid; import com.github.drinkjava2.frog.brain.Organ; -import com.github.drinkjava2.frog.util.RandomUtils; /** * Active always active @@ -25,19 +24,25 @@ import com.github.drinkjava2.frog.util.RandomUtils; */ public class Active extends Organ {// 这个器官的作用总是激活一个固定区,它有可能会被自然选择选中 private static final long serialVersionUID = 1L; - public int actEngery = 5; + public int actEngery = 2; public Active() { this.shape = new Cuboid(15, 10, FROG_BRAIN_ZSIZE / 2 + 3, 1, 1, 1); } public Organ[] vary(Frog f) {// 重写器官的very方法 - actEngery = RandomUtils.varyInLimit(actEngery, 1, 500); + // actEngery = RandomUtils.varyInLimit(actEngery, 1, 5); +// if (RandomUtils.percent(3f)) { +// Active a = new Active(); +// Cuboid c = (Cuboid) a.shape; +// c.y--; +// return new Organ[] { this, a }; +// } return new Organ[] { this }; } @Override public void cellAct(Frog f, Cell c) { - addLineEnergy(f, c, actEngery); + c.energy -= actEngery; } } diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Eat.java b/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Eat.java index 1838cfa..2f6eeb1 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Eat.java +++ b/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Eat.java @@ -10,34 +10,25 @@ */ package com.github.drinkjava2.frog.brain.organ; -import static com.github.drinkjava2.frog.Env.FROG_BRAIN_ZSIZE; - import com.github.drinkjava2.frog.Env; import com.github.drinkjava2.frog.Frog; -import com.github.drinkjava2.frog.brain.Cuboid; import com.github.drinkjava2.frog.brain.Organ; -import com.github.drinkjava2.frog.util.RandomUtils; /** * Happy active after ate food */ public class Eat extends Organ { // Eat器官的作用就是如果位置与食物重合,增加frog的能量 - private static final long serialVersionUID = 1L; public int actEngery = 1000; - public Eat() { - this.shape = new Cuboid(15, 13, FROG_BRAIN_ZSIZE / 2 + 3, 1, 1, 1); - } - public Organ[] vary(Frog f) {// 重写器官的very方法 - actEngery = RandomUtils.varyInLimit(actEngery, 1, 5000); return new Organ[] { this }; } @Override public void active(Frog f) { if (Env.foundAndAteFood(f.x, f.y)) { + f.ateFood++; f.energy += actEngery; } } diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java b/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java index 393bc08..4532f9f 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java +++ b/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java @@ -35,11 +35,13 @@ public class Eye {// 这个眼睛是从青蛙视角来观察,因为青蛙生 public static class SeeUp extends Organ {// 这个感光细胞只能看到上方有没有物体 private static final long serialVersionUID = 1L; public int seeDistance = 10; - public int addEyeEnergy = 6; + public int addEng = 30; + public int subEng = 2; public Organ[] vary(Frog f) {// 重写器官的very方法,允许眼睛看到的距离随机进化 - seeDistance = RandomUtils.varyInLimit(seeDistance, 1, 50); - addEyeEnergy = RandomUtils.varyInLimit(addEyeEnergy, 1, 200); + seeDistance = RandomUtils.varyInLimit(seeDistance, 5, 15); + addEng = RandomUtils.varyInLimit(addEng, 10, 30); + subEng = RandomUtils.varyInLimit(subEng, 1, 30); return new Organ[] { this }; } @@ -50,8 +52,10 @@ public class Eye {// 这个眼睛是从青蛙视角来观察,因为青蛙生 public void cellAct(Frog f, Cell c) {// 如果上方有物体就激活视网膜细胞 for (int i = 1; i <= seeDistance; i++) if (Env.foundAnyThing(f.x, f.y - i)) { - addLineEnergy(f, c, addEyeEnergy); + c.addEnergy(addEng); + return; } + c.subEnergy(subEng); } } @@ -62,11 +66,13 @@ public class Eye {// 这个眼睛是从青蛙视角来观察,因为青蛙生 shape = new Cuboid(cx, cy - 2, cz, 1, 1, 1); } - public void cellAct(Frog f, Cell c) {// 如果上方有物体就激活视网膜细胞 + public void cellAct(Frog f, Cell c) { for (int i = 1; i <= seeDistance; i++) if (Env.foundAnyThing(f.x, f.y + i)) { - addLineEnergy(f, c, addEyeEnergy); + c.addEnergy(addEng); + return; } + c.subEnergy(subEng); } } @@ -77,11 +83,13 @@ public class Eye {// 这个眼睛是从青蛙视角来观察,因为青蛙生 shape = new Cuboid(cx - 2, cy, cz, 1, 1, 1); } - public void cellAct(Frog f, Cell c) {// 如果上方有物体就激活视网膜细胞 + public void cellAct(Frog f, Cell c) { for (int i = 1; i <= seeDistance; i++) if (Env.foundAnyThing(f.x - i, f.y)) { - addLineEnergy(f, c, addEyeEnergy); + c.addEnergy(addEng); + return; } + c.subEnergy(subEng); } } @@ -92,11 +100,13 @@ public class Eye {// 这个眼睛是从青蛙视角来观察,因为青蛙生 shape = new Cuboid(cx + 2, cy, cz, 1, 1, 1); } - public void cellAct(Frog f, Cell c) {// 如果上方有物体就激活视网膜细胞 + public void cellAct(Frog f, Cell c) { for (int i = 1; i <= seeDistance; i++) if (Env.foundAnyThing(f.x + i, f.y)) { - addLineEnergy(f, c, addEyeEnergy); + c.addEnergy(addEng); + return; } + c.subEnergy(subEng); } } diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Line.java b/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Line.java index 3e9ba88..e855680 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Line.java +++ b/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Line.java @@ -10,9 +10,11 @@ */ package com.github.drinkjava2.frog.brain.organ; -import java.io.Serializable; - +import com.github.drinkjava2.frog.Frog; +import com.github.drinkjava2.frog.brain.BrainPicture; import com.github.drinkjava2.frog.brain.Cell; +import com.github.drinkjava2.frog.brain.Organ; +import com.github.drinkjava2.frog.util.RandomUtils; /** * Line is a line from cell1 to cell2 @@ -20,16 +22,13 @@ import com.github.drinkjava2.frog.brain.Cell; * @author Yong Zhu * @since 2020-04-18 */ -public class Line implements Serializable {// Line代表一个从cell1到cell2的神经元连接,energy表示连接能量 +public class Line extends Organ {// Line代表一个从cell1到cell2的神经元连接,energy表示连接能量 private static final long serialVersionUID = 1L; - public float energy; + + public int eng = 30; public int fat = 0; public int x1, y1, z1, x2, y2, z2; - public Line() { - // 缺省构造器必有, 因为从磁盘上反序列化要先调用这个构造器 - } - public Line(Cell c1, Cell c2) { this.x1 = c1.x; this.y1 = c1.y; @@ -39,4 +38,37 @@ public class Line implements Serializable {// Line代表一个从cell1到cell2 this.z2 = c2.z; } + public void active(Frog f) {// 重写active方法,line的作用就是在细胞c1,c2间传送能量(即信息) + if (!f.alive) + return; + if (RandomUtils.percent(5)) + eng = RandomUtils.varyInLimit(eng, 1, 70);// 传输的能量也参与进化 + Cell c1 = f.getCell1(this); + if (c1 == null) + return; + Cell c2 = f.getCell2(this); + if (c2 == null) + return; + if (c1.energy > eng) { // 为了保证能量(即熵)守恒,传出的能量要不大于输入能量 + fat++; + c1.subEnergy(eng); + c2.addEnergy(eng); + } + } + + @Override + public Organ[] vary(Frog f) { + if (fat <= 0)// 如果胖值为0,表示这个组的细胞没有用到,可以小概率丢掉它了 + if (RandomUtils.percent(30)) + return new Organ[] {}; + if (RandomUtils.percent(3)) // 有3%的几率丢掉它,防止这个器官数量只增不减 + return new Organ[] {}; + return new Organ[] { this }; + } + + public void drawOnBrainPicture(Frog f, BrainPicture pic) { + pic.drawLine(this); + pic.drawPoint(this.x2 + .5f, this.y2 + .5f, this.z2 + .5f, 5); + pic.drawText((x1 + x2) / 2, (y1 + y2) / 2, (z1 + z2) / 2, "" + eng, 1); + } } diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Lines.java b/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Lines.java deleted file mode 100644 index 1d37a1f..0000000 --- a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Lines.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2018 the original author or authors. - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by - * applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS - * OF ANY KIND, either express or implied. See the License for the specific - * language governing permissions and limitations under the License. - */ -package com.github.drinkjava2.frog.brain.organ; - -import java.awt.Color; - -import com.github.drinkjava2.frog.Env; -import com.github.drinkjava2.frog.Frog; -import com.github.drinkjava2.frog.brain.BrainPicture; -import com.github.drinkjava2.frog.brain.Cell; -import com.github.drinkjava2.frog.brain.Organ; -import com.github.drinkjava2.frog.util.RandomUtils; - -/** - * If move cell active, frog will move - * - * Move被分成上下左右四个独立的运动输出器官,这样方便编程 - * - * @author Yong Zhu - */ -public class Lines extends Organ {// Lines器官很重要,它是神经元之间的连线,由随机生成,由生存竟争淘汰 - private static final long serialVersionUID = 1L; - private static final int LINE_QTY = 100;// 总共允许最多有多少根线条 - public Line[] lines; - - public Lines() { - shape = null; - organName = null; - if (lines == null) - lines = new Line[LINE_QTY]; - } - - public void init(Frog f, int orgNo) { // 在青蛙生成时会调用这个方法,进行一些初始化 - if (RandomUtils.percent(3f)) // 生成线 - addLine(f); - if (RandomUtils.percent(3f)) // 丢弃线 - discardLine(f); - } - - /** - * 有两个任务:1.生成或丢弃线 2.用线在细胞间传输能量 - */ - public void active(Frog f) { - for (Line line : lines) { - if (line == null) - continue; - f.energy -= 1; //线不是越多越好,线越多,所需能量越多 - } - } - - public void addLine(Frog f) {// 随机生成线 - Cell c1 = RandomUtils.getRandomCell(f); - if (c1 == null) - return; - Cell c2 = RandomUtils.getRandomCell(f); - if (c2 == null) - return; - for (int i = 0; i < lines.length; i++) {// 找空位插入新的线 - if (lines[i] == null) { - lines[i] = new Line(c1, c2); - return; - } - } - // 没找到? 随便找个位置顶替原来的线 - lines[RandomUtils.nextInt(LINE_QTY)] = new Line(c1, c2); - } - - public void discardLine(Frog f) {// 随机丢弃线 - lines[RandomUtils.nextInt(LINE_QTY)] = null; - } - - /** Child class can override this method to drawing picture */ - public void drawOnBrainPicture(Frog f, BrainPicture pic) { // 把器官的轮廓显示在脑图上 - if (!Env.SHOW_FIRST_FROG_BRAIN || !f.alive) // 如果不允许画或青蛙死了,就直接返回 - return; - for (Line line : lines) { - if (line == null) - continue; - if (line.energy > 0) // 正值用兰色,负值用红色表示 - pic.setPicColor(Color.RED); - else - pic.setPicColor(Color.GRAY); - pic.drawLine(line); - pic.drawPoint(line.x2 + .5f, line.y2 + .5f, line.z2 + .5f, 10); - } - } - -} diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Move.java b/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Move.java index 1eb32ec..24e1765 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Move.java +++ b/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Move.java @@ -39,7 +39,7 @@ public class Move {// 因为青蛙生活在二次元,所以只有上下左右4 @Override public void cellAct(Frog f, Cell c) { - if (getLineEnergy(f, c)) + if (c.inActive()) f.y--; } } @@ -53,7 +53,7 @@ public class Move {// 因为青蛙生活在二次元,所以只有上下左右4 @Override public void cellAct(Frog f, Cell c) { - if (getLineEnergy(f, c)) + if (c.inActive()) f.y++; } } @@ -67,7 +67,7 @@ public class Move {// 因为青蛙生活在二次元,所以只有上下左右4 @Override public void cellAct(Frog f, Cell c) { - if (getLineEnergy(f, c)) + if (c.inActive()) f.x--; } } @@ -81,7 +81,7 @@ public class Move {// 因为青蛙生活在二次元,所以只有上下左右4 @Override public void cellAct(Frog f, Cell c) { - if (getLineEnergy(f, c)) + if (c.inActive()) f.x++; } } diff --git a/core/src/main/java/com/github/drinkjava2/frog/egg/Egg.java b/core/src/main/java/com/github/drinkjava2/frog/egg/Egg.java index 37755d5..5d0b650 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/egg/Egg.java +++ b/core/src/main/java/com/github/drinkjava2/frog/egg/Egg.java @@ -17,10 +17,10 @@ import java.util.List; import com.github.drinkjava2.frog.Frog; import com.github.drinkjava2.frog.brain.Organ; import com.github.drinkjava2.frog.brain.organ.Active; -import com.github.drinkjava2.frog.brain.organ.Eye; import com.github.drinkjava2.frog.brain.organ.Eat; -import com.github.drinkjava2.frog.brain.organ.Lines; +import com.github.drinkjava2.frog.brain.organ.Eye; import com.github.drinkjava2.frog.brain.organ.Move; +import com.github.drinkjava2.frog.brain.organ.Move.MoveUp; import com.github.drinkjava2.frog.util.RandomUtils; /** @@ -50,7 +50,6 @@ public class Egg implements Serializable { organs.add(new Move.MoveRight()); organs.add(new Active()); // 始终激活 organs.add(new Eat()); // 没有什么比吃到东西更愉快的了 - organs.add(new Lines()); // 连线 } /** Create egg from frog */ diff --git a/core/src/main/java/com/github/drinkjava2/frog/util/RandomUtils.java b/core/src/main/java/com/github/drinkjava2/frog/util/RandomUtils.java index 59ac0bd..d6540be 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/util/RandomUtils.java +++ b/core/src/main/java/com/github/drinkjava2/frog/util/RandomUtils.java @@ -109,15 +109,29 @@ public class RandomUtils { return v; } +// public static int vary(int v) {// 随机有大概率小变异,小概率大变异,极小概率极大变异 +// if (percent(40)) +// v *= .98 + .04 * nextFloat(); // 0.98~1.02 +// if (percent(10)) +// v *= .95 + .103 * nextFloat(); // 0.95~1.053 +// else if (percent(5)) +// v *= .08 + 0.45 * nextFloat(); // 0.8~1.25 +// else if (percent(1)) +// v *= .05 + 1.5 * nextFloat(); // 0.5~2 +// return v; +// } + public static int vary(int v) {// 随机有大概率小变异,小概率大变异,极小概率极大变异 if (percent(40)) - v *= .98 + .04 * nextFloat(); // 0.98~1.02 + v += v * .04 * (nextFloat() - 0.5); // v=v+-.04 if (percent(10)) - v *= .95 + .103 * nextFloat(); // 0.95~1.053 + v += v * .103 * (nextFloat() - 0.5); // v=v+-0.1 else if (percent(5)) - v *= .08 + 0.45 * nextFloat(); // 0.8~1.25 - else if (percent(1)) - v *= .05 + 1.5 * nextFloat(); // 0.5~2 + v += v * 1 * (nextFloat() - 0.5); // v=v+-0.4 + else if (percent(2)) + v += v * 4 * (nextFloat() - 0.5); // v=v+-2 + else if (percent(1f)) + v += v * 8 * (nextFloat() - 0.5); // v=v+-6 return v; } @@ -136,15 +150,29 @@ public class RandomUtils { return v; } +// public static float vary(float v) {// 随机有大概率小变异,小概率大变异,极小概率极大变异 +// if (percent(40)) +// v *= .98 + .04 * nextFloat(); // 0.98~1.02 +// if (percent(10)) +// v *= .95 + .103 * nextFloat(); // 0.95~1.053 +// else if (percent(5)) +// v *= .08 + 0.45 * nextFloat(); // 0.8~1.25 +// else if (percent(1)) +// v *= .05 + 1.5 * nextFloat(); // 0.5~2 +// return v; +// } + public static float vary(float v) {// 随机有大概率小变异,小概率大变异,极小概率极大变异 if (percent(40)) - v *= .98 + .04 * nextFloat(); // 0.98~1.02 + v += v * .04 * (nextFloat() - 0.5); // v=v+-.04 if (percent(10)) - v *= .95 + .103 * nextFloat(); // 0.95~1.053 + v += v * .103 * (nextFloat() - 0.5); // v=v+-0.1 else if (percent(5)) - v *= .08 + 0.45 * nextFloat(); // 0.8~1.25 - else if (percent(1)) - v *= .05 + 1.5 * nextFloat(); // 0.5~2 + v += v * 1 * (nextFloat() - 0.5); // v=v+-0.4 + else if (percent(2)) + v += v * 4 * (nextFloat() - 0.5); // v=v+-2 + else if (percent(1f)) + v += v * 8 * (nextFloat() - 0.5); // v=v+-6 return v; } diff --git a/history/001_first_version/README.md b/history/001_first_version/README.md new file mode 100644 index 0000000..7c07ef6 --- /dev/null +++ b/history/001_first_version/README.md @@ -0,0 +1,3 @@ +## history\001分支简介 +2019.03.11 这是frog项目第一个版本,虚拟环境初步建立,可以模拟低等生命的遗传、繁殖、变异、进化现象,但只能往一个方向运动,相当于一个最简单的单细胞生物,还不具备视觉能力,不具备主动找食能力。 +运行run.bat可以查看演示(需要安装Java8和Maven)。 diff --git a/history/002_first_eye/README.md b/history/002_first_eye/README.md new file mode 100644 index 0000000..cd0607c --- /dev/null +++ b/history/002_first_eye/README.md @@ -0,0 +1,3 @@ +## history\002分支简介 +2019-04-12 添加一个简单的眼睛(只有四个感光细胞),自然选择的结果是眼睛被选中,但是和运动区短路了,谈不上智能。但有眼睛后找食效率明显提高了。 +这个分支的意义在于它证明了完全随机分布的神经元可以进化成眼睛。 \ No newline at end of file diff --git a/history/003_trap/README.md b/history/003_trap/README.md new file mode 100644 index 0000000..906553e --- /dev/null +++ b/history/003_trap/README.md @@ -0,0 +1,6 @@ +## history\003分支简介 +2019-07-28 有以下改动: +1.在Env区中间加了一个陷阱区Trap,以增加趣味性,自然选择的结果是青蛙会自动绕开陷阱区。 +2.增加一个Active器官,它的作用是一直保持激活,发现比Hungry器官驱动更能提高找食效率。 +3.增加一个Chance器官,它的作用是引入随机扰动,打破青蛙有时候围着一个食物打转就是吃不着的死循环。目前进食奖励信号没用到,白白浪费了。 +另外Chance和Eye类里也再次运用了随机试错原理去确定关键参数, \ No newline at end of file diff --git a/history/003a_legs/README.md b/history/003a_legs/README.md new file mode 100644 index 0000000..319053d --- /dev/null +++ b/history/003a_legs/README.md @@ -0,0 +1,2 @@ +## 简介 +2019-12-27 在history\003a_legs目录下(依然是2维脑)尝试给青蛙加两条腿,看它能不能自动学会走路。一条腿位于下方,负责左右移动,一条腿位于右侧,负责上下移动,每条腿有抬腿、落腿、转动和相应的感觉细胞。只有当腿落下且转动,而且另一条脚抬起来时青蛙才会位移,具体什么时候抬腿、什么时候转动腿完全由随机数决定。经过一段时间的生存汰淘之后,青蛙会进化出会利用两条腿走路了,但需要的时间非常长,约几个小时之后才达到最高吃食率50%左右,走路风格也比较诡异,是小碎步而不是大踏步。但至少这是青蛙第一次利用两条腿来走路,还是有点意义的,这证明生命进化中就算神经元随机排布,进化出眼睛和腿也是非常简单自然的事。 \ No newline at end of file diff --git a/history/003b_simple/LICENSE b/history/003b_simple/LICENSE new file mode 100644 index 0000000..8dada3e --- /dev/null +++ b/history/003b_simple/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/history/003b_simple/README.md b/history/003b_simple/README.md new file mode 100644 index 0000000..4f843f6 --- /dev/null +++ b/history/003b_simple/README.md @@ -0,0 +1,5 @@ +## 这个分支是基于003_trap基础上简化得来的,意义不是很大,只是为了方便我整理一下思路 + + +说明:本人在作3D脑结构时,发现找食率始终很难提高到40%以上,原因是没有忠实地照搬2维脑的逻辑,但一时找不到问题所在。原来的2维脑器官太多,因此这在个分支里先去除不需要的器官和逻辑,把2维脑精简到能进化出眼睛的最简结构,以便于为下一步转化到3D模式作准备。 +在实验中发现Active中的organOutputEnergy参数对进化影响非常大,最合适的值为1~3之间,吃食率最高可达80%,其它的值吃食率极低。 diff --git a/history/003b_simple/maven_clean.bat b/history/003b_simple/maven_clean.bat new file mode 100644 index 0000000..2f3d3e5 --- /dev/null +++ b/history/003b_simple/maven_clean.bat @@ -0,0 +1 @@ +mvn clean \ No newline at end of file diff --git a/history/003b_simple/maven_eclipse_clean.bat b/history/003b_simple/maven_eclipse_clean.bat new file mode 100644 index 0000000..a427bd7 --- /dev/null +++ b/history/003b_simple/maven_eclipse_clean.bat @@ -0,0 +1 @@ +mvn eclipse:clean \ No newline at end of file diff --git a/history/003b_simple/maven_eclipse_eclipse.bat b/history/003b_simple/maven_eclipse_eclipse.bat new file mode 100644 index 0000000..99fa0b2 --- /dev/null +++ b/history/003b_simple/maven_eclipse_eclipse.bat @@ -0,0 +1,2 @@ +call mvn eclipse:eclipse +call pause \ No newline at end of file diff --git a/history/003b_simple/pom.xml b/history/003b_simple/pom.xml new file mode 100644 index 0000000..f7e7a24 --- /dev/null +++ b/history/003b_simple/pom.xml @@ -0,0 +1,102 @@ + + 4.0.0 + com.gitee.drinkjava2 + frog003b + jar + 1.0 + + frog + An artificial life test project + https://gitee.com/drinkjava2/jsqlbox/frog + + + gitee Issue + https://gitee.com/drinkjava2/jsqlbox/frog/issues + + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + + Yong Zhu + yong9981@gmail.com + https://gitee.com/drinkjava2/ + + + + + scm:git@gitee.com:drinkjava2/frog.git + scm:git@gitee.com:drinkjava2/frog.git + git@gitee.com:drinkjava2/frog.git + + + + UTF-8 + UTF-8 + UTF-8 + + 1.8 + 6 + 3.3 + 2.6 + 3.0.0 + 2.7 + 2.19 + 2.6 + 2.4 + 2.10.3 + 1.6 + + + + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${version.compiler-plugin} + + ${version.java} + ${version.java} + UTF-8 + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.2 + + + + true + false + lib/ + com.github.drinkjava2.frog.Application + + + + + + + + + + + diff --git a/history/003b_simple/run.bat b/history/003b_simple/run.bat new file mode 100644 index 0000000..ab1bab3 --- /dev/null +++ b/history/003b_simple/run.bat @@ -0,0 +1,4 @@ +call mvn clean compile +cd target\classes +java -classpath ".;*" com.github.drinkjava2.frog.Application +@pause \ No newline at end of file diff --git a/history/003b_simple/run.sh b/history/003b_simple/run.sh new file mode 100644 index 0000000..836c941 --- /dev/null +++ b/history/003b_simple/run.sh @@ -0,0 +1,2 @@ +mvn clean package +java -jar target/frog-*.jar diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/Application.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/Application.java new file mode 100644 index 0000000..bd58fa5 --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/Application.java @@ -0,0 +1,107 @@ +package com.github.drinkjava2.frog; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JSlider; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import com.github.drinkjava2.frog.brain.BrainPicture; + +/** + * Application's main method start the program + * + * @author Yong Zhu + * @since 1.0 + */ +public class Application { + /** SHOW first frog's brain structure */ + public static boolean SHOW_FIRST_FROG_BRAIN = false; + public static final String CLASSPATH; + + static { + String classpath = new File("").getAbsolutePath(); + int i = classpath.indexOf("\\frog\\"); + if (i > 0) + CLASSPATH = classpath.substring(0, i) + "\\frog\\";// windows + else + CLASSPATH = classpath + "/"; // UNIX + } + public static JFrame mainFrame = new JFrame(); + public static Env env = new Env(); + public static BrainPicture brainPic = new BrainPicture(Env.ENV_WIDTH + 5, 0, Env.FROG_BRAIN_WIDTH, + Env.FROG_BRAIN_DISP_WIDTH); + + public static void main(String[] args) throws InterruptedException { + mainFrame.setLayout(null); + mainFrame.setSize(Env.ENV_WIDTH + 20, Env.ENV_HEIGHT + 125); // 窗口大小 + mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 关闭时退出程序 + mainFrame.add(env); + + mainFrame.add(brainPic); + + JButton button = new JButton("Show first frog's brain"); + int buttonWidth = 180; + int buttonHeight = 22; + int buttonXpos = Env.ENV_WIDTH / 2 - buttonWidth / 2; + button.setBounds(buttonXpos, Env.ENV_HEIGHT + 8, buttonWidth, buttonHeight); + ActionListener al = new ActionListener() { + @Override + public void actionPerformed(ActionEvent arg0) { + SHOW_FIRST_FROG_BRAIN = !SHOW_FIRST_FROG_BRAIN; + if (SHOW_FIRST_FROG_BRAIN) { + button.setText("Hide first frog's brain"); + int y = Env.ENV_HEIGHT + 125; + if (Env.FROG_BRAIN_DISP_WIDTH + 41 > y) + y = Env.FROG_BRAIN_DISP_WIDTH + 41; + mainFrame.setSize(Env.ENV_WIDTH + Env.FROG_BRAIN_DISP_WIDTH + 25, y); + } else { + button.setText("Show first frog's brain"); + mainFrame.setSize(Env.ENV_WIDTH + 20, Env.ENV_HEIGHT + 125); + } + } + }; + button.addActionListener(al); + mainFrame.add(button); + + JButton stopButton = new JButton("Pause"); + stopButton.setBounds(buttonXpos, Env.ENV_HEIGHT + 35, buttonWidth, buttonHeight); + ActionListener a2 = new ActionListener() { + @Override + public void actionPerformed(ActionEvent arg0) { + Env.pause = !Env.pause; + if (Env.pause) { + stopButton.setText("Resume"); + } else { + stopButton.setText("Pause"); + } + } + }; + stopButton.addActionListener(a2); + mainFrame.add(stopButton); + + + + final JSlider speedSlider = new JSlider(1, 10, (int) Math.round(Math.sqrt(Env.SHOW_SPEED))); // 速度条 + speedSlider.setBounds(buttonXpos - 50, stopButton.getY() + 25, buttonWidth + 100, buttonHeight); + ChangeListener slideAction = new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + Env.SHOW_SPEED = speedSlider.getValue() * speedSlider.getValue() * speedSlider.getValue(); + } + }; + speedSlider.addChangeListener(slideAction); + mainFrame.add(speedSlider); + final JLabel label = new JLabel("Speed:"); + label.setBounds(buttonXpos - 90, stopButton.getY() + 23, 100, buttonHeight); + mainFrame.add(label); + mainFrame.setVisible(true); + env.run(); + } + +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/Env.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/Env.java new file mode 100644 index 0000000..29a476b --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/Env.java @@ -0,0 +1,256 @@ +package com.github.drinkjava2.frog; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Image; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.JPanel; + +import com.github.drinkjava2.frog.brain.organ.Line; +import com.github.drinkjava2.frog.egg.Egg; +import com.github.drinkjava2.frog.egg.EggTool; +import com.github.drinkjava2.frog.objects.Food; +import com.github.drinkjava2.frog.objects.Material; +import com.github.drinkjava2.frog.objects.Object; +import com.github.drinkjava2.frog.util.RandomUtils; + +/** + * Env is the living space of frog. draw it on JPanel + * + * @author Yong Zhu + * @since 1.0 + */ +@SuppressWarnings("all") +public class Env extends JPanel { + /** Speed of test */ + public static int SHOW_SPEED = 4; // 测试速度,-1000~1000,可调, 数值越小,速度越慢 + + /** Delete eggs at beginning of each run */ + public static final boolean DELETE_EGGS = true;// 每次运行是否先删除保存的蛋 + + public static final int EGG_QTY = 25; // 每轮下n个蛋,可调,只有最优秀的前n个青蛙们才允许下蛋 + + public static final int FROG_PER_EGG = 4; // 每个蛋可以孵出几个青蛙 + + public static final int SCREEN = 1; // 分几屏测完 + + public static final int FROG_PER_SCREEN = EGG_QTY * FROG_PER_EGG / SCREEN; // 每屏上显示几个青蛙,这个数值由上面三个参数计算得来 + + /** Draw first frog's brain after some steps */ + public static int DRAW_BRAIN_AFTER_STEPS = 50; // 以此值为间隔动态画出脑图,设为0则关闭这个动态脑图功能,只显示一个静态、不闪烁的脑图 + + /** Environment x width, unit: pixels */ + public static final int ENV_WIDTH = 400; // 虚拟环境的宽度, 可调 + + /** Environment y height, unit: pixels */ + public static final int ENV_HEIGHT = ENV_WIDTH; // 虚拟环境高度, 可调,通常取正方形 + + /** Frog's brain display width on screen, not important */ + public static final int FROG_BRAIN_DISP_WIDTH = 400; // Frog的脑图在屏幕上的显示大小,可调 + + /** Steps of one test round */ + public static final int STEPS_PER_ROUND = 2000;// 每轮测试步数,可调 + + /** Frog's brain width, fixed to 1000 unit */ + public static final float FROG_BRAIN_WIDTH = 1000; // frog的脑宽度固定为1000,不要随便调整,因为器官的相对位置和大小是按脑大小设定的 + + public static final int FOOD_QTY = 1500; // 食物数量, 可调 + + public static boolean pause = false; // 暂停按钮按下将暂停测试 + + public static byte[][] bricks = new byte[ENV_WIDTH][ENV_HEIGHT];// 组成环境的材料,0=无, 1=食, 其它=其它... + + public static List frogs = new ArrayList<>(); // 这里存放所有待测的青蛙,可能分几次测完,由FROG_PER_SCREEN大小来决定 + + public static List eggs = new ArrayList<>(); // 这里存放从磁盘载入或上轮下的蛋,每个蛋可能生成1~n个青蛙, + + public static Object[] things = new Object[] { new Food() }; + + static { + System.out.println("唵缚悉波罗摩尼莎诃!"); // 杀生前先打印往生咒,见码云issue#IW4H8 + if (DELETE_EGGS) + EggTool.deleteEggs(); + } + + public Env() { + super(); + this.setLayout(null);// 空布局 + this.setBounds(1, 1, ENV_WIDTH, ENV_HEIGHT); + } + + public static boolean insideEnv(int x, int y) {// 如果指定点在边界内 + return !(x < 0 || y < 0 || x >= ENV_WIDTH || y >= ENV_HEIGHT); + } + + public static boolean outsideEnv(int x, int y) {// 如果指定点超出边界 + return x < 0 || y < 0 || x >= ENV_WIDTH || y >= ENV_HEIGHT; + } + + public static boolean closeToEdge(Frog f) {// 青蛙靠近边界? 离死不远了 + return f.x < 20 || f.y < 20 || f.x > (Env.ENV_WIDTH - 20) || f.y > (Env.ENV_HEIGHT - 20); + } + + public static boolean foundAnyThing(int x, int y) {// 如果指定点看到任意东西或超出边界 + return x < 0 || y < 0 || x >= ENV_WIDTH || y >= ENV_HEIGHT || Env.bricks[x][y] >= Material.VISIBLE; + } + + public static boolean foundAndAteFood(int x, int y) {// 如果x,y有食物,将其清0,返回true + if (insideEnv(x, y) && Env.bricks[x][y] == Material.FOOD) { + bricks[x][y] = 0; + return true; + } + return false; + } + + private void rebuildFrogs() { + frogs.clear(); + for (int i = 0; i < eggs.size(); i++) {// 创建青蛙,每个蛋生成n个蛙,并随机取一个别的蛋作为精子 + int loop = FROG_PER_EGG; + if (eggs.size() > 20) { // 如果数量多,进行一些优化,让排名靠前的Egg多孵出青蛙 + if (i < FROG_PER_EGG)// 0,1,2,3 + loop = FROG_PER_EGG + 1; + if (i >= (eggs.size() - FROG_PER_EGG)) + loop = FROG_PER_EGG - 1; + } + for (int j = 0; j < loop; j++) { + Egg zygote = new Egg(eggs.get(i), eggs.get(RandomUtils.nextInt(eggs.size()))); + frogs.add(new Frog(RandomUtils.nextInt(ENV_WIDTH), RandomUtils.nextInt(ENV_HEIGHT), zygote)); + } + } + } + + private void drawWorld(Graphics g) { + byte brick; + for (int x = 0; x < ENV_WIDTH; x++) + for (int y = 0; y < ENV_HEIGHT; y++) { + brick = bricks[x][y]; + if (brick != 0) { + g.setColor(Material.color(brick)); + if (brick == Material.FOOD) + g.fillRoundRect(x, y, 4, 4, 2, 2); // show food bigger + else + g.drawLine(x, y, x, y); // only 1 point + } + } + g.setColor(Color.BLACK); + } + + static final NumberFormat format100 = NumberFormat.getPercentInstance(); + static { + format100.setMaximumFractionDigits(2); + } + + private static int foodFoundAmount() {// 统计找食数等 + int leftfood = 0; + for (int x = 0; x < ENV_WIDTH; x++) + for (int y = 0; y < ENV_HEIGHT; y++) + if (bricks[x][y] == Material.FOOD) + leftfood++; + return FOOD_QTY - leftfood; + } + + private String foodFoundCountText() {// 统计找食数等 + int foodFound = foodFoundAmount(); + int maxFound = 0; + for (Frog f : frogs) + if (f.ateFood > maxFound) + maxFound = f.ateFood; + return new StringBuilder("找食率:").append(format100.format(foodFound * 1.00 / FOOD_QTY)).append(", 平均: ") + .append(foodFound * 1.0f / FROG_PER_SCREEN).append(",最多:").append(maxFound).toString(); + } + + private static void sleep(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + public void run() { + EggTool.loadEggs(); // 从磁盘加载egg,或新建一批egg + Image buffImg = createImage(this.getWidth(), this.getHeight()); + Graphics g = buffImg.getGraphics(); + long time0;// 计时用 + int round = 1; + do { + rebuildFrogs(); + for (int screen = 0; screen < SCREEN; screen++) {// 分屏测试,每屏FROG_PER_SCREEN个蛙 + time0 = System.currentTimeMillis(); + if (pause) + do { + sleep(300); + } while (pause); + for (Object thing : things) // 创建食物、陷阱等物体 + thing.build(); + boolean allDead = false; + Frog firstFrog = frogs.get(screen * FROG_PER_SCREEN); + for (int j = 0; j < FROG_PER_SCREEN; j++) { + Frog f = frogs.get(screen * FROG_PER_SCREEN + j); + f.initOrgans(); + } + for (int i = 0; i < STEPS_PER_ROUND; i++) { + for (Object thing : things)// 调用食物、陷阱等物体的动作 + thing.active(screen); + if (allDead) + break; // 青蛙全死光了就直接跳到下一轮,以节省时间 + allDead = true; + for (int j = 0; j < FROG_PER_SCREEN; j++) { + Frog f = frogs.get(screen * FROG_PER_SCREEN + j); + if (f.active(this)) + allDead = false; + if (f.alive && RandomUtils.percent(0.2f)) {// 有很小的机率在青蛙活着时就创建新的器官 + Line newConGrp = new Line(); + newConGrp.initFrog(f); + f.organs.add(newConGrp); + } + } + + if (SHOW_SPEED > 0 && i % SHOW_SPEED != 0) // 用画青蛙的方式来拖慢速度 + continue; + + if (SHOW_SPEED < 0) // 如果speed小于0,人为加入延迟 + sleep(-SHOW_SPEED); + + // 开始画青蛙 + g.setColor(Color.white); + g.fillRect(0, 0, this.getWidth(), this.getHeight()); + g.setColor(Color.BLACK); + drawWorld(g); + for (int j = 0; j < FROG_PER_SCREEN; j++) { + Frog f = frogs.get(screen * FROG_PER_SCREEN + j); + f.show(g); + } + + if (firstFrog.alive) { // 开始显示第一个Frog的动态脑图 + if (Application.SHOW_FIRST_FROG_BRAIN) { + g.setColor(Color.red); + g.drawArc(firstFrog.x - 15, firstFrog.y - 15, 30, 30, 0, 360); + g.setColor(Color.BLACK); + } + if (DRAW_BRAIN_AFTER_STEPS > 0 && i % DRAW_BRAIN_AFTER_STEPS == 0) + Application.brainPic.drawBrainPicture(firstFrog); + } + Graphics g2 = this.getGraphics(); + g2.drawImage(buffImg, 0, 0, this); + } + for (int j = 0; j < FROG_PER_SCREEN; j++) { + Frog f = frogs.get(screen * FROG_PER_SCREEN + j); + f.cells.clear(); + } + Application.brainPic.drawBrainPicture(firstFrog); + Application.mainFrame.setTitle(new StringBuilder("Round: ").append(round).append(", screen:") + .append(screen).append(", ").append(foodFoundCountText()).append(", 用时: ") + .append(System.currentTimeMillis() - time0).append("ms").toString()); + for (Object thing : things)// 去除食物、陷阱等物体 + thing.destory(); + } + round++; + EggTool.layEggs(); + } while (true); + } + +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/Frog.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/Frog.java new file mode 100644 index 0000000..cf8be8d --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/Frog.java @@ -0,0 +1,89 @@ +/* + * Copyright 2018 the original author or authors. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by + * applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package com.github.drinkjava2.frog; + +import java.awt.Graphics; +import java.awt.Image; +import java.io.FileInputStream; +import java.util.ArrayList; +import java.util.List; + +import javax.imageio.ImageIO; + +import com.github.drinkjava2.frog.brain.Cell; +import com.github.drinkjava2.frog.brain.Organ; +import com.github.drinkjava2.frog.egg.Egg; +import com.github.drinkjava2.frog.objects.Material; + +/** + * Frog = organs + brain cells + * + * 青蛙由器官组成,器官中的Group类会生成各种脑细胞 + * + * @author Yong Zhu + * @since 1.0 + */ +public class Frog { + + /** brain cells */ + public List cells = new ArrayList<>(); + + /** organs */ + public List organs = new ArrayList<>(); + + public int x; // frog在Env中的x坐标 + public int y; // frog在Env中的y坐标 + public long energy = 100000; // 青蛙的能量为0则死掉 + public boolean alive = true; // 设为false表示青蛙死掉了,将不参与计算和显示,以节省时间 + public int ateFood = 0; + + static Image frogImg; + static { + try { + frogImg = ImageIO.read(new FileInputStream(Application.CLASSPATH + "frog.png")); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public Frog(int x, int y, Egg egg) { + this.x = x; + this.y = y; + for (Organ org : egg.organs) + organs.add(org); + } + + public void initOrgans() { + for (Organ org : organs) + org.initFrog(this);// 每个新器官初始化,如果是Group类,它们会生成许多脑细胞 + } + + public boolean active(Env v) { + // 如果能量小于0则死、出界、与非食物的点重合则判死 + if (!alive || energy < 0 || Env.outsideEnv(x, y) || Env.bricks[x][y] >= Material.KILLFROG) { + energy -= 100; // 死掉的青蛙也要消耗能量,确保淘汰出局 + alive = false; + return false; + } + energy -= 20; + for (Organ o : organs) { + o.active(this); + } + return alive; + } + + public void show(Graphics g) {// 显示青蛙的图象 + if (!alive) + return; + g.drawImage(frogImg, x - 8, y - 8, 16, 16, null); + } + +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java new file mode 100644 index 0000000..44de23f --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java @@ -0,0 +1,128 @@ +package com.github.drinkjava2.frog.brain; + +import static java.awt.Color.BLUE; +import static java.awt.Color.CYAN; +import static java.awt.Color.GREEN; +import static java.awt.Color.MAGENTA; +import static java.awt.Color.ORANGE; +import static java.awt.Color.RED; +import static java.awt.Color.YELLOW; + +import java.awt.Color; +import java.awt.Graphics; + +import javax.swing.JPanel; + +import com.github.drinkjava2.frog.Application; +import com.github.drinkjava2.frog.Frog; + +/** + * BrainPicture show first frog's brain structure, for debug purpose only + * + * @author Yong Zhu + * @since 1.0 + */ +@SuppressWarnings("serial") +public class BrainPicture extends JPanel { + private float brainWidth; // real brain width + private int brainDispWidth; // screen display width + private Color color = Color.BLACK; + + public void setColor(Color c) { + color = c; + } + + public BrainPicture(int x, int y, float brainWidth, int brainDispWidth) { + super(); + this.setLayout(null);// 空布局 + this.brainDispWidth = brainDispWidth; + this.brainWidth = brainWidth; + this.setBounds(x, y, brainDispWidth + 1, brainDispWidth + 1); + } + + public void drawZone( Zone z) {Graphics g = this.getGraphics(); + g.setColor(color); + float rate = brainDispWidth / brainWidth; + int x = Math.round(z.x * rate); + int y = Math.round(z.y * rate); + int radius = Math.round(z.r * rate); + g.drawRect(x - radius, y - radius, radius * 2, radius * 2); + } + + public void drawCircle( Zone z) {Graphics g = this.getGraphics(); + g.setColor(color); + float rate = brainDispWidth / brainWidth; + int x = Math.round(z.x * rate); + int y = Math.round(z.y * rate); + g.drawArc(x - 5, y - 5, 10, 10, 0, 360); + } + + public void fillZone( Zone z) {Graphics g = this.getGraphics(); + g.setColor(color); + float rate = brainDispWidth / brainWidth; + int x = Math.round(z.x * rate); + int y = Math.round(z.y * rate); + int radius = Math.round(z.r * rate); + g.fillRect(x - radius, y - radius, radius * 2, radius * 2); + } + + public void drawLine(Zone z1, Zone z2) { + Graphics g = this.getGraphics(); + g.setColor(color); + float rate = brainDispWidth / brainWidth; + int x1 = Math.round(z1.x * rate); + int y1 = Math.round(z1.y * rate); + int x2 = Math.round(z2.x * rate); + int y2 = Math.round(z2.y * rate); + g.drawLine(x1, y1, x2, y2); + } + + public void drawText( Zone z, String text) {Graphics g = this.getGraphics(); + g.setColor(color); + float rate = brainDispWidth / brainWidth; + int x = Math.round(z.x * rate); + int y = Math.round(z.y * rate); + g.drawString(text, x - text.length() * 3 - 2, y); + } + + private static final Color[] rainbow = new Color[] { RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA }; + private static int nextColor = 0; + + public static Color nextRainbowColor() { + if (nextColor == rainbow.length) + nextColor = 0; + return rainbow[nextColor++]; + } + + public static Color color(float i) { + if (i == 0) + return Color.black; + if (i == 1) + return Color.RED; + if (i <= 3) + return Color.ORANGE; + if (i <= 10) + return Color.YELLOW; + if (i <= 20) + return Color.GREEN; + if (i <= 50) + return Color.CYAN; + if (i <= 100) + return Color.BLUE; + return Color.MAGENTA; + } + + public void drawBrainPicture(Frog frog) { + if (!Application.SHOW_FIRST_FROG_BRAIN) + return; + Graphics g = this.getGraphics();// border + g.setColor(Color.WHITE); + g.fillRect(0, 0, brainDispWidth, brainDispWidth); + g.setColor(Color.black); + g.drawRect(0, 0, brainDispWidth, brainDispWidth); + + for (Organ organ : frog.organs) + organ.drawOnBrainPicture(frog, this); // each organ draw itself + } + +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/Cell.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/Cell.java new file mode 100644 index 0000000..fdae751 --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/Cell.java @@ -0,0 +1,34 @@ +/* + * Copyright 2018 the original author or authors. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by + * applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package com.github.drinkjava2.frog.brain; + +/** + * Cell is the basic unit of frog's brain + * + * @author Yong Zhu + * @since 1.0 + */ +public class Cell { + public static final float MAX_ENERGY_LIMIT = 100.0f; + + // this cell belong to frog's which organ + public Organ organ; + + // inputs of cell + public Input[] inputs; // 每个细胞有一组输入触突 + + // outputs of cell + public Output[] outputs; // 每个细胞有一组输出触突 + + // energy of cell, energy got from food + public float energy; // 每个细胞当前的能量值 + +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/Input.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/Input.java new file mode 100644 index 0000000..78f16b4 --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/Input.java @@ -0,0 +1,26 @@ +/* + * Copyright 2018 the original author or authors. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by + * applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package com.github.drinkjava2.frog.brain; + +/** + * Input is the sensor of nerve cell + * + * @author Yong Zhu + * @since 1.0 + */ +@SuppressWarnings("serial") +public class Input extends Zone { + public Cell cell; // 这个输入触突属于哪个脑细胞 + + public Input(Zone z) { + super(z); + } +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/Organ.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/Organ.java new file mode 100644 index 0000000..d74dca3 --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/Organ.java @@ -0,0 +1,105 @@ +/* + * Copyright 2018 the original author or authors. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by + * applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package com.github.drinkjava2.frog.brain; + +import java.awt.Color; + +import com.github.drinkjava2.frog.Application; +import com.github.drinkjava2.frog.Frog; + +/** + * Organ is a part of frog, organ can be saved in egg + * + * 器官是脑的一部分,多个器官在脑内可以允许重叠出现在同一位置。 + * + * @author Yong Zhu + * @since 1.0.4 + */ +public class Organ extends Zone { + private static final long serialVersionUID = 1L; + public String name; // 显示在脑图上的器官名称,可选 + public long fat = 0; // 如果活跃多,fat值高,则保留(及变异)的可能性大,反之则很可能丢弃掉 + // public float organWasteEnergy = 0.05f; // + // 器官在每个测试循环中需要消耗青蛙多少能量,可以通过调节这个参数抑制器官数量无限增长 + public float organActiveEnergy = 1; // 输出器官激活需要消耗每个脑细胞多少能量 + public float organOutputEnergy = 2; // 感觉器官激活会给每个脑细胞增加多少能量 + public boolean initilized; // 通过这个标记判断是否需要手工给定它的参数初值 + + public boolean allowBorrow() { // 是否允许在精子中将这个器官借出 + return false; + } + + /** Each loop step call active method, Child class can override this method */ + public void active(Frog f) { // 每一步都会调用器官的active方法 ,缺省啥也不干 + } + + /** If active in this organ's zone? */ + public boolean outputActive(Frog f) { // 如果一个细胞能量>10,且它的输出触突位于这个器官内,则器官被激活 + for (Cell cell : f.cells) { + if (cell.energy > organActiveEnergy) + for (Output output : cell.outputs) { // + if (this.nearby(output)) { + cell.organ.fat++; + cell.energy -= 30;// + return true; + } + } + } + return false; + } + + /** If active in this organ's zone? */ + public void activeInput(Frog f, float energy) { // 如果一个细胞能量>10,且它的输出触突位于这个器官内,则器官被激活 + for (Cell cell : f.cells) + if (cell.energy < 100) + for (Input input : cell.inputs) + if (input.nearby(this)) { + input.cell.energy += energy; + return; + } + } + + /** Set X, Y, Radius, name of current Organ */ + public Organ setXYRN(float x, float y, float r, String name) { + this.setXYR(x, y, r); + this.name = name; + return this; + } + + /** Child class can override this method to drawing picture */ + public void drawOnBrainPicture(Frog f, BrainPicture pic) {// 把自已这个器官在脑图上显示出来,子类可以重写这个方法 + if (!Application.SHOW_FIRST_FROG_BRAIN) + return; + pic.setColor(Color.BLACK); // 缺省是黑色 + pic.drawZone(this); + if (this.name != null) + pic.drawText(this, String.valueOf(this.name)); + } + + /** Only call once when frog created , Child class can override this method */ + public void initFrog(Frog f) { // 仅在Frog生成时这个方法会调用一次,缺省啥也不干,通常用于Group子类的初始化 + } + + /** Only call once after organ be created by new() method */ + public Organ[] vary() { // 在下蛋时每个器官会调用这个方法,缺省返回一个类似自已的副本,子类通常要覆盖这个方法 + Organ newOrgan = null; + try { + newOrgan = this.getClass().newInstance(); + } catch (Exception e) { + throw new UnknownError("Can not make new Organ copy for " + this); + } + copyXYR(this, newOrgan); + newOrgan.name = this.name; + newOrgan.fat = this.fat; + return new Organ[] { newOrgan }; + } + +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/Output.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/Output.java new file mode 100644 index 0000000..b794b93 --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/Output.java @@ -0,0 +1,26 @@ +/* + * Copyright 2018 the original author or authors. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by + * applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package com.github.drinkjava2.frog.brain; + +/** + * Output can active other nerve cell's input + * + * @author Yong Zhu + * @since 1.0 + */ +@SuppressWarnings("serial") +public class Output extends Zone { + public Cell cell; // 这个输出触突属于哪个脑细胞 + + public Output(Zone z) { + super(z); + } +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/Zone.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/Zone.java new file mode 100644 index 0000000..d8ae70e --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/Zone.java @@ -0,0 +1,84 @@ +/* + * Copyright 2018 the original author or authors. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by + * applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package com.github.drinkjava2.frog.brain; + +import java.io.Serializable; + +import com.github.drinkjava2.frog.Env; + +/** + * Zone represents a rectangle zone in brain + * + * @author Yong Zhu + * @since 1.0 + */ +public class Zone implements Serializable { + private static final long serialVersionUID = 1L; + + public float x; + public float y; + public float r;// r为这个矩形区边长的一半 + + public Zone() { + // 空构造器不能省 + } + + public Zone(float x, float y, float r) {// 用x,y,r来构造 + this.x = x; + this.y = y; + this.r = r; + if (this.x < 0) + this.x = 0; + if (this.y < 0) + this.y = 0; + if (this.x > Env.FROG_BRAIN_WIDTH) + this.x = Env.FROG_BRAIN_WIDTH; + if (this.y > Env.FROG_BRAIN_WIDTH) + this.y = Env.FROG_BRAIN_WIDTH; + } + + public Zone(Zone z) {// 用另一个Zone来构造 + this.x = z.x; + this.y = z.y; + this.r = z.r; + } + + public boolean nearby(Zone z) { + float dist = r + z.r; + return (Math.abs(x - z.x) < dist && Math.abs(y - z.y) < dist); + } + + public int roundX() { + return Math.round(x); + } + + public int roundY() { + return Math.round(y); + } + + public static void copyXY(Zone from, Zone to) { + to.x = from.x; + to.y = from.y; + } + + public static void copyXYR(Zone from, Zone to) { + to.x = from.x; + to.y = from.y; + to.r = from.r; + } + + public void setXYR(float x, float y, float r) { + this.x = x; + this.y = y; + this.r = r; + } + +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/Active.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/Active.java new file mode 100644 index 0000000..e0d8838 --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/Active.java @@ -0,0 +1,48 @@ +/* + * Copyright 2018 the original author or authors. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by + * applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package com.github.drinkjava2.frog.brain.organ; + +import com.github.drinkjava2.frog.Frog; +import com.github.drinkjava2.frog.brain.Cell; +import com.github.drinkjava2.frog.brain.Input; +import com.github.drinkjava2.frog.brain.Organ; +import com.github.drinkjava2.frog.util.RandomUtils; + +/** + * Active always keep active + * + * 这个器官永远激活 + */ +public class Active extends Organ {// 以前的实验发现添加一个始终激活的区比用Hungry来驱动更能提高找食效率 + + private static final long serialVersionUID = 1L; + + @Override + public void initFrog(Frog f) { + if (!initilized) { + initilized = true; + organOutputEnergy = 2f; + } + } + + @Override + public void active(Frog f) { + for (Cell cell : f.cells) { + if (cell.energy > 0) + cell.energy--; + if (cell.energy < Cell.MAX_ENERGY_LIMIT) + for (Input input : cell.inputs) + if (input.nearby(this)) // if input zone near by happy zone + cell.energy += organOutputEnergy; + } + } + +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/Eat.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/Eat.java new file mode 100644 index 0000000..0c160f5 --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/Eat.java @@ -0,0 +1,31 @@ +/* + * Copyright 2018 the original author or authors. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by + * applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package com.github.drinkjava2.frog.brain.organ; + +import com.github.drinkjava2.frog.Env; +import com.github.drinkjava2.frog.Frog; +import com.github.drinkjava2.frog.brain.Organ; + +/** + * Eat food at current x, y position + */ +public class Eat extends Organ {// Eat这个类将食物转化为能量,能量小于0,则青蛙死掉 + private static final long serialVersionUID = 1L; + + @Override + public void active(Frog f) { + if (Env.foundAndAteFood(f.x, f.y)) { + f.ateFood++; + f.energy += 1000;// 如果青蛙的坐标与食物重合,吃掉food,能量境加 + } + } + +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java new file mode 100644 index 0000000..29d9686 --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java @@ -0,0 +1,138 @@ +/* + * Copyright 2018 the original author or authors. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by + * applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package com.github.drinkjava2.frog.brain.organ; + +import com.github.drinkjava2.frog.Application; +import com.github.drinkjava2.frog.Env; +import com.github.drinkjava2.frog.Frog; +import com.github.drinkjava2.frog.brain.BrainPicture; +import com.github.drinkjava2.frog.brain.Cell; +import com.github.drinkjava2.frog.brain.Input; +import com.github.drinkjava2.frog.brain.Organ; +import com.github.drinkjava2.frog.brain.Zone; +import com.github.drinkjava2.frog.util.RandomUtils; + +/** + * Eye can only see 4 direction + * + * @author Yong Zhu + * @since 1.0 + */ +public class Eye extends Organ {// 这个Eye是老版的眼睛,只能看到四个方向,但它的调节距离会自动随机调整到一个最佳值,这就是随机试错算法的一个应用 + private static final long serialVersionUID = 1L; + public int seeDistance; // 眼睛能看到的距离 + + @Override + public void initFrog(Frog f) { // 仅在Frog生成时这个方法会调用一次 + if (!initilized) { + initilized = true; + organOutputEnergy = 30; + seeDistance = 8; + } + } + + @Override + public void drawOnBrainPicture(Frog f, BrainPicture pic) {// 把自已这个器官在脑图上显示出来 + if (!Application.SHOW_FIRST_FROG_BRAIN) + return; + super.drawOnBrainPicture(f, pic); + float qRadius = r / 4; + float q3Radius = (float) (r * .75); + Zone seeUp = new Zone(x, y + q3Radius, qRadius); + Zone seeDown = new Zone(x, y - q3Radius, qRadius); + Zone seeLeft = new Zone(x - q3Radius, y, qRadius); + Zone seeRight = new Zone(x + q3Radius, y, qRadius); + pic.drawZone(seeUp); + pic.drawZone(seeDown); + pic.drawZone(seeLeft); + pic.drawZone(seeRight); + } + + @Override + public Organ[] vary() { + if (RandomUtils.percent(5)) { // 可视距离有5%的机率变异 + seeDistance = seeDistance + 1 - 2 * RandomUtils.nextInt(2); + if (seeDistance < 1) + seeDistance = 1; + if (seeDistance > 50) + seeDistance = 50; + } + return new Organ[] { this }; + } + + @Override + public void active(Frog f) { + // 第一个眼睛只能观察上、下、左、右四个方向有没有食物 + float qRadius = r / 4; + float q3Radius = (float) (r * .75); + Zone seeUp = new Zone(x, y + q3Radius, qRadius); + Zone seeDown = new Zone(x, y - q3Radius, qRadius); + Zone seeLeft = new Zone(x - q3Radius, y, qRadius); + Zone seeRight = new Zone(x + q3Radius, y, qRadius); + + boolean seeSomething = false; + boolean atUp = false; + boolean atDown = false; + boolean atLeft = false; + boolean atRight = false; + + for (int i = 1; i < seeDistance; i++) + if (Env.foundAnyThing(f.x, f.y + i)) { + seeSomething = true; + atUp = true; + break; + } + + for (int i = 1; i < seeDistance; i++) + if (Env.foundAnyThing(f.x, f.y - i)) { + seeSomething = true; + atDown = true; + break; + } + + for (int i = 1; i < seeDistance; i++) + if (Env.foundAnyThing(f.x - i, f.y)) { + seeSomething = true; + atLeft = true; + break; + } + + for (int i = 1; i < seeDistance; i++) + if (Env.foundAnyThing(f.x + i, f.y)) { + seeSomething = true; + atRight = true; + break; + } + + if (seeSomething) + for (Cell cell : f.cells) { + if (cell.energy < 100) + for (Input input : cell.inputs) { + if (input.nearby(this)) { + if (atUp && input.nearby(seeUp)) { + input.cell.energy += organOutputEnergy; + } + if (atDown && input.nearby(seeDown)) { + input.cell.energy += organOutputEnergy; + } + if (atLeft && input.nearby(seeLeft)) { + input.cell.energy += organOutputEnergy; + } + if (atRight && input.nearby(seeRight)) { + input.cell.energy += organOutputEnergy; + } + } + } + } + + } + +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/Eyes.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/Eyes.java new file mode 100644 index 0000000..e65a5a8 --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/Eyes.java @@ -0,0 +1,100 @@ +/* + * Copyright 2018 the original author or authors. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by + * applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package com.github.drinkjava2.frog.brain.organ; + +import com.github.drinkjava2.frog.Env; +import com.github.drinkjava2.frog.Frog; +import com.github.drinkjava2.frog.brain.Organ; +import com.github.drinkjava2.frog.util.RandomUtils; + +/** + * Eye can only see 4 direction + * + * @author Yong Zhu + * @since 1.0 + */ +public class Eyes { + + public static class SeeUp extends Organ {// 只能看到上方食物 + private static final long serialVersionUID = 1L; + public int seeDistance; // 眼睛能看到的距离 + + @Override + public void initFrog(Frog f) { // 仅在Frog生成时这个方法会调用一次 + if (!initilized) { + initilized = true; + seeDistance = 8; + } + } + + @Override + public Organ[] vary() { + seeDistance=RandomUtils.varyInLimit(seeDistance, 5, 20); + if (RandomUtils.percent(5)) { // 可视距离有5%的机率变异 + seeDistance = seeDistance + 1 - 2 * RandomUtils.nextInt(2); + if (seeDistance < 1) + seeDistance = 1; + if (seeDistance > 50) + seeDistance = 50; + } + return new Organ[] { this }; + } + + @Override + public void active(Frog f) { + for (int i = 1; i < seeDistance; i++) + if (Env.foundAnyThing(f.x, f.y + i)) { + activeInput(f, 30); + return; + } + } + } + + public static class SeeDown extends SeeUp {// 只能看到下方食物 + private static final long serialVersionUID = 1L; + + @Override + public void active(Frog f) { + for (int i = 1; i < seeDistance; i++) + if (Env.foundAnyThing(f.x, f.y - i)) { + activeInput(f, 30); + return; + } + } + } + + public static class SeeLeft extends SeeUp {// 只能看到左方食物 + private static final long serialVersionUID = 1L; + + @Override + public void active(Frog f) { + for (int i = 1; i < seeDistance; i++) + if (Env.foundAnyThing(f.x - i, f.y)) { + activeInput(f, 30); + return; + } + } + } + + public static class SeeRight extends SeeUp {// 只能看到右方食物 + private static final long serialVersionUID = 1L; + + @Override + public void active(Frog f) { + for (int i = 1; i < seeDistance; i++) + if (Env.foundAnyThing(f.x + i, f.y)) { + activeInput(f, 30); + return; + } + } + } + +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/Line.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/Line.java new file mode 100644 index 0000000..e855a25 --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/Line.java @@ -0,0 +1,99 @@ +/* + * Copyright 2018 the original author or authors. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by + * applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package com.github.drinkjava2.frog.brain.organ; + +import java.awt.Color; + +import com.github.drinkjava2.frog.Env; +import com.github.drinkjava2.frog.Frog; +import com.github.drinkjava2.frog.brain.BrainPicture; +import com.github.drinkjava2.frog.brain.Cell; +import com.github.drinkjava2.frog.brain.Input; +import com.github.drinkjava2.frog.brain.Organ; +import com.github.drinkjava2.frog.brain.Output; +import com.github.drinkjava2.frog.brain.Zone; +import com.github.drinkjava2.frog.util.RandomUtils; + +/** + * Line + * + * 这是一个随机方式连接两端的Organ,它是从旧版的RandomConnectGroup改造过来,这是一种最简单的神经元排列方式, + * + * @author Yong Zhu + * @since 1.0 + */ +public class Line extends Organ { + private static final long serialVersionUID = 1L; + + public Zone inputZone; // 输入触突区 + public Zone outputZone; // 输出触突区 + + @Override + public boolean allowBorrow() { // 是否允许在精子中将这个器官借出 + return true; + } + + @Override + public void initFrog(Frog f) { + if (!initilized) { + initilized = true; + // organWasteEnergy=.05f; + x = Env.FROG_BRAIN_WIDTH / 2; + y = Env.FROG_BRAIN_WIDTH / 2; + r = Env.FROG_BRAIN_WIDTH / 2; + inputZone = RandomUtils.randomPosInAnyFrogOrgan(f); + outputZone = RandomUtils.randomPosInAnyFrogOrgan(f); + } + + this.fat = 0;// 每次fat清0,因为遗传下来的fat不为0 + + Cell c = new Cell(); + Input in = new Input(inputZone); + in.cell = c; + c.inputs = new Input[] { in }; + + Output out = new Output(outputZone); + out.cell = c; + c.outputs = new Output[] { out }; + + c.organ = this; + f.cells.add(c); + } + + @Override + public Organ[] vary() { + organOutputEnergy = RandomUtils.varyInLimit(organOutputEnergy, -3, 3); + if (fat <= 0)// 如果胖值为0,表示这个组的细胞没有用到,可以小概率丢掉它了 + if (RandomUtils.percent(30)) + return new Organ[] {}; + if (RandomUtils.percent(3)) // 有3%的几率丢掉它,防止这个器官数量只增不减 + return new Organ[] {}; + return new Organ[] { this }; + } + + @Override + public void drawOnBrainPicture(Frog f, BrainPicture pic) {// 把自已这个器官在脑图上显示出来 + if (fat <= 0) + pic.setColor(Color.LIGHT_GRAY); // 没用到? 灰色 + else if (organOutputEnergy <= 0) + pic.setColor(Color.BLUE); + else + pic.setColor(Color.red); // 用到了?红色 + pic.drawLine(inputZone, outputZone); + pic.drawZone(this); + pic.drawZone(inputZone); + pic.fillZone(outputZone); + pic.setColor(Color.red); + + pic.drawCircle(outputZone); // 如果胖了,表示激活过了,下次下蛋少不了这一组 + } + +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveDown.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveDown.java new file mode 100644 index 0000000..62381d9 --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveDown.java @@ -0,0 +1,28 @@ +/* + * Copyright 2018 the original author or authors. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by + * applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package com.github.drinkjava2.frog.brain.organ; + +import com.github.drinkjava2.frog.Frog; +import com.github.drinkjava2.frog.brain.Organ; + +/** + * Move down frog 1 unit if outputs of nerve cells active in this zone + */ +public class MoveDown extends Organ { + private static final long serialVersionUID = 1L; + + @Override + public void active(Frog f) { + if (outputActive(f)) + f.y++; + } + +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveLeft.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveLeft.java new file mode 100644 index 0000000..04e5f2e --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveLeft.java @@ -0,0 +1,27 @@ +/* + * Copyright 2018 the original author or authors. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by + * applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package com.github.drinkjava2.frog.brain.organ; + +import com.github.drinkjava2.frog.Frog; +import com.github.drinkjava2.frog.brain.Organ; + +/** + * Move left frog 1 unit if outputs of nerve cells active in this zone + */ +public class MoveLeft extends Organ { + private static final long serialVersionUID = 1L; + + @Override + public void active(Frog f) { + if (outputActive(f)) + f.x--; + } +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveRight.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveRight.java new file mode 100644 index 0000000..21c50c8 --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveRight.java @@ -0,0 +1,29 @@ +/* + * Copyright 2018 the original author or authors. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by + * applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package com.github.drinkjava2.frog.brain.organ; + +import com.github.drinkjava2.frog.Frog; +import com.github.drinkjava2.frog.brain.Organ; + +/** + * Move right frog 1 unit if outputs of nerve cells active in this zone + */ +public class MoveRight extends Organ { + private static final long serialVersionUID = 1L; + + @Override + public void active(Frog f) { + if (outputActive(f)) + f.x++; + } + + +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveUp.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveUp.java new file mode 100644 index 0000000..d02cd91 --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveUp.java @@ -0,0 +1,28 @@ +/* + * Copyright 2018 the original author or authors. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by + * applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package com.github.drinkjava2.frog.brain.organ; + +import com.github.drinkjava2.frog.Frog; +import com.github.drinkjava2.frog.brain.Organ; + +/** + * Move up frog 1 unit if outputs of nerve cells active in this zone + */ +public class MoveUp extends Organ { + private static final long serialVersionUID = 1L; + + @Override + public void active(Frog f) { + if (outputActive(f)) + f.y--; + } + +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/egg/Egg.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/egg/Egg.java new file mode 100644 index 0000000..0778948 --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/egg/Egg.java @@ -0,0 +1,94 @@ +/* + * Copyright 2018 the original author or authors. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by + * applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package com.github.drinkjava2.frog.egg; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import com.github.drinkjava2.frog.Frog; +import com.github.drinkjava2.frog.brain.Organ; +import com.github.drinkjava2.frog.brain.organ.Active; +import com.github.drinkjava2.frog.brain.organ.Eat; +import com.github.drinkjava2.frog.brain.organ.Eyes.SeeDown; +import com.github.drinkjava2.frog.brain.organ.Eyes.SeeLeft; +import com.github.drinkjava2.frog.brain.organ.Eyes.SeeRight; +import com.github.drinkjava2.frog.brain.organ.Eyes.SeeUp; +import com.github.drinkjava2.frog.brain.organ.MoveDown; +import com.github.drinkjava2.frog.brain.organ.MoveLeft; +import com.github.drinkjava2.frog.brain.organ.MoveRight; +import com.github.drinkjava2.frog.brain.organ.MoveUp; +import com.github.drinkjava2.frog.util.RandomUtils; + +/** + * Egg is the static structure description of frog, can save as text file, to + * build a frog, first need build a egg.
+ * + * 蛋存在的目的是为了以最小的字节数串行化存储Frog,它是Frog的生成算法描述,而不是Frog本身,这样一来Frog就不能"永生"了,因为每一个egg都不等同于 + * 它的母体, 而且每一次测试,大部分条件反射的建立都必须从头开始训练,类似于人类,无论人类社会有多聪明, 婴儿始终是一张白纸,需要花大量的时间从头学习。 + * + * @author Yong Zhu + * @since 1.0 + */ +public class Egg implements Serializable { + // 为了缩短时间,这个程序随机生成的联结将只落在固定的器官上而不是漫天撒网(见4.12提交),这是程序的优化,实现的逻辑和随机漫天撒网定是相同的。 + // 但是这个优化带来的问题是这是一个硬编码逻辑,不利于器官的优胜劣汰, 而且下面这个 FIXED_ORGAN_QTY必须每次手工设定,以后需要重构这块的代码 + public static int FIXED_ORGAN_QTY = 9; + + private static final long serialVersionUID = 1L; + + public List organs = new ArrayList<>(); + + public Egg() {// 无中生有,创建一个蛋,先有蛋,后有蛙 + organs.add(new MoveUp().setXYRN(800, 100, 60, "Up")); + organs.add(new MoveDown().setXYRN(800, 400, 60, "Down")); + organs.add(new MoveLeft().setXYRN(700, 250, 60, "Left")); + organs.add(new MoveRight().setXYRN(900, 250, 60, "Right")); + organs.add(new SeeUp().setXYRN(200, 300 + 90, 40, "SeeUp")); + organs.add(new SeeDown().setXYRN(200, 300 - 90, 40, "SeeDown")); + organs.add(new SeeLeft().setXYRN(200 - 90, 300, 40, "SeeLeft")); + organs.add(new SeeRight().setXYRN(200 + 90, 300, 40, "SeeRight")); +// organs.add(new Eye().setXYRN(100, 300, 100, "Eye")); + organs.add(new Active().setXYRN(500, 100, 60, "Active")); // 永远激活 + // 以上数量就是FIXED_ORGAN_QTY值 + + organs.add(new Eat().setXYRN(0, 0, 0, "Eat")); // EAT不是感觉或输出器官,没有位置和大小 + + } + + /** Create egg from frog */ + public Egg(Frog frog) { // 青蛙下蛋,每个青蛙的器官会创建自已的副本或变异,可以是0或多个 + for (Organ organ : frog.organs) + for (Organ newOrgan : organ.vary()) + organs.add(newOrgan); + } + + /** + * Create a egg by join 2 eggs, x+y=zygote 模拟X、Y 染色体合并,两个蛋生成一个新的蛋, X从Y里借一个器官, + * 不用担心器官会越来越多,因为通过用进废退原则来筛选,没用到的器官会在几代之后被自然淘汰掉 + * 器官不是越多越好,因为器官需要消耗能量,器官数量多了,在生存竞争中也是劣势 + * + */ + public Egg(Egg x, Egg y) { + // x里原来的organ + for (Organ organ : x.organs) + organs.add(organ); + + // 从y里借一个organ + int yOrganSize = y.organs.size(); + if (yOrganSize > 0) { + Organ o = y.organs.get(RandomUtils.nextInt(yOrganSize)); + if (o.allowBorrow()) + organs.add(o); + } + } + +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/egg/EggTool.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/egg/EggTool.java new file mode 100644 index 0000000..bbb97c2 --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/egg/EggTool.java @@ -0,0 +1,107 @@ +/* + * Copyright 2018 the original author or authors. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by + * applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package com.github.drinkjava2.frog.egg; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import com.github.drinkjava2.frog.Application; +import com.github.drinkjava2.frog.Env; +import com.github.drinkjava2.frog.Frog; +import com.github.drinkjava2.frog.util.FrogFileUtils; + +/** + * EggTool save eggs to disk + * + * @author Yong Zhu + * @since 1.0 + */ +public class EggTool { + + /** + * Frogs which have higher energy lay eggs + * + * 利用Java串行机制存盘。 能量多(也就是吃的更多)的Frog下蛋并存盘, 以进行下一轮测试,能量少的Frog被淘汰,没有下蛋的资格。 + * 用能量的多少来简化生存竟争模拟,每次下蛋数量固定为EGG_QTY个 + */ + public static void layEggs() { + sortFrogsOrderByEnergyDesc(); + + Frog first = Env.frogs.get(0); + Frog last = Env.frogs.get(Env.frogs.size() - 1); + + try { + Env.eggs.clear(); + for (int i = 0; i < Env.EGG_QTY; i++) + Env.eggs.add(new Egg(Env.frogs.get(i))); + FileOutputStream fo = new FileOutputStream(Application.CLASSPATH + "eggs.ser"); + ObjectOutputStream so = new ObjectOutputStream(fo); + so.writeObject(Env.eggs); + so.close(); + System.out.print("\r1st frog has " + first.organs.size() + " organs, energy=" + first.energy ); + System.out.println(", Last frog has " + last.organs.size() + " organs, energy=" + last.energy); + System.out.println("Saved " + Env.eggs.size() + " eggs to file '" + Application.CLASSPATH + "eggs.ser'"); + } catch (IOException e) { + System.out.println(e); + } + } + + private static void sortFrogsOrderByEnergyDesc() {// 按能量多少给青蛙排序 + Collections.sort(Env.frogs, new Comparator() { + public int compare(Frog a, Frog b) { + if (a.energy > b.energy) + return -1; + else if (a.energy == b.energy) + return 0; + else + return 1; + } + }); + } + + public static void deleteEggs() { + System.out.println("Delete exist egg file: '" + Application.CLASSPATH + "eggs.ser'"); + FrogFileUtils.deleteFile(Application.CLASSPATH + "eggs.ser"); + } + + /** + * 从磁盘读入一批Egg + */ + @SuppressWarnings("unchecked") + public static void loadEggs() { + boolean errorfound = false; + try { + FileInputStream eggsFile = new FileInputStream(Application.CLASSPATH + "eggs.ser"); + ObjectInputStream eggsInputStream = new ObjectInputStream(eggsFile); + Env.eggs = (List) eggsInputStream.readObject(); + System.out.println( + "Loaded " + Env.eggs.size() + " eggs from file '" + Application.CLASSPATH + "eggs.ser" + "'.\n"); + eggsInputStream.close(); + } catch (Exception e) { + errorfound = true; + } + if (errorfound) { + Env.eggs.clear(); + for (int j = 0; j < Env.EGG_QTY; j++) + Env.eggs.add(new Egg()); + System.out.println("Fail to load egg file at path '" + Application.CLASSPATH + "', created " + + Env.eggs.size() + " eggs to do test.\n"); + } + + } + +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/objects/Food.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/objects/Food.java new file mode 100644 index 0000000..ea03051 --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/objects/Food.java @@ -0,0 +1,48 @@ +/* Copyright 2018-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by + * applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package com.github.drinkjava2.frog.objects; + +import static com.github.drinkjava2.frog.Env.ENV_HEIGHT; +import static com.github.drinkjava2.frog.Env.ENV_WIDTH; +import static com.github.drinkjava2.frog.Env.FOOD_QTY; +import static com.github.drinkjava2.frog.Env.bricks; + +import com.github.drinkjava2.frog.util.RandomUtils; + +/** + * Food randomly scatter on Env + * + * @author Yong Zhu + * @since 1.0 + */ +public class Food implements Object { + + @Override + public void build() { + for (int i = 0; i < FOOD_QTY; i++) // 生成食物 + bricks[RandomUtils.nextInt(ENV_WIDTH)][RandomUtils.nextInt(ENV_HEIGHT)] = Material.FOOD; + } + + @Override + public void destory() { + for (int i = 0; i < ENV_WIDTH; i++) {// 清除食物 + for (int j = 0; j < ENV_HEIGHT; j++) + if (bricks[i][j] == Material.FOOD) + bricks[i][j] = 0; + } + } + + @Override + public void active(int screen) { + // Food do not have any active + } + +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/objects/Material.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/objects/Material.java new file mode 100644 index 0000000..ca66cc7 --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/objects/Material.java @@ -0,0 +1,40 @@ +/* Copyright 2018-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by + * applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package com.github.drinkjava2.frog.objects; + +import java.awt.Color; + +/** + * Object means some thing in Env + * + * @author Yong Zhu + * @since 1.0 + */ +public class Material { + public static final byte VISIBLE = 10; // if>=10 will visible to frog + public static final byte KILLFROG = 20; // if>=20 will kill frog + + public static final byte NO = 0; + public static final byte SEESAW_BASE = 1; // 1~9 is invisible to frog + + public static final byte FOOD = VISIBLE + 1; + public static final byte SEESAW = VISIBLE + 2; // if <0 will not cause frog die + + public static final byte BRICK = KILLFROG + 1; + public static final byte TRAP = KILLFROG + 2; + + public static Color color(byte material) { + if (material == TRAP) + return Color.LIGHT_GRAY; + else + return Color.BLACK; + } +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/objects/Object.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/objects/Object.java new file mode 100644 index 0000000..daa3160 --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/objects/Object.java @@ -0,0 +1,26 @@ +/* Copyright 2018-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by + * applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package com.github.drinkjava2.frog.objects; + +/** + * Object means some thing in Env + * + * @author Yong Zhu + * @since 1.0 + */ +public interface Object { + + public void build(); + + public void destory(); + + public void active(int screen); +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/util/FrogFileUtils.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/util/FrogFileUtils.java new file mode 100644 index 0000000..16f1999 --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/util/FrogFileUtils.java @@ -0,0 +1,141 @@ +/* Copyright 2018-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by + * applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package com.github.drinkjava2.frog.util; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * File Utilities used in this project + * + * @author Yong Zhu + * @since 1.0 + */ +public class FrogFileUtils { + + private FrogFileUtils() { + // default constructor + } + + public static boolean deleteFile(String fileFullPath) { + File file = new File(fileFullPath); + return file.delete(); // NOSONAR + } + + public static void writeFile(String fileFullPath, byte[] byteArry) { + File file = new File(fileFullPath); + if (!file.getParentFile().exists()) + file.getParentFile().mkdirs(); + FileOutputStream fos = null; + try { + fos = new FileOutputStream(file); + fos.write(byteArry); + fos.close(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (fos != null) { + try { + try { + fos.flush(); + } catch (Exception e) { + } + fos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + public static void writeFile(String fileFullPath, String text, String encoding) { + File file = new File(fileFullPath); + if (!file.getParentFile().exists()) + file.getParentFile().mkdirs(); + FileOutputStream fos = null; + try { + fos = new FileOutputStream(file); + byte[] bytes; + bytes = text.getBytes(encoding); + fos.write(bytes); + fos.close(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (fos != null) { + try { + try { + fos.flush(); + } catch (Exception e) { + } + fos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + public static String readFile(String fileFullPath, String encoding) { + InputStream inputStream; + try { + inputStream = new FileInputStream(new File(fileFullPath)); + } catch (FileNotFoundException e1) { + return null; + } + try { + ByteArrayOutputStream result = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int length; + while ((length = inputStream.read(buffer)) != -1) + result.write(buffer, 0, length); + String string = result.toString(encoding); + return string; + } catch (IOException e) { + e.printStackTrace(); + return null; + } finally { + try { + inputStream.close(); + } catch (IOException e) { + } + } + } + + public static void appendFile(String fileName, String content) { + FileOutputStream fos = null; + try { + fos = new FileOutputStream(fileName, true); + fos.write(content.getBytes()); + fos.write("\r\n".getBytes()); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (fos != null) { + try { + try { + fos.flush(); + } catch (Exception e) { + } + fos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + +} diff --git a/history/003b_simple/src/main/java/com/github/drinkjava2/frog/util/RandomUtils.java b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/util/RandomUtils.java new file mode 100644 index 0000000..b01f69b --- /dev/null +++ b/history/003b_simple/src/main/java/com/github/drinkjava2/frog/util/RandomUtils.java @@ -0,0 +1,108 @@ +/* Copyright 2018-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by + * applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package com.github.drinkjava2.frog.util; + +import java.util.Random; + +import com.github.drinkjava2.frog.Frog; +import com.github.drinkjava2.frog.brain.Zone; +import com.github.drinkjava2.frog.egg.Egg; + +/** + * Random Utilities used in this project + * + * @author Yong Zhu + * @since 1.0 + */ +public class RandomUtils { + private static final Random rand = new Random(); + + public static int nextInt(int i) { + return rand.nextInt(i); + } + + public static float nextFloat() { + return rand.nextFloat(); + } + + /** Return a random zone inside of a zone */ + public static Zone randomZoneInZone(Zone z) { // 在一个区内随机取一个小小区 + return new Zone(z.x - z.r + z.r * 2 * rand.nextFloat(), z.y - z.r + z.r * 2 * rand.nextFloat(), + z.r * rand.nextFloat() * .04f); + } + + /** Return a random zone inside of frog's random organ */ + public static Zone randomPosInAnyFrogOrgan(Frog f) { + if (f.organs == null || f.organs.size() == 0) + throw new IllegalArgumentException("Can not call randomPosInRandomOrgan method when frog has no organ"); + return randomZoneInZone(f.organs.get(RandomUtils.nextInt(Egg.FIXED_ORGAN_QTY))); + } + + /** Return a random zone inside of frog's random organ */ + public static Zone randomPosMostInNewEye(Frog f) { + if (f.organs == null || f.organs.size() == 0) + throw new IllegalArgumentException("Can not call randomPosInRandomOrgan method when frog has no organ"); + if (RandomUtils.percent(95)) + return randomZoneInZone(f.organs.get(7));// 这是一个硬编码,大部分新联接建立在newEye中 + return randomZoneInZone(f.organs.get(RandomUtils.nextInt(Egg.FIXED_ORGAN_QTY))); + } + + public static boolean percent(float percent) { + return rand.nextFloat() * 100 < percent; + } + + public static int vary(int v) {// 随机有大概率小变异,小概率大变异,极小概率极大变异 + if (percent(40)) + v += v * .04 * (nextFloat() - 0.5); // v=v+-.04 + if (percent(10)) + v += v * .103 * (nextFloat() - 0.5); // v=v+-0.1 + else if (percent(5)) + v += v * 1 * (nextFloat() - 0.5); // v=v+-0.4 + else if (percent(2)) + v += v * 4 * (nextFloat() - 0.5); // v=v+-2 + else if (percent(1f)) + v += v * 8 * (nextFloat() - 0.5); // v=v+-6 + return v; + } + + public static float vary(float v) {// 随机有大概率小变异,小概率大变异,极小概率极大变异 + if (percent(40)) + v += v * .04 * (nextFloat() - 0.5); // v=v+-.04 + if (percent(10)) + v += v * .103 * (nextFloat() - 0.5); // v=v+-0.1 + else if (percent(5)) + v += v * 1 * (nextFloat() - 0.5); // v=v+-0.4 + else if (percent(2)) + v += v * 4 * (nextFloat() - 0.5); // v=v+-2 + else if (percent(1f)) + v += v * 8 * (nextFloat() - 0.5); // v=v+-6 + return v; + } + + public static int varyInLimit(int v, int from, int to) {// 让返回值在from和to之间随机变异 + int i = vary(v); + if (i < from) + i = from; + if (i > to) + i = to; + return i; + } + + public static float varyInLimit(float v, float from, float to) {// 让返回值在from和to之间随机变异 + float i = vary(v); + if (i < from) + i = from; + if (i > to) + i = to; + return i; + } + +} diff --git a/history/004_seasaw/README.md b/history/004_seasaw/README.md new file mode 100644 index 0000000..8891e01 --- /dev/null +++ b/history/004_seasaw/README.md @@ -0,0 +1,3 @@ +## history\004分支简介 +2019-08-05 有了分组测试功能后,顺手加上了一个青蛙走跷跷板自动平衡的演示,它每次只出场一个青蛙, 每轮包括100场测试,大约跑90多轮半个小时(电脑慢)后,出现了青蛙可以自动走跷跷板保持平衡的画面。 +这个版本的目的是为了增加一点趣味性,显得青蛙还是有点"用处"的,省得让人以为这个项目不务正业,青蛙只会找食。这个版本青蛙的脑结构和找食版的青蛙基本相同,区别只是在于环境不同,也就是说它的表现随着环境而变化,这符合"通用人工智能"的概念,即信号感受器官是统一的(通常是眼睛),但能根据不同的环境完成不同的任务。 \ No newline at end of file diff --git a/history/005_letter_test/README.md b/history/005_letter_test/README.md new file mode 100644 index 0000000..559c7f0 --- /dev/null +++ b/history/005_letter_test/README.md @@ -0,0 +1,5 @@ +## history\005分支简介 +这是采用体全息存贮概念进行模式识别的原理演示,只是原理演示,并不是最终的脑结构,因为我后来发现光子实际上是可以不需要模拟出来的。 +这个体全息存贮模式识别的原理比较简单,不需要任何高等数学知识,每个人都能看懂,简单说就相当于两或多个信号互为体全息存贮方案中的参考(检索)信号,在参考信号激活下,细胞会反向发出光子,从而在信号源处逆向成像。而且这个信息存贮模式可能更符合人脑的工作原理,它可以进行图像到声音的关联,也可以实现声音到图像成像的逆关联,另外还有两个重要优点: +1.它可以同时处理多维的、多个方向同时传来的信号,也就是说可以同时处理多个图片、声音等信号。 +2.它的训练速度非常快,没有采用什么海量的大数据来进行训练,只要任意有关联的信号,哪怕信号只出现一两次,它都会自动将它们关联起来,这个关联是动物的条件反射能够建立的基础。 \ No newline at end of file