function [X, Y, exit] = programalineal(F, C, D, signoX, signoXF)
%programalineal
%   [X, Y] = programalineal(F, C, D)
%
%   Lanza las funciones correspondientes en cada software para obtener la
%   solución del programa lineal
%      Max X C                Min D Y
%      D + X F ~ 0     <->    -Y ~ 0             (D + X F) .* Y' = 0
%      X ~ 0           <->    C + F Y ~ 0        X' .* (C + F Y) = 0
%
%   [X, Y, exit] = programalineal(F, C, D, signoX, signoXF)
%      F          matriz m*n
%      C          vector columna m*1
%      D          vector fila 1*n
%      signoX     signo de las variables; por defecto X >= 0
%      signoXF    signo de las restricciones; por defecto D + X F = 0
%      X          vector fila 1*m de variables
%      Y          vector columnas n*1 de multiplicadores de Lagrange
%      exit       si es 1 la solución cumple las condiciones del programa
%
%   Los códigos para los signos son   0 =    1 >=    2 <=    3 >=<

%necesita programalinealaux.m

if nargin < 1, F = []; end
if nargin < 2, C = []; end
if nargin < 3, D = []; end
if nargin < 4, signoX = []; end
if nargin < 5, signoXF = []; end

[filas, columnas] = size(F);
if isempty(C), C = zeros(filas, 1); end
if isempty(D), D = zeros(1, columnas); end
if isempty(signoX), signoX = 1; end
if isempty(signoXF), signoXF = 0; end
if size(signoX, 2) == 1, signoX = signoX .* ones(1, filas); end
if size(signoXF, 2) == 1, signoXF = signoXF .* ones(1, columnas); end

homogeneo = (sum(abs(C))+sum(abs(D))) == 0;                          %establece si el programa es homogéneo
if exist('OCTAVE_VERSION')                                           %si se usa Octave
    if homogeneo                                                         %si el programa es homogéneo
        [X, Y, exit] = programalinealhomogeneo(F, signoX, signoXF);          %
    else                                                                 %si no es homogéneo
        [X, Y, exit] = programalinealaux(F, C, D, signoX, signoXF, 1);       %
    end                                                                  %
else                                                                 %si se usa Matlab
    v = version;                                                         %determina la versión del software que se usa
    if v([1,2]) == '5.'                                                  %si la versión es la 5
        if homogeneo                                                         %si el programa es homogéneo   
            [X, Y, exit] = programalinealhomogeneo(F, signoX, signoXF);          %
        else                                                                 %si no es homogéneo
            [X, Y, exit] = programalinealmatlab5(F, C, D, signoX, signoXF);      %
        end                                                                  %
    else                                                                 %si es otra versión
        [X, Y, exit] = programalinealaux(F, C, D, signoX, signoXF, 2);       %
    end                                                                  %
end                                                                  %

 


function [X, Y, exit] = programalinealhomogeneo(F, signoX, signoXF)
cero = 1e-14;
[u, X, Y] = cpdistancia(F, signoX, signoXF);
if u > cero, Y = Y .* 0; elseif u < -cero, X = X .* 0; end
exit = 1;




function [X, Y, exit] = programalinealmatlab5(F, C, D, signoX, signoXF)
[filas, columnas] = size(F);
filasn = filas - sum(signoX == 0);
LB = zeros(1, filasn); UB = zeros(1, filasn); Fn = zeros(filasn, columnas); Cn = zeros(filasn, 1);
c2 = 1;
for c1 = 1:filas
    switch signoX(c1)
        case 0,
        case 1, LB(c2) = 0   ; UB(c2) = Inf; Fn(c2,:) = F(c1,:); Cn(c2) = C(c1); c2 = c2 + 1;
        case 2, LB(c2) = -Inf; UB(c2) = 0  ; Fn(c2,:) = F(c1,:); Cn(c2) = C(c1); c2 = c2 + 1;
        case 3, LB(c2) = -Inf; UB(c2) = Inf; Fn(c2,:) = F(c1,:); Cn(c2) = C(c1); c2 = c2 + 1;
    end
end
numeq = sum(signoXF == 0);
numin = columnas + numeq;
Ain = zeros(filasn, numin); Din = zeros(1, numin);
cin = 1;
for c1 = 1:columnas
    switch signoXF(c1)
        case 0, Ain(:, cin) = Fn(:,c1); Din(cin) = D(c1); Ain(:, cin+1) = -Fn(:,c1); Din(cin+1) = -D(c1); cin = cin + 2;
        case 1, Ain(:, cin) = Fn(:,c1); Din(cin) = D(c1); cin = cin + 1;
        case 2, Ain(:, cin) = -Fn(:,c1); Din(cin) = -D(c1); cin = cin + 1;
        case 3
    end
end
[Xn, Yn, HOW] = lp(-Cn', -Ain', Din', LB, UB, [], 0, -1);
X = zeros(1, filas);
c0 = 1;
for c1 = 1:filas
    switch signoX(c1)
        case 0,
        case 1, X(c1) = Xn(c0); c0 = c0 + 1;
        case 2, X(c1) = Xn(c0); c0 = c0 + 1;
        case 3, X(c1) = Xn(c0); c0 = c0 + 1;
    end
end
Y = zeros(columnas, 1);
ci0 = 1;
for c1 = 1:columnas
    switch signoXF(c1)
        case 0, Y(c1) = Yn(ci0) - Yn(ci0+1); ci0 = ci0 + 2;
        case 1, Y(c1) = Yn(ci0) ; ci0 = ci0 + 1;
        case 2, Y(c1) = -Yn(ci0) ; ci0 = ci0 + 1;
        case 3
    end
end
switch HOW
    case 'ok', exit = 1;
    case 'infeasible', exit = -2;
    case 'unbounded', exit = -3;
    case 'unrealiable', exit = -4;
    case 'illposed', exit = -7;
    otherwise, exit = 0;
end
