Exemplo n.º 1
0
// IntMutation performs the mutation of genetic data from A
//  Output: modified individual 'A'
func IntMutation(A []int, time int, ops *OpsData) {
	size := len(A)
	if !rnd.FlipCoin(ops.Pm) || size < 1 {
		return
	}
	pos := rnd.IntGetUniqueN(0, size, ops.Nchanges)
	for _, i := range pos {
		m := rnd.Int(1, int(ops.Mmax))
		if rnd.FlipCoin(0.5) {
			A[i] += m * A[i]
		} else {
			A[i] -= m * A[i]
		}
	}
}
Exemplo n.º 2
0
// Fight implements the competition between A and B
func (A *Solution) Fight(B *Solution) (A_wins bool) {

	// compare solutions
	A_dom, B_dom := A.Compare(B)
	if A_dom {
		return true
	}
	if B_dom {
		return false
	}

	// tie: single-objective problems
	if A.prms.Nova < 2 {
		if A.DistNeigh > B.DistNeigh {
			return true
		}
		if B.DistNeigh > A.DistNeigh {
			return false
		}
		return rnd.FlipCoin(0.5)
	}

	// tie: multi-objective problems: same Pareto front
	if A.FrontId == B.FrontId {
		if A.DistCrowd > B.DistCrowd {
			return true
		}
		if B.DistCrowd > A.DistCrowd {
			return false
		}
		return rnd.FlipCoin(0.5)
	}

	// tie: multi-objective problems: different Pareto fronts
	if A.FrontId < B.FrontId {
		return true
	}
	if B.FrontId < A.FrontId {
		return false
	}
	if A.DistNeigh > B.DistNeigh {
		return true
	}
	if B.DistNeigh > A.DistNeigh {
		return false
	}
	return rnd.FlipCoin(0.5)
}
Exemplo n.º 3
0
// StrCrossover performs the crossover of genetic data from A and B
//  Output:
//   a and b -- offspring
//  Example:
//         0 1 2 3 4 5 6 7
//     A = a b c d e f g h    size = 8
//     B = * . . . . * * *    cuts = [1, 5]
//          ↑       ↑     ↑   ends = [1, 5, 8]
//          1       5     8
//     a = a . . . . f g h
//     b = * b c d e * * *
func StrCrossover(a, b, A, B []string, time int, ops *OpsData) (ends []int) {
	size := len(A)
	if !rnd.FlipCoin(ops.Pc) || size < 2 {
		for i := 0; i < len(A); i++ {
			a[i], b[i] = A[i], B[i]
		}
		return
	}
	ends = GenerateCxEnds(size, ops.Ncuts, ops.Cuts)
	swap := false
	start := 0
	for _, end := range ends {
		if swap {
			for j := start; j < end; j++ {
				b[j], a[j] = A[j], B[j]
			}
		} else {
			for j := start; j < end; j++ {
				a[j], b[j] = A[j], B[j]
			}
		}
		start = end
		swap = !swap
	}
	return
}
Exemplo n.º 4
0
// MtInt performs the mutation of genetic data from A
//  Output: modified individual 'A'
func MtInt(A []int, prms *Parameters) {
	size := len(A)
	if !rnd.FlipCoin(prms.IntPm) || size < 1 {
		return
	}
	mmax := 2
	pos := rnd.IntGetUniqueN(0, size, prms.IntNchanges)
	for _, i := range pos {
		m := rnd.Int(1, mmax)
		if rnd.FlipCoin(0.5) {
			A[i] += m * A[i]
		} else {
			A[i] -= m * A[i]
		}
	}
}
Exemplo n.º 5
0
// BytCrossover performs the crossover of genetic data from A and B
//  Output:
//   a and b -- offspring
//  Example:
//         0 1 2 3 4 5 6 7
//     A = a b c d e f g h    size = 8
//     B = * . . . . * * *    cuts = [1, 5]
//          ↑       ↑     ↑   ends = [1, 5, 8]
//          1       5     8
//     a = a . . . . f g h
//     b = * b c d e * * *
func BytCrossover(a, b, A, B [][]byte, time int, ops *OpsData) (ends []int) {
	size := len(A)
	if !rnd.FlipCoin(ops.Pc) || size < 2 {
		for i := 0; i < len(A); i++ {
			copy(a[i], A[i])
			copy(b[i], B[i])
		}
		return
	}
	ends = GenerateCxEnds(size, ops.Ncuts, ops.Cuts)
	swap := false
	start := 0
	for _, end := range ends {
		if swap {
			for j := start; j < end; j++ {
				copy(b[j], A[j])
				copy(a[j], B[j])
			}
		} else {
			for j := start; j < end; j++ {
				copy(a[j], A[j])
				copy(b[j], B[j])
			}
		}
		start = end
		swap = !swap
	}
	return
}
Exemplo n.º 6
0
// CxInt performs the crossover of genetic data from A and B
//  Output:
//   a and b -- offspring
//  Example:
//         0 1 2 3 4 5 6 7
//     A = a b c d e f g h    size = 8
//     B = * . . . . * * *    cuts = [1, 5]
//          ↑       ↑     ↑   ends = [1, 5, 8]
//          1       5     8
//     a = a . . . . f g h
//     b = * b c d e * * *
func CxInt(a, b, A, B []int, prms *Parameters) {
	size := len(A)
	if !rnd.FlipCoin(prms.IntPc) || size < 2 {
		for i := 0; i < len(A); i++ {
			a[i], b[i] = A[i], B[i]
		}
		return
	}
	ends := GenerateCxEnds(size, prms.IntNcuts, nil)
	swap := false
	start := 0
	for _, end := range ends {
		if swap {
			for j := start; j < end; j++ {
				b[j], a[j] = A[j], B[j]
			}
		} else {
			for j := start; j < end; j++ {
				a[j], b[j] = A[j], B[j]
			}
		}
		start = end
		swap = !swap
	}
	return
}
Exemplo n.º 7
0
// StrMutation performs the mutation of genetic data from A
//  Output: modified individual 'A'
func StrMutation(A []string, time int, ops *OpsData) {
	size := len(A)
	if !rnd.FlipCoin(ops.Pm) || size < 1 {
		return
	}
	pos := rnd.IntGetUniqueN(0, size, ops.Nchanges)
	for _, i := range pos {
		A[i] = "TODO" // TODO: improve this
	}
}
Exemplo n.º 8
0
// KeyMutation performs the mutation of genetic data from A
//  Output: modified individual 'A'
func KeyMutation(A []byte, time int, ops *OpsData) {
	size := len(A)
	if !rnd.FlipCoin(ops.Pm) || size < 1 {
		return
	}
	pos := rnd.IntGetUniqueN(0, size, ops.Nchanges)
	for _, i := range pos {
		v := rnd.Int(0, 100)
		A[i] = byte(v) // TODO: improve this
	}
}
Exemplo n.º 9
0
// FunMutation performs the mutation of genetic data from A
//  Output: modified individual 'A'
func FunMutation(A []Func_t, time int, ops *OpsData) {
	size := len(A)
	if !rnd.FlipCoin(ops.Pm) || size < 1 {
		return
	}
	pos := rnd.IntGetUniqueN(0, size, ops.Nchanges)
	for _, i := range pos {
		// TODO: improve this
		A[i] = func(ind *Individual) string { return "mutated" }
	}
}
Exemplo n.º 10
0
// MtIntBin performs the mutation of a binary chromosome
//  Output: modified individual 'A'
func MtIntBin(A []int, prms *Parameters) {
	size := len(A)
	if !rnd.FlipCoin(prms.IntPm) || size < 1 {
		return
	}
	pos := rnd.IntGetUniqueN(0, size, prms.IntNchanges)
	for _, i := range pos {
		if A[i] == 0 {
			A[i] = 1
		} else {
			A[i] = 0
		}
	}
}
Exemplo n.º 11
0
// IntBinMutation performs the mutation of a binary chromosome
//  Output: modified individual 'A'
func IntBinMutation(A []int, time int, ops *OpsData) {
	size := len(A)
	if !rnd.FlipCoin(ops.Pm) || size < 1 {
		return
	}
	pos := rnd.IntGetUniqueN(0, size, ops.Nchanges)
	for _, i := range pos {
		if A[i] == 0 {
			A[i] = 1
		} else {
			A[i] = 0
		}
	}
}
Exemplo n.º 12
0
// MtIntOrd performs the mutation of genetic data from a ordered list of integers A
//  Output: modified individual 'A'
//  Note: using DM method as explained in [1] (citing [2])
//  References:
//   [1] Larrañaga P, Kuijpers CMH, Murga RH, Inza I and Dizdarevic S. Genetic Algorithms for the
//       Travelling Salesman Problem: A Review of Representations and Operators. Artificial
//       Intelligence Review, 13:129-170; 1999. doi:10.1023/A:1006529012972
//   [2] Michalewicz Z. Genetic Algorithms + Data Structures = Evolution Programs. Berlin
//       Heidelberg: Springer Verlag; 1992
//       Joint Conference on Artificial Intelligence, 162-164; 1985.
//
//  DM displacement mutation method:
//   Ex:
//           0 1 2 3 4 5 6 7
//       A = a b c d e f g h   s = 2
//              ↑     ↑        t = 5
//              2     5
//
//       core = c d e  (subtour)  ncore = t - s = 5 - 2 = 3
//
//                0 1 2 3 4
//       remain = a b f g h  (remaining)  nrem = size - ncore = 8 - 3 = 5
//                       ↑
//                       4 = ins
func MtIntOrd(A []int, prms *Parameters) {
	size := len(A)
	if !rnd.FlipCoin(prms.IntPm) || size < 3 {
		if size == 2 {
			A[0], A[1] = A[1], A[0]
		}
		return
	}
	var indices []int
	var s, t, ncore, nrem, ins int
	if indices != nil {
		s, t, ins = indices[0], indices[1], indices[2]
		ncore = t - s
		nrem = size - ncore
	} else {
		s = rnd.Int(1, size-2)
		t = rnd.Int(s+1, size-1)
		ncore = t - s
		nrem = size - ncore
		ins = rnd.Int(1, nrem)
	}
	core := make([]int, ncore)
	remain := make([]int, nrem)
	var jc, jr int
	for i := 0; i < size; i++ {
		if i >= s && i < t {
			core[jc] = A[i]
			jc++
		} else {
			remain[jr] = A[i]
			jr++
		}
	}
	jc, jr = 0, 0
	for i := 0; i < size; i++ {
		if i < ins {
			A[i] = remain[jr]
			jr++
		} else {
			if jc < ncore {
				A[i] = core[jc]
				jc++
			} else {
				A[i] = remain[jr]
				jr++
			}
		}
	}
}
Exemplo n.º 13
0
// CxIntOrd performs the crossover in a pair of individuals with integer numbers
// that correspond to a ordered sequence, e.g. for traveling salesman problem
//  Output:
//    a and b -- offspring chromosomes
//  Note: using OX1 method explained in [1] (proposed in [2])
//  References:
//   [1] Larrañaga P, Kuijpers CMH, Murga RH, Inza I and Dizdarevic S. Genetic Algorithms for the
//       Travelling Salesman Problem: A Review of Representations and Operators. Artificial
//       Intelligence Review, 13:129-170; 1999. doi:10.1023/A:1006529012972
//   [2] Davis L. Applying Adaptive Algorithms to Epistatic Domains. Proceedings of International
//       Joint Conference on Artificial Intelligence, 162-164; 1985.
//  Example:
//   data:
//         0 1   2 3 4   5 6 7
//     A = a b | c d e | f g h        size = 8
//     B = b d | f h g | e c a        cuts = [2, 5]
//             ↑       ↑       ↑      ends = [2, 5, 8]
//             2       5       8
//   first step: copy subtours
//     a = . . | f h g | . . .
//     b = . . | c d e | . . .
//   second step: copy unique from subtour's end, position 5
//               start adding here
//                       ↓                           5 6 7   0 1   2 3 4
//     a = d e | f h g | a b c         get from A: | f̶ g̶ h̶ | a b | c d e
//     b = h g | c d e | a b f         get from B: | e̶ c̶ a | b d̶ | f h g
func CxIntOrd(a, b, A, B []int, prms *Parameters) {
	size := len(A)
	if !rnd.FlipCoin(prms.IntPc) || size < 3 {
		for i := 0; i < len(A); i++ {
			a[i], b[i] = A[i], B[i]
		}
		return
	}
	var s, t int
	var cuts []int
	if len(cuts) == 2 {
		s, t = cuts[0], cuts[1]
	} else {
		s = rnd.Int(1, size-2)
		t = rnd.Int(s+1, size-1)
	}
	chk.IntAssertLessThan(s, t)
	acore := B[s:t]
	bcore := A[s:t]
	ncore := t - s
	acorehas := make(map[int]bool) // TODO: check if map can be replaced => improve efficiency
	bcorehas := make(map[int]bool)
	for i := 0; i < ncore; i++ {
		a[s+i] = acore[i]
		b[s+i] = bcore[i]
		acorehas[acore[i]] = true
		bcorehas[bcore[i]] = true
	}
	ja, jb := t, t
	for i := 0; i < size; i++ {
		k := (i + t) % size
		if !acorehas[A[k]] {
			a[ja] = A[k]
			ja++
			if ja == size {
				ja = 0
			}
		}
		if !bcorehas[B[k]] {
			b[jb] = B[k]
			jb++
			if jb == size {
				jb = 0
			}
		}
	}
	return
}
Exemplo n.º 14
0
// IntOrdMutation performs the mutation of genetic data from a ordered list of integers A
//  Output: modified individual 'A'
//  Note: using DM method as explained in [1] (citing [2])
//  References:
//   [1] Larrañaga P, Kuijpers CMH, Murga RH, Inza I and Dizdarevic S. Genetic Algorithms for the
//       Travelling Salesman Problem: A Review of Representations and Operators. Artificial
//       Intelligence Review, 13:129-170; 1999. doi:10.1023/A:1006529012972
//   [2] Michalewicz Z. Genetic Algorithms + Data Structures = Evolution Programs. Berlin
//       Heidelberg: Springer Verlag; 1992
//       Joint Conference on Artificial Intelligence, 162-164; 1985.
//
//  DM displacement mutation method:
//   Ex:
//           0 1 2 3 4 5 6 7
//       A = a b c d e f g h   s = 2
//              ↑     ↑        t = 5
//              2     5
//
//       core = c d e  (subtour)  ncore = t - s = 5 - 2 = 3
//
//                0 1 2 3 4
//       remain = a b f g h  (remaining)  nrem = size - ncore = 8 - 3 = 5
//                       ↑
//                       4 = ins
func IntOrdMutation(A []int, time int, ops *OpsData) {
	size := len(A)
	if !rnd.FlipCoin(ops.Pm) || size < 3 {
		if size == 2 {
			A[0], A[1] = A[1], A[0]
		}
		return
	}
	var s, t, ncore, nrem, ins int
	if ops.OrdSti != nil {
		s, t, ins = ops.OrdSti[0], ops.OrdSti[1], ops.OrdSti[2]
		ncore = t - s
		nrem = size - ncore
	} else {
		s = rnd.Int(1, size-2)
		t = rnd.Int(s+1, size-1)
		ncore = t - s
		nrem = size - ncore
		ins = rnd.Int(1, nrem)
	}
	core := make([]int, ncore)
	remain := make([]int, nrem)
	var jc, jr int
	for i := 0; i < size; i++ {
		if i >= s && i < t {
			core[jc] = A[i]
			jc++
		} else {
			remain[jr] = A[i]
			jr++
		}
	}
	jc, jr = 0, 0
	for i := 0; i < size; i++ {
		if i < ins {
			A[i] = remain[jr]
			jr++
		} else {
			if jc < ncore {
				A[i] = core[jc]
				jc++
			} else {
				A[i] = remain[jr]
				jr++
			}
		}
	}
}
Exemplo n.º 15
0
// 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)
		}
	}
}
Exemplo n.º 16
0
func Test_int01(tst *testing.T) {

	//verbose()
	chk.PrintTitle("int01. organise sequence of ints")
	io.Pf("\n")

	// initialise random numbers generator
	rnd.Init(0) // 0 => use current time as seed

	// parameters
	C := NewConfParams()
	C.Nova = 1
	C.Noor = 0
	C.Nisl = 1
	C.Ninds = 20
	C.RegTol = 0
	C.NumInts = 20
	//C.GAtype = "crowd"
	C.CrowdSize = 2
	C.Tf = 50
	C.Verbose = chk.Verbose
	C.CalcDerived()

	// mutation function
	C.Ops.MtInt = func(A []int, time int, ops *OpsData) {
		size := len(A)
		if !rnd.FlipCoin(ops.Pm) || size < 1 {
			return
		}
		pos := rnd.IntGetUniqueN(0, size, ops.Nchanges)
		for _, i := range pos {
			if A[i] == 1 {
				A[i] = 0
			}
			if A[i] == 0 {
				A[i] = 1
			}
		}
	}

	// generation function
	C.PopIntGen = func(id int, cc *ConfParams) Population {
		o := make([]*Individual, cc.Ninds)
		genes := make([]int, cc.NumInts)
		for i := 0; i < cc.Ninds; i++ {
			for j := 0; j < cc.NumInts; j++ {
				genes[j] = rand.Intn(2)
			}
			o[i] = NewIndividual(cc.Nova, cc.Noor, cc.Nbases, genes)
		}
		return o
	}

	// objective function
	C.OvaOor = func(ind *Individual, idIsland, time int, report *bytes.Buffer) {
		score := 0.0
		count := 0
		for _, val := range ind.Ints {
			if val == 0 && count%2 == 0 {
				score += 1.0
			}
			if val == 1 && count%2 != 0 {
				score += 1.0
			}
			count++
		}
		ind.Ovas[0] = 1.0 / (1.0 + score)
		return
	}

	// run optimisation
	evo := NewEvolver(C)
	evo.Run()

	// results
	ideal := 1.0 / (1.0 + float64(C.NumInts))
	io.PfGreen("\nBest = %v\nBestOV = %v  (ideal=%v)\n", evo.Best.Ints, evo.Best.Ovas[0], ideal)
}
Exemplo n.º 17
0
// 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
}