|
|
|
@ -13,12 +13,10 @@ package com.github.drinkjava2.frog.egg;
|
|
|
|
|
import java.io.Serializable;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Random;
|
|
|
|
|
|
|
|
|
|
import com.github.drinkjava2.frog.Env;
|
|
|
|
|
import com.github.drinkjava2.frog.Frog;
|
|
|
|
|
import com.github.drinkjava2.frog.brain.Organ;
|
|
|
|
|
import com.github.drinkjava2.frog.brain.Zone;
|
|
|
|
|
import com.github.drinkjava2.frog.brain.group.Group;
|
|
|
|
|
import com.github.drinkjava2.frog.brain.group.RandomConnectGroup;
|
|
|
|
|
import com.github.drinkjava2.frog.brain.organ.Eat;
|
|
|
|
|
import com.github.drinkjava2.frog.brain.organ.Eye;
|
|
|
|
@ -27,6 +25,7 @@ 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
|
|
|
|
@ -40,117 +39,57 @@ import com.github.drinkjava2.frog.brain.organ.MoveUp;
|
|
|
|
|
*/
|
|
|
|
|
public class Egg implements Serializable {
|
|
|
|
|
private static final long serialVersionUID = 1L;
|
|
|
|
|
public int randomCellGroupQty = 30; // 随机生成多少个组
|
|
|
|
|
public int randomCellQtyPerGroup = 3; // 每个组有多少个脑细胞
|
|
|
|
|
public int randomInputQtyPerCell = 3;// 每个脑细胞有多少个输入触突
|
|
|
|
|
public int randomOutQtyPerCell = 2; // 每个脑细胞有多少个输出触突
|
|
|
|
|
|
|
|
|
|
public RandomConnectGroup[] cellGroups;
|
|
|
|
|
public List<Organ> organs = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
public List<Organ> organs = new ArrayList<Organ>();
|
|
|
|
|
public List<Group> groups = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
public Egg() {
|
|
|
|
|
// default constructor
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static Random r = new Random();
|
|
|
|
|
|
|
|
|
|
/** Create a egg by join 2 eggs, x+y=zygote */
|
|
|
|
|
public Egg(Egg x, Egg y) {
|
|
|
|
|
// 模拟XY染色体,不能做简单加法,会撑暴内存的,现在每次只随机加一个y的cellgroup进来,这也不太好,因为基因会越加越多,只好用用进废退原则来加大淘汰率。
|
|
|
|
|
|
|
|
|
|
// x里原来的CellGroup
|
|
|
|
|
cellGroups = new RandomConnectGroup[x.cellGroups.length + 1 + randomCellGroupQty];
|
|
|
|
|
for (int i = 0; i < x.cellGroups.length; i++) {
|
|
|
|
|
RandomConnectGroup oldCellGroup = x.cellGroups[i];
|
|
|
|
|
RandomConnectGroup cellGroup = new RandomConnectGroup();
|
|
|
|
|
cellGroups[i] = cellGroup;
|
|
|
|
|
cellGroup.inherit = true;
|
|
|
|
|
cellGroup.groupInputZone = new Zone(oldCellGroup.groupInputZone);
|
|
|
|
|
cellGroup.groupOutputZone = new Zone(oldCellGroup.groupOutputZone);
|
|
|
|
|
cellGroup.cellQty = oldCellGroup.cellQty;
|
|
|
|
|
cellGroup.cellInputRadius = oldCellGroup.cellInputRadius;
|
|
|
|
|
cellGroup.cellOutputRadius = oldCellGroup.cellOutputRadius;
|
|
|
|
|
cellGroup.inputQtyPerCell = oldCellGroup.inputQtyPerCell;
|
|
|
|
|
cellGroup.outputQtyPerCell = oldCellGroup.outputQtyPerCell;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 从y里借一个CellGroup
|
|
|
|
|
RandomConnectGroup randomY = y.cellGroups[r.nextInt(y.cellGroups.length)];
|
|
|
|
|
RandomConnectGroup cellGroup = new RandomConnectGroup(randomY);
|
|
|
|
|
cellGroups[x.cellGroups.length] = cellGroup;
|
|
|
|
|
|
|
|
|
|
// 随机生成一批CellGroup
|
|
|
|
|
for (int i = 0; i < randomCellGroupQty; i++)
|
|
|
|
|
cellGroups[i + x.cellGroups.length + 1] = new RandomConnectGroup(Env.FROG_BRAIN_WIDTH, x.randomCellQtyPerGroup,
|
|
|
|
|
x.randomInputQtyPerCell, x.randomOutQtyPerCell);
|
|
|
|
|
|
|
|
|
|
addInitialOrgans();
|
|
|
|
|
public Egg() {// 无中生有,创建一个蛋,先有蛋,后有鸡
|
|
|
|
|
organs.add(new Hungry().setXYRN(300, 100, 100, "Hungry"));
|
|
|
|
|
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 Eat().setXYRN(0, 0, 0, "Eat"));
|
|
|
|
|
organs.add(new Eye().setXYRN(100, 400, 100, "Eye"));
|
|
|
|
|
for (int i = 0; i <10; i++) {
|
|
|
|
|
organs.add( new RandomConnectGroup().setXYRN(500, 500, 500, null));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** create a brand new Egg */
|
|
|
|
|
public static Egg createBrandNewEgg() { // 无中生有,创建一个蛋,先有蛋,后有鸡
|
|
|
|
|
Egg egg = new Egg();
|
|
|
|
|
egg.cellGroups = new RandomConnectGroup[egg.randomCellGroupQty];
|
|
|
|
|
for (int i = 0; i < egg.randomCellGroupQty; i++)
|
|
|
|
|
egg.cellGroups[i] = new RandomConnectGroup(Env.FROG_BRAIN_WIDTH, egg.randomCellQtyPerGroup,
|
|
|
|
|
egg.randomInputQtyPerCell, egg.randomOutQtyPerCell);
|
|
|
|
|
egg.addInitialOrgans();
|
|
|
|
|
return egg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static boolean percent(int percent) {
|
|
|
|
|
return r.nextInt(100) < percent;
|
|
|
|
|
/** Create egg from frog */
|
|
|
|
|
public Egg(Frog frog) { // 青蛙下蛋,每个青蛙的器官会创建自已的副本或变异,可以是0或多个
|
|
|
|
|
for (Organ organ : frog.organs)
|
|
|
|
|
for (Organ newOrgan : organ.vary())
|
|
|
|
|
organs.add(newOrgan);
|
|
|
|
|
for (int i = 0; i <10; i++) {
|
|
|
|
|
organs.add( new RandomConnectGroup().setXYRN(500, 500, 500, null));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static float vary(float f) { // 大部分时候不变,有极小机会变异,有极极小机会大变异,有极极极小机会大大大变异
|
|
|
|
|
int i = r.nextInt(100);
|
|
|
|
|
if (i < 95)
|
|
|
|
|
return f;
|
|
|
|
|
float rate = .05f;
|
|
|
|
|
if (i > 97)
|
|
|
|
|
rate = .1f;
|
|
|
|
|
return (float) (f * ((1 - rate) + r.nextFloat() * rate * 2));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Create egg from frog */
|
|
|
|
|
public Egg(Frog frog) { // 青蛙下蛋,蛋的基因生成遵循用进废退、随机变异两个原则
|
|
|
|
|
List<RandomConnectGroup> gpList = new ArrayList<>();
|
|
|
|
|
for (int i = 0; i < frog.cellGroups.length; i++) {
|
|
|
|
|
if (frog.cellGroups[i].fat <= 0) {
|
|
|
|
|
if (!frog.cellGroups[i].inherit)
|
|
|
|
|
continue;// 从未激活过的神经元,并且就是本轮随机生成的,丢弃之
|
|
|
|
|
if (percent(5))
|
|
|
|
|
continue;// 继承下来的神经元,但是本轮并没用到, 扔掉又可惜,可以小概率丢掉
|
|
|
|
|
}
|
|
|
|
|
RandomConnectGroup cellGroup = new RandomConnectGroup();
|
|
|
|
|
RandomConnectGroup oldGp = frog.cellGroups[i];
|
|
|
|
|
cellGroup.groupInputZone = new Zone(vary(oldGp.groupInputZone.x), vary(oldGp.groupInputZone.y),
|
|
|
|
|
vary(oldGp.groupInputZone.radius));
|
|
|
|
|
cellGroup.groupOutputZone = new Zone(vary(oldGp.groupOutputZone.x), vary(oldGp.groupOutputZone.y),
|
|
|
|
|
vary(oldGp.groupOutputZone.radius));
|
|
|
|
|
cellGroup.cellQty = Math.round(vary(oldGp.cellQty));
|
|
|
|
|
cellGroup.cellInputRadius = vary(oldGp.cellInputRadius);
|
|
|
|
|
cellGroup.cellOutputRadius = vary(oldGp.cellOutputRadius);
|
|
|
|
|
cellGroup.inputQtyPerCell = Math.round(vary(oldGp.inputQtyPerCell));
|
|
|
|
|
cellGroup.outputQtyPerCell = Math.round(vary(oldGp.outputQtyPerCell));
|
|
|
|
|
cellGroup.inherit = true;
|
|
|
|
|
gpList.add(cellGroup);
|
|
|
|
|
/**
|
|
|
|
|
* 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)
|
|
|
|
|
for (Organ newOrgan : organ.vary())
|
|
|
|
|
organs.add(newOrgan);
|
|
|
|
|
|
|
|
|
|
// 从y里借一个organ
|
|
|
|
|
int yOrganSize = y.organs.size();
|
|
|
|
|
if (yOrganSize > 0) {
|
|
|
|
|
Organ o = y.organs.get(RandomUtils.nextInt(yOrganSize));
|
|
|
|
|
if (o.allowBorrow())
|
|
|
|
|
organs.add(o);
|
|
|
|
|
}
|
|
|
|
|
cellGroups = gpList.toArray(new RandomConnectGroup[gpList.size()]);
|
|
|
|
|
addInitialOrgans();
|
|
|
|
|
for (int i = 0; i <10; i++) {
|
|
|
|
|
organs.add( new RandomConnectGroup().setXYRN(500, 500, 500, null));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Hard code add initial organs */
|
|
|
|
|
public void addInitialOrgans() { // 这是硬编码添加初始器官, 器官的数量、位置、内部参数会参加遗传、变异
|
|
|
|
|
organs.add(new Hungry().setXYRN(300, 100, 100, "Hungry"));
|
|
|
|
|
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 Eat().setXYRN(0, 0, 0, "Eat"));
|
|
|
|
|
organs.add(new Eye().setXYRN(100, 400, 100, "Eye"));
|
|
|
|
|
//organs.add(new Eye().setXYRN(100, 700, 100, "Eye"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|