working genetics prototype
This commit is contained in:
122
internal/work/worker.go
Normal file
122
internal/work/worker.go
Normal file
@@ -0,0 +1,122 @@
|
||||
package work
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
|
||||
"edgaru089.ink/go/gl01/internal/io"
|
||||
"github.com/go-gl/mathgl/mgl64"
|
||||
)
|
||||
|
||||
type Worker struct {
|
||||
t1, t2 mgl64.Mat4
|
||||
t3 mgl64.Mat2x4
|
||||
}
|
||||
|
||||
func randomSlice64(s []float64) {
|
||||
for i := range s {
|
||||
s[i] = rand.NormFloat64()
|
||||
}
|
||||
}
|
||||
|
||||
// RandomWorker generates a random worker.
|
||||
func RandomWorker() (w Worker) {
|
||||
randomSlice64(w.t1[:])
|
||||
randomSlice64(w.t2[:])
|
||||
randomSlice64(w.t3[:])
|
||||
return
|
||||
}
|
||||
|
||||
func mutateSlice64(s []float64, stddev float64) {
|
||||
for i := range s {
|
||||
s[i] = rand.NormFloat64()*stddev + s[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Offspring generates an offspring with the given variance.
|
||||
func (w *Worker) Offspring(stddev float64) (s Worker) {
|
||||
s = *w
|
||||
mutateSlice64(s.t1[:], stddev)
|
||||
mutateSlice64(s.t2[:], stddev)
|
||||
mutateSlice64(s.t3[:], stddev)
|
||||
return
|
||||
}
|
||||
|
||||
// Calculate runs a Vec4 through the Worker.
|
||||
func (w *Worker) Calculate(input mgl64.Vec4) (output mgl64.Vec2) {
|
||||
imm1 := w.t1.Mul4x1(input)
|
||||
imm2 := w.t2.Mul4x1(imm1)
|
||||
output = w.t3.Mul4x1(imm2)
|
||||
return
|
||||
}
|
||||
|
||||
// WorkerInstance is a instance of a worker.
|
||||
type WorkerInstance struct {
|
||||
worker Worker
|
||||
pos mgl64.Vec2
|
||||
target mgl64.Vec2
|
||||
|
||||
score float64
|
||||
|
||||
distance float64
|
||||
step0 int
|
||||
}
|
||||
|
||||
var (
|
||||
Radius float64 = 10 // Radius of all worker instances
|
||||
Step float64 = 1 // Move length of a advance step
|
||||
|
||||
OffspringStdVar float64 = 0.5
|
||||
|
||||
Score float64 = 1
|
||||
|
||||
TargetAreaSize = mgl64.Vec2{750, 750}
|
||||
)
|
||||
|
||||
func randomTarget() (t mgl64.Vec2) {
|
||||
return mgl64.Vec2{
|
||||
TargetAreaSize[0] * (rand.Float64() - .5),
|
||||
TargetAreaSize[1] * (rand.Float64() - .5),
|
||||
}
|
||||
}
|
||||
|
||||
func (i *WorkerInstance) Step(step_num int) {
|
||||
output := i.worker.Calculate(mgl64.Vec4{
|
||||
i.pos[0],
|
||||
i.pos[1],
|
||||
i.target[0],
|
||||
i.target[1],
|
||||
})
|
||||
|
||||
direction := mgl64.Vec2{output[0], output[1]}.Normalize()
|
||||
step := direction.Mul(Step)
|
||||
|
||||
i.pos = i.pos.Add(step)
|
||||
if i.pos.Sub(i.target).Len() < Radius {
|
||||
// Score!
|
||||
i.score += Score
|
||||
|
||||
io.StepFactors = append(io.StepFactors, (float64(step_num-i.step0)*Step)/i.distance)
|
||||
|
||||
i.target = randomTarget()
|
||||
i.step0 = step_num
|
||||
i.distance = i.pos.Sub(i.target).Len()
|
||||
}
|
||||
}
|
||||
|
||||
func (i *WorkerInstance) Offspring() (it WorkerInstance) {
|
||||
it.pos = randomTarget()
|
||||
it.target = randomTarget()
|
||||
it.distance = it.pos.Sub(it.target).Len()
|
||||
it.score = 0
|
||||
it.worker = i.worker.Offspring(OffspringStdVar)
|
||||
return
|
||||
}
|
||||
|
||||
func RandomInstance() (i WorkerInstance) {
|
||||
i.worker = RandomWorker()
|
||||
i.pos = randomTarget()
|
||||
i.target = randomTarget()
|
||||
i.distance = i.pos.Sub(i.target).Len()
|
||||
i.score = 0
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user