function [xout,it]=mad(W,xin,it_max)

%
% Rede Neural Dinâmica Progressiva com atualizacoes assincronas
% (Arquitetura para as M. A's de Hopfield, Personnaz e Kanter-Sompolinsky).
%
% Comando: [xout,it]=mad(W,xin,it_max)
% 
% Entradas:
%        W  - Matriz dos pesos sinápticos,
%       xin - Padrão de entrada,
%    it_max - número máximo de iteração (padrão: it_max=N, núm. de neurônios),
%   
% Saídas:
%      xout - Padrão recordado pela memória associativa,
%        it - Número de iterações efetuadas,
%

% Número de neurônios da rede,
N=size(xin,1);

% Define o número máximo de iterações,
if nargin<3
    it_max=N;
end

% it, conta o numero de iterações,
it=0;
% Usado como critério de parada:
Erro=1;
% Calcular até convergir ou até o número máximo de iterações,
while (Erro>1.e-4)&(it<it_max)
    % Conta o número da iterações,
    it=it+1;
    % xout, será o resultado no final da iteração, i.e., xout=x(t+1).
    xout=xin;
    % Escolhe uma seqüência de índices aleatoriamente,
    ind=randperm(N);
    % Para cada índice da seqüência gerada aleatoriamente, faça:
    for i=1:N
       % Calcula a ativação do neurônio com certo índice,
       clear u;
       u=W(ind(i),:)*xout;
       xout(ind(i))=sign(u);
       % Calcula a saída do neurônio e atualiza xout.
       % Se u=0, então x(t+1)_i = x(t)_i,
       if abs(u)<1.e-9 % Evitar erros de arredondamento! 
          xout(ind(i))=xin(ind(i));
       end
    end
    % Calcula o erro entre x(t) e x(t+1);
    Erro=norm(xout-xin);
    % Atualiza x(t+1).
    xin=xout;
end