ai4ruby 1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +47 -0
 - data/examples/classifiers/id3_data.csv +121 -0
 - data/examples/classifiers/id3_example.rb +29 -0
 - data/examples/classifiers/naive_bayes_data.csv +11 -0
 - data/examples/classifiers/naive_bayes_example.rb +16 -0
 - data/examples/classifiers/results.txt +31 -0
 - data/examples/genetic_algorithm/genetic_algorithm_example.rb +37 -0
 - data/examples/genetic_algorithm/travel_cost.csv +16 -0
 - data/examples/neural_network/backpropagation_example.rb +67 -0
 - data/examples/neural_network/patterns_with_base_noise.rb +68 -0
 - data/examples/neural_network/patterns_with_noise.rb +66 -0
 - data/examples/neural_network/training_patterns.rb +68 -0
 - data/examples/neural_network/xor_example.rb +35 -0
 - data/examples/som/som_data.rb +156 -0
 - data/examples/som/som_multi_node_example.rb +22 -0
 - data/examples/som/som_single_example.rb +24 -0
 - data/lib/ai4r.rb +33 -0
 - data/lib/ai4r/classifiers/classifier.rb +62 -0
 - data/lib/ai4r/classifiers/hyperpipes.rb +118 -0
 - data/lib/ai4r/classifiers/ib1.rb +121 -0
 - data/lib/ai4r/classifiers/id3.rb +326 -0
 - data/lib/ai4r/classifiers/multilayer_perceptron.rb +135 -0
 - data/lib/ai4r/classifiers/naive_bayes.rb +259 -0
 - data/lib/ai4r/classifiers/one_r.rb +110 -0
 - data/lib/ai4r/classifiers/prism.rb +197 -0
 - data/lib/ai4r/classifiers/zero_r.rb +73 -0
 - data/lib/ai4r/clusterers/average_linkage.rb +59 -0
 - data/lib/ai4r/clusterers/bisecting_k_means.rb +93 -0
 - data/lib/ai4r/clusterers/centroid_linkage.rb +66 -0
 - data/lib/ai4r/clusterers/clusterer.rb +61 -0
 - data/lib/ai4r/clusterers/complete_linkage.rb +67 -0
 - data/lib/ai4r/clusterers/diana.rb +139 -0
 - data/lib/ai4r/clusterers/k_means.rb +126 -0
 - data/lib/ai4r/clusterers/median_linkage.rb +61 -0
 - data/lib/ai4r/clusterers/single_linkage.rb +194 -0
 - data/lib/ai4r/clusterers/ward_linkage.rb +64 -0
 - data/lib/ai4r/clusterers/ward_linkage_hierarchical.rb +31 -0
 - data/lib/ai4r/clusterers/weighted_average_linkage.rb +61 -0
 - data/lib/ai4r/data/data_set.rb +266 -0
 - data/lib/ai4r/data/parameterizable.rb +64 -0
 - data/lib/ai4r/data/proximity.rb +100 -0
 - data/lib/ai4r/data/statistics.rb +77 -0
 - data/lib/ai4r/experiment/classifier_evaluator.rb +95 -0
 - data/lib/ai4r/genetic_algorithm/genetic_algorithm.rb +270 -0
 - data/lib/ai4r/neural_network/backpropagation.rb +326 -0
 - data/lib/ai4r/neural_network/hopfield.rb +149 -0
 - data/lib/ai4r/som/layer.rb +68 -0
 - data/lib/ai4r/som/node.rb +96 -0
 - data/lib/ai4r/som/som.rb +155 -0
 - data/lib/ai4r/som/two_phase_layer.rb +90 -0
 - data/test/classifiers/hyperpipes_test.rb +84 -0
 - data/test/classifiers/ib1_test.rb +78 -0
 - data/test/classifiers/id3_test.rb +208 -0
 - data/test/classifiers/multilayer_perceptron_test.rb +79 -0
 - data/test/classifiers/naive_bayes_test.rb +43 -0
 - data/test/classifiers/one_r_test.rb +62 -0
 - data/test/classifiers/prism_test.rb +85 -0
 - data/test/classifiers/zero_r_test.rb +49 -0
 - data/test/clusterers/average_linkage_test.rb +51 -0
 - data/test/clusterers/bisecting_k_means_test.rb +66 -0
 - data/test/clusterers/centroid_linkage_test.rb +53 -0
 - data/test/clusterers/complete_linkage_test.rb +57 -0
 - data/test/clusterers/diana_test.rb +69 -0
 - data/test/clusterers/k_means_test.rb +100 -0
 - data/test/clusterers/median_linkage_test.rb +53 -0
 - data/test/clusterers/single_linkage_test.rb +122 -0
 - data/test/clusterers/ward_linkage_hierarchical_test.rb +61 -0
 - data/test/clusterers/ward_linkage_test.rb +53 -0
 - data/test/clusterers/weighted_average_linkage_test.rb +53 -0
 - data/test/data/data_set_test.rb +96 -0
 - data/test/data/proximity_test.rb +81 -0
 - data/test/data/statistics_test.rb +65 -0
 - data/test/experiment/classifier_evaluator_test.rb +76 -0
 - data/test/genetic_algorithm/chromosome_test.rb +58 -0
 - data/test/genetic_algorithm/genetic_algorithm_test.rb +81 -0
 - data/test/neural_network/backpropagation_test.rb +82 -0
 - data/test/neural_network/hopfield_test.rb +72 -0
 - data/test/som/som_test.rb +97 -0
 - metadata +168 -0
 
| 
         @@ -0,0 +1,85 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'test/unit'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require File.dirname(__FILE__) + '/../../lib/ai4r/classifiers/prism'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            class PrismTest < Test::Unit::TestCase
         
     | 
| 
      
 6 
     | 
    
         
            +
              
         
     | 
| 
      
 7 
     | 
    
         
            +
              include Ai4r::Classifiers
         
     | 
| 
      
 8 
     | 
    
         
            +
              include Ai4r::Data
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              @@data_examples = [   ['New York',  '<30',      'M', 'Y'],
         
     | 
| 
      
 11 
     | 
    
         
            +
                            ['Chicago',     '<30',      'M', 'Y'],
         
     | 
| 
      
 12 
     | 
    
         
            +
                            ['Chicago',     '<30',      'F', 'Y'],
         
     | 
| 
      
 13 
     | 
    
         
            +
                            ['New York',  '<30',      'M', 'Y'],
         
     | 
| 
      
 14 
     | 
    
         
            +
                            ['New York',  '<30',      'M', 'Y'],
         
     | 
| 
      
 15 
     | 
    
         
            +
                            ['Chicago',     '[30-50)',  'M', 'Y'],
         
     | 
| 
      
 16 
     | 
    
         
            +
                            ['New York',  '[30-50)',  'F', 'N'],
         
     | 
| 
      
 17 
     | 
    
         
            +
                            ['Chicago',     '[30-50)',  'F', 'Y'],
         
     | 
| 
      
 18 
     | 
    
         
            +
                            ['New York',  '[30-50)',  'F', 'N'],
         
     | 
| 
      
 19 
     | 
    
         
            +
                            ['Chicago',     '[50-80]', 'M', 'N'],
         
     | 
| 
      
 20 
     | 
    
         
            +
                            ['New York',  '[50-80]', 'F', 'N'],
         
     | 
| 
      
 21 
     | 
    
         
            +
                            ['New York',  '[50-80]', 'M', 'N'],
         
     | 
| 
      
 22 
     | 
    
         
            +
                            ['Chicago',     '[50-80]', 'M', 'N'],
         
     | 
| 
      
 23 
     | 
    
         
            +
                            ['New York',  '[50-80]', 'F', 'N'],
         
     | 
| 
      
 24 
     | 
    
         
            +
                            ['Chicago',     '>80',      'F', 'Y']
         
     | 
| 
      
 25 
     | 
    
         
            +
                          ]
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              @@data_labels = [ 'city', 'age_range', 'gender', 'marketing_target'  ]
         
     | 
| 
      
 28 
     | 
    
         
            +
              
         
     | 
| 
      
 29 
     | 
    
         
            +
              def test_build
         
     | 
| 
      
 30 
     | 
    
         
            +
                assert_raise(ArgumentError) { Prism.new.build(DataSet.new) } 
         
     | 
| 
      
 31 
     | 
    
         
            +
                classifier = Prism.new.build(DataSet.new(:data_items=>@@data_examples))
         
     | 
| 
      
 32 
     | 
    
         
            +
                assert_not_nil(classifier.data_set.data_labels)
         
     | 
| 
      
 33 
     | 
    
         
            +
                assert_not_nil(classifier.rules)
         
     | 
| 
      
 34 
     | 
    
         
            +
                assert_equal("attribute_1", classifier.data_set.data_labels.first)
         
     | 
| 
      
 35 
     | 
    
         
            +
                assert_equal("class_value", classifier.data_set.data_labels.last)
         
     | 
| 
      
 36 
     | 
    
         
            +
                classifier = Prism.new.build(DataSet.new(:data_items => @@data_examples, 
         
     | 
| 
      
 37 
     | 
    
         
            +
                    :data_labels => @@data_labels))
         
     | 
| 
      
 38 
     | 
    
         
            +
                assert_not_nil(classifier.data_set.data_labels)
         
     | 
| 
      
 39 
     | 
    
         
            +
                assert_not_nil(classifier.rules)
         
     | 
| 
      
 40 
     | 
    
         
            +
                assert_equal("city", classifier.data_set.data_labels.first)
         
     | 
| 
      
 41 
     | 
    
         
            +
                assert_equal("marketing_target", classifier.data_set.data_labels.last)
         
     | 
| 
      
 42 
     | 
    
         
            +
                assert !classifier.rules.empty?
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                Prism.send(:public, *Prism.protected_instance_methods)
         
     | 
| 
      
 45 
     | 
    
         
            +
                Prism.send(:public, *Prism.private_instance_methods)
         
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
              
         
     | 
| 
      
 48 
     | 
    
         
            +
              def test_eval
         
     | 
| 
      
 49 
     | 
    
         
            +
                classifier = Prism.new.build(DataSet.new(:data_items=>@@data_examples))
         
     | 
| 
      
 50 
     | 
    
         
            +
                @@data_examples.each do |data|
         
     | 
| 
      
 51 
     | 
    
         
            +
                  assert_equal(data.last, classifier.eval(data[0...-1]))
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
              end
         
     | 
| 
      
 54 
     | 
    
         
            +
              
         
     | 
| 
      
 55 
     | 
    
         
            +
              def test_get_rules
         
     | 
| 
      
 56 
     | 
    
         
            +
                classifier = Prism.new.build(DataSet.new(:data_items => @@data_examples, 
         
     | 
| 
      
 57 
     | 
    
         
            +
                    :data_labels => @@data_labels))
         
     | 
| 
      
 58 
     | 
    
         
            +
                marketing_target = nil
         
     | 
| 
      
 59 
     | 
    
         
            +
                age_range = nil
         
     | 
| 
      
 60 
     | 
    
         
            +
                city = 'Chicago'
         
     | 
| 
      
 61 
     | 
    
         
            +
                eval(classifier.get_rules) 
         
     | 
| 
      
 62 
     | 
    
         
            +
                age_range = '<30'
         
     | 
| 
      
 63 
     | 
    
         
            +
                eval(classifier.get_rules) 
         
     | 
| 
      
 64 
     | 
    
         
            +
                assert_equal("Y", marketing_target)
         
     | 
| 
      
 65 
     | 
    
         
            +
                age_range = '[30-50)'
         
     | 
| 
      
 66 
     | 
    
         
            +
                eval(classifier.get_rules) 
         
     | 
| 
      
 67 
     | 
    
         
            +
                assert_equal("Y", marketing_target)
         
     | 
| 
      
 68 
     | 
    
         
            +
                age_range = '[30-50)'
         
     | 
| 
      
 69 
     | 
    
         
            +
                city = 'New York'
         
     | 
| 
      
 70 
     | 
    
         
            +
                eval(classifier.get_rules) 
         
     | 
| 
      
 71 
     | 
    
         
            +
                assert_equal("N", marketing_target)
         
     | 
| 
      
 72 
     | 
    
         
            +
                age_range = '[50-80]'
         
     | 
| 
      
 73 
     | 
    
         
            +
                eval(classifier.get_rules) 
         
     | 
| 
      
 74 
     | 
    
         
            +
                assert_equal("N", marketing_target)   
         
     | 
| 
      
 75 
     | 
    
         
            +
              end
         
     | 
| 
      
 76 
     | 
    
         
            +
                
         
     | 
| 
      
 77 
     | 
    
         
            +
              def test_matches_conditions
         
     | 
| 
      
 78 
     | 
    
         
            +
                classifier = Prism.new.build(DataSet.new(:data_labels => @@data_labels,
         
     | 
| 
      
 79 
     | 
    
         
            +
                  :data_items => @@data_examples))
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                assert classifier.matches_conditions(['New York', '<30', 'M', 'Y'], {"age_range" => "<30"})
         
     | 
| 
      
 82 
     | 
    
         
            +
                assert !classifier.matches_conditions(['New York', '<30', 'M', 'Y'], {"age_range" => "[50-80]"})
         
     | 
| 
      
 83 
     | 
    
         
            +
              end
         
     | 
| 
      
 84 
     | 
    
         
            +
            end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,49 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'test/unit'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require File.dirname(__FILE__) + '/../../lib/ai4r/classifiers/zero_r'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require File.dirname(__FILE__) + '/../../lib/ai4r/data/data_set'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            class ZeroRTest < Test::Unit::TestCase
         
     | 
| 
      
 6 
     | 
    
         
            +
              
         
     | 
| 
      
 7 
     | 
    
         
            +
              include Ai4r::Classifiers
         
     | 
| 
      
 8 
     | 
    
         
            +
              include Ai4r::Data
         
     | 
| 
      
 9 
     | 
    
         
            +
              
         
     | 
| 
      
 10 
     | 
    
         
            +
              @@data_examples = [   ['New York',  '<30',      'M', 'Y'],
         
     | 
| 
      
 11 
     | 
    
         
            +
                            ['Chicago',     '<30',      'M', 'Y'],
         
     | 
| 
      
 12 
     | 
    
         
            +
                            ['New York',  '<30',      'M', 'Y'],
         
     | 
| 
      
 13 
     | 
    
         
            +
                            ['New York',  '[30-50)',  'F', 'N'],
         
     | 
| 
      
 14 
     | 
    
         
            +
                            ['Chicago',     '[30-50)',  'F', 'Y'],
         
     | 
| 
      
 15 
     | 
    
         
            +
                            ['New York',  '[30-50)',  'F', 'N'],
         
     | 
| 
      
 16 
     | 
    
         
            +
                            ['Chicago',     '[50-80]', 'M', 'N'],
         
     | 
| 
      
 17 
     | 
    
         
            +
                          ]
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              @@data_labels = [ 'city', 'age_range', 'gender', 'marketing_target'  ]
         
     | 
| 
      
 20 
     | 
    
         
            +
              
         
     | 
| 
      
 21 
     | 
    
         
            +
              def test_build
         
     | 
| 
      
 22 
     | 
    
         
            +
                assert_raise(ArgumentError) { ZeroR.new.build(DataSet.new) } 
         
     | 
| 
      
 23 
     | 
    
         
            +
                classifier = ZeroR.new.build(DataSet.new(:data_items => @@data_examples))
         
     | 
| 
      
 24 
     | 
    
         
            +
                assert_equal("Y", classifier.class_value)
         
     | 
| 
      
 25 
     | 
    
         
            +
                assert_equal("attribute_1", classifier.data_set.data_labels.first)
         
     | 
| 
      
 26 
     | 
    
         
            +
                assert_equal("class_value", classifier.data_set.data_labels.last)
         
     | 
| 
      
 27 
     | 
    
         
            +
                classifier = ZeroR.new.build(DataSet.new(:data_items => @@data_examples, 
         
     | 
| 
      
 28 
     | 
    
         
            +
                    :data_labels => @@data_labels))
         
     | 
| 
      
 29 
     | 
    
         
            +
                assert_equal("Y", classifier.class_value)
         
     | 
| 
      
 30 
     | 
    
         
            +
                assert_equal("city", classifier.data_set.data_labels.first)
         
     | 
| 
      
 31 
     | 
    
         
            +
                assert_equal("marketing_target", classifier.data_set.data_labels.last)
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
              
         
     | 
| 
      
 34 
     | 
    
         
            +
              def test_eval
         
     | 
| 
      
 35 
     | 
    
         
            +
                classifier = ZeroR.new.build(DataSet.new(:data_items => @@data_examples))
         
     | 
| 
      
 36 
     | 
    
         
            +
                assert_equal('Y', classifier.eval(@@data_examples.first) )
         
     | 
| 
      
 37 
     | 
    
         
            +
                assert_equal('Y', classifier.eval(@@data_examples.last) )
         
     | 
| 
      
 38 
     | 
    
         
            +
              end
         
     | 
| 
      
 39 
     | 
    
         
            +
              
         
     | 
| 
      
 40 
     | 
    
         
            +
              def test_get_rules
         
     | 
| 
      
 41 
     | 
    
         
            +
                classifier = ZeroR.new.build(DataSet.new(:data_items => @@data_examples,
         
     | 
| 
      
 42 
     | 
    
         
            +
                  :data_labels => @@data_labels))
         
     | 
| 
      
 43 
     | 
    
         
            +
                marketing_target = nil
         
     | 
| 
      
 44 
     | 
    
         
            +
                eval(classifier.get_rules) 
         
     | 
| 
      
 45 
     | 
    
         
            +
                assert_equal('Y', marketing_target)
         
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
              
         
     | 
| 
      
 48 
     | 
    
         
            +
            end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,51 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Author::    Sergio Fierens (implementation)
         
     | 
| 
      
 2 
     | 
    
         
            +
            # License::   MPL 1.1
         
     | 
| 
      
 3 
     | 
    
         
            +
            # Project::   ai4r
         
     | 
| 
      
 4 
     | 
    
         
            +
            # Url::       http://ai4r.rubyforge.org/
         
     | 
| 
      
 5 
     | 
    
         
            +
            #
         
     | 
| 
      
 6 
     | 
    
         
            +
            # You can redistribute it and/or modify it under the terms of 
         
     | 
| 
      
 7 
     | 
    
         
            +
            # the Mozilla Public License version 1.1  as published by the 
         
     | 
| 
      
 8 
     | 
    
         
            +
            # Mozilla Foundation at http://www.mozilla.org/MPL/MPL-1.1.txt
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            require 'test/unit'
         
     | 
| 
      
 11 
     | 
    
         
            +
            require File.dirname(__FILE__) + '/../../lib/ai4r/clusterers/average_linkage'
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            class Ai4r::Clusterers::AverageLinkage < Ai4r::Clusterers::SingleLinkage
         
     | 
| 
      
 14 
     | 
    
         
            +
              attr_accessor :data_set, :number_of_clusters, :clusters, :distance_matrix
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            class AverageLinkageTest < Test::Unit::TestCase
         
     | 
| 
      
 18 
     | 
    
         
            +
              
         
     | 
| 
      
 19 
     | 
    
         
            +
              include Ai4r::Clusterers
         
     | 
| 
      
 20 
     | 
    
         
            +
              include Ai4r::Data
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              @@data = [  [10, 3], [3, 10], [2, 8], [2, 5], [3, 8], [10, 3],
         
     | 
| 
      
 23 
     | 
    
         
            +
                          [1, 3], [8, 1], [2, 9], [2, 5], [3, 3], [9, 4]]
         
     | 
| 
      
 24 
     | 
    
         
            +
                        
         
     | 
| 
      
 25 
     | 
    
         
            +
              @@expected_distance_matrix = [ 
         
     | 
| 
      
 26 
     | 
    
         
            +
                    [98.0], 
         
     | 
| 
      
 27 
     | 
    
         
            +
                    [89.0, 5.0], 
         
     | 
| 
      
 28 
     | 
    
         
            +
                    [68.0, 26.0, 9.0], 
         
     | 
| 
      
 29 
     | 
    
         
            +
                    [74.0, 4.0, 1.0, 10.0], 
         
     | 
| 
      
 30 
     | 
    
         
            +
                    [0.0, 98.0, 89.0, 68.0, 74.0], 
         
     | 
| 
      
 31 
     | 
    
         
            +
                    [81.0, 53.0, 26.0, 5.0, 29.0, 81.0], 
         
     | 
| 
      
 32 
     | 
    
         
            +
                    [8.0, 106.0, 85.0, 52.0, 74.0, 8.0, 53.0], 
         
     | 
| 
      
 33 
     | 
    
         
            +
                    [100.0, 2.0, 1.0, 16.0, 2.0, 100.0, 37.0, 100.0], 
         
     | 
| 
      
 34 
     | 
    
         
            +
                    [68.0, 26.0, 9.0, 0.0, 10.0, 68.0, 5.0, 52.0, 16.0], 
         
     | 
| 
      
 35 
     | 
    
         
            +
                    [49.0, 49.0, 26.0, 5.0, 25.0, 49.0, 4.0, 29.0, 37.0, 5.0], 
         
     | 
| 
      
 36 
     | 
    
         
            +
                    [2.0, 72.0, 65.0, 50.0, 52.0, 2.0, 65.0, 10.0, 74.0, 50.0, 37.0]]
         
     | 
| 
      
 37 
     | 
    
         
            +
                  
         
     | 
| 
      
 38 
     | 
    
         
            +
               def setup
         
     | 
| 
      
 39 
     | 
    
         
            +
                 Ai4r::Clusterers::AverageLinkage.send(:public, 
         
     | 
| 
      
 40 
     | 
    
         
            +
                   *Ai4r::Clusterers::AverageLinkage.protected_instance_methods)  
         
     | 
| 
      
 41 
     | 
    
         
            +
               end
         
     | 
| 
      
 42 
     | 
    
         
            +
              
         
     | 
| 
      
 43 
     | 
    
         
            +
               def test_linkage_distance
         
     | 
| 
      
 44 
     | 
    
         
            +
                clusterer = Ai4r::Clusterers::AverageLinkage.new
         
     | 
| 
      
 45 
     | 
    
         
            +
                clusterer.distance_matrix = @@expected_distance_matrix
         
     | 
| 
      
 46 
     | 
    
         
            +
                assert_equal 93.5, clusterer.linkage_distance(0,1,2)
         
     | 
| 
      
 47 
     | 
    
         
            +
                assert_equal 37.5, clusterer.linkage_distance(4,2,5)
         
     | 
| 
      
 48 
     | 
    
         
            +
              end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
            end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,66 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Author::    Sergio Fierens (implementation)
         
     | 
| 
      
 2 
     | 
    
         
            +
            # License::   MPL 1.1
         
     | 
| 
      
 3 
     | 
    
         
            +
            # Project::   ai4r
         
     | 
| 
      
 4 
     | 
    
         
            +
            # Url::       http://ai4r.rubyforge.org/
         
     | 
| 
      
 5 
     | 
    
         
            +
            #
         
     | 
| 
      
 6 
     | 
    
         
            +
            # You can redistribute it and/or modify it under the terms of 
         
     | 
| 
      
 7 
     | 
    
         
            +
            # the Mozilla Public License version 1.1  as published by the 
         
     | 
| 
      
 8 
     | 
    
         
            +
            # Mozilla Foundation at http://www.mozilla.org/MPL/MPL-1.1.txt
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            require 'test/unit'
         
     | 
| 
      
 11 
     | 
    
         
            +
            require File.dirname(__FILE__) + '/../../lib/ai4r/clusterers/bisecting_k_means'
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            class BisectingKMeansTest < Test::Unit::TestCase
         
     | 
| 
      
 14 
     | 
    
         
            +
              
         
     | 
| 
      
 15 
     | 
    
         
            +
              include Ai4r::Clusterers
         
     | 
| 
      
 16 
     | 
    
         
            +
              include Ai4r::Data
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              @@data = [  [10, 3], [3, 10], [2, 8], [2, 5], [3, 8], [10, 3],
         
     | 
| 
      
 19 
     | 
    
         
            +
                          [1, 3], [8, 1], [2, 9], [2, 5], [3, 3], [9, 4]]
         
     | 
| 
      
 20 
     | 
    
         
            +
              
         
     | 
| 
      
 21 
     | 
    
         
            +
              def test_build_without_refine
         
     | 
| 
      
 22 
     | 
    
         
            +
                build(false)
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
              
         
     | 
| 
      
 25 
     | 
    
         
            +
              def test_build_with_refine
         
     | 
| 
      
 26 
     | 
    
         
            +
                build(true)
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
              
         
     | 
| 
      
 29 
     | 
    
         
            +
              protected
         
     | 
| 
      
 30 
     | 
    
         
            +
              def build(refine)
         
     | 
| 
      
 31 
     | 
    
         
            +
                data_set = DataSet.new(:data_items => @@data, :data_labels => ["X", "Y"])
         
     | 
| 
      
 32 
     | 
    
         
            +
                clusterer = BisectingKMeans.new
         
     | 
| 
      
 33 
     | 
    
         
            +
                clusterer.set_parameters :refine => refine
         
     | 
| 
      
 34 
     | 
    
         
            +
                clusterer.build(data_set, 4)
         
     | 
| 
      
 35 
     | 
    
         
            +
                #draw_map(clusterer)
         
     | 
| 
      
 36 
     | 
    
         
            +
                # Verify that all 4 clusters are created
         
     | 
| 
      
 37 
     | 
    
         
            +
                assert_equal 4, clusterer.clusters.length
         
     | 
| 
      
 38 
     | 
    
         
            +
                assert_equal 4, clusterer.centroids.length
         
     | 
| 
      
 39 
     | 
    
         
            +
                # The addition of all instances of every cluster must be equal than
         
     | 
| 
      
 40 
     | 
    
         
            +
                # the number of data points
         
     | 
| 
      
 41 
     | 
    
         
            +
                total_length = 0
         
     | 
| 
      
 42 
     | 
    
         
            +
                clusterer.clusters.each do |cluster| 
         
     | 
| 
      
 43 
     | 
    
         
            +
                  total_length += cluster.data_items.length
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
                assert_equal @@data.length, total_length
         
     | 
| 
      
 46 
     | 
    
         
            +
                # Data inside clusters must be the same as orifinal data
         
     | 
| 
      
 47 
     | 
    
         
            +
                clusterer.clusters.each do |cluster| 
         
     | 
| 
      
 48 
     | 
    
         
            +
                 cluster.data_items.each do |data_item|
         
     | 
| 
      
 49 
     | 
    
         
            +
                   assert @@data.include?(data_item)
         
     | 
| 
      
 50 
     | 
    
         
            +
                 end
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
              
         
     | 
| 
      
 54 
     | 
    
         
            +
              private
         
     | 
| 
      
 55 
     | 
    
         
            +
              def draw_map(clusterer)
         
     | 
| 
      
 56 
     | 
    
         
            +
                map = Array.new(11) {Array.new(11, 0)}
         
     | 
| 
      
 57 
     | 
    
         
            +
                clusterer.clusters.each_index do |i|
         
     | 
| 
      
 58 
     | 
    
         
            +
                  clusterer.clusters[i].data_items.each do |point|
         
     | 
| 
      
 59 
     | 
    
         
            +
                    map[point.first][point.last]=(i+1)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
                map.each { |row| puts row.inspect}
         
     | 
| 
      
 63 
     | 
    
         
            +
              end
         
     | 
| 
      
 64 
     | 
    
         
            +
              
         
     | 
| 
      
 65 
     | 
    
         
            +
            end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,53 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Author::    Sergio Fierens (implementation)
         
     | 
| 
      
 2 
     | 
    
         
            +
            # License::   MPL 1.1
         
     | 
| 
      
 3 
     | 
    
         
            +
            # Project::   ai4r
         
     | 
| 
      
 4 
     | 
    
         
            +
            # Url::       http://ai4r.rubyforge.org/
         
     | 
| 
      
 5 
     | 
    
         
            +
            #
         
     | 
| 
      
 6 
     | 
    
         
            +
            # You can redistribute it and/or modify it under the terms of 
         
     | 
| 
      
 7 
     | 
    
         
            +
            # the Mozilla Public License version 1.1  as published by the 
         
     | 
| 
      
 8 
     | 
    
         
            +
            # Mozilla Foundation at http://www.mozilla.org/MPL/MPL-1.1.txt
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            require 'test/unit'
         
     | 
| 
      
 11 
     | 
    
         
            +
            require File.dirname(__FILE__) + '/../../lib/ai4r/clusterers/centroid_linkage'
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            class Ai4r::Clusterers::CentroidLinkage
         
     | 
| 
      
 14 
     | 
    
         
            +
              attr_accessor :data_set, :number_of_clusters, :clusters, :distance_matrix, :index_clusters
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            class Ai4r::Clusterers::CentroidLinkageTest < Test::Unit::TestCase
         
     | 
| 
      
 18 
     | 
    
         
            +
              
         
     | 
| 
      
 19 
     | 
    
         
            +
              include Ai4r::Clusterers
         
     | 
| 
      
 20 
     | 
    
         
            +
              include Ai4r::Data
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              @@data = [  [10, 3], [3, 10], [2, 8], [2, 5], [3, 8], [10, 3],
         
     | 
| 
      
 23 
     | 
    
         
            +
                          [1, 3], [8, 1], [2, 9], [2, 5], [3, 3], [9, 4]]
         
     | 
| 
      
 24 
     | 
    
         
            +
                        
         
     | 
| 
      
 25 
     | 
    
         
            +
              @@expected_distance_matrix = [ 
         
     | 
| 
      
 26 
     | 
    
         
            +
                    [98.0], 
         
     | 
| 
      
 27 
     | 
    
         
            +
                    [89.0, 5.0], 
         
     | 
| 
      
 28 
     | 
    
         
            +
                    [68.0, 26.0, 9.0], 
         
     | 
| 
      
 29 
     | 
    
         
            +
                    [74.0, 4.0, 1.0, 10.0], 
         
     | 
| 
      
 30 
     | 
    
         
            +
                    [0.0, 98.0, 89.0, 68.0, 74.0], 
         
     | 
| 
      
 31 
     | 
    
         
            +
                    [81.0, 53.0, 26.0, 5.0, 29.0, 81.0], 
         
     | 
| 
      
 32 
     | 
    
         
            +
                    [8.0, 106.0, 85.0, 52.0, 74.0, 8.0, 53.0], 
         
     | 
| 
      
 33 
     | 
    
         
            +
                    [100.0, 2.0, 1.0, 16.0, 2.0, 100.0, 37.0, 100.0], 
         
     | 
| 
      
 34 
     | 
    
         
            +
                    [68.0, 26.0, 9.0, 0.0, 10.0, 68.0, 5.0, 52.0, 16.0], 
         
     | 
| 
      
 35 
     | 
    
         
            +
                    [49.0, 49.0, 26.0, 5.0, 25.0, 49.0, 4.0, 29.0, 37.0, 5.0], 
         
     | 
| 
      
 36 
     | 
    
         
            +
                    [2.0, 72.0, 65.0, 50.0, 52.0, 2.0, 65.0, 10.0, 74.0, 50.0, 37.0]]
         
     | 
| 
      
 37 
     | 
    
         
            +
              
         
     | 
| 
      
 38 
     | 
    
         
            +
               def setup
         
     | 
| 
      
 39 
     | 
    
         
            +
                 Ai4r::Clusterers::CentroidLinkage.send(:public, 
         
     | 
| 
      
 40 
     | 
    
         
            +
                   *Ai4r::Clusterers::CentroidLinkage.protected_instance_methods)  
         
     | 
| 
      
 41 
     | 
    
         
            +
               end
         
     | 
| 
      
 42 
     | 
    
         
            +
              
         
     | 
| 
      
 43 
     | 
    
         
            +
               def test_linkage_distance
         
     | 
| 
      
 44 
     | 
    
         
            +
                clusterer = Ai4r::Clusterers::CentroidLinkage.new
         
     | 
| 
      
 45 
     | 
    
         
            +
                clusterer.data_set = DataSet.new :data_items => @@data
         
     | 
| 
      
 46 
     | 
    
         
            +
                clusterer.index_clusters = clusterer.create_initial_index_clusters
         
     | 
| 
      
 47 
     | 
    
         
            +
                clusterer.distance_matrix = @@expected_distance_matrix
         
     | 
| 
      
 48 
     | 
    
         
            +
                assert_equal 92.25, clusterer.linkage_distance(0,1,2)
         
     | 
| 
      
 49 
     | 
    
         
            +
                assert_equal 15.25, clusterer.linkage_distance(4,2,5)
         
     | 
| 
      
 50 
     | 
    
         
            +
              end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
            end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,57 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Author::    Sergio Fierens (implementation)
         
     | 
| 
      
 2 
     | 
    
         
            +
            # License::   MPL 1.1
         
     | 
| 
      
 3 
     | 
    
         
            +
            # Project::   ai4r
         
     | 
| 
      
 4 
     | 
    
         
            +
            # Url::       http://ai4r.rubyforge.org/
         
     | 
| 
      
 5 
     | 
    
         
            +
            #
         
     | 
| 
      
 6 
     | 
    
         
            +
            # You can redistribute it and/or modify it under the terms of 
         
     | 
| 
      
 7 
     | 
    
         
            +
            # the Mozilla Public License version 1.1  as published by the 
         
     | 
| 
      
 8 
     | 
    
         
            +
            # Mozilla Foundation at http://www.mozilla.org/MPL/MPL-1.1.txt
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            require 'test/unit'
         
     | 
| 
      
 11 
     | 
    
         
            +
            require File.dirname(__FILE__) + '/../../lib/ai4r/clusterers/complete_linkage'
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            class Ai4r::Clusterers::CompleteLinkage
         
     | 
| 
      
 14 
     | 
    
         
            +
              attr_accessor :data_set, :number_of_clusters, :clusters, :distance_matrix
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            class CompleteLinkageTest < Test::Unit::TestCase
         
     | 
| 
      
 18 
     | 
    
         
            +
              
         
     | 
| 
      
 19 
     | 
    
         
            +
              include Ai4r::Clusterers
         
     | 
| 
      
 20 
     | 
    
         
            +
              include Ai4r::Data
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              @@data = [  [10, 3], [3, 10], [2, 8], [2, 5], [3, 8], [10, 3],
         
     | 
| 
      
 23 
     | 
    
         
            +
                          [1, 3], [8, 1], [2, 9], [2, 5], [3, 3], [9, 4]]
         
     | 
| 
      
 24 
     | 
    
         
            +
                        
         
     | 
| 
      
 25 
     | 
    
         
            +
              @@expected_distance_matrix = [ 
         
     | 
| 
      
 26 
     | 
    
         
            +
                    [98.0], 
         
     | 
| 
      
 27 
     | 
    
         
            +
                    [89.0, 5.0], 
         
     | 
| 
      
 28 
     | 
    
         
            +
                    [68.0, 26.0, 9.0], 
         
     | 
| 
      
 29 
     | 
    
         
            +
                    [74.0, 4.0, 1.0, 10.0], 
         
     | 
| 
      
 30 
     | 
    
         
            +
                    [0.0, 98.0, 89.0, 68.0, 74.0], 
         
     | 
| 
      
 31 
     | 
    
         
            +
                    [81.0, 53.0, 26.0, 5.0, 29.0, 81.0], 
         
     | 
| 
      
 32 
     | 
    
         
            +
                    [8.0, 106.0, 85.0, 52.0, 74.0, 8.0, 53.0], 
         
     | 
| 
      
 33 
     | 
    
         
            +
                    [100.0, 2.0, 1.0, 16.0, 2.0, 100.0, 37.0, 100.0], 
         
     | 
| 
      
 34 
     | 
    
         
            +
                    [68.0, 26.0, 9.0, 0.0, 10.0, 68.0, 5.0, 52.0, 16.0], 
         
     | 
| 
      
 35 
     | 
    
         
            +
                    [49.0, 49.0, 26.0, 5.0, 25.0, 49.0, 4.0, 29.0, 37.0, 5.0], 
         
     | 
| 
      
 36 
     | 
    
         
            +
                    [2.0, 72.0, 65.0, 50.0, 52.0, 2.0, 65.0, 10.0, 74.0, 50.0, 37.0]]
         
     | 
| 
      
 37 
     | 
    
         
            +
                  
         
     | 
| 
      
 38 
     | 
    
         
            +
               def setup
         
     | 
| 
      
 39 
     | 
    
         
            +
                 Ai4r::Clusterers::CompleteLinkage.send(:public, 
         
     | 
| 
      
 40 
     | 
    
         
            +
                   *Ai4r::Clusterers::CompleteLinkage.protected_instance_methods)  
         
     | 
| 
      
 41 
     | 
    
         
            +
               end
         
     | 
| 
      
 42 
     | 
    
         
            +
              
         
     | 
| 
      
 43 
     | 
    
         
            +
               def test_linkage_distance
         
     | 
| 
      
 44 
     | 
    
         
            +
                clusterer = Ai4r::Clusterers::CompleteLinkage.new
         
     | 
| 
      
 45 
     | 
    
         
            +
                clusterer.distance_matrix = @@expected_distance_matrix
         
     | 
| 
      
 46 
     | 
    
         
            +
                assert_equal 98, clusterer.linkage_distance(0,1,2)
         
     | 
| 
      
 47 
     | 
    
         
            +
                assert_equal 74, clusterer.linkage_distance(4,2,5)
         
     | 
| 
      
 48 
     | 
    
         
            +
              end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
              def test_distance_between_item_and_cluster
         
     | 
| 
      
 51 
     | 
    
         
            +
                clusterer = CompleteLinkage.new
         
     | 
| 
      
 52 
     | 
    
         
            +
                assert_equal 32.0, clusterer.distance_between_item_and_cluster([1,2], 
         
     | 
| 
      
 53 
     | 
    
         
            +
                  DataSet.new(:data_items => [[3,4],[5,6]]))
         
     | 
| 
      
 54 
     | 
    
         
            +
              end
         
     | 
| 
      
 55 
     | 
    
         
            +
              
         
     | 
| 
      
 56 
     | 
    
         
            +
            end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,69 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Author::    Sergio Fierens (implementation)
         
     | 
| 
      
 2 
     | 
    
         
            +
            # License::   MPL 1.1
         
     | 
| 
      
 3 
     | 
    
         
            +
            # Project::   ai4r
         
     | 
| 
      
 4 
     | 
    
         
            +
            # Url::       http://ai4r.rubyforge.org/
         
     | 
| 
      
 5 
     | 
    
         
            +
            #
         
     | 
| 
      
 6 
     | 
    
         
            +
            # You can redistribute it and/or modify it under the terms of 
         
     | 
| 
      
 7 
     | 
    
         
            +
            # the Mozilla Public License version 1.1  as published by the 
         
     | 
| 
      
 8 
     | 
    
         
            +
            # Mozilla Foundation at http://www.mozilla.org/MPL/MPL-1.1.txt
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            require 'test/unit'
         
     | 
| 
      
 11 
     | 
    
         
            +
            require File.dirname(__FILE__) + '/../../lib/ai4r/clusterers/diana'
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            class Ai4r::Clusterers::Diana
         
     | 
| 
      
 14 
     | 
    
         
            +
              attr_accessor :data_set, :number_of_clusters, :clusters
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            class DianaTest < Test::Unit::TestCase
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              @@data = [  [10, 3], [3, 10], [2, 8], [2, 5], [3, 8], [10, 3],
         
     | 
| 
      
 20 
     | 
    
         
            +
                          [1, 3], [8, 1], [2, 9], [2, 5], [3, 3], [9, 4]]
         
     | 
| 
      
 21 
     | 
    
         
            +
                          
         
     | 
| 
      
 22 
     | 
    
         
            +
              include Ai4r::Clusterers
         
     | 
| 
      
 23 
     | 
    
         
            +
              include Ai4r::Data
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              def setup
         
     | 
| 
      
 26 
     | 
    
         
            +
                Diana.send(:public, *Diana.protected_instance_methods)
         
     | 
| 
      
 27 
     | 
    
         
            +
                @data_set = DataSet.new(:data_items => @@data.clone)
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
                      
         
     | 
| 
      
 30 
     | 
    
         
            +
              def test_build
         
     | 
| 
      
 31 
     | 
    
         
            +
                clusterer = Diana.new.build(@data_set, 4)
         
     | 
| 
      
 32 
     | 
    
         
            +
                assert_equal 4, clusterer.clusters.length
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
              
         
     | 
| 
      
 35 
     | 
    
         
            +
              def test_eval
         
     | 
| 
      
 36 
     | 
    
         
            +
                clusterer = Diana.new.build(@data_set, 4)
         
     | 
| 
      
 37 
     | 
    
         
            +
                assert_equal 0, clusterer.eval([0, 0])
         
     | 
| 
      
 38 
     | 
    
         
            +
                assert_equal 1, clusterer.eval([9, 3])
         
     | 
| 
      
 39 
     | 
    
         
            +
                assert_equal 2, clusterer.eval([0,10])
         
     | 
| 
      
 40 
     | 
    
         
            +
                assert_equal 3, clusterer.eval([8, 0])
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
              
         
     | 
| 
      
 43 
     | 
    
         
            +
              def test_cluster_diameter
         
     | 
| 
      
 44 
     | 
    
         
            +
                clusterer = Diana.new
         
     | 
| 
      
 45 
     | 
    
         
            +
                assert_equal 106, clusterer.cluster_diameter(@data_set)
         
     | 
| 
      
 46 
     | 
    
         
            +
                assert_equal 98, clusterer.cluster_diameter(@data_set[0..2])
         
     | 
| 
      
 47 
     | 
    
         
            +
              end
         
     | 
| 
      
 48 
     | 
    
         
            +
              
         
     | 
| 
      
 49 
     | 
    
         
            +
              def test_max_diameter_cluster
         
     | 
| 
      
 50 
     | 
    
         
            +
                clusterer = Diana.new
         
     | 
| 
      
 51 
     | 
    
         
            +
                assert_equal 0, clusterer.max_diameter_cluster([@data_set, @data_set[0..2]])
         
     | 
| 
      
 52 
     | 
    
         
            +
                assert_equal 1, clusterer.max_diameter_cluster([@data_set[0..2], @data_set])
         
     | 
| 
      
 53 
     | 
    
         
            +
              end 
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
              def test_init_splinter_cluster
         
     | 
| 
      
 56 
     | 
    
         
            +
                clusterer = Diana.new 
         
     | 
| 
      
 57 
     | 
    
         
            +
                assert_equal [10,3], clusterer.
         
     | 
| 
      
 58 
     | 
    
         
            +
                  init_splinter_cluster(@data_set).data_items[0]
         
     | 
| 
      
 59 
     | 
    
         
            +
              end
         
     | 
| 
      
 60 
     | 
    
         
            +
              
         
     | 
| 
      
 61 
     | 
    
         
            +
              def test_max_distance_difference
         
     | 
| 
      
 62 
     | 
    
         
            +
                clusterer = Diana.new 
         
     | 
| 
      
 63 
     | 
    
         
            +
                data_set_a = @data_set[1..-1]
         
     | 
| 
      
 64 
     | 
    
         
            +
                data_set_b = @data_set[0]
         
     | 
| 
      
 65 
     | 
    
         
            +
                assert_equal [63.7, 4], clusterer.
         
     | 
| 
      
 66 
     | 
    
         
            +
                  max_distance_difference(data_set_a, data_set_b)
         
     | 
| 
      
 67 
     | 
    
         
            +
              end
         
     | 
| 
      
 68 
     | 
    
         
            +
              
         
     | 
| 
      
 69 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,100 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Author::    Sergio Fierens (implementation)
         
     | 
| 
      
 2 
     | 
    
         
            +
            # License::   MPL 1.1
         
     | 
| 
      
 3 
     | 
    
         
            +
            # Project::   ai4r
         
     | 
| 
      
 4 
     | 
    
         
            +
            # Url::       http://ai4r.rubyforge.org/
         
     | 
| 
      
 5 
     | 
    
         
            +
            #
         
     | 
| 
      
 6 
     | 
    
         
            +
            # You can redistribute it and/or modify it under the terms of 
         
     | 
| 
      
 7 
     | 
    
         
            +
            # the Mozilla Public License version 1.1  as published by the 
         
     | 
| 
      
 8 
     | 
    
         
            +
            # Mozilla Foundation at http://www.mozilla.org/MPL/MPL-1.1.txt
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            require 'test/unit'
         
     | 
| 
      
 11 
     | 
    
         
            +
            require File.dirname(__FILE__) + '/../../lib/ai4r/clusterers/k_means'
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            class KMeansTest < Test::Unit::TestCase
         
     | 
| 
      
 14 
     | 
    
         
            +
              
         
     | 
| 
      
 15 
     | 
    
         
            +
              include Ai4r::Clusterers
         
     | 
| 
      
 16 
     | 
    
         
            +
              include Ai4r::Data
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              @@data = [  [10, 3], [3, 10], [2, 8], [2, 5], [3, 8], [10, 3],
         
     | 
| 
      
 19 
     | 
    
         
            +
                          [1, 3], [8, 1], [2, 9], [2, 5], [3, 3], [9, 4]]
         
     | 
| 
      
 20 
     | 
    
         
            +
              
         
     | 
| 
      
 21 
     | 
    
         
            +
              def test_build
         
     | 
| 
      
 22 
     | 
    
         
            +
                data_set = DataSet.new(:data_items => @@data, :data_labels => ["X", "Y"])
         
     | 
| 
      
 23 
     | 
    
         
            +
                clusterer = KMeans.new.build(data_set, 4)
         
     | 
| 
      
 24 
     | 
    
         
            +
                #draw_map(clusterer)
         
     | 
| 
      
 25 
     | 
    
         
            +
                # Verify that all 4 clusters are created
         
     | 
| 
      
 26 
     | 
    
         
            +
                assert_equal 4, clusterer.clusters.length
         
     | 
| 
      
 27 
     | 
    
         
            +
                assert_equal 4, clusterer.centroids.length
         
     | 
| 
      
 28 
     | 
    
         
            +
                # The addition of all instances of every cluster must be equal than
         
     | 
| 
      
 29 
     | 
    
         
            +
                # the number of data points
         
     | 
| 
      
 30 
     | 
    
         
            +
                total_length = 0
         
     | 
| 
      
 31 
     | 
    
         
            +
                clusterer.clusters.each do |cluster| 
         
     | 
| 
      
 32 
     | 
    
         
            +
                  total_length += cluster.data_items.length
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
                assert_equal @@data.length, total_length
         
     | 
| 
      
 35 
     | 
    
         
            +
                # Data inside clusters must be the same as orifinal data
         
     | 
| 
      
 36 
     | 
    
         
            +
                clusterer.clusters.each do |cluster| 
         
     | 
| 
      
 37 
     | 
    
         
            +
                 cluster.data_items.each do |data_item|
         
     | 
| 
      
 38 
     | 
    
         
            +
                   assert @@data.include?(data_item)
         
     | 
| 
      
 39 
     | 
    
         
            +
                 end
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
              
         
     | 
| 
      
 43 
     | 
    
         
            +
              def test_eval
         
     | 
| 
      
 44 
     | 
    
         
            +
                data_set = DataSet.new(:data_items => @@data, :data_labels => ["X", "Y"])
         
     | 
| 
      
 45 
     | 
    
         
            +
                clusterer = KMeans.new.build(data_set, 4)
         
     | 
| 
      
 46 
     | 
    
         
            +
                item = [10,0]
         
     | 
| 
      
 47 
     | 
    
         
            +
                cluster_index = clusterer.eval(item)
         
     | 
| 
      
 48 
     | 
    
         
            +
                # Must return a valid cluster index [0-3]
         
     | 
| 
      
 49 
     | 
    
         
            +
                assert cluster_index >= 0 && cluster_index < 4
         
     | 
| 
      
 50 
     | 
    
         
            +
                # Distance to cluster centroid must be less than distance to any other
         
     | 
| 
      
 51 
     | 
    
         
            +
                # centroid
         
     | 
| 
      
 52 
     | 
    
         
            +
                min_distance = clusterer.distance(clusterer.centroids[cluster_index], item)
         
     | 
| 
      
 53 
     | 
    
         
            +
                clusterer.centroids.each do |centroid|
         
     | 
| 
      
 54 
     | 
    
         
            +
                  assert clusterer.distance(centroid, item) >= min_distance
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
              end
         
     | 
| 
      
 57 
     | 
    
         
            +
              
         
     | 
| 
      
 58 
     | 
    
         
            +
              def test_distance
         
     | 
| 
      
 59 
     | 
    
         
            +
                clusterer = KMeans.new
         
     | 
| 
      
 60 
     | 
    
         
            +
                # By default, distance returns the eucledian distance to the power of 2
         
     | 
| 
      
 61 
     | 
    
         
            +
                assert_equal 2385, clusterer.distance(
         
     | 
| 
      
 62 
     | 
    
         
            +
                  [1, 10, "Chicago", 2], 
         
     | 
| 
      
 63 
     | 
    
         
            +
                  [10, 10, "London", 50])
         
     | 
| 
      
 64 
     | 
    
         
            +
                # Test new distance definition
         
     | 
| 
      
 65 
     | 
    
         
            +
                manhattan_distance = lambda do |a, b| 
         
     | 
| 
      
 66 
     | 
    
         
            +
                    dist = 0.0
         
     | 
| 
      
 67 
     | 
    
         
            +
                    a.each_index do |index|
         
     | 
| 
      
 68 
     | 
    
         
            +
                      if a[index].is_a?(Numeric) && b[index].is_a?(Numeric)
         
     | 
| 
      
 69 
     | 
    
         
            +
                        dist = dist + (a[index]-b[index]).abs
         
     | 
| 
      
 70 
     | 
    
         
            +
                      end
         
     | 
| 
      
 71 
     | 
    
         
            +
                    end
         
     | 
| 
      
 72 
     | 
    
         
            +
                    dist
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
                clusterer.set_parameters({:distance_function => manhattan_distance})
         
     | 
| 
      
 75 
     | 
    
         
            +
                assert_equal 57, clusterer.distance(
         
     | 
| 
      
 76 
     | 
    
         
            +
                  [1, 10, "Chicago", 2], 
         
     | 
| 
      
 77 
     | 
    
         
            +
                  [10, 10, "London", 50])
         
     | 
| 
      
 78 
     | 
    
         
            +
              end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
              def test_max_iterations
         
     | 
| 
      
 81 
     | 
    
         
            +
                data_set = DataSet.new(:data_items => @@data, :data_labels => ["X", "Y"])
         
     | 
| 
      
 82 
     | 
    
         
            +
                clusterer = KMeans.new.
         
     | 
| 
      
 83 
     | 
    
         
            +
                  set_parameters({:max_iterations=>1}).
         
     | 
| 
      
 84 
     | 
    
         
            +
                  build(data_set, 4)
         
     | 
| 
      
 85 
     | 
    
         
            +
                assert_equal 1, clusterer.iterations
         
     | 
| 
      
 86 
     | 
    
         
            +
              end
         
     | 
| 
      
 87 
     | 
    
         
            +
              
         
     | 
| 
      
 88 
     | 
    
         
            +
              private
         
     | 
| 
      
 89 
     | 
    
         
            +
              def draw_map(clusterer)
         
     | 
| 
      
 90 
     | 
    
         
            +
                map = Array.new(11) {Array.new(11, 0)}
         
     | 
| 
      
 91 
     | 
    
         
            +
                clusterer.clusters.each_index do |i|
         
     | 
| 
      
 92 
     | 
    
         
            +
                  clusterer.clusters[i].data_items.each do |point|
         
     | 
| 
      
 93 
     | 
    
         
            +
                    map[point.first][point.last]=(i+1)
         
     | 
| 
      
 94 
     | 
    
         
            +
                  end
         
     | 
| 
      
 95 
     | 
    
         
            +
                end
         
     | 
| 
      
 96 
     | 
    
         
            +
                map.each { |row| puts row.inspect}
         
     | 
| 
      
 97 
     | 
    
         
            +
              end
         
     | 
| 
      
 98 
     | 
    
         
            +
              
         
     | 
| 
      
 99 
     | 
    
         
            +
            end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     |