3 releases (breaking)

0.3.0 Oct 1, 2022
0.2.0 Jan 16, 2022
0.1.0 Jan 13, 2022

#759 in Programming languages

MIT/Apache

105KB
2.5K SLoC

AIVM

Artificial intelligence that embraces the hardware it runs on.

Instead of relying on huge matrix multiplications and non-linear activation functions, AIVM uses a virtual machine with trainable code to directly drive its decision making. The code can be compiled into native machine code, removing an expensive layer of abstraction from typical artificial intelligence agents.

Agent structure

An agent has the following components:

  • Thread The thread that runs the machine code.
  • Memory The short and long term memory of the agent. Also used to pass sensory input and read output.
  • Stack A space for local variables in functions (see below). It consists of 64 8 byte values.
  • Code A collection of functions with one entry point. Functions have no arguments and do not return values, it is expected that information is shared through the memory. The entry point is executed once at each step, which is similar to a forward pass.

Code generation

Each program has the following parameters:

  • Memory The initial values for the agent's memory, in 8 byte chunks.
  • Code string A string of 64 bit values that is used to generate the actual code.

A mix of integer, bitwise, call, load/store and conditional branch instructions is used. Infinite loops are prevented by only allowing a branch to jump to a later part in the same function, and by making recursive function calls impossible.

For details of instruction encoding, check compile.rs.


lib.rs:

Artificial intelligence that embraces the hardware it runs on.

Instead of relying on huge matrix multiplications and non-linear activation functions, AIVM uses a virtual machine with trainable code to directly drive its decision making. The code can be compiled into native machine code, removing an expensive layer of abstraction from typical artificial intelligence agents.

Quick start

use aivm::{codegen, Compiler, Runner};

const LOWEST_FUNCTION_LEVEL: u32 = 1;
const MEMORY_SIZE: u32 = 4;
const INPUT_SIZE: u32 = 4;
const OUTPUT_SIZE: u32 = 4;

let gen = codegen::Interpreter::new();
let mut compiler = Compiler::new(gen);

// TODO: train code and memory to make it do something useful.
let code = [0; 16];
let mut runner = compiler.compile(
    &code,
    LOWEST_FUNCTION_LEVEL,
    MEMORY_SIZE,
    INPUT_SIZE,
    OUTPUT_SIZE,
);
let mut memory = [0; (MEMORY_SIZE + INPUT_SIZE + OUTPUT_SIZE) as usize];

runner.step(&mut memory);

Dependencies

~0–1.6MB
~33K SLoC