about summary refs log tree commit diff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--build.zig5
-rw-r--r--src/monkey_brain/multi_layer_perceptron.zig0
-rw-r--r--src/monkey_brain/neural_network/layer.zig5
-rw-r--r--src/monkey_brain/neural_network/neuron.zig56
-rw-r--r--src/monkey_brain/perceptron.zig16
-rw-r--r--src/monkey_brain/test.zig9
6 files changed, 80 insertions, 11 deletions
diff --git a/build.zig b/build.zig
index aea990e..9b16a14 100644
--- a/build.zig
+++ b/build.zig
@@ -23,10 +23,9 @@ fn define_subproj(name: []const u8, b: *std.Build, target: std.Build.ResolvedTar
     run_step.dependOn(&run_cmd.step);
 
     const test_exe = b.addTest(.{ .root_source_file = b.path(test_path), .target = target, .optimize = optimize });
-
-    const test_cmd = b.addRunArtifact(test_exe);
+    const run_unit_tests = b.addRunArtifact(test_exe);
     const test_step = b.step(test_task_name, test_task_desc);
-    test_step.dependOn(&test_cmd.step);
+    test_step.dependOn(&run_unit_tests.step);
 }
 
 pub fn build(b: *std.Build) !void {
diff --git a/src/monkey_brain/multi_layer_perceptron.zig b/src/monkey_brain/multi_layer_perceptron.zig
deleted file mode 100644
index e69de29..0000000
--- a/src/monkey_brain/multi_layer_perceptron.zig
+++ /dev/null
diff --git a/src/monkey_brain/neural_network/layer.zig b/src/monkey_brain/neural_network/layer.zig
new file mode 100644
index 0000000..7b2bf6e
--- /dev/null
+++ b/src/monkey_brain/neural_network/layer.zig
@@ -0,0 +1,5 @@
+const std = @import("std");
+const math = std.math;
+const Random = std.Random;
+const ArrayList = std.ArrayList;
+const testing = std.testing;
diff --git a/src/monkey_brain/neural_network/neuron.zig b/src/monkey_brain/neural_network/neuron.zig
new file mode 100644
index 0000000..a26b787
--- /dev/null
+++ b/src/monkey_brain/neural_network/neuron.zig
@@ -0,0 +1,56 @@
+const std = @import("std");
+const math = std.math;
+const Random = std.Random;
+const ArrayList = std.ArrayList;
+const testing = std.testing;
+
+pub const Neuron = struct {
+    weights: ArrayList(f64),
+    bias: f64,
+
+    pub fn init(allocator: std.mem.Allocator, num_inputs: usize) !Neuron {
+        var weights = ArrayList(f64).init(allocator);
+        var prng = Random.DefaultPrng.init(blk: {
+            const seed: u64 = @intCast(std.time.milliTimestamp());
+            break :blk seed;
+        });
+
+        var random = prng.random();
+        var i: usize = 0;
+
+        while (i < num_inputs) : (i += 1) {
+            try weights.append(random.float(f64) * 2 - 1);
+        }
+
+        return Neuron{
+            .weights = weights,
+            .bias = random.float(f64) * 2 - 1,
+        };
+    }
+
+    pub fn deinit(self: *Neuron) void {
+        self.weights.deinit();
+    }
+
+    pub fn activate(self: *const Neuron, inputs: []const f64) f64 {
+        var sum: f64 = self.bias;
+        for (self.weights.items, 0..) |weight, i| {
+            sum += inputs[i] * weight;
+        }
+        return sigmoid(sum);
+    }
+};
+
+fn sigmoid(x: f64) f64 {
+    return 1.0 / (1.0 + math.exp(-x));
+}
+
+test "Neuron initialization" {
+    const allocator = testing.allocator;
+    var neuron = try Neuron.init(allocator, 2);
+    defer neuron.deinit();
+
+    std.debug.print("Testing neuron", .{});
+    try testing.expect(neuron.weights.items.len == 2);
+    try testing.expect(neuron.bias >= -1 and neuron.bias <= 1);
+}
diff --git a/src/monkey_brain/perceptron.zig b/src/monkey_brain/perceptron.zig
index 893bb16..1d819d1 100644
--- a/src/monkey_brain/perceptron.zig
+++ b/src/monkey_brain/perceptron.zig
@@ -5,7 +5,7 @@ const math = std.math;
 const input_size: usize = 2;
 const training_set_size: usize = 4;
 const learning_rate: f64 = 0.1;
-const epochs: u64 = 1000000;
+const epochs: u64 = 10000;
 
 // https://en.wikipedia.org/wiki/Sigmoid_function - more details
 // https://www.youtube.com/watch?v=TPqr8t919YM
@@ -40,8 +40,8 @@ fn train(weights: *[input_size]f64, bias: *f64, training_data: [training_set_siz
 }
 
 pub fn demo() !void {
-    var weights = [_]f64{ std.crypto.random.float(f64), std.crypto.random.float(f64) };
-    var bias: f64 = std.crypto.random.float(f64);
+    var weights = [_]f64{ std.crypto.random.float(f64) * 2 - 1, std.crypto.random.float(f64) * 2 - 1 };
+    var bias: f64 = std.crypto.random.float(f64) * 2 - 1;
 
     const training_data = [_][input_size]f64{
         .{ 0, 0 },
@@ -63,8 +63,8 @@ pub fn demo() !void {
 }
 
 test "OR gate" {
-    var weights = [_]f64{ 0, 0 };
-    var bias: f64 = 0;
+    var weights = [_]f64{ 0.3, 0.2 };
+    var bias: f64 = 0.5;
 
     const training_data = [_][input_size]f64{
         .{ 0, 0 },
@@ -78,6 +78,10 @@ test "OR gate" {
 
     for (training_data, labels) |inputs, expected| {
         const prediction = predict(weights, bias, inputs);
-        try testing.expect((prediction - expected) < 0.1);
+        const predicted_error = prediction - expected;
+        std.debug.print("Predicted error {}\n", .{predicted_error});
+        std.debug.print("Predicted: {} | Expected: {}\n", .{ prediction, expected });
+
+        try testing.expect(predicted_error < 0.1);
     }
 }
diff --git a/src/monkey_brain/test.zig b/src/monkey_brain/test.zig
index b3363e9..dd14718 100644
--- a/src/monkey_brain/test.zig
+++ b/src/monkey_brain/test.zig
@@ -1,3 +1,8 @@
-comptime {
-    _ = @import("perceptron.zig");
+const std = @import("std");
+const testing = std.testing;
+pub const perceptron = @import("perceptron.zig");
+pub const neuron = @import("neural_network/neuron.zig");
+
+test {
+    testing.refAllDeclsRecursive(@This());
 }