File: update_cluster_membership.m

package info (click to toggle)
octave-fuzzy-logic-toolkit 0.6.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,024 kB
  • sloc: makefile: 147
file content (144 lines) | stat: -rw-r--r-- 5,000 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
## Copyright (C) 2011-2025 L. Markowsky <lmarkowsky@gmail.com>
##
## This file is part of the fuzzy-logic-toolkit.
##
## The fuzzy-logic-toolkit 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 3 of
## the License, or (at your option) any later version.
##
## The fuzzy-logic-toolkit 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 the fuzzy-logic-toolkit; see the file COPYING.  If not,
## see <http://www.gnu.org/licenses/>.

## -*- texinfo -*-
## @deftypefn {Function File} {@var{Mu} =} update_cluster_membership (@var{V}, @var{X}, @var{m}, @var{k}, @var{n}, @var{sqr_dist})
##
## Compute Mu for each (cluster center, input point) pair.
##
## @seealso{fcm, gustafson_kessel, init_cluster_prototypes, update_cluster_prototypes, compute_cluster_obj_fcn, compute_cluster_convergence}
##
## @end deftypefn

## Authors:       Tony Trew, L. Markowsky
## Keywords:      fuzzy-logic-toolkit fuzzy partition clustering
## Directory:     fuzzy-logic-toolkit/inst/private/
## Filename:      update_cluster_membership.m
## Last-Modified: 5 Jun 2024

##----------------------------------------------------------------------
## Note:     This function is an implementation of Equation 13.4 in
##           Fuzzy Logic: Intelligence, Control and Information, by
##           J. Yen and R. Langari, Prentice Hall, 1999, page 380
##           (International Edition) and Step 3 of Algorithm 4.1 in
##           Fuzzy and Neural Control, by Robert Babuska, November 2009,
##           p. 63.
##----------------------------------------------------------------------

function Mu = update_cluster_membership (V, X, m, k, n, sqr_dist)

  sqr_dist_zeros = (sqr_dist == 0);
  num_zeros = sum (sum (sqr_dist_zeros));

  if (num_zeros == 0)
    exponent = 1.0 / (m - 1);
    summation = (sqr_dist ./ sum(sqr_dist)).^exponent;

    if (all (all (summation != 0)))
      Mu = 1.0 ./ summation;
      Mu ./= sum (Mu);
    else
      error ("division by 0 in update_cluster_membership'\n");
    endif

  else
    Mu = sqr_dist_zeros / num_zeros;

  endif

endfunction

%!test
%!  ## Test the vectorized version of this function (above) by comparing its
%!  ## output with the output of the previous, nested-for-loop version (below).
%!  ##
%!  ## The test is run 100 times (but is reported by the Octave interpreter as
%!  ## "1 test"). In each of the 100 test runs, the vectorized and loop versions
%!  ## of the function are called using randomly generated matrices X, V.
%!  ##
%!  ## The sizes of X and V, however, aren't random: X has 100 rows, 8 cols,
%!  ## and V has 5 rows, 8 cols. That is, the entries in X and V are random
%!  ## values in the range [0, 1], but the sizes of X and V are hard-coded.
%!  ##
%!  ## The test is passed if all entries of the two results differ by less than
%!  ## a tolerance of 10e-9 in all 100 test runs.
%!  
%!  function Mu = update_cluster_membership_using_for_loops (V, X, m, k, n, sqr_dist)
%!
%!    Mu = zeros (k, n);
%!
%!    if (min (min (sqr_dist)) > 0)
%!      exponent = 1.0 / (m - 1);
%!      for i = 1 : k
%!        for j = 1 : n
%!          summation = 0.0;
%!          for l = 1 : k
%!            summation += (sqr_dist(i, j) / sqr_dist(l, j))^exponent;
%!          endfor
%!          if (summation != 0)
%!            Mu(i, j) = 1.0 / summation;
%!          else
%!            error ("division by 0 in update_cluster_membership'\n");
%!          endif
%!        endfor
%!      endfor
%!
%!    else
%!      num_zeros = 0;
%!      for i = 1 : k
%!        for j = 1 : n
%!          if (sqr_dist(i, j) == 0)
%!            num_zeros++;
%!            Mu(i, j) = 1.0;
%!          endif
%!        endfor
%!      endfor
%!      Mu = Mu / num_zeros;
%!    endif
%!
%!  endfunction
%!
%!  ## Fixed array sizes, exponent, and tolerance for the test.
%!
%!  n = 100;
%!  f = 8;
%!  k = 5;
%!  m = 2;
%!  tolerance = 10e-9;
%!
%!  ## Run the test 100 times, in a loop. In the last 5 test runs, make 3 of
%!  ## the data points in X identical to cluster centers in V in order to test
%!  ## the else case in the function. 
%!
%!  ## Each test run is successful if the vectorized and nested-for-loop
%!  ## version of the function produce results within the hard-coded tolerance.
%!
%!  for i = 1 : 100
%!    X = rand (n, f);
%!    V = rand (k, f);
%!
%!    if (i > 95)
%!      X(1:3) = V(1:3);
%!    endif
%!
%!    sqr_dist = square_distance_matrix (X, V);
%!    vec_result = update_cluster_membership (V, X, m, k, n, sqr_dist);
%!    loop_result = update_cluster_membership_using_for_loops (V, X, m, k, n, sqr_dist);
%!    assert (abs (vec_result - loop_result) < tolerance)
%!  endfor