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 }