added many implementation details and some clarifications

This commit is contained in:
Enrico Fasoli 2015-10-02 00:38:08 +02:00
parent ef5e7b6650
commit bb1af59e17

View File

@ -114,18 +114,6 @@ Examples:
- a "mouth" block that can communicate wether food is available to eat and can receive eat
commands at the same time
### Evaluating a machine's mind's iteration
for each iteration, the `stored signal` of each block is calculated using its connection with adiacent blocks.
This `new stored signal` is stored in a special variable without overwriting the `current stored signal`
so that the process can be easily accomplished in multithreading execution environments.
After all the `new stored signals` have been calculated, their value is applied to the `current stored signal`
and the calculation process is repeated. This is done to encourage parallel computing.
__Note:__ the bigger a machine, the slower it reacts to signals because they need more time to travel through the body
### Reproduction and evolution
This requires two action blocks:
@ -150,7 +138,6 @@ This requires some new blocks:
- the energy drain block
- the generator block
- the stomach block
- the energy drain block sucks energy from a structure's batteries.
- the battery block stores energy and emits the current level to its connections
- the generator block uses up a lot of energy, then gives back slightly more
@ -162,7 +149,7 @@ This requires some new blocks:
- each action block uses up a moderate amount of energy when activated
- each sensor block uses up a small amount of energy when activated
## Fitness of a structure
### Fitness of a structure
The fitness is calculated by dividing the creature's total harvested energy by the creature's total consumed energy.
@ -177,6 +164,21 @@ This method to calculate fitness has many problems:
The conclusion is that this system is far too complex to consider fitness evaluation.
### Complexity of a structure
The complexity of a structure is:
- if the fitness is `> 0`: the sum of the complexity of all its blocks.
- if the fitness is `<= 0`: 0
Complexity of a block starts at 0, then:
- increases by 1 for every not null connection of the block, if the block is an input block
- increases by x for every output block, depending on the specific block
The point of structure complexity is to try and approximately figure out how computationally expensive it is
to compute an itearation of the simulation for the structure
## Primordial world
The world should be composed of a variety of huge, small and anything in between energy farming or storage
@ -201,14 +203,18 @@ even early in an implementation. We __don't__ want to lose good machines!
## Interface
- navigate world
It is very important to give the user the ability to see the world in motion.
The interface should be structured akin to the following guidelines:
- a world navigation screen
- lets the user create an empty structure (needs at least 1 block)
- navigate structure
- structure navigation screen
- ability to save the structure to file
- has a small _selected block_ sidebar with block informaton
- lets the user clear cells or set a block to them
- view block
- provides all info about the block and maybe signal activity monitoring
- block navigation screen
- provides all info about the block and signal activity information
- lets the user view all connections and edit them
- lets the user edit the block type, preserving the connections
@ -217,3 +223,52 @@ A sidebar has controls to handle simulation speed and pausing and other informat
- current CPU load.
- available energy in the world and amount being generated
- population information
## Implementation
The rust programming language is the best suited for a variety of reasons, namely:
- it is a fast language, well suited for performance intensive tasks
- it has a package manager that allows a programmer to focus on writing the code, not
desiging infrastructure, build systems, or coding functions already available in popular libraries
- it produces native, multiplatform binaries
- it obviously supports all the required features for the implementation of the simulation
But most importantly:
- it is built with a focus on type safety, concurrency and thread safety
- it's impossible to compile a thread unsafe concurrent program with the rust reference compiler
### Simulation iteration evaluation algorithm
- __MT__: main thread, controls the flow, HIGHEST PRIORITY
- __WT__: worker thread, evaluates a simulation iteration for one or more structures
- __AT__: applier threads, applies actions and writes the `new stored signal` into the `current stored signal`
for all blocks
One tick is evaluated using the following algorithm:
1. __MT__
- rebalances the __WTs__ work load, evaluating it based on structure complexity
- assignes newborn structures to the workers
- starts all the workers
1. __WTs__ work, __MT__ waits until they are done
1. __MT__ assigns actions returned by all the __WTs__ to a number of __ATs__
- tries to balance the __ATs__' work
- groups events from creatures that interact with each other together, keeping it thread safe but as distributed
across threads as possible
1. __ATs__ work, __MT__ waits untile they are done
It's probably not as fast as it gets, but it should be decent
#### Structure iteration evaluation algorithm
1. the `new stored signal` of each block is calculated
- if the block is a neuron block, calculate its `new stored signal` using immutable references to the other blocks
and the connection values.
- if the block is an input block, run its logic to figure out what its output should be
- if the block is an output block, add the action it should perform to the action queue
- This `new stored signal` is stored in a special variable without overwriting the `current stored signal`
so that the process can be easily accomplished in multithreading execution environments.
__Note:__ the bigger a machine, the slower it reacts to inputs because signals need more time to travel through the body