1 /* 2 Copyright (c) 2005-2020 Intel Corporation 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 // 18 // Self-organizing map 19 // 20 // support for self-ordering maps 21 #ifndef __SOM_H__ 22 #define __SOM_H__ 23 24 #include <vector> 25 #include <cstdlib> 26 #include <cmath> 27 #include <cfloat> 28 #include <iostream> 29 #include <cstdio> 30 31 #include "tbb/flow_graph.h" 32 #include "tbb/blocked_range2d.h" 33 34 using namespace tbb; 35 using namespace tbb::flow; 36 37 typedef blocked_range2d<int> subsquare_type; 38 typedef tuple<double,int,int> search_result_type; 39 40 std::ostream& operator<<( std::ostream &out, const search_result_type &s); 41 42 #define RADIUS 0 // for the std::gets 43 #define XV 1 44 #define YV 2 45 46 // to have single definitions of static variables, define _MAIN_C_ in the main program 47 // 48 #ifdef _MAIN_C_ 49 #define DEFINE // nothing 50 #define INIT(n) = n 51 #else // not in main file 52 #define DEFINE extern 53 #define INIT(n) // nothing 54 #endif // _MAIN_C_ 55 56 DEFINE int nElements INIT(3); // length of input vectors, matching vector in map 57 DEFINE double max_learning_rate INIT(0.8); // decays exponentially 58 DEFINE double radius_decay_rate; 59 DEFINE double learning_decay_rate INIT(0.005); 60 DEFINE double max_radius; 61 DEFINE bool extra_debug INIT(false); 62 DEFINE bool cancel_test INIT(false); 63 64 DEFINE int xMax INIT(100); 65 DEFINE int yMax INIT(100); 66 DEFINE int nPasses INIT(100); 67 68 enum InitializeType { InitializeRandom, InitializeGradient }; 69 #define RED 0 70 #define GREEN 1 71 #define BLUE 2 72 class SOM_element; 73 void remark_SOM_element(const SOM_element &s); 74 75 // all SOM_element vectors are the same length (nElements), so we do not have 76 // to range-check the vector accesses. 77 class SOM_element { 78 std::vector<double> w; 79 public: 80 friend std::ostream& operator<<( std::ostream &out, const SOM_element &s); 81 friend void remark_SOM_element(const SOM_element &s); SOM_element()82 SOM_element() : w(nElements,0.0) {} 83 double &operator[](int indx) { return w.at(indx); } 84 const double &operator[](int indx) const { return w.at(indx); } 85 bool operator==(SOM_element const &other) const { 86 for(size_t i=0;i<size();++i) { 87 if(w[i] != other.w[i]) { 88 return false; 89 } 90 } 91 return true; 92 } 93 bool operator!=(SOM_element const &other) const { return !operator==(other); } elementwise_max(SOM_element const & other)94 void elementwise_max(SOM_element const &other) { 95 for(size_t i = 0; i < w.size(); ++i) if(w[i] < other.w[i]) w[i] = other.w[i]; 96 } elementwise_min(SOM_element const & other)97 void elementwise_min(SOM_element const &other) { 98 for(size_t i = 0; i < w.size(); ++i) if(w[i] > other.w[i]) w[i] = other.w[i]; 99 } size()100 size_t size() const { return w.size(); } 101 }; 102 103 typedef std::vector<SOM_element> teaching_vector_type; 104 105 DEFINE SOM_element max_range; 106 DEFINE SOM_element min_range; 107 108 extern double randval( double lowlimit, double highlimit); 109 110 extern void find_data_ranges(teaching_vector_type &teaching, SOM_element &max_range, SOM_element &min_range ); 111 112 extern void add_fraction_of_difference( SOM_element &to, SOM_element &from, double frac); 113 114 DEFINE teaching_vector_type my_teaching; 115 116 class SOMap { 117 std::vector< std::vector< SOM_element > > my_map; 118 public: SOMap(int xSize,int ySize)119 SOMap(int xSize, int ySize) { 120 my_map.reserve(xSize); 121 for(int i = 0; i < xSize; ++i) { 122 my_map.push_back(teaching_vector_type()); 123 my_map[i].reserve(ySize); 124 for(int j = 0; j < ySize;++j) { 125 my_map[i].push_back(SOM_element()); 126 } 127 } 128 } size()129 size_t size() { return my_map.size(); } 130 void initialize(InitializeType it, SOM_element &max_range, SOM_element &min_range); 131 teaching_vector_type &operator[](int indx) { return my_map[indx]; } at(int xVal,int yVal)132 SOM_element &at(int xVal, int yVal) { return my_map[xVal][yVal]; } at(search_result_type const & s)133 SOM_element &at(search_result_type const &s) { return my_map[flow::get<1>(s)][flow::get<2>(s)]; } epoch_update(SOM_element const & s,int epoch,int min_x,int min_y,double radius,double learning_rate)134 void epoch_update( SOM_element const &s, int epoch, int min_x, int min_y, double radius, double learning_rate) { 135 int min_xiter = (int)((double)min_x - radius); 136 if(min_xiter < 0) min_xiter = 0; 137 int max_xiter = (int)((double)min_x + radius); 138 if(max_xiter > (int)my_map.size()-1) max_xiter = (int)(my_map.size()-1); 139 blocked_range<int> br1(min_xiter, max_xiter, 1); 140 epoch_update_range(s, epoch, min_x, min_y, radius, learning_rate, br1); 141 } 142 void epoch_update_range( SOM_element const &s, int epoch, int min_x, int min_y, double radius, double learning_rate, blocked_range<int> &r); 143 void teach( teaching_vector_type &id); 144 void debug_output(); 145 // find BMU given an input, returns distance 146 double BMU_range(const SOM_element &s, int &xval, int &yval, subsquare_type &r); BMU(const SOM_element & s,int & xval,int & yval)147 double BMU(const SOM_element &s, int &xval, int &yval) { 148 subsquare_type br(0,(int)my_map.size(),1,0,(int)my_map[0].size(),1); 149 return BMU_range(s, xval, yval, br); 150 } 151 }; 152 153 extern double distance_squared(SOM_element x, SOM_element y); 154 void remark_SOM_element(const SOM_element &s); 155 156 extern void readInputData(); 157 #endif // __SOM_H__ 158