func PrintIndicatorMatrix(x [][]int) (l string) { m, n := len(x), len(x[0]) w := 2*n + 6 + 13 l = io.Sf("%s i\\j |", io.StrThickLine(w)) for j := 0; j < n; j++ { l += io.Sf("%2d", j) } l += io.Sf(" | sum\n%s", io.StrThinLine(w)) S := make([]int, n) for i := 0; i < m; i++ { l += io.Sf(" %3d |", i) s := 0 for j := 0; j < n; j++ { l += io.Sf("%2d", x[i][j]) s += x[i][j] S[j] += x[i][j] } l += io.Sf(" | Σ xij = %2d\n", s) } l += io.Sf("%s sum =", io.StrThinLine(w)) for j := 0; j < n; j++ { l += io.Sf("%2d", S[j]) } l += io.Sf("\n%s", io.StrThickLine(w)) return }
// Run computes β starting witn an initial guess func (o *ReliabFORM) Run(βtrial float64, verbose bool, args ...interface{}) (β float64, μ, σ, x []float64) { // initial random variables β = βtrial nx := len(o.μ) μ = make([]float64, nx) // mean values (equivalent normal value) σ = make([]float64, nx) // deviation values (equivalent normal value) x = make([]float64, nx) // current vector of random variables defining min(β) for i := 0; i < nx; i++ { μ[i] = o.μ[i] σ[i] = o.σ[i] x[i] = o.μ[i] } // lognormal distribution structure var lnd DistLogNormal // has lognormal random variable? haslrv := false for _, found := range o.lrv { if found { haslrv = true break } } // function to compute β with x-constant // gβ(β) = g(μ - β・A・σ) = 0 var err error gβfcn := func(fy, y []float64) error { βtmp := y[0] for i := 0; i < nx; i++ { o.xtmp[i] = μ[i] - βtmp*o.α[i]*σ[i] } fy[0], err = o.gfcn(o.xtmp, args) if err != nil { chk.Panic("cannot compute gfcn(%v):\n%v", o.xtmp, err) } return nil } // derivative of gβ w.r.t β hβfcn := func(dfdy [][]float64, y []float64) error { βtmp := y[0] for i := 0; i < nx; i++ { o.xtmp[i] = μ[i] - βtmp*o.α[i]*σ[i] } err = o.hfcn(o.dgdx, o.xtmp, args) if err != nil { chk.Panic("cannot compute hfcn(%v):\n%v", o.xtmp, err) } dfdy[0][0] = 0 for i := 0; i < nx; i++ { dfdy[0][0] -= o.dgdx[i] * o.α[i] * σ[i] } return nil } // nonlinear solver with y[0] = β // solving: gβ(β) = g(μ - β・A・σ) = 0 var nls num.NlSolver nls.Init(1, gβfcn, nil, hβfcn, true, false, nil) defer nls.Clean() // message if verbose { io.Pf("\n%s", io.StrThickLine(60)) } // plotting plot := o.PlotFnk != "" if nx != 2 { plot = false } if plot { if o.PlotNp < 3 { o.PlotNp = 41 } var umin, umax, vmin, vmax float64 if o.PlotCf < 1 { o.PlotCf = 2 } if len(o.PlotUrange) == 0 { umin, umax = μ[0]-o.PlotCf*μ[0], μ[0]+o.PlotCf*μ[0] vmin, vmax = μ[1]-o.PlotCf*μ[1], μ[1]+o.PlotCf*μ[1] } else { chk.IntAssert(len(o.PlotUrange), 2) chk.IntAssert(len(o.PlotVrange), 2) umin, umax = o.PlotUrange[0], o.PlotUrange[1] vmin, vmax = o.PlotVrange[0], o.PlotVrange[1] } o.PlotU, o.PlotV = utl.MeshGrid2D(umin, umax, vmin, vmax, o.PlotNp, o.PlotNp) o.PlotZ = la.MatAlloc(o.PlotNp, o.PlotNp) plt.SetForEps(0.8, 300) for i := 0; i < o.PlotNp; i++ { for j := 0; j < o.PlotNp; j++ { o.xtmp[0] = o.PlotU[i][j] o.xtmp[1] = o.PlotV[i][j] o.PlotZ[i][j], err = o.gfcn(o.xtmp, args) if err != nil { chk.Panic("cannot compute gfcn(%v):\n%v", x, err) } } } plt.Contour(o.PlotU, o.PlotV, o.PlotZ, "") plt.ContourSimple(o.PlotU, o.PlotV, o.PlotZ, true, 8, "levels=[0], colors=['yellow']") plt.PlotOne(x[0], x[1], "'ro', label='initial'") } // iterations to find β var dat VarData B := []float64{β} itB := 0 for itB = 0; itB < o.NmaxItB; itB++ { // message if verbose { gx, err := o.gfcn(x, args) if err != nil { chk.Panic("cannot compute gfcn(%v):\n%v", x, err) } io.Pf("%s itB=%d β=%g g=%g\n", io.StrThinLine(60), itB, β, gx) } // plot if plot { plt.PlotOne(x[0], x[1], "'r.'") } // compute direction cosines itA := 0 for itA = 0; itA < o.NmaxItA; itA++ { // has lognormal random variable (lrv) if haslrv { // find equivalent normal mean and std deviation for lognormal variables for i := 0; i < nx; i++ { if o.lrv[i] { // set distribution dat.M, dat.S = o.μ[i], o.σ[i] lnd.Init(&dat) // update μ and σ fx := lnd.Pdf(x[i]) Φinvx := (math.Log(x[i]) - lnd.M) / lnd.S φx := math.Exp(-Φinvx*Φinvx/2.0) / math.Sqrt2 / math.SqrtPi σ[i] = φx / fx μ[i] = x[i] - Φinvx*σ[i] } } } // compute direction cosines err = o.hfcn(o.dgdx, x, args) if err != nil { chk.Panic("cannot compute hfcn(%v):\n%v", x, err) } den := 0.0 for i := 0; i < nx; i++ { den += math.Pow(o.dgdx[i]*σ[i], 2.0) } den = math.Sqrt(den) αerr := 0.0 // difference on α for i := 0; i < nx; i++ { αnew := o.dgdx[i] * σ[i] / den αerr += math.Pow(αnew-o.α[i], 2.0) o.α[i] = αnew } αerr = math.Sqrt(αerr) // message if verbose { io.Pf(" itA=%d\n", itA) io.Pf("%12s%12s%12s%12s\n", "x", "μ", "σ", "α") for i := 0; i < nx; i++ { io.Pf("%12.3f%12.3f%12.3f%12.3f\n", x[i], μ[i], σ[i], o.α[i]) } } // update x-star for i := 0; i < nx; i++ { x[i] = μ[i] - β*o.α[i]*σ[i] } // check convergence on α if itA > 1 && αerr < o.TolA { if verbose { io.Pfgrey(". . . converged on α with αerr=%g . . .\n", αerr) } break } } // failed to converge on α if itA == o.NmaxItA { chk.Panic("failed to convege on α") } // compute new β B[0] = β nls.Solve(B, o.NlsSilent) βerr := math.Abs(B[0] - β) β = B[0] if o.NlsCheckJ { nls.CheckJ(B, o.NlsCheckJtol, true, false) } // update x-star for i := 0; i < nx; i++ { x[i] = μ[i] - β*o.α[i]*σ[i] } // check convergence on β if βerr < o.TolB { if verbose { io.Pfgrey2(". . . converged on β with βerr=%g . . .\n", βerr) } break } } // failed to converge on β if itB == o.NmaxItB { chk.Panic("failed to converge on β") } // message if verbose { gx, err := o.gfcn(x, args) if err != nil { chk.Panic("cannot compute gfcn(%v):\n%v", x, err) } io.Pfgreen("x = %v\n", x) io.Pfgreen("g = %v\n", gx) io.PfGreen("β = %v\n", β) } // plot if plot { plt.Gll("$x_0$", "$x_1$", "") plt.Cross("") plt.SaveD("/tmp/gosl", "fig_form_"+o.PlotFnk+".eps") } return }
// Output generates a nice table with population data func (o Population) Output(C *ConfParams) (buf *bytes.Buffer) { // check if len(o) < 1 { return } // compute sizes and generate formats list if C.NumFmts == nil { sizes := make([][]int, 6) for _, ind := range o { sz := ind.GetStringSizes() for i := 0; i < 6; i++ { if len(sizes[i]) == 0 { sizes[i] = make([]int, len(sz[i])) } for j, s := range sz[i] { sizes[i][j] = utl.Imax(sizes[i][j], s) } } } name := []string{"int", "flt", "str", "key", "byt", "fun"} C.NumFmts = make(map[string][]string) for i, str := range []string{"d", "g", "s", "x", "s", "s"} { C.NumFmts[name[i]] = make([]string, len(sizes[i])) for j, sz := range sizes[i] { C.NumFmts[name[i]][j] = io.Sf("%%%d%s", sz+1, str) } } } // compute sizes of header items nova := len(o[0].Ovas) noor := len(o[0].Oors) szova, szoor, szdem := make([]int, nova), make([]int, noor), 0 for k, ind := range o { if C.ShowNinds > 0 && k >= C.ShowNinds { break } for i := 0; i < nova; i++ { szova[i] = utl.Imax(szova[i], len(io.Sf("%g", ind.Ovas[i]))) } if C.ShowOor { for i := 0; i < noor; i++ { szoor[i] = utl.Imax(szoor[i], len(io.Sf("%g", ind.Oors[i]))) } } szdem = utl.Imax(szdem, len(io.Sf("%g", ind.Demerit))) } for i := 0; i < nova; i++ { szova[i] = utl.Imax(szova[i], 5) // 5 ==> len("Ova##") } if C.ShowOor { for i := 0; i < noor; i++ { szoor[i] = utl.Imax(szoor[i], 5) // 5 ==> len("Oor####") } } szdem = utl.Imax(szdem, 7) // 7 ==> len("Demerit") // print individuals fmtova := make([]string, nova) fmtoor := make([]string, noor) for i := 0; i < nova; i++ { fmtova[i] = io.Sf("%%%d", szova[i]+1) } if C.ShowOor { for i := 0; i < noor; i++ { fmtoor[i] = io.Sf("%%%d", szoor[i]+1) } } fmtdem := io.Sf("%%%d", szdem+1) line, sza, szb := "", 0, 0 first := true for i, ind := range o { if C.ShowNinds > 0 && i >= C.ShowNinds { break } stra := "" for j := 0; j < nova; j++ { stra += io.Sf(fmtova[j]+"g", ind.Ovas[j]) } if C.ShowOor { for j := 0; j < noor; j++ { if ind.Oors[j] > 0 { stra += io.Sf(fmtoor[j]+"g", ind.Oors[j]) } else { stra += io.Sf(fmtoor[j]+"s", "n/a") } } } else { unfeasible := false for j := 0; j < noor; j++ { if ind.Oors[j] > 0 { unfeasible = true } } if unfeasible { stra += " unfe." } else { stra += " " } } if C.ShowDem { stra += io.Sf(fmtdem+"g", ind.Demerit) + " " } strb := ind.Output(C.NumFmts, C.ShowBases) line += stra + strb + "\n" if first { sza, szb = len(stra), len(strb) first = false } } // write to buffer fmtgenes := io.Sf("%%%d.%ds\n", szb, szb) n := sza + szb buf = new(bytes.Buffer) io.Ff(buf, io.StrThickLine(n)) for i := 0; i < nova; i++ { io.Ff(buf, fmtova[i]+"s", io.Sf("Ova%d", i)) } if C.ShowOor { for i := 0; i < noor; i++ { io.Ff(buf, fmtoor[i]+"s", io.Sf("Oor%d", i)) } } else { io.Ff(buf, " check") } if C.ShowDem { io.Ff(buf, fmtdem+"s ", "Demerit") } io.Ff(buf, fmtgenes, "Genes") io.Ff(buf, io.StrThinLine(n)) io.Ff(buf, line) io.Ff(buf, io.StrThickLine(n)) return }