From: <nir...@us...> - 2012-04-18 20:42:30
|
Revision: 10279 http://octave.svn.sourceforge.net/octave/?rev=10279&view=rev Author: nir-krakauer Date: 2012-04-18 20:42:20 +0000 (Wed, 18 Apr 2012) Log Message: ----------- Added new functions for working with circulant matrices Added Paths: ----------- trunk/octave-forge/main/linear-algebra/inst/circulant_eig.m trunk/octave-forge/main/linear-algebra/inst/circulant_inv.m trunk/octave-forge/main/linear-algebra/inst/circulant_make_matrix.m trunk/octave-forge/main/linear-algebra/inst/circulant_matrix_vector_product.m Added: trunk/octave-forge/main/linear-algebra/inst/circulant_eig.m =================================================================== --- trunk/octave-forge/main/linear-algebra/inst/circulant_eig.m (rev 0) +++ trunk/octave-forge/main/linear-algebra/inst/circulant_eig.m 2012-04-18 20:42:20 UTC (rev 10279) @@ -0,0 +1,60 @@ +## Copyright (C) 2012 Nir Krakauer +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn{Function File}{[@var{lambda}] =} circulant_eig (@var{v}) +## @deftypefnx{Function File}{[@var{vs}, @var{lambda}] =} circulant_eig (@var{v}) +## +## Fast, compact calculation of eigenvalues and eigenvectors of a circulant matrix@* +## Given an @var{n}*1 vector @var{v}, return the eigenvalues @var{lambda} and optionally eigenvectors @var{vs} of the @var{n}*@var{n} circulant matrix @var{C} that has @var{v} as its first column +## +## Theoretically same as @code{eig(make_circulant_matrix(v))}, but many fewer computations; does not form @var{C} explicitly +## +## Reference: Robert M. Gray, Toeplitz and Circulant Matrices: A Review, Now Publishers, http://ee.stanford.edu/~gray/toeplitz.pdf, Chapter 3 +## +## @end deftypefn +## @seealso{circulant_make_matrix, circulant_matrix_vector_product, circulant_inv} + +## Author: Nir Krakauer <nkr...@cc...> + +function [a, b] = circulant_eig(v) + + +warning ("off", "Octave:broadcast"); #the code below uses broadcasting + +#find the eigenvalues +n = numel(v); +lambda = ones(n, 1); +s = (0:(n-1)); +lambda = sum(v .* exp(-2*pi*i*s'*s/n))'; + +if nargout < 2 + a = lambda; + return +endif + +#find the eigenvectors (which in fact do not depend on v) +a = exp(-2*i*pi*s'*s/n) / sqrt(n); +b = diag(lambda); + + +endfunction + + +%!shared v,C,vs,lambda +%! v = [1 2 3]'; +%! C = circulant_make_matrix(v); +%! [vs lambda] = circulant_eig(v); +%!assert (vs*lambda, C*vs, 100*eps); Added: trunk/octave-forge/main/linear-algebra/inst/circulant_inv.m =================================================================== --- trunk/octave-forge/main/linear-algebra/inst/circulant_inv.m (rev 0) +++ trunk/octave-forge/main/linear-algebra/inst/circulant_inv.m 2012-04-18 20:42:20 UTC (rev 10279) @@ -0,0 +1,49 @@ +## Copyright (C) 2012 Nir Krakauer +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn{Function File}{[@var{c}] =} circulant_inv (@var{v}) +## +## Fast, compact calculation of inverse of a circulant matrix@* +## Given an @var{n}*1 vector @var{v}, return the inverse @var{c} of the @var{n}*@var{n} circulant matrix @var{C} that has @var{v} as its first column +## The returned @var{c} is the first column of the inverse, which is also circulant -- to get the full matrix, use `circulant_make_matrix(c)' +## +## Theoretically same as @code{inv(make_circulant_matrix(v))(:, 1)}, but requires many fewer computations and does not form matrices explicitly +## +## Roundoff may induce a small imaginary component in @var{c} even if @var{v} is real -- use @code{real(c)} to remedy this +## +## Reference: Robert M. Gray, Toeplitz and Circulant Matrices: A Review, Now Publishers, http://ee.stanford.edu/~gray/toeplitz.pdf, Chapter 3 +## +## @end deftypefn +## @seealso{circulant_make_matrix, circulant_matrix_vector_product, circulant_eig} + +## Author: Nir Krakauer <nkr...@cc...> + +function c = circulant_inv(v) + + +## Find the eigenvalues and eigenvectors +[vs, lambda] = circulant_eig(v); + +## Find the first column of the inverse +c = vs * diag(1 ./ diag(lambda)) * conj(vs(:, 1)); + + +endfunction + + +%!shared v +%! v = [1 2 3]'; +%!assert (make_circulant_matrix(circulant_inv(v)), inv(make_circulant_matrix(v)), 10*eps); Added: trunk/octave-forge/main/linear-algebra/inst/circulant_make_matrix.m =================================================================== --- trunk/octave-forge/main/linear-algebra/inst/circulant_make_matrix.m (rev 0) +++ trunk/octave-forge/main/linear-algebra/inst/circulant_make_matrix.m 2012-04-18 20:42:20 UTC (rev 10279) @@ -0,0 +1,46 @@ +## Copyright (C) 2012 Nir Krakauer +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn{Function File}{[@var{C}] =} circulant_make_matrix(@var{v}) +## +## Produce a full circulant matrix given the first column@* +## Given an @var{n}*1 vector @var{v}, returns the @var{n}*@var{n} circulant matrix @var{C} where @var{v} is the left column and all other columns are downshifted versions of @var{v} +## +## Note: If the first row @var{r} of a circulant matrix is given, the first column @var{v} can be obtained as @code{v = r([1 end:-1:2])} +## +## Reference: Gene H. Golub and Charles F. Van Loan, Matrix Computations, 3rd Ed., Section 4.7.7 +## +## @end deftypefn +## @seealso{circulant_matrix_vector_product, circulant_eig, circulant_inv} + +## Author: Nir Krakauer <nkr...@cc...> + + +function C = circulant_make_matrix(v) + +n = numel(v); + +C = ones(n, n); + +for i = 1:n + C(:, i) = v([(end-i+2):end 1:(end-i+1)]); #or circshift(v, i-1) +endfor + +endfunction + +%!shared v,C +%! v = [1 2 3]'; C = [1 3 2; 2 1 3; 3 2 1]; +%!assert (circulant_make_matrix(v), C); Added: trunk/octave-forge/main/linear-algebra/inst/circulant_matrix_vector_product.m =================================================================== --- trunk/octave-forge/main/linear-algebra/inst/circulant_matrix_vector_product.m (rev 0) +++ trunk/octave-forge/main/linear-algebra/inst/circulant_matrix_vector_product.m 2012-04-18 20:42:20 UTC (rev 10279) @@ -0,0 +1,48 @@ +## Copyright (C) 2012 Nir Krakauer +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn{Function File}{[@var{y}] =} circulant_matrix_vector_product(@var{v}, @var{x}) +## +## Fast, compact calculation of the product of a circulant matrix with a vector@* +## Given @var{n}*1 vectors @var{v} and @var{x}, return the matrix-vector product @var{y} = @var{C}@var{x}, where @var{C} is the @var{n}*@var{n} circulant matrix that has @var{v} as its first column +## +## Theoretically the same as @code{make_circulant_matrix(x) * v}, but does not form @var{C} explicitly; uses the discrete Fourier transform +## +## Because of roundoff, the returned @var{y} may have a small imaginary component even if @var{v} and @var{x} are real (use @code{real(y)} to remedy this) +## +## Reference: Gene H. Golub and Charles F. Van Loan, Matrix Computations, 3rd Ed., Section 4.7.7 +## +## @end deftypefn +## @seealso{circulant_make_matrix, circulant_eig, circulant_inv} + +## Author: Nir Krakauer <nkr...@cc...> + +function y = circulant_matrix_vector_product(v, x) + + +xf = fft(x); +vf = fft(v); +z = vf .* xf; +y = ifft(z); + + +endfunction + + + +%!shared v,x +%! v = [1 2 3]'; x = [2 5 6]'; +%!assert (circulant_matrix_vector_product(v, x), circulant_make_matrix(v)*x, eps); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |