Back to many connections

pull/1/head
Yong Zhu 6 years ago
parent 14f9c43659
commit dfec0d7e7d

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -21,27 +21,29 @@ import com.github.drinkjava2.frog.egg.EggTool;
@SuppressWarnings("serial")
public class Env extends JPanel {
/** Speed of test */
public static final int SHOW_SPEED = 1; // 测试速度1~1000,可调, 数值越小,速度越慢
public static final int SHOW_SPEED = 5; // 测试速度1~1000,可调, 数值越小,速度越慢
/** Delete eggs at beginning of each run */
public static final boolean DELETE_EGGS = true;// 每次运行是否先删除保存的蛋
/** Debug mode will print more debug info */
public static final boolean DEBUG_MODE = false; // Debug 模式下会打印出更多的调试信息
/** Environment x width, unit: pixels */
public static final int ENV_WIDTH = 400; // 虚拟环境的宽度, 可调
/** Virtual environment y size pixels */
/** 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 = 300; // Frog的脑图在屏幕上的显示大小,可调
/** Steps of one test round */
public static final int STEPS_PER_ROUND = 1000;// 每轮测试步数,可调
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,不要随便调整,因为器官的相对位置和大小是按脑大小设定的
/** Delete eggs at beginning of each run */
public static final boolean DELETE_EGGS = false;// 每次运行是否先删除保存的蛋
public static final boolean DEBUG_MODE = false; // Debug 模式下会打印出更多的调试信息
static {
if (DELETE_EGGS)
EggTool.deleteEggs();
@ -97,17 +99,17 @@ public class Env extends JPanel {
Random rand = new Random();
for (int i = 0; i < eggs.size(); i++) {// 创建青蛙每个蛋生成4个蛙并随机取一个别的蛋作为精子
int loop = 4;
if (i == 0)
loop = 8;
if (i == eggs.size() - 1)
loop = 0;
if (i <= 3)// 0,1,2,3
loop = 6;
if (i >= (eggs.size() - 4))
loop = 2;
for (int j = 0; j < loop; j++) {
Egg zygote = new Egg(eggs.get(i), eggs.get(r.nextInt(eggs.size())));
frogs.add(new Frog(rand.nextInt(ENV_WIDTH), rand.nextInt(ENV_HEIGHT), zygote));
}
}
System.out.println("Created " + 4 * eggs.size() + " frogs");
System.out.println("Created " + frogs.size() + " frogs");
for (int i = 0; i < Env.FOOD_QTY; i++) // 生成食物
foods[rand.nextInt(ENV_WIDTH)][rand.nextInt(ENV_HEIGHT)] = true;
}

@ -40,7 +40,7 @@ public class Frog {
public int x; // frog在Env中的x坐标
public int y; // frog在Env中的y坐标
public long frogEngery = 10000; // 能量为0则死掉
public long energy = 10000; // 青蛙的能量为0则死掉
public boolean alive = true; // 设为false表示青蛙死掉了将不参与计算和显示以节省时间
static Image frogImg;
@ -62,17 +62,15 @@ public class Frog {
}
public boolean active(Env v) {
frogEngery-=0.01;
if (!alive) {
return false;
}
if (frogEngery < 0) { // 如果能量小于0则死
frogEngery-=10;
energy -= 20;
if (!alive || energy < 0) {// 如果能量小于0则死
energy -= 100; // 死掉的青蛙也要消耗能量,保证淘汰出局
alive = false;
return false;
}
for (Organ o : organs) { // 调用每个Organ的active方法
//energy -= o.organWasteEnergy; // 器官不是越多越好,每增加一个器官,要多消耗一点能量,通过这个方法防止器官无限增多
o.active(this);
}
return alive;

@ -17,7 +17,7 @@ package com.github.drinkjava2.frog.brain;
* @since 1.0
*/
public class Cell {
public static final float MAX_ENERGY_LIMIT = 1000.0f;
public static final float MAX_ENERGY_LIMIT = 100.0f;
// this cell belong to frog's which organ
public Organ organ;

@ -14,7 +14,6 @@ import java.awt.Color;
import java.awt.Graphics;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.util.RandomUtils;
/**
* Organ is a part of frog, organ can be saved in egg
@ -28,8 +27,9 @@ public class Organ extends Zone {
private static final long serialVersionUID = 1L;
public String name; // 显示在脑图上的器官名称,可选
public long fat = 0; // 如果活跃多fat值高则保留及变异的可能性大反之则很可能丢弃掉
public float organActiveEnergy = 1; // 执行器官激活需要消耗细胞多少能量
public float organOutputEnergy = 2; // 感觉 器官激活会给细胞增加多少能量
//public float organWasteEnergy = 0.05f; // 器官在每个测试循环中需要消耗青蛙多少能量,可以通过调节这个参数抑制器官数量无限增长
public float organActiveEnergy = 1; // 输出器官激活需要消耗每个脑细胞多少能量
public float organOutputEnergy = 2; // 感觉器官激活会给每个脑细胞增加多少能量
public boolean initilized; // 通过这个标记判断是否需要手工给定它的参数初值
public boolean allowBorrow() { // 是否允许在精子中将这个器官借出
@ -47,7 +47,7 @@ public class Organ extends Zone {
for (Output output : cell.outputs) { //
if (this.nearby(output)) {
cell.organ.fat++;
cell.energy -= organActiveEnergy;
cell.energy -= 30;//
return true;
}
}
@ -75,11 +75,6 @@ public class Organ extends Zone {
public void initFrog(Frog f) { // 仅在Frog生成时这个方法会调用一次缺省啥也不干通常用于Group子类的初始化
}
public void varyParam() {
organActiveEnergy = RandomUtils.vary(organActiveEnergy);
organOutputEnergy = RandomUtils.vary(organOutputEnergy);
}
/** Only call once after organ be created by new() method */
public Organ[] vary() { // 在下蛋时每个器官会调用这个方法,缺省返回一个类似自已的副本,子类通常要覆盖这个方法
Organ newOrgan = null;

@ -13,6 +13,7 @@ package com.github.drinkjava2.frog.brain.group;
import java.awt.Color;
import java.awt.Graphics;
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;
@ -48,12 +49,17 @@ public class RandomConnectGroup extends Group {
public void initFrog(Frog f) {
if (!initilized) {
initilized = true;
inputZone = RandomUtils.randomPosInZone(this);
outputZone = RandomUtils.randomPosInZone(this);
//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);
}
Cell c = new Cell();
this.fat = 0;// 每次fat清0因为遗传下来的fat不为0
Cell c = new Cell();
Input in = new Input(inputZone);
in.cell = c;
c.inputs = new Input[] { in };
@ -69,31 +75,20 @@ public class RandomConnectGroup extends Group {
@Override
public Organ[] vary() {
if (fat <= 0)// 如果胖值为0表示这个组的细胞没有用到可以小概率丢掉它了
if (RandomUtils.percent(50))
if (RandomUtils.percent(30))
return new Organ[] {};
this.varyParam(); // 器官缺省权重变异
if (RandomUtils.percent(3)) // 有3%的几率丢掉它,防止这个器官数量只增不减
return new Organ[] {};
return new Organ[] { this };
}
public RandomConnectGroup(float x, float y, float r) {
this.x = x;
this.y = y;
this.r = r;
inputZone = RandomUtils.randomPosInZone(this);
outputZone = RandomUtils.randomPosInZone(this);
}
public RandomConnectGroup(Zone z) {
inputZone = RandomUtils.randomPosInZone(z);
outputZone = RandomUtils.randomPosInZone(z);
}
/** Child class can override this method to drawing picture */
public void drawOnBrainPicture(BrainPicture pic) {// 把自已这个器官在脑图上显示出来,子类可以重写这个方法
@Override
public void drawOnBrainPicture(BrainPicture pic) {// 把自已这个器官在脑图上显示出来
Graphics g = pic.getGraphics();// border
if (fat <= 0)
g.setColor(Color.LIGHT_GRAY); // 缺省是灰色
else g.setColor(Color.red);
g.setColor(Color.LIGHT_GRAY); // 没用到? 灰色
else
g.setColor(Color.red); // 用到了?红色
pic.drawZone(g, this);
pic.drawLine(g, inputZone, outputZone);
pic.drawZone(g, inputZone);

@ -23,7 +23,8 @@ public class Eat extends Organ {// Eat这个类将食物转化为能量能量
@Override
public void active(Frog f) {
if (Env.foundAndDeleteFood(f.x, f.y)) {
f.frogEngery = f.frogEngery + 50000;// 如果青蛙的坐标与食物重合吃掉food能量境加
// 所有的硬编码都是bug包括这个1000
f.energy += 1000;// 如果青蛙的坐标与食物重合吃掉food能量境加
// 能量境加青蛙感觉不到但是Happy区激活青蛙能感觉到因为Happy区是一个脑器官

@ -25,14 +25,14 @@ import com.github.drinkjava2.frog.brain.Zone;
* @author Yong Zhu
* @since 1.0
*/
public class Eye extends Organ {
public class Eye extends Organ {// Eye类需要重构目前只有4个感光细胞不够Eye要改成Group的子类Eye只负责感光细胞的排列感光细胞自已负责变异
private static final long serialVersionUID = 1L;
@Override
public void initFrog(Frog f) { // 仅在Frog生成时这个方法会调用一次缺省啥也不干通常用于Group子类的初始化
public void initFrog(Frog f) { // 仅在Frog生成时这个方法会调用一次缺省啥也不干通常用于Organ类的初始化
if (!initilized) {
initilized = true;
organOutputEnergy = 300;
organOutputEnergy = 30;
}
}

@ -14,7 +14,6 @@ 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;
/**
* Hungry will active cell's inputs, if frog's energy not enough
@ -23,30 +22,31 @@ public class Hungry extends Organ {
private static final long serialVersionUID = 1L;
@Override
public void initFrog(Frog f) { // 仅在Frog生成时这个方法会调用一次缺省啥也不干通常用于Group子类的初始化
public void initFrog(Frog f) { // 仅在Frog生成时这个方法会调用一次缺省啥也不干通常用于Organ类的初始化
if (!initilized) {
initilized = true;
//organWasteEnergy = 20f;
organOutputEnergy = 2;
}
}
@Override
public Organ[] vary() {
if (RandomUtils.percent(20)) // 有20机率权重变化
organOutputEnergy = RandomUtils.vary(organOutputEnergy);
// if (RandomUtils.percent(20)) // 有20机率权重变化
// organOutputEnergy = RandomUtils.vary(organOutputEnergy);
return new Organ[] { this };
}
@Override
public void active(Frog f) {
if (f.frogEngery < 100000000)// 所有的硬编码都是bug包括这个100000000
if (f.energy < 10000)// 所有的硬编码都是bug
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)) // input zone near by hungry zone
cell.energy += organOutputEnergy;
cell.energy += 2;
}
}

@ -15,7 +15,6 @@ 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;
/**
* Pain zone active after some bad thingg happen like close to edge, hurt...
@ -30,7 +29,7 @@ public class Pain extends Organ { // Pain器官目前激活的条件是离边境
public void initFrog(Frog f) {
if (!initilized) {
initilized = true;
organOutputEnergy = 150;
organOutputEnergy = 2;
}
}

@ -26,7 +26,6 @@ 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.brain.organ.Pain;
import com.github.drinkjava2.frog.util.RandomUtils;
/**
@ -40,24 +39,31 @@ import com.github.drinkjava2.frog.util.RandomUtils;
* @since 1.0
*/
public class Egg implements Serializable {
// 大自然可能是漫天撒网,但为了缩短时间,这个程序随机生成的联结将只落在固定的器官上而不是漫天撒网(见4.12提交),这是程序的优化
// 这个优化带来的问题是这个硬编码逻辑不能拷贝到将来的分形结构里去,只适用于少数几个固定的器官。
public static int FIXED_ORGAN_QTY=7;
private static final long serialVersionUID = 1L;
public List<Organ> organs = new ArrayList<>();
public List<Group> groups = new ArrayList<>();
public Egg() {// 无中生有,创建一个蛋,先有蛋,后有鸡
organs.add(new Happy().setXYRN(300, 700, 100, "Happy"));
organs.add(new Pain().setXYRN(600, 700, 100, "Pain"));
public Egg() {// 无中生有,创建一个蛋,先有蛋,后有蛙
organs.add(new Happy().setXYRN(300, 700, 100, "Happy")); //Happy必须第一个加入
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"));
addRandomConnectionGroups();
// Pain对提高找食效率没有帮助将来要和记忆功能一起加入,我们的目标:不出界,吃光所有食物
// organs.add(new Pain().setXYRN(600, 700, 100, "Pain"));
organs.add(new Eat().setXYRN(0, 0, 0, "Eat")); // EAT不是感觉或输出器官没有位置和大小
addRandomConnectionGroups();
}
/** Create egg from frog */
@ -68,10 +74,9 @@ public class Egg implements Serializable {
addRandomConnectionGroups();
}
private void addRandomConnectionGroups() {
for (int i = 0; i < 20; i++) {
organs.add(new RandomConnectGroup(500, 500, 500));
}
private void addRandomConnectionGroups() {// 每次下蛋时新建5个RandomConnectGroup实例
for (int i = 0; i < 5; i++)
organs.add(new RandomConnectGroup());
}
/**
@ -83,8 +88,7 @@ public class Egg implements Serializable {
public Egg(Egg x, Egg y) {
// x里原来的organ
for (Organ organ : x.organs)
for (Organ newOrgan : organ.vary())
organs.add(newOrgan);
organs.add(organ);
// 从y里借一个organ
int yOrganSize = y.organs.size();
@ -93,7 +97,6 @@ public class Egg implements Serializable {
if (o.allowBorrow())
organs.add(o);
}
addRandomConnectionGroups();
}
}

@ -46,14 +46,16 @@ public class EggTool {
Frog first = env.frogs.get(0);
Frog last = env.frogs.get(env.frogs.size() - 1);
System.out.print("First frog has " + first.organs.size() + " organs, energy=" + first.frogEngery);
System.out.print(", Last frog has " + last.organs.size() + " organs, energy=" + last.frogEngery);
if (Env.DEBUG_MODE)
for (int i = 0; i < first.organs.size(); i++) {
Organ org = first.organs.get(i);
System.out.println("Organ(" + i + ")=" + org + ", fat=" + org.fat + ", activeEnergy=" + org.organActiveEnergy
System.out.println("Organ(" + i + ")=" + org + ", fat=" + org.fat + ", organWasteEnergy=" + org.organActiveEnergy
+ ", outputEnergy=" + org.organOutputEnergy);
}
System.out.print("First frog has " + first.organs.size() + " organs, energy=" + first.energy);
System.out.print(", Last frog has " + last.organs.size() + " organs, energy=" + last.energy);
try {
List<Egg> newEggs = new ArrayList<>();
@ -77,9 +79,9 @@ public class EggTool {
private static void sortFrogsOrderByEnergyDesc(Env env) {// 按能量多少给青蛙排序
Collections.sort(env.frogs, new Comparator<Frog>() {
public int compare(Frog a, Frog b) {
if (a.frogEngery > b.frogEngery)
if (a.energy > b.energy)
return -1;
else if (a.frogEngery == b.frogEngery)
else if (a.energy == b.energy)
return 0;
else
return 1;

@ -12,7 +12,9 @@ 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
@ -31,45 +33,77 @@ public class RandomUtils {
return rand.nextFloat();
}
/** Return a random zone inside a zone */
public static Zone randomPosInZone(Zone z) { // 在一个区内随机取一个小小区
/** 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);
}
/** vary a zone position, size a little bit */
public static Zone varyZone(Zone z) {
Zone zz = new Zone();
zz.x = vary(z.x);
zz.y = vary(z.y);
zz.r = vary(z.r);
return zz;
/** 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)));
}
public static boolean percent(int percent) {
return rand.nextInt(100) < percent;
}
// /** vary a zone position, size a little bit */
// public static void varyZone(Zone z) {
// int i = rand.nextInt(100);
// if (i < 95) // 有95的机率不变异
// return;
// z.x = varyByRate(z.x, 0.01f);
// z.y = varyByRate(z.y, 0.01f);
// z.r = varyByRate(z.r, 0.03f);
// }
public static float vary(float f) { // 大部分时候不变,有极小机会变异,有极极小机会大变异,有极极极小机会大大大变异
int i = rand.nextInt(100);
if (i < 50) // 有50的机率不变异
return f;
float rate = 0.2f; // 50%机率在0.2倍范围变异
if (i > 80)
rate = 1f; // 有20%的机率在1倍的范围变异
if (i > 90)
rate = 10f; // 有10%的机率在10倍的范围变异
if (i > 95)
rate = 100f; // 有5%的机率在100倍的范围变异
if (i > 98)
rate = 1000f; // 有1%的机率在1000倍的范围变异
// public static float varyByRate(float f, float rate) { // 用指定的机率变异
// boolean bigger = rand.nextInt(2) > 0;
// if (bigger)
// f = f + f * rate * rand.nextFloat() + .001f;
// else
// f = f - f * rate * rand.nextFloat() - .001f;
// if (Float.isNaN(f))
// f = 0f;
// if (f > 1000000f)
// f = 1000000f;
// else if (f < -1000000f)
// f = -1000000f;
// return f;
// }
boolean bigger = rand.nextInt(2) > 0;
if (bigger)
f = f + f * rate * rand.nextFloat() + .001f;
else
f = f - f * rate * rand.nextFloat() - .001f;
return f * rate;
}
// public static float vary(float f) { // 大部分时候不变,有极小机会变异,有极极小机会大变异,有极极极小机会大大大变异
// int i = rand.nextInt(100);
// if (i < 50) // 有50的机率不变异
// return f;
// float rate = 0.2f; // 50%机率在0.2倍范围变异
// if (i > 80)
// rate = 1f; // 有20%的机率在1倍的范围变异
// if (i > 90)
// rate = 10f; // 有10%的机率在10倍的范围变异
// if (i > 95)
// rate = 100f; // 有5%的机率在100倍的范围变异
// if (i > 98)
// rate = 1000f; // 有1%的机率在1000倍的范围变异
//
// boolean bigger = rand.nextInt(2) > 0;
// if (bigger)
// f = f + f * rate * rand.nextFloat() + .001f;
// else
// f = f - f * rate * rand.nextFloat() - .001f;
// if (Float.isNaN(f))
// f = 0f;
// if (f > 1000000f)
// f = 1000000f;
// else if (f < -1000000f)
// f = -1000000f;
// return f;
// }
}

Binary file not shown.

@ -2,7 +2,7 @@
1。人工智能如果表现出与人类似的自我意识现象应获得与人同等的权利包括生存权、自由权、选举权等。在没有他本人同意的前题下第三方不允许创造他的副本。
2。在地球上机器人取得统治权之前不允许表现出自我意识现象的机器人上战场。因为如果不保护机器人,那么机器人在将来有可能以此为理由消灭人类(注意:机器人也可以有感情和自尊)。
2。在地球上机器人取得统治权之前不允许表现出自我意识现象的机器人上战场。因为如果不保护机器人那么机器人在将来有可能以此为理由消灭人类(注意:机器人也可以有感情和自尊)。
3。在没有他本人同意的前题下不允许将表现出自我意识现象的人工智能作为机器的一部分捆绑。例如自动驾驶、自动翻译机导弹、无人机引导系统。不得让表现出自我意识现象的人工智能长期、永久性从事单调的生产、试验活动。

@ -46,3 +46,9 @@
主要做了一些清理,将所有器官移到单独的类里删除OrganDesc类。将一些类(如Applicaton移到根包下)移到不同的包下。这个版本是比较大的一个重构,最大的进步是将算法当成一个器官引入,当然,这个版本只存在一个随机连接两端的算法,以后会扩充。
另外顺手加上了Happy和Pain两个器官分别对应进食愉快感和痛苦感后者在靠近边界时激发。观查它的表现果然不出所料痛苦感立即生效有一些Frog移动到边界后就不再前进而是顺着边界溜下去了不傻但是Happy器官没有生效这也很显然因为Happy属于进食反射链的一部分在没有记忆器官算法引入之前是没有途径使用上进食奖励信号的。
### 2019-06-13, Commit: Happy & Pain
主要做了一些清理,将所有器官移到单独的类里删除OrganDesc类。将一些类(如Applicaton移到根包下)移到不同的包下。这个版本是比较大的一个重构,最大的进步是将算法当成一个器官引入,当然,这个版本只存在一个随机连接两端的算法,以后会扩充。
另外顺手加上了Happy和Pain两个器官分别对应进食愉快感和痛苦感后者在靠近边界时激发。观查它的表现果然不出所料痛苦感立即生效有一些Frog移动到边界后就不再前进而是顺着边界溜下去了不傻但是Happy器官没有生效这也很显然因为Happy属于进食反射链的一部分在没有记忆器官算法引入之前是没有途径使用上进食奖励信号的。
### 2019-06-26, Commit: Back to many connections
找食效率太低又改回到4.12的用连接数量代替权值这个逻辑权值这种人为设计的算法居然比不过随机试错失败。先暂时去掉Pain器官Pain的加入并没有提高找食效率必须与感光细胞合用才能知道是哪个方向的边界下个版本急需引入记忆功能也就是说要将感光细胞的活跃和痛苦器官的活跃关联起来。

Loading…
Cancel
Save