function output = callsedumi(model)

% Author Johan Löfberg 
% $Id: callsedumi.m,v 1.30 2008-06-09 06:29:48 joloef Exp $

% Retrieve needed data
options = model.options;
F_struc = model.F_struc;
c       = model.c;
K       = model.K;
ub      = model.ub;
lb      = model.lb;

% Create the parameter structure
pars = options.sedumi;
pars.fid = double(options.verbose);

% *********************************************
% Bounded variables converted to constraints
% N.B. Only happens when caller is BNB
% *********************************************
if ~isempty(ub)
    [F_struc,K] = addbounds(F_struc,K,ub,lb);
end

% Avoid bug (by design?) in SeDuMi on 1D second order cones
if any(K.q == 2)
    [F_struc,K] = fix1Dqcone(F_struc,K);
end

if options.savedebug
    save sedumidebug F_struc c K pars
end

% *********************************************
% Call SeDuMi
% *********************************************
if options.showprogress;showprogress(['Calling ' model.solver.tag],options.showprogress);end

solvertime = clock; 
problem = 0;  
try
    [x_s,y_s,info] = sedumi(-F_struc(:,2:end),-c,F_struc(:,1),K,pars);
catch
    try
        if options.verbose > 0
            disp(' ');
            disp('SeDuMi had unexplained problems, maybe due to linear dependence?')
            disp('YALMIP tweaks the problem (adds 1e6 magnitude bounds on all variables) and restarts...')            
            disp(' ');
        end
        % Boring issue in sedumi for trivial problem min x+y, s.t x+y>0
        n = length(c);
        [F_struc,K] = addbounds(F_struc,K,ones(n,1)*1e6,-ones(n,1)*1e6);
        [x_s,y_s,info] = sedumi(-F_struc(:,2:end),-c,F_struc(:,1),K,pars);
        x_s((1:2*n)+K.f)=[];
        K.l=K.l-2*n;
    catch
        disp('Nope, unexplained crash in SeDuMi! (could be memory issues or wrong binary)')
        disp('Make sure you have a recent and compiled version')
        disp('For better diagnostics, use sdpsettings(''debug'',1)')        
    end
end
% solvertime = cputime - solvertime;%etime(clock,solvertime
if model.getsolvertime solvertime = etime(clock,solvertime);else solvertime = 0;end


% Internal format
Primal = y_s; 
Dual   = x_s;

temp = info.pinf;
pinf = info.dinf;
dinf = temp;

% Check for reported errors
if (pinf==0) &  (dinf==0)
    problem = 0; % No problems
end

% We can only report one error, use priorities
if (problem==0) & (pinf==1)
    problem = 1; % Primal infeasability
end

if (problem==0) & (dinf==1)
    problem = 2; % Dual infeasability
end

if (problem==0) & (info.numerr==1) | (info.numerr==2)
    problem = 4; %Numerical problems
end

if (problem==0) & (info.iter >= options.sedumi.maxiter)
    % Did we need exactly maxiter iterations to find optimum
    if (pinf==0) & (dinf==0) & (info.numerr==0)
        problem = 0; % Yes
    else
        problem = 3; % No, we are not optimal yet
    end
end

if (problem==0) & (info.feasratio<0.98) 
    problem = 4; 
end

% Fix for cases not really explained in documentation of sedumi?
if (abs(info.feasratio+1)<0.1) & (pinf==0) &  (dinf==0)
    problem = 1; 
end
if (abs(info.feasratio+1)<0.1) & (pinf==0) &  (dinf==0) & (c'*y_s<-1e10)
    problem = 2; 
end


infostr = yalmiperror(problem,model.solver.tag);

% Save ALL data sent to solver
if options.savesolverinput
    solverinput.A = -F_struc(:,2:end);
    solverinput.c = F_struc(:,1);
    solverinput.b = -c;
    solverinput.K = K;
    solverinput.pars = pars;
else
    solverinput = [];
end

% Save ALL data from the solution?
if options.savesolveroutput
    solveroutput.x = x_s;
    solveroutput.y = y_s;
    solveroutput.info = info;
else
    solveroutput = [];
end

% Standard interface 
output.Primal      = Primal;
output.Dual        = Dual;
output.Slack       = [];
output.problem     = problem;
output.infostr     = infostr;
output.solverinput = solverinput;
output.solveroutput= solveroutput;
output.solvertime  = solvertime;
 
function [new_F_struc,K] = fix1Dqcone(F_struc,K); 

new_F_struc = F_struc(1:(K.l+K.f),:);
top = K.f + K.l + 1;
for i = 1:length(K.q)
    if K.q(i) == 2
      new_F_struc = [new_F_struc;F_struc(top,:);F_struc(top+1,:);F_struc(top,:)*0];
      K.q(i) = 3;
      top = top + 2;
    else
      new_F_struc = [new_F_struc;F_struc(top:top+K.q(i)-1,:)];
      top = top + K.q(i);
    end
end
new_F_struc = [new_F_struc;F_struc(top:end,:)];