Exemple #1
0
func PrintSolutions(fed *FemData, sols []*goga.Solution) (l string) {
	goga.SortByOva(sols, 0)
	l = io.Sf("%8s%6s%6s |%s\n", "weight", "umax", "smax", "areas")
	for _, sol := range sols {
		mob, fail, weight, umax, smax, errU, errS := fed.RunFEM(sol.Int, sol.Flt, 0, false)
		if mob > 0 || fail > 0 || errU > 0 || errS > 0 {
			l += io.Sf("%20s |%s\n", "unfeasible    ", FltFormatter(sol.Flt))
			continue
		}
		l += io.Sf("%8.1f%6.2f%6.2f |%s\n", weight, umax, smax, FltFormatter(sol.Flt))
	}
	return
}
Exemple #2
0
func solve_problem(problem int) (opt *goga.Optimiser) {

	io.Pf("\n\n------------------------------------- problem = %d ---------------------------------------\n", problem)

	// GA parameters
	opt = new(goga.Optimiser)
	opt.Default()
	opt.Nsol = 20
	opt.Ncpu = 1
	opt.Tf = 40
	opt.Verbose = false
	opt.EpsH = 1e-3

	// problem variables
	var ng, nh int
	var fcn goga.MinProb_t
	var cprms goga.ContourParams
	cprms.Npts = 201
	eps_prop := 0.8
	eps_size := 300.0

	// problems
	switch problem {

	// problem # 1: quadratic function with inequalities
	case 1:
		opt.FltMin = []float64{-2, -2}
		opt.FltMax = []float64{2, 2}
		ng, nh = 5, 0
		fcn = func(f, g, h, x []float64, ξ []int, cpu int) {
			f[0] = x[0]*x[0]/2.0 + x[1]*x[1] - x[0]*x[1] - 2.0*x[0] - 6.0*x[1]
			g[0] = 2.0 - x[0] - x[1]     // ≥ 0
			g[1] = 2.0 + x[0] - 2.0*x[1] // ≥ 0
			g[2] = 3.0 - 2.0*x[0] - x[1] // ≥ 0
			g[3] = x[0]                  // ≥ 0
			g[4] = x[1]                  // ≥ 0
		}

	// problem # 2: circle with equality constraint
	case 2:
		xe := 1.0                      // centre of circle
		le := -0.4                     // selected level of f(x)
		ys := xe - (1.0+le)/math.Sqrt2 // coordinates of minimum point with level=le
		y0 := 2.0*ys + xe              // vertical axis intersect of straight line defined by c(x)
		xc := []float64{xe, xe}        // centre
		opt.FltMin = []float64{-1, -1}
		opt.FltMax = []float64{3, 3}
		ng, nh = 0, 1
		fcn = func(f, g, h, x []float64, ξ []int, cpu int) {
			res := 0.0
			for i := 0; i < len(x); i++ {
				res += (x[i] - xc[i]) * (x[i] - xc[i])
			}
			f[0] = math.Sqrt(res) - 1.0
			h[0] = x[0] + x[1] + xe - y0
		}

	// problem # 3: Deb (2000) narrow crescent-shaped region
	case 3:
		opt.FltMin = []float64{0, 0}
		opt.FltMax = []float64{6, 6}
		ng, nh = 2, 0
		fcn = func(f, g, h, x []float64, ξ []int, cpu int) {
			f[0] = math.Pow(x[0]*x[0]+x[1]-11.0, 2.0) + math.Pow(x[0]+x[1]*x[1]-7.0, 2.0)
			g[0] = 4.84 - math.Pow(x[0]-0.05, 2.0) - math.Pow(x[1]-2.5, 2.0) // ≥ 0
			g[1] = x[0]*x[0] + math.Pow(x[1]-2.5, 2.0) - 4.84                // ≥ 0
		}
		cprms.Args = "levels=[1, 10, 25, 50, 100, 200, 400, 600, 1000, 1500]"
		cprms.Csimple = true
		cprms.Lwg = 0.6
		eps_prop = 1
	}

	// initialise optimiser
	nf := 1
	opt.Init(goga.GenTrialSolutions, nil, fcn, nf, ng, nh)

	// initial solutions
	sols0 := opt.GetSolutionsCopy()

	// solve
	opt.Solve()

	// results
	goga.SortByOva(opt.Solutions, 0)
	best := opt.Solutions[0]
	io.Pforan("X_best = %v\n", best.Flt)
	io.Pforan("F_best = %v\n", best.Ova[0])
	io.Pforan("Oor    = %v\n", best.Oor)

	// text box
	extra := func() {
		str := io.Sf("$f(%.5f,%.5f)=%.5f$", best.Flt[0], best.Flt[1], best.Ova[0])
		plt.Text(0.98, 0.03, str, "size=12, transform=gca().transAxes, ha='right', zorder=2000, bbox=dict(boxstyle='round', facecolor='lightgray')")
	}

	// plot
	plt.SetForEps(eps_prop, eps_size)
	goga.PlotFltFltContour(io.Sf("simpleoptm%d", problem), opt, sols0, 0, 1, 0, cprms, extra, true)
	return opt
}
Exemple #3
0
func runone(ncpu int) (nsol, tf int, elaspsedTime time.Duration) {

	// input filename
	fn, fnkey := io.ArgToFilename(0, "ground10", ".sim", true)

	// GA parameters
	var opt goga.Optimiser
	opt.Read("ga-" + fnkey + ".json")
	opt.GenType = "rnd"
	nsol, tf = opt.Nsol, opt.Tf
	postproc := true
	if ncpu > 0 {
		opt.Ncpu = ncpu
		postproc = false
	}

	// FEM
	data := make([]*FemData, opt.Ncpu)
	for i := 0; i < opt.Ncpu; i++ {
		data[i] = NewData(fn, fnkey, i)
	}
	io.Pforan("MaxWeight = %v\n", data[0].MaxWeight)

	// set integers
	if data[0].Opt.BinInt {
		opt.CxInt = goga.CxInt
		opt.MtInt = goga.MtIntBin
		opt.BinInt = data[0].Ncells
	}

	// set floats
	opt.FltMin = make([]float64, data[0].Nareas)
	opt.FltMax = make([]float64, data[0].Nareas)
	for i := 0; i < data[0].Nareas; i++ {
		opt.FltMin[i] = data[0].Opt.Amin
		opt.FltMax[i] = data[0].Opt.Amax
	}

	// initialise optimiser
	opt.Nova = 2 // weight and deflection
	opt.Noor = 4 // mobility, feasibility, maxdeflection, stress
	opt.Init(goga.GenTrialSolutions, func(sol *goga.Solution, cpu int) {
		mob, fail, weight, umax, _, errU, errS := data[cpu].RunFEM(sol.Int, sol.Flt, 0, false)
		sol.Ova[0] = weight
		sol.Ova[1] = umax
		sol.Oor[0] = mob
		sol.Oor[1] = fail
		sol.Oor[2] = errU
		sol.Oor[3] = errS
	}, nil, 0, 0, 0)

	// initial solutions
	var sols0 []*goga.Solution
	if false {
		sols0 = opt.GetSolutionsCopy()
	}

	// benchmark
	initialTime := time.Now()
	defer func() {
		elaspsedTime = time.Now().Sub(initialTime)
	}()

	// solve
	opt.Verbose = true
	opt.Solve()
	goga.SortByOva(opt.Solutions, 0)

	// post processing
	if !postproc {
		return
	}

	// check
	nfailed, front0 := goga.CheckFront0(&opt, true)

	// save results
	var log, res bytes.Buffer
	io.Ff(&log, opt.LogParams())
	io.Ff(&res, PrintSolutions(data[0], opt.Solutions))
	io.Ff(&res, io.Sf("\n\nnfailed = %d\n", nfailed))
	io.WriteFileVD("/tmp/goga", fnkey+".log", &log)
	io.WriteFileVD("/tmp/goga", fnkey+".res", &res)

	// plot Pareto-optimal front
	feasibleOnly := true
	plt.SetForEps(0.8, 350)
	if strings.HasPrefix(fnkey, "ground10") {
		_, ref, _ := io.ReadTable("p460_fig300.dat")
		plt.Plot(ref["w"], ref["u"], "'b-', label='reference'")
	}
	fmtAll := &plt.Fmt{L: "final solutions", M: ".", C: "orange", Ls: "none", Ms: 3}
	fmtFront := &plt.Fmt{L: "final Pareto front", C: "r", M: "o", Ms: 3, Ls: "none"}
	goga.PlotOvaOvaPareto(&opt, sols0, 0, 1, feasibleOnly, fmtAll, fmtFront)
	plt.Gll("weight ($f_0$)", "deflection ($f_1)$", "") //, "leg_out=1, leg_ncol=4, leg_hlen=1.5")
	if strings.HasPrefix(fnkey, "ground10") {
		plt.AxisRange(1800, 14000, 1, 6)
	}

	// plot selected results
	ia, ib, ic, id, ie := 0, 0, 0, 0, 0
	nfront0 := len(front0)
	io.Pforan("nfront0 = %v\n", nfront0)
	if nfront0 > 4 {
		ib = nfront0 / 10
		ic = nfront0 / 5
		id = nfront0 / 2
		ie = nfront0 - 1
	}
	A := front0[ia]
	B := front0[ib]
	C := front0[ic]
	D := front0[id]
	E := front0[ie]
	wid, hei := 0.20, 0.10
	draw_truss(data[0], "A", A, 0.17, 0.75, wid, hei)
	draw_truss(data[0], "B", B, 0.20, 0.55, wid, hei)
	draw_truss(data[0], "C", C, 0.28, 0.33, wid, hei)
	draw_truss(data[0], "D", D, 0.47, 0.22, wid, hei)
	draw_truss(data[0], "E", E, 0.70, 0.18, wid, hei)

	// save figure
	plt.SaveD("/tmp/goga", fnkey+".eps")

	// tex file
	title := "Shape and topology optimisation. Results."
	label := "topoFront"
	document := true
	compact := true
	tex_results("/tmp/goga", "tmp_"+fnkey, title, label, data[0], A, B, C, D, E, document, compact)
	document = false
	tex_results("/tmp/goga", fnkey, title, label, data[0], A, B, C, D, E, document, compact)
	return
}
Exemple #4
0
func solve_problem(fnkey string, problem int) (opt *goga.Optimiser) {

	// GA parameters
	opt = new(goga.Optimiser)
	opt.Default()

	// options for report
	opt.RptFmtF = "%.4f"
	opt.RptFmtX = "%.3f"
	opt.RptFmtFdev = "%.1e"
	opt.RptWordF = "\\beta"
	opt.HistFmt = "%.2f"
	opt.HistNdig = 3
	opt.HistDelFmin = 0.005
	opt.HistDelFmax = 0.005

	// FORM data
	var lsft LSF_T
	var vars rnd.Variables

	// simple problem or FEM sim
	if fnkey == "simple" {
		opt.Read("ga-simple.json")
		opt.ProbNum = problem
		lsft, vars = get_simple_data(opt)
		fnkey += io.Sf("-%d", opt.ProbNum)
		io.Pf("\n----------------------------------- simple problem %d --------------------------------\n", opt.ProbNum)
	} else {
		opt.Read("ga-" + fnkey + ".json")
		lsft, vars = get_femsim_data(opt, fnkey)
		io.Pf("\n----------------------------------- femsim %s --------------------------------\n", fnkey)
	}

	// set limits
	nx := len(vars)
	opt.FltMin = make([]float64, nx)
	opt.FltMax = make([]float64, nx)
	for i, dat := range vars {
		opt.FltMin[i] = dat.Min
		opt.FltMax[i] = dat.Max
	}

	// log input
	var buf bytes.Buffer
	io.Ff(&buf, "%s", opt.LogParams())
	io.WriteFileVD("/tmp/gosl", fnkey+".log", &buf)

	// initialise distributions
	err := vars.Init()
	if err != nil {
		chk.Panic("cannot initialise distributions:\n%v", err)
	}

	// plot distributions
	if opt.PlotSet1 {
		io.Pf(". . . . . . . .  plot distributions  . . . . . . . .\n")
		np := 201
		for i, dat := range vars {
			plt.SetForEps(0.75, 250)
			dat.PlotPdf(np, "'b-',lw=2,zorder=1000")
			//plt.AxisXrange(dat.Min, dat.Max)
			plt.SetXnticks(15)
			plt.SaveD("/tmp/sims", io.Sf("distr-%s-%d.eps", fnkey, i))
		}
		return
	}

	// objective function
	nf := 1
	var ng, nh int
	var fcn goga.MinProb_t
	var obj goga.ObjFunc_t
	switch opt.Strategy {

	// argmin_x{ β(y(x)) | lsf(x) ≤ 0 }
	//  f ← sqrt(y dot y)
	//  g ← -lsf(x) ≥ 0
	//  h ← out-of-range in case Transform fails
	case 0:
		ng, nh = 1, 1
		fcn = func(f, g, h, x []float64, ξ []int, cpu int) {

			// original and normalised variables
			h[0] = 0
			y, invalid := vars.Transform(x)
			if invalid {
				h[0] = 1
				return
			}

			// objective value
			f[0] = math.Sqrt(la.VecDot(y, y)) // β

			// inequality constraint
			lsf, failed := lsft(x, cpu)
			g[0] = -lsf
			h[0] = failed
		}

	// argmin_x{ β(y(x)) | lsf(x) = 0 }
	//  f  ← sqrt(y dot y)
	//  h0 ← lsf(x)
	//  h1 ← out-of-range in case Transform fails
	case 1:
		ng, nh = 0, 2
		fcn = func(f, g, h, x []float64, ξ []int, cpu int) {

			// original and normalised variables
			h[0], h[1] = 0, 0
			y, invalid := vars.Transform(x)
			if invalid {
				h[0], h[1] = 1, 1
				return
			}

			// objective value
			f[0] = math.Sqrt(la.VecDot(y, y)) // β

			// equality constraint
			lsf, failed := lsft(x, cpu)
			h[0] = lsf
			h[1] = failed

			// induce minmisation of h0
			//f[0] += math.Abs(lsf)
		}

	case 2:
		opt.Nova = 1
		opt.Noor = 2
		obj = func(sol *goga.Solution, cpu int) {

			// clear out-of-range values
			sol.Oor[0] = 0 // invalid transformation or FEM failed
			sol.Oor[1] = 0 // g(x) ≤ 0 was violated

			// original and normalised variables
			x := sol.Flt
			y, invalid := vars.Transform(x)
			if invalid {
				sol.Oor[0] = goga.INF
				sol.Oor[1] = goga.INF
				return
			}

			// objective value
			sol.Ova[0] = math.Sqrt(la.VecDot(y, y)) // β

			// inequality constraint
			lsf, failed := lsft(x, cpu)
			sol.Oor[0] = failed
			sol.Oor[1] = fun.Ramp(lsf)
		}

	default:
		chk.Panic("strategy %d is not available", opt.Strategy)
	}

	// initialise optimiser
	opt.Init(goga.GenTrialSolutions, obj, fcn, nf, ng, nh)

	// solve
	io.Pf(". . . . . . . .  running  . . . . . . . .\n")
	opt.RunMany("", "")
	goga.StatF(opt, 0, true)
	io.Pfblue2("Tsys = %v\n", opt.SysTimeAve)

	// check
	goga.CheckFront0(opt, true)

	// results
	sols := goga.GetFeasible(opt.Solutions)
	if len(sols) > 0 {
		goga.SortByOva(sols, 0)
		best := sols[0]
		io.Pforan("x    = %.6f\n", best.Flt)
		io.Pforan("xref = %.6f\n", opt.RptXref)
		io.Pforan("β = %v  (%v)\n", best.Ova[0], opt.RptFref[0])
	}
	return
}
Exemple #5
0
func solve_problem(problem int) (opt *goga.Optimiser) {

	io.Pf("\n\n------------------------------------- problem = %d ---------------------------------------\n", problem)

	// GA parameters
	opt = new(goga.Optimiser)
	opt.Default()
	opt.Nsol = 200
	opt.Ncpu = 5
	opt.Tf = 500
	opt.Nsamples = 2
	opt.DEC = 0.01

	// options for report
	opt.HistNsta = 6
	opt.HistLen = 13
	opt.RptFmtE = "%.4e"
	opt.RptFmtL = "%.4e"
	opt.RptFmtEdev = "%.3e"
	opt.RptFmtLdev = "%.3e"
	opt.RptFmin = make([]float64, 3)
	opt.RptFmax = make([]float64, 3)
	for i := 0; i < 3; i++ {
		opt.RptFmax[i] = 1
	}

	// problem variables
	var αcone float64        // cone half-opening angle
	var nf, ng, nh int       // number of functions
	var fcn goga.MinProb_t   // functions
	var plot_solution func() // plot solution in 3D

	// problems
	switch problem {

	// DTLZ1
	case 1:
		opt.RptName = "DTLZ1"
		opt.FltMin = make([]float64, 7)
		opt.FltMax = make([]float64, 7)
		for i := 0; i < 7; i++ {
			opt.FltMin[i], opt.FltMax[i] = 0, 1
		}
		nf, ng, nh = 3, 0, 0
		fcn = func(f, g, h, x []float64, ξ []int, cpu int) {
			c := 5.0
			for i := 2; i < 7; i++ {
				c += math.Pow((x[i]-0.5), 2.0) - math.Cos(20.0*PI*(x[i]-0.5))
			}
			c *= 100.0
			f[0] = 0.5 * x[0] * x[1] * (1.0 + c)
			f[1] = 0.5 * x[0] * (1.0 - x[1]) * (1.0 + c)
			f[2] = 0.5 * (1.0 - x[0]) * (1.0 + c)
		}
		opt.Multi_fcnErr = func(f []float64) float64 {
			return f[0] + f[1] + f[2] - 0.5
		}
		plot_solution = func() { plot_plane(false) }
		opt.RptFmax = []float64{0.5, 0.5, 0.5}

	// DTLZ2
	case 2:
		opt.RptName = "DTLZ2"
		opt.FltMin = make([]float64, 12)
		opt.FltMax = make([]float64, 12)
		for i := 0; i < 12; i++ {
			opt.FltMin[i], opt.FltMax[i] = 0, 1
		}
		nf, ng, nh = 3, 0, 0
		fcn = func(f, g, h, x []float64, ξ []int, cpu int) {
			var c float64
			for i := 2; i < 12; i++ {
				c += math.Pow((x[i] - 0.5), 2.0)
			}
			f[0] = (1.0 + c) * math.Cos(x[0]*PI/2.0) * math.Cos(x[1]*PI/2.0)
			f[1] = (1.0 + c) * math.Cos(x[0]*PI/2.0) * math.Sin(x[1]*PI/2.0)
			f[2] = (1.0 + c) * math.Sin(x[0]*PI/2.0)
		}
		opt.Multi_fcnErr = func(f []float64) float64 {
			return f[0]*f[0] + f[1]*f[1] + f[2]*f[2] - 1.0
		}
		plot_solution = func() { plot_sphere(false) }

	// DTLZ3
	case 3:
		opt.RptName = "DTLZ3"
		opt.FltMin = make([]float64, 12)
		opt.FltMax = make([]float64, 12)
		for i := 0; i < 12; i++ {
			opt.FltMin[i], opt.FltMax[i] = 0, 1
		}
		nf, ng, nh = 3, 0, 0
		fcn = func(f, g, h, x []float64, ξ []int, cpu int) {
			c := 10.0
			for i := 2; i < 12; i++ {
				c += math.Pow((x[i]-0.5), 2.0) - math.Cos(20.0*PI*(x[i]-0.5))
			}
			c *= 100.0
			f[0] = (1.0 + c) * math.Cos(x[0]*PI/2.0) * math.Cos(x[1]*PI/2.0)
			f[1] = (1.0 + c) * math.Cos(x[0]*PI/2.0) * math.Sin(x[1]*PI/2.0)
			f[2] = (1.0 + c) * math.Sin(x[0]*PI/2.0)
		}
		opt.Multi_fcnErr = func(f []float64) float64 {
			return f[0]*f[0] + f[1]*f[1] + f[2]*f[2] - 1.0
		}
		plot_solution = func() { plot_sphere(false) }

	// DTLZ4
	case 4:
		opt.RptName = "DTLZ4"
		opt.FltMin = make([]float64, 12)
		opt.FltMax = make([]float64, 12)
		for i := 0; i < 12; i++ {
			opt.FltMin[i], opt.FltMax[i] = 0, 1
		}
		nf, ng, nh = 3, 0, 0
		fcn = func(f, g, h, x []float64, ξ []int, cpu int) {
			var c float64
			for i := 2; i < 12; i++ {
				c += math.Pow((x[i] - 0.5), 2.0)
			}
			a := 100.0
			f[0] = (1.0 + c) * math.Cos(math.Pow(x[0], a)*PI/2.0) * math.Cos(math.Pow(x[1], a)*PI/2.0)
			f[1] = (1.0 + c) * math.Cos(math.Pow(x[0], a)*PI/2.0) * math.Sin(math.Pow(x[1], a)*PI/2.0)
			f[2] = (1.0 + c) * math.Sin(math.Pow(x[0], a)*PI/2.0)
		}
		opt.Multi_fcnErr = func(f []float64) float64 {
			return f[0]*f[0] + f[1]*f[1] + f[2]*f[2] - 1.0
		}
		plot_solution = func() { plot_sphere(false) }

	// DTLZ2x (convex)
	case 5:
		opt.RptName = "DTLZ2x"
		opt.FltMin = make([]float64, 12)
		opt.FltMax = make([]float64, 12)
		for i := 0; i < 12; i++ {
			opt.FltMin[i], opt.FltMax[i] = 0, 1
		}
		nf, ng, nh = 3, 0, 0
		fcn = func(f, g, h, x []float64, ξ []int, cpu int) {
			var c float64
			for i := 2; i < 12; i++ {
				c += math.Pow((x[i] - 0.5), 2.0)
			}
			f[0] = (1.0 + c) * math.Cos(x[0]*PI/2.0) * math.Cos(x[1]*PI/2.0)
			f[1] = (1.0 + c) * math.Cos(x[0]*PI/2.0) * math.Sin(x[1]*PI/2.0)
			f[2] = (1.0 + c) * math.Sin(x[0]*PI/2.0)
			f[0] = math.Pow(f[0], 4.0)
			f[1] = math.Pow(f[1], 4.0)
			f[2] = math.Pow(f[2], 2.0)
		}
		opt.Multi_fcnErr = func(f []float64) float64 {
			return math.Pow(math.Abs(f[0]), 0.5) + math.Pow(math.Abs(f[1]), 0.5) + f[2] - 1.0
		}
		plot_solution = func() { plot_convex(1.0, false) }

	// DTLZ2c (constraint)
	case 6:
		opt.RptName = "DTLZ2c"
		opt.FltMin = make([]float64, 12)
		opt.FltMax = make([]float64, 12)
		for i := 0; i < 12; i++ {
			opt.FltMin[i], opt.FltMax[i] = 0, 1
		}
		nf, ng, nh = 3, 1, 0
		//αcone = math.Atan(1.0 / SQ2) // <<< touches lower plane
		//αcone = PI/2.0 - αcone // <<< touches upper plane
		αcone = 15.0 * PI / 180.0
		fcn = func(f, g, h, x []float64, ξ []int, cpu int) {
			var c float64
			for i := 2; i < 12; i++ {
				c += math.Pow((x[i] - 0.5), 2.0)
			}
			f[0] = (1.0 + c) * math.Cos(x[0]*PI/2.0) * math.Cos(x[1]*PI/2.0)
			f[1] = (1.0 + c) * math.Cos(x[0]*PI/2.0) * math.Sin(x[1]*PI/2.0)
			f[2] = (1.0 + c) * math.Sin(x[0]*PI/2.0)
			g[0] = math.Tan(αcone) - cone_angle(f)
		}
		opt.Multi_fcnErr = func(f []float64) float64 {
			return f[0]*f[0] + f[1]*f[1] + f[2]*f[2] - 1.0
		}
		plot_solution = func() {
			plot_sphere(false)
			plot_cone(αcone, true)
		}

	// Superquadric 1
	case 7:
		opt.RptName = "SUQ1"
		opt.FltMin = make([]float64, 12)
		opt.FltMax = make([]float64, 12)
		for i := 0; i < 12; i++ {
			opt.FltMin[i], opt.FltMax[i] = 0, 1
		}
		a, b, c := 0.5, 0.5, 0.5
		A, B, C := 2.0/a, 2.0/b, 2.0/c
		nf, ng, nh = 3, 0, 0
		fcn = func(f, g, h, x []float64, ξ []int, cpu int) {
			var c float64
			for i := 2; i < 12; i++ {
				c += math.Pow((x[i] - 0.5), 2.0)
			}
			f[0] = (1.0 + c) * cosX(x[0]*PI/2.0, A) * cosX(x[1]*PI/2.0, A)
			f[1] = (1.0 + c) * cosX(x[0]*PI/2.0, B) * sinX(x[1]*PI/2.0, B)
			f[2] = (1.0 + c) * sinX(x[0]*PI/2.0, C)
		}
		opt.Multi_fcnErr = func(f []float64) float64 {
			return math.Pow(math.Abs(f[0]), a) + math.Pow(math.Abs(f[1]), b) + math.Pow(math.Abs(f[2]), c) - 1.0
		}
		plot_solution = func() { plot_superquadric(a, b, c, false) }

	// Superquadric 2
	case 8:
		opt.RptName = "SUQ2"
		opt.FltMin = make([]float64, 12)
		opt.FltMax = make([]float64, 12)
		for i := 0; i < 12; i++ {
			opt.FltMin[i], opt.FltMax[i] = 0, 1
		}
		a, b, c := 2.0, 1.0, 0.5
		A, B, C := 2.0/a, 2.0/b, 2.0/c
		nf, ng, nh = 3, 0, 0
		fcn = func(f, g, h, x []float64, ξ []int, cpu int) {
			var c float64
			for i := 2; i < 12; i++ {
				c += math.Pow((x[i] - 0.5), 2.0)
			}
			f[0] = (1.0 + c) * cosX(x[0]*PI/2.0, A) * cosX(x[1]*PI/2.0, A)
			f[1] = (1.0 + c) * cosX(x[0]*PI/2.0, B) * sinX(x[1]*PI/2.0, B)
			f[2] = (1.0 + c) * sinX(x[0]*PI/2.0, C)
		}
		opt.Multi_fcnErr = func(f []float64) float64 {
			return math.Pow(math.Abs(f[0]), a) + math.Pow(math.Abs(f[1]), b) + math.Pow(math.Abs(f[2]), c) - 1.0
		}
		plot_solution = func() { plot_superquadric(a, b, c, false) }

	default:
		chk.Panic("problem %d is not available", problem)
	}

	// initialise optimiser
	opt.Init(goga.GenTrialSolutions, nil, fcn, nf, ng, nh)

	// solve
	opt.RunMany("", "")
	goga.StatMulti(opt, true)

	// check
	goga.CheckFront0(opt, true)

	// print results
	if false {
		goga.SortByOva(opt.Solutions, 0)
		m, l := opt.Nsol/2, opt.Nsol-1
		A, B, C := opt.Solutions[0], opt.Solutions[m], opt.Solutions[l]
		io.Pforan("A = %v\n", A.Flt)
		io.Pforan("B = %v\n", B.Flt)
		io.Pforan("C = %v\n", C.Flt)
	}

	// plot results
	if false {
		py_plot3(0, 1, nf-1, opt, plot_solution, true, true)
	}

	// vtk
	if false {
		ptRad := 0.015
		if opt.RptName == "DTLZ1" {
			ptRad = 0.01
		}
		vtk_plot3(opt, αcone, ptRad, true, true)
	}

	// star plot
	if false {
		plt.SetForEps(1, 300)
		goga.PlotStar(opt)
		plt.SaveD("/tmp/goga", io.Sf("starplot_%s.eps", opt.RptName))
	}

	// write all results
	if false {
		goga.WriteAllValues("/tmp/goga", "res_three-obj", opt)
	}
	return
}