Skip to main content

mathematical optimization - Is there any strategy to have a compiled version of FindFit or NonlinearModelFit?


Disclaimer: This is not a precise question with a definite answer.


I know that neither FindFit nor NonlinearModelFit is in the list returned by the command:


Compile`CompilerFunctions[] // Sort


But I am in the middle of refactoring a large Wolfram Language code base which uses FindFit in many places. I need to write compiled versions of each of these functions, so that I may generate C code out of it, which will be built into a DLL and included in our one-step build process for our overall web application.


Since FindFit and NonlinearModelFit do not compile, I would like to come up with a substitute strategy. Short of trying to reimplement these functions, is there any way to generate the replacement rules returned by FindFit, or the function generated by NonlinearModelFit so that the code using these functions can be compiled?



Answer



No, it is not possible.


With code converted to a LibraryLink library by way of Compile you are limited to using functions that either can be expressed directly in C, or exist in the runtime library; unfortunately, FindFit is not included in either category. When present in code passed to Compile, FindFit results in a call back to the top level, and it is handled by a C implementation in the Mathematica runtime (i.e., the kernel), where it calls the same code exposed by FindMinimum. NonlinearModelFit is actually implemented entirely as top-level code (which in turn calls FindFit for the actual fitting), and so its requirements are even further removed from what one can provide in LibraryLink libraries.


This situation exists for many Mathematica functions, and the requirement for the code to be interpretable by the compiler (with its strict limitations, many oddities, and occasional bugs) may make your task (with your current approach) more difficult to accomplish than simply rewriting from scratch in conventional C or C++. If this is not possible or desirable, for example due to the use of algorithms or features not available elsewhere, then you should probably consider having Mathematica available on the server, where you can call it via MathLink in a mixed C/Mathematica language implementation.


As far as your question is concerned, all that you really need to do a nonlinear fit is a reasonably robust minimization algorithm implemented in the compilable subset. Various options are available to you for this, including conjugate gradient methods (quasi-Newton methods unfortunately are not possible because Inverse is not compilable, being itself implemented as a call to the MKL), differential evolution, or the Nelder-Mead downhill simplex algorithm. My favorite of these is the latter, because it is reasonably economical with objective function evaluations while not requiring the function to be differentiable, and it also has a straightforward procedural implementation involving not much more than simple arithmetic. For these reasons I already implemented it in compiled code, and in fact specifically for a fitting application. The same code may help you, if FindFit is really the only thing you need to reproduce in C.


Comments

Popular posts from this blog

plotting - Filling between two spheres in SphericalPlot3D

Manipulate[ SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, Mesh -> None, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], {n, 0, 1}] I cant' seem to be able to make a filling between two spheres. I've already tried the obvious Filling -> {1 -> {2}} but Mathematica doesn't seem to like that option. Is there any easy way around this or ... Answer There is no built-in filling in SphericalPlot3D . One option is to use ParametricPlot3D to draw the surfaces between the two shells: Manipulate[ Show[SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], ParametricPlot3D[{ r {Sin[t] Cos[1.5 Pi], Sin[t] Sin[1.5 Pi], Cos[t]}, r {Sin[t] Cos[0 Pi], Sin[t] Sin[0 Pi], Cos[t]}}, {r, 1, 2 - n}, {t, 0, Pi}, PlotStyle -> Yellow, Mesh -> {2, 15}]], {n, 0, 1}]

plotting - Plot 4D data with color as 4th dimension

I have a list of 4D data (x position, y position, amplitude, wavelength). I want to plot x, y, and amplitude on a 3D plot and have the color of the points correspond to the wavelength. I have seen many examples using functions to define color but my wavelength cannot be expressed by an analytic function. Is there a simple way to do this? Answer Here a another possible way to visualize 4D data: data = Flatten[Table[{x, y, x^2 + y^2, Sin[x - y]}, {x, -Pi, Pi,Pi/10}, {y,-Pi,Pi, Pi/10}], 1]; You can use the function Point along with VertexColors . Now the points are places using the first three elements and the color is determined by the fourth. In this case I used Hue, but you can use whatever you prefer. Graphics3D[ Point[data[[All, 1 ;; 3]], VertexColors -> Hue /@ data[[All, 4]]], Axes -> True, BoxRatios -> {1, 1, 1/GoldenRatio}]

plotting - Adding a thick curve to a regionplot

Suppose we have the following simple RegionPlot: f[x_] := 1 - x^2 g[x_] := 1 - 0.5 x^2 RegionPlot[{y < f[x], f[x] < y < g[x], y > g[x]}, {x, 0, 2}, {y, 0, 2}] Now I'm trying to change the curve defined by $y=g[x]$ into a thick black curve, while leaving all other boundaries in the plot unchanged. I've tried adding the region $y=g[x]$ and playing with the plotstyle, which didn't work, and I've tried BoundaryStyle, which changed all the boundaries in the plot. Now I'm kinda out of ideas... Any help would be appreciated! Answer With f[x_] := 1 - x^2 g[x_] := 1 - 0.5 x^2 You can use Epilog to add the thick line: RegionPlot[{y < f[x], f[x] < y < g[x], y > g[x]}, {x, 0, 2}, {y, 0, 2}, PlotPoints -> 50, Epilog -> (Plot[g[x], {x, 0, 2}, PlotStyle -> {Black, Thick}][[1]]), PlotStyle -> {Directive[Yellow, Opacity[0.4]], Directive[Pink, Opacity[0.4]],