function [u, X, Y, v] = cpdistancia(F, signoX, signoXF)
%cpdistancia
%   u = cpdistancia(Fact)
%
%   Determina la distancia a un crecimiento proporcional con la matriz
%   numérica de fujos actualizados para un factor, transformando el
%   problema a la forma canónica y resolviendo el juego con la matriz de
%   pagos correspondiente.
%
%   [u, X, Y] = cpdistancia(Fact, signoX, signoXF)
%      Fact       matriz numérica con los flujos actualizados
%      signoX     signo de las intensidades; por defecto X >= 0
%      signoXF    signo de los balances materiales; por defecto X F(k) = 0
%      u          si u >= 0 existe un crecimiento proporcional, si u < 0 no
%      X          intensidades
%      Y          multiplicadores de Lagrange
%
%   Si escribimos
%      [u, X, Y] = cpdistancia(forma0(F,k), signoX, signoXF)
%   nos determinará si existe un crecimiento proporcional para unas recetas
%   en tiempo discreto o continuo con el factor k. También si escribimos 
%      [u, X, Y] = cpdistancia(P, 1, 1)
%   obtendremos el valor u y las estrategias X e Y del juego para la matriz
%   de pagos P.

%   necesita formaproblema.m, formasolucion.m

if nargin < 2, signoX = []; end
if nargin < 3, signoXF = []; end

if isempty(signoX), s3 = 0; else s3 = sum(signoX == 3); end      %determina si algún X tiene signo >=< 0
if s3 == 0                                                       %si ningún X >=< 0
    [Fcan, signoX, signoXF] = formaproblema(F, signoX, signoXF, 1);   %convierte el problema a la forma canónica
    [u, X, Y, v] = juego(Fcan);                                       %resuelve el juego
    [X, Y] = formasolucion(X, Y, signoX, signoXF, 1);                 %convierte la solucion desde la forma canonica
else                                                             %en caso contrario
    for c1 = 1:size(signoX,2), if signoX(c1) == 3, break; end, end    %determina el primer caso con X >=< 0
    signoX(c1) = 1;                                                   %establece que ese signoX(c1) sea 1
    [u1, X1, Y1, v1] = cpdistancia(F, signoX, signoXF);               %calcula la distancia u1 para signoX(c1) = 1
    signoX(c1) = 2;                                                   %establece que ese signoX(c1) sea 2
    [u2, X2, Y2, v2] = cpdistancia(F, signoX, signoXF);               %calcula la distancia u2 para signoX(c1) = 2
    if u1 >= u2                                                       %si u1 es mayor o igual a u2
        u = u1; X = X1; Y = Y1; v = v1;                                    %establece como solución la de signoX(c1) = 1
    else                                                              %en caso contrario
        u = u2; X = X2; Y = Y2; v = v2;                                    %establece como solución la de signoX(c1) = 2
    end
end





function [u, X, Y, v] = juego(F)
%juego
%   [u, X, Y, v] = juego(F)
%
%   Calcula el valor del juego u para la matriz de pagos F resolviendo el
%   programa lineal
%      max u                           min v
%      X F >= u                        Y >= 0
%      1 - sum(X) = 0                  v >=< 0
%      X >= 0                          F Y <= v
%      u >=< 0                         1 - sum(Y) = 0

%necesita programalineal.m

[filas, columnas] = size(F);                                                %determina el tamaño de F
Fn = [F, -ones(filas,1); -ones(1, columnas), 0];                            %establece la matriz del programa lineal [F,-1; -1, 0]
C = [zeros(filas,1); 1];                                                    %define la función objetivo [X, u] [0; 0; 0;...; 0; 1]
D = [zeros(1,columnas), 1];                                                 %[0, 0, 0, ..., 0, 1]
signoX = [ones(1, filas), 3];                                               %establece que X >= 0, u >=< 0
signoXF = [ones(1, columnas), 0];                                           %establece que X F - u >= 0, 1 - sum(X) = 0
[Xu, Yv] = programalineal(Fn, C, D, signoX, signoXF);                       %resuelve el programa lineal
u = Xu(filas+1); X = Xu(1:filas); Y = Yv(1:columnas); v = Yv(columnas+1);   %extrae u, X, Y, v de la solución


