func (sol ProjGrad) Solve(o Grad, proj Projection, in *Solution, p *Params, u ...Updater) *Result { r := NewResult(in) obj := ObjGradWrapper{r: r, o: o} r.initGrad(obj) h := newHelper(r.Solution, u) n := len(r.X) s := 1.0 //initial step size d := mat.NewVec(n) d.Copy(r.GradX) d.Scal(-1) xTemp := mat.NewVec(n) xTemp.Copy(r.X) xTemp.Axpy(s/2, d) proj.Project(xTemp) xTemp.Sub(xTemp, r.X) xTemp.Scal(2 / s) gLin := -xTemp.Nrm2Sq() lineFunc := NewLineFuncProj(obj, proj, r.X, d) lsInit := uni.NewSolution() lsParams := uni.NewParams() for ; r.Status == NotTerminated; h.update(r, p) { lsInit.SetX(s) lsInit.SetLB(0, r.ObjX, gLin) lsRes := sol.LineSearch.Solve(lineFunc, lsInit, lsParams) if lsRes.Status < 0 { r.Status = Status(lsRes.Status) break } s, r.ObjX = lsRes.X, lsRes.ObjX r.X.Axpy(s, d) proj.Project(r.X) obj.ValGrad(r.X, r.GradX) d.Copy(r.GradX) d.Scal(-1) xTemp.Copy(r.X) xTemp.Axpy(s/2, d) proj.Project(xTemp) xTemp.Sub(xTemp, r.X) xTemp.Scal(2 / s) gLin = -xTemp.Nrm2Sq() } return r }
func (sol SteepestDescent) Solve(o Grad, in *Solution, p *Params, u ...Updater) *Result { r := NewResult(in) obj := ObjGradWrapper{r: r, o: o} r.initGrad(obj) h := newHelper(r.Solution, u) n := len(r.X) s := 1.0 //initial step size gLin := -r.GradX.Nrm2Sq() d := mat.NewVec(n) d.Copy(r.GradX) d.Scal(-1) lineFunc := NewLineFuncDeriv(obj, r.X, d) lsInit := uni.NewSolution() lsParams := uni.NewParams() for ; r.Status == NotTerminated; h.update(r, p) { lsInit.SetX(s) lsInit.SetLB(0, r.ObjX, gLin) lsRes := sol.LineSearch.Solve(lineFunc, lsInit, lsParams) if lsRes.Status < 0 { r.Status = Status(lsRes.Status) break } s, r.ObjX = lsRes.X, lsRes.ObjX r.X.Axpy(s, d) obj.ValGrad(r.X, r.GradX) d.Copy(r.GradX) d.Scal(-1) gLin = -d.Nrm2Sq() } return r }
func (sol LBFGS) Solve(o Grad, in *Solution, p *Params, u ...Updater) *Result { r := NewResult(in) obj := ObjGradWrapper{r: r, o: o} r.initGrad(obj) h := newHelper(r.Solution, u) stepSize := 1.0 gLin := 0.0 n := len(r.X) S := make([]mat.Vec, sol.Mem) Y := make([]mat.Vec, sol.Mem) for i := 0; i < sol.Mem; i++ { S[i] = mat.NewVec(n) Y[i] = mat.NewVec(n) } d := mat.NewVec(n) xOld := mat.NewVec(n) gOld := mat.NewVec(n) sNew := mat.NewVec(n) yNew := mat.NewVec(n) alphas := mat.NewVec(sol.Mem) betas := mat.NewVec(sol.Mem) rhos := mat.NewVec(sol.Mem) lineFunc := NewLineFuncDeriv(obj, r.X, d) lsInit := uni.NewSolution() lsParams := uni.NewParams() for ; r.Status == NotTerminated; h.update(r, p) { d.Copy(r.GradX) if r.Iter > 0 { yNew.Sub(r.GradX, gOld) sNew.Sub(r.X, xOld) temp := S[len(S)-1] copy(S[1:], S) S[0] = temp S[0].Copy(sNew) temp = Y[len(S)-1] copy(Y[1:], Y) Y[0] = temp Y[0].Copy(yNew) copy(rhos[1:], rhos) rhos[0] = 1 / mat.Dot(sNew, yNew) for i := 0; i < sol.Mem; i++ { alphas[i] = rhos[i] * mat.Dot(S[i], d) d.Axpy(-alphas[i], Y[i]) } for i := sol.Mem - 1; i >= 0; i-- { betas[i] = rhos[i] * mat.Dot(Y[i], d) d.Axpy(alphas[i]-betas[i], S[i]) } } d.Scal(-1) gLin = mat.Dot(d, r.GradX) lsInit.SetX(stepSize) lsInit.SetLB(0, r.ObjX, gLin) lsRes := sol.LineSearch.Solve(lineFunc, lsInit, lsParams) if lsRes.Status < 0 { fmt.Println("Linesearch:", lsRes.Status) d.Copy(r.GradX) d.Scal(-1) lsInit.SetLB(0, r.ObjX, -r.GradX.Nrm2Sq()) lsRes = sol.LineSearch.Solve(lineFunc, lsInit, lsParams) if lsRes.Status < 0 { fmt.Println("Linesearch:", lsRes.Status) r.Status = Status(lsRes.Status) break } } stepSize, r.ObjX = lsRes.X, lsRes.ObjX xOld.Copy(r.X) gOld.Copy(r.GradX) r.X.Axpy(stepSize, d) obj.ValGrad(r.X, r.GradX) } return r }
func (sol *Rosenbrock) Solve(o Function, in *Solution, p *Params, u ...Updater) *Result { r := NewResult(in) obj := ObjWrapper{r: r, o: o} r.init(obj) h := newHelper(r.Solution, u) eps := 1.0 n := len(r.X) d := make([]mat.Vec, n) for i := range d { d[i] = mat.NewVec(n) d[i][i] = 1 } lambda := make([]float64, n) lf := make([]*LineFunc, n) for i := range lf { lf[i] = NewLineFunc(obj, r.X, d[i]) } lsInit := uni.NewSolution() lsParams := uni.NewParams() lsParams.XTolAbs = p.XTolAbs lsParams.XTolRel = p.XTolRel lsParams.FunTolAbs = 0 lsParams.FunTolRel = 0 for ; r.Status == NotTerminated; h.update(r, p) { //Search in all directions for i := range d { lf[i].Dir = 1 valNeg := 0.0 valPos := lf[i].Val(eps) if valPos >= r.ObjX { lf[i].Dir = -1 valNeg = lf[i].Val(eps) if valNeg >= r.ObjX { eps *= 0.5 lf[i].Dir = 1 lsInit.SetLB(-eps) lsInit.SetUB(eps) lsInit.SetX(0) } else { lsInit.SetUB() lsInit.SetLB() lsInit.SetX(eps) } } else { lsInit.SetUB() lsInit.SetLB() lsInit.SetX(eps) } lsRes := sol.LineSearch.Solve(lf[i], lsInit, lsParams) lambda[i] = lf[i].Dir * lsRes.X r.X.Axpy(lambda[i], d[i]) r.ObjX = lsRes.ObjX } //Find new directions for i := range d { if math.Abs(lambda[i]) > p.XTolAbs { d[i].Scal(lambda[i]) for j := i + 1; j < n; j++ { d[i].Axpy(lambda[j], d[j]) } } } //Gram-Schmidt, TODO:use QR factorization for i := range d { d[i].Scal(1 / d[i].Nrm2()) for j := i + 1; j < n; j++ { d[j].Axpy(-mat.Dot(d[i], d[j]), d[i]) } } } return r }