seeded randomness through context.random_generator

This commit is contained in:
2026-02-06 07:19:26 +01:00
parent 6a05b906d4
commit 4f69d0f9c9
4 changed files with 62 additions and 68 deletions
+1 -1
View File
@@ -17,7 +17,7 @@ Problem :: struct {
name: string,
chromosome_size: int,
fitness_proc: proc(_: Chromosome) -> f64,
maximize: bool, // true = higher better, false = lower better
maximize: bool,
}
Stats :: struct {
+55 -10
View File
@@ -1,5 +1,6 @@
package main
import "core:math/rand"
import "core:container/bit_array"
import "core:encoding/csv"
import "core:fmt"
@@ -63,16 +64,29 @@ fitness_features :: proc(chrom: Chromosome) -> f64 {
delete(y)
}
// Train/test split
X_train, X_test, y_train, y_test := train_test_split(X, y, 0.2, RANDOM_SEED)
defer {
for row in X_train {delete(row)}
for row in X_test {delete(row)}
delete(X_train)
delete(X_test)
delete(y_train)
delete(y_test)
}
// NOW split based on actual data size
n := len(X)
test_count := int(f64(n) * 0.2)
train_count := n - test_count
// Create indices and shuffle ONCE per fitness eval
indices := make([]int, n)
defer delete(indices)
for i in 0 ..< n {
indices[i] = i
}
rand.shuffle(indices[:]) // Uses your seeded generator
// Split using shuffled indices
X_train, X_test, y_train, y_test := split_by_indices(X, y, indices, train_count)
defer {
for row in X_train {delete(row)}
for row in X_test {delete(row)}
delete(X_train)
delete(X_test)
delete(y_train)
delete(y_test)
}
// Train and evaluate
beta := train_linear_regression(X_train, y_train)
@@ -84,6 +98,37 @@ fitness_features :: proc(chrom: Chromosome) -> f64 {
return rmse(predictions, y_test)
}
split_by_indices :: proc(
X: [][]f64,
y: []f64,
indices: []int,
train_count: int,
) -> ([][]f64, [][]f64, []f64, []f64) {
n_features := len(X[0])
test_count := len(indices) - train_count
X_train := make([][]f64, train_count)
X_test := make([][]f64, test_count)
y_train := make([]f64, train_count)
y_test := make([]f64, test_count)
for i in 0 ..< train_count {
idx := indices[i]
X_train[i] = make([]f64, n_features)
copy(X_train[i], X[idx])
y_train[i] = y[idx]
}
for i in 0 ..< test_count {
idx := indices[train_count + i]
X_test[i] = make([]f64, n_features)
copy(X_test[i], X[idx])
y_test[i] = y[idx]
}
return X_train, X_test, y_train, y_test
}
get_selected_features :: proc(dataset: Dataset, chrom: Chromosome) -> ([][]f64, []f64) {
n_rows := len(dataset)
+1 -57
View File
@@ -1,5 +1,6 @@
package main
import "core:hash"
import "core:math"
import "core:math/rand"
@@ -114,60 +115,3 @@ rmse :: proc(predictions: []f64, actual: []f64) -> f64 {
}
return math.sqrt(sum / f64(len(predictions)))
}
// Train/test split
train_test_split :: proc(
X: [][]f64,
y: []f64,
test_size: f64 = 0.2,
random_seed: u64 = 0,
) -> (
[][]f64,
[][]f64,
[]f64,
[]f64,
) {
n := len(X)
if n == 0 || len(X[0]) == 0 {
return nil, nil, nil, nil
}
n_features := len(X[0])
test_count := int(f64(n) * test_size)
train_count := n - test_count
// Shuffle indices
indices := make([]int, n)
defer delete(indices)
for i in 0 ..< n {
indices[i] = i
}
rng := rand.create(random_seed)
context.random_generator = rand.default_random_generator(&rng)
rand.shuffle(indices[:])
// Allocate
X_train := make([][]f64, train_count)
X_test := make([][]f64, test_count)
y_train := make([]f64, train_count)
y_test := make([]f64, test_count)
// Copy training data
for i in 0 ..< train_count {
idx := indices[i]
X_train[i] = make([]f64, n_features)
copy(X_train[i], X[idx])
y_train[i] = y[idx]
}
// Copy test data
for i in 0 ..< test_count {
idx := indices[train_count + i]
X_test[i] = make([]f64, n_features)
copy(X_test[i], X[idx])
y_test[i] = y[idx]
}
return X_train, X_test, y_train, y_test
}
+5
View File
@@ -1,11 +1,16 @@
package main
import "core:math/rand"
import "core:fmt"
import "base:runtime"
main :: proc() {
// Choose problem
problem_type := "feature_selection" // or "knapsack"
state := rand.create(RANDOM_SEED)
context.random_generator = runtime.default_random_generator(&state)
problem: Problem
switch problem_type {
case "knapsack":