Example #1
0
// NewProposalNormal constructs a new ProposalNormal for use as a proposal
// distribution for Metropolis-Hastings. ProposalNormal is a multivariate normal
// distribution (implemented by distmv.Normal) where the covariance matrix is fixed
// and the mean of the distribution changes.
//
// NewProposalNormal returns {nil, false} if the covariance matrix is not positive-definite.
func NewProposalNormal(sigma *mat64.SymDense, src *rand.Rand) (*ProposalNormal, bool) {
	mu := make([]float64, sigma.Symmetric())
	normal, ok := distmv.NewNormal(mu, sigma, src)
	if !ok {
		return nil, false
	}
	p := &ProposalNormal{
		normal: normal,
	}
	return p, true
}
Example #2
0
// CovarianceMatrix returns the covariance matrix of the distribution. Upon
// return, the value at element {i, j} of the covariance matrix is equal to
// the covariance of the i^th and j^th variables.
//  covariance(i, j) = E[(x_i - E[x_i])(x_j - E[x_j])]
// If the input matrix is nil a new matrix is allocated, otherwise the result
// is stored in-place into the input.
func (n *Normal) CovarianceMatrix(s *mat64.SymDense) *mat64.SymDense {
	if s == nil {
		s = mat64.NewSymDense(n.Dim(), nil)
	}
	sn := s.Symmetric()
	if sn != n.Dim() {
		panic("normal: input matrix size mismatch")
	}
	n.setSigma()
	s.CopySym(n.sigma)
	return s
}
Example #3
0
// CovarianceMatrix calculates a covariance matrix (also known as a
// variance-covariance matrix) from a matrix of data, using a two-pass
// algorithm.
//
// The weights must have length equal to the number of rows in
// input data matrix x. If cov is nil, then a new matrix with appropriate size will
// be constructed. If cov is not nil, it should have the same number of columns as the
// input data matrix x, and it will be used as the destination for the covariance
// data. Weights must not be negative.
func CovarianceMatrix(cov *mat64.SymDense, x mat64.Matrix, weights []float64) *mat64.SymDense {
	// This is the matrix version of the two-pass algorithm. It doesn't use the
	// additional floating point error correction that the Covariance function uses
	// to reduce the impact of rounding during centering.

	r, c := x.Dims()

	if cov == nil {
		cov = mat64.NewSymDense(c, nil)
	} else if n := cov.Symmetric(); n != c {
		panic(matrix.ErrShape)
	}

	var xt mat64.Dense
	xt.Clone(x.T())
	// Subtract the mean of each of the columns.
	for i := 0; i < c; i++ {
		v := xt.RawRowView(i)
		// This will panic with ErrShape if len(weights) != len(v), so
		// we don't have to check the size later.
		mean := Mean(v, weights)
		floats.AddConst(-mean, v)
	}

	if weights == nil {
		// Calculate the normalization factor
		// scaled by the sample size.
		cov.SymOuterK(1/(float64(r)-1), &xt)
		return cov
	}

	// Multiply by the sqrt of the weights, so that multiplication is symmetric.
	sqrtwts := make([]float64, r)
	for i, w := range weights {
		if w < 0 {
			panic("stat: negative covariance matrix weights")
		}
		sqrtwts[i] = math.Sqrt(w)
	}
	// Weight the rows.
	for i := 0; i < c; i++ {
		v := xt.RawRowView(i)
		floats.Mul(v, sqrtwts)
	}

	// Calculate the normalization factor
	// scaled by the weighted sample size.
	cov.SymOuterK(1/(floats.Sum(weights)-1), &xt)
	return cov
}
Example #4
0
func (gp *GP) setKernelMat(s *mat64.SymDense, noise float64) {
	n := s.Symmetric()
	for i := 0; i < n; i++ {
		for j := i; j < n; j++ {
			v := gp.kernel.Distance(
				gp.inputs.RawRowView(i),
				gp.inputs.RawRowView(j),
			)
			if i == j {
				v += noise
			}
			s.SetSym(i, j, v)
		}
	}
}
Example #5
0
func (BrownBadlyScaled) Hess(x []float64, hess *mat64.SymDense) {
	if len(x) != 2 {
		panic("dimension of the problem must be 2")
	}
	if len(x) != hess.Symmetric() {
		panic("incorrect size of the Hessian")
	}

	h00 := 2 + 2*x[1]*x[1]
	h01 := 4*x[0]*x[1] - 4
	h11 := 2 + 2*x[0]*x[0]
	hess.SetSym(0, 0, h00)
	hess.SetSym(0, 1, h01)
	hess.SetSym(1, 1, h11)
}
Example #6
0
// covToCorr converts a covariance matrix to a correlation matrix.
func covToCorr(c *mat64.SymDense) {
	r := c.Symmetric()

	s := make([]float64, r)
	for i := 0; i < r; i++ {
		s[i] = 1 / math.Sqrt(c.At(i, i))
	}
	for i, sx := range s {
		// Ensure that the diagonal has exactly ones.
		c.SetSym(i, i, 1)
		for j := i + 1; j < r; j++ {
			v := c.At(i, j)
			c.SetSym(i, j, v*sx*s[j])
		}
	}
}
Example #7
0
func (Watson) Hess(x []float64, hess *mat64.SymDense) {
	dim := len(x)
	if dim != hess.Symmetric() {
		panic("incorrect size of the Hessian")
	}

	for j := 0; j < dim; j++ {
		for k := j; k < dim; k++ {
			hess.SetSym(j, k, 0)
		}
	}
	for i := 1; i <= 29; i++ {
		d1 := float64(i) / 29
		d2 := 1.0
		var s1 float64
		for j := 1; j < dim; j++ {
			s1 += float64(j) * d2 * x[j]
			d2 *= d1
		}

		d2 = 1.0
		var s2 float64
		for _, v := range x {
			s2 += d2 * v
			d2 *= d1
		}

		t := s1 - s2*s2 - 1
		s3 := 2 * d1 * s2
		d2 = 2 / d1
		th := 2 * d1 * d1 * t
		for j := 0; j < dim; j++ {
			v := float64(j) - s3
			d3 := 1 / d1
			for k := 0; k <= j; k++ {
				hess.SetSym(k, j, hess.At(k, j)+d2*d3*(v*(float64(k)-s3)-th))
				d3 *= d1
			}
			d2 *= d1
		}
	}
	t1 := x[1] - x[0]*x[0] - 1
	hess.SetSym(0, 0, hess.At(0, 0)+8*x[0]*x[0]+2-4*t1)
	hess.SetSym(0, 1, hess.At(0, 1)-4*x[0])
	hess.SetSym(1, 1, hess.At(1, 1)+2)
}
Example #8
0
func (Wood) Hess(x []float64, hess *mat64.SymDense) {
	if len(x) != 4 {
		panic("dimension of the problem must be 4")
	}
	if len(x) != hess.Symmetric() {
		panic("incorrect size of the Hessian")
	}

	hess.SetSym(0, 0, 400*(3*x[0]*x[0]-x[1])+2)
	hess.SetSym(0, 1, -400*x[0])
	hess.SetSym(1, 1, 220.2)
	hess.SetSym(0, 2, 0)
	hess.SetSym(1, 2, 0)
	hess.SetSym(2, 2, 360*(3*x[2]*x[2]-x[3])+2)
	hess.SetSym(0, 3, 0)
	hess.SetSym(1, 3, 19.8)
	hess.SetSym(2, 3, -360*x[2])
	hess.SetSym(3, 3, 200.2)
}
Example #9
0
func (PowellBadlyScaled) Hess(x []float64, hess *mat64.SymDense) {
	if len(x) != 2 {
		panic("dimension of the problem must be 2")
	}
	if len(x) != hess.Symmetric() {
		panic("incorrect size of the Hessian")
	}

	t1 := 1e4*x[0]*x[1] - 1
	s1 := math.Exp(-x[0])
	s2 := math.Exp(-x[1])
	t2 := s1 + s2 - 1.0001

	h00 := 2 * (1e8*x[1]*x[1] + s1*(s1+t2))
	h01 := 2 * (1e4*(1+2*t1) + s1*s2)
	h11 := 2 * (1e8*x[0]*x[0] + s2*(s2+t2))
	hess.SetSym(0, 0, h00)
	hess.SetSym(0, 1, h01)
	hess.SetSym(1, 1, h11)
}
Example #10
0
func (BrownAndDennis) Hess(x []float64, hess *mat64.SymDense) {
	if len(x) != 4 {
		panic("dimension of the problem must be 4")
	}
	if len(x) != hess.Symmetric() {
		panic("incorrect size of the Hessian")
	}

	for i := 0; i < 4; i++ {
		for j := i; j < 4; j++ {
			hess.SetSym(i, j, 0)
		}
	}
	for i := 1; i <= 20; i++ {
		d1 := float64(i) / 5
		d2 := math.Sin(d1)
		t1 := x[0] + d1*x[1] - math.Exp(d1)
		t2 := x[2] + d2*x[3] - math.Cos(d1)
		t := t1*t1 + t2*t2
		s3 := 2 * t1 * t2
		r1 := t + 2*t1*t1
		r2 := t + 2*t2*t2
		hess.SetSym(0, 0, hess.At(0, 0)+r1)
		hess.SetSym(0, 1, hess.At(0, 1)+d1*r1)
		hess.SetSym(1, 1, hess.At(1, 1)+d1*d1*r1)
		hess.SetSym(0, 2, hess.At(0, 2)+s3)
		hess.SetSym(1, 2, hess.At(1, 2)+d1*s3)
		hess.SetSym(2, 2, hess.At(2, 2)+r2)
		hess.SetSym(0, 3, hess.At(0, 3)+d2*s3)
		hess.SetSym(1, 3, hess.At(1, 3)+d1*d2*s3)
		hess.SetSym(2, 3, hess.At(2, 3)+d2*r2)
		hess.SetSym(3, 3, hess.At(3, 3)+d2*d2*r2)
	}
	for i := 0; i < 4; i++ {
		for j := i; j < 4; j++ {
			hess.SetSym(i, j, 4*hess.At(i, j))
		}
	}
}
Example #11
0
func (Beale) Hess(x []float64, hess *mat64.SymDense) {
	if len(x) != 2 {
		panic("dimension of the problem must be 2")
	}
	if len(x) != hess.Symmetric() {
		panic("incorrect size of the Hessian")
	}

	t1 := 1 - x[1]
	t2 := 1 - x[1]*x[1]
	t3 := 1 - x[1]*x[1]*x[1]
	f1 := 1.5 - x[1]*t1
	f2 := 2.25 - x[1]*t2
	f3 := 2.625 - x[1]*t3

	h00 := 2 * (t1*t1 + t2*t2 + t3*t3)
	h01 := 2 * (f1 + x[1]*(2*f2+3*x[1]*f3) - x[0]*(t1+x[1]*(2*t2+3*x[1]*t3)))
	h11 := 2 * x[0] * (x[0] + 2*f2 + x[1]*(6*f3+x[0]*x[1]*(4+9*x[1]*x[1])))
	hess.SetSym(0, 0, h00)
	hess.SetSym(0, 1, h01)
	hess.SetSym(1, 1, h11)
}
Example #12
0
// NewNormalPrecision creates a new Normal distribution with the given mean and
// precision matrix (inverse of the covariance matrix). NewNormalPrecision
// panics if len(mu) is not equal to prec.Symmetric(). If the precision matrix
// is not positive-definite, NewNormalPrecision returns nil for norm and false
// for ok.
func NewNormalPrecision(mu []float64, prec *mat64.SymDense, src *rand.Rand) (norm *Normal, ok bool) {
	if len(mu) == 0 {
		panic(badZeroDimension)
	}
	dim := prec.Symmetric()
	if dim != len(mu) {
		panic(badSizeMismatch)
	}
	// TODO(btracey): Computing a matrix inverse is generally numerically instable.
	// This only has to compute the inverse of a positive definite matrix, which
	// is much better, but this still loses precision. It is worth considering if
	// instead the precision matrix should be stored explicitly and used instead
	// of the Cholesky decomposition of the covariance matrix where appropriate.
	var chol mat64.Cholesky
	ok = chol.Factorize(prec)
	if !ok {
		return nil, false
	}
	var sigma mat64.SymDense
	sigma.InverseCholesky(&chol)
	return NewNormal(mu, &sigma, src)
}