% APM Report Problem Details
%
% y = apm_details(server,app,x,lam)
%
% This function reports the details of a problem
% located on the APM server with the following arguments:
%
% server = address of server
% app = application name
% x = values of all variables
% lam = Lagrange multipliers
% y = structure with problem information
%
% Reports model details such as values, multipliers, residuals,
% first derivatives, and second derivatives
%
% y.nvar = number of variables
% y.var.lb = variable lower bounds
% y.var.val = variable values
% y.var.ub = variable upper bounds
% y.obj = objective value
% y.obj_grad = objective gradient
% y.neqn = number of equations
% y.eqn.lb = equation lower bounds
% y.eqn.res = equation residuals
% y.eqn.ub = equation upper bounds
% y.jac = jacobian (1st derivatives)
% y.lam = lagrange multipliers
% y.hes_obj = second derivative of the objective
% y.hes_eqn{i} = second derivatives of equation {i}
% y.hes = full Hessian
%
function y = apm_details(server,app,x,lam)
persistent sol_prev sol_count
% initialize sol_count
if (isempty(sol_count)),
sol_count = 0;
end
% tolerance for checking if the values are the same
% as the previous call
tol = 1e-10;
% optionally load solution vector of variables
if (nargin>=3),
% create 'warm' as a column vector
if (size(x,1)==1),
warm = x';
else
warm = x;
end
% see if the values are the same as a previous call
warm_sum = sum(warm);
for i = 1:sol_count,
% check summation of warm first
if (abs(sol_prev(i).y.sumx-warm_sum) <= tol),
% check individual elements next
if (abs(sol_prev(i).y.var.val-warm) <= tol),
% return previous solution if values haven't changed
y = sol_prev(i).y;
return
end
end
end
% load warm.t0 to the server
fid = fopen('warm.t0','w');
fprintf(fid,'%20.12e\n',warm);
fclose(fid);
t0_load(server,app,'warm.t0');
delete('warm.t0');
end
% optionally load lagrange multipliers to server
if (nargin>=4),
% create 'lam' as a column vector
if (size(lam,1)==1),
lam = lam';
end
fid = fopen('lam.t0','w');
fprintf(fid,'%20.12e\n',lam);
fclose(fid);
t0_load(server,app,'lam.t0');
delete('lam.t0');
end
% compute details on server
output = apm(server,app,'solve');
% retrieve variables and bounds
apm_get(server,app,'apm_var.txt');
load apm_var.txt
delete('apm_var.txt');
y.nvar = size(apm_var,1); % get number of variables
y.var.lb = apm_var(:,1);
y.var.val = apm_var(:,2);
y.var.ub = apm_var(:,3);
% retrieve objective function value
apm_get(server,app,'apm_obj.txt');
load apm_obj.txt
delete('apm_obj.txt');
y.obj = apm_obj;
% retrieve objective gradient
apm_get(server,app,'apm_obj_grad.txt');
load apm_obj_grad.txt
delete('apm_obj_grad.txt');
y.obj_grad = apm_obj_grad;
% retrieve equation residuals and bounds
apm_get(server,app,'apm_eqn.txt');
load apm_eqn.txt
delete('apm_eqn.txt');
y.neqn = size(apm_eqn,1); % get number of equations
y.eqn.lb = apm_eqn(:,1);
y.eqn.res = apm_eqn(:,2);
y.eqn.ub = apm_eqn(:,3);
% retrieve jacobian
apm_get(server,app,'apm_jac.txt');
load apm_jac.txt
delete('apm_jac.txt');
jac = apm_jac;
y.jac = sparse(jac(:,1),jac(:,2),jac(:,3),y.neqn,y.nvar);
% retrieve lagrange multipliers
apm_get(server,app,'apm_lam.txt');
load apm_lam.txt
delete('apm_lam.txt');
y.lam = apm_lam;
% retrieve hessian of the objective only
apm_get(server,app,'apm_hes_obj.txt');
load apm_hes_obj.txt
delete('apm_hes_obj.txt');
hs = apm_hes_obj;
y.hes_obj = sparse(hs(:,1),hs(:,2),hs(:,3),y.nvar,y.nvar);
% retrieve hessian of the equations only
apm_get(server,app,'apm_hes_eqn.txt');
load apm_hes_eqn.txt
delete('apm_hes_eqn.txt');
hs = apm_hes_eqn;
nhs = size(apm_hes_eqn,1);
i1(1:y.neqn)=0;
i2(1:y.neqn)=0;
% equations listed in sequential order
for i = 1:nhs,
if(i1(hs(i,1))==0),
i1(hs(i,1)) = i;
end
i2(hs(i,1)) = i;
end
for i = 1:y.neqn,
if (i1(i)==0),
y.hes_eqn{i} = sparse(y.nvar,y.nvar);
else
y.hes_eqn{i} = sparse(hs(i1(i):i2(i),2),hs(i1(i):i2(i),3),hs(i1(i):i2(i),4),y.nvar,y.nvar);
end
end
% construct hessian from obj, lam, and eqn portions
y.hes = y.hes_obj;
for i = 1:y.neqn,
y.hes = y.hes + y.lam(i) * y.hes_eqn{i};
end
% store values
sol_count = sol_count + 1;
sol_prev(sol_count).y = y;
sol_prev(sol_count).y.sumx = sum(y.var.val);