// SUSselect performs the Stochastic-Universal-Sampling selection // Input: // cumprob -- cumulated probabilities (from sorted population) // pb -- one random number corresponding to the first probability (pointer/position) // use pb = -1 to generate a random value here // Output: // selinds -- selected individuals (indices) func SUSselect(selinds []int, cumprob []float64, pb float64) { nsel := len(selinds) chk.IntAssertLessThanOrEqualTo(nsel, len(cumprob)) dp := 1.0 / float64(nsel) if pb < 0 { pb = rnd.Float64(0, dp) } var j int for i := 0; i < nsel; i++ { j = 0 for pb > cumprob[j] { j += 1 } pb += dp selinds[i] = j } }
// GenTrialSolutions generates (initial) trial solutions func GenTrialSolutions(sols []*Solution, prms *Parameters) { // floats n := len(sols) // cannot use Nsol here because subsets of Solutions may be provided; e.g. parallel code if prms.Nflt > 0 { // interior points switch prms.GenType { case "latin": K := rnd.LatinIHS(prms.Nflt, n, prms.LatinDup) for i := 0; i < n; i++ { for j := 0; j < prms.Nflt; j++ { sols[i].Flt[j] = prms.FltMin[j] + float64(K[j][i]-1)*prms.DelFlt[j]/float64(n-1) } } case "halton": H := rnd.HaltonPoints(prms.Nflt, n) for i := 0; i < n; i++ { for j := 0; j < prms.Nflt; j++ { sols[i].Flt[j] = prms.FltMin[j] + H[j][i]*prms.DelFlt[j] } } default: for i := 0; i < n; i++ { for j := 0; j < prms.Nflt; j++ { sols[i].Flt[j] = rnd.Float64(prms.FltMin[j], prms.FltMax[j]) } } } // extra points if prms.UseMesh { initX := func(isol int) { for k := 0; k < prms.Nflt; k++ { sols[isol].Flt[k] = (prms.FltMin[k] + prms.FltMax[k]) / 2.0 } } isol := prms.Nsol - prms.NumExtraSols for i := 0; i < prms.Nflt-1; i++ { for j := i + 1; j < prms.Nflt; j++ { // (min,min) corner initX(isol) sols[isol].Flt[i] = prms.FltMin[i] sols[isol].Flt[j] = prms.FltMin[j] sols[isol].Fixed = true isol++ // (min,max) corner initX(isol) sols[isol].Flt[i] = prms.FltMin[i] sols[isol].Flt[j] = prms.FltMax[j] sols[isol].Fixed = true isol++ // (max,max) corner initX(isol) sols[isol].Flt[i] = prms.FltMax[i] sols[isol].Flt[j] = prms.FltMax[j] sols[isol].Fixed = true isol++ // (max,min) corner initX(isol) sols[isol].Flt[i] = prms.FltMax[i] sols[isol].Flt[j] = prms.FltMin[j] sols[isol].Fixed = true isol++ // Xi-min middle points ndelta := float64(prms.Nbry - 1) for m := 0; m < prms.Nbry-2; m++ { initX(isol) sols[isol].Flt[i] = prms.FltMin[i] sols[isol].Flt[j] = prms.FltMin[j] + float64(m+1)*prms.DelFlt[j]/ndelta sols[isol].Fixed = true isol++ } // Xi-max middle points for m := 0; m < prms.Nbry-2; m++ { initX(isol) sols[isol].Flt[i] = prms.FltMax[i] sols[isol].Flt[j] = prms.FltMin[j] + float64(m+1)*prms.DelFlt[j]/ndelta sols[isol].Fixed = true isol++ } // Xj-min middle points for m := 0; m < prms.Nbry-2; m++ { initX(isol) sols[isol].Flt[i] = prms.FltMin[i] + float64(m+1)*prms.DelFlt[i]/ndelta sols[isol].Flt[j] = prms.FltMin[j] sols[isol].Fixed = true isol++ } // Xj-max middle points for m := 0; m < prms.Nbry-2; m++ { initX(isol) sols[isol].Flt[i] = prms.FltMin[i] + float64(m+1)*prms.DelFlt[i]/ndelta sols[isol].Flt[j] = prms.FltMax[j] sols[isol].Fixed = true isol++ } } } chk.IntAssert(isol, prms.Nsol) } } // skip if there are no ints if prms.Nint < 2 { return } // binary numbers if prms.BinInt > 0 { for i := 0; i < n; i++ { for j := 0; j < prms.Nint; j++ { if rnd.FlipCoin(0.5) { sols[i].Int[j] = 1 } else { sols[i].Int[j] = 0 } } } return } // general integers L := rnd.LatinIHS(prms.Nint, n, prms.LatinDup) for i := 0; i < n; i++ { for j := 0; j < prms.Nint; j++ { sols[i].Int[j] = prms.IntMin[j] + (L[j][i]-1)*prms.DelInt[j]/(n-1) } } }
// PopFltGen generates a population of individuals with float point numbers // Notes: (1) ngenes = len(C.RangeFlt) func PopFltGen(id int, C *ConfParams) Population { o := make([]*Individual, C.Ninds) ngenes := len(C.RangeFlt) for i := 0; i < C.Ninds; i++ { o[i] = NewIndividual(C.Nova, C.Noor, C.Nbases, make([]float64, ngenes)) } if C.Latin { K := rnd.LatinIHS(ngenes, C.Ninds, C.LatinDf) dx := make([]float64, ngenes) for i := 0; i < ngenes; i++ { dx[i] = (C.RangeFlt[i][1] - C.RangeFlt[i][0]) / float64(C.Ninds-1) } for i := 0; i < ngenes; i++ { for j := 0; j < C.Ninds; j++ { o[j].SetFloat(i, C.RangeFlt[i][0]+float64(K[i][j]-1)*dx[i]) } } return o } npts := int(math.Pow(float64(C.Ninds), 1.0/float64(ngenes))) // num points in 'square' grid ntot := int(math.Pow(float64(npts), float64(ngenes))) // total num of individuals in grid den := 1.0 // denominator to calculate dx if npts > 1 { den = float64(npts - 1) } var lfto int // leftover, e.g. n % (nx*ny) var rdim int // reduced dimension, e.g. (nx*ny) var idx int // index of gene in grid var dx, x, mul, xmin, xmax float64 for i := 0; i < C.Ninds; i++ { if i < ntot { // on grid lfto = i for j := 0; j < ngenes; j++ { rdim = int(math.Pow(float64(npts), float64(ngenes-1-j))) idx = lfto / rdim lfto = lfto % rdim xmin = C.RangeFlt[j][0] xmax = C.RangeFlt[j][1] dx = xmax - xmin x = xmin + float64(idx+id)*dx/den if C.Noise > 0 { mul = rnd.Float64(0, C.Noise) if rnd.FlipCoin(0.5) { x += mul * x } else { x -= mul * x } } if x < xmin { x = xmin + (xmin - x) } if x > xmax { x = xmax - (x - xmax) } o[i].SetFloat(j, x) } } else { // additional individuals for j := 0; j < ngenes; j++ { xmin = C.RangeFlt[j][0] xmax = C.RangeFlt[j][1] x = rnd.Float64(xmin, xmax) o[i].SetFloat(j, x) } } } return o }