%
% This is a handy function to pass things along to Cplex
% The form is that of linprog:
%          min c'x : Ax <= b, Aeq x = beq, lb <= x <= ub
%
% VarType and SolverType are Cplex directives
%          VarType is a vector, with 'C' -> continuous var
%                                    'B' -> binary var
%
%          SolverType is 'mip' -> mixed integer program
%                        'barrier' -> interior point
%                        'psimplex' -> primal simplex
%                        'dsimplex' -> dual simplex
%                        others described in cplex.m
%

function [Soln] = CplexLink(c, A, b, Aeq, beq, lb, ub, VarType, SolverType);


%
% Grab some sizes
%
[m,n] = size(A);
[mEq,nEq] = size(Aeq);

%
% Check to make sure the dimensions of the problem agree
%
DimAgree = 0;
if (~isempty(A)) & (~isempty(Aeq))
   if (n == nEq) & (n == length(c))
      DimAgree = 1;
   end
end
if (~isempty(A)) & (m == length(b))
      DimAgree = 1;
end
if (~isempty(Aeq)) & (mEq == length(beq))
   DimAgree = 1;
end

%
% Build problem and send it to solver
%
if DimAgree
   % Make sure that linebreaks are not sent to cplex
   format compact;
  
   % Free past problems and create a new problem 
   Soln = cplex('free all problems');
   Soln = cplex('create problem', 'LP');
  
   % Set the optional parameters of lower and upper bounds
   % and variable type. 
   if (~isempty(lb))
      optdat_LP.lb = lb;
   end
   if (~isempty(ub))
   	optdat_LP.ub = ub;
   end
   if (~isempty(VarType))
      optdat_LP.mip.ctype = VarType;
   end
 
   % Create the variables and read the objective coefficients
   if (~isempty(c)) 
      Soln = cplex('new variables', 'LP', c, optdat_LP);
   else
      LogMesg('RAD -> c is empty in CplexLink');
   end

   % Read the inequalities.
   if (~isempty(A))
      % set the type to be less than or equal to
      optdat_LP.sense = char(ones(m,1)*'L');
      % read the constraints
      Soln = cplex('add constraints', 'LP', A, b, optdat_LP);
   else
      LogMesg('RAD -> There are no inequalities.');
   end

   % Read the equalities
   if (~isempty(Aeq))
      % set the type to be equal
      optdat_LP.sense = char(ones(mEq,1)*'E');
      % read the constraints
      Soln = cplex('add constraints', 'LP', Aeq, beq, optdat_LP);
   else
      %LogMesg('RAD -> There are no equalities.');
   end

   % Send the problem to the solver
   if strcmp(SolverType,'barrier')
      Soln = cplex('baropt stop', 'LP');
   elseif strcmp(SolverType,'psimplex')
      Soln = cplex('primopt', 'LP');
   elseif strcmp(SolverType,'mip')
      Soln = cplex('mipopt', 'LP');
   elseif strcmp(SolverType,'dsimplex')
      Soln = cplex('dual simplex', 'LP');
   else
      LogMesg('RAD -> Unknown SolverType:');
      LogMesg('  must be one of barrier, psimplex, dsimplex or mip.');
   end
   
   % Retrieve the Sol'n
   Soln = cplex('get solution', 'LP');
   
   % Revert to standard format
   format loose;

   return;
else
   LogMesg('RAD -> Demensions in CplexLink do not agree');
   return;
end
