// PlotTwoVarsContour plots contour for two variables problem. len(x) == 2 // Input // dirout -- directory to save files // fnkey -- file name key for eps figure // x -- solution. can be <nil> // np -- number of points for contour // extra -- called just before saving figure // axequal -- axis.equal // vmin -- min 0 values // vmax -- max 1 values // f -- function to plot filled contour. can be <nil> // gs -- functions to plot contour @ level 0. can be <nil> func PlotTwoVarsContour(dirout, fnkey string, x []float64, np int, extra func(), axequal bool, vmin, vmax []float64, f TwoVarsFunc_t, gs ...TwoVarsFunc_t) { if fnkey == "" { return } chk.IntAssert(len(vmin), 2) chk.IntAssert(len(vmax), 2) V0, V1 := utl.MeshGrid2D(vmin[0], vmax[0], vmin[1], vmax[1], np, np) var Zf [][]float64 var Zg [][][]float64 if f != nil { Zf = la.MatAlloc(np, np) } if len(gs) > 0 { Zg = utl.Deep3alloc(len(gs), np, np) } xtmp := make([]float64, 2) for i := 0; i < np; i++ { for j := 0; j < np; j++ { xtmp[0], xtmp[1] = V0[i][j], V1[i][j] if f != nil { Zf[i][j] = f(xtmp) } for k, g := range gs { Zg[k][i][j] = g(xtmp) } } } plt.Reset() plt.SetForEps(0.8, 350) if f != nil { cmapidx := 0 plt.Contour(V0, V1, Zf, io.Sf("fsz=7, cmapidx=%d", cmapidx)) } for k, _ := range gs { plt.ContourSimple(V0, V1, Zg[k], false, 8, "zorder=5, levels=[0], colors=['yellow'], linewidths=[2], clip_on=0") } if x != nil { plt.PlotOne(x[0], x[1], "'r*', label='optimum', zorder=10") } if extra != nil { extra() } if dirout == "" { dirout = "." } plt.Cross("clr='grey'") plt.SetXnticks(11) plt.SetYnticks(11) if axequal { plt.Equal() } plt.AxisRange(vmin[0], vmax[0], vmin[1], vmax[1]) args := "leg_out='1', leg_ncol=4, leg_hlen=1.5" plt.Gll("$x_0$", "$x_1$", args) plt.SaveD(dirout, fnkey+".eps") }
func Test_bins02(tst *testing.T) { //verbose() chk.PrintTitle("bins02. find along line (2D)") // bins var bins Bins bins.Init([]float64{-0.2, -0.2}, []float64{0.8, 1.8}, 5) // fill bins structure maxit := 5 // number of entries ID := make([]int, maxit) for k := 0; k < maxit; k++ { x := float64(k) / float64(maxit) ID[k] = k err := bins.Append([]float64{x, 2*x + 0.2}, ID[k]) if err != nil { chk.Panic(err.Error()) } } // add more points to bins for i := 0; i < 5; i++ { err := bins.Append([]float64{float64(i) * 0.1, 1.8}, 100+i) if err != nil { chk.Panic(err.Error()) } } // message for _, bin := range bins.All { if bin != nil { io.Pf("%v\n", bin) } } // find points along diagonal ids := bins.FindAlongSegment([]float64{0.0, 0.2}, []float64{0.8, 1.8}, 1e-8) io.Pforan("ids = %v\n", ids) chk.Ints(tst, "ids", ids, ID) // find additional points ids = bins.FindAlongSegment([]float64{-0.2, 1.8}, []float64{0.8, 1.8}, 1e-8) io.Pfcyan("ids = %v\n", ids) chk.Ints(tst, "ids", ids, []int{100, 101, 102, 103, 104, 4}) // draw if chk.Verbose { plt.SetForPng(1, 500, 150) bins.Draw2d(true, true, true, true, map[int]bool{8: true, 9: true, 10: true}) plt.SetXnticks(15) plt.SetYnticks(15) plt.SaveD("/tmp/gosl/gm", "test_bins02.png") } }
// PlotFltFlt plots flt-flt contour // use iFlt==-1 || jFlt==-1 to plot all combinations func (o *Optimiser) PlotFltFltContour(sols0 []*Solution, iFlt, jFlt, iOva int, pp *PlotParams) { best, _ := GetBestFeasible(o, iOva) plotAll := iFlt < 0 || jFlt < 0 plotCommands := func(i, j int) { o.PlotContour(i, j, iOva, pp) if sols0 != nil { o.PlotAddFltFlt(i, j, sols0, &pp.FmtSols0) } o.PlotAddFltFlt(i, j, o.Solutions, &pp.FmtSols) if best != nil { plt.PlotOne(best.Flt[i], best.Flt[j], pp.FmtBest.GetArgs("")) } if pp.Extra != nil { pp.Extra() } if pp.AxEqual { plt.Equal() } } if plotAll { idx := 1 ncol := o.Nflt - 1 for row := 0; row < o.Nflt; row++ { idx += row for col := row + 1; col < o.Nflt; col++ { plt.Subplot(ncol, ncol, idx) plt.SplotGap(0.0, 0.0) plotCommands(col, row) if col > row+1 { plt.SetXnticks(0) plt.SetYnticks(0) } else { plt.Gll(io.Sf("$x_{%d}$", col), io.Sf("$x_{%d}$", row), "leg=0") } idx++ } } idx = ncol*(ncol-1) + 1 plt.Subplot(ncol, ncol, idx) plt.AxisOff() // TODO: fix formatting of open marker, add star to legend plt.DrawLegend([]plt.Fmt{pp.FmtSols0, pp.FmtSols, pp.FmtBest}, 8, "center", false, "") } else { plotCommands(iFlt, jFlt) if pp.Xlabel == "" { plt.Gll(io.Sf("$x_{%d}$", iFlt), io.Sf("$x_{%d}$", jFlt), pp.LegPrms) } else { plt.Gll(pp.Xlabel, pp.Ylabel, pp.LegPrms) } } plt.SaveD(pp.DirOut, pp.FnKey+pp.FnExt) }
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 }
func main() { PI := math.Pi yf := func(x float64) float64 { return 1.0 - math.Sqrt(x) - math.Sin(10.0*math.Pi*x)*x } dydx := func(x float64) float64 { return -math.Sin(10.0*PI*x) - 10.0*PI*x*math.Cos(10.0*PI*x) - 1.0/(2.0*math.Sqrt(x)) } var nlsDY num.NlSolver nlsDY.Init(1, func(fx, x []float64) error { fx[0] = dydx(x[0]) return nil }, nil, nil, false, true, nil) defer nlsDY.Clean() X := []float64{0.09, 0.25, 0.45, 0.65, 0.85} Y := make([]float64, len(X)) for i, x := range X { // find min xx := []float64{x} err := nlsDY.Solve(xx, true) if err != nil { io.PfRed("dydx nls failed:\n%v", err) return } X[i] = xx[0] Y[i] = yf(X[i]) } // find next point along horizontal line Xnext := []float64{0.2, 0.4, 0.6, 0.8} Ynext := make([]float64, len(Xnext)) for i, xnext := range Xnext { var nlsX num.NlSolver nlsX.Init(1, func(fx, x []float64) error { fx[0] = Y[i] - yf(x[0]) return nil }, nil, nil, false, true, nil) defer nlsX.Clean() xx := []float64{xnext} err := nlsX.Solve(xx, true) if err != nil { io.PfRed("dydx nls failed:\n%v", err) return } Xnext[i] = xx[0] Ynext[i] = yf(Xnext[i]) } // auxiliary points XX := []float64{ 0, X[0], Xnext[0], X[1], Xnext[1], X[2], Xnext[2], X[3], Xnext[3], X[4], } YY := []float64{ 1, Y[0], Ynext[0], Y[1], Ynext[1], Y[2], Ynext[2], Y[3], Ynext[3], Y[4], } io.Pforan("XX = %.3f\n", XX) io.Pforan("YY = %.3f\n", YY) // find arc-length arclen := 0.0 for i := 0; i < len(XX); i += 2 { a := XX[i] b := XX[i+1] if i == 0 { a += 1e-7 } var quad num.Simp quad.Init(func(x float64) float64 { return math.Sqrt(1.0 + math.Pow(dydx(x), 2.0)) }, a, b, 1e-4) res, err := quad.Integrate() if err != nil { io.PfRed("quad failed:\n%v", err) return } arclen += res io.Pf("int(...) from %.15f to %.15f = %g\n", a, b, res) } io.Pforan("arclen = %v\n", arclen) np := 201 xx := utl.LinSpace(0, 1, np) yy := make([]float64, np) for i := 0; i < np; i++ { yy[i] = yf(xx[i]) } plt.Plot(xx, yy, "'b-', clip_on=0") for i, x := range X { plt.PlotOne(x, Y[i], "'r|', mew=2, ms=30, clip_on=0") } for i, x := range Xnext { plt.PlotOne(x, Ynext[i], "'r_', mew=2, ms=30, clip_on=0") } for i := 0; i < len(XX); i += 2 { x0, y0 := XX[i], YY[i] x1, y1 := XX[i+1], YY[i+1] plt.Arrow(x0, y0, x1, y1, "") } plt.SetXnticks(11) plt.Gll("x", "y", "") plt.SaveD("/tmp/goga", "calcZDT3pts.eps") }