spm_kernels.m 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. function [K0,K1,K2,H1] = spm_kernels(varargin)
  2. % returns global Volterra kernels for a MIMO Bilinear system
  3. % FORMAT [K0,K1,K2] = spm_kernels(M,P,N,dt) - output kernels
  4. % FORMAT [K0,K1,K2] = spm_kernels(M0,M1,N,dt) - state kernels
  5. % FORMAT [K0,K1,K2] = spm_kernels(M0,M1,L1,N,dt) - output kernels (1st)
  6. % FORMAT [K0,K1,K2] = spm_kernels(M0,M1,L1,L2,N,dt) - output kernels (2nd)
  7. %
  8. % M,P - model structure and parameters;
  9. % or its bilinear reduction:
  10. %
  11. % M0 - (n x n) df(q(0),0)/dq - n states
  12. % M1 - {m}(n x n) d2f(q(0),0)/dqdu - m inputs
  13. % L1 - (l x n) dldq - l outputs
  14. % L2 - {m}(n x n) dl2dqq
  15. %
  16. % N - kernel depth {intervals}
  17. % dt - interval {seconds}
  18. %
  19. % Volterra kernels:
  20. %---------------------------------------------------------------------------
  21. % K0 - (1 x l) = K0(t) = y(t)
  22. % K1 - (N x l x m) = K1i(t,s1) = dy(t)/dui(t - s1)
  23. % K2 - (N x N x l x m x m) = K2ij(t,s1,s2) = d2y(t)/dui(t - s1)duj(t - s2)
  24. %
  25. %___________________________________________________________________________
  26. % Returns Volterra kernels for bilinear systems of the form
  27. %
  28. % dq/dt = f(q,u) = M0*q + M1{1}*q*u1 + ... M1{m}*q*um
  29. % y(i) = L1(i,:)*q + q'*L2{i}*q
  30. %
  31. % where q = [1 x(t)] are the states augmented with a constant term
  32. %
  33. %__________________________________________________________________________
  34. % Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
  35. % Karl Friston
  36. % $Id: spm_kernels.m 6937 2016-11-20 12:30:40Z karl $
  37. % assign inputs
  38. %--------------------------------------------------------------------------
  39. if nargin == 4
  40. M0 = varargin{1};
  41. M1 = varargin{2};
  42. N = varargin{3};
  43. dt = varargin{4};
  44. elseif nargin == 5
  45. M0 = varargin{1};
  46. M1 = varargin{2};
  47. L1 = varargin{3};
  48. N = varargin{4};
  49. dt = varargin{5};
  50. elseif nargin == 6
  51. M0 = varargin{1};
  52. M1 = varargin{2};
  53. L1 = varargin{3};
  54. L2 = varargin{4};
  55. N = varargin{5};
  56. dt = varargin{6};
  57. end
  58. % bilinear reduction if necessary
  59. %--------------------------------------------------------------------------
  60. if isstruct(M0)
  61. [M0,M1,L1,L2] = spm_bireduce(M0,M1);
  62. end
  63. % Volterra kernels for bilinear systems
  64. %==========================================================================
  65. % make states the outputs (i.e. remove constant) if L1 is not specified
  66. %--------------------------------------------------------------------------
  67. try
  68. L1;
  69. catch
  70. L1 = speye(size(M0));
  71. L1 = L1(2:end,:);
  72. end
  73. try
  74. L2;
  75. catch
  76. L2 = [];
  77. end
  78. % parameters
  79. %--------------------------------------------------------------------------
  80. N = fix(N); % kernel depth
  81. n = size(M0,1); % state variables
  82. m = size(M1,1); % inputs
  83. l = size(L1,1); % outputs
  84. H1 = zeros(N,n,m);
  85. K1 = zeros(N,l,m);
  86. K2 = zeros(N,N,l,m,m);
  87. M0 = full(M0);
  88. % pre-compute matrix exponentials
  89. %--------------------------------------------------------------------------
  90. e1 = expm( dt*M0);
  91. e2 = expm(-dt*M0);
  92. for p = 1:m
  93. M{1,p} = e1*M1{p}*e2;
  94. end
  95. ei = e1;
  96. for i = 2:N
  97. ei = e1*ei;
  98. for p = 1:m
  99. M{i,p} = e1*M{i - 1,p}*e2;
  100. end
  101. end
  102. % 0th order kernel
  103. %--------------------------------------------------------------------------
  104. X0 = sparse(1,1,1,n,1);
  105. if nargout > 0
  106. H0 = ei*X0;
  107. K0 = L1*H0;
  108. end
  109. % 1st order kernel
  110. %--------------------------------------------------------------------------
  111. if nargout > 1
  112. for p = 1:m
  113. for i = 1:N
  114. H1(i,:,p) = M{i,p}*H0;
  115. K1(i,:,p) = H1(i,:,p)*L1';
  116. end
  117. end
  118. end
  119. % 2nd order kernels
  120. %--------------------------------------------------------------------------
  121. if nargout > 2
  122. for p = 1:m
  123. for q = 1:m
  124. for j = 1:N
  125. H = L1*M{j,q}*H1((j:N),:,p)';
  126. K2(j,j:N,:,q,p) = H';
  127. K2(j:N,j,:,p,q) = H';
  128. end
  129. end
  130. end
  131. if isempty(L2), return, end
  132. % add output nonlinearity
  133. %----------------------------------------------------------------------
  134. for i = 1:m
  135. for j = 1:m
  136. for p = 1:l
  137. K2(:,:,p,i,j) = K2(:,:,p,i,j) + H1(:,:,i)*L2{p}*H1(:,:,j)';
  138. end
  139. end
  140. end
  141. end