예제 #1
0
func TestDaxpy(t *testing.T) {
	fmt.Printf("* L1 * test axpy: Y = alpha * X + Y\n")
	X := matrix.FloatVector([]float64{1, 1, 1})
	Y := matrix.FloatVector([]float64{0, 0, 0})
	fmt.Printf("before:\nX=\n%v\nY=\n%v\n", X, Y)
	Axpy(X, Y, matrix.FScalar(5.0))
	fmt.Printf("after:\nX=\n%v\nY=\n%v\n", X, Y)
}
예제 #2
0
func main() {
	flag.Parse()
	reftest := flag.NFlag() > 0

	gdata0 := [][]float64{
		[]float64{12., 13., 12.},
		[]float64{6., -3., -12.},
		[]float64{-5., -5., 6.}}

	gdata1 := [][]float64{
		[]float64{3., 3., -1., 1.},
		[]float64{-6., -6., -9., 19.},
		[]float64{10., -2., -2., -3.}}

	c := matrix.FloatVector([]float64{-2.0, 1.0, 5.0})
	g0 := matrix.FloatMatrixStacked(gdata0, matrix.ColumnOrder)
	g1 := matrix.FloatMatrixStacked(gdata1, matrix.ColumnOrder)
	Ghq := cvx.FloatSetNew("Gq", "hq")
	Ghq.Append("Gq", g0, g1)

	h0 := matrix.FloatVector([]float64{-12.0, -3.0, -2.0})
	h1 := matrix.FloatVector([]float64{27.0, 0.0, 3.0, -42.0})
	Ghq.Append("hq", h0, h1)

	var Gl, hl, A, b *matrix.FloatMatrix = nil, nil, nil, nil
	var solopts cvx.SolverOptions
	solopts.MaxIter = 30
	solopts.ShowProgress = true
	sol, err := cvx.Socp(c, Gl, hl, A, b, Ghq, &solopts, nil, nil)
	fmt.Printf("status: %v\n", err)
	if sol != nil && sol.Status == cvx.Optimal {
		x := sol.Result.At("x")[0]
		fmt.Printf("x=\n%v\n", x.ToString("%.9f"))
		for i, m := range sol.Result.At("sq") {
			fmt.Printf("sq[%d]=\n%v\n", i, m.ToString("%.9f"))
		}
		for i, m := range sol.Result.At("zq") {
			fmt.Printf("zq[%d]=\n%v\n", i, m.ToString("%.9f"))
		}
		if reftest {
			sq0 := sol.Result.At("sq")[0]
			sq1 := sol.Result.At("sq")[1]
			zq0 := sol.Result.At("zq")[0]
			zq1 := sol.Result.At("zq")[1]
			check(x, sq0, sq1, zq0, zq1)
		}
	}
}
예제 #3
0
// v = X.T * Y
func TestDdot(t *testing.T) {
	fmt.Printf("* L1 * test dot: X.T*Y\n")
	A := matrix.FloatVector([]float64{1.0, 1.0, 1.0, 1.0, 1.0, 1.0})
	B := matrix.FloatVector([]float64{2.0, 2.0, 2.0, 2.0, 2.0, 2.0})
	v1 := Dot(A, B)
	v2 := Dot(A, B, &linalg.IOpt{"offset", 3})
	v3 := Dot(A, B, &linalg.IOpt{"inc", 2})
	fmt.Printf("Ddot: X.T * Y\n")
	fmt.Printf("%.3f\n", v1.Float())
	fmt.Printf("%.3f\n", v2.Float())
	fmt.Printf("%.3f\n", v3.Float())
	// Output:
	// 12.000
	// 6.000
	// 6.000
}
예제 #4
0
// Dscal: X = alpha * X
func TestDscal(t *testing.T) {
	fmt.Printf("* L1 * test scal: X = alpha * X\n")
	alpha := matrix.FScalar(2.0)
	A := matrix.FloatVector([]float64{1.0, 1.0, 1.0, 1.0, 1.0, 1.0})
	Scal(A, alpha)
	fmt.Printf("Dscal 2.0 * A\n")
	fmt.Printf("%s\n", A)
	A = matrix.FloatVector([]float64{1.0, 1.0, 1.0, 1.0, 1.0, 1.0})
	Scal(A, alpha, &linalg.IOpt{"offset", 3})
	fmt.Printf("Dscal 2.0 * A[3:]\n")
	fmt.Printf("%s\n", A)
	A = matrix.FloatVector([]float64{1.0, 1.0, 1.0, 1.0, 1.0, 1.0})
	fmt.Printf("Dscal 2.0* A[::2]\n")
	Scal(A, alpha, &linalg.IOpt{"inc", 2})
	fmt.Printf("%s\n", A)
}
예제 #5
0
func TestDgemv(t *testing.T) {
	fmt.Printf("* L2 * test gemv: Y = alpha * A * X + beta * Y\n")
	A := matrix.FloatNew(3, 2, []float64{1, 1, 1, 2, 2, 2})
	X := matrix.FloatVector([]float64{1, 1})
	Y := matrix.FloatVector([]float64{0, 0, 0})
	alpha := matrix.FScalar(1.0)
	beta := matrix.FScalar(0.0)
	fmt.Printf("before: alpha=1.0, beta=0.0\nA=\n%v\nX=\n%v\nY=\n%v\n", A, X, Y)
	err := Gemv(A, X, Y, alpha, beta)
	fmt.Printf("after:\nA=\n%v\nX=\n%v\nY=\n%v\n", A, X, Y)
	fmt.Printf("* L2 * test gemv: X = alpha * A.T * Y + beta * X\n")
	err = Gemv(A, Y, X, alpha, beta, linalg.OptTrans)
	if err != nil {
		fmt.Printf("error: %s\n", err)
	}
	fmt.Printf("after:\nA=\n%v\nX=\n%v\nY=\n%v\n", A, X, Y)
}
예제 #6
0
func main() {

	flag.Parse()
	reftest := flag.NFlag() > 0

	gdata := [][]float64{
		[]float64{16., 7., 24., -8., 8., -1., 0., -1., 0., 0., 7.,
			-5., 1., -5., 1., -7., 1., -7., -4.},
		[]float64{-14., 2., 7., -13., -18., 3., 0., 0., -1., 0., 3.,
			13., -6., 13., 12., -10., -6., -10., -28.},
		[]float64{5., 0., -15., 12., -6., 17., 0., 0., 0., -1., 9.,
			6., -6., 6., -7., -7., -6., -7., -11.}}

	hdata := []float64{-3., 5., 12., -2., -14., -13., 10., 0., 0., 0., 68.,
		-30., -19., -30., 99., 23., -19., 23., 10.}

	c := matrix.FloatVector([]float64{-6., -4., -5.})
	G := matrix.FloatMatrixStacked(gdata)
	h := matrix.FloatVector(hdata)

	dims := cvx.DSetNew("l", "q", "s")
	dims.Set("l", []int{2})
	dims.Set("q", []int{4, 4})
	dims.Set("s", []int{3})

	var solopts cvx.SolverOptions
	solopts.MaxIter = 30
	solopts.ShowProgress = true
	sol, err := cvx.ConeLp(c, G, h, nil, nil, dims, &solopts, nil, nil)
	if err == nil {
		x := sol.Result.At("x")[0]
		s := sol.Result.At("s")[0]
		z := sol.Result.At("z")[0]
		fmt.Printf("Optimal\n")
		fmt.Printf("x=\n%v\n", x.ToString("%.9f"))
		fmt.Printf("s=\n%v\n", s.ToString("%.9f"))
		fmt.Printf("z=\n%v\n", z.ToString("%.9f"))
		if reftest {
			check(x, s, z)
		}
	} else {
		fmt.Printf("status: %s\n", err)
	}
}
예제 #7
0
func (p *FloorPlan) F2(x, z *matrix.FloatMatrix) (f, Df, H *matrix.FloatMatrix, err error) {
	f, Df, err = p.F1(x)
	x17 := matrix.FloatVector(x.FloatArray()[17:])
	tmp := p.Amin.Div(x17.Pow(3.0))
	tmp = z.Mul(tmp).Scale(2.0)
	diag := matrix.FloatDiagonal(5, tmp.FloatArray()...)
	H = matrix.FloatZeros(22, 22)
	H.SetSubMatrix(17, 17, diag)
	return
}
예제 #8
0
파일: misc.go 프로젝트: hrautila/go.opt.old
func sinv(x, y *matrix.FloatMatrix, dims *DimensionSet, mnl int) (err error) {
	/*DEBUGGED*/

	err = nil

	// For the nonlinear and 'l' blocks:
	//
	//     yk o\ xk = yk .\ xk.

	ind := mnl + dims.At("l")[0]
	blas.Tbsv(y, x, &la_.IOpt{"n", ind}, &la_.IOpt{"k", 0}, &la_.IOpt{"ldA", 1})

	// For the 'q' blocks:
	//
	//                        [ l0   -l1'              ]
	//     yk o\ xk = 1/a^2 * [                        ] * xk
	//                        [ -l1  (a*I + l1*l1')/l0 ]
	//
	// where yk = (l0, l1) and a = l0^2 - l1'*l1.

	for _, m := range dims.At("q") {
		aa := blas.Nrm2Float(y, &la_.IOpt{"n", m - 1}, &la_.IOpt{"offset", ind + 1})
		ee := y.GetIndex(ind)
		aa = (ee + aa) * (ee - aa)
		cc := x.GetIndex(ind)
		dd := blas.DotFloat(x, y, &la_.IOpt{"n", m - 1}, &la_.IOpt{"offsetx", ind + 1},
			&la_.IOpt{"offsety", ind + 1})
		x.SetIndex(ind, cc*ee-dd)
		blas.ScalFloat(x, aa/ee, &la_.IOpt{"n", m - 1}, &la_.IOpt{"offset", ind + 1})
		blas.AxpyFloat(y, x, dd/ee-cc, &la_.IOpt{"n", m - 1},
			&la_.IOpt{"offsetx", ind + 1}, &la_.IOpt{"offsety", ind + 1})
		blas.ScalFloat(x, 1.0/aa, &la_.IOpt{"n", m}, &la_.IOpt{"offset", ind})
		ind += m
	}

	// For the 's' blocks:
	//
	//     yk o\ xk =  xk ./ gamma
	//
	// where gammaij = .5 * (yk_i + yk_j).

	ind2 := ind
	for _, m := range dims.At("s") {
		for j := 0; j < m; j++ {
			u := matrix.FloatVector(y.FloatArray()[ind2+j : ind2+m])
			u.Add(y.GetIndex(ind2 + j))
			u.Scale(0.5)
			blas.Tbsv(u, x, &la_.IOpt{"n", m - j}, &la_.IOpt{"k", 0}, &la_.IOpt{"lda", 1},
				&la_.IOpt{"offsetx", ind + j*(m+1)})
		}
		ind += m * m
		ind2 += m
	}
	return
}
예제 #9
0
func (p *FloorPlan) F1(x *matrix.FloatMatrix) (f, Df *matrix.FloatMatrix, err error) {
	err = nil
	mn := x.Min(-1, -2, -3, -4, -5)
	if mn <= 0.0 {
		f, Df = nil, nil
		return
	}
	zeros := matrix.FloatZeros(5, 12)
	dk1 := matrix.FloatDiagonal(5, -1.0)
	dk2 := matrix.FloatZeros(5, 5)
	x17 := matrix.FloatVector(x.FloatArray()[17:])
	// -( Amin ./ (x17 .* x17) )
	diag := p.Amin.Div(x17.Mul(x17)).Scale(-1.0)
	dk2.SetIndexes(matrix.MakeDiagonalSet(5, 5), diag.FloatArray())
	Df, _ = matrix.FloatMatrixCombined(matrix.StackRight, zeros, dk1, dk2)

	x12 := matrix.FloatVector(x.FloatArray()[12:17])
	// f = -x[12:17] + div(Amin, x[17:])
	f = p.Amin.Div(x17).Minus(x12)
	return
}
예제 #10
0
func main() {
	flag.Parse()
	reftest := flag.NFlag() > 0

	x := floorplan(matrix.FloatWithValue(5, 1, 100.0))
	if x != nil {
		W := x.Get(0)
		H := x.Get(1)
		xs := matrix.FloatVector(x.FloatArray()[2:7])
		ys := matrix.FloatVector(x.FloatArray()[7:12])
		ws := matrix.FloatVector(x.FloatArray()[12:17])
		hs := matrix.FloatVector(x.FloatArray()[17:])
		fmt.Printf("W = %.5f, H = %.5f\n", W, H)
		fmt.Printf("x = \n%v\n", xs.ToString("%.5f"))
		fmt.Printf("y = \n%v\n", ys.ToString("%.5f"))
		fmt.Printf("w = \n%v\n", ws.ToString("%.5f"))
		fmt.Printf("h = \n%v\n", hs.ToString("%.5f"))
		if reftest {
			check(x)
		}
	}
}
예제 #11
0
// a = sum(X)
func TestDasum(t *testing.T) {
	fmt.Printf("* L1 * test sum: sum(X)\n")
	A := matrix.FloatVector([]float64{1.0, 1.0, 1.0, 1.0, 1.0, 1.0})
	v1 := Asum(A, &linalg.IOpt{"offset", 0})
	v2 := Asum(A, &linalg.IOpt{"offset", 3})
	v3 := Asum(A, &linalg.IOpt{"inc", 2})
	fmt.Printf("Dasum\n")
	fmt.Printf("%.3f\n", v1.Float())
	fmt.Printf("%.3f\n", v2.Float())
	fmt.Printf("%.3f\n", v3.Float())
	// Output:
	// 6.000
	// 3.000
	// 3.000
}
예제 #12
0
// a = norm2(A)
func TestDnrm2(t *testing.T) {
	fmt.Printf("* L1 * test sum: nrm2(X)\n")
	A := matrix.FloatVector([]float64{1.0, 1.0, 1.0, 1.0, 1.0, 1.0})
	v1 := Nrm2(A, &linalg.IOpt{"offset", 0})
	v2 := Nrm2(A, &linalg.IOpt{"offset", 3})
	v3 := Nrm2(A, &linalg.IOpt{"inc", 2})
	fmt.Printf("Ddnrm2\n")
	fmt.Printf("%.3f\n", v1.Float())
	fmt.Printf("%.3f\n", v2.Float())
	fmt.Printf("%.3f\n", v3.Float())
	// Output:
	// 2.499
	// 1.732
	// 1.732
}
예제 #13
0
func main() {

	Sdata := [][]float64{
		[]float64{ 4e-2,  6e-3, -4e-3,   0.0 },
        []float64{ 6e-3,  1e-2,  0.0,    0.0 },
        []float64{-4e-3,  0.0,   2.5e-3, 0.0 },
        []float64{ 0.0,   0.0,   0.0,    0.0 }}

	pbar := matrix.FloatVector([]float64{.12, .10, .07, .03})
	S := matrix.FloatMatrixStacked(Sdata)
	n := pbar.Rows()
	G := matrix.FloatDiagonal(n, -1.0)
	h := matrix.FloatZeros(n, 1)
	A := matrix.FloatWithValue(1, n, 1.0)
	b := matrix.FloatNew(1,1, []float64{1.0})

	var solopts cvx.SolverOptions
	solopts.MaxIter = 30
	solopts.ShowProgress = true

	mu := 1.0
	Smu := S.Copy().Scale(mu)
	pbarNeg := pbar.Copy().Scale(-1.0)
	fmt.Printf("Smu=\n%v\n", Smu.String())
	fmt.Printf("-pbar=\n%v\n", pbarNeg.String())

	sol, err := cvx.Qp(Smu, pbarNeg, G, h, A, b, &solopts, nil)

	fmt.Printf("status: %v\n", err)
	if sol != nil && sol.Status == cvx.Optimal {
		x := sol.Result.At("x")[0]
		ret := blas.DotFloat(x, pbar)
		risk := math.Sqrt(blas.DotFloat(x, S.Times(x)))
		fmt.Printf("ret=%.3f, risk=%.3f\n", ret, risk)
		fmt.Printf("x=\n%v\n", x)
	}
}
예제 #14
0
// X <--> Y
func TestDswap(t *testing.T) {
	fmt.Printf("* L1 * test swap: X <--> Y\n")
	A := matrix.FloatVector([]float64{1.0, 1.0, 1.0, 1.0, 1.0, 1.0})
	B := matrix.FloatVector([]float64{2.0, 2.0, 2.0, 2.0, 2.0, 2.0})
	Swap(A, B)
	fmt.Printf("Dswap A, B\n")
	fmt.Printf("%s\n", A)
	A = matrix.FloatVector([]float64{1.0, 1.0, 1.0, 1.0, 1.0, 1.0})
	B = matrix.FloatVector([]float64{2.0, 2.0, 2.0, 2.0, 2.0, 2.0})
	Swap(A, B, &linalg.IOpt{"offset", 3})
	fmt.Printf("Dswap A[3:], B[3:]\n")
	fmt.Printf("%s\n", A)
	A = matrix.FloatVector([]float64{1.0, 1.0, 1.0, 1.0, 1.0, 1.0})
	B = matrix.FloatVector([]float64{2.0, 2.0, 2.0, 2.0, 2.0, 2.0})
	fmt.Printf("Dswap A[::2], B[::2]\n")
	Swap(A, B, &linalg.IOpt{"inc", 2})
	fmt.Printf("%s\n", A)
}
예제 #15
0
파일: misc.go 프로젝트: hrautila/go.opt.old
/*
   Returns the Nesterov-Todd scaling W at points s and z, and stores the
   scaled variable in lmbda.

       W * z = W^{-T} * s = lmbda.

   W is a MatrixSet with entries:

   - W['dnl']: positive vector
   - W['dnli']: componentwise inverse of W['dnl']
   - W['d']: positive vector
   - W['di']: componentwise inverse of W['d']
   - W['v']: lists of 2nd order cone vectors with unit hyperbolic norms
   - W['beta']: list of positive numbers
   - W['r']: list of square matrices
   - W['rti']: list of square matrices.  rti[k] is the inverse transpose
     of r[k].

*/
func computeScaling(s, z, lmbda *matrix.FloatMatrix, dims *DimensionSet, mnl int) (W *FloatMatrixSet, err error) {
	/*DEBUGGED*/
	err = nil
	W = FloatSetNew("dnl", "dnli", "d", "di", "v", "beta", "r", "rti")

	// For the nonlinear block:
	//
	//     W['dnl'] = sqrt( s[:mnl] ./ z[:mnl] )
	//     W['dnli'] = sqrt( z[:mnl] ./ s[:mnl] )
	//     lambda[:mnl] = sqrt( s[:mnl] .* z[:mnl] )

	var stmp, ztmp, lmd *matrix.FloatMatrix
	if mnl > 0 {
		stmp = matrix.FloatVector(s.FloatArray()[:mnl])
		ztmp = matrix.FloatVector(z.FloatArray()[:mnl])
		dnl := stmp.Div(ztmp)
		dnl.Apply(dnl, math.Sqrt)
		dnli := dnl.Copy()
		dnli.Apply(dnli, func(a float64) float64 { return 1.0 / a })
		W.Set("dnl", dnl)
		W.Set("dnli", dnli)
		lmd = stmp.Mul(ztmp)
		lmd.Apply(lmd, math.Sqrt)
		lmbda.SetIndexes(matrix.MakeIndexSet(0, mnl, 1), lmd.FloatArray())
	} else {
		mnl = 0
	}

	// For the 'l' block:
	//
	//     W['d'] = sqrt( sk ./ zk )
	//     W['di'] = sqrt( zk ./ sk )
	//     lambdak = sqrt( sk .* zk )
	//
	// where sk and zk are the first dims['l'] entries of s and z.
	// lambda_k is stored in the first dims['l'] positions of lmbda.

	m := dims.At("l")[0]
	td := s.FloatArray()
	stmp = matrix.FloatVector(td[mnl : mnl+m])
	zd := z.FloatArray()
	//fmt.Printf("zdata=%v\n", zd[mnl:mnl+m])
	ztmp = matrix.FloatVector(zd[mnl : mnl+m])
	d := stmp.Div(ztmp)
	d.Apply(d, math.Sqrt)
	di := d.Copy()
	di.Apply(di, func(a float64) float64 { return 1.0 / a })
	//fmt.Printf("d:\n%v\n", d)
	//fmt.Printf("di:\n%v\n", di)
	W.Set("d", d)
	W.Set("di", di)
	lmd = stmp.Mul(ztmp)
	lmd.Apply(lmd, math.Sqrt)
	// lmd has indexes mnl:mnl+m and length of m
	lmbda.SetIndexes(matrix.MakeIndexSet(mnl, mnl+m, 1), lmd.FloatArray())
	//fmt.Printf("after l:\n%v\n", lmbda)

	/*
	   For the 'q' blocks, compute lists 'v', 'beta'.

	   The vector v[k] has unit hyperbolic norm:

	       (sqrt( v[k]' * J * v[k] ) = 1 with J = [1, 0; 0, -I]).

	   beta[k] is a positive scalar.

	   The hyperbolic Householder matrix H = 2*v[k]*v[k]' - J
	   defined by v[k] satisfies

	       (beta[k] * H) * zk  = (beta[k] * H) \ sk = lambda_k

	   where sk = s[indq[k]:indq[k+1]], zk = z[indq[k]:indq[k+1]].

	   lambda_k is stored in lmbda[indq[k]:indq[k+1]].
	*/
	ind := mnl + dims.At("l")[0]
	var beta *matrix.FloatMatrix

	for _, k := range dims.At("q") {
		W.Append("v", matrix.FloatZeros(k, 1))
	}
	beta = matrix.FloatZeros(len(dims.At("q")), 1)
	W.Set("beta", beta)
	vset := W.At("v")
	for k, m := range dims.At("q") {
		v := vset[k]
		// a = sqrt( sk' * J * sk )  where J = [1, 0; 0, -I]
		aa := jnrm2(s, m, ind)
		// b = sqrt( zk' * J * zk )
		bb := jnrm2(z, m, ind)
		// beta[k] = ( a / b )**1/2
		beta.SetIndex(k, math.Sqrt(aa/bb))
		// c = sqrt( (sk/a)' * (zk/b) + 1 ) / sqrt(2)
		c0 := blas.DotFloat(s, z, &la_.IOpt{"n", m},
			&la_.IOpt{"offsetx", ind}, &la_.IOpt{"offsety", ind})
		cc := math.Sqrt((c0/aa/bb + 1.0) / 2.0)

		// vk = 1/(2*c) * ( (sk/a) + J * (zk/b) )
		blas.CopyFloat(z, v, &la_.IOpt{"offsetx", ind}, &la_.IOpt{"n", m})
		blas.ScalFloat(v, -1.0/bb)
		v.SetIndex(0, -1.0*v.GetIndex(0))
		blas.AxpyFloat(s, v, 1.0/aa, &la_.IOpt{"offsetx", ind}, &la_.IOpt{"n", m})
		blas.ScalFloat(v, 1.0/2.0/cc)

		// v[k] = 1/sqrt(2*(vk0 + 1)) * ( vk + e ),  e = [1; 0]
		v.SetIndex(0, v.GetIndex(0)+1.0)
		blas.ScalFloat(v, (1.0 / math.Sqrt(2.0*v.GetIndex(0))))
		/*
		   To get the scaled variable lambda_k

		       d =  sk0/a + zk0/b + 2*c
		       lambda_k = [ c;
		                    (c + zk0/b)/d * sk1/a + (c + sk0/a)/d * zk1/b ]
		       lambda_k *= sqrt(a * b)
		*/
		lmbda.SetIndex(ind, cc)
		dd := 2*cc + s.GetIndex(ind)/aa + z.GetIndex(ind)/bb
		blas.CopyFloat(s, lmbda, &la_.IOpt{"offsetx", ind + 1}, &la_.IOpt{"offsety", ind + 1},
			&la_.IOpt{"n", m - 1})
		zz := (cc + z.GetIndex(ind)/bb) / dd / aa
		ss := (cc + s.GetIndex(ind)/aa) / dd / bb
		blas.ScalFloat(lmbda, zz, &la_.IOpt{"offset", ind + 1}, &la_.IOpt{"n", m - 1})
		blas.AxpyFloat(z, lmbda, ss, &la_.IOpt{"offsetx", ind + 1},
			&la_.IOpt{"offsety", ind + 1}, &la_.IOpt{"n", m - 1})
		blas.ScalFloat(lmbda, math.Sqrt(aa*bb), &la_.IOpt{"offset", ind}, &la_.IOpt{"n", m})

		ind += m
		//fmt.Printf("after q[%d]:\n%v\n", k, lmbda)
	}
	/*
	   For the 's' blocks: compute two lists 'r' and 'rti'.

	       r[k]' * sk^{-1} * r[k] = diag(lambda_k)^{-1}
	       r[k]' * zk * r[k] = diag(lambda_k)

	   where sk and zk are the entries inds[k] : inds[k+1] of
	   s and z, reshaped into symmetric matrices.

	   rti[k] is the inverse of r[k]', so

	       rti[k]' * sk * rti[k] = diag(lambda_k)^{-1}
	       rti[k]' * zk^{-1} * rti[k] = diag(lambda_k).

	   The vectors lambda_k are stored in

	       lmbda[ dims['l'] + sum(dims['q']) : -1 ]
	*/
	for _, k := range dims.At("s") {
		W.Append("r", matrix.FloatZeros(k, k))
		W.Append("rti", matrix.FloatZeros(k, k))
	}
	maxs := maxdim(dims.At("s"))
	work := matrix.FloatZeros(maxs*maxs, 1)
	Ls := matrix.FloatZeros(maxs*maxs, 1)
	Lz := matrix.FloatZeros(maxs*maxs, 1)
	ind2 := ind
	for k, m := range dims.At("s") {
		r := W.At("r")[k]
		rti := W.At("rti")[k]

		// Factor sk = Ls*Ls'; store Ls in ds[inds[k]:inds[k+1]].
		blas.CopyFloat(s, Ls, &la_.IOpt{"offsetx", ind2}, &la_.IOpt{"n", m * m})
		lapack.PotrfFloat(Ls, &la_.IOpt{"n", m}, &la_.IOpt{"lda", m})

		// Factor zs[k] = Lz*Lz'; store Lz in dz[inds[k]:inds[k+1]].
		blas.CopyFloat(z, Lz, &la_.IOpt{"offsetx", ind2}, &la_.IOpt{"n", m * m})
		lapack.PotrfFloat(Lz, &la_.IOpt{"n", m}, &la_.IOpt{"lda", m})

		// SVD Lz'*Ls = U*diag(lambda_k)*V'.  Keep U in work.
		for i := 0; i < m; i++ {
			blas.ScalFloat(Ls, 0.0, &la_.IOpt{"offset", i * m}, &la_.IOpt{"n", i})
		}
		blas.CopyFloat(Ls, work, &la_.IOpt{"n", m * m})
		blas.TrmmFloat(Lz, work, 1.0, la_.OptTransA, &la_.IOpt{"lda", m}, &la_.IOpt{"ldb", m},
			&la_.IOpt{"n", m}, &la_.IOpt{"m", m})
		lapack.GesvdFloat(work, lmbda, nil, nil,
			la_.OptJobuO, &la_.IOpt{"lda", m}, &la_.IOpt{"offsetS", ind},
			&la_.IOpt{"n", m}, &la_.IOpt{"m", m})

		// r = Lz^{-T} * U
		blas.CopyFloat(work, r, &la_.IOpt{"n", m * m})
		blas.TrsmFloat(Lz, r, 1.0, la_.OptTransA,
			&la_.IOpt{"lda", m}, &la_.IOpt{"n", m}, &la_.IOpt{"m", m})

		// rti = Lz * U
		blas.CopyFloat(work, rti, &la_.IOpt{"n", m * m})
		blas.TrmmFloat(Lz, rti, 1.0,
			&la_.IOpt{"lda", m}, &la_.IOpt{"n", m}, &la_.IOpt{"m", m})

		// r := r * diag(sqrt(lambda_k))
		// rti := rti * diag(1 ./ sqrt(lambda_k))
		for i := 0; i < m; i++ {
			a := math.Sqrt(lmbda.GetIndex(ind + i))
			blas.ScalFloat(r, a, &la_.IOpt{"offset", m * i}, &la_.IOpt{"n", m})
			blas.ScalFloat(rti, 1.0/a, &la_.IOpt{"offset", m * i}, &la_.IOpt{"n", m})
		}
		ind += m
		ind2 += m * m
	}
	return
}
예제 #16
0
파일: misc.go 프로젝트: hrautila/go.opt.old
func updateScaling(W *FloatMatrixSet, lmbda, s, z *matrix.FloatMatrix) (err error) {
	err = nil
	var stmp, ztmp *matrix.FloatMatrix
	/*
	   Nonlinear and 'l' blocks

	      d :=  d .* sqrt( s ./ z )
	      lmbda := lmbda .* sqrt(s) .* sqrt(z)
	*/
	mnl := 0
	dnlset := W.At("dnl")
	dnliset := W.At("dnli")
	dset := W.At("d")
	diset := W.At("di")
	beta := W.At("beta")[0]
	if dnlset != nil && dnlset[0].NumElements() > 0 {
		mnl = dnlset[0].NumElements()
	}
	ml := dset[0].NumElements()
	m := mnl + ml
	//fmt.Printf("ml=%d, mnl=%d, m=%d'n", ml, mnl, m)

	stmp = matrix.FloatVector(s.FloatArray()[:m])
	stmp.Apply(stmp, math.Sqrt)
	s.SetIndexes(matrix.MakeIndexSet(0, m, 1), stmp.FloatArray())

	ztmp = matrix.FloatVector(z.FloatArray()[:m])
	ztmp.Apply(ztmp, math.Sqrt)
	z.SetIndexes(matrix.MakeIndexSet(0, m, 1), ztmp.FloatArray())

	// d := d .* s .* z
	if len(dnlset) > 0 {
		blas.TbmvFloat(s, dnlset[0], &la_.IOpt{"n", mnl}, &la_.IOpt{"k", 0}, &la_.IOpt{"lda", 1})
		blas.TbsvFloat(z, dnlset[0], &la_.IOpt{"n", mnl}, &la_.IOpt{"k", 0}, &la_.IOpt{"lda", 1})
		dnliset[0].Apply(dnlset[0], func(a float64) float64 { return 1.0 / a })
	}
	blas.TbmvFloat(s, dset[0], &la_.IOpt{"n", ml},
		&la_.IOpt{"k", 0}, &la_.IOpt{"lda", 1}, &la_.IOpt{"offseta", mnl})
	blas.TbsvFloat(z, dset[0], &la_.IOpt{"n", ml},
		&la_.IOpt{"k", 0}, &la_.IOpt{"lda", 1}, &la_.IOpt{"offseta", mnl})
	diset[0].Apply(dset[0], func(a float64) float64 { return 1.0 / a })

	// lmbda := s .* z
	blas.CopyFloat(s, lmbda, &la_.IOpt{"n", m})
	blas.TbmvFloat(z, lmbda, &la_.IOpt{"n", m}, &la_.IOpt{"k", 0}, &la_.IOpt{"lda", 1})

	//fmt.Printf("-- end of l:\nz=\n%v\nlmbda=\n%v\n", z.ConvertToString(), lmbda.ConvertToString())
	//fmt.Printf("W[d]=\n%v\n", dset[0].ConvertToString())
	//fmt.Printf("W[di]=\n%v\n", diset[0].ConvertToString())

	// 'q' blocks.
	// Let st and zt be the new variables in the old scaling:
	//
	//     st = s_k,   zt = z_k
	//
	// and a = sqrt(st' * J * st),  b = sqrt(zt' * J * zt).
	//
	// 1. Compute the hyperbolic Householder transformation 2*q*q' - J
	//    that maps st/a to zt/b.
	//
	//        c = sqrt( (1 + st'*zt/(a*b)) / 2 )
	//        q = (st/a + J*zt/b) / (2*c).
	//
	//    The new scaling point is
	//
	//        wk := betak * sqrt(a/b) * (2*v[k]*v[k]' - J) * q
	//
	//    with betak = W['beta'][k].
	//
	// 3. The scaled variable:
	//
	//        lambda_k0 = sqrt(a*b) * c
	//        lambda_k1 = sqrt(a*b) * ( (2vk*vk' - J) * (-d*q + u/2) )_1
	//
	//    where
	//
	//        u = st/a - J*zt/b
	//        d = ( vk0 * (vk'*u) + u0/2 ) / (2*vk0 *(vk'*q) - q0 + 1).
	//
	// 4. Update scaling
	//
	//        v[k] := wk^1/2
	//              = 1 / sqrt(2*(wk0 + 1)) * (wk + e).
	//        beta[k] *=  sqrt(a/b)

	ind := m
	for k, v := range W.At("v") {
		m = v.NumElements()

		// ln = sqrt( lambda_k' * J * lambda_k ) !! NOT USED!!
		jnrm2(lmbda, m, ind) // ?? NOT USED ??

		// a = sqrt( sk' * J * sk ) = sqrt( st' * J * st )
		// s := s / a = st / a
		aa := jnrm2(s, m, ind)
		blas.ScalFloat(s, 1.0/aa, &la_.IOpt{"n", m}, &la_.IOpt{"offset", ind})

		// b = sqrt( zk' * J * zk ) = sqrt( zt' * J * zt )
		// z := z / a = zt / b
		bb := jnrm2(z, m, ind)
		blas.ScalFloat(z, 1.0/bb, &la_.IOpt{"n", m}, &la_.IOpt{"offset", ind})

		// c = sqrt( ( 1 + (st'*zt) / (a*b) ) / 2 )
		cc := blas.DotFloat(s, z, &la_.IOpt{"offsetx", ind}, &la_.IOpt{"offsety", ind},
			&la_.IOpt{"n", m})
		cc = math.Sqrt((1.0 + cc) / 2.0)

		// vs = v' * st / a
		vs := blas.DotFloat(v, s, &la_.IOpt{"offsety", ind}, &la_.IOpt{"n", m})

		// vz = v' * J *zt / b
		vz := jdot(v, z, m, 0, ind)

		// vq = v' * q where q = (st/a + J * zt/b) / (2 * c)
		vq := (vs + vz) / 2.0 / cc

		// vq = v' * q where q = (st/a + J * zt/b) / (2 * c)
		vu := vs - vz
		// lambda_k0 = c
		lmbda.SetIndex(ind, cc)

		// wk0 = 2 * vk0 * (vk' * q) - q0
		wk0 := 2.0*v.GetIndex(0)*vq - (s.GetIndex(ind)+z.GetIndex(ind))/2.0/cc

		// d = (v[0] * (vk' * u) - u0/2) / (wk0 + 1)
		dd := (v.GetIndex(0)*vu - s.GetIndex(ind)/2.0 + z.GetIndex(ind)/2.0) / (wk0 + 1.0)

		// lambda_k1 = 2 * v_k1 * vk' * (-d*q + u/2) - d*q1 + u1/2
		blas.CopyFloat(v, lmbda, &la_.IOpt{"offsetx", 1}, &la_.IOpt{"offsety", ind + 1},
			&la_.IOpt{"n", m - 1})
		blas.ScalFloat(lmbda, (2.0 * (-dd*vq + 0.5*vu)),
			&la_.IOpt{"offsetx", ind + 1}, &la_.IOpt{"offsety", ind + 1}, &la_.IOpt{"n", m - 1})
		blas.AxpyFloat(s, lmbda, 0.5*(1.0-dd/cc),
			&la_.IOpt{"offsetx", ind + 1}, &la_.IOpt{"offsety", ind + 1}, &la_.IOpt{"n", m - 1})
		blas.AxpyFloat(z, lmbda, 0.5*(1.0+dd/cc),
			&la_.IOpt{"offsetx", ind + 1}, &la_.IOpt{"offsety", ind + 1}, &la_.IOpt{"n", m - 1})

		// Scale so that sqrt(lambda_k' * J * lambda_k) = sqrt(aa*bb).
		blas.ScalFloat(lmbda, math.Sqrt(aa*bb), &la_.IOpt{"offset", ind}, &la_.IOpt{"n", m})

		// v := (2*v*v' - J) * q
		//    = 2 * (v'*q) * v' - (J* st/a + zt/b) / (2*c)
		blas.ScalFloat(v, 2.0*vq)
		v.SetIndex(0, v.GetIndex(0)-(s.GetIndex(ind)/2.0/cc))
		blas.AxpyFloat(s, v, 0.5/cc, &la_.IOpt{"offsetx", ind + 1}, &la_.IOpt{"offsety", 1},
			&la_.IOpt{"n", m - 1})
		blas.AxpyFloat(z, v, -0.5/cc, &la_.IOpt{"offsetx", ind}, &la_.IOpt{"n", m})

		// v := v^{1/2} = 1/sqrt(2 * (v0 + 1)) * (v + e)
		v0 := v.GetIndex(0) + 1.0
		v.SetIndex(0, v0)
		blas.ScalFloat(v, 1.0/math.Sqrt(2.0*v0))

		// beta[k] *= ( aa / bb )**1/2
		bk := beta.GetIndex(k)
		beta.SetIndex(k, bk*math.Sqrt(aa/bb))

		ind += m
	}
	//fmt.Printf("-- end of q:\nz=\n%v\nlmbda=\n%v\n", z.ConvertToString(), lmbda.ConvertToString())
	//fmt.Printf("beta=\n%v\n", beta.ConvertToString())

	// 's' blocks
	//
	// Let st, zt be the updated variables in the old scaling:
	//
	//     st = Ls * Ls', zt = Lz * Lz'.
	//
	// where Ls and Lz are the 's' components of s, z.
	//
	// 1.  SVD Lz'*Ls = Uk * lambda_k^+ * Vk'.
	//
	// 2.  New scaling is
	//
	//         r[k] := r[k] * Ls * Vk * diag(lambda_k^+)^{-1/2}
	//         rti[k] := r[k] * Lz * Uk * diag(lambda_k^+)^{-1/2}.
	//

	maxr := 0
	for _, m := range W.At("r") {
		if m.Rows() > maxr {
			maxr = m.Rows()
		}
	}
	work := matrix.FloatZeros(maxr*maxr, 1)
	vlensum := 0
	for _, m := range W.At("v") {
		vlensum += m.NumElements()
	}
	ind = mnl + ml + vlensum
	ind2 := ind
	ind3 := 0
	rset := W.At("r")
	rtiset := W.At("rti")

	for k, _ := range rset {
		r := rset[k]
		rti := rtiset[k]
		m = r.Rows()
		//fmt.Printf("m=%d, r=\n%v\nrti=\n%v\n", m, r.ConvertToString(), rti.ConvertToString())

		// r := r*sk = r*Ls
		blas.GemmFloat(r, s, work, 1.0, 0.0, &la_.IOpt{"m", m}, &la_.IOpt{"n", m},
			&la_.IOpt{"k", m}, &la_.IOpt{"ldb", m}, &la_.IOpt{"ldc", m},
			&la_.IOpt{"offsetb", ind2})
		//fmt.Printf("1 work=\n%v\n", work.ConvertToString())
		blas.CopyFloat(work, r, &la_.IOpt{"n", m * m})

		// rti := rti*zk = rti*Lz
		blas.GemmFloat(rti, z, work, 1.0, 0.0, &la_.IOpt{"m", m}, &la_.IOpt{"n", m},
			&la_.IOpt{"k", m}, &la_.IOpt{"ldb", m}, &la_.IOpt{"ldc", m},
			&la_.IOpt{"offsetb", ind2})
		//fmt.Printf("2 work=\n%v\n", work.ConvertToString())
		blas.CopyFloat(work, rti, &la_.IOpt{"n", m * m})

		// SVD Lz'*Ls = U * lmbds^+ * V'; store U in sk and V' in zk. '
		blas.GemmFloat(z, s, work, 1.0, 0.0, la_.OptTransA, &la_.IOpt{"m", m},
			&la_.IOpt{"n", m}, &la_.IOpt{"k", m}, &la_.IOpt{"lda", m}, &la_.IOpt{"ldb", m},
			&la_.IOpt{"ldc", m}, &la_.IOpt{"offseta", ind2}, &la_.IOpt{"offsetb", ind2})
		//fmt.Printf("3 work=\n%v\n", work.ConvertToString())

		// U = s, Vt = z
		lapack.GesvdFloat(work, lmbda, s, z, la_.OptJobuAll, la_.OptJobvtAll,
			&la_.IOpt{"m", m}, &la_.IOpt{"n", m}, &la_.IOpt{"lda", m}, &la_.IOpt{"ldu", m},
			&la_.IOpt{"ldvt", m}, &la_.IOpt{"offsets", ind}, &la_.IOpt{"offsetu", ind2},
			&la_.IOpt{"offsetvt", ind2})

		// r := r*V
		blas.GemmFloat(r, z, work, 1.0, 0.0, la_.OptTransB, &la_.IOpt{"m", m},
			&la_.IOpt{"n", m}, &la_.IOpt{"k", m}, &la_.IOpt{"ldb", m}, &la_.IOpt{"ldc", m},
			&la_.IOpt{"offsetb", ind2})
		//fmt.Printf("4 work=\n%v\n", work.ConvertToString())
		blas.CopyFloat(work, r, &la_.IOpt{"n", m * m})

		// rti := rti*U
		blas.GemmFloat(rti, s, work, 1.0, 0.0, &la_.IOpt{"m", m}, &la_.IOpt{"n", m},
			&la_.IOpt{"k", m}, &la_.IOpt{"ldb", m}, &la_.IOpt{"ldc", m},
			&la_.IOpt{"offsetb", ind2})
		//fmt.Printf("5 work=\n%v\n", work.ConvertToString())
		blas.CopyFloat(work, rti, &la_.IOpt{"n", m * m})

		for i := 0; i < m; i++ {
			a := 1.0 / math.Sqrt(lmbda.GetIndex(ind+i))
			blas.ScalFloat(r, a, &la_.IOpt{"n", m}, &la_.IOpt{"offset", m * i})
			blas.ScalFloat(rti, a, &la_.IOpt{"n", m}, &la_.IOpt{"offset", m * i})
		}
		ind += m
		ind2 += m * m
		ind3 += m // !!NOT USED: ind3!!
	}

	//fmt.Printf("-- end of s:\nz=\n%v\nlmbda=\n%v\n", z.ConvertToString(), lmbda.ConvertToString())

	return

}
예제 #17
0
파일: misc.go 프로젝트: hrautila/go.opt.old
/*
   Evaluates

       x := H(lambda^{1/2}) * x   (inverse is 'N')
       x := H(lambda^{-1/2}) * x  (inverse is 'I').

   H is the Hessian of the logarithmic barrier.

*/
func scale2(lmbda, x *matrix.FloatMatrix, dims *DimensionSet, mnl int, inverse bool) (err error) {
	err = nil

	// For the nonlinear and 'l' blocks,
	//
	//     xk := xk ./ l   (inverse is 'N')
	//     xk := xk .* l   (inverse is 'I')
	//
	// where l is lmbda[:mnl+dims['l']].
	ind := mnl + dims.Sum("l")
	if !inverse {
		blas.TbsvFloat(lmbda, x, &la_.IOpt{"n", ind}, &la_.IOpt{"k", 0}, &la_.IOpt{"lda", 1})
	} else {
		blas.TbmvFloat(lmbda, x, &la_.IOpt{"n", ind}, &la_.IOpt{"k", 0}, &la_.IOpt{"lda", 1})
	}

	// For 'q' blocks, if inverse is 'N',
	//
	//     xk := 1/a * [ l'*J*xk;
	//         xk[1:] - (xk[0] + l'*J*xk) / (l[0] + 1) * l[1:] ].
	//
	// If inverse is 'I',
	//
	//     xk := a * [ l'*xk;
	//         xk[1:] + (xk[0] + l'*xk) / (l[0] + 1) * l[1:] ].
	//
	// a = sqrt(lambda_k' * J * lambda_k), l = lambda_k / a.
	for _, m := range dims.At("q") {
		var lx, a, c, x0 float64
		a = jnrm2(lmbda, m, ind) //&la_.IOpt{"n", m}, &la_.IOpt{"offset", ind})
		if !inverse {
			lx = jdot(lmbda, x, m, ind, ind) //&la_.IOpt{"n", m}, &la_.IOpt{"offsetx", ind},
			//&la_.IOpt{"offsety", ind})
			lx /= a
		} else {
			lx = blas.DotFloat(lmbda, x, &la_.IOpt{"n", m}, &la_.IOpt{"offsetx", ind},
				&la_.IOpt{"offsety", ind})
			lx /= a
		}
		x0 = x.GetIndex(ind)
		x.SetIndex(ind, lx)
		c = (lx + x0) / (lmbda.GetIndex(ind)/a + 1.0) / a
		if !inverse {
			c *= -1.0
		}
		blas.AxpyFloat(lmbda, x, c, &la_.IOpt{"n", m - 1}, &la_.IOpt{"offsetx", ind + 1},
			&la_.IOpt{"offsety", ind + 1})
		if !inverse {
			a = 1.0 / a
		}
		blas.ScalFloat(x, a, &la_.IOpt{"offset", ind}, &la_.IOpt{"n", m})
		ind += m
	}
	// For the 's' blocks, if inverse is 'N',
	//
	//     xk := vec( diag(l)^{-1/2} * mat(xk) * diag(k)^{-1/2}).
	//
	// If inverse is true,
	//
	//     xk := vec( diag(l)^{1/2} * mat(xk) * diag(k)^{1/2}).
	//
	// where l is kth block of lambda.
	//
	// We scale upper and lower triangular part of mat(xk) because the
	// inverse operation will be applied to nonsymmetric matrices.
	ind2 := ind
	sdims := dims.At("s")
	for k := 0; k < len(sdims); k++ {
		m := sdims[k]
		scaleF := func(v, x float64) float64 {
			return math.Sqrt(v) * math.Sqrt(x)
		}
		for j := 0; j < m; j++ {
			c := matrix.FloatVector(lmbda.FloatArray()[ind2 : ind2+m])
			c.ApplyConst(c, scaleF, lmbda.GetIndex(ind2+j))
			if !inverse {
				blas.Tbsv(c, x, &la_.IOpt{"n", m}, &la_.IOpt{"k", 0}, &la_.IOpt{"lda", 1},
					&la_.IOpt{"offsetx", ind + j*m})
			} else {
				blas.Tbmv(c, x, &la_.IOpt{"n", m}, &la_.IOpt{"k", 0}, &la_.IOpt{"lda", 1},
					&la_.IOpt{"offsetx", ind + j*m})
			}
		}
		ind += m * m
		ind2 += m
	}
	return
}
예제 #18
0
파일: misc.go 프로젝트: hrautila/go.opt.old
// The product x := (y o x).  If diag is 'D', the 's' part of y is
// diagonal and only the diagonal is stored.
func sprod(x, y *matrix.FloatMatrix, dims *DimensionSet, mnl int, opts ...la_.Option) (err error) {

	err = nil
	diag := la_.GetStringOpt("diag", "N", opts...)
	// For the nonlinear and 'l' blocks:
	//
	//     yk o xk = yk .* xk.
	ind := mnl + dims.At("l")[0]
	err = blas.Tbmv(y, x, &la_.IOpt{"n", ind}, &la_.IOpt{"k", 0}, &la_.IOpt{"lda", 1})
	if err != nil {
		return
	}
	//fmt.Printf("Sprod l:x=\n%v\n", x)

	// For 'q' blocks:
	//
	//               [ l0   l1'  ]
	//     yk o xk = [           ] * xk
	//               [ l1   l0*I ]
	//
	// where yk = (l0, l1).
	for _, m := range dims.At("q") {
		dd := blas.DotFloat(x, y, &la_.IOpt{"offsetx", ind}, &la_.IOpt{"offsety", ind},
			&la_.IOpt{"n", m})
		//fmt.Printf("dd=%v\n", dd)
		alpha := y.GetIndex(ind)
		//fmt.Printf("scal=%v\n", alpha)
		blas.ScalFloat(x, alpha, &la_.IOpt{"offset", ind + 1}, &la_.IOpt{"n", m - 1})
		alpha = x.GetIndex(ind)
		//fmt.Printf("axpy=%v\n", alpha)
		blas.AxpyFloat(y, x, alpha, &la_.IOpt{"offsetx", ind + 1}, &la_.IOpt{"offsety", ind + 1},
			&la_.IOpt{"n", m - 1})
		x.SetIndex(ind, dd)
		ind += m
	}
	//fmt.Printf("Sprod q :x=\n%v\n", x)

	// For the 's' blocks:
	//
	//    yk o sk = .5 * ( Yk * mat(xk) + mat(xk) * Yk )
	//
	// where Yk = mat(yk) if diag is 'N' and Yk = diag(yk) if diag is 'D'.

	if diag[0] == 'N' {
		// DEBUGGED
		maxm := maxdim(dims.At("s"))
		A := matrix.FloatZeros(maxm, maxm)
		for _, m := range dims.At("s") {
			blas.Copy(x, A, &la_.IOpt{"offsetx", ind}, &la_.IOpt{"n", m * m})
			for i := 0; i < m-1; i++ { // i < m-1 --> i < m
				symm(A, m, 0)
				symm(y, m, ind)
			}
			err = blas.Syr2kFloat(A, y, x, 0.5, 0.0, &la_.IOpt{"n", m}, &la_.IOpt{"k", m},
				&la_.IOpt{"lda", m}, &la_.IOpt{"ldb", m}, &la_.IOpt{"ldc", m},
				&la_.IOpt{"offsetb", ind}, &la_.IOpt{"offsetc", ind})
			if err != nil {
				return
			}
			ind += m * m
		}
		//fmt.Printf("Sprod diag=N s:x=\n%v\n", x)

	} else {
		ind2 := ind
		for _, m := range dims.At("s") {
			for i := 0; i < m; i++ {
				// original: u = 0.5 * ( y[ind2+i:ind2+m] + y[ind2+i] )
				// creates matrix of elements: [ind2+i ... ind2+m] then
				// element wisely adds y[ind2+i] and scales by 0.5
				iset := matrix.MakeIndexSet(ind2+i, ind2+m, 1)
				u := matrix.FloatVector(y.GetIndexes(iset))
				u.Add(y.GetIndex(ind2 + i))
				u.Scale(0.5)
				err = blas.Tbmv(u, x, &la_.IOpt{"n", m - i}, &la_.IOpt{"k", 0}, &la_.IOpt{"lda", 1},
					&la_.IOpt{"offsetx", ind + i*(m+1)})
				if err != nil {
					return
				}
			}
			ind += m * m
			ind2 += m
		}
		//fmt.Printf("Sprod diag=T s:x=\n%v\n", x)
	}
	return
}
예제 #19
0
func main() {
	flag.Parse()
	reftest := flag.NFlag() > 0

	gdata0 := [][]float64{
		[]float64{-7., -11., -11., 3.},
		[]float64{7., -18., -18., 8.},
		[]float64{-2., -8., -8., 1.}}

	gdata1 := [][]float64{
		[]float64{-21., -11., 0., -11., 10., 8., 0., 8., 5.},
		[]float64{0., 10., 16., 10., -10., -10., 16., -10., 3.},
		[]float64{-5., 2., -17., 2., -6., 8., -17., -7., 6.}}

	hdata0 := [][]float64{
		[]float64{33., -9.},
		[]float64{-9., 26.}}

	hdata1 := [][]float64{
		[]float64{14., 9., 40.},
		[]float64{9., 91., 10.},
		[]float64{40., 10., 15.}}

	g0 := matrix.FloatMatrixStacked(gdata0, matrix.ColumnOrder)
	g1 := matrix.FloatMatrixStacked(gdata1, matrix.ColumnOrder)
	Ghs := cvx.FloatSetNew("Gs", "hs")
	Ghs.Append("Gs", g0, g1)

	h0 := matrix.FloatMatrixStacked(hdata0, matrix.ColumnOrder)
	h1 := matrix.FloatMatrixStacked(hdata1, matrix.ColumnOrder)
	Ghs.Append("hs", h0, h1)

	c := matrix.FloatVector([]float64{1.0, -1.0, 1.0})
	Ghs.Print()
	fmt.Printf("calling...\n")
	// nil variables
	var Gs, hs, A, b *matrix.FloatMatrix = nil, nil, nil, nil

	var solopts cvx.SolverOptions
	solopts.MaxIter = 30
	solopts.ShowProgress = true
	sol, err := cvx.Sdp(c, Gs, hs, A, b, Ghs, &solopts, nil, nil)
	if sol != nil && sol.Status == cvx.Optimal {
		x := sol.Result.At("x")[0]
		fmt.Printf("x=\n%v\n", x.ToString("%.9f"))
		for i, m := range sol.Result.At("ss") {
			fmt.Printf("ss[%d]=\n%v\n", i, m.ToString("%.9f"))
		}
		for i, m := range sol.Result.At("zs") {
			fmt.Printf("zs[%d]=\n%v\n", i, m.ToString("%.9f"))
		}
		if reftest {
			ss0 := sol.Result.At("ss")[0]
			ss1 := sol.Result.At("ss")[1]
			zs0 := sol.Result.At("zs")[0]
			zs1 := sol.Result.At("zs")[1]
			check(x, ss0, ss1, zs0, zs1)
		}
	} else {
		fmt.Printf("status: %v\n", err)
	}
}
예제 #20
0
//    Solves a pair of primal and dual SOCPs
//
//        minimize    c'*x
//        subject to  Gl*x + sl = hl
//                    Gq[k]*x + sq[k] = hq[k],  k = 0, ..., N-1
//                    A*x = b
//                    sl >= 0,
//                    sq[k] >= 0, k = 0, ..., N-1
//
//        maximize    -hl'*z - sum_k hq[k]'*zq[k] - b'*y
//        subject to  Gl'*zl + sum_k Gq[k]'*zq[k] + A'*y + c = 0
//                    zl >= 0,  zq[k] >= 0, k = 0, ..., N-1.
//
//    The inequalities sl >= 0 and zl >= 0 are elementwise vector
//    inequalities.  The inequalities sq[k] >= 0, zq[k] >= 0 are second
//    order cone inequalities, i.e., equivalent to
//
//        sq[k][0] >= || sq[k][1:] ||_2,  zq[k][0] >= || zq[k][1:] ||_2.
//
func Socp(c, Gl, hl, A, b *matrix.FloatMatrix, Ghq *FloatMatrixSet, solopts *SolverOptions, primalstart, dualstart *FloatMatrixSet) (sol *Solution, err error) {
	if c == nil {
		err = errors.New("'c' must a column matrix")
		return
	}
	n := c.Rows()
	if n < 1 {
		err = errors.New("Number of variables must be at least 1")
		return
	}
	if Gl == nil {
		Gl = matrix.FloatZeros(0, n)
	}
	if Gl.Cols() != n {
		err = errors.New(fmt.Sprintf("'G' must be matrix with %d columns", n))
		return
	}
	ml := Gl.Rows()
	if hl == nil {
		hl = matrix.FloatZeros(0, 1)
	}
	if !hl.SizeMatch(ml, 1) {
		err = errors.New(fmt.Sprintf("'hl' must be matrix of size (%d,1)", ml))
		return
	}
	Gqset := Ghq.At("Gq")
	mq := make([]int, 0)
	for i, Gq := range Gqset {
		if Gq.Cols() != n {
			err = errors.New(fmt.Sprintf("'Gq' must be list of matrices with %d columns", n))
			return
		}
		if Gq.Rows() == 0 {
			err = errors.New(fmt.Sprintf("the number of rows of 'Gq[%d]' is zero", i))
			return
		}
		mq = append(mq, Gq.Rows())
	}
	hqset := Ghq.At("hq")
	if len(Gqset) != len(hqset) {
		err = errors.New(fmt.Sprintf("'hq' must be a list of %d matrices", len(Gqset)))
		return
	}
	for i, hq := range hqset {
		if !hq.SizeMatch(Gqset[i].Rows(), 1) {
			s := fmt.Sprintf("hq[%d] has size (%d,%d). Expected size is (%d,1)",
				i, hq.Rows(), hq.Cols(), Gqset[i].Rows())
			err = errors.New(s)
			return
		}
	}
	if A == nil {
		A = matrix.FloatZeros(0, n)
	}
	if A.Cols() != n {
		err = errors.New(fmt.Sprintf("'A' must be matrix with %d columns", n))
		return
	}
	p := A.Rows()
	if b == nil {
		b = matrix.FloatZeros(0, 1)
	}
	if !b.SizeMatch(p, 1) {
		err = errors.New(fmt.Sprintf("'b' must be matrix of size (%d,1)", p))
		return
	}
	dims := DSetNew("l", "q", "s")
	dims.Set("l", []int{ml})
	dims.Set("q", mq)
	//N := dims.Sum("l", "q")

	hargs := make([]*matrix.FloatMatrix, 0, len(hqset)+1)
	hargs = append(hargs, hl)
	hargs = append(hargs, hqset...)
	h, indh := matrix.FloatMatrixCombined(matrix.StackDown, hargs...)

	Gargs := make([]*matrix.FloatMatrix, 0, len(Gqset)+1)
	Gargs = append(Gargs, Gl)
	Gargs = append(Gargs, Gqset...)
	G, indg := matrix.FloatMatrixCombined(matrix.StackDown, Gargs...)

	var pstart, dstart *FloatMatrixSet = nil, nil
	if primalstart != nil {
		pstart = FloatSetNew("x", "s")
		pstart.Set("x", primalstart.At("x")[0])
		slset := primalstart.At("sl")
		margs := make([]*matrix.FloatMatrix, 0, len(slset)+1)
		margs = append(margs, primalstart.At("s")[0])
		margs = append(margs, slset...)
		sl, _ := matrix.FloatMatrixCombined(matrix.StackDown, margs...)
		pstart.Set("s", sl)
	}

	if dualstart != nil {
		dstart = FloatSetNew("y", "z")
		dstart.Set("y", dualstart.At("y")[0])
		zlset := primalstart.At("zl")
		margs := make([]*matrix.FloatMatrix, 0, len(zlset)+1)
		margs = append(margs, dualstart.At("z")[0])
		margs = append(margs, zlset...)
		zl, _ := matrix.FloatMatrixCombined(matrix.StackDown, margs...)
		dstart.Set("z", zl)
	}

	sol, err = ConeLp(c, G, h, A, b, dims, solopts, pstart, dstart)
	// unpack sol.Result
	if err == nil {
		s := sol.Result.At("s")[0]
		sl := matrix.FloatVector(s.FloatArray()[:ml])
		sol.Result.Append("sl", sl)
		ind := ml
		for _, k := range indh[1:] {
			sk := matrix.FloatVector(s.FloatArray()[ind : ind+k])
			sol.Result.Append("sq", sk)
			ind += k
		}

		z := sol.Result.At("z")[0]
		zl := matrix.FloatVector(z.FloatArray()[:ml])
		sol.Result.Append("zl", zl)
		ind = ml
		for _, k := range indg[1:] {
			zk := matrix.FloatVector(z.FloatArray()[ind : ind+k])
			sol.Result.Append("zq", zk)
			ind += k
		}
	}
	sol.Result.Remove("s")
	sol.Result.Remove("z")

	return
}
예제 #21
0
//    Solves a pair of primal and dual SDPs
//
//        minimize    c'*x
//        subject to  Gl*x + sl = hl
//                    mat(Gs[k]*x) + ss[k] = hs[k], k = 0, ..., N-1
//                    A*x = b
//                    sl >= 0,  ss[k] >= 0, k = 0, ..., N-1
//
//        maximize    -hl'*z - sum_k trace(hs[k]*zs[k]) - b'*y
//        subject to  Gl'*zl + sum_k Gs[k]'*vec(zs[k]) + A'*y + c = 0
//                    zl >= 0,  zs[k] >= 0, k = 0, ..., N-1.
//
//    The inequalities sl >= 0 and zl >= 0 are elementwise vector
//    inequalities.  The inequalities ss[k] >= 0, zs[k] >= 0 are matrix
//    inequalities, i.e., the symmetric matrices ss[k] and zs[k] must be
//    positive semidefinite.  mat(Gs[k]*x) is the symmetric matrix X with
//    X[:] = Gs[k]*x.  For a symmetric matrix, zs[k], vec(zs[k]) is the
//    vector zs[k][:].
//
func Sdp(c, Gl, hl, A, b *matrix.FloatMatrix, Ghs *FloatMatrixSet, solopts *SolverOptions, primalstart, dualstart *FloatMatrixSet) (sol *Solution, err error) {
	if c == nil {
		err = errors.New("'c' must a column matrix")
		return
	}
	n := c.Rows()
	if n < 1 {
		err = errors.New("Number of variables must be at least 1")
		return
	}
	if Gl == nil {
		Gl = matrix.FloatZeros(0, n)
	}
	if Gl.Cols() != n {
		err = errors.New(fmt.Sprintf("'G' must be matrix with %d columns", n))
		return
	}
	ml := Gl.Rows()
	if hl == nil {
		hl = matrix.FloatZeros(0, 1)
	}
	if !hl.SizeMatch(ml, 1) {
		err = errors.New(fmt.Sprintf("'hl' must be matrix of size (%d,1)", ml))
		return
	}
	Gsset := Ghs.At("Gs")
	ms := make([]int, 0)
	for i, Gs := range Gsset {
		if Gs.Cols() != n {
			err = errors.New(fmt.Sprintf("'Gs' must be list of matrices with %d columns", n))
			return
		}
		sz := int(math.Sqrt(float64(Gs.Rows())))
		if Gs.Rows() != sz*sz {
			err = errors.New(fmt.Sprintf("the squareroot of the number of rows of 'Gq[%d]' is not an integer", i))
			return
		}
		ms = append(ms, sz)
	}

	hsset := Ghs.At("hs")
	if len(Gsset) != len(hsset) {
		err = errors.New(fmt.Sprintf("'hs' must be a list of %d matrices", len(Gsset)))
		return
	}
	for i, hs := range hsset {
		if !hs.SizeMatch(ms[i], ms[i]) {
			s := fmt.Sprintf("hq[%d] has size (%d,%d). Expected size is (%d,%d)",
				i, hs.Rows(), hs.Cols(), ms[i], ms[i])
			err = errors.New(s)
			return
		}
	}
	if A == nil {
		A = matrix.FloatZeros(0, n)
	}
	if A.Cols() != n {
		err = errors.New(fmt.Sprintf("'A' must be matrix with %d columns", n))
		return
	}
	p := A.Rows()
	if b == nil {
		b = matrix.FloatZeros(0, 1)
	}
	if !b.SizeMatch(p, 1) {
		err = errors.New(fmt.Sprintf("'b' must be matrix of size (%d,1)", p))
		return
	}
	dims := DSetNew("l", "q", "s")
	dims.Set("l", []int{ml})
	dims.Set("s", ms)
	N := dims.Sum("l") + dims.SumSquared("s")

	// Map hs matrices to h vector
	h := matrix.FloatZeros(N, 1)
	h.SetIndexes(matrix.MakeIndexSet(0, ml, 1), hl.FloatArray()[:ml])
	ind := ml
	for k, hs := range hsset {
		h.SetIndexes(matrix.MakeIndexSet(ind, ind+ms[k]*ms[k], 1), hs.FloatArray())
		ind += ms[k] * ms[k]
	}

	Gargs := make([]*matrix.FloatMatrix, 0)
	Gargs = append(Gargs, Gl)
	Gargs = append(Gargs, Gsset...)
	G, sizeg := matrix.FloatMatrixCombined(matrix.StackDown, Gargs...)

	var pstart, dstart *FloatMatrixSet = nil, nil
	if primalstart != nil {
		pstart = FloatSetNew("x", "s")
		pstart.Set("x", primalstart.At("x")[0])
		slset := primalstart.At("sl")
		margs := make([]*matrix.FloatMatrix, 0, len(slset)+1)
		margs = append(margs, primalstart.At("s")[0])
		margs = append(margs, slset...)
		sl, _ := matrix.FloatMatrixCombined(matrix.StackDown, margs...)
		pstart.Set("s", sl)
	}

	if dualstart != nil {
		dstart = FloatSetNew("y", "z")
		dstart.Set("y", dualstart.At("y")[0])
		zlset := primalstart.At("zl")
		margs := make([]*matrix.FloatMatrix, 0, len(zlset)+1)
		margs = append(margs, dualstart.At("z")[0])
		margs = append(margs, zlset...)
		zl, _ := matrix.FloatMatrixCombined(matrix.StackDown, margs...)
		dstart.Set("z", zl)
	}

	sol, err = ConeLp(c, G, h, A, b, dims, solopts, pstart, dstart)
	// unpack sol.Result
	if err == nil {
		s := sol.Result.At("s")[0]
		sl := matrix.FloatVector(s.FloatArray()[:ml])
		sol.Result.Append("sl", sl)
		ind := ml
		for _, m := range ms {
			sk := matrix.FloatNew(m, m, s.FloatArray()[ind:ind+m*m])
			sol.Result.Append("ss", sk)
			ind += m * m
		}

		z := sol.Result.At("z")[0]
		zl := matrix.FloatVector(s.FloatArray()[:ml])
		sol.Result.Append("zl", zl)
		ind = ml
		for i, k := range sizeg[1:] {
			zk := matrix.FloatNew(ms[i], ms[i], z.FloatArray()[ind:ind+k])
			sol.Result.Append("zs", zk)
			ind += k
		}
	}
	sol.Result.Remove("s")
	sol.Result.Remove("z")

	return

}