Exemplo n.º 1
0
func mcsdp(w *matrix.FloatMatrix) (*Solution, error) {
	//
	// Returns solution x, z to
	//
	//    (primal)  minimize    sum(x)
	//              subject to  w + diag(x) >= 0
	//
	//    (dual)    maximize    -tr(w*z)
	//              subject to  diag(z) = 1
	//                          z >= 0.
	//
	n := w.Rows()
	G := &matrixFs{n}

	cngrnc := func(r, x *matrix.FloatMatrix, alpha float64) (err error) {
		// Congruence transformation
		//
		//    x := alpha * r'*x*r.
		//
		// r and x are square matrices.
		//
		err = nil

		// tx = matrix(x, (n,n)) is copying and reshaping
		// scale diagonal of x by 1/2, (x is (n,n))
		tx := x.Copy()
		matrix.Reshape(tx, n, n)
		tx.Diag().Scale(0.5)

		// a := tril(x)*r
		// (python: a = +r is really making a copy of r)
		a := r.Copy()

		err = blas.TrmmFloat(tx, a, 1.0, linalg.OptLeft)

		// x := alpha*(a*r' + r*a')
		err = blas.Syr2kFloat(r, a, tx, alpha, 0.0, linalg.OptTrans)

		// x[:] = tx[:]
		tx.CopyTo(x)
		return
	}

	Fkkt := func(W *sets.FloatMatrixSet) (KKTFunc, error) {

		//    Solve
		//                  -diag(z)                           = bx
		//        -diag(x) - inv(rti*rti') * z * inv(rti*rti') = bs
		//
		//    On entry, x and z contain bx and bs.
		//    On exit, they contain the solution, with z scaled
		//    (inv(rti)'*z*inv(rti) is returned instead of z).
		//
		//    We first solve
		//
		//        ((rti*rti') .* (rti*rti')) * x = bx - diag(t*bs*t)
		//
		//    and take z  = -rti' * (diag(x) + bs) * rti.

		var err error = nil
		rti := W.At("rti")[0]

		// t = rti*rti' as a nonsymmetric matrix.
		t := matrix.FloatZeros(n, n)
		err = blas.GemmFloat(rti, rti, t, 1.0, 0.0, linalg.OptTransB)
		if err != nil {
			return nil, err
		}

		// Cholesky factorization of tsq = t.*t.
		tsq := matrix.Mul(t, t)
		err = lapack.Potrf(tsq)
		if err != nil {
			return nil, err
		}

		f := func(x, y, z *matrix.FloatMatrix) (err error) {
			// tbst := t * zs * t = t * bs * t
			tbst := z.Copy()
			matrix.Reshape(tbst, n, n)
			cngrnc(t, tbst, 1.0)

			// x := x - diag(tbst) = bx - diag(rti*rti' * bs * rti*rti')
			diag := tbst.Diag().Transpose()
			x.Minus(diag)

			// x := (t.*t)^{-1} * x = (t.*t)^{-1} * (bx - diag(t*bs*t))
			err = lapack.Potrs(tsq, x)

			// z := z + diag(x) = bs + diag(x)
			// z, x are really column vectors here
			z.AddIndexes(matrix.MakeIndexSet(0, n*n, n+1), x.FloatArray())

			// z := -rti' * z * rti = -rti' * (diag(x) + bs) * rti
			cngrnc(rti, z, -1.0)
			return nil
		}
		return f, nil
	}

	c := matrix.FloatWithValue(n, 1, 1.0)

	// initial feasible x: x = 1.0 - min(lmbda(w))
	lmbda := matrix.FloatZeros(n, 1)
	wp := w.Copy()
	lapack.Syevx(wp, lmbda, nil, 0.0, nil, []int{1, 1}, linalg.OptRangeInt)
	x0 := matrix.FloatZeros(n, 1).Add(-lmbda.GetAt(0, 0) + 1.0)
	s0 := w.Copy()
	s0.Diag().Plus(x0.Transpose())
	matrix.Reshape(s0, n*n, 1)

	// initial feasible z is identity
	z0 := matrix.FloatIdentity(n)
	matrix.Reshape(z0, n*n, 1)

	dims := sets.DSetNew("l", "q", "s")
	dims.Set("s", []int{n})

	primalstart := sets.FloatSetNew("x", "s")
	dualstart := sets.FloatSetNew("z")
	primalstart.Set("x", x0)
	primalstart.Set("s", s0)
	dualstart.Set("z", z0)

	var solopts SolverOptions
	solopts.MaxIter = 30
	solopts.ShowProgress = false
	h := w.Copy()
	matrix.Reshape(h, h.NumElements(), 1)
	return ConeLpCustomMatrix(c, G, h, nil, nil, dims, Fkkt, &solopts, primalstart, dualstart)
}
Exemplo n.º 2
0
func TestConeLp(t *testing.T) {

	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.}

	// these reference values obtained from running cvxopt conelp.py example
	xref := []float64{-1.22091525026262993, 0.09663323966626469, 3.57750155386611057}

	sref := []float64{
		0.00000172588537019, 13.35314040819201864,
		94.28805677232460880, -53.44110853283719109,
		18.97172963929198275, -75.32834138499130461,
		10.00000013568614321, -1.22091525026262993,
		0.09663323966626476, 3.57750155386611146,
		44.05899318373081286, -58.82581769017131990,
		4.26572401145687596, -58.82581769017131990,
		124.10382738701650851, 40.46243652188705653,
		4.26572401145687596, 40.46243652188705653,
		47.17458693781828316}

	zref := []float64{
		0.09299833991484617, 0.00000001060210894,
		0.23532251654806322, 0.13337937743566930,
		-0.04734875722474355, 0.18800192060450249,
		0.00000001245876667, 0.00000000007816348,
		-0.00000000039584268, -0.00000000183463577,
		0.12558704894101563, 0.08777794737598217,
		-0.08664401207348003, 0.08777794737598217,
		0.06135161787371416, -0.06055906182304811,
		-0.08664401207348003, -0.06055906182304811,
		0.05977675078191153}

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

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

	var solopts SolverOptions
	solopts.MaxIter = 30
	solopts.ShowProgress = false
	sol, err := ConeLp(c, G, h, nil, nil, dims, &solopts, nil, nil)
	if err == nil {
		fail := false
		x := sol.Result.At("x")[0]
		s := sol.Result.At("s")[0]
		z := sol.Result.At("z")[0]
		t.Logf("Optimal\n")
		t.Logf("x=\n%v\n", x.ToString("%.9f"))
		t.Logf("s=\n%v\n", s.ToString("%.9f"))
		t.Logf("z=\n%v\n", z.ToString("%.9f"))
		xe, _ := nrmError(matrix.FloatVector(xref), x)
		if xe > TOL {
			t.Logf("x differs [%.3e] from exepted too much.", xe)
			fail = true
		}
		se, _ := nrmError(matrix.FloatVector(sref), s)
		if se > TOL {
			t.Logf("s differs [%.3e] from exepted too much.", se)
			fail = true
		}
		ze, _ := nrmError(matrix.FloatVector(zref), z)
		if ze > TOL {
			t.Logf("z differs [%.3e] from exepted too much.", ze)
			fail = true
		}
		if fail {
			t.Fail()
		}
	} else {
		t.Logf("status: %s\n", err)
		t.Fail()
	}
}
Exemplo n.º 3
0
func TestConeQp(t *testing.T) {
	adata := [][]float64{
		[]float64{0.3, -0.4, -0.2, -0.4, 1.3},
		[]float64{0.6, 1.2, -1.7, 0.3, -0.3},
		[]float64{-0.3, 0.0, 0.6, -1.2, -2.0}}

	// reference values from cvxopt coneqp.py
	xref := []float64{0.72558318685981904, 0.61806264311119252, 0.30253527966423444}
	sref := []float64{
		0.72558318685981904, 0.61806264311119263,
		0.30253527966423449, 1.00000000000041678,
		-0.72558318686012169, -0.61806264311145032,
		-0.30253527966436067}
	zref := []float64{
		0.00000003332583626, 0.00000005116586239,
		0.00000009993673262, 0.56869648433154019,
		0.41264857754144563, 0.35149286573190930,
		0.17201618570052318}

	A := matrix.FloatMatrixFromTable(adata, matrix.ColumnOrder)
	b := matrix.FloatVector([]float64{1.5, 0.0, -1.2, -0.7, 0.0})

	_, n := A.Size()
	N := n + 1 + n

	h := matrix.FloatZeros(N, 1)
	h.SetIndex(n, 1.0)

	I0 := matrix.FloatDiagonal(n, -1.0)
	I1 := matrix.FloatIdentity(n)
	G, _ := matrix.FloatMatrixStacked(matrix.StackDown, I0, matrix.FloatZeros(1, n), I1)

	At := A.Transpose()
	P := matrix.Times(At, A)
	q := matrix.Times(At, b).Scale(-1.0)

	dims := sets.DSetNew("l", "q", "s")
	dims.Set("l", []int{n})
	dims.Set("q", []int{n + 1})

	var solopts SolverOptions
	solopts.MaxIter = 10
	solopts.ShowProgress = false
	sol, err := ConeQp(P, q, G, h, nil, nil, dims, &solopts, nil)
	if err == nil {
		fail := false
		x := sol.Result.At("x")[0]
		s := sol.Result.At("s")[0]
		z := sol.Result.At("z")[0]
		t.Logf("Optimal\n")
		t.Logf("x=\n%v\n", x.ToString("%.9f"))
		t.Logf("s=\n%v\n", s.ToString("%.9f"))
		t.Logf("z=\n%v\n", z.ToString("%.9f"))
		xe, _ := nrmError(matrix.FloatVector(xref), x)
		if xe > TOL {
			t.Logf("x differs [%.3e] from exepted too much.", xe)
			fail = true
		}
		se, _ := nrmError(matrix.FloatVector(sref), s)
		if se > TOL {
			t.Logf("s differs [%.3e] from exepted too much.", se)
			fail = true
		}
		ze, _ := nrmError(matrix.FloatVector(zref), z)
		if ze > TOL {
			t.Logf("z differs [%.3e] from exepted too much.", ze)
			fail = true
		}
		if fail {
			t.Fail()
		}
	}

}