static omxFitFunction *omxNewInternalFitFunction(omxState* os, const char *fitType, omxExpectation *expect, omxMatrix *matrix, bool rowLik) { omxFitFunction *obj = (omxFitFunction*) R_alloc(1, sizeof(omxFitFunction)); OMXZERO(obj, 1); for (size_t fx=0; fx < OMX_STATIC_ARRAY_SIZE(omxFitFunctionSymbolTable); fx++) { const omxFitFunctionTableEntry *entry = omxFitFunctionSymbolTable + fx; if(strcmp(fitType, entry->name) == 0) { obj->fitType = entry->name; obj->initFun = entry->initFun; // We need to set up the FreeVarGroup before calling initFun // because older fit functions expect to know the number of // free variables during initFun. obj->setVarGroup = entry->setVarGroup; // ugh! obj->addOutput = defaultAddOutput; break; } } if(obj->initFun == NULL) Rf_error("Fit function '%s' not implemented", fitType); if (!matrix) { obj->matrix = omxInitMatrix(1, 1, TRUE, os); obj->matrix->hasMatrixNumber = TRUE; obj->matrix->matrixNumber = ~os->algebraList.size(); os->algebraList.push_back(obj->matrix); } else { obj->matrix = matrix; } obj->matrix->fitFunction = obj; obj->expectation = expect; if (rowLik && expect && expect->data) { omxData *dat = expect->data; omxResizeMatrix(matrix, dat->rows, 1); } else { omxResizeMatrix(matrix, 1, 1); } return obj; }
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 omxZeroByZeroMatrix(omxMatrix *om) { if (om->rows > 0 || om->cols > 0) { omxResizeMatrix(om, 0, 0); } }