Coder Social home page Coder Social logo

exouxas / fosterscript.core Goto Github PK

View Code? Open in Web Editor NEW
1.0 1.0 0.0 262 KB

A flexible NEAT-based neural network library for .NET, empowering intelligent agents in research, games, and AI simulations.

License: MIT License

C# 100.00%
ai evolutionary-algorithm neat-algorithm neural-network neuro-evolution

fosterscript.core's Introduction

FosterScript.Core

FosterScript.Core is a C# library that provides a framework for genetic evolution of virtual species. It is designed to facilitate the implementation of the Neuroevolution of Augmenting Topologies (NEAT) algorithm, while offering high flexibility and dynamic behavior.

Key Features

The essential features of this library is:

  • Scriptable neurons: FosterScript.Core allows you to create custom neuron types with different calculations, enabling the development of novel neural network architectures.
  • Scriptable modules: Modules are components that enhance the functionality of agents. You can define and add custom modules to your agents to incorporate specific behaviors and capabilities.
  • Propagation: The library supports signal propagation where neurons transmit signals in discrete steps, allowing for back-propagation and introducing a realistic delay between input and output.

Planned Usage

I am planning to develop a server-hosted implementation of FosterScript.Core, featuring a web-based graphical user interface. This implementation will provide a live view of the agents' survival attempts, showcasing their adaptation to dynamic events. It will serve as a tool for researchers, game developers, and individuals interested in learning about neural networks and genetic algorithms.

Inspiration

FosterScript.Core was inspired by a video from David Randall Miller, which explores various aspects of neural networks and genetic evolution. You can watch the video here. The video covers topics such as neural network structure, diverse input and output nodes, weighting systems, and network visualization.

Getting Started

To integrate FosterScript.Core into your project, please refer to the implementation guide for detailed instructions.

Examples

The FosterScript.Examples repository contains several examples demonstrating the usage of FosterScript.Core. You can explore these examples to gain insights into implementing the framework in your own projects.

Best Practices

When creating custom modules, it is recommended to follow the best practice of inheriting the Module base class. Here's an example illustrating the inheritance:

public class ExampleModule : Module
{
    // Inherited Properties
    public override string Name => "Example module";
    public override int[] Version => new int[] { 1, 0, 0 };

    // Custom Properties
    public double StoredSample
    {
        get { return _storedSample; }
        set
        {
            if (value <= 0)
            {
                // Example of how to terminate the host actor
                Body?.Kill();
            }
            _storedSample = value;
        }
    }
    private double _storedSample;

    public ExampleModule() : base()
    {
        // Pre-initialization code
    }

    public override void Initialize()
    {
        // Perform initialization tasks, including adding input and output neurons.
    }

    public override void Think()
    {
        // Observation phase: Add logic for observing the environment, such as distance calculations with other actors.
    }

    public override void Act()
    {
        // Action phase: Execute planned interactions or behaviors.
    }
}

Definitions

For detailed definitions and explanations of key terms used throughout the framework, please refer to the DEFINITIONS.md file. This document provides comprehensive descriptions of concepts such as modules, nodes, neural connections, actors, and more. It serves as a valuable resource for gaining a deeper understanding of the framework's components and their interactions.

fosterscript.core's People

Contributors

exouxas avatar

Stargazers

 avatar

Watchers

 avatar

fosterscript.core's Issues

Milestone 2 - Everything needed for publishing the repo

All classes required for making the MVP for a functioning AI:

  • NeuralNetwork.Brain.cs
  • Agents.Learner.cs
  • Environments.FiniteWorld.cs
  • Dependency.cs

Descriptions

Brain.cs

Contains a list or lists of nodes, and calculates these. Nodes contain a "Calculate" and a "Propagate" method, these will be in Brain.cs too, and will start a propagation process and a calculation process. Both will be threaded, but the methods will be synchronized to make using them easier (calling Propagate() should act the same as if it wasn't threaded, but have the

Learner.cs

An Actor.cs with a Brain.cs in it.

FiniteWorld.cs

An instance of this contains several Actors (which can be Learners in the future, as Actor is the superclass of Learner), and allows for those Actors to interact with and perceive their surroundings. Will run without an integrated clock cycle, and instead finish ASAP. If it's very similar to IndefiniteWorld.cs, then some functionality should either be moved over to World.cs or be implemented directly from IndefiniteWorld.cs through inheritance.

Dependency.cs

Allows an inheriting class to be dependent on in other classes. This is to make the dynamic loader possible without crashing if one file is missing.

GPU optimized calculations

I would like for the project to be able to use GPU-optimized calculations. Mainly for when you make a hidden node, but possibly also for improving the performance of the future "position based optimization" that will be added to worlds in #15

Position based optimization

A way for actors to effectively know what other actors are nearby to perceive or act on.

The World classes will be made without this optimization first, and later upgraded using this issue.

The idea is to create a class that acts as a collection, where each entity is forced to have some sort of position. It uses this position data to effectively store the locations of all the entities and has methods for grabbing all entities within a radius of another entity.

Refs:
https://programming.guide/robin-hood-hashing.html
https://www.nuget.org/packages/Faster.Map#readme-body-tab
https://doc.cgal.org/latest/Orthtree/index.html#Chapter_Orthtree

Make compilation work for both .NET 6 and .NET 7

We need to create a list of .NET versions to compile with. I want this project to be compatible with at least the following:

  • The newest LTS version
  • The newest version

Any other versions will be kept up to date until it becomes too annoying to do so.

There are also vague plans to convert this project to C++ or something that might improve performance.

Create method of grabbing nearby actors

The World class needs a way to grab all actors within a specified range for when implementing a sensing module for actors.

This does not have to be optimized, as optimization will be done in #15

Fix unsafe module addition

When adding modules using the method that adds single modules, it doesn't check if the module has all its needed dependencies. In addition to this, if it can't initialize, it will never be initialized.

  • Make sure the module has all dependencies before initializing
  • Throw an exception if the module is missing a dependency during initialization
  • In general find ways to make this safer

Restructuring namespaces

Current structure:

  • Core
    • Nodes
      • Neuron.cs
      • InputNode.cs
      • HiddenNode.cs
      • OutputNode.cs
      • NeuralConnection.cs
    • Loader.cs
  • Actor.cs
  • Learner.cs
  • Module.cs

I'd like to separate the namespaces into somethinglike this:

  • Core
    • NeuralNetwork
      • Neuron.cs
      • InputNode.cs
      • HiddenNode.cs
      • OutputNode.cs
      • NeuralConnection.cs
      • Brain.cs
    • Agents
      • Actor.cs
      • Learner.cs
      • Module.cs
    • Environments
      • World.cs
      • IndefiniteWorld.cs
      • FiniteWorld.cs
    • Loader.cs

So to fix this I need to figure out the following:

  • Core name? Keep it as core? Remove the namespace? Rename the repo to FosterScript.Core?
  • Collective name for the actor, learner, and module classes.
  • Collective name for the world classes.

Add world wrapping

Correcting position using MoveTo can be complex or, worse, recursive. Add a way to set bounds of the World class, with features for both boundaries blocking or repeating as an option.

Milestone 1 - Prep for hardcoding

All classes required for making the MVP for a hardcoded "AI":

  • Agents.Actor.cs
  • Agents.Module.cs
  • Environments.World.cs
  • Environments.IndefiniteWorld.cs

Descriptions

Actor.cs

Takes functionality from the Module subclasses added to its module "reservior". Needs to be able to function in a World.

Module.cs

The logic for when an Actor needs to sense something or act on something in a World.

World.cs

The basis for both IndefiniteWorld.cs and FiniteWorld.cs. Needs more description I think.

IndefiniteWorld.cs

An instance of this contains several Actors (which can be Learners in the future, as Actor is the superclass of Learner), and allows for those Actors to interact with and perceive their surroundings. Will have an integrated clock cycle, run on a thread, and not have a definite time to stop. The FiniteWorld.cs class will be the altered version of this that runs X cycles.

Functionalities needed:

  • JSON (or other type of serialization) for save/load/reuse. This one seems complicated due to the interconnectedness of the classes, so it will be its own issue.

Use HashSet instead of Dictionary

When checking for dependencies, use HashSet instead of Dictionary—supposed to be faster. Won't make a difference if all agents have the same modules all the time, but if the amount of modules is variable per actor basis, it should help with the performance.

Indefinite world never runs

The IndefiniteExample.cs file creates all actors and fills them with the correct modules, but running the world.Start() method doesn't make it actually run.

It seems like something might be wrong with the timer inside the IndefiniteWorld class.

Module dependencies

Dependency.cs

Allows an inheriting class to be dependent on in other classes. This is to make the dynamic loader possible without crashing if one file is missing.

Create tests

The project should have tests created for as many testable cases as possible to make sure everything is functional.

Clean project

Before publishing the repo, clean up the code and repo.

  • Remove unused imports
  • Sort properties, fields, constructors, methods etc
  • Add XML to everything that's public
  • Add comments to the code
  • Verify formatting
  • Add descriptions to all issues
  • Remove stale or unneeded issues
  • Clean branches
  • Clean/remove "GitHub Projects"
  • Separate examples into their own projects
  • Fix as many warnings and messages as possible
  • Fix accessors for all classes, variables, and methods

Continuous Integration

Create GitHub action to automatically compile the code that gets committed to the main branch, or when a pull request is made to the main branch.

Improve folder structure

There's definitely some improvement to be done on the folder structure of the project. When building and packaging, it outputs to ./src/Core/* while it should probably output to ./.

Basic world system with the World and IndefiniteWorld classes

Here are a few different ways of structuring the World related classes (and potentially probably interfaces). World will optimize Actor calculation by limiting operations based on proximity. At first I think it should just be made the simplest way possible with no optimization, but careful thought should be used for how to structure it still as this project definitely needs optimization later. Optimization will be done in #15.

How to handle positions of actors

Storing position values could use one of three strategies:

  1. Store position as properties in Actor.
  2. Store position as properties inside a Module included in an Actor.
  3. Store position in a list or dictionary in the World.

Option 1

Actors should not need to have a position. Other applications may use this neural network, which might not need positions, so forcing every actor to have a position would be wrong. Position related calculation optimization would not work if all actors were on the same point, but creating this optimization would only be relevant if the actors need a position.

Option 2

When using the module approach, removing the module to remove the positions would be easy. Still, it might break the code depending on how the calculation optimization is written.

Option 3

However, using the third option, where positions are stored in the world, then the world will define everything position related. And the modules for movement etc., would either need to be extra generic or maybe even written inside the world class used.

When a world calls on the actors' methods to think and act, the actor can have a property that tells the world how long its sensory and motor/acting range is. This would make it possible for the world to decide which actors can perceive or act on other actors. Greatly expands the possibility for custom world systems.

Conclusion

Using the module strategy would align with the project's original vision, but this could be more challenging. On the other hand, using the direct property strategy would be incredibly easy but would not align as well with the direction this project is heading.

The third option seems more and more in line with the vision of the project. This will be attempted, and the result will decide wether or not it's a good method.

IndefiniteWorld.cs

An instance of this contains several Actors (which can be Learners in the future, as Actor is the superclass of Learner) and allows those Actors to interact with and perceive their surroundings. It will have an integrated clock cycle, run on a thread, and not have a definite time to stop. The FiniteWorld.cs class will be the altered version of this that runs X cycles, specified in #11.

Structure idea:

This structure has World as a superclass that implements a container for the Actors.

    flowchart LR
    world[World]
    worldf[FiniteWorld]
    worldi[IndefiniteWorld]
    
    worldi-->world
    worldf-->world
Loading

World could have the methods Think() and Act(), which would trigger its inhabitants' respective methods.

Although having a third dimension would increase computation time when it might not be needed, for example, if you're only using two of the dimensions, it would make it a lot easier to just force all positions to always be in 3d, so we will do this.

Actors extendible by Modules

Actor.cs

Takes functionality from the Module child classes added to its module "reservior". Needs to be able to function in a World.

Modules used to extend Actors

Module

The logic for when an Actor needs to sense something or act on something in a World.

Dependencies

Need to figure out a smart way to do dependencies. The idea was to have a list of the Dependency class, but this seems weird as it's abstract and means we'd need to add an instance of a complete module for it to work. Maybe a list of classes instead, and versions that go with them?

Make NuGet package workflow

I haven't looked enough into this, but I would like there to be a workflow that automatically makes a NuGet package of this library whenever there's a new version. Maybe with automatic versioning?

I'll have to research how others do it to see what is common.

Fix null related warnings

The serialization implementation adds a bunch of warnings. Attempt to get rid of them:

  • CS8600
  • CS8601
  • CS8605
  • CS8618

Finish or remove IMPLEMENTATION.md

The file was meant to show how to use the library, but now that there will be an example repo, this might not be needed.

If it's still needed, fill the entire description

Create some way to access actor position within a module

There needs to be a way for Module to access their actors position. Consider some different approaches, and implement the best suited one.

Some options:

  • Public method in Actor that gets the position from the World it's contained in.
  • Making the _world field public.

Considering that I would like to change World into not having positions stored, and instead have a subclass for positioning, the following are the drawbacks of each approach:

  • Public method in Actor that gets the position from the World it's contained in: Having tight coupling wouldn't work, as not every Actor would be in a world with positions for its actors.
  • Making the _world field public: I believe this would only cause issues within a Module if the referenced world doesn't cast to a world subclass with positioning.

Both of these approaches could be fixed by making a subclass of Actor, and implementing one of the suggested approaches. Might be an idea to also create a subclass of Module in this case.

"Liquid" neurons

Basically create a set of neurons or a neuron that can mimic any other neuron, and let it decide whether it needs to calculate or not, maybe disable all following neurons' calculations for one step.

Disabling the following neurons could be difficult or problematic, since this neural net will have the possibility of backpropagation.

Has to be discussed more before working on it, but keep the thought vaguely in mind while designing the brain system.

FiniteWorld to do "sets" of AIs instead of a concurrent world

FiniteWorld.cs

An instance of this contains several Actors (which can be Learners in the future, as Actor is the superclass of Learner), and allows for those Actors to interact with and perceive their surroundings. Will run without an integrated clock cycle, and instead finish ASAP. If it's very similar to IndefiniteWorld.cs, then some functionality should either be moved over to World.cs or be implemented directly from IndefiniteWorld.cs through inheritance.

Script loading during runtime

Use the Roslyn runtime compiler to load modules during runtime

  • Observe a folder (and its subfolders, preferably recursively) using FileSystemWatcher
  • Load any new file, unload removed files
  • Sort the classes based on a list of types, and cache the classes
  • Generate instances of said classes using a method

Brain to contain and manage the neural network

Brain.cs

Contains a list or lists of nodes, and calculates these. Nodes contain a "Calculate" and a "Propagate" method, these will be in Brain.cs too, and will start a propagation process and a calculation process. Both will be threaded, but the methods will be synchronized to make using them easier (calling Propagate() should act the same as if it wasn't threaded, but have the calculation(s) have the benefit of threading)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.