public static void VarianceGammaTimesGaussianMoments2(double a, double m, double v, out double mu, out double vu) { // compute weights Matrix laplacianMoments = new Matrix(nWeights, nWeights); DenseVector exactMoments = DenseVector.Constant(laplacianMoments.Rows, 1.0); // a=10: 7-1 // a=15: 8-1 // a=20: 10-1 // a=21: 10-1 // a=30: 12-1 // get best results if the lead term has flat moment ratio int jMax = Math.Max(laplacianMoments.Cols, (int)Math.Round(a - 10)) - 1; jMax = laplacianMoments.Cols - 1; for (int i = 0; i < exactMoments.Count; i++) { //int ii = jMax-i; int ii = i; double logMoment = MMath.GammaLn(ii + a) - MMath.GammaLn(a) - MMath.GammaLn(ii + 1); for (int j = 0; j < laplacianMoments.Cols; j++) { int jj = jMax - j; laplacianMoments[i, j] = Math.Exp(MMath.GammaLn(2 * ii + jj + 1) - MMath.GammaLn(2 * ii + 1) - MMath.GammaLn(jj + 1) - logMoment); } } //Console.WriteLine("exactMoments = {0}, laplacianMoments = ", exactMoments); //Console.WriteLine(laplacianMoments); (new LuDecomposition(laplacianMoments)).Solve(exactMoments); DenseVector weights = exactMoments; Console.WriteLine("weights = {0}", weights); double Z0Plus = 0, Z1Plus = 0, Z2Plus = 0; double Z0Minus = 0, Z1Minus = 0, Z2Minus = 0; double sqrtV = Math.Sqrt(v); double InvSqrtV = 1 / sqrtV; double mPlus = (m - v) * InvSqrtV; double mMinus = (-m - v) * InvSqrtV; for (int j = 0; j < weights.Count; j++) { int jj = jMax - j; Z0Plus += weights[j] * MMath.NormalCdfMomentRatio(0 + jj, mPlus) * Math.Pow(sqrtV, 0 + jj); Z1Plus += weights[j] * MMath.NormalCdfMomentRatio(1 + jj, mPlus) * (1 + jj) * Math.Pow(sqrtV, 1 + jj); Z2Plus += weights[j] * MMath.NormalCdfMomentRatio(2 + jj, mPlus) * (1 + jj) * (2 + jj) * Math.Pow(sqrtV, 2 + jj); Z0Minus += weights[j] * MMath.NormalCdfMomentRatio(0 + jj, mMinus) * Math.Pow(sqrtV, 0 + jj); Z1Minus += weights[j] * MMath.NormalCdfMomentRatio(1 + jj, mMinus) * (1 + jj) * Math.Pow(sqrtV, 1 + jj); Z2Minus += weights[j] * MMath.NormalCdfMomentRatio(2 + jj, mMinus) * (1 + jj) * (2 + jj) * Math.Pow(sqrtV, 2 + jj); } double Z0 = Z0Plus + Z0Minus; double Z1 = Z1Plus - Z1Minus; double Z2 = Z2Plus + Z2Minus; mu = Z1 / Z0; vu = Z2 / Z0 - mu * mu; }
// returns (E[x],var(x)) where p(x) =propto VG(x;a) N(x;m,v). public static void VarianceGammaTimesGaussianMoments3(double a, double m, double v, out double mu, out double vu) { // compute weights // termMoments[i,j] is the ith moment of the jth term Matrix termMoments = new Matrix(nWeights, nWeights); DenseVector exactMoments = DenseVector.Constant(termMoments.Rows, 1.0); for (int i = 0; i < exactMoments.Count; i++) { // ii is half of the exponent int ii = i; double logMoment = MMath.GammaLn(ii + a) - MMath.GammaLn(a) - MMath.GammaLn(ii + 1); for (int j = 0; j < termMoments.Cols; j++) { // jj is the term shape int jj = j + 1; termMoments[i, j] = Math.Exp(MMath.GammaLn(ii + jj) - MMath.GammaLn(ii + 1) - MMath.GammaLn(jj) - logMoment); } } //Console.WriteLine("exactMoments = {0}, termMoments = ", exactMoments); //Console.WriteLine(termMoments); (new LuDecomposition(termMoments)).Solve(exactMoments); DenseVector weights = exactMoments; Console.WriteLine("weights = {0}", weights); double Z0Plus = 0, Z1Plus = 0, Z2Plus = 0; double Z0Minus = 0, Z1Minus = 0, Z2Minus = 0; for (int j = 0; j < weights.Count; j++) { int jj = j + 1; Z0Plus += weights[j] * NormalVGMomentRatio(0, jj, m - v, v); Z1Plus += weights[j] * NormalVGMomentRatio(1, jj, m - v, v); Z2Plus += weights[j] * NormalVGMomentRatio(2, jj, m - v, v); Z0Minus += weights[j] * NormalVGMomentRatio(0, jj, -m - v, v); Z1Minus += weights[j] * NormalVGMomentRatio(1, jj, -m - v, v); Z2Minus += weights[j] * NormalVGMomentRatio(2, jj, -m - v, v); } double Z0 = Z0Plus + Z0Minus; double Z1 = Z1Plus - Z1Minus; double Z2 = Z2Plus + Z2Minus; mu = Z1 / Z0; vu = Z2 / Z0 - mu * mu; //Console.WriteLine("mu = {0}, vu = {1}", mu, vu); }
#pragma warning disable 162 #endif // returns (E[x],var(x)) where p(x) =propto VG(x;a) N(x;m,v). public static void VarianceGammaTimesGaussianMoments4(double a, double m, double v, out double mu, out double vu) { // compute weights // termMoments[i,j] is the ith moment of the jth term Matrix termMoments = new Matrix(nWeights, nWeights); DenseVector weights = DenseVector.Constant(termMoments.Rows, 1.0); // choose shapes of terms to bracket the true shape 'a' int shapeMin = Math.Max(1, (int)Math.Round(a - nWeights / 2)); for (int j = 0; j < termMoments.Cols; j++) { // jj is the term shape int jj = shapeMin + j; double r = jj / a; double moment = 1; for (int i = 0; i < termMoments.Rows; i++) { termMoments[i, j] = moment; moment *= r; } } //Console.WriteLine("exactMoments = {0}, termMoments = ", exactMoments); //Console.WriteLine(termMoments); (new LuDecomposition(termMoments)).Solve(weights); Console.WriteLine("weights = {0}", weights); if (false) { // exact formula for the weights for (int i = 0; i < weights.Count; i++) { double sum = 0; double term = 1; double numr = a - shapeMin + 1; double denomr = 0; for (int j = 0; j < i; j++) { numr--; denomr++; term *= numr / denomr; } denomr = 0; for (int j = i; j < weights.Count; j++) { //Console.WriteLine("term = {0}", term); sum += term; //Console.WriteLine("sum({0},{1}) = {2}", i,j, sum); numr--; denomr++; term *= -numr / denomr; } weights[i] = sum; } Console.WriteLine("weights = {0}", weights); } double Z0Plus = 0, Z1Plus = 0, Z2Plus = 0; double Z0Minus = 0, Z1Minus = 0, Z2Minus = 0; double[][] momentsPlus = NormalVGMomentRatios(2, shapeMin + weights.Count - 1, m - v, v); double[][] momentsMinus = NormalVGMomentRatios(2, shapeMin + weights.Count - 1, -m - v, v); for (int j = 0; j < weights.Count; j++) { int jj = shapeMin + j; Z0Plus += weights[j] * momentsPlus[jj - 1][0]; Z1Plus += weights[j] * momentsPlus[jj - 1][1]; Z2Plus += weights[j] * momentsPlus[jj - 1][2]; Z0Minus += weights[j] * momentsMinus[jj - 1][0]; Z1Minus += weights[j] * momentsMinus[jj - 1][1]; Z2Minus += weights[j] * momentsMinus[jj - 1][2]; } if (false) { double[] binomt = new double[nWeights]; for (int i = 0; i < binomt.Length; i++) { binomt[i] = momentsPlus[shapeMin - 1 + i][0]; } double Z0Plus2 = InterpolateBesselKMoment(a - shapeMin + 1, binomt); Console.WriteLine("Z0Plus = {0}", Z0Plus); Console.WriteLine("Z0Plus2 = {0}", Z0Plus2); } //Console.WriteLine("Z1Plus = {0}, Z1Minus = {1}", Z1Plus, Z1Minus); double Z0 = Z0Plus + Z0Minus; double Z1 = Z1Plus - Z1Minus; double Z2 = Z2Plus + Z2Minus; mu = Z1 / Z0; vu = Z2 / Z0 - mu * mu; //Console.WriteLine("mu = {0}, vu = {1}", mu, vu); }