An implementation of the Levenberg-Marquardt algorithm using the cblas library included in the Accelerate framework (Mac OS X).
- boltzmann - Boltzmann sigmoid
- expdecay - Exponential decay
- gaussian - Gaussian function
- hill - Hill equation
- ic50 - Dose response
- mm - Michaelis-Menten
- modsin - Sine wave
This program can be extended to accommodate more functions than those currently included. Say you want to add the following function:
Where
The goal of the program is to find values for x that minimize the sum of the square residuals between the data and the model.
- Provide a name for the model, say
expfunc
, and add the model name to theenum Model
inCblasLMSolver.h
enum Model {
boltzmann,
expdecay,
expfunc, // newly added
gaussian,
hill,
ic50,
mm,
modsin
};
- Edit the
switch
statement in theinitWithFileAtPath
function inCblasLMSolver.m
(there are 4 variable to solve in this model).
switch (model) {
case boltzmann:
case expfunc: // newly added
case gaussian:
varlen = 4;
break;
case expdecay:
case hill:
case ic50:
case modsin:
varlen = 3;
break;
case mm:
varlen = 2;
break;
default:
NSLog(@"varlen fail.");
exit(1);
break;
}
- Next, edit the
switch
statement in theequation
method in this file:
...
case expfunc:
m[i] = var[2] * exp(var[0] * xi) + var[3] * exp(var[2] * t);
break
...
Note that the x vector of the equation above is represented as the array var
, and the independent variable t is represented by xi
.
- Compute the partial derivatives of M with respect to each variable in
var
.
- Edit the
switch
statement inderivatives
method inCblasLMSolver.m
:
...
case expfunc:
d1[i] = var[2] * xi * exp(var[0] * xi);
d2[i] = var[3] * xi * exp(var[1] * xi);
d3[i] = exp(var[0] * xi);
d4[i] = exp(var[1] * xi);
break;
...
- Edit the
switch
statement inget_jac
method inCblasLMSolver.m
:
...
case boltzmann:
case expfunc: // newly added
case gaussian:
jac[i] = -d1[i];
jac[j] = -d2[i];
jac[k] = -d3[i];
jac[l] = -d4[i];
break;
...
- Edit
main
function inmain.m
to include the new function:
if ([modelName isEqualToString:@"boltzmann"]) {
myModel = boltzmann;
} else if ([modelName isEqualToString:@"expdecay"]) {
myModel = expdecay;
} else if ([modelName isEqualToString:@"expfunc"]) { // newly added
myModel = expfunc; // newly added
} else if ([modelName isEqualToString:@"gaussian"]) {
myModel = gaussian;
} else if ([modelName isEqualToString:@"hill"]) {
myModel = hill;
} else if ([modelName isEqualToString:@"ic50"]) {
myModel = ic50;
} else if ([modelName isEqualToString:@"mm"]) {
myModel = mm;
} else if ([modelName isEqualToString:@"modsin"]) {
myModel = modsin;
} else {
usage(argv);
}
-
Edit
usage
function inmain.m
. -
NOTE: if your function has more than four variables to solve for, you will need to do more work, such as allocating additional arrays, then freeing them later.