Home || Architecture || Video Search || Visual Search || Scripts || Applications || Important Messages || OGL || Src

MatNorm2Dist.h

Go to the documentation of this file.
00001 #ifndef Impala_Core_Matrix_MatNorm2Dist_h
00002 #define Impala_Core_Matrix_MatNorm2Dist_h
00003 
00004 #include "Core/Matrix/MatFunc.h"
00005 #include "Core/Matrix/MatSum.h"
00006 #include "Core/Matrix/MatMul.h"
00007 #include "Core/Matrix/MatReplicateMatrix.h"
00008 #include "Core/Array/Abs.h"
00009 #include "Core/Array/Add.h"
00010 #include "Core/Array/Mul.h"
00011 #include "Core/Array/MulVal.h"
00012 #include "Core/Array/Sqrt.h"
00013 #include "Basis/Timer.h"
00014 #ifdef CUDA
00015 #include "Link/Cuda/Cuda.h"
00016 #include "Link/Cuda/MatNorm2Dist.h"
00017 #endif
00018 //#include "Core/Array/WriteRaw.h"
00019 
00020 namespace Impala
00021 {
00022 namespace Core
00023 {
00024 namespace Matrix
00025 {
00026 
00027 /*
00028 def distance(a,b):
00029     """Computes Euclidean distance matrix
00030 
00031     E = distance(A,B)
00032     
00033         A - (DxM) matrix
00034         B - (DxN) matrix
00035     
00036     Returns:
00037         E - (MxN) Euclidean distances between vectors in A and B
00038     
00039     
00040     Description :
00041         This fully vectorized (VERY FAST!) script computes the
00042         Euclidean distance between two vectors by:
00043     
00044                      ||A-B|| = sqrt ( ||A||^2 + ||B||^2 - 2*A.B )
00045     
00046     Example :
00047         A = rand(400,100); B = rand(400,200);
00048         d = distance(A,B);
00049     
00050     Credits for original Matlab script:
00051     % Author   : Roland Bunschoten
00052     %            University of Amsterdam
00053     %            Intelligent Autonomous Systems (IAS) group
00054     %            Kruislaan 403  1098 SJ Amsterdam
00055     %            tel.(+31)20-5257524
00056     %            bunschot@wins.uva.nl
00057     % Last Rev : Oct 29 16:35:48 MET DST 1999
00058     % Tested   : PC Matlab v5.2 and Solaris Matlab v5.3
00059     % Thanx    : Nikos Vlassis
00060     
00061     % Copyright notice: You are free to modify, extend and distribute
00062     %    this code granted that the author of the original code is
00063     %    mentioned as the original author of the code.
00064     """
00065     from numpy import multiply, transpose, sum, dot, abs, sqrt
00066     from numpy.matlib import repmat
00067 
00068     assert a.shape[0] == b.shape[0], 'A and B should be of same dimensionality'
00069 
00070     # aa=sum(a.*a,1); bb=sum(b.*b,1); ab=a'*b;
00071     #d = sqrt(abs(repmat(aa',[1 size(bb,2)]) + repmat(bb,[size(aa,2) 1]) - 2*ab));
00072 
00073     aa = sum(multiply(a,a), axis=0)      # aa = sum(a.*a,1)
00074     bb = sum(multiply(b,b), axis=0)      # bb = sum(b.*b,1)
00075     ab = dot(transpose(a),b)             # ab = a'*b   
00076     return sqrt(abs(transpose(repmat(aa,bb.shape[0],1)) + repmat(bb,aa.shape[0],1) - 2*ab))
00077 */
00078 
00079 template<class ArrayT>
00080 inline ArrayT*
00081 MatNorm2DistInternal(ArrayT* aT, ArrayT* b)
00082 {
00083     ILOG_VAR(Core.Matrix.MatNorm2Dist);
00084     if (MatNrCol(aT) != MatNrRow(b)) {
00085         ILOG_ERROR("MatNorm2DistInternal operands: dimensionality problem");
00086     }
00087 
00088     Timer timer;
00089     
00090     // aa = sum(multiply(a,a), axis=0)      # aa = sum(a.*a,1)
00091     ArrayT* tempAT = 0;
00092     Mul(tempAT, aT, aT);         // elementwise multiplication
00093     ArrayT* aaT = MatSumAxis1(tempAT);
00094     delete tempAT;
00095 
00096     ILOG_DEBUG("aaT: " << timer.SplitTimeStr());
00097 
00098     // bb = sum(multiply(b,b), axis=0)      # bb = sum(b.*b,1)
00099     ArrayT* tempB = 0;
00100     Mul(tempB, b, b);         // elementwise multiplication
00101     ArrayT* bb = MatSumAxis0(tempB);
00102     delete tempB;
00103 
00104     ILOG_DEBUG("bb: " << timer.SplitTimeStr());
00105 
00106     // ab = dot(transpose(a),b)             # ab = a'*b   
00107     //ArrayT* aT = MatTranspose(a);
00108     //ILOG_DEBUG("transpose: " << timer.SplitTimeStr());
00109 
00110     ILOG_DEBUG("aT " << MatNrRow(aT) << " " << MatNrCol(aT));
00111     ILOG_DEBUG("b  " << MatNrRow(b) << " " << MatNrCol(b));
00112 
00113     ArrayT* ab = MatMul(aT, b);
00114 
00115     ILOG_DEBUG("matmul: " << timer.SplitTimeStr());
00116 
00117     MulVal(ab, ab, -2.0);                   // -2*ab
00118 
00119     ILOG_DEBUG("ab: " << timer.SplitTimeStr());
00120 
00121     // return sqrt(abs(transpose(repmat(aa,bb.shape[0],1)) + repmat(bb,aa.shape[0],1) - 2*ab))
00122     // #d = sqrt(abs(repmat(aa',[1 size(bb,2)]) + repmat(bb,[size(aa,2) 1]) - 2*ab));
00123     //ArrayT* aaT = MatTranspose(aa);
00124     //ILOG_DEBUG("transpose: " << timer.SplitTimeStr());
00125 
00126     ArrayT* repAAT = MatReplicateMatrix(aaT, 1, MatNrCol(bb));
00127     ILOG_DEBUG("repmatAAT: " << timer.SplitTimeStr());
00128     ArrayT* repBB = MatReplicateMatrix(bb, MatNrRow(aaT), 1);
00129     ILOG_DEBUG("repmatBB: " << timer.SplitTimeStr());
00130     delete bb;
00131     delete aaT;
00132 
00133     ILOG_DEBUG("delete: " << timer.SplitTimeStr());
00134 
00135     Add(repAAT, repAAT, repBB);
00136     delete repBB;
00137     Add(repAAT, repAAT, ab);
00138     ILOG_DEBUG("add: " << timer.SplitTimeStr());
00139 
00140     delete ab;
00141     Abs(repAAT, repAAT);
00142     ILOG_DEBUG("abs: " << timer.SplitTimeStr());
00143 
00144     Sqrt(repAAT, repAAT);
00145 
00146     ILOG_DEBUG("sqrt: " << timer.SplitTimeStr());
00147 //WriteRaw(a, "matrix_a.raw", &Util::Database::GetInstance(), true);
00148 //WriteRaw(b, "matrix_b.raw", &Util::Database::GetInstance(), true);
00149 //WriteRaw(repAAT, "matrix_c.raw", &Util::Database::GetInstance(), true);
00150     //ILOG_INFO("cpu-matnorm2dist-total: " << timer.SplitTime());
00151     ILOG_DEBUG(timer.SplitTime() << " (cpu-matnorm2dist-total)");
00152     return repAAT;
00153 }
00154 
00155 
00156 template<class ArrayT>
00157 inline ArrayT*
00158 MatNorm2Dist(ArrayT* a, ArrayT* b)
00159 {
00160 /*
00161     Computes Euclidean distance matrix
00162 
00163     E = MatNorm2Dist(A,B)
00164     
00165         A - (DxM) matrix
00166         B - (DxN) matrix
00167     
00168     Returns:
00169         E - (MxN) Euclidean distances between vectors in A and B
00170 */
00171     ILOG_VAR(Core.Matrix.MatNorm2Dist);
00172     if (MatNrRow(a) != MatNrRow(b)) {
00173         ILOG_ERROR("MatNorm2Dist operands: A and B should be of same dimensionality");
00174     }
00175     Mat* aT = MatTranspose(a);
00176     ArrayT* result = MatNorm2DistInternal(aT, b);
00177     delete aT;
00178     return result;
00179 }
00180 
00181 
00182 template<class ArrayT>
00183 inline ArrayT*
00184 MatNorm2DistTransposed(ArrayT* aT, ArrayT* bT)
00185 {
00186 /*
00187     Computes Euclidean distance matrix
00188 
00189     E = MatNorm2DistTransposed(A,B)
00190     
00191         A - (MxD) matrix
00192         B - (NxD) matrix
00193     
00194     Returns:
00195         E - (MxN) Euclidean distances between vectors in A and B
00196 */
00197     ILOG_VAR(Core.Matrix.MatNorm2DistTransposed);
00198     if (MatNrCol(aT) != MatNrCol(bT)) {
00199         ILOG_ERROR("MatNorm2DistTransposed operands: A and B should be of same dimensionality");
00200     }
00201 #ifdef CUDA
00202     if(Link::Cuda::CudaUsed())
00203     {
00204         return Link::Cuda::MatNorm2DistTransposed(aT, bT);
00205     }
00206 #endif
00207     Mat* b = MatTranspose(bT);
00208     Mat* result = MatNorm2DistInternal(aT, b);
00209     delete b;
00210     return result;
00211 }
00212 
00213 } // namespace Matrix
00214 } // namespace Core
00215 } // namespace Impala
00216 
00217 #endif

Generated on Fri Mar 19 09:31:16 2010 for ImpalaSrc by  doxygen 1.5.1