% apca -  PCA
%
% acpa ::
%    [[N,M]] ~'initial weight vectors',
%    options {
%       ordered :: bool   /1  ~'produce PCs in variance order?';
%       rate    :: nonneg/1e-7 ~'adaptation rate';
%       subsample :: natural/1;
%       plotfig   :: natural/0;
%    }
% -> arrow({[[N]]},{[[M]]},apca_state).

function o=apca(W0,varargin)
	opts=options('rate',1e-7,'ordered',1,'subsample',1,'plotfig',0,varargin{:});

	rate=opts.rate;
	if opts.ordered
		o=loop(@update1,@(s)W0);
	else
		o=loop(@update,@(s)W0);
	end
	if opts.plotfig>0,
		o=estates(o,opts.subsample)*(aid + erate(plotter('fig',opts.plotfig,'name','PC basis')))
	end

	function [y,W]=update(x,W)
		y=W'*x;
		e=x-W*y;
		W=W+rate*e*y';
	end

	function [y,W]=update1(x,W)
		y=W'*x;
		NY=repmat(-y',size(x,1),1);
		E=cumsum([x,W.*NY],2); % errors after progressive reconstruction
		W=W-rate*(E(:,2:end).*NY);
	end
end
