// curve optimization called here- adjust optimization parameters here internal void calculate() { FittingCost costFunction = costFunction_; Constraint constraint = new NoConstraint(); // start with the guess solution, if it exists Vector x = new Vector(size(), 0.0); if (!curve_.guessSolution_.empty()) { x = curve_.guessSolution_; } if (curve_.maxEvaluations_ == 0) { //Don't calculate, simply use given parameters to provide a fitted curve. //This turns the fittedbonddiscountcurve into an evaluator of the parametric //curve, for example allowing to use the parameters for a credit spread curve //calculated with bonds in one currency to be coupled to a discount curve in //another currency. return; } //workaround for backwards compatibility OptimizationMethod optimization = optimizationMethod_; if (optimization == null) { optimization = new Simplex(curve_.simplexLambda_); } Problem problem = new Problem(costFunction, constraint, x); double rootEpsilon = curve_.accuracy_; double functionEpsilon = curve_.accuracy_; double gradientNormEpsilon = curve_.accuracy_; EndCriteria endCriteria = new EndCriteria(curve_.maxEvaluations_, curve_.maxStationaryStateIterations_, rootEpsilon, functionEpsilon, gradientNormEpsilon); optimization.minimize(problem, endCriteria); solution_ = problem.currentValue(); numberOfIterations_ = problem.functionEvaluation(); costValue_ = problem.functionValue(); // save the results as the guess solution, in case of recalculation curve_.guessSolution_ = solution_; }
//! Calibrate to a set of market instruments (caps/swaptions) /*! An additional constraint can be passed which must be * satisfied in addition to the constraints of the model. */ public void calibrate(List <CalibrationHelper> instruments, OptimizationMethod method, EndCriteria endCriteria, Constraint additionalConstraint = null, List <double> weights = null, List <bool> fixParameters = null) { if (weights == null) { weights = new List <double>(); } if (additionalConstraint == null) { additionalConstraint = new Constraint(); } Utils.QL_REQUIRE(weights.empty() || weights.Count == instruments.Count, () => "mismatch between number of instruments (" + instruments.Count + ") and weights(" + weights.Count + ")"); Constraint c; if (additionalConstraint.empty()) { c = constraint_; } else { c = new CompositeConstraint(constraint_, additionalConstraint); } List <double> w = weights.Count == 0 ? new InitializedList <double>(instruments.Count, 1.0) : weights; Vector prms = parameters(); List <bool> all = new InitializedList <bool>(prms.size(), false); Projection proj = new Projection(prms, fixParameters ?? all); CalibrationFunction f = new CalibrationFunction(this, instruments, w, proj); ProjectedConstraint pc = new ProjectedConstraint(c, proj); Problem prob = new Problem(f, pc, proj.project(prms)); shortRateEndCriteria_ = method.minimize(prob, endCriteria); Vector result = new Vector(prob.currentValue()); setParams(proj.include(result)); Vector shortRateProblemValues_ = prob.values(result); notifyObservers(); }
//! Solve least square problem using numerix solver public Vector perform(ref LeastSquareProblem lsProblem) { double eps = accuracy_; // wrap the least square problem in an optimization function LeastSquareFunction lsf = new LeastSquareFunction(lsProblem); // define optimization problem Problem P = new Problem(lsf, c_, initialValue_); // minimize EndCriteria ec = new EndCriteria(maxIterations_, Math.Min(maxIterations_ / 2, 100), eps, eps, eps); exitFlag_ = (int)om_.minimize(P, ec); results_ = P.currentValue(); resnorm_ = P.functionValue(); bestAccuracy_ = P.functionValue(); return(results_); }
// Optimization function for hypersphere and lower-diagonal algorithm private static Matrix hypersphereOptimize(Matrix targetMatrix, Matrix currentRoot, bool lowerDiagonal) { int i, j, k, size = targetMatrix.rows(); Matrix result = new Matrix(currentRoot); Vector variance = new Vector(size); for (i = 0; i < size; i++) { variance[i] = Math.Sqrt(targetMatrix[i, i]); } if (lowerDiagonal) { Matrix approxMatrix = result * Matrix.transpose(result); result = MatrixUtilities.CholeskyDecomposition(approxMatrix, true); for (i = 0; i < size; i++) { for (j = 0; j < size; j++) { result[i, j] /= Math.Sqrt(approxMatrix[i, i]); } } } else { for (i = 0; i < size; i++) { for (j = 0; j < size; j++) { result[i, j] /= variance[i]; } } } ConjugateGradient optimize = new ConjugateGradient(); EndCriteria endCriteria = new EndCriteria(100, 10, 1e-8, 1e-8, 1e-8); HypersphereCostFunction costFunction = new HypersphereCostFunction(targetMatrix, variance, lowerDiagonal); NoConstraint constraint = new NoConstraint(); // hypersphere vector optimization if (lowerDiagonal) { Vector theta = new Vector(size * (size - 1) / 2); const double eps = 1e-16; for (i = 1; i < size; i++) { for (j = 0; j < i; j++) { theta[i * (i - 1) / 2 + j] = result[i, j]; if (theta[i * (i - 1) / 2 + j] > 1 - eps) { theta[i * (i - 1) / 2 + j] = 1 - eps; } if (theta[i * (i - 1) / 2 + j] < -1 + eps) { theta[i * (i - 1) / 2 + j] = -1 + eps; } for (k = 0; k < j; k++) { theta[i * (i - 1) / 2 + j] /= Math.Sin(theta[i * (i - 1) / 2 + k]); if (theta[i * (i - 1) / 2 + j] > 1 - eps) { theta[i * (i - 1) / 2 + j] = 1 - eps; } if (theta[i * (i - 1) / 2 + j] < -1 + eps) { theta[i * (i - 1) / 2 + j] = -1 + eps; } } theta[i * (i - 1) / 2 + j] = Math.Acos(theta[i * (i - 1) / 2 + j]); if (j == i - 1) { if (result[i, i] < 0) { theta[i * (i - 1) / 2 + j] = -theta[i * (i - 1) / 2 + j]; } } } } Problem p = new Problem(costFunction, constraint, theta); optimize.minimize(p, endCriteria); theta = p.currentValue(); result.fill(1); for (i = 0; i < size; i++) { for (k = 0; k < size; k++) { if (k > i) { result[i, k] = 0; } else { for (j = 0; j <= k; j++) { if (j == k && k != i) { result[i, k] *= Math.Cos(theta[i * (i - 1) / 2 + j]); } else if (j != i) { result[i, k] *= Math.Sin(theta[i * (i - 1) / 2 + j]); } } } } } } else { Vector theta = new Vector(size * (size - 1)); const double eps = 1e-16; for (i = 0; i < size; i++) { for (j = 0; j < size - 1; j++) { theta[j * size + i] = result[i, j]; if (theta[j * size + i] > 1 - eps) { theta[j * size + i] = 1 - eps; } if (theta[j * size + i] < -1 + eps) { theta[j * size + i] = -1 + eps; } for (k = 0; k < j; k++) { theta[j * size + i] /= Math.Sin(theta[k * size + i]); if (theta[j * size + i] > 1 - eps) { theta[j * size + i] = 1 - eps; } if (theta[j * size + i] < -1 + eps) { theta[j * size + i] = -1 + eps; } } theta[j * size + i] = Math.Acos(theta[j * size + i]); if (j == size - 2) { if (result[i, j + 1] < 0) { theta[j * size + i] = -theta[j * size + i]; } } } } Problem p = new Problem(costFunction, constraint, theta); optimize.minimize(p, endCriteria); theta = p.currentValue(); result.fill(1); for (i = 0; i < size; i++) { for (k = 0; k < size; k++) { for (j = 0; j <= k; j++) { if (j == k && k != size - 1) { result[i, k] *= Math.Cos(theta[j * size + i]); } else if (j != size - 1) { result[i, k] *= Math.Sin(theta[j * size + i]); } } } } } for (i = 0; i < size; i++) { for (j = 0; j < size; j++) { result[i, j] *= variance[i]; } } return(result); }
public override void update() { coeff_.updateModelInstance(); // we should also check that y contains positive values only // we must update weights if it is vegaWeighted if (vegaWeighted_) { coeff_.weights_.Clear(); double weightsSum = 0.0; for (int i = 0; i < xBegin_.Count; i++) { double stdDev = Math.Sqrt((yBegin_[i]) * (yBegin_[i]) * coeff_.t_); coeff_.weights_.Add(coeff_.model_.weight(xBegin_[i], forward_, stdDev, coeff_.addParams_)); weightsSum += coeff_.weights_.Last(); } // weight normalization for (int i = 0; i < coeff_.weights_.Count; i++) { coeff_.weights_[i] /= weightsSum; } } // there is nothing to optimize if (coeff_.paramIsFixed_.Aggregate((a, b) => b && a)) { coeff_.error_ = interpolationError(); coeff_.maxError_ = interpolationMaxError(); coeff_.XABREndCriteria_ = EndCriteria.Type.None; return; } XABRError costFunction = new XABRError(this); Vector guess = new Vector(coeff_.model_.dimension()); for (int i = 0; i < guess.size(); ++i) { guess[i] = coeff_.params_[i].GetValueOrDefault(); } int iterations = 0; int freeParameters = 0; double bestError = double.MaxValue; Vector bestParameters = new Vector(); for (int i = 0; i < coeff_.model_.dimension(); ++i) { if (!coeff_.paramIsFixed_[i]) { ++freeParameters; } } HaltonRsg halton = new HaltonRsg(freeParameters, 42); EndCriteria.Type tmpEndCriteria; double tmpInterpolationError; do { if (iterations > 0) { Sample <List <double> > s = halton.nextSequence(); coeff_.model_.guess(guess, coeff_.paramIsFixed_, forward_, coeff_.t_, s.value, coeff_.addParams_); for (int i = 0; i < coeff_.paramIsFixed_.Count; ++i) { if (coeff_.paramIsFixed_[i]) { guess[i] = coeff_.params_[i].GetValueOrDefault(); } } } Vector inversedTransformatedGuess = new Vector(coeff_.model_.inverse(guess, coeff_.paramIsFixed_, coeff_.params_, forward_)); ProjectedCostFunction rainedXABRError = new ProjectedCostFunction(costFunction, inversedTransformatedGuess, coeff_.paramIsFixed_); Vector projectedGuess = new Vector(rainedXABRError.project(inversedTransformatedGuess)); constraint_.config(rainedXABRError, coeff_, forward_); Problem problem = new Problem(rainedXABRError, constraint_, projectedGuess); tmpEndCriteria = optMethod_.minimize(problem, endCriteria_); Vector projectedResult = new Vector(problem.currentValue()); Vector transfResult = new Vector(rainedXABRError.include(projectedResult)); Vector result = coeff_.model_.direct(transfResult, coeff_.paramIsFixed_, coeff_.params_, forward_); tmpInterpolationError = useMaxError_ ? interpolationMaxError() : interpolationError(); if (tmpInterpolationError < bestError) { bestError = tmpInterpolationError; bestParameters = result; coeff_.XABREndCriteria_ = tmpEndCriteria; } }while (++iterations < maxGuesses_ && tmpInterpolationError > errorAccept_); for (int i = 0; i < bestParameters.size(); ++i) { coeff_.params_[i] = bestParameters[i]; } coeff_.error_ = interpolationError(); coeff_.maxError_ = interpolationMaxError(); }
public override EndCriteria.Type minimize(Problem P, EndCriteria endCriteria) { // set up of the problem //double ftol = endCriteria.functionEpsilon(); // end criteria on f(x) (see Numerical Recipes in C++, p.410) double xtol = endCriteria.rootEpsilon(); // end criteria on x (see GSL v. 1.9, http://www.gnu.org/software/gsl/) int maxStationaryStateIterations_ = endCriteria.maxStationaryStateIterations(); EndCriteria.Type ecType = EndCriteria.Type.None; P.reset(); Vector x_ = P.currentValue(); int iterationNumber_ = 0; // Initialize vertices of the simplex bool end = false; int n = x_.Count; vertices_ = new InitializedList <Vector>(n + 1, x_); for (int i = 0; i < n; i++) { Vector direction = new Vector(n, 0.0); Vector vertice = vertices_[i + 1]; direction[i] = 1.0; P.constraint().update(ref vertice, direction, lambda_); vertices_[i + 1] = vertice; } // Initialize function values at the vertices of the simplex values_ = new Vector(n + 1, 0.0); for (int i = 0; i <= n; i++) { values_[i] = P.value(vertices_[i]); } // Loop looking for minimum do { sum_ = new Vector(n, 0.0); for (int i = 0; i <= n; i++) { sum_ += vertices_[i]; } // Determine the best (iLowest), worst (iHighest) // and 2nd worst (iNextHighest) vertices int iLowest = 0; int iHighest; int iNextHighest; if (values_[0] < values_[1]) { iHighest = 1; iNextHighest = 0; } else { iHighest = 0; iNextHighest = 1; } for (int i = 1; i <= n; i++) { if (values_[i] > values_[iHighest]) { iNextHighest = iHighest; iHighest = i; } else { if ((values_[i] > values_[iNextHighest]) && i != iHighest) { iNextHighest = i; } } if (values_[i] < values_[iLowest]) { iLowest = i; } } // Now compute accuracy, update iteration number and check end criteria // GSL exit strategy on x (see GSL v. 1.9, http://www.gnu.org/software/gsl double simplexSize = Utils.computeSimplexSize(vertices_); ++iterationNumber_; if (simplexSize < xtol || endCriteria.checkMaxIterations(iterationNumber_, ref ecType)) { endCriteria.checkStationaryPoint(0.0, 0.0, ref maxStationaryStateIterations_, ref ecType); endCriteria.checkMaxIterations(iterationNumber_, ref ecType); x_ = vertices_[iLowest]; double low = values_[iLowest]; P.setFunctionValue(low); P.setCurrentValue(x_); return(ecType); } // If end criteria is not met, continue double factor = -1.0; double vTry = extrapolate(ref P, iHighest, ref factor); if ((vTry <= values_[iLowest]) && (factor.IsEqual(-1.0))) { factor = 2.0; extrapolate(ref P, iHighest, ref factor); } else if (Math.Abs(factor) > Const.QL_EPSILON) { if (vTry >= values_[iNextHighest]) { double vSave = values_[iHighest]; factor = 0.5; vTry = extrapolate(ref P, iHighest, ref factor); if (vTry >= vSave && Math.Abs(factor) > Const.QL_EPSILON) { for (int i = 0; i <= n; i++) { if (i != iLowest) { #if QL_ARRAY_EXPRESSIONS vertices_[i] = 0.5 * (vertices_[i] + vertices_[iLowest]); #else vertices_[i] += vertices_[iLowest]; vertices_[i] *= 0.5; #endif values_[i] = P.value(vertices_[i]); } } } } } // If can't extrapolate given the constraints, exit if (Math.Abs(factor) <= Const.QL_EPSILON) { x_ = vertices_[iLowest]; double low = values_[iLowest]; P.setFunctionValue(low); P.setCurrentValue(x_); return(EndCriteria.Type.StationaryFunctionValue); } }while (end == false); Utils.QL_FAIL("optimization failed: unexpected behaviour"); return(0); }
public override EndCriteria.Type minimize(Problem P, EndCriteria endCriteria) { int stationaryStateIterations_ = 0; EndCriteria.Type ecType = EndCriteria.Type.None; P.reset(); Vector x = P.currentValue(); iteration_ = 0; n_ = x.size(); ptry_ = new Vector(n_, 0.0); // build vertices vertices_ = new InitializedList <Vector>(n_ + 1, x); for (i_ = 0; i_ < n_; i_++) { Vector direction = new Vector(n_, 0.0); direction[i_] = 1.0; Vector tmp = vertices_[i_ + 1]; P.constraint().update(ref tmp, direction, lambda_); vertices_[i_ + 1] = tmp; } values_ = new Vector(n_ + 1, 0.0); for (i_ = 0; i_ <= n_; i_++) { if (!P.constraint().test(vertices_[i_])) { values_[i_] = Double.MaxValue; } else { values_[i_] = P.value(vertices_[i_]); } if (Double.IsNaN(ytry_)) { // handle NAN values_[i_] = Double.MaxValue; } } // minimize T_ = T0_; yb_ = Double.MaxValue; pb_ = new Vector(n_, 0.0); do { iterationT_ = iteration_; do { sum_ = new Vector(n_, 0.0); for (i_ = 0; i_ <= n_; i_++) { sum_ += vertices_[i_]; } tt_ = -T_; ilo_ = 0; ihi_ = 1; ynhi_ = values_[0] + tt_ * Math.Log(rng_.next().value); ylo_ = ynhi_; yhi_ = values_[1] + tt_ * Math.Log(rng_.next().value); if (ylo_ > yhi_) { ihi_ = 0; ilo_ = 1; ynhi_ = yhi_; yhi_ = ylo_; ylo_ = ynhi_; } for (i_ = 2; i_ < n_ + 1; i_++) { yt_ = values_[i_] + tt_ * Math.Log(rng_.next().value); if (yt_ <= ylo_) { ilo_ = i_; ylo_ = yt_; } if (yt_ > yhi_) { ynhi_ = yhi_; ihi_ = i_; yhi_ = yt_; } else { if (yt_ > ynhi_) { ynhi_ = yt_; } } } // GSL end criterion in x (cf. above) if (endCriteria.checkStationaryPoint(simplexSize(), 0.0, ref stationaryStateIterations_, ref ecType) || endCriteria.checkMaxIterations(iteration_, ref ecType)) { // no matter what, we return the best ever point ! P.setCurrentValue(pb_); P.setFunctionValue(yb_); return(ecType); } iteration_ += 2; amotsa(P, -1.0); if (ytry_ <= ylo_) { amotsa(P, 2.0); } else { if (ytry_ >= ynhi_) { ysave_ = yhi_; amotsa(P, 0.5); if (ytry_ >= ysave_) { for (i_ = 0; i_ < n_ + 1; i_++) { if (i_ != ilo_) { for (j_ = 0; j_ < n_; j_++) { sum_[j_] = 0.5 * (vertices_[i_][j_] + vertices_[ilo_][j_]); vertices_[i_][j_] = sum_[j_]; } values_[i_] = P.value(sum_); } } iteration_ += n_; for (i_ = 0; i_ < n_; i_++) { sum_[i_] = 0.0; } for (i_ = 0; i_ <= n_; i_++) { sum_ += vertices_[i_]; } } } else { iteration_ += 1; } } }while (iteration_ < iterationT_ + (scheme_ == Scheme.ConstantFactor ? m_ : 1)); switch (scheme_) { case Scheme.ConstantFactor: T_ *= (1.0 - epsilon_); break; case Scheme.ConstantBudget: if (iteration_ <= K_) { T_ = T0_ * Math.Pow(1.0 - Convert.ToDouble(iteration_) / Convert.ToDouble(K_), alpha_); } else { T_ = 0.0; } break; } }while (true); }
public override EndCriteria.Type minimize(Problem P, EndCriteria endCriteria) { // Initializations double ftol = endCriteria.functionEpsilon(); int maxStationaryStateIterations_ = endCriteria.maxStationaryStateIterations(); EndCriteria.Type ecType = EndCriteria.Type.None; // reset end criteria P.reset(); // reset problem Vector x_ = P.currentValue(); // store the starting point int iterationNumber_ = 0; // dimension line search lineSearch_.searchDirection = new Vector(x_.size()); bool done = false; // function and squared norm of gradient values double fnew, fold, gold2; double fdiff; // classical initial value for line-search step double t = 1.0; // Set gradient g at the size of the optimization problem // search direction int sz = lineSearch_.searchDirection.size(); Vector prevGradient = new Vector(sz), d = new Vector(sz), sddiff = new Vector(sz), direction = new Vector(sz); // Initialize cost function, gradient prevGradient and search direction P.setFunctionValue(P.valueAndGradient(ref prevGradient, x_)); P.setGradientNormValue(Vector.DotProduct(prevGradient, prevGradient)); lineSearch_.searchDirection = prevGradient * -1; bool first_time = true; // Loop over iterations do { // Linesearch if (!first_time) { prevGradient = lineSearch_.lastGradient(); } t = (lineSearch_.value(P, ref ecType, endCriteria, t)); // don't throw: it can fail just because maxIterations exceeded if (lineSearch_.succeed()) { // Updates // New point x_ = lineSearch_.lastX(); // New function value fold = P.functionValue(); P.setFunctionValue(lineSearch_.lastFunctionValue()); // New gradient and search direction vectors // orthogonalization coef gold2 = P.gradientNormValue(); P.setGradientNormValue(lineSearch_.lastGradientNorm2()); // conjugate gradient search direction direction = getUpdatedDirection(P, gold2, prevGradient); sddiff = direction - lineSearch_.searchDirection; lineSearch_.searchDirection = direction; // Now compute accuracy and check end criteria // Numerical Recipes exit strategy on fx (see NR in C++, p.423) fnew = P.functionValue(); fdiff = 2.0 * Math.Abs(fnew - fold) / (Math.Abs(fnew) + Math.Abs(fold) + Const.QL_EPSILON); if (fdiff < ftol || endCriteria.checkMaxIterations(iterationNumber_, ref ecType)) { endCriteria.checkStationaryFunctionValue(0.0, 0.0, ref maxStationaryStateIterations_, ref ecType); endCriteria.checkMaxIterations(iterationNumber_, ref ecType); return(ecType); } P.setCurrentValue(x_); // update problem current value ++iterationNumber_; // Increase iteration number first_time = false; } else { done = true; } }while (!done); P.setCurrentValue(x_); return(ecType); }
public override EndCriteria.Type minimize(Problem P, EndCriteria endCriteria) { EndCriteria.Type ecType = EndCriteria.Type.None; P.reset(); Vector x_ = P.currentValue(); currentProblem_ = P; initCostValues_ = P.costFunction().values(x_); int m = initCostValues_.size(); int n = x_.size(); if (useCostFunctionsJacobian_) { initJacobian_ = new Matrix(m, n); P.costFunction().jacobian(initJacobian_, x_); } Vector xx = new Vector(x_); Vector fvec = new Vector(m), diag = new Vector(n); int mode = 1; double factor = 1; int nprint = 0; int info = 0; int nfev = 0; Matrix fjac = new Matrix(m, n); int ldfjac = m; List <int> ipvt = new InitializedList <int>(n); Vector qtf = new Vector(n), wa1 = new Vector(n), wa2 = new Vector(n), wa3 = new Vector(n), wa4 = new Vector(m); // call lmdif to minimize the sum of the squares of m functions // in n variables by the Levenberg-Marquardt algorithm. Func <int, int, Vector, int, Matrix> j = null; if (useCostFunctionsJacobian_) { j = jacFcn; } // requirements; check here to get more detailed error messages. Utils.QL_REQUIRE(n > 0, () => "no variables given"); Utils.QL_REQUIRE(m >= n, () => $"less functions ({m}) than available variables ({n})"); Utils.QL_REQUIRE(endCriteria.functionEpsilon() >= 0.0, () => "negative f tolerance"); Utils.QL_REQUIRE(xtol_ >= 0.0, () => "negative x tolerance"); Utils.QL_REQUIRE(gtol_ >= 0.0, () => "negative g tolerance"); Utils.QL_REQUIRE(endCriteria.maxIterations() > 0, () => "null number of evaluations"); MINPACK.lmdif(m, n, xx, ref fvec, endCriteria.functionEpsilon(), xtol_, gtol_, endCriteria.maxIterations(), epsfcn_, diag, mode, factor, nprint, ref info, ref nfev, ref fjac, ldfjac, ref ipvt, ref qtf, wa1, wa2, wa3, wa4, fcn, j); info_ = info; // check requirements & endCriteria evaluation Utils.QL_REQUIRE(info != 0, () => "MINPACK: improper input parameters"); if (info != 6) { ecType = EndCriteria.Type.StationaryFunctionValue; } endCriteria.checkMaxIterations(nfev, ref ecType); Utils.QL_REQUIRE(info != 7, () => "MINPACK: xtol is too small. no further " + "improvement in the approximate " + "solution x is possible."); Utils.QL_REQUIRE(info != 8, () => "MINPACK: gtol is too small. fvec is " + "orthogonal to the columns of the " + "jacobian to machine precision."); // set problem x_ = new Vector(xx.GetRange(0, n)); P.setCurrentValue(x_); P.setFunctionValue(P.costFunction().value(x_)); return(ecType); }
// LineSearchBasedMethod interface protected override Vector getUpdatedDirection(Problem P, double gold2, Vector oldGradient) { if (inverseHessian_.rows() == 0) { // first time in this update, we create needed structures inverseHessian_ = new Matrix(P.currentValue().size(), P.currentValue().size(), 0.0); for (int i = 0; i < P.currentValue().size(); ++i) { inverseHessian_[i, i] = 1.0; } } Vector diffGradient = new Vector(); Vector diffGradientWithHessianApplied = new Vector(P.currentValue().size(), 0.0); diffGradient = lineSearch_.lastGradient() - oldGradient; for (int i = 0; i < P.currentValue().size(); ++i) { for (int j = 0; j < P.currentValue().size(); ++j) { diffGradientWithHessianApplied[i] += inverseHessian_[i, j] * diffGradient[j]; } } double fac, fae, fad; double sumdg, sumxi; fac = fae = sumdg = sumxi = 0.0; for (int i = 0; i < P.currentValue().size(); ++i) { fac += diffGradient[i] * lineSearch_.searchDirection[i]; fae += diffGradient[i] * diffGradientWithHessianApplied[i]; sumdg += Math.Pow(diffGradient[i], 2.0); sumxi += Math.Pow(lineSearch_.searchDirection[i], 2.0); } if (fac > Math.Sqrt(1e-8 * sumdg * sumxi)) // skip update if fac not sufficiently positive { fac = 1.0 / fac; fad = 1.0 / fae; for (int i = 0; i < P.currentValue().size(); ++i) { diffGradient[i] = fac * lineSearch_.searchDirection[i] - fad * diffGradientWithHessianApplied[i]; } for (int i = 0; i < P.currentValue().size(); ++i) { for (int j = 0; j < P.currentValue().size(); ++j) { inverseHessian_[i, j] += fac * lineSearch_.searchDirection[i] * lineSearch_.searchDirection[j]; inverseHessian_[i, j] -= fad * diffGradientWithHessianApplied[i] * diffGradientWithHessianApplied[j]; inverseHessian_[i, j] += fae * diffGradient[i] * diffGradient[j]; } } } Vector direction = new Vector(P.currentValue().size()); for (int i = 0; i < P.currentValue().size(); ++i) { direction[i] = 0.0; for (int j = 0; j < P.currentValue().size(); ++j) { direction[i] -= inverseHessian_[i, j] * lineSearch_.lastGradient()[j]; } } return(direction); }
public void compute() { if (vegaWeighted_) { double weightsSum = 0.0; for (int i = 0; i < times_.Count; i++) { double stdDev = Math.Sqrt(blackVols_[i] * blackVols_[i] * times_[i]); // when strike==forward, the blackFormulaStdDevDerivative becomes weights_[i] = new CumulativeNormalDistribution().derivative(.5 * stdDev); weightsSum += weights_[i]; } // weight normalization for (int i = 0; i < times_.Count; i++) { weights_[i] /= weightsSum; } } // there is nothing to optimize if (aIsFixed_ && bIsFixed_ && cIsFixed_ && dIsFixed_) { abcdEndCriteria_ = QLCore.EndCriteria.Type.None; return; } else { AbcdError costFunction = new AbcdError(this); transformation_ = new AbcdParametersTransformation(); Vector guess = new Vector(4); guess[0] = a_; guess[1] = b_; guess[2] = c_; guess[3] = d_; List <bool> parameterAreFixed = new InitializedList <bool>(4); parameterAreFixed[0] = aIsFixed_; parameterAreFixed[1] = bIsFixed_; parameterAreFixed[2] = cIsFixed_; parameterAreFixed[3] = dIsFixed_; Vector inversedTransformatedGuess = new Vector(transformation_.inverse(guess)); ProjectedCostFunction projectedAbcdCostFunction = new ProjectedCostFunction(costFunction, inversedTransformatedGuess, parameterAreFixed); Vector projectedGuess = new Vector(projectedAbcdCostFunction.project(inversedTransformatedGuess)); NoConstraint constraint = new NoConstraint(); Problem problem = new Problem(projectedAbcdCostFunction, constraint, projectedGuess); abcdEndCriteria_ = optMethod_.minimize(problem, endCriteria_); Vector projectedResult = new Vector(problem.currentValue()); Vector transfResult = new Vector(projectedAbcdCostFunction.include(projectedResult)); Vector result = transformation_.direct(transfResult); QLCore.AbcdMathFunction.validate(a_, b_, c_, d_); a_ = result[0]; b_ = result[1]; c_ = result[2]; d_ = result[3]; } }