function saida = stateFeedback_Pafim(A, B2, xi)
% function saida = stateFeedback_Pafim(A, B2, xi)
%
% Calcula um controlador robusto estabilizante por realimentaçao de estados  para um sistema linear 
% com incerteza politópica usando o seguinte problema de factibilidade:
%       [AiX+XAi'+B2iZ+Z'B2i'    Wi-X'+xiAiX + xiB2iZ] 
%       [Wi - X+xiX'Ai'+xiZ'B2i'       -xiX-xiX'     ] < 0,
%       
% As LMIs são programadas usando o YALMIP  e podem ser resolvidas
% por qualquer resolvedor de LMIs compatível com o YALMIP (SeDuM é o padrão).
%
% entradas : A  -> vértices da matriz dinâmica do sistema
%            B2 -> vértices da matriz da entrada de controle do sistema.
%            xi -> valor usado para realizar busca unidimensional.
%
% saídas : saida.factivel -> 1 se factivel, infinito caso contrário.
%          saida.cpusec   -> tempo de cpu para resolver as LMIs (segundos)
%          saida.cpusec_m -> tempo de cpu para programar as LMIs (segundos)
%          saida.V        -> número de variáveis escalares.
%          saida.L        -> number de linhas de LMIs.
%          saida.W        -> variável soluçao W (se existir).
%          saida.K        -> controlador robusto (se existir).
%
% Autor: ricfow@dt.fee.unicamp.br
% Data:  07/09/2010
%
% Exemplo:
% clear all;
% A{1}=[5.3 5.0; -5.3 -12.7];
% A{2}=[-13.0 20.9;-0.6 -14.2];
% B2{1}=[-0.2; -1.2];
% B2{2}=[0.0; 0.1];
% xi = 0.1;
% saida = stateFeedback_Pafim(A, B2,xi)

% Determina as dimensões do problema.
ordem    = size(A{1},1);
vertices = size(A,2);
entradas_c = size(B2{1},2);

% Tempo de programação das LMIs.
saida.cpusec_m = clock;

% Inicializa a variável que armazenará as LMIs do problema.
LMIs = set([]);

% Cria as variáveis do problema.
for i=1:vertices
    W{i} = sdpvar(ordem,ordem,'symmetric');
end
Z = sdpvar(entradas_c,ordem,'full');    
X = sdpvar(ordem,ordem,'full');

% Entra com as LMIs do problema.
for i=1:vertices
    
    L11 = A{i}*X+X'*A{i}'+B2{i}*Z+Z'*B2{i}';
    L12 = W{i}-X'+xi*(A{i}*X+B2{i}*Z);
    L22 = -xi*(X+X');

    LMIs = LMIs + set(W{i} > 0) + set([L11 L12;L12' L22] < 0);
end

% Finaliza o tempo de programação.
saida.cpusec_m = etime(clock,saida.cpusec_m);

% Determina o número de linhas de LMIs
saida.L = 0;
for i=1:size(LMIs,1)
    saida.L = saida.L + size(LMIs{i},1);
end

% Determina o número de variáveis escalares.
saida.V = size(getvariables(LMIs),2);

% Finalmente, o problema de otimização é resolvido.
solucao = solvesdp(LMIs,[],sdpsettings('solver','sedumi'));
saida.cpusec = solucao.solvertime;

% Acessa o menor resíduo primal.
p=min(checkset(LMIs));
saida.delta = p;

saida.factivel = inf;
% Capturando a solução (se existir).
if p > 0
    saida.factivel = 1;
    for i=1:vertices
        saida.W{i}     = double(W{i});
    end
    saida.K = double(Z)*inv(double(X));
end