Be the first to rate this file! 7 downloads (last 30 days) File Size: 18.73 KB File ID: #26611

On-The-Fly Definition of Custom Matrix Objects

by Matt J

 

07 Feb 2010

Code covered by the BSD License  

Class of matrix-like objects with on-the-fly definable methods.

Download Now | Watch this File

File Information
Description

This submission defines a generic class of matrix-like objects called MatrixObj. Objects of the class are capable of behaving as matrices, but whose math operators (+,-,*,\,.*,<,>,etc...) and other methods can be (re)defined from within any Mfile or even from the command line. This removes the restriction of writing a dedicated classdef file or class directory for every new matrix-type object that a user might wish to create.
 
The class works by storing function handles to the various matrix operator functions (plus, minus, mtimes, mldivide, etc...) in a property of MatrixObj called Ops, which is a structure variable. Hence, one can set the matrix operators as desired simply by setting the fields of Ops to an appropriate function handle.
 
MatrixObj objects are particularly useful when an object needs to be endowed with just a few matrix-like capabilities that are very quickly expressed using anonymous functions or a few short nested functions. This is illustrated in the examples below that deal with creating an efficient version of a DFT matrix. Another advantage of MatrixObj objects is that it is not necessary to issue a "clear classes" command when their Ops methods need to be edited or redefined.
 
EXAMPLE 1: Implementing fft() in operator form. As is well-known, the operation fft(x) can be represented as a matrix-vector multiplication. If you have the Signal Processing Toolbox, the relevant matrix can be generated using the DFTMTX function. Otherwise, it can be generated as follows,
  
   d=2500;
   Q=fft(eye(d)); %DFT matrix - 2500x2500
   
The operation fft(x) is equivalent to Q*x, but this is a slow way to perform the operation,
  
   x=rand(d);
   
   tic; y0=Q*x; toc %Elapsed time is 3.595847 seconds.
 
However, using the MatrixObj class, we can quickly create an object Qobj which can transform x using the same matrix multiplication syntax, Qobj*x, but which uses fft() under the hood, with all of its advantages in speed,
  
 
   Qobj=MatrixObj;
   Qobj.Ops.mtimes=@(obj,z) fft(z); %set the mtimes method in 1 line!!
   

   tic; y1=Qobj*x; toc %Elapsed time is 0.212282 seconds.
   tic; y2=fft(x); toc %Elapsed time is 0.212496 seconds.
   
   isequal(y1,y2); % =1
   
 
And of of course, the memory footprint of Qobj is far less than for the full matrix Q
  
  >>whos Q Qobj
    
  Name Size Bytes Class Attributes
  
  Q 2500x2500 100000000 double complex
  Qobj 1x1 6688 MatrixObj

  
EXAMPLE 2: Continuing with Example 1, suppose I now decide that I still want Qobj to represent an fft() operation, but that it be normalized to satisfy Parseval's theorem. A simple on-the-fly redefinition of mtimes() can accomplish this.
  
   Qobj.Ops.mtimes=@(obj,z) (1/sqrt(numel(z)))*fft(z);
   
   x=rand(d,1);
   
   TestParseval=[norm(x), norm(Qobj*x)], % =[28.2807, 28.2807]
   
  
EXAMPLE 3: Continuing with Example 2, let us now look at how to give Qobj a ctranspose method so that Qobj' is defined. Because Qobj satisfies Parseval's theorem, Qobj' is its inverse. We will implement this by putting the following nested function in the workspace,
  
  
          function obj=fftCtranspose(obj)
  
              forw='@(obj,z)(1/sqrt(numel(z)))*fft(z)';
              back='@(obj,z)sqrt(numel(z))*ifft(z)';
              s=func2str(obj.Ops.mtimes);
  
              if isequal(deblank(s),forw)%fft-to-ifft
                 obj.Ops.mtimes=str2func(back);
              else
                 obj.Ops.mtimes=str2func(forw);
              end
  
          end
  
whereupon by passing an appropriate function handle, we add this to the list of operations defined for Qobj,
  
    Qobj.Ops.ctranspose=@fftCtranspose;
    
The code below verifies that the ctranpose operation has various anticipated properties,
  
    TestParseval=[norm(x), norm(Qobj'*x)], % =[28.2807, 28.2807]
    
    AdjointOfAdjoint=isequal(Qobj*x, (Qobj')'*x), % =1
    
    InversionErrorLeft=norm(x- Qobj'*(Qobj*x)), % =8.4315e-015
    
    InversionErrorRight=norm(x- Qobj*(Qobj'*x)), % =7.9086e-015
  
EXAMPLE 4: The MatrixObj class has a property called Params (default=[]) which can be used to hold a structure of object parameters, or any other desired object data. The next example uses the Params property to create a specialized vector for which addition and subtraction invoke bsxfun(). This can be useful if one wishes to circumvent bsxfun's lengthy function syntax.
  
        v=MatrixObj;
  
        v.Params=[1;2];
        v.Ops.minus=@(A,obj) bsxfun(@minus,A,obj.Params);
        v.Ops.plus= @(A,obj) bsxfun(@plus,A,obj.Params);
  
        A=[1,2;3,4].'; %some data
  
        >>B=A-v,
  
          B =
  
               0 2
               0 2

MATLAB release MATLAB 7.9 (2009b)
Zip File Content  
Other Files
@MatrixObj/and.m,
@MatrixObj/colon.m,
@MatrixObj/ctranspose.m,
@MatrixObj/end.m,
@MatrixObj/eq.m,
@MatrixObj/ge.m,
@MatrixObj/get.m,
@MatrixObj/gt.m,
@MatrixObj/horzcat.m,
@MatrixObj/inv.m,
@MatrixObj/ldivide.m,
@MatrixObj/le.m,
@MatrixObj/loadobj.m,
@MatrixObj/lt.m,
@MatrixObj/MatrixObj.m,
@MatrixObj/minus.m,
@MatrixObj/mldivide.m,
@MatrixObj/mpower.m,
@MatrixObj/mrdivide.m,
@MatrixObj/mtimes.m,
@MatrixObj/ne.m,
@MatrixObj/not.m,
@MatrixObj/or.m,
@MatrixObj/plus.m,
@MatrixObj/power.m,
@MatrixObj/private/gateway.m,
@MatrixObj/rdivide.m,
@MatrixObj/set.m,
@MatrixObj/size.m,
@MatrixObj/subsasgn.m,
@MatrixObj/subsindex.m,
@MatrixObj/subsref.m,
@MatrixObj/sum.m,
@MatrixObj/times.m,
@MatrixObj/transpose.m,
@MatrixObj/uminus.m,
@MatrixObj/uplus.m,
@MatrixObj/vertcat.m,
GettingStarted.txt,
license.txt,
MatrixObjExamples.m,
mobjtest.m
Tags for This File  
Everyone's Tags
Tags I've Applied
Add New Tags Please login to tag files.
Please login to add a comment or rating.
Tag Activity for this File
Tag Applied By Date/Time
oop Matt J 08 Feb 2010 11:42:57
operator Matt J 08 Feb 2010 11:42:57
matrix Matt J 08 Feb 2010 11:42:57
onthefly Matt J 08 Feb 2010 11:42:58
matrixobj Matt J 08 Feb 2010 11:42:58

Contact us at files@mathworks.com