func (m *OWLQNMinimizer) updateGradForNewPos(x *core.Vector, grad *core.Vector, dir *core.Vector) {
	if m.l1reg == 0 {
		return
	}
	for key, val := range grad.Data {
		xval := x.GetValue(key)
		if xval < 0 {
			grad.SetValue(key, val-m.l1reg)
		} else if xval > 0 {
			grad.SetValue(key, val+m.l1reg)
		} else {
			dirval := dir.GetValue(key)
			if dirval < 0 {
				grad.SetValue(key, val-m.l1reg)
			} else if dirval > 0 {
				grad.SetValue(key, val+m.l1reg)
			}
		}
	}
	return
}
Description: assume all the features in x also appears in grad
all the features in dir must be in grad
package lr
import (
	"fmt"
	"github.com/xlvector/hector/core"
	"math"
)
type OWLQNMinimizer struct {
	l1reg        float64
	costFun      DiffFunction
	numHist      int
	maxIteration int
	tolerance    float64
}
var owlqn_output_switch bool = false
func NewOWLQNMinimizer(l1reg float64) *OWLQNMinimizer {
	m := new(OWLQNMinimizer)
	m.l1reg = l1reg
	m.numHist = 10
	m.maxIteration = 20
	m.tolerance = 1e-4
	return m
}
func (m *OWLQNMinimizer) Minimize(costfun DiffFunction, init *core.Vector) *core.Vector {
	m.costFun = costfun
	var cost float64 = m.Evaluate(init)
	var grad *core.Vector = costfun.Gradient(init).Copy()
	var pos *core.Vector = init.Copy()
	var terminalCriterion *relativeMeanImprCriterion = NewRelativeMeanImprCriterion(m.tolerance)
	terminalCriterion.addCost(cost)
	var helper *QuasiNewtonHelper = NewQuasiNewtonHelper(m.numHist, m, pos, grad)
	if owlqn_output_switch {
		fmt.Println("Iter\tcost\timprovement")
		fmt.Printf("%d\t%e\tUndefined", 0, cost)
	}
	for iter := 1; iter <= m.maxIteration; iter++ {
		steepestDescDir := grad.Copy()
		m.updateGrad(pos, steepestDescDir)
		steepestDescDir.ApplyScale(-1.0)
		dir := steepestDescDir.Copy()
		helper.ApplyQuasiInverseHession(dir)
		m.fixDirSign(dir, steepestDescDir)
		potentialGrad := grad.Copy()
		m.updateGradForNewPos(pos, potentialGrad, dir)
		newCost, newPos := helper.BackTrackingLineSearch(cost, pos, potentialGrad, dir, iter == 1)
		if owlqn_output_switch {
			fmt.Println("")
		}
		if cost == newCost {
			break
		}
		cost = newCost
		pos = newPos
		grad = costfun.Gradient(pos).Copy()
		terminalCriterion.addCost(cost)
		if owlqn_output_switch {
			fmt.Printf("%d\t%e\t%e", iter, newCost, terminalCriterion.improvement)
		}
		if terminalCriterion.isTerminable() || helper.UpdateState(pos, grad) {
			if owlqn_output_switch {
				fmt.Println("")
			}
			break
		}
	}
	return pos
}