====== Dev Blog ======
===== July 20, 2023 =====
* the system
* work to understand people
* understand why they do what they do
* understand what is their motivation
* understand something that is happening and the person's motivation to make such an event happen.
* determine if the event will cause harm to others
* cost benefit analysis
* identify perpetrator
* identify victims
* identify person in the position to help the most
* notify person
===== October 28, 2022 =====
* papers titled “A Model for Self-Organization of Sensorimotor Function: The Spinal Monosynaptic Loop" and "Spinal Intraneuronal Integration”
* [[https://jneurophysiol.podbean.com/e/self-organization-of-spinal-monosynaptic-and-interneuronal-circuitry/|self organization of spinal circuitry]]
===== October 11, 2021 =====
* They are not Spikes, they are sparks.
* in terms of self assembling structures
* and spiking neural networks
* they're not spikes, their sparks as in lightning
* the electricity builds up and then discharges.
===== July 28, 2021 =====
* along with self assembling structures
* Battery dendrite formation
* Simulating dendrite formation
===== April 10, 2021 =====
* self assembling stuctures
* youtube video self-assebmling wires
* Dr. Hubler
* This behavior solves the node connection problem
===== March 20, 2021 =====
* I first tried to figure out gravity. I.e. create anti-gravity
* I didn't have much understanding of electronics or physics at the time and didn't have path forward in solving such a problem
* Then I wasted some time trying to figure out infinite energy. Had some ideas but these were quickly tested by others and shown not to be a useful solution.
* I then got a job doing natural language processing, which is machine learning or Artificial intelligence.
* Once I started grasping this world, it all coalesced.
* I've been studying human behavior, i.e. psychology, because I don't understand people
* But I've also been studying computer programming.
* When you merge these 2 together, you get Artificial Intelligence.
* And I started thinking about how the human brain works and how someone could recreate the human brain in a computer.
* I had an idea on how to solve this.
* I spent the next 15 years trying to determine an algorithm that would recreate this behavior
* in 2015, I realized exactly what algorithm would behave like the human brain.
* Since 2015, I started trying to figure out how to fund the effort of taking this algorithm and turning it into a full product.
* at the end of 2020, I succeeded in creating the funds needed to pursue this algorithm full time.
* Now, I have been thinking about how this algorithm could help people.
* It can be used to automate production.
* It could be used to subvert the governments of the world and make societies better for the common person.
* It could be used to generate even more money, but if it automates the means of production, money would be meaningless.
===== February 22, 2021 =====
[[https://www.iflscience.com/brain/people-with-no-internal-monologue-explain-what-its-like-in-their-head/|Inner monologue]]
* A normal(25% of people) person will have both and inner dialog with their logical brain and with their emotional brain.
* A person with Asperger's only has an inner dialog of their logical brain.
* apparently there are people with only the emotional dialog, probably highly empathetic people.
* Do you have an emotional inner dialog?
* Do you have a logical inner dialog?
* Do you have both that argue with each other?
* Do you have neither, and only feel emotions?
===== October 10, 2020 =====
Dynamic population encoding algorithm
author : Tofara Moyo
We believe that humans map inputs to actions. In order to do this optimally some action in the distant past has to have an effect on the present actions. This was handled by nature by giving some means to divert the input signal and have the diverted signal influence the action at a later stage.
This was also sufficient to make this a function, because similar states could now cause widely different actions because the action was conditioned not only on the current state, but also on the diverted input signal.
Also, within the brain, which was made with the sole purpose of diverting the signal, subnetworks with strong local connectivity within themselves would cause different effects to other networks (even those with other networks in between) at different times by diverting the signal they received, through the rest of the networks, before affecting the network they were trying to effect. This is true pairwise between every network in the brain.
The neural model we propose consists of a networked cellular automaton, where unlike in a traditional cellular automaton where physical boundaries determine neighbours, neighbouring cells could be “further” apart. What this means is that it will be necessary to keep an adjacency matrix that shows which neurons are connected to which.
The network will be initialized randomly with 2 % connectivity throughout the network in order to simulate sparse codes.Then spectral graph analysis will be used to determine which segments the network can be broken into most logically. An agent A will be assigned to each subnetwork, and its set of actions will have it move from node to node within its subnet . We borrow ideas from internetworking by having an instance of the rapid spanning tree protocol running in each network.
The rapid spanning tree algorithm is used in cisco routers in order to prevent loops within a network. It does so by determining which connections should be blocked and which maintained. we will use the RSTA in order to adjust the topology of each of the subnetworks. Within RSTA switches exchange information in order to vote for a root bridge/switch. The choice of root bridge finally settled on influences how the topology of the network will be set. In our case we will omit the voting feature from our implementation.
instead the node that the agent A associated with the subnetwork is currently positioned on will be chosen as the root node. Note that the agent A is free to hop from node to node, even if they are not directly connected. Once the root node is chosen , the topology of the subnet is adjusted in line with this information. Our aim is to get each agent A to maximise its own reward by indirectly changing the topology of the network and influencing yet another network, which will act as the environment of the agent.
Each agent A will be associated with two networks. the network that it is hoping from node to node in, and one of the other networks. This secondary network will act as a part of the environment for the agent and will give it its reward. In a robotic system, once the total reward is calculated we would like a way to use it to influence which rewards a particular network feeds its paired agent A. this will be done by having each network keep a Q table with the action being increasing or decreasing the reward that the network gives out and the state being the global reward.
This means in short that each network has two associated agents, A and B. One A that hops from node to node changing the topology of the network. And one B that calculates the reward it should emit to the diametrically opposed agent from the paired network. The dynamics of the network would have each network’s agent A figure out a way to maximise its total personal reward by changing the topology of its network, and causing a ripple effect that will modulate the network that is diametrically opposite it.
This reward is calculated by the second network's agent B from the global reward. This second agent maximises (its) the global reward, by giving the first agent the most fitting rewards for actions. In order to connect this to traditional neural networks we will do the following. Given the input to the neural network we will have the outputs of this network be given a multi class distribution where the input activates some of the cells in a particular network within the neural model.
One of the other networks in the model will act as a teacher and have mirrored neurons for each of the output neurons mentioned. Once the neural network has received some input and predicted the particular cells that it does. The difference between the signal received by the mirrored neurons and the neural networks output cells will be used to come up with a loss value in which to train the neural networks.
===== July 10, 2020 =====
* It creates multiple connections then drops around 30% of those connections : ref - Workshop on continual learning | CVPR 2020 | subutai ahmad
===== January 12, 2020 =====
* Input - [[https://www.quantamagazine.org/a-mathematical-model-unlocks-the-secrets-of-vision-20190821/|Paper]] about sensors in the eye
* Node creation - paper about neuro plasticity
* Output Discovery - My own work in watching the neuron algorithm
* Feedback loop - [[https://www.jneurosci.org/content/36/49/12368|paper]] about sine wave behavior in the brain
===== December 22, 2019 =====
* [[https://m.phys.org/news/2019-12-brain-like-behavior-nanoscale-device.html|Brain like behavior nanoscale device]]
===== December 7, 2019 =====
* another potential market - [[https://buildingiq.com/blog/simulation-a-safe-playground-for-smart-hvac-control/|Building control]]
===== November 30, 2019 =====
* what if I track node activation with reward output feedback, where it sees the nodes that contributed to the result and it works to minimized the path between the input nodes and the output nodes.
===== November 21, 2019 =====
* desire is to connect to an output. I.e. if there isn't a output that is stimulated then trying to find that connection is the driving force. "Something is nagging me and I can't quite put my finger on it."
===== September 28, 2019 =====
* am I driving the nervous system or am I remembering the sensation of the memory system?
===== September 21, 2019 =====
* Multiple inputs drive intensity of neuron activation. The intensity competes with other stimulus. The one with the most intense activation drives motors. If none are intense enough then they just linger as thoughts.
* is the spinal cord more of an input/output without intensity? The brain is more about thought which gives suggestions to the spinal cord? muffling the input/output of the brain?
* I think it is the complexity of inputs. There are so many inputs and outputs that the brain can linger on a thought without activation because the combined intensity is still low enough not to activate the motor.
===== September 18, 2019 =====
* I have to continue living the life that I have been living to make progress on TrueAI. Without this interaction or activities that I experience, I will not be able to make breakthroughs on how people work. For example. I'm currently watching servamp anime. Which gave me insight into sadness and how the physical body reacts to that emotion and how those reactions drive the mind. All of this, through the way I live.
===== August 23, 2019 =====
* [[https://m.medicalxpress.com/news/2019-08-memories.html|Persistence of neuronal representations through time and damage in the hippocampus.]]
This paper describes pretty accurately how my algorithm works. and based on it's description you can correlate what my algorithm is doing to the behavior that they describe.
===== August 15, 2019 =====
Had a discussion with a person from DARPA. She said a lot of interesting things. Most notably, I need to formalize my work into scientific papers. Yes, multiple. I would need to start from existing research and show how I got to where I am.
here are notes from the meeting
open baa
hp1 - contract type
hebbian learning
neurons fire together fire together
aie - contract type
white paper -- problem space - class of problems - metrics -
portfolios on polyplexus - abstract
===== August 5, 2019 =====
* arm lightweight cores cpu
===== July 26, 2019 =====
* Ok, so there is the thing called Spiking Neural Network. From the high level description, it sounds really close to what I have built.
* But the earliest paper I could find is 2002. How have they not created a fully functional human level intelligence by now?
* here's a paper - [[https://towardsdatascience.com/spiking-neural-networks-the-next-generation-of-machine-learning-84e167f4eb2b|Spiking Neural Networks - The Next Generation of Machine Learning]]
* It's just a variation on neural networks.
* link weights -> delay activation
* sigmoid -> accumulation of spikes
* layers and nodes are still there along with everything is connected to everything (from one layer to the next) and the flow through the graph is controlled by link weights
* they have multiple discrete networks that are connected by a routing function
* basically it's an efficient implementation of a neural network in silicon.
* So they are able to create very large networks that compute really fast and don't use a lot of electricity
===== July 14, 2019 =====
* The heat map of the link weights on a neural network shows how the network is inflexable if the data gets to disparate.
* [[https://it.mathworks.com/help/deeplearning/ug/cluster-with-self-organizing-map-neural-network.html|Heat Map]]
===== July 13, 2019 =====
* [[https://scienceblog.com/494232/mind-controlled-device-helps-stroke-patients-retrain-brains-move-paralyzed-hands/|Stroke victim retains hand]]
* [[http://www.chessgames.com/perl/chesscollection?cid=1001601|Chess Games]]
* [[http://www.mentalconstruction.com/mental-construction/neural-connections/maps-brain/attachment/cortical-layers/|Cortical Layers]]
* [[https://www.livescience.com/7822-girl-sees-fine-brain.html|Girl Sees Fine With Half a Brain]]
* [[https://jeb.biologists.org/content/209/12/2312|Neuronal networks and synaptic plasticity: understanding complex system dynamics by interfacing neurons with silicon technologies]]
* [[http://bsi.riken.jp/bsi-news/bsinews38/no38/research1e.html|The Mechanism that Controls the Direction of Axon Elongation]]
* [[http://bme240.eng.uci.edu/students/07s/sliu/|Neuron Silicon Interface]]
===== July 11, 2019 =====
* they are looking at a car and they are looking at the materials that make up the car but they don't even have a concept of what a bolt is and how it plays within the system of making a car.
* [[https://deepmind.com/blog/hippocampus-predictive-map/|The hippocampus as a predictive map]]
* This [[https://advances.sciencemag.org/content/5/2/eaat7603|neuroscience paper]] has a better understanding of how the brain works.
===== June 22, 2019 =====
Neural networks have reached their peak. It's evident by looking at how they architected Alpha Star. Alpha Star uses a very cluegy architecture to solve the problem. It's not self contained within a neural network. Also, the errors that happen within a neural network, don't happen within a human brain. My algorithm is elegant. It's simple. You have 2 nerve ends and they are active. The brain says, connect those 2 with a neuron. Then you have 2 active neurons. the brain says, connect those 2. and so on. This is played out in the real world. Scientists conducted a test where they put a brain slice on a silicon chip. The brain slice grew to where there was activity on the silicon. It is a very simple process that is capable of very complex action and I've captured it within my algorithm.
===== February 10, 2019 =====
Maybe I should study psychology
* [[https://www.psychologytoday.com/us/blog/intense-emotions-and-strong-feelings/201501/seeking-comfort-the-impossible-way|Seeking Comfort the impossible way]], Emotions motivate us to do something
* [[https://www.psychologytoday.com/us/blog/theory-consciousness|Theory of Consciousness]], self model
===== January 31, 2019 =====
With the input nodes "growing" to connect the the same kind of "growth" for the output nodes. This mid line connection is what creates consciousness. When training the output side has an active node tree. But after learning a few inputs the mid line will have more than one active node. This multiple activation is what gives rise to humans pondering what action to take.
This and also the before mentioned, constant looping of the thoughts which give rise to active memory.
===== December 2, 2018 =====
* maybe of interest
* https://aws.amazon.com/deepracer/
* https://hackaday.com/2018/11/30/buy-or-build-an-autonomous-race-car-to-take-the-checkered-flag/
===== November 29, 2018 =====
* From the top layer from the input nodes.
* Connect to the output node
* if there are more than one node active at the top of input nodes, create a new node connecting them
* If there is a layer above the top nodes, for all that are active create a new layer along with a new node
* there needs to be a layer with only one node active to connect to the output node.
* but just like with the input layers, they are capped to 7 layers
===== November 26, 2018 =====
* activation is just the individual nodes cascading the chain to the output nodes. Easy to make parallel
* This activation needs to be stored then recalled later for training, short term memory
* training is a slow linear process. i.e. dreams
===== November 24, 2018 =====
* applying to investors, below is a list of ones that I've applied.
* https://fundersclub.com/
* http://innovationplatformcapital.com/
* https://www.seedequity.com/
* https://www.ourcrowd.com/
* angel investors - https://www.inc.com/guides/start_biz/24011.html
===== November 20, 2018 =====
* https://www.angelcapitalassociation.org/directory/
===== October 25, 2018 =====
* So I realized out to output from the network
* just work backwards from the primary active node down to the desired output node
===== October 24, 2018 =====
* Multiple relationships of patterns that represent clusters.
* It's a multi-relationship database of patterns
===== October 23, 2018 =====
* [[http://www.ros.org/]] Start wiht this to simulate the ai controlling a robot.
===== October 9, 2018 =====
* [[https://www.google.com/search?q=ai+basic+research+funding|Google Search funding]]
===== September 16, 2018 =====
* the difference between my A.i. and neural networks
* neural networks are not able to have disparate conflicting ideas
* for example: the dataset has zeros for inputs 1-10 and values for 11-15
* these inputs conclude a certain output
* then you have values for 1-5 but zeros for 6-15
* these new set of values are pointing to a different output or the same one
* neural networks cannot handle this.
===== September 5, 2018 =====
* Background video that pre-dates the "Body & Mind" video
* I have aspberger's
* Pay a lot of attention to how/why people do things
* TLC had various shows on about how the mind works
* Self understanding with the mirror concept
* Heart attack/stroke but still able to relearn, shows new path ways neurons being formed
* Reaction time, showing an MRI scan that shows the inception point of a thought
* Talk to an MRI scan between Aspberger's and a normal person
* Not a focus until I got a job researching NLP
* The book "On Intelligence"
* The Mind, body, soul discussion/book
* This lead me down the path thinking about how we truly learn something
===== May 7, 2016 =====
* [[http://opencores.org/projects]]
===== March 24, 2016 =====
* Interesting note: It's an ontology [[http://schema.org/]]
* also some history, Lenat built Cyc, which is a very complicated rule engine.
===== March 10, 2016 =====
* [[https://storage.googleapis.com/deepmind-data/assets/papers/DeepMindNature14236Paper.pdf|AlphGo]] how does it compare to my algorithm?
===== January 16, 2016 =====
* Clint suggested [[http://www.graphviz.org/doc/info/lang.html|Graph viz]] or the dot file format
===== November 20, 2015 =====
* Development Tasks
* first task is to create a Temperature based test case. Where 2 opposing corners are hot/cold. The Ai is a 3x3 square set of pixels and each pixel is a temperature sensor. The Ai can also move in a cardinal direction.
* Second task is to start targeting each Ai challenge found on a google search.
===== October 17, 2015 =====
* the brain is constantly on. Input, output, input, output. The desire system changes the output to cause the brain to keep moving forward, which also changes the environments input. The sleep state disables all input so that the brain can reach a stale/neutral state.
===== October 8, 2015 =====
* Neural Graph -- title for the patent.
* after talking with clint:
0 0 0 l1n1(1)
1 0 0 l1n2(1) -> l1n1(.66)+l1n2(1) -> l2n1(1)
0 1 0 l1n3(1) -> l1n1(.66)+l1n2(.33)+l1n3(1) -> l2n2(1) -> l2n1(?)+l2n2(1) -> l3n1(1)
* maybe related to [[https://www.google.com/search?q=neural+graph&oq=neural+graph&aqs=chrome..69i57.2664j0j7&sourceid=chrome&es_sm=93&ie=UTF-8|Graph Neural Networks]]
===== October 1, 2015 =====
* growing a Neural Network -- patent that.
* perception of time, it's just a cascading effect. a feedback loop.
* after reading this link, I was able to understand the solution I needed to have for true AI: http://stats.stackexchange.com/questions/39037/how-does-neural-network-recognise-images
===== September 29, 2015 =====
* I keep coming back to this. So with a neural network, if it is looking at several pictures and the pictures are varying degrees of similarity how does the neural network know what the percentage of similarity is to each of the pictures? Currently, I would believe that the process is that someone sitting there is inputting a value to each of the images and training the neural network. But what if we used a base image of 100% accuracy and then used an FFT to compare it to other knowns or unknowns then feed the resulting variable as the result the NN needs to obtain.
* http://arxiv.org/abs/1312.5851
* http://www2.compute.dtu.dk/~abll/blog/fft_based_cnn/
===== August 17, 2015 =====
* merge networks that are used to get to the same output. for example. I'm driving a car. I've determined that this specific place(image) means that I should accelerate. If I have a bunch of places that cause me to accelerate, merge the data sets into one and train a single network to know the result.
===== August 15, 2015 =====
* Show the list of decisions for each action, would allow me to tune the ai steering it to better choices.
===== June 15, 2015 =====
* [[https://www.youtube.com/watch?v=qv6UVOQ0F44|link]]
-- MarI/O by SethBling
-- Feel free to use this code, but please do not redistribute it.
-- Intended for use with the BizHawk emulator and Super Mario World or Super Mario Bros. ROM.
if gameinfo.getromname() == "Super Mario World (USA)" then
Filename = "DP1.state"
ButtonNames = {
"A",
"B",
"X",
"Y",
"Up",
"Down",
"Left",
"Right",
}
elseif gameinfo.getromname() == "Super Mario Bros." then
Filename = "SMB1-1.state"
ButtonNames = {
"A",
"B",
"Up",
"Down",
"Left",
"Right",
}
end
BoxRadius = 6
InputSize = (BoxRadius*2+1)*(BoxRadius*2+1)
Inputs = InputSize+1
Outputs = #ButtonNames
Population = 300
DeltaDisjoint = 2.0
DeltaWeights = 0.4
DeltaThreshold = 1.0
StaleSpecies = 15
MutateConnectionsChance = 0.25
PerturbChance = 0.90
CrossoverChance = 0.75
LinkMutationChance = 2.0
NodeMutationChance = 0.50
BiasMutationChance = 0.40
StepSize = 0.1
DisableMutationChance = 0.4
EnableMutationChance = 0.2
TimeoutConstant = 20
MaxNodes = 1000000
function getPositions()
if gameinfo.getromname() == "Super Mario World (USA)" then
marioX = memory.read_s16_le(0x94)
marioY = memory.read_s16_le(0x96)
local layer1x = memory.read_s16_le(0x1A);
local layer1y = memory.read_s16_le(0x1C);
screenX = marioX-layer1x
screenY = marioY-layer1y
elseif gameinfo.getromname() == "Super Mario Bros." then
marioX = memory.readbyte(0x6D) * 0x100 + memory.readbyte(0x86)
marioY = memory.readbyte(0x03B8)+16
screenX = memory.readbyte(0x03AD)
screenY = memory.readbyte(0x03B8)
end
end
function getTile(dx, dy)
if gameinfo.getromname() == "Super Mario World (USA)" then
x = math.floor((marioX+dx+8)/16)
y = math.floor((marioY+dy)/16)
return memory.readbyte(0x1C800 + math.floor(x/0x10)*0x1B0 + y*0x10 + x%0x10)
elseif gameinfo.getromname() == "Super Mario Bros." then
local x = marioX + dx + 8
local y = marioY + dy - 16
local page = math.floor(x/256)%2
local subx = math.floor((x%256)/16)
local suby = math.floor((y - 32)/16)
local addr = 0x500 + page*13*16+suby*16+subx
if suby >= 13 or suby < 0 then
return 0
end
if memory.readbyte(addr) ~= 0 then
return 1
else
return 0
end
end
end
function getSprites()
if gameinfo.getromname() == "Super Mario World (USA)" then
local sprites = {}
for slot=0,11 do
local status = memory.readbyte(0x14C8+slot)
if status ~= 0 then
spritex = memory.readbyte(0xE4+slot) + memory.readbyte(0x14E0+slot)*256
spritey = memory.readbyte(0xD8+slot) + memory.readbyte(0x14D4+slot)*256
sprites[#sprites+1] = {["x"]=spritex, ["y"]=spritey}
end
end
return sprites
elseif gameinfo.getromname() == "Super Mario Bros." then
local sprites = {}
for slot=0,4 do
local enemy = memory.readbyte(0xF+slot)
if enemy ~= 0 then
local ex = memory.readbyte(0x6E + slot)*0x100 + memory.readbyte(0x87+slot)
local ey = memory.readbyte(0xCF + slot)+24
sprites[#sprites+1] = {["x"]=ex,["y"]=ey}
end
end
return sprites
end
end
function getExtendedSprites()
if gameinfo.getromname() == "Super Mario World (USA)" then
local extended = {}
for slot=0,11 do
local number = memory.readbyte(0x170B+slot)
if number ~= 0 then
spritex = memory.readbyte(0x171F+slot) + memory.readbyte(0x1733+slot)*256
spritey = memory.readbyte(0x1715+slot) + memory.readbyte(0x1729+slot)*256
extended[#extended+1] = {["x"]=spritex, ["y"]=spritey}
end
end
return extended
elseif gameinfo.getromname() == "Super Mario Bros." then
return {}
end
end
function getInputs()
getPositions()
sprites = getSprites()
extended = getExtendedSprites()
local inputs = {}
for dy=-BoxRadius*16,BoxRadius*16,16 do
for dx=-BoxRadius*16,BoxRadius*16,16 do
inputs[#inputs+1] = 0
tile = getTile(dx, dy)
if tile == 1 and marioY+dy < 0x1B0 then
inputs[#inputs] = 1
end
for i = 1,#sprites do
distx = math.abs(sprites[i]["x"] - (marioX+dx))
disty = math.abs(sprites[i]["y"] - (marioY+dy))
if distx <= 8 and disty <= 8 then
inputs[#inputs] = -1
end
end
for i = 1,#extended do
distx = math.abs(extended[i]["x"] - (marioX+dx))
disty = math.abs(extended[i]["y"] - (marioY+dy))
if distx < 8 and disty < 8 then
inputs[#inputs] = -1
end
end
end
end
--mariovx = memory.read_s8(0x7B)
--mariovy = memory.read_s8(0x7D)
return inputs
end
function sigmoid(x)
return 2/(1+math.exp(-4.9*x))-1
end
function newInnovation()
pool.innovation = pool.innovation + 1
return pool.innovation
end
function newPool()
local pool = {}
pool.species = {}
pool.generation = 0
pool.innovation = Outputs
pool.currentSpecies = 1
pool.currentGenome = 1
pool.currentFrame = 0
pool.maxFitness = 0
return pool
end
function newSpecies()
local species = {}
species.topFitness = 0
species.staleness = 0
species.genomes = {}
species.averageFitness = 0
return species
end
function newGenome()
local genome = {}
genome.genes = {}
genome.fitness = 0
genome.adjustedFitness = 0
genome.network = {}
genome.maxneuron = 0
genome.globalRank = 0
genome.mutationRates = {}
genome.mutationRates["connections"] = MutateConnectionsChance
genome.mutationRates["link"] = LinkMutationChance
genome.mutationRates["bias"] = BiasMutationChance
genome.mutationRates["node"] = NodeMutationChance
genome.mutationRates["enable"] = EnableMutationChance
genome.mutationRates["disable"] = DisableMutationChance
genome.mutationRates["step"] = StepSize
return genome
end
function copyGenome(genome)
local genome2 = newGenome()
for g=1,#genome.genes do
table.insert(genome2.genes, copyGene(genome.genes[g]))
end
genome2.maxneuron = genome.maxneuron
genome2.mutationRates["connections"] = genome.mutationRates["connections"]
genome2.mutationRates["link"] = genome.mutationRates["link"]
genome2.mutationRates["bias"] = genome.mutationRates["bias"]
genome2.mutationRates["node"] = genome.mutationRates["node"]
genome2.mutationRates["enable"] = genome.mutationRates["enable"]
genome2.mutationRates["disable"] = genome.mutationRates["disable"]
return genome2
end
function basicGenome()
local genome = newGenome()
local innovation = 1
genome.maxneuron = Inputs
mutate(genome)
return genome
end
function newGene()
local gene = {}
gene.into = 0
gene.out = 0
gene.weight = 0.0
gene.enabled = true
gene.innovation = 0
return gene
end
function copyGene(gene)
local gene2 = newGene()
gene2.into = gene.into
gene2.out = gene.out
gene2.weight = gene.weight
gene2.enabled = gene.enabled
gene2.innovation = gene.innovation
return gene2
end
function newNeuron()
local neuron = {}
neuron.incoming = {}
neuron.value = 0.0
return neuron
end
function generateNetwork(genome)
local network = {}
network.neurons = {}
for i=1,Inputs do
network.neurons[i] = newNeuron()
end
for o=1,Outputs do
network.neurons[MaxNodes+o] = newNeuron()
end
table.sort(genome.genes, function (a,b)
return (a.out < b.out)
end)
for i=1,#genome.genes do
local gene = genome.genes[i]
if gene.enabled then
if network.neurons[gene.out] == nil then
network.neurons[gene.out] = newNeuron()
end
local neuron = network.neurons[gene.out]
table.insert(neuron.incoming, gene)
if network.neurons[gene.into] == nil then
network.neurons[gene.into] = newNeuron()
end
end
end
genome.network = network
end
function evaluateNetwork(network, inputs)
table.insert(inputs, 1)
if #inputs ~= Inputs then
console.writeline("Incorrect number of neural network inputs.")
return {}
end
for i=1,Inputs do
network.neurons[i].value = inputs[i]
end
for _,neuron in pairs(network.neurons) do
local sum = 0
for j = 1,#neuron.incoming do
local incoming = neuron.incoming[j]
local other = network.neurons[incoming.into]
sum = sum + incoming.weight * other.value
end
if #neuron.incoming > 0 then
neuron.value = sigmoid(sum)
end
end
local outputs = {}
for o=1,Outputs do
local button = "P1 " .. ButtonNames[o]
if network.neurons[MaxNodes+o].value > 0 then
outputs[button] = true
else
outputs[button] = false
end
end
return outputs
end
function crossover(g1, g2)
-- Make sure g1 is the higher fitness genome
if g2.fitness > g1.fitness then
tempg = g1
g1 = g2
g2 = tempg
end
local child = newGenome()
local innovations2 = {}
for i=1,#g2.genes do
local gene = g2.genes[i]
innovations2[gene.innovation] = gene
end
for i=1,#g1.genes do
local gene1 = g1.genes[i]
local gene2 = innovations2[gene1.innovation]
if gene2 ~= nil and math.random(2) == 1 and gene2.enabled then
table.insert(child.genes, copyGene(gene2))
else
table.insert(child.genes, copyGene(gene1))
end
end
child.maxneuron = math.max(g1.maxneuron,g2.maxneuron)
for mutation,rate in pairs(g1.mutationRates) do
child.mutationRates[mutation] = rate
end
return child
end
function randomNeuron(genes, nonInput)
local neurons = {}
if not nonInput then
for i=1,Inputs do
neurons[i] = true
end
end
for o=1,Outputs do
neurons[MaxNodes+o] = true
end
for i=1,#genes do
if (not nonInput) or genes[i].into > Inputs then
neurons[genes[i].into] = true
end
if (not nonInput) or genes[i].out > Inputs then
neurons[genes[i].out] = true
end
end
local count = 0
for _,_ in pairs(neurons) do
count = count + 1
end
local n = math.random(1, count)
for k,v in pairs(neurons) do
n = n-1
if n == 0 then
return k
end
end
return 0
end
function containsLink(genes, link)
for i=1,#genes do
local gene = genes[i]
if gene.into == link.into and gene.out == link.out then
return true
end
end
end
function pointMutate(genome)
local step = genome.mutationRates["step"]
for i=1,#genome.genes do
local gene = genome.genes[i]
if math.random() < PerturbChance then
gene.weight = gene.weight + math.random() * step*2 - step
else
gene.weight = math.random()*4-2
end
end
end
function linkMutate(genome, forceBias)
local neuron1 = randomNeuron(genome.genes, false)
local neuron2 = randomNeuron(genome.genes, true)
local newLink = newGene()
if neuron1 <= Inputs and neuron2 <= Inputs then
--Both input nodes
return
end
if neuron2 <= Inputs then
-- Swap output and input
local temp = neuron1
neuron1 = neuron2
neuron2 = temp
end
newLink.into = neuron1
newLink.out = neuron2
if forceBias then
newLink.into = Inputs
end
if containsLink(genome.genes, newLink) then
return
end
newLink.innovation = newInnovation()
newLink.weight = math.random()*4-2
table.insert(genome.genes, newLink)
end
function nodeMutate(genome)
if #genome.genes == 0 then
return
end
genome.maxneuron = genome.maxneuron + 1
local gene = genome.genes[math.random(1,#genome.genes)]
if not gene.enabled then
return
end
gene.enabled = false
local gene1 = copyGene(gene)
gene1.out = genome.maxneuron
gene1.weight = 1.0
gene1.innovation = newInnovation()
gene1.enabled = true
table.insert(genome.genes, gene1)
local gene2 = copyGene(gene)
gene2.into = genome.maxneuron
gene2.innovation = newInnovation()
gene2.enabled = true
table.insert(genome.genes, gene2)
end
function enableDisableMutate(genome, enable)
local candidates = {}
for _,gene in pairs(genome.genes) do
if gene.enabled == not enable then
table.insert(candidates, gene)
end
end
if #candidates == 0 then
return
end
local gene = candidates[math.random(1,#candidates)]
gene.enabled = not gene.enabled
end
function mutate(genome)
for mutation,rate in pairs(genome.mutationRates) do
if math.random(1,2) == 1 then
genome.mutationRates[mutation] = 0.95*rate
else
genome.mutationRates[mutation] = 1.05263*rate
end
end
if math.random() < genome.mutationRates["connections"] then
pointMutate(genome)
end
local p = genome.mutationRates["link"]
while p > 0 do
if math.random() < p then
linkMutate(genome, false)
end
p = p - 1
end
p = genome.mutationRates["bias"]
while p > 0 do
if math.random() < p then
linkMutate(genome, true)
end
p = p - 1
end
p = genome.mutationRates["node"]
while p > 0 do
if math.random() < p then
nodeMutate(genome)
end
p = p - 1
end
p = genome.mutationRates["enable"]
while p > 0 do
if math.random() < p then
enableDisableMutate(genome, true)
end
p = p - 1
end
p = genome.mutationRates["disable"]
while p > 0 do
if math.random() < p then
enableDisableMutate(genome, false)
end
p = p - 1
end
end
function disjoint(genes1, genes2)
local i1 = {}
for i = 1,#genes1 do
local gene = genes1[i]
i1[gene.innovation] = true
end
local i2 = {}
for i = 1,#genes2 do
local gene = genes2[i]
i2[gene.innovation] = true
end
local disjointGenes = 0
for i = 1,#genes1 do
local gene = genes1[i]
if not i2[gene.innovation] then
disjointGenes = disjointGenes+1
end
end
for i = 1,#genes2 do
local gene = genes2[i]
if not i1[gene.innovation] then
disjointGenes = disjointGenes+1
end
end
local n = math.max(#genes1, #genes2)
return disjointGenes / n
end
function weights(genes1, genes2)
local i2 = {}
for i = 1,#genes2 do
local gene = genes2[i]
i2[gene.innovation] = gene
end
local sum = 0
local coincident = 0
for i = 1,#genes1 do
local gene = genes1[i]
if i2[gene.innovation] ~= nil then
local gene2 = i2[gene.innovation]
sum = sum + math.abs(gene.weight - gene2.weight)
coincident = coincident + 1
end
end
return sum / coincident
end
function sameSpecies(genome1, genome2)
local dd = DeltaDisjoint*disjoint(genome1.genes, genome2.genes)
local dw = DeltaWeights*weights(genome1.genes, genome2.genes)
return dd + dw < DeltaThreshold
end
function rankGlobally()
local global = {}
for s = 1,#pool.species do
local species = pool.species[s]
for g = 1,#species.genomes do
table.insert(global, species.genomes[g])
end
end
table.sort(global, function (a,b)
return (a.fitness < b.fitness)
end)
for g=1,#global do
global[g].globalRank = g
end
end
function calculateAverageFitness(species)
local total = 0
for g=1,#species.genomes do
local genome = species.genomes[g]
total = total + genome.globalRank
end
species.averageFitness = total / #species.genomes
end
function totalAverageFitness()
local total = 0
for s = 1,#pool.species do
local species = pool.species[s]
total = total + species.averageFitness
end
return total
end
function cullSpecies(cutToOne)
for s = 1,#pool.species do
local species = pool.species[s]
table.sort(species.genomes, function (a,b)
return (a.fitness > b.fitness)
end)
local remaining = math.ceil(#species.genomes/2)
if cutToOne then
remaining = 1
end
while #species.genomes > remaining do
table.remove(species.genomes)
end
end
end
function breedChild(species)
local child = {}
if math.random() < CrossoverChance then
g1 = species.genomes[math.random(1, #species.genomes)]
g2 = species.genomes[math.random(1, #species.genomes)]
child = crossover(g1, g2)
else
g = species.genomes[math.random(1, #species.genomes)]
child = copyGenome(g)
end
mutate(child)
return child
end
function removeStaleSpecies()
local survived = {}
for s = 1,#pool.species do
local species = pool.species[s]
table.sort(species.genomes, function (a,b)
return (a.fitness > b.fitness)
end)
if species.genomes[1].fitness > species.topFitness then
species.topFitness = species.genomes[1].fitness
species.staleness = 0
else
species.staleness = species.staleness + 1
end
if species.staleness < StaleSpecies or species.topFitness >= pool.maxFitness then
table.insert(survived, species)
end
end
pool.species = survived
end
function removeWeakSpecies()
local survived = {}
local sum = totalAverageFitness()
for s = 1,#pool.species do
local species = pool.species[s]
breed = math.floor(species.averageFitness / sum * Population)
if breed >= 1 then
table.insert(survived, species)
end
end
pool.species = survived
end
function addToSpecies(child)
local foundSpecies = false
for s=1,#pool.species do
local species = pool.species[s]
if not foundSpecies and sameSpecies(child, species.genomes[1]) then
table.insert(species.genomes, child)
foundSpecies = true
end
end
if not foundSpecies then
local childSpecies = newSpecies()
table.insert(childSpecies.genomes, child)
table.insert(pool.species, childSpecies)
end
end
function newGeneration()
cullSpecies(false) -- Cull the bottom half of each species
rankGlobally()
removeStaleSpecies()
rankGlobally()
for s = 1,#pool.species do
local species = pool.species[s]
calculateAverageFitness(species)
end
removeWeakSpecies()
local sum = totalAverageFitness()
local children = {}
for s = 1,#pool.species do
local species = pool.species[s]
breed = math.floor(species.averageFitness / sum * Population) - 1
for i=1,breed do
table.insert(children, breedChild(species))
end
end
cullSpecies(true) -- Cull all but the top member of each species
while #children + #pool.species < Population do
local species = pool.species[math.random(1, #pool.species)]
table.insert(children, breedChild(species))
end
for c=1,#children do
local child = children[c]
addToSpecies(child)
end
pool.generation = pool.generation + 1
writeFile("backup." .. pool.generation .. "." .. forms.gettext(saveLoadFile))
end
function initializePool()
pool = newPool()
for i=1,Population do
basic = basicGenome()
addToSpecies(basic)
end
initializeRun()
end
function clearJoypad()
controller = {}
for b = 1,#ButtonNames do
controller["P1 " .. ButtonNames[b]] = false
end
joypad.set(controller)
end
function initializeRun()
savestate.load(Filename);
rightmost = 0
pool.currentFrame = 0
timeout = TimeoutConstant
clearJoypad()
local species = pool.species[pool.currentSpecies]
local genome = species.genomes[pool.currentGenome]
generateNetwork(genome)
evaluateCurrent()
end
function evaluateCurrent()
local species = pool.species[pool.currentSpecies]
local genome = species.genomes[pool.currentGenome]
inputs = getInputs()
controller = evaluateNetwork(genome.network, inputs)
if controller["P1 Left"] and controller["P1 Right"] then
controller["P1 Left"] = false
controller["P1 Right"] = false
end
if controller["P1 Up"] and controller["P1 Down"] then
controller["P1 Up"] = false
controller["P1 Down"] = false
end
joypad.set(controller)
end
if pool == nil then
initializePool()
end
function nextGenome()
pool.currentGenome = pool.currentGenome + 1
if pool.currentGenome > #pool.species[pool.currentSpecies].genomes then
pool.currentGenome = 1
pool.currentSpecies = pool.currentSpecies+1
if pool.currentSpecies > #pool.species then
newGeneration()
pool.currentSpecies = 1
end
end
end
function fitnessAlreadyMeasured()
local species = pool.species[pool.currentSpecies]
local genome = species.genomes[pool.currentGenome]
return genome.fitness ~= 0
end
function displayGenome(genome)
local network = genome.network
local cells = {}
local i = 1
local cell = {}
for dy=-BoxRadius,BoxRadius do
for dx=-BoxRadius,BoxRadius do
cell = {}
cell.x = 50+5*dx
cell.y = 70+5*dy
cell.value = network.neurons[i].value
cells[i] = cell
i = i + 1
end
end
local biasCell = {}
biasCell.x = 80
biasCell.y = 110
biasCell.value = network.neurons[Inputs].value
cells[Inputs] = biasCell
for o = 1,Outputs do
cell = {}
cell.x = 220
cell.y = 30 + 8 * o
cell.value = network.neurons[MaxNodes + o].value
cells[MaxNodes+o] = cell
local color
if cell.value > 0 then
color = 0xFF0000FF
else
color = 0xFF000000
end
gui.drawText(223, 24+8*o, ButtonNames[o], color, 9)
end
for n,neuron in pairs(network.neurons) do
cell = {}
if n > Inputs and n <= MaxNodes then
cell.x = 140
cell.y = 40
cell.value = neuron.value
cells[n] = cell
end
end
for n=1,4 do
for _,gene in pairs(genome.genes) do
if gene.enabled then
local c1 = cells[gene.into]
local c2 = cells[gene.out]
if gene.into > Inputs and gene.into <= MaxNodes then
c1.x = 0.75*c1.x + 0.25*c2.x
if c1.x >= c2.x then
c1.x = c1.x - 40
end
if c1.x < 90 then
c1.x = 90
end
if c1.x > 220 then
c1.x = 220
end
c1.y = 0.75*c1.y + 0.25*c2.y
end
if gene.out > Inputs and gene.out <= MaxNodes then
c2.x = 0.25*c1.x + 0.75*c2.x
if c1.x >= c2.x then
c2.x = c2.x + 40
end
if c2.x < 90 then
c2.x = 90
end
if c2.x > 220 then
c2.x = 220
end
c2.y = 0.25*c1.y + 0.75*c2.y
end
end
end
end
gui.drawBox(50-BoxRadius*5-3,70-BoxRadius*5-3,50+BoxRadius*5+2,70+BoxRadius*5+2,0xFF000000, 0x80808080)
for n,cell in pairs(cells) do
if n > Inputs or cell.value ~= 0 then
local color = math.floor((cell.value+1)/2*256)
if color > 255 then color = 255 end
if color < 0 then color = 0 end
local opacity = 0xFF000000
if cell.value == 0 then
opacity = 0x50000000
end
color = opacity + color*0x10000 + color*0x100 + color
gui.drawBox(cell.x-2,cell.y-2,cell.x+2,cell.y+2,opacity,color)
end
end
for _,gene in pairs(genome.genes) do
if gene.enabled then
local c1 = cells[gene.into]
local c2 = cells[gene.out]
local opacity = 0xA0000000
if c1.value == 0 then
opacity = 0x20000000
end
local color = 0x80-math.floor(math.abs(sigmoid(gene.weight))*0x80)
if gene.weight > 0 then
color = opacity + 0x8000 + 0x10000*color
else
color = opacity + 0x800000 + 0x100*color
end
gui.drawLine(c1.x+1, c1.y, c2.x-3, c2.y, color)
end
end
gui.drawBox(49,71,51,78,0x00000000,0x80FF0000)
if forms.ischecked(showMutationRates) then
local pos = 100
for mutation,rate in pairs(genome.mutationRates) do
gui.drawText(100, pos, mutation .. ": " .. rate, 0xFF000000, 10)
pos = pos + 8
end
end
end
function writeFile(filename)
local file = io.open(filename, "w")
file:write(pool.generation .. "\n")
file:write(pool.maxFitness .. "\n")
file:write(#pool.species .. "\n")
for n,species in pairs(pool.species) do
file:write(species.topFitness .. "\n")
file:write(species.staleness .. "\n")
file:write(#species.genomes .. "\n")
for m,genome in pairs(species.genomes) do
file:write(genome.fitness .. "\n")
file:write(genome.maxneuron .. "\n")
for mutation,rate in pairs(genome.mutationRates) do
file:write(mutation .. "\n")
file:write(rate .. "\n")
end
file:write("done\n")
file:write(#genome.genes .. "\n")
for l,gene in pairs(genome.genes) do
file:write(gene.into .. " ")
file:write(gene.out .. " ")
file:write(gene.weight .. " ")
file:write(gene.innovation .. " ")
if(gene.enabled) then
file:write("1\n")
else
file:write("0\n")
end
end
end
end
file:close()
end
function savePool()
local filename = forms.gettext(saveLoadFile)
writeFile(filename)
end
function loadFile(filename)
local file = io.open(filename, "r")
pool = newPool()
pool.generation = file:read("*number")
pool.maxFitness = file:read("*number")
forms.settext(maxFitnessLabel, "Max Fitness: " .. math.floor(pool.maxFitness))
local numSpecies = file:read("*number")
for s=1,numSpecies do
local species = newSpecies()
table.insert(pool.species, species)
species.topFitness = file:read("*number")
species.staleness = file:read("*number")
local numGenomes = file:read("*number")
for g=1,numGenomes do
local genome = newGenome()
table.insert(species.genomes, genome)
genome.fitness = file:read("*number")
genome.maxneuron = file:read("*number")
local line = file:read("*line")
while line ~= "done" do
genome.mutationRates[line] = file:read("*number")
line = file:read("*line")
end
local numGenes = file:read("*number")
for n=1,numGenes do
local gene = newGene()
table.insert(genome.genes, gene)
local enabled
gene.into, gene.out, gene.weight, gene.innovation, enabled = file:read("*number", "*number", "*number", "*number", "*number")
if enabled == 0 then
gene.enabled = false
else
gene.enabled = true
end
end
end
end
file:close()
while fitnessAlreadyMeasured() do
nextGenome()
end
initializeRun()
pool.currentFrame = pool.currentFrame + 1
end
function loadPool()
local filename = forms.gettext(saveLoadFile)
loadFile(filename)
end
function playTop()
local maxfitness = 0
local maxs, maxg
for s,species in pairs(pool.species) do
for g,genome in pairs(species.genomes) do
if genome.fitness > maxfitness then
maxfitness = genome.fitness
maxs = s
maxg = g
end
end
end
pool.currentSpecies = maxs
pool.currentGenome = maxg
pool.maxFitness = maxfitness
forms.settext(maxFitnessLabel, "Max Fitness: " .. math.floor(pool.maxFitness))
initializeRun()
pool.currentFrame = pool.currentFrame + 1
return
end
function onExit()
forms.destroy(form)
end
writeFile("temp.pool")
event.onexit(onExit)
form = forms.newform(200, 260, "Fitness")
maxFitnessLabel = forms.label(form, "Max Fitness: " .. math.floor(pool.maxFitness), 5, 8)
showNetwork = forms.checkbox(form, "Show Map", 5, 30)
showMutationRates = forms.checkbox(form, "Show M-Rates", 5, 52)
restartButton = forms.button(form, "Restart", initializePool, 5, 77)
saveButton = forms.button(form, "Save", savePool, 5, 102)
loadButton = forms.button(form, "Load", loadPool, 80, 102)
saveLoadFile = forms.textbox(form, Filename .. ".pool", 170, 25, nil, 5, 148)
saveLoadLabel = forms.label(form, "Save/Load:", 5, 129)
playTopButton = forms.button(form, "Play Top", playTop, 5, 170)
hideBanner = forms.checkbox(form, "Hide Banner", 5, 190)
while true do
local backgroundColor = 0xD0FFFFFF
if not forms.ischecked(hideBanner) then
gui.drawBox(0, 0, 300, 26, backgroundColor, backgroundColor)
end
local species = pool.species[pool.currentSpecies]
local genome = species.genomes[pool.currentGenome]
if forms.ischecked(showNetwork) then
displayGenome(genome)
end
if pool.currentFrame%5 == 0 then
evaluateCurrent()
end
joypad.set(controller)
getPositions()
if marioX > rightmost then
rightmost = marioX
timeout = TimeoutConstant
end
timeout = timeout - 1
local timeoutBonus = pool.currentFrame / 4
if timeout + timeoutBonus <= 0 then
local fitness = rightmost - pool.currentFrame / 2
if gameinfo.getromname() == "Super Mario World (USA)" and rightmost > 4816 then
fitness = fitness + 1000
end
if gameinfo.getromname() == "Super Mario Bros." and rightmost > 3186 then
fitness = fitness + 1000
end
if fitness == 0 then
fitness = -1
end
genome.fitness = fitness
if fitness > pool.maxFitness then
pool.maxFitness = fitness
forms.settext(maxFitnessLabel, "Max Fitness: " .. math.floor(pool.maxFitness))
writeFile("backup." .. pool.generation .. "." .. forms.gettext(saveLoadFile))
end
console.writeline("Gen " .. pool.generation .. " species " .. pool.currentSpecies .. " genome " .. pool.currentGenome .. " fitness: " .. fitness)
pool.currentSpecies = 1
pool.currentGenome = 1
while fitnessAlreadyMeasured() do
nextGenome()
end
initializeRun()
end
local measured = 0
local total = 0
for _,species in pairs(pool.species) do
for _,genome in pairs(species.genomes) do
total = total + 1
if genome.fitness ~= 0 then
measured = measured + 1
end
end
end
if not forms.ischecked(hideBanner) then
gui.drawText(0, 0, "Gen " .. pool.generation .. " species " .. pool.currentSpecies .. " genome " .. pool.currentGenome .. " (" .. math.floor(measured/total*100) .. "%)", 0xFF000000, 11)
gui.drawText(0, 12, "Fitness: " .. math.floor(rightmost - (pool.currentFrame) / 2 - (timeout + timeoutBonus)*2/3), 0xFF000000, 11)
gui.drawText(100, 12, "Max Fitness: " .. math.floor(pool.maxFitness), 0xFF000000, 11)
end
pool.currentFrame = pool.currentFrame + 1
emu.frameadvance();
end