On Wed, Nov 12, 2008 at 6:32 PM, Francesco Potortì <[EMAIL PROTECTED]> wrote:
>>a nice job (I wanted this function several times).
>
> If you use it, and especially if you have the possibility of making
> further checks against Matlab's behaviour, please let me know, or just
> correct it.  I have not uploaded it yet, going home now.  Hope tomorrow.
>
>>I have two comments:
>>1. I think that instead of
>>if (...)
>>  switch ...
>>   case ...
>>     return
>>   case ...
>>     return
>>endif
>>
>>...code...
>>
>>you should use
>>if (...)
>>  switch ...
>>   case ...
>>   case ...
>>else
>> ...code...
>>endif
>>
>>I.e., no return in each case. This is more consistent with our
>>recommended coding style, where we try to minimize the number of exit
>>points from a function.
>
> I tried several alternatives, at last this one seemed the less ugly.  In
> fact, we have three cases for funcname: either one of the eleven known
> strings, or a function name string, or a function name handle.  The
> latter two are treated the same way using feval.  This way, the program
> flow is straightforward, I have no code duplication, and all the return
> statements are at the end of a case label, i.e., they are not scattered
> through the code, which is what makes maintenance difficult.  And
> unfortunately I cannot manage the function handle case into the
> otherwise label of switch, because switch barfs when comparing a
> function handle to a string.
>
> Mmmh.  I could avoid the return statementes and check for the function
> return value having been assigned at the end of the switch...
>

I was thinking about this:

 if (ischar (distfun))
   order = nchoosek(1:rows(x),2);
   Xi = order(:,1);
   Yi = order(:,2);
   X = x';
   y = feval (["pdist_" distfun], x', Xi, Yi, varargin{:});
   switch (distfun)
     case "euclidean"
       diff = X(:,Xi) - X(:,Yi);
       d = sqrt (sumsq (diff));
     case "seuclidean"
       diff = X(:,Xi) - X(:,Yi);
       weights = inv (diag (var (X')));
       d = sqrt (sum ((weights * diff) .* diff));
     case "mahalanobis"
       diff = X(:,Xi) - X(:,Yi);
       weights = inv (cov (X'));
       d = sqrt (sum ((weights * diff) .* diff));
     case "cityblock"
       diff = X(:,Xi) - X(:,Yi);
       d = sum (abs (diff));
     case "minkowski"
       diff = X(:,Xi) - X(:,Yi);
       if (nargin > 2)
         p = varargin{1};
         d = (sum ((abs (diff)).^p)).^(1/p);
       else
         d = sqrt (sumsq (diff)); # default p=2
       endif
     case "cosine"
       prod = X(:,Xi) .* X(:,Yi);
       weights = sumsq (X(:,Xi)) .* sumsq (X(:,Yi));
       d = 1 - sum (prod) ./ sqrt (weights);
     case "correlation"
       corr = cor (X);
       d = 1 - corr (sub2ind (size (corr), Xi, Yi))';
     case "spearman"
       corr = spearman (X);
       d = 1 - corr (sub2ind (size (corr), Xi, Yi))';
     case "hamming"
       diff = logical (X(:,Xi) - X(:,Yi));
       d = sum (diff) / rows (X);
     case "jaccard"
       diff = logical (X(:,Xi) - X(:,Yi));
       weights = X(:,Xi) | X(:,Yi);
       d = sum (diff & weights) ./ sum (weights);
     case "chebychev"
       diff = X(:,Xi) - X(:,Yi);
       d = max (abs (diff));
   endswitch
 else

   ## Distfun is a function handle or the name of an external function
    l = rows (x);
   y = zeros (1, nchoosek (l, 2))
   idx = 1;
   for ii = 1:l-1
     for jj = ii+1:l
       y(idx++) = feval (distfun, x(ii,:), x, varargin{:})(jj);
     endfor
   endfor
 endif

I don't see any problem here. Am I missing something? Note that in
Octave, switch cases are exclusive (they don't fall through).

>>2. The changeset http://hg.savannah.gnu.org/hgweb/octave/rev/b11c31849b44
>>equipped `norm' with the ability to compute column or row norms of a matrix.
>>This can be used to your explicit norm expressions like
>>`sqrt (sumsq (diff))' or `(sum ((abs (diff)).^p)).^(1/p)'
>>by
>>`norm (diff, 'cols')' or `norm (diff, p, 'cols')', respectively.
>
> Thank you, I will look into those.
>
>>Similarly for the 1- and Inf- norm.
>>Using the latter will probably be faster (avoids temporary matrices)
>>and will also be robust w.r.t. overflow (i.e. the 20-norm of numbers
>>of order 1e20 won't be Inf).
>
> Sorry, I do not follow you here.  What are the 1- and Inf- norms, and
> what is their relationship with pdist?
The minkowski 1- and Inf- norms are related to cityblock and
mahalanobis distance, i.e. for a matrix diff,
`sum (abs (diff))' is `norm (diff, 1, 'cols')'.
`max (abs (diff))' is `norm (diff, Inf, 'cols')'.


>
>>This is going to be a feature of 3.2.0, so if you're fine with pdist
>>depending on 3.2.0, I think you may exploit it.
>
> Maybe I can write commented code, to be uncommented out later on, when
> 3.2 becomes widespread.

Alternatively, you can check `ver' and use the new code if ver is >=
3.2.0, or you can even check directly for the feature using `try'. The
advantage is that you will actually get the new functionality. The old
code may be removed at some point in the future. Your choice, of
course.

regards

-- 
RNDr. Jaroslav Hajek
computing expert
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Octave-dev mailing list
Octave-dev@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/octave-dev

Reply via email to