about summary refs log tree commit diff
diff options
context:
space:
mode:
authormakefunstuff <[email protected]>2024-07-08 23:44:06 +0200
committermakefunstuff <[email protected]>2024-07-08 23:44:06 +0200
commit82c57cbd54bc20c5a6b1f1a12f42db8018c0f07a (patch)
treeac68745cb8af63688159f993ed5b6adabc26079a
parentc01d9802552e44bf228de141c572d1e8419a16a9 (diff)
downloadtinkerbunk-82c57cbd54bc20c5a6b1f1a12f42db8018c0f07a.tar.gz
monkey brain one
-rw-r--r--build.zig62
-rw-r--r--src/monkey_brain/main.zig69
2 files changed, 76 insertions, 55 deletions
diff --git a/build.zig b/build.zig
index cd4e0ae..dbaf428 100644
--- a/build.zig
+++ b/build.zig
@@ -15,42 +15,44 @@ pub fn build(b: *std.Build) void {
     // set a preferred release mode, allowing the user to decide how to optimize.
     const optimize = b.standardOptimizeOption(.{});
 
-    const exe = b.addExecutable(.{
-        .name = "tinkerbunk",
-        .root_source_file = b.path("src/main.zig"),
-        .target = target,
-        .optimize = optimize,
-    });
+    if (target.query.os_tag == .linux) {
+        const exe = b.addExecutable(.{
+            .name = "tinkerbunk",
+            .root_source_file = b.path("src/main.zig"),
+            .target = target,
+            .optimize = optimize,
+        });
 
-    exe.linkSystemLibrary("SDL2");
-    exe.linkSystemLibrary("mpg123");
-    exe.linkSystemLibrary("asound");
-    exe.linkLibC();
-    exe.addCSourceFile(.{ .file = b.path("csrc/cbrr.c"), .flags = &.{} });
-    exe.addIncludePath(b.path("./csrc"));
+        exe.linkSystemLibrary("SDL2");
+        exe.linkSystemLibrary("mpg123");
+        exe.linkSystemLibrary("asound");
+        exe.linkLibC();
+        exe.addCSourceFile(.{ .file = b.path("csrc/cbrr.c"), .flags = &.{} });
+        exe.addIncludePath(b.path("./csrc"));
 
-    b.installArtifact(exe);
+        b.installArtifact(exe);
 
-    const run_cmd = b.addRunArtifact(exe);
-    run_cmd.step.dependOn(b.getInstallStep());
+        const run_cmd = b.addRunArtifact(exe);
+        run_cmd.step.dependOn(b.getInstallStep());
 
-    // This allows the user to pass arguments to the application in the build
-    // command itself, like this: `zig build run -- arg1 arg2 etc`
-    if (b.args) |args| {
-        run_cmd.addArgs(args);
-    }
+        // This allows the user to pass arguments to the application in the build
+        // command itself, like this: `zig build run -- arg1 arg2 etc`
+        if (b.args) |args| {
+            run_cmd.addArgs(args);
+        }
 
-    const run_step = b.step("run", "Run the app");
-    run_step.dependOn(&run_cmd.step);
+        const run_step = b.step("run", "Run the app");
+        run_step.dependOn(&run_cmd.step);
 
-    const exe_unit_tests = b.addTest(.{
-        .root_source_file = b.path("src/main.zig"),
-        .target = target,
-        .optimize = optimize,
-    });
-    const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
-    const test_step = b.step("test", "Run unit tests");
-    test_step.dependOn(&run_exe_unit_tests.step);
+        const exe_unit_tests = b.addTest(.{
+            .root_source_file = b.path("src/main.zig"),
+            .target = target,
+            .optimize = optimize,
+        });
+        const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
+        const test_step = b.step("test", "Run unit tests");
+        test_step.dependOn(&run_exe_unit_tests.step);
+    }
 
     // monkey brains
     const monkey_brain = b.addExecutable(.{
diff --git a/src/monkey_brain/main.zig b/src/monkey_brain/main.zig
index 52ff9e5..5d0e616 100644
--- a/src/monkey_brain/main.zig
+++ b/src/monkey_brain/main.zig
@@ -1,13 +1,14 @@
 const std = @import("std");
 const testing = std.testing;
+const math = std.math;
 
 const input_size: usize = 2;
 const training_set_size: usize = 4;
 const learning_rate: f64 = 0.1;
-const epochs: u64 = 100 * 1000;
+const epochs: u64 = 1000000;
 
 fn sigmoid(x: f64) f64 {
-    return 1.0 / (1.0 + std.math.exp(-x));
+    return 1.0 / (1.0 + math.exp(-x));
 }
 
 fn sigmoid_derivative(output: f64) f64 {
@@ -15,23 +16,21 @@ fn sigmoid_derivative(output: f64) f64 {
 }
 
 fn predict(weights: [input_size]f64, bias: f64, inputs: [input_size]f64) f64 {
-    var total: f64 = 0.0;
-    for (0..input_size) |i| {
-        total += weights[i] * inputs[i];
+    var total: f64 = bias;
+    for (inputs, 0..) |input, i| {
+        total += weights[i] * input;
     }
-    total += bias;
     return sigmoid(total);
 }
 
 fn train(weights: *[input_size]f64, bias: *f64, training_data: [training_set_size][input_size]f64, labels: [training_set_size]f64) void {
     for (0..epochs) |_| {
-        for (0..training_set_size) |i| {
-            const prediction = predict(weights.*, bias.*, training_data[i]);
-            const err = labels[i] - prediction;
+        for (training_data, labels) |inputs, label| {
+            const prediction = predict(weights.*, bias.*, inputs);
+            const err = label - prediction;
             const adjustment = err * sigmoid_derivative(prediction);
-
-            for (0..input_size) |j| {
-                weights[j] += learning_rate * adjustment * training_data[i][j];
+            for (inputs, 0..) |input, j| {
+                weights[j] += learning_rate * adjustment * input;
             }
             bias.* += learning_rate * adjustment;
         }
@@ -39,24 +38,44 @@ fn train(weights: *[input_size]f64, bias: *f64, training_data: [training_set_siz
 }
 
 pub fn main() !void {
-    const w1 = std.crypto.random.float(f64);
-    const w2 = std.crypto.random.float(f64);
-
-    var weights: [input_size]f64 = .{ w1, w2 };
-    var bias: f64 = 0.0;
-
-    const training_data: [training_set_size][input_size]f64 = .{ .{ 0, 0 }, .{ 0, 1 }, .{ 1, 0 }, .{ 1, 1 } };
+    var weights = [_]f64{ std.crypto.random.float(f64), std.crypto.random.float(f64) };
+    var bias: f64 = std.crypto.random.float(f64);
 
-    const labels: [training_set_size]f64 = .{ 0, 0, 0, 1 };
+    const training_data = [_][input_size]f64{
+        .{ 0, 0 },
+        .{ 0, 1 },
+        .{ 1, 0 },
+        .{ 1, 1 },
+    };
+    const labels = [_]f64{ 0, 1, 1, 1 }; // OR operation
 
     train(&weights, &bias, training_data, labels);
 
-    for (0..training_set_size) |i| {
-        const prediction = predict(weights, bias, training_data[i]);
-        std.log.info("Input {} {}, Predicted output: {}", .{ training_data[i][0], training_data[i][1], prediction });
+    std.debug.print("Trained weights: {d}, {d}\n", .{ weights[0], weights[1] });
+    std.debug.print("Trained bias: {d}\n", .{bias});
+
+    for (training_data, labels) |inputs, expected| {
+        const prediction = predict(weights, bias, inputs);
+        std.debug.print("Input: {d}, {d}, Predicted: {d:.4}, Expected: {d}\n", .{ inputs[0], inputs[1], prediction, expected });
     }
 }
 
-test "hello" {
-    try testing.expect(true);
+test "OR gate" {
+    var weights = [_]f64{ 0, 0 };
+    var bias: f64 = 0;
+
+    const training_data = [_][input_size]f64{
+        .{ 0, 0 },
+        .{ 0, 1 },
+        .{ 1, 0 },
+        .{ 1, 1 },
+    };
+    const labels = [_]f64{ 0, 1, 1, 1 };
+
+    train(&weights, &bias, training_data, labels);
+
+    for (training_data, labels) |inputs, expected| {
+        const prediction = predict(weights, bias, inputs);
+        try testing.expect((prediction - expected) < 0.1);
+    }
 }