void loglikelihoodCIFun(omxFitFunction *ff, int want, FitContext *fc) { const omxConfidenceInterval *CI = fc->CI; if (want & FF_COMPUTE_PREOPTIMIZE) { fc->targetFit = (fc->lowerBound? CI->lbound : CI->ubound) + fc->fit; //mxLog("Set target fit to %f (MLE %f)", fc->targetFit, fc->fit); return; } if (!(want & FF_COMPUTE_FIT)) { Rf_error("Not implemented yet"); } omxMatrix *fitMat = ff->matrix; // We need to compute the fit here because that's the only way to // check our soft feasibility constraints. If parameters don't // change between here and the constraint evaluation then we // should avoid recomputing the fit again in the constraint. TODO omxFitFunctionCompute(fitMat->fitFunction, FF_COMPUTE_FIT, fc); const double fit = totalLogLikelihood(fitMat); omxRecompute(CI->matrix, fc); double CIElement = omxMatrixElement(CI->matrix, CI->row, CI->col); omxResizeMatrix(fitMat, 1, 1); if (!std::isfinite(fit) || !std::isfinite(CIElement)) { fc->recordIterationError("Confidence interval is in a range that is currently incalculable. Add constraints to keep the value in the region where it can be calculated."); fitMat->data[0] = nan("infeasible"); return; } if (want & FF_COMPUTE_FIT) { double param = (fc->lowerBound? CIElement : -CIElement); if (fc->compositeCIFunction) { double diff = fc->targetFit - fit; diff *= diff; if (diff > 1e2) { // Ensure there aren't any creative solutions diff = nan("infeasible"); return; } fitMat->data[0] = diff + param; } else { fitMat->data[0] = param; } //mxLog("param at %f", fitMat->data[0]); } if (want & (FF_COMPUTE_GRADIENT | FF_COMPUTE_HESSIAN | FF_COMPUTE_IHESSIAN)) { // add deriv adjustments here TODO } }
void ComputeFit(const char *callerName, omxMatrix *fitMat, int want, FitContext *fc) { bool doFit = want & FF_COMPUTE_FIT; fc->incrComputeCount(); omxFitFunction *ff = fitMat->fitFunction; if (ff) { omxFitFunctionComputeAuto(ff, want, fc); } else { if (want != FF_COMPUTE_FIT) Rf_error("Only fit is available"); if (fc->ciobj) Rf_error("CIs cannot be computed for unitless algebra"); omxRecompute(fitMat, fc); } if (doFit) { fc->fit = totalLogLikelihood(fitMat); if (std::isfinite(fc->fit)) { fc->resetIterationError(); } Global->checkpointPostfit(callerName, fc, fc->est, false); if (OMX_DEBUG) { mxLog("%s: completed evaluation, fit=%.12g", fitMat->name(), fc->fit); } } }
void ComputeFit(const char *callerName, omxMatrix *fitMat, int want, FitContext *fc) { bool doFit = want & FF_COMPUTE_FIT; R_CheckUserInterrupt(); #pragma omp atomic ++Global->computeCount; // could avoid lock by keeping in FitContext // old version of openmp can't do this as part of the atomic instruction int evaluation = Global->computeCount; if (doFit) { if (OMX_DEBUG) { mxLog("%s: starting evaluation %d, want %d", fitMat->name(), evaluation, want); } Global->checkpointPrefit(callerName, fc, fc->est, false); } omxFitFunction *ff = fitMat->fitFunction; if (ff) { omxFitFunctionComputeAuto(ff, want, fc); } else { if (want != FF_COMPUTE_FIT) Rf_error("Only fit is available"); if (fc->CI) Rf_error("CIs cannot be computed for unitless algebra"); omxRecompute(fitMat, fc); } if (doFit) { fc->fit = totalLogLikelihood(fitMat); if (std::isfinite(fc->fit)) { fc->resetIterationError(); } Global->checkpointPostfit(fc); if (OMX_DEBUG) { mxLog("%s: completed evaluation %d, fit=%f", fitMat->name(), evaluation, fc->fit); } } }