function FEP_Manifold % This demonstration routine simulates the emergence of life - as defined % in terms of active inference - using a synthetic primordial soup. The key % aspect of this dynamics is that there is a separation between dynamical % states and structural states; where the dynamical states of the % microsystem are equipped with a Lorentz attractor and the structural % states correspond to position and velocity. The flow of structural % states conforms to classical Newtonian mechanics. Crucially, the physical % motion of each microsystem is coupled to its internal dynamics and vice % versa; where the coupling among dynamics rests upon short range % (electrochemical) forces. This means that the dependencies among the % dynamics of each microsystem dependent on their positions. This induces a % dependency of the systems structural integrity on its internal dynamics - % which leads to biological self-organisation. This biological self- % organisation is illustrated in terms of the following: % % i) the existence of a Markov blanket that separates internal and external % states, where the internal states are associated with a system that % engages in active or embodied inference. % % ii) emergent inference is demonstrated by showing that the internal % states can predict the extent states, despite their separation by the % Markov blanket. % % iii) this inference (encoded by the internal dynamics) is necessary to % maintain structural integrity, as illustrated by simulated lesion % experiments, in which the influence of various states are quenched. % %__________________________________________________________________________ % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging % Karl Friston % $Id: FEP_Manifold.m 7163 2017-09-04 09:12:50Z karl $ % default settings (GRAPHICS sets movies) %-------------------------------------------------------------------------- rng('default') GRAPHICS = 1; % Demo of synchronization manifold using coupled Lorenz attractors %========================================================================== d = 8; N = 128; % number of (Lorenz) oscillators T = 2048; % number of time bins t = (T - 256):T; % final time indices dt = 1/32; % time interval % parameters %-------------------------------------------------------------------------- P.k = 1 - exp(-rand(1,N)*4); % variations in temporal scale P.a = rand(1,N) > 2/3; % no out influences P.e = exp(0); % energy parameter (well depth) % states %-------------------------------------------------------------------------- x.p = randn(2,N)*4; % microstates (position) x.v = zeros(2,N); % microstates (velocity) x.q = randn(3,N)/32; % microstates (states) u = zeros(1,T); % exogenous fluctuations % illustrate dynamics from initial conditions %========================================================================== spm_figure('GetWin','Dynamics');clf if GRAPHICS subplot(2,2,1) else subplot(2,1,1) end [Q,X,V,A,x] = spm_Manifold_solve(x,u,P,T,dt,1); % pretty graphics %-------------------------------------------------------------------------- if GRAPHICS subplot(2,2,2) spm_Manifold_solve(x,u,P,128,1/128,3); end % Markov blanket - parents, children, and parents of children %========================================================================== % Adjacency matrix %-------------------------------------------------------------------------- L = sparse(double(any(A(:,:,t),3))); % internal states (defined by principle eigenvector of Markov blanket) %-------------------------------------------------------------------------- B = double((L + L' + L'*L)); B = B - diag(diag(B)); v = spm_svd(B*B',1); [v,j] = sort(abs(v(:,1)),'descend'); % get Markov blanket and divide into sensory and active states %-------------------------------------------------------------------------- j = j(1:8); % internal cluster jj = sparse(j,1,1,N,1); % internal states bb = B*jj & (1 - jj); % Markov blanket ee = 1 - bb - jj; % external states b = find(bb); e = find(ee); s = b(find( any(L(e,b)))); a = b(find(~any(L(e,b)))); % adjacency matrix - with partition underneath (LL) %-------------------------------------------------------------------------- k = [e; s; a; j]; LL = L'; LL(e,e) = LL(e,e) + 1/8; LL(s,s) = LL(s,s) + 1/8; LL(a,a) = LL(a,a) + 1/8; LL(j,j) = LL(j,j) + 1/8; LL = LL(k,k); % plot dynamics for the initial and subsequent time periods %-------------------------------------------------------------------------- subplot(4,1,3) r = 1:512; plot(r,squeeze(Q(1,e,r)),':c'), hold on plot(r,squeeze(Q(1,j,r)),' b'), hold off axis([r(1) r(end) -32 32]) xlabel('time','FontSize',12) title('State dymanics','FontSize',16) subplot(4,1,4) r = 1:2048; plot(r,squeeze(V(1,e,r)),':c'), hold on plot(r,squeeze(V(1,j,r)),' b'), hold off axis([r(1) r(end) -32 32]) xlabel('time','FontSize',12) title('State dymanics','FontSize',16) % Markov blanket - self-assembly %========================================================================== spm_figure('GetWin','Markov blanket'); subplot(2,2,1) imagesc(1 - LL) axis square xlabel('Element','FontSize',12) xlabel('Element','FontSize',12) title('Adjacency matrix','FontSize',16) clear M % follow self-assembly %-------------------------------------------------------------------------- for i = (T-512):T % plot positions %---------------------------------------------------------------------- subplot(2,2,2),set(gca,'color','w') px = ones(3,1)*X(1,:,i) + Q([1 2 3],:,i)/16; py = ones(3,1)*X(2,:,i) + Q([2 3 1],:,i)/16; plot(px,py,'.b','MarkerSize',8), hold on px = X(1,e,i); py = X(2,e,i); plot(px,py,'.c','MarkerSize',24) px = X(1,j,i); py = X(2,j,i); plot(px,py,'.b','MarkerSize',24) px = X(1,s,i); py = X(2,s,i); plot(px,py,'.m','MarkerSize',24) px = X(1,a,i); py = X(2,a,i); plot(px,py,'.r','MarkerSize',24) xlabel('Position','FontSize',12) ylabel('Position','FontSize',12) title('Markov Blanket','FontSize',16) axis([-1 1 -1 1]*d) axis square hold off drawnow % save %---------------------------------------------------------------------- if i > (T - 128) && GRAPHICS M(i - T + 128) = getframe(gca); end end % set ButtonDownFcn %-------------------------------------------------------------------------- if GRAPHICS h = findobj(gca); set(h(1),'Userdata',{M,16}) set(h(1),'ButtonDownFcn','spm_DEM_ButtonDownFcn') xlabel('Click for Movie','Color','r') end % overlay attributes %-------------------------------------------------------------------------- subplot(2,2,3) plot(X(1,e,T),X(2,e,T),'.c','MarkerSize',24), hold on plot(X(1,j,T),X(2,j,T),'.b','MarkerSize',24), hold on plot(X(1,s,T),X(2,s,T),'.m','MarkerSize',24), hold on plot(X(1,a,T),X(2,a,T),'.r','MarkerSize',24), hold on px = X(1,find(~P.a),T); py = X(2,find(~P.a),T); plot(px,py,'.w','MarkerSize',22) xlabel('Position','FontSize',12) title('Dynamically closed','FontSize',16) axis([-1 1 -1 1]*d) axis square hold off subplot(2,2,4) plot(X(1,e,T),X(2,e,T),'.c','MarkerSize',24), hold on plot(X(1,j,T),X(2,j,T),'.b','MarkerSize',24), hold on plot(X(1,s,T),X(2,s,T),'.m','MarkerSize',24), hold on plot(X(1,a,T),X(2,a,T),'.r','MarkerSize',24), hold on px = X(1,find(P.k > 1/2),T); py = X(2,find(P.k > 1/2),T); plot(px,py,'.w','MarkerSize',22) xlabel('Position','FontSize',12) title('Slow systems','FontSize',16) axis([-1 1 -1 1]*d) axis square hold off drawnow % Evolution of the Markov blanket %========================================================================== spm_figure('GetWin','Evolution of the Markov blanket');clf rng('default') T = 512; for i = 1:4 % intervention %-------------------------------------------------------------------------- PP = P; if i == 2 PP.a(a) = 1; % lesion active elements elseif i == 3 PP.a(s) = 1; % lesion sensory elements elseif i == 4 PP.a(j) = 1; % lesion internal elements end % continue integration %-------------------------------------------------------------------------- [QQ,XX] = spm_Manifold_solve(x,u,PP,T,dt,0); % plot trajectories of Markov Blanket and final internal state %-------------------------------------------------------------------------- subplot(2,2,i),set(gca,'color','w') px = squeeze(XX(1,s,:)); py = squeeze(XX(2,s,:)); plot(px,py,'.m','MarkerSize',4), hold on px = squeeze(XX(1,a,:)); py = squeeze(XX(2,a,:)); plot(px,py,'.r','MarkerSize',4), hold on px = squeeze(XX(1,j,:)); py = squeeze(XX(2,j,:)); plot(px,py,'.b','MarkerSize',8), hold off xlabel('Position','FontSize',12) axis([-1 1 -1 1]*d) axis square % title %-------------------------------------------------------------------------- if i == 1 title('Markov blanket','FontSize',16) elseif i == 2 title('Active lesion','FontSize',16); elseif i == 3 title('Sensory lesion','FontSize',16); elseif i == 4 title('Internal lesion','FontSize',16); end end % illustrate the Bayesian perspective (predictability of external states) %========================================================================== spm_figure('GetWin','Bayesian perspective');clf % establish a statistical dependency between internal (dynamic) states (XQ) %-------------------------------------------------------------------------- clear XQ T = 512; % length of timeseries n = 64; % temporal embedding t = size(Q,3) - n - T - n; for i = 1:T for k = 1:(n + n) XQ{i,k} = spm_vec(Q(:,j,i + k + t))'; end end % normalise and retain principal eigenvariates %-------------------------------------------------------------------------- Xq = spm_en(diff(spm_cat(XQ),1)); [Xq,S,UX] = spm_svd(Xq,1); Xq = Xq(:,1:32); X0 = ones(size(Xq,1),1); subplot(3,2,1) imagesc(Xq') xlabel('Time', 'FontSize',12) ylabel('Modes','FontSize',12) title('Internal states','FontSize',16) axis square % get equivalent external states to be predicted %-------------------------------------------------------------------------- t = size(Q,3) + (1:T) - n - T; for c = 1:length(e) % get the external states for this element %---------------------------------------------------------------------- Y = squeeze(X(:,e(c),t))'; Y0 = flipud(Y); Y = diff(spm_en(Y ),1); Y0 = diff(spm_en(Y0),1); % and take the principal eigenvariates %---------------------------------------------------------------------- Yq = spm_svd(Y,1); Yq0 = spm_svd(Y0,1); % test for dependencies using canonical variance analysis %---------------------------------------------------------------------- CVA(c) = spm_cva(Yq,Xq,X0); CVA0 = spm_cva(Yq0,Xq,X0); SPM(c) = CVA(c).chi(1); SPM0(c) = CVA0.chi(1); end % show results %-------------------------------------------------------------------------- subplot(3,2,3) [k,i] = max(SPM); CVA = CVA(i); plot(CVA.v(:,1),'b:'), hold on plot(CVA.w(:,1),'b' ), hold off xlabel('Time', 'FontSize',12) ylabel('External states','FontSize',12) title('Motion (where)','FontSize',16) axis square spm_axis tight % SPM of external prediciability %-------------------------------------------------------------------------- subplot(3,2,4) W = (SPM/max(SPM)).^2; for k = 1:length(e) c = [0 1 1]*W(k) + [1 1 1]*(1 - W(k)); plot(X(1,e(k),end),X(2,e(k),end),'.','MarkerSize',32,'Color',c), hold on end plot(X(1,e(i),end),X(2,e(i),end),'.m','MarkerSize',32), hold on plot(X(1,j,end),X(2,j,end),'.b','MarkerSize',32), hold off xlabel('Position','FontSize',12) ylabel('Position','FontSize',12) title('Predictability','FontSize',16) axis([-1 1 -1 1]*d) axis square hold off % Distributions %-------------------------------------------------------------------------- subplot(3,2,2) hist([SPM' SPM0'],4) xlabel('Chi-squared','FontSize',12) ylabel('Freuquency','FontSize',12) title('Distributions','FontSize',16) ne = sum(SPM > max(SPM0)); pe = 1 - spm_Icdf(ne,length(e),1/length(e)); fprintf('\nOminbus p-value: p < %-0.5f\n',pe); return % NOTES: Phase portrait and entropies (temperature) %========================================================================== spm_figure('GetWin','Phases and entropies'); T = 1024; t = (T - 512):T; n = 16; Hp = zeros(1,n); Hq = zeros(1,n); Pe = linspace(-4,4,n); Pp = P; for i = 1:n % parameters (energy and state-dependent forces) %------------------------------------------------------------------ Pp.e = exp(Pe(i)); % entropy of dynamics %------------------------------------------------------------------ [Q,X] = spm_Manifold_solve(x,u,Pp,T,1/32,0); % entropy of dynamics %------------------------------------------------------------------ q = squeeze(Q(1,:,t)); Hq(i) = spm_logdet(cov(q')); % configuration entropy %------------------------------------------------------------------ p = squeeze(X(1,:,t)); Hp(i) = spm_logdet(cov(p')); % update with graphics %------------------------------------------------------------------ subplot(2,2,1) plot(Pe,Hp,Pe,Hq) title('Phases and entropy','FontSize',16) xlabel('Entropy','FontSize',12) ylabel('Potential energy','FontSize',12) legend({'Structural','Functional'}) axis square subplot(2,2,2) plot(Pe,Hp - Hq) title('Difference','FontSize',16) xlabel('Entropy','FontSize',12) ylabel('Potential energy','FontSize',12) axis square % plot dynamics %-------------------------------------------------------------------------- subplot(2,2,3) plot(1:T,squeeze(X(1,:,:)),':',t,squeeze(X(1,:,t)),'-') axis([1 T -64 64]) xlabel('time','FontSize',12) title('Dynamics','FontSize',16) axis square % plot entropies %-------------------------------------------------------------------------- subplot(2,2,4) plot(Hq(:),Hp(:),'.',Hq(:),Hp(:),'o') xlabel('Functional entropy','FontSize',12) ylabel('Structural entropy','FontSize',12) title('Entropies','FontSize',16) axis square end