Example #1
0
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
}
Example #2
0
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
}
Example #3
0
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
}
Example #4
0
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
}