summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ctx.rs76
-rw-r--r--src/main.rs10
-rw-r--r--src/quad.rs30
-rw-r--r--src/step.rs7
4 files changed, 90 insertions, 33 deletions
diff --git a/src/ctx.rs b/src/ctx.rs
index 90d6c15..29161f2 100644
--- a/src/ctx.rs
+++ b/src/ctx.rs
@@ -1,32 +1,74 @@
use std::marker::PhantomData;
use crate::quad::{Quad, Node, Embed};
+pub trait Approx<A: Embed, B: Embed, S>: Default {
+ fn color_base(state: &mut S, base: A) -> [u8; 4];
+
+ fn compress_node(state: &mut S, compr: [B; 4]) -> B;
+ fn expand_node(state: &mut S, compr: B) -> [B; 4];
+
+ fn compress_base(state: &mut S, embed: A) -> B;
+ fn expand_base(state: &mut S, compr: B) -> A;
+}
+
+#[derive(Default)]
+pub struct Basic;
+
+impl Approx<u8, u8, ()> for Basic {
+ fn color_base(state: &mut (), base: u8) -> [u8; 4] {
+ [base;4]
+ }
+
+ fn compress_node(state: &mut (), c: [u8; 4]) -> u8 {
+ c[0]/4 + c[1]/4 + c[2]/4 + c[3]/4
+ }
+
+ fn expand_node(state: &mut (), compr: u8) -> [u8; 4] {
+ [compr;4]
+ }
+
+ fn compress_base(state: &mut (), embed: u8) -> u8 {
+ embed
+ }
+
+ fn expand_base(state: &mut (), compr: u8) -> u8 {
+ compr
+ }
+}
+
/// Represents a context with shared state.
-#[derive(Default, Debug)]
-pub struct Ctx<A: Embed, B: Embed> {
+#[derive(Debug)]
+pub struct Ctx<A: Embed, B: Embed, S, N: Approx<A, B, S>> {
_phantom_a: PhantomData<A>,
_phantom_b: PhantomData<B>,
+ state: S,
+ networks: N,
}
-impl<A: Embed, B: Embed> Ctx<A, B> {
+impl<A: Embed, B: Embed, S, N: Approx<A, B, S>> Ctx<A, B, S, N> {
/// Creates a new uninitialized context.
- pub fn new_empty() -> Self {
- Default::default()
+ pub fn new(state: S, networks: N) -> Self {
+ Ctx {
+ _phantom_a: PhantomData,
+ _phantom_b: PhantomData,
+ state,
+ networks,
+ }
}
- /// Combines 4 child node representations into a single representation
- /// Using a neural network.
- pub fn combine(&mut self, compr: [B; 4]) -> B {
- todo!("Build new B from 4 child B");
+ pub fn color_base(&mut self, base: A) -> [u8; 4] {
+ N::color_base(&mut self.state, base)
}
/// Compresses a base-level cell into a vector.
pub fn compress_base(&mut self, base: A) -> B {
- todo!("Turn Base Cell into a vector B");
+ N::compress_base(&mut self.state, base)
}
- pub fn color_base(&mut self, base: &A) -> [u8; 4] {
- todo!();
+ /// Combines 4 child node representations into a single representation
+ /// Using a neural network.
+ pub fn compress_node(&mut self, compr: [B; 4]) -> B {
+ N::compress_node(&mut self.state, compr)
}
/// Compresses a single node into a vector representation.
@@ -36,7 +78,7 @@ impl<A: Embed, B: Embed> Ctx<A, B> {
match quad {
Quad::Base(b) => Some(self.compress_base(*b)),
Quad::Node(n) => Some(
- self.combine([
+ self.compress_node([
n[0].compr,
n[1].compr,
n[2].compr,
@@ -48,12 +90,12 @@ impl<A: Embed, B: Embed> Ctx<A, B> {
}
/// Compresses a base-level cell into a vector.
- fn expand_base(&mut self, compr: B) -> A {
- todo!("Turn compressed B into the A that made it");
+ pub fn expand_base(&mut self, compr: B) -> A {
+ N::expand_base(&mut self.state, compr)
}
- fn expand_node(&mut self, compr: B) -> [B; 4] {
- todo!("Turn compressed B into 4 child B that made it");
+ pub fn expand_node(&mut self, compr: B) -> [B; 4] {
+ N::expand_node(&mut self.state, compr)
}
/// Expands the compressed representation of a node into a node with 4 children.
diff --git a/src/main.rs b/src/main.rs
index 3078f49..6134893 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -6,9 +6,15 @@ mod render;
fn main() {
println!("Warming up...");
- let mut ctx = ctx::Ctx::new_empty();
+ let mut ctx = ctx::Ctx::new((), ctx::Basic);
+
+ let mut base = vec![];
+ for i in 0..16 {
+ base.push(i);
+ }
+
let quad: quad::Node<u8, u8> = quad::Node::new_from_square(
- &mut ctx, vec![0xFF;64],
+ &mut ctx, base,
);
// render::graphics();
diff --git a/src/quad.rs b/src/quad.rs
index 2eb23b1..0ce8b58 100644
--- a/src/quad.rs
+++ b/src/quad.rs
@@ -1,7 +1,7 @@
-use crate::ctx::Ctx;
+use crate::ctx::{Ctx, Approx};
pub trait Embed: Default + Copy + Sized + std::fmt::Debug {
-
+
}
/// Represents the data present in a quad-tree node.
@@ -32,7 +32,12 @@ pub struct Node<A: Embed, B: Embed> {
}
impl<A: Embed, B: Embed> Node<A, B> {
- pub fn sample_color(self, ctx: &mut Ctx<A, B>, x: isize, y: isize) -> (Self, [u8; 4]) {
+ pub fn sample_color<S, N: Approx<A, B, S>>(
+ self,
+ ctx: &mut Ctx<A, B, S, N>,
+ x: isize,
+ y: isize,
+ ) -> (Self, [u8; 4]) {
// self = ctx.expand(self);
// if let Quad::Base(b) = self.data {
// return (self, ctx.color_base(&b));
@@ -54,12 +59,12 @@ impl<A: Embed, B: Embed> Node<A, B> {
}
/// Creates a new tree with a single empty base node
- pub fn new_empty(ctx: &mut Ctx<A, B>) -> Self {
+ pub fn new_empty<S, N: Approx<A, B, S>>(ctx: &mut Ctx<A, B, S, N>) -> Self {
Self::new_base(ctx, Default::default())
}
/// Creates a new tree from a single base node
- pub fn new_base(ctx: &mut Ctx<A, B>, base: A) -> Self {
+ pub fn new_base<S, N: Approx<A, B, S>>(ctx: &mut Ctx<A, B, S, N>, base: A) -> Self {
Node {
depth: 0,
compr: ctx.compress_base(base),
@@ -67,7 +72,7 @@ impl<A: Embed, B: Embed> Node<A, B> {
}
}
- pub fn new_node(ctx: &mut Ctx<A, B>, children: [Node<A, B>;4]) -> Self {
+ pub fn new_node<S, N: Approx<A, B, S>>(ctx: &mut Ctx<A, B, S, N>, children: [Node<A, B>;4]) -> Self {
// Make sure the depths check out
assert_eq!(children[0].depth, children[1].depth);
assert_eq!(children[1].depth, children[2].depth);
@@ -88,8 +93,8 @@ impl<A: Embed, B: Embed> Node<A, B> {
}
}
- fn build_square(
- ctx: &mut Ctx<A, B>,
+ fn build_square<S, N: Approx<A, B, S>>(
+ ctx: &mut Ctx<A, B, S, N>,
square: &[A],
abs_size: usize,
depth: usize,
@@ -106,16 +111,17 @@ impl<A: Embed, B: Embed> Node<A, B> {
let half = size / 2;
// in a z-like pattern
let children = [
- Self::build_square(ctx, square, abs_size, depth - 1, x + half, y ),
Self::build_square(ctx, square, abs_size, depth - 1, x , y ),
- Self::build_square(ctx, square, abs_size, depth - 1, x + half, y + half),
+ Self::build_square(ctx, square, abs_size, depth - 1, x + half, y ),
Self::build_square(ctx, square, abs_size, depth - 1, x , y + half),
+ Self::build_square(ctx, square, abs_size, depth - 1, x + half, y + half),
+
];
Self::new_node(ctx, children)
}
}
- pub fn new_from_square(ctx: &mut Ctx<A, B>, square: Vec<A>) -> Self {
+ pub fn new_from_square<S, N: Approx<A, B, S>>(ctx: &mut Ctx<A, B, S, N>, square: Vec<A>) -> Self {
// get the side length, ensure this is a pow2 square
let area = square.len();
let size = ((area as f64).sqrt() + 0.5) as usize;
@@ -135,7 +141,7 @@ impl<A: Embed, B: Embed> Node<A, B> {
/// Creates a new node double the size by centering the current node
/// on a node double the size.
- pub fn pad_empty(self, ctx: &mut Ctx<A, B>) -> Self {
+ pub fn pad_empty<S, N: Approx<A, B, S>>(self, ctx: &mut Ctx<A, B, S, N>) -> Self {
todo!()
}
}
diff --git a/src/step.rs b/src/step.rs
index 7010bd9..35d4328 100644
--- a/src/step.rs
+++ b/src/step.rs
@@ -1,7 +1,10 @@
-use crate::ctx::Ctx;
+use crate::ctx::{Ctx, Approx};
use crate::quad::{Node, Embed};
-pub fn step<A: Embed, B: Embed>(ctx: &mut Ctx<A, B>, node: Node<A, B>) -> Node<A, B> {
+pub fn step<A: Embed, B: Embed, S, N: Approx<A, B, S>>(
+ ctx: &mut Ctx<A, B, S, N>,
+ node: Node<A, B>
+) -> Node<A, B> {
// pad the graph if needed.
// if we're at the base, run the cellular automation rule: