Thursday 27 August 2015

Wrapping up

So, the GSoC period has come to an end now.

Project Goals  
My project was about creating Matlab compatible wrappers for the optim package.  Here is a brief list of my project goals.

1- lsqnonlin wrapping nonlin_residmin and residmin_stat
2- lsqcurvefit wrapping nonlin_curvefit and curvefit_stat
3- nlinfit wrapping nonlin_curvefit (it was initially decided to wrap leasqr but changed to avoid extra computations)
4- quadprog wrapping __qp__ instead of qp and returning lambda in the form of a structure as in Matlab
5- fmincon wrapping nonlin_min
6- Test and demos for the above functions
7- Stretch goals: previously decided to create other missing functions or perhaps additional backends but before midterm I decided instead to include optimoptions in my to do list.


Achievements
The functions lsqnonlinlsqcurvefit and nlinfit are complete with tests and demos and integrated in the optim package. Since nlinfit is from the statistics package in Matlab, additional functions such as statset, statget were required for handling options. These functions are implemented with minor modifications in optimset, optimget and __all_opts__ as statset, statget and __all_stat_opts__ and are now a part of optim package.

The function quadprog required directly wrapping __qp__ instead of qp for the ordering of lambda. It is in the final stages of review and will soon be integrated.

fmincon has not been thoroughly reviewed yet. I will send it to Olaf after quadprog is committed to optim. 

Hiccups in the stretch goal
I couldn't create optimoptions in the GSoC time frame because it was a bit open ended and I had to come up with an object oriented design for the function. I was trying to understand how Matlab implements it for quite some time. Anyway, I didn't pursue it further and shifted my focus on the refinement of my almost complete functions to get them integrated in optim.  

Interesting Takeaways
This is my first experience of working with any open source organization and it's definitely a pleasant one. It's delightful to see people using my functions and possibly benefiting from my work [2-3]. :)

I think I have managed to meet all the goals I set before the start of GSoC. (Regrets? Well, I could have saved more time for optimoptions and it would've been better to discuss it way before than being stuck for a while.)

I'm extremely grateful to the Octave community, especially my mentors Olaf Till and Nir Krakauer for their unrelenting support. GSoC wouldn't have been possible without their constructive feedback. I have learned a lot from this experience.


[1] https://github.com/AsmaAfzal/octave_workspace/issues/1
[2] http://octave.1599824.n4.nabble.com/GSoC-2015-Optimization-Package-Non-linear-and-constrained-least-squares-lsqcurvefit-lsqlin-lsqnonlin-tp4668777p4670940.html

6 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. Hi Asma Afzal,

    First of all, thanks for your work.
    I am using your functions to perform some fittings on experimental data and it it works very well.
    Nevertheless, I cannot get the code to show the iterations on the command window. I have read in the notes, that it is capable of showing the iterations (Display = 'Iter'), but it does not work.
    I have tried with the example code modifying the line:
    opts = optimset ('Jacobian', 'on', 'Display','iter');
    I have tested it on Matlab and it works there, but I would like to keep using Octave for my projects.

    Regards,
    Francisco

    ReplyDelete
  3. Sorry for late reply. It gives me great pleasure that you have found the functions useful. Could you please specify the function which is not displaying the iterations so I can have a look at the code.

    Best,
    Asma

    ReplyDelete
  4. Hi, I tested the code with the example function that is in the lsqnonlin function. I just changed the option for displaying. It works properly in Matlab, showing the iterations, but it does not show them in Octave. I checked and lsqnonlin sends the options to nonlin_residmin function, and this function calls __nonlin_residmin__ function with the proper arguments.
    I would really appreciate if you could take a look into it.

    Thanks in advance,
    Francisco

    %% model function:
    function [F,J] = myfun (p, x, y)
    F = p(1) * exp (-p(2) * x) - y;
    if nargout > 1
    J = [exp(- p(2) * x), - p(1) * x .* exp(- p(2) * x)];
    end
    end

    %% Example for user specified Jacobian.
    %% independents
    x = [1:10:100]';
    %% observed data
    y =[9.2160e-001, 3.3170e-001, 8.9789e-002, 2.8480e-002, 2.6055e-002,...
    8.3641e-003, 4.2362e-003, 3.1693e-003, 1.4739e-004, 2.9406e-004]';
    %% initial values:
    p0=[0.8; 0.05];
    %% bounds
    lb=[0; 0]; ub=[];
    %% Jacobian setting
    opts = optimset ('Jacobian', 'on', 'Display','iter');

    c = ...
    lsqnonlin(@(p) myfun(p, x, y), p0, lb, ub, opts)

    ReplyDelete
  5. You are right. lsqnonlin in Octave does not display the number of iterations with this setting. I should add this.
    With the current backend (lm_svd_feasible), you can only obtain the number of iterations.
    Use the following modification for now
    [c,~,~,~,output] = lsqnonlin(@(p) myfun(p, x, y), p0, lb, ub, opts)
    The scalar structure output contains the field niter.
    Hope this helps.

    ReplyDelete
  6. Hi Asma,
    What's the status with the fmincon function? I notice that you were working on it in 2015, but has anyone tried to get it integrated into the forge optim package since then?

    ReplyDelete