You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							169 lines
						
					
					
						
							6.1 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							169 lines
						
					
					
						
							6.1 KiB
						
					
					
				| /* | |
|     Copyright 2005-2014 Intel Corporation.  All Rights Reserved. | |
|  | |
|     This file is part of Threading Building Blocks. | |
|  | |
|     Threading Building Blocks is free software; you can redistribute it | |
|     and/or modify it under the terms of the GNU General Public License | |
|     version 2 as published by the Free Software Foundation. | |
|  | |
|     Threading Building Blocks 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 Threading Building Blocks; if not, write to the Free Software | |
|     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA | |
|  | |
|     As a special exception, you may use this file as part of a free software | |
|     library without restriction.  Specifically, if other files instantiate | |
|     templates or use macros or inline functions from this file, or you compile | |
|     this file and link it with other files to produce an executable, this | |
|     file does not by itself cause the resulting executable to be covered by | |
|     the GNU General Public License.  This exception does not however | |
|     invalidate any other reasons why the executable file might be covered by | |
|     the GNU General Public License. | |
| */ | |
| 
 | |
| // | |
| // Self-organizing map | |
| // | |
| // support for self-ordering maps | |
| #ifndef __SOM_H__ | |
| #define __SOM_H__ | |
|  | |
| #include <vector> | |
| #include <cstdlib> | |
| #include <cmath> | |
| #include <cfloat> | |
| #include <iostream> | |
| #include <cstdio> | |
|  | |
| #include "tbb/flow_graph.h" | |
| #include "tbb/blocked_range2d.h" | |
|  | |
| using namespace tbb; | |
| using namespace tbb::flow; | |
| 
 | |
| typedef blocked_range2d<int> subsquare_type; | |
| typedef tuple<double,int,int> search_result_type; | |
| 
 | |
| std::ostream& operator<<( std::ostream &out, const search_result_type &s); | |
| 
 | |
| #define RADIUS 0  // for the std::gets | |
| #define XV     1 | |
| #define YV     2 | |
|  | |
| // to have single definitions of static variables, define _MAIN_C_ in the main program | |
| //  | |
| #ifdef _MAIN_C_ | |
| #define DEFINE // nothing | |
| #define INIT(n) = n | |
| #else // not in main file | |
| #define DEFINE extern | |
| #define INIT(n) // nothing | |
| #endif  // _MAIN_C_ | |
|  | |
| DEFINE int nElements INIT(3);  // length of input vectors, matching vector in map | |
| DEFINE double max_learning_rate INIT(0.8);  // decays exponentially | |
| DEFINE double radius_decay_rate; | |
| DEFINE double learning_decay_rate INIT(0.005); | |
| DEFINE double max_radius; | |
| DEFINE bool extra_debug INIT(false); | |
| DEFINE bool cancel_test INIT(false); | |
| 
 | |
| DEFINE int xMax INIT(100); | |
| DEFINE int yMax INIT(100); | |
| DEFINE int nPasses INIT(100); | |
| 
 | |
| enum InitializeType { InitializeRandom, InitializeGradient }; | |
| #define RED 0 | |
| #define GREEN 1 | |
| #define BLUE 2 | |
| class SOM_element; | |
| void remark_SOM_element(const SOM_element &s); | |
| 
 | |
| // all SOM_element vectors are the same length (nElements), so we do not have | |
| // to range-check the vector accesses. | |
| class SOM_element { | |
|     std::vector<double> w; | |
| public: | |
|     friend std::ostream& operator<<( std::ostream &out, const SOM_element &s); | |
|     friend void remark_SOM_element(const SOM_element &s); | |
|     SOM_element() : w(nElements,0.0) {} | |
|     double &operator[](int indx) { return w.at(indx); } | |
|     const double &operator[](int indx) const { return w.at(indx); } | |
|     bool operator==(SOM_element const &other) const { | |
|         for(size_t i=0;i<size();++i) { | |
|             if(w[i] != other.w[i]) { | |
|                 return false; | |
|             } | |
|         } | |
|         return true; | |
|     } | |
|     bool operator!=(SOM_element const &other) const { return !operator==(other); } | |
|     void elementwise_max(SOM_element const &other) { | |
|         for(size_t i = 0; i < w.size(); ++i) if(w[i] < other.w[i]) w[i] = other.w[i]; | |
|     } | |
|     void elementwise_min(SOM_element const &other) { | |
|         for(size_t i = 0; i < w.size(); ++i) if(w[i] > other.w[i]) w[i] = other.w[i]; | |
|     } | |
|     size_t size() const { return w.size(); } | |
| }; | |
| 
 | |
| typedef std::vector<SOM_element> teaching_vector_type; | |
| 
 | |
| DEFINE SOM_element max_range; | |
| DEFINE SOM_element min_range; | |
| 
 | |
| extern double randval( double lowlimit, double highlimit); | |
| 
 | |
| extern void find_data_ranges(teaching_vector_type &teaching, SOM_element &max_range, SOM_element &min_range ); | |
| 
 | |
| extern void add_fraction_of_difference( SOM_element &to, SOM_element &from, double frac); | |
| 
 | |
| DEFINE teaching_vector_type my_teaching; | |
| 
 | |
| class SOMap { | |
|     std::vector< std::vector< SOM_element > > my_map; | |
| public: | |
|     SOMap(int xSize, int ySize) { | |
|         my_map.reserve(xSize); | |
|         for(int i = 0; i < xSize; ++i) { | |
|             my_map.push_back(teaching_vector_type()); | |
|             my_map[i].reserve(ySize); | |
|             for(int j = 0; j < ySize;++j) { | |
|                 my_map[i].push_back(SOM_element()); | |
|             } | |
|         } | |
|     } | |
|     size_t size() { return my_map.size(); } | |
|     void initialize(InitializeType it, SOM_element &max_range, SOM_element &min_range); | |
|     teaching_vector_type &operator[](int indx) { return my_map[indx]; } | |
|     SOM_element &at(int xVal, int yVal) { return my_map[xVal][yVal]; } | |
|     SOM_element &at(search_result_type const &s) { return my_map[flow::get<1>(s)][flow::get<2>(s)]; } | |
|     void epoch_update( SOM_element const &s, int epoch, int min_x, int min_y, double radius, double learning_rate) { | |
|         int min_xiter = (int)((double)min_x - radius); | |
|         if(min_xiter < 0) min_xiter = 0; | |
|         int max_xiter = (int)((double)min_x + radius); | |
|         if(max_xiter > (int)my_map.size()-1) max_xiter = (int)(my_map.size()-1); | |
|         blocked_range<int> br1(min_xiter, max_xiter, 1); | |
|         epoch_update_range(s, epoch, min_x, min_y, radius, learning_rate, br1); | |
|     } | |
|     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); | |
|     void teach( teaching_vector_type &id); | |
|     void debug_output(); | |
|     // find BMU given an input, returns distance | |
|     double BMU_range(const SOM_element &s, int &xval, int &yval, subsquare_type &r); | |
|     double BMU(const SOM_element &s, int &xval, int &yval) { | |
|         subsquare_type br(0,(int)my_map.size(),1,0,(int)my_map[0].size(),1); | |
|         return BMU_range(s, xval, yval, br); | |
|     } | |
| }; | |
| 
 | |
| extern double distance_squared(SOM_element x, SOM_element y); | |
| void remark_SOM_element(const SOM_element &s); | |
| 
 | |
| extern void readInputData(); | |
| #endif // __SOM_H__
 |