func sendMessageHelper(msgIdx, varIdx int, msgBag, varBag *collection.DistributionBag) float64 { mar := varBag.Get(varIdx) msg := msgBag.Get(msgIdx) varBag.Put(varIdx, mar.Mul(msg)) // logZ return gaussian.LogProdNorm(mar, msg) }
func gaussianGreaterThanOrWithinUpdateMessage(epsilon float64, msgIdx, varIdx int, msgBag, varBag *collection.DistributionBag, vFunc, wFunc func(t, epsilon float64) float64) float64 { oldMarginal := varBag.Get(varIdx) oldMsg := msgBag.Get(msgIdx) msgFromVar := oldMarginal.Div(oldMsg) c := msgFromVar.Precision d := msgFromVar.PrecisionMean sqrtC := math.Sqrt(c) dOnSqrtC := d / sqrtC epsTimesSqrtC := epsilon * sqrtC denom := 1.0 - wFunc(dOnSqrtC, epsTimesSqrtC) newPrecision := c / denom newPrecisionMean := (d + sqrtC*vFunc(dOnSqrtC, epsTimesSqrtC)) / denom newMarginal := gaussian.NewFromPrecision(newPrecisionMean, newPrecision) newMsg := oldMsg.Mul(newMarginal).Div(oldMarginal) msgBag.Put(msgIdx, newMsg) varBag.Put(varIdx, newMarginal) return newMarginal.Sub(oldMarginal) }
// GaussianPrior calculates the prior for the factor graph. func (gf GaussianFactors) GaussianPrior(mu, sigmaSquared float64, varIdx int, varBag *collection.DistributionBag) Factor { msgIdx := gf.msgBag.NextIndex() newMsg := gaussian.NewFromMeanAndVariance(mu, sigmaSquared) updateMessage := func(i int) float64 { if i != 0 { panic("Index out of range") } oldMarginal := varBag.Get(varIdx) oldMsg := gf.msgBag.Get(msgIdx) newMarginal := gaussian.NewFromPrecision(oldMarginal.PrecisionMean+newMsg.PrecisionMean-oldMsg.PrecisionMean, oldMarginal.Precision+newMsg.Precision-oldMsg.Precision) varBag.Put(varIdx, newMarginal) gf.msgBag.Put(msgIdx, newMsg) delta := oldMarginal.Sub(newMarginal) return delta } sendMessage := func(i int) float64 { if i != 0 { panic("Index out of range") } return sendMessageHelper(msgIdx, varIdx, gf.msgBag, varBag) } return Factor{ UpdateMessage: updateMessage, LogNormalization: func() float64 { return 0 }, NumMessages: 1, ResetMarginals: func() { varBag.PutPriorAt(varIdx) }, SendMessage: sendMessage, } }