global mu_l mu_a c_ea c_el c_pa b mydatafit myDays myb

% Beetles, Cannibalism, and Chaos
% Solution to Problem 3
% Dianne O'Leary 12/2006
%

disp('Read beetledata')
beetledata;

% Part (a). 
% Perform the least squares fit to determine the size
% parameters for each of the four experimental colonies.
% 
% We use lsqnonlin, with lower (lb) and upper (ub) bounds on the
% parameters.  The parameters are ordered

%        c_el c_ea c_pa   b mu_L mu_A
param0 = [0.1; 0.1; 0.1;  6; 0.5; 0.1];
lb     = [0  ;   0;   0; .1;   0;   0];
ub     = [1  ;   1;   1;  9;   1;   1];

% Loop over the colonies.

for mycase=1:4,

% Set mydatafit to the number of larvae, pupae, and adults for this colony.

  mydatafit = [Data(:,1+mycase),Data(:,5+mycase),Data(:,9+mycase)];
  myDays = Data(:,1) + 1;

% Perform the least squares fit.

  [paramlog(:,mycase),rnormlog(mycase)] = lsqnonlin(@evalls2,param0,lb,ub);

% Part (b).
% Compare the predictions of this model to that of Dennis et al.
% using a plot.  A printed summary will be made later.

  [diffs,L,P,A]=evalls2(paramlog(:,mycase));
  [diffs,Ld,Pd,Ad]=evalls2(param_dl(:,mycase));
  figure(mycase)
  subplot(3,1,1)
  plot(1:20,mydatafit(:,1),'r-', 1:20,A, 'rs', 1:20,Ad,'r+')
  legend('Adults')
  title('Predictions by Dennis et al. (+) and our calculations (square)')
  subplot(3,1,2)
  plot(1:20,mydatafit(:,2),'b:', 1:20,P ,'bs', 1:20,Pd,'b+')
  legend('Pupae')
  subplot(3,1,3)
  plot(1:20,mydatafit(:,3),'g--', 1:20,L ,'gs', 1:20,Ld,'g+')
  legend('Larvae')

end

% Part (c).
% For the second colony, explore the sensitivity of the model for
% the second colony.

mycase = 2;
mydatafit = [Data(:,1+mycase),Data(:,5+mycase),Data(:,9+mycase)];

% First: A backward error analysis: how sensitive is the model to
% changes in the b parameter?
% Compute the residual after changing just the b parameter,
% leaving the other parameters fixed at their optimal values.

myparam = paramlog(:,mycase);
myparam(4) = 0;
e4 = [0;0;0;1;0;0];

figure(5)
pert = 4:.25:12;
for j=1:length(pert)
   r(j) = norm(evalls2(myparam+pert(j)*e4));
end
plot(pert,r)
xlabel('b')
ylabel('Residual norm')
axis([min(pert),max(pert) 7 8])
title('How sensitive is the residual to changes in b?')

% Second, a forward error analysis: how sensitive is b to
% small changes in the measured data?
% Repeat the fit, after adding 250 samples of normally
% distributed error to the log of the counts, mean 0, standard deviation 1.

for k=1:250,
   mydatafit = [Data(:,1+mycase),Data(:,5+mycase),Data(:,9+mycase)]; 
   mydatafit = exp(log(mydatafit) + randn(size(mydatafit)));
   [paramlogpert,rnorm(k)] = lsqnonlin(@evalls2,paramlog(:,2),lb,ub);
   b(k) = paramlogpert(4);
end

% Plot the results; we will print a summary sentence later.

figure(6)
plot(b,zeros(1,250),'*') 
xlabel('b estimates')
title('Results of random perturbations on data for the second colony')

% Finally, a homotopy to see how much the residual changes as
% we change b.
% We fix b and do a least squares fit to find optimal values for the
% other 5 parameters.  We plot the resulting residual norm as a function
% of b.  As a side effect, we actually find a better solution than
% we had before.

myb_all = 1:.5:50;
lbs = lb([1:3,5:6]);
ubs = ub([1:3,5:6]);
param = paramlog([1:3,5:6,2]);
mymin = 20;

for k=1:length(myb_all)
   myb = myb_all(k);
   mydatafit = [Data(:,1+mycase),Data(:,5+mycase),Data(:,9+mycase)];
   [param,rnorm(k)] = lsqnonlin(@evallsh,param,lbs,ubs);
   res(k) = norm(evallsh(param));
   if (res(k) < mymin)
      mymin = res(k);
      myminparam= param;
      myminb = myb;
    end
end

figure(7)
plot(myb_all,res,'bo',myb_all,ones(size(myb_all))*mymin*1.05,'r-') 
legend('Best','1.05*Optimal')
xlabel('b')
ylabel('Residual norm')
title('Comparison of optimal residual norm with best found for fixed b')


% Print some summary results 

disp(' ')
disp('Parameter estimates from least squares:')
disp(' ')
disp('colony        c_el     c_ea     c_pa        b     mu_L     mu_A  residual')
for mycase=1:4,
  mydatafit = [Data(:,1+mycase),Data(:,5+mycase),Data(:,9+mycase)];
  disp(sprintf('mine:   %d %f %f %f %f %f %f %f', ...
       mycase, paramlog(:,mycase)',norm(evalls2(paramlog(:,mycase)))))
  disp(sprintf('theirs: %d %f %f %f %f %f %f %f', ...
       mycase, param_dl(:,mycase)',norm(evalls2(param_dl(:,mycase)))))
end

disp(' ')
disp(' ')
disp('Residual norms:')
for mycase=1:4,
  mydatafit = [Data(:,1+mycase),Data(:,5+mycase),Data(:,9+mycase)];
  disp(sprintf('Dataset %d, norm of data vector %f, my residual %f, Dennis et al. residual %f', ...
       mycase, norm(log(mydatafit(2:end,:)),'fro'), ...
       norm(evalls2(paramlog(:,mycase))), ...
       norm(evalls2(param_dl(:,mycase)))   ))
end

disp(' ')
disp('Parameter estimates from homotopy for Colony 2:')
disp(' ')
mycase = 2;
best = [myminparam(1:3),myminb,myminparam(4:5)];
mydatafit = [Data(:,1+mycase),Data(:,5+mycase),Data(:,9+mycase)];
disp(sprintf('mine:   %d %f %f %f %f %f %f %f', ...
     mycase, best,norm(evalls2(paramlog(:,mycase)))))
disp(sprintf('theirs: %d %f %f %f %f %f %f %f', ...
     mycase, param_dl(:,mycase)',norm(evalls2(param_dl(:,mycase)))))

[diffs,L,P,A]=evalls2(best);
  [diffs,Ld,Pd,Ad]=evalls2(param_dl(:,mycase));
  figure(8)
  subplot(3,1,1)
  plot(1:20,mydatafit(:,1),'r-', 1:20,A, 'rs', 1:20,Ad,'r+')
  legend('Adults')
  title('Predictions by Dennis et al. (+) and our calculations (square)')
  subplot(3,1,2)
  plot(1:20,mydatafit(:,2),'b:', 1:20,P ,'bs', 1:20,Pd,'b+')
  legend('Pupae')
  subplot(3,1,3)
  plot(1:20,mydatafit(:,3),'g--', 1:20,L ,'gs', 1:20,Ld,'g+')
  legend('Larvae')



% Print a summary of the results of random perturbations in the data.

disp(' ')
disp(sprintf('When the data is randomly perturbed, the estimate of b'))
disp(sprintf('for the second colony ranges from %f to %f.', min(b),max(b)))

