Пример #1
0
// HashPoint returns a unique id of a point
func HashPoint(x, xmin, xdel []float64, tol float64) int {
	if tol < 1e-15 {
		chk.Panic("HashPoint: minimum tolerance must be 1e-15. %v is invalid", tol)
	}
	coefs := []float64{11, 101, 1001}
	n := utl.Imin(len(x), 3)
	var hash, xbar float64
	for i := 0; i < n; i++ {
		if x[i] < xmin[i] {
			chk.Panic("HashPoint: coordinate is outside range: %v < %v", x[i], xmin[i])
		}
		if x[i] > xmin[i]+xdel[i] {
			chk.Panic("HashPoint: coordinate is outside range: %v > %v", x[i], xmin[i]+xdel[i])
		}
		if xdel[i] > 0 {
			xbar = (x[i] - xmin[i]) / xdel[i]
			if xbar < 0 {
				xbar = 0
			}
			if xbar > 1 {
				xbar = 1
			}
			hash += (xbar / tol) * coefs[i]
		}
	}
	return int(hash)
}
Пример #2
0
// Solve solves optimisation problem
func (o *Optimiser) Solve() {

	// benchmark
	if o.Verbose {
		t0 := gotime.Now()
		defer func() {
			io.Pf("\nnfeval = %d\n", o.Nfeval)
			io.Pfblue2("cpu time = %v\n", gotime.Now().Sub(t0))
		}()
	}

	// output
	if o.Output != nil {
		o.Output(0, o.Solutions)
	}

	// perform evolution
	done := make(chan int, o.Ncpu)
	time := 0
	texc := time + o.DtExc
	for time < o.Tf {

		// run groups in parallel. up to exchange time
		for icpu := 0; icpu < o.Ncpu; icpu++ {
			go func(cpu int) {
				nfeval := 0
				for t := time; t < texc; t++ {
					if cpu == 0 && o.Verbose {
						io.Pf("time = %10d\r", t+1)
					}
					nfeval += o.EvolveOneGroup(cpu)
				}
				done <- nfeval
			}(icpu)
		}
		for cpu := 0; cpu < o.Ncpu; cpu++ {
			o.Nfeval += <-done
		}

		// compute metrics with all solutions included
		o.Metrics.Compute(o.Solutions)

		// exchange via tournament
		if o.Ncpu > 1 {
			if o.ExcTour {
				for i := 0; i < o.Ncpu; i++ {
					j := (i + 1) % o.Ncpu
					I := rnd.IntGetUnique(o.Groups[i].Indices, 2)
					J := rnd.IntGetUnique(o.Groups[j].Indices, 2)
					A, B := o.Groups[i].All[I[0]], o.Groups[i].All[I[1]]
					a, b := o.Groups[j].All[J[0]], o.Groups[j].All[J[1]]
					o.Tournament(A, B, a, b, o.Metrics)
				}
			}

			// exchange one randomly
			if o.ExcOne {
				rnd.IntGetGroups(o.cpupairs, utl.IntRange(o.Ncpu))
				for _, pair := range o.cpupairs {
					i, j := pair[0], pair[1]
					n := utl.Imin(o.Groups[i].Ncur, o.Groups[j].Ncur)
					k := rnd.Int(0, n)
					A := o.Groups[i].All[k]
					B := o.Groups[j].All[k]
					B.CopyInto(o.tmp)
					A.CopyInto(B)
					o.tmp.CopyInto(A)
				}
			}
		}

		// update time variables
		time += o.DtExc
		texc += o.DtExc
		time = utl.Imin(time, o.Tf)
		texc = utl.Imin(texc, o.Tf)

		// output
		if o.Output != nil {
			o.Output(time, o.Solutions)
		}
	}
}
Пример #3
0
// Compute computes limits, find non-dominated Pareto fronts, and compute crowd distances
func (o *Metrics) Compute(sols []*Solution) (nfronts int) {

	// reset variables and find limits
	z := o.Fsizes
	nsol := len(sols)
	for i, sol := range sols {

		// reset values
		sol.Nwins = 0
		sol.Nlosses = 0
		sol.FrontId = 0
		sol.DistCrowd = 0
		sol.DistNeigh = INF
		z[i] = 0

		// check oors
		for j := 0; j < o.prms.Noor; j++ {
			if math.IsNaN(sol.Oor[j]) {
				chk.Panic("NaN found in out-of-range value array\n\txFlt = %v\n\txInt = %v\n\tova = %v\n\toor = %v", sol.Flt, sol.Int, sol.Ova, sol.Oor)
			}
		}

		// ovas range
		for j := 0; j < o.prms.Nova; j++ {
			x := sol.Ova[j]
			if math.IsNaN(x) {
				chk.Panic("NaN found in objective value array\n\txFlt = %v\n\txInt = %v\n\tova = %v\n\toor = %v", sol.Flt, sol.Int, sol.Ova, sol.Oor)
			}
			if i == 0 {
				o.Omin[j] = x
				o.Omax[j] = x
			} else {
				o.Omin[j] = utl.Min(o.Omin[j], x)
				o.Omax[j] = utl.Max(o.Omax[j], x)
			}
		}

		// floats range
		for j := 0; j < o.prms.Nflt; j++ {
			x := sol.Flt[j]
			if i == 0 {
				o.Fmin[j] = x
				o.Fmax[j] = x
			} else {
				o.Fmin[j] = utl.Min(o.Fmin[j], x)
				o.Fmax[j] = utl.Max(o.Fmax[j], x)
			}
		}

		// ints range
		for j := 0; j < o.prms.Nint; j++ {
			x := sol.Int[j]
			if i == 0 {
				o.Imin[j] = x
				o.Imax[j] = x
			} else {
				o.Imin[j] = utl.Imin(o.Imin[j], x)
				o.Imax[j] = utl.Imax(o.Imax[j], x)
			}
		}
	}

	// compute neighbour distance
	for i := 0; i < nsol; i++ {
		A := sols[i]
		for j := i + 1; j < nsol; j++ {
			B := sols[j]
			o.closest(A, B)
		}
	}

	// skip if single-objective problem
	if o.prms.Nova < 2 {
		return
	}

	// compute wins/losses data
	for i := 0; i < nsol; i++ {
		A := sols[i]
		for j := i + 1; j < nsol; j++ {
			B := sols[j]
			A_win, B_win := A.Compare(B)
			if A_win {
				A.WinOver[A.Nwins] = B
				A.Nwins++
				B.Nlosses++
			}
			if B_win {
				B.WinOver[B.Nwins] = A
				B.Nwins++
				A.Nlosses++
			}
		}
	}

	// first front
	for _, sol := range sols {
		if sol.Nlosses == 0 {
			o.Fronts[0][z[0]] = sol
			z[0]++
		}
	}

	// next fronts
	for r, front := range o.Fronts {
		if z[r] == 0 {
			break
		}
		s := r + 1
		nfronts++
		for i := 0; i < z[r]; i++ {
			A := front[i]
			for j := 0; j < A.Nwins; j++ {
				B := A.WinOver[j]
				B.Nlosses--
				if B.Nlosses == 0 { // B belongs to next front
					B.FrontId = s
					o.Fronts[s][z[s]] = B
					z[s]++
				}
			}
		}
	}

	// crowd distances
	for r := 0; r < nfronts; r++ {
		l, m := z[r], z[r]-1
		if l == 1 {
			o.Fronts[r][0].DistCrowd = -1
			continue
		}
		F := o.Fronts[r][:l]
		for j := 0; j < o.prms.Nova; j++ {
			SortByOva(F, j)
			δ := o.Omax[j] - o.Omin[j] + 1e-15
			F[0].DistCrowd = INF
			F[m].DistCrowd = INF
			for i := 1; i < m; i++ {
				F[i].DistCrowd += ((F[i].Ova[j] - F[i-1].Ova[j]) / δ) * ((F[i+1].Ova[j] - F[i].Ova[j]) / δ)
			}
		}
	}
	return
}