Add File
This commit is contained in:
@@ -0,0 +1,188 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.Arrays;
|
||||||
|
|
||||||
|
import com.github.drinkjava2.frog.util.ColorUtils;
|
||||||
|
import com.github.drinkjava2.frog.util.RandomUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cell is the smallest unit of brain space, a Cell can have many actions and
|
||||||
|
* photons and holes and relations
|
||||||
|
*
|
||||||
|
* Cell是脑的最小空间单元,可以存在多个行为(由organs中的器官代号来表示)和光子(Photon)和洞(Hole)和关联(Relation),脑是由frog中的cells三维数组组
|
||||||
|
* 成,但不是每一维都初始化过。
|
||||||
|
*
|
||||||
|
* Cell原则上只有数据,应该把所有方法移出去,放到具体的器官行为中,见CellActions类,但暂时图省事,在Cell里放一些常用方法
|
||||||
|
*
|
||||||
|
* Jelly或MoveJelly器官有一种特殊行为,它可以产生动态触突效果,可以把具备动态触突的神经元比作一个果冻,光子来了,在上面撞了一个坑(hole)并损失能量,
|
||||||
|
* 如果来的多,或者速度快(能量大),一部分的光子就被从果冻的另一头撞出去了(光直线传播,寻找下一个神经元,增加信息存储单元,实现体全息存贮)。如果在另一个角度又
|
||||||
|
* 来了新的光子,同样的过程在发生,只不过在撞击的过程中,以前被撞出的坑里有可能被撞出光子来,沿着撞击坑的路径直线逆向返回(即波的逆向成像,两个撞击事件,如果
|
||||||
|
* 在短期内同时发生,或长期反复发生,就形成比较稳定的关联,这个与神经网络的hebb规则相符合,以后在这个基础上,看看能不能将深度学习的分层结构借签进来,用图形化
|
||||||
|
* 表示,并有可能是无级分层的,层与层之前没有明显界限。
|
||||||
|
*
|
||||||
|
* @author Yong Zhu
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public class Cell {
|
||||||
|
public int x;
|
||||||
|
public int y;
|
||||||
|
public int z;
|
||||||
|
|
||||||
|
public Cell(int x, int y, int z) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Active of current cell */
|
||||||
|
public boolean hasInput = false; // 这个细胞是否有外界信号(如光、声音)输入
|
||||||
|
|
||||||
|
public int[] organs = null; //// 每个Cell可以被多个Organ登记,这里保存organ在蛋里的序号
|
||||||
|
|
||||||
|
public Photon[] photons = null;// 光子
|
||||||
|
|
||||||
|
public Hole[] holes = null;// 洞(即动态突触),洞由光子产生,洞由时间抹平
|
||||||
|
|
||||||
|
public Relation[] relations = null;// 洞的关联关系
|
||||||
|
|
||||||
|
public int color;// Cell的颜色取最后一次被添加的光子的颜色,颜色不重要,但能方便观察
|
||||||
|
|
||||||
|
public int photonQty = 0; // 这个细胞里当前包含的光子总数
|
||||||
|
|
||||||
|
public int photonSum = 0; // 这个细胞里曾经收到的光子总数
|
||||||
|
|
||||||
|
public void regOrgan(int orgNo) {// 每个Cell可以被多个Organ登记,通常只在青蛙初始化器官时调用这个方法
|
||||||
|
if (organs == null)
|
||||||
|
organs = new int[] {};
|
||||||
|
organs = Arrays.copyOf(organs, organs.length + 1);
|
||||||
|
organs[organs.length - 1] = orgNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPhoton(Photon p) {// 每个cell可以存在多个光子
|
||||||
|
if (p == null)
|
||||||
|
return;
|
||||||
|
photonQty++;
|
||||||
|
photonSum++;
|
||||||
|
color = p.color; // Cell的颜色取最后一次被添加的光子的颜色
|
||||||
|
if (photons == null) {
|
||||||
|
photons = new Photon[] { p };// 创建数组
|
||||||
|
return;
|
||||||
|
} else
|
||||||
|
for (int i = 0; i < photons.length; i++) { // 找空位插入,尽量重复利用内存
|
||||||
|
if (photons[i] == null) {
|
||||||
|
photons[i] = p;
|
||||||
|
return; // 如找到就插入,返回
|
||||||
|
}
|
||||||
|
}
|
||||||
|
photons = Arrays.copyOf(photons, photons.length + 1);// 否则追加新光子到未尾
|
||||||
|
photons[photons.length - 1] = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void digHole(Photon p) {// 根据光子来把洞挖大一点,同时,如果有洞和它年龄相近,将把它们绑定起来,如果已有绑定的洞,有可能在绑定的洞里撞出光子来
|
||||||
|
if (p == null || p.isBackway())// 反向的光子不参与挖坑
|
||||||
|
return;
|
||||||
|
if (holes == null) {// 如果没有坑,就新挖一个
|
||||||
|
holes = new Hole[] { new Hole(p) }; // 新挖的坑不参与绑定
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RandomUtils.percent(10)) // 这个机率纯粹是为了减少光子数,增加运行速度
|
||||||
|
for (int i = 0; i < holes.length; i++) { // 这部分很关键,光子如果与坑同向或角度相近,会在与坑绑定的坑上撞出新的光子反向飞回,注意只针对绑定的坑
|
||||||
|
Hole h = holes[i];
|
||||||
|
if (h != null) {
|
||||||
|
float r = h.angleCompare(p);
|
||||||
|
if (r < 0.05) {
|
||||||
|
if (RandomUtils.percent(h.size))
|
||||||
|
createBackPhoton(h); // 产生光子的机率与洞的大小有关
|
||||||
|
} else if (r > 0.1 && r < 0.5) { // 这个叫侧抑制,角度不等但相近的光子射过来会使洞变小
|
||||||
|
h.size -= 10;
|
||||||
|
if (h.size < 10)
|
||||||
|
h.size = 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Hole found = null;
|
||||||
|
for (int i = 0; i < holes.length; i++) { // 先看看已存在的洞是不是与光子同向,是的话就把洞挖大一点
|
||||||
|
Hole h = holes[i];
|
||||||
|
if (h != null && h.ifSimilarWay(p)) { // 找到了与入射光子同向的洞,实际上就是同一个波源发来的
|
||||||
|
found = h;
|
||||||
|
h.size += 10;
|
||||||
|
h.age = 0; // 为0表示这个洞被重新激活,可以参与绑定
|
||||||
|
if (h.size > 100)
|
||||||
|
h.size = 100;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found != null) { // 如果第二次扩洞,且光子和洞不是同一个器官产生的,这时可以把这个洞和其它洞关联起来了
|
||||||
|
for (Hole hole : holes) {
|
||||||
|
if (hole != found && found.organNo != hole.organNo && (Math.abs(found.age - hole.age) < 80)) {// TODO:不应用固定值
|
||||||
|
bind(found, hole);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found == null) {// 如果还没有找到旧坑,只好挖一个新坑到未尾
|
||||||
|
holes = Arrays.copyOf(holes, holes.length + 1);
|
||||||
|
holes[holes.length - 1] = new Hole(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createBackPhoton(Hole h) { // 根据给定的洞,把所有与它绑定的洞上撞出光子来
|
||||||
|
if (relations == null)
|
||||||
|
return;
|
||||||
|
for (Relation r : relations) {
|
||||||
|
Hole f = null;
|
||||||
|
if (h.equals(r.h1))
|
||||||
|
f = r.h2;// h2与h是一对绑定的
|
||||||
|
else if (h.equals(r.h2))
|
||||||
|
f = r.h1; // h1与h是一对绑定的
|
||||||
|
if (f != null) {
|
||||||
|
Photon back = new Photon(-1, ColorUtils.RED, f.x, f.y, f.z, -f.mx, -f.my, -f.mz);// 生成反向的光子
|
||||||
|
addPhoton(back);
|
||||||
|
// energy -= 90;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bind(Hole a, Hole b) {// 将两个坑绑定,以后只要有一个坑激活,另一个坑也会产生出光子
|
||||||
|
if (relations == null) {
|
||||||
|
relations = new Relation[] { new Relation(a, b) };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (Relation r : relations) {// 先看看是不是已绑过,绑过就把强度乘1.5
|
||||||
|
if ((r.h1 == a && r.h2 == b) || (r.h2 == a && r.h1 == b)) {
|
||||||
|
r.strength *= 1.5;
|
||||||
|
if (r.strength > 100000) // TODO: strength要有遗忘机制
|
||||||
|
r.strength = 100000;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
relations = Arrays.copyOf(relations, relations.length + 1);
|
||||||
|
relations[relations.length - 1] = new Relation(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removePhoton(int i) {// 删第几个光子
|
||||||
|
if (photons[i] != null) {
|
||||||
|
photons[i] = null;
|
||||||
|
photonQty--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteAllPhotons() {
|
||||||
|
photons = null;
|
||||||
|
photonQty = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user