// @(#)root/tmva $Id$
// Author: Rustem Ospanov

/**********************************************************************************
 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis       *
 * Package: TMVA                                                                  *
 * Class  : ModulekNN                                                             *
 * Web    : http://tmva.sourceforge.net                                           *
 *                                                                                *
 * Description:                                                                   *
 *      Module for k-nearest neighbor algorithm                                   *
 *                                                                                *
 * Author:                                                                        *
 *      Rustem Ospanov <rustem@fnal.gov> - U. of Texas at Austin, USA             *
 *                                                                                *
 * Copyright (c) 2007:                                                            *
 *      CERN, Switzerland                                                         *
 *      MPI-K Heidelberg, Germany                                                 *
 *      U. of Texas at Austin, USA                                                *
 *                                                                                *
 * Redistribution and use in source and binary forms, with or without             *
 * modification, are permitted according to the terms listed in LICENSE           *
 * (http://tmva.sourceforge.net/LICENSE)                                          *
 **********************************************************************************/

#ifndef ROOT_TMVA_ModulekNN
#define ROOT_TMVA_ModulekNN

//______________________________________________________________________
/*
  kNN::Event describes point in input variable vector-space, with
  additional functionality like distance between points
*/
//______________________________________________________________________


// C++
#include <cassert>
#include <iosfwd>
#include <map>
#include <string>
#include <vector>

// ROOT
#ifndef ROOT_Rtypes
#include "Rtypes.h"
#endif
#ifndef ROOT_TRandom
#include "TRandom3.h"
#endif
#ifndef ROOT_ThreadLocalStorage
#include "ThreadLocalStorage.h"
#endif
#ifndef ROOT_TMVA_NodekNN
#include "TMVA/NodekNN.h"
#endif

namespace TMVA {

   class MsgLogger;

   namespace kNN {
      
      typedef Float_t VarType;
      typedef std::vector<VarType> VarVec;
      
      class Event {
      public:

         Event();
         Event(const VarVec &vec, Double_t weight, Short_t type);
         Event(const VarVec &vec, Double_t weight, Short_t type, const VarVec &tvec);
         ~Event();

         Double_t GetWeight() const;

         VarType GetVar(UInt_t i) const;
         VarType GetTgt(UInt_t i) const;

         UInt_t GetNVar() const;
         UInt_t GetNTgt() const;

         Short_t GetType() const;

         // keep these two function separate
         VarType GetDist(VarType var, UInt_t ivar) const;
         VarType GetDist(const Event &other) const;

         void SetTargets(const VarVec &tvec);
         const VarVec& GetTargets() const;
         const VarVec& GetVars() const;

         void Print() const;
         void Print(std::ostream& os) const;

      private:

         VarVec fVar; // coordinates (variables) for knn search
         VarVec fTgt; // targets for regression analysis

         Double_t fWeight; // event weight
         Short_t fType; // event type ==0 or == 1, expand it to arbitrary class types? 
      };

      typedef std::vector<TMVA::kNN::Event> EventVec;
      typedef std::pair<const Node<Event> *, VarType> Elem;
      typedef std::list<Elem> List;

      std::ostream& operator<<(std::ostream& os, const Event& event);

      class ModulekNN
      {
      public:

         typedef std::map<int, std::vector<Double_t> > VarMap;

      public:

         ModulekNN();
         ~ModulekNN();

         void Clear();

         void Add(const Event &event);

         Bool_t Fill(const UShort_t odepth, UInt_t ifrac, const std::string &option = "");

         Bool_t Find(Event event, UInt_t nfind = 100, const std::string &option = "count") const;
         Bool_t Find(UInt_t nfind, const std::string &option) const;
      
         const EventVec& GetEventVec() const;

         const List& GetkNNList() const;
         const Event& GetkNNEvent() const;

         const VarMap& GetVarMap() const;

         const std::map<Int_t, Double_t>& GetMetric() const;
      
         void Print() const;
         void Print(std::ostream &os) const;

      private:

         Node<Event>* Optimize(UInt_t optimize_depth);

         void ComputeMetric(UInt_t ifrac);

         const Event Scale(const Event &event) const;

      private:

        // This is a workaround for OSx where static thread_local data members are
        // not supported. The C++ solution would indeed be the following:
         static TRandom3& GetRndmThreadLocal() {TTHREAD_TLS_DECL_ARG(TRandom3,fgRndm,1); return fgRndm;};

         UInt_t fDimn;

         Node<Event> *fTree;

         std::map<Int_t, Double_t> fVarScale;

         mutable List  fkNNList;     // latest result from kNN search
         mutable Event fkNNEvent;    // latest event used for kNN search
         
         std::map<Short_t, UInt_t> fCount; // count number of events of each type

         EventVec fEvent; // vector of all events used to build tree and analysis
         VarMap   fVar;   // sorted map of variables in each dimension for all event types

         mutable MsgLogger* fLogger;   // message logger
         MsgLogger& Log() const { return *fLogger; }
      };

      //
      // inlined functions for Event class
      //
      inline VarType Event::GetDist(const VarType var1, const UInt_t ivar) const
      {
         const VarType var2 = GetVar(ivar);
         return (var1 - var2) * (var1 - var2);
      }
      inline Double_t Event::GetWeight() const
      {
         return fWeight;
      }
      inline VarType Event::GetVar(const UInt_t i) const
      {
         return fVar[i];
      }
      inline VarType Event::GetTgt(const UInt_t i) const
      {
         return fTgt[i];
      }

      inline UInt_t Event::GetNVar() const
      {
         return fVar.size();
      }
      inline UInt_t Event::GetNTgt() const
      {
         return fTgt.size();
      }
      inline Short_t Event::GetType() const
      {
         return fType;
      }

      //
      // inline functions for ModulekNN class
      //
      inline const List& ModulekNN::GetkNNList() const
      {
         return fkNNList;
      }
      inline const Event& ModulekNN::GetkNNEvent() const
      {
         return fkNNEvent;
      }
      inline const EventVec& ModulekNN::GetEventVec() const
      {
         return fEvent;
      }
      inline const ModulekNN::VarMap& ModulekNN::GetVarMap() const
      {
         return fVar;
      }
      inline const std::map<Int_t, Double_t>& ModulekNN::GetMetric() const
      {
         return fVarScale;
      }

   } // end of kNN namespace
} // end of TMVA namespace

#endif

 ModulekNN.h:1
 ModulekNN.h:2
 ModulekNN.h:3
 ModulekNN.h:4
 ModulekNN.h:5
 ModulekNN.h:6
 ModulekNN.h:7
 ModulekNN.h:8
 ModulekNN.h:9
 ModulekNN.h:10
 ModulekNN.h:11
 ModulekNN.h:12
 ModulekNN.h:13
 ModulekNN.h:14
 ModulekNN.h:15
 ModulekNN.h:16
 ModulekNN.h:17
 ModulekNN.h:18
 ModulekNN.h:19
 ModulekNN.h:20
 ModulekNN.h:21
 ModulekNN.h:22
 ModulekNN.h:23
 ModulekNN.h:24
 ModulekNN.h:25
 ModulekNN.h:26
 ModulekNN.h:27
 ModulekNN.h:28
 ModulekNN.h:29
 ModulekNN.h:30
 ModulekNN.h:31
 ModulekNN.h:32
 ModulekNN.h:33
 ModulekNN.h:34
 ModulekNN.h:35
 ModulekNN.h:36
 ModulekNN.h:37
 ModulekNN.h:38
 ModulekNN.h:39
 ModulekNN.h:40
 ModulekNN.h:41
 ModulekNN.h:42
 ModulekNN.h:43
 ModulekNN.h:44
 ModulekNN.h:45
 ModulekNN.h:46
 ModulekNN.h:47
 ModulekNN.h:48
 ModulekNN.h:49
 ModulekNN.h:50
 ModulekNN.h:51
 ModulekNN.h:52
 ModulekNN.h:53
 ModulekNN.h:54
 ModulekNN.h:55
 ModulekNN.h:56
 ModulekNN.h:57
 ModulekNN.h:58
 ModulekNN.h:59
 ModulekNN.h:60
 ModulekNN.h:61
 ModulekNN.h:62
 ModulekNN.h:63
 ModulekNN.h:64
 ModulekNN.h:65
 ModulekNN.h:66
 ModulekNN.h:67
 ModulekNN.h:68
 ModulekNN.h:69
 ModulekNN.h:70
 ModulekNN.h:71
 ModulekNN.h:72
 ModulekNN.h:73
 ModulekNN.h:74
 ModulekNN.h:75
 ModulekNN.h:76
 ModulekNN.h:77
 ModulekNN.h:78
 ModulekNN.h:79
 ModulekNN.h:80
 ModulekNN.h:81
 ModulekNN.h:82
 ModulekNN.h:83
 ModulekNN.h:84
 ModulekNN.h:85
 ModulekNN.h:86
 ModulekNN.h:87
 ModulekNN.h:88
 ModulekNN.h:89
 ModulekNN.h:90
 ModulekNN.h:91
 ModulekNN.h:92
 ModulekNN.h:93
 ModulekNN.h:94
 ModulekNN.h:95
 ModulekNN.h:96
 ModulekNN.h:97
 ModulekNN.h:98
 ModulekNN.h:99
 ModulekNN.h:100
 ModulekNN.h:101
 ModulekNN.h:102
 ModulekNN.h:103
 ModulekNN.h:104
 ModulekNN.h:105
 ModulekNN.h:106
 ModulekNN.h:107
 ModulekNN.h:108
 ModulekNN.h:109
 ModulekNN.h:110
 ModulekNN.h:111
 ModulekNN.h:112
 ModulekNN.h:113
 ModulekNN.h:114
 ModulekNN.h:115
 ModulekNN.h:116
 ModulekNN.h:117
 ModulekNN.h:118
 ModulekNN.h:119
 ModulekNN.h:120
 ModulekNN.h:121
 ModulekNN.h:122
 ModulekNN.h:123
 ModulekNN.h:124
 ModulekNN.h:125
 ModulekNN.h:126
 ModulekNN.h:127
 ModulekNN.h:128
 ModulekNN.h:129
 ModulekNN.h:130
 ModulekNN.h:131
 ModulekNN.h:132
 ModulekNN.h:133
 ModulekNN.h:134
 ModulekNN.h:135
 ModulekNN.h:136
 ModulekNN.h:137
 ModulekNN.h:138
 ModulekNN.h:139
 ModulekNN.h:140
 ModulekNN.h:141
 ModulekNN.h:142
 ModulekNN.h:143
 ModulekNN.h:144
 ModulekNN.h:145
 ModulekNN.h:146
 ModulekNN.h:147
 ModulekNN.h:148
 ModulekNN.h:149
 ModulekNN.h:150
 ModulekNN.h:151
 ModulekNN.h:152
 ModulekNN.h:153
 ModulekNN.h:154
 ModulekNN.h:155
 ModulekNN.h:156
 ModulekNN.h:157
 ModulekNN.h:158
 ModulekNN.h:159
 ModulekNN.h:160
 ModulekNN.h:161
 ModulekNN.h:162
 ModulekNN.h:163
 ModulekNN.h:164
 ModulekNN.h:165
 ModulekNN.h:166
 ModulekNN.h:167
 ModulekNN.h:168
 ModulekNN.h:169
 ModulekNN.h:170
 ModulekNN.h:171
 ModulekNN.h:172
 ModulekNN.h:173
 ModulekNN.h:174
 ModulekNN.h:175
 ModulekNN.h:176
 ModulekNN.h:177
 ModulekNN.h:178
 ModulekNN.h:179
 ModulekNN.h:180
 ModulekNN.h:181
 ModulekNN.h:182
 ModulekNN.h:183
 ModulekNN.h:184
 ModulekNN.h:185
 ModulekNN.h:186
 ModulekNN.h:187
 ModulekNN.h:188
 ModulekNN.h:189
 ModulekNN.h:190
 ModulekNN.h:191
 ModulekNN.h:192
 ModulekNN.h:193
 ModulekNN.h:194
 ModulekNN.h:195
 ModulekNN.h:196
 ModulekNN.h:197
 ModulekNN.h:198
 ModulekNN.h:199
 ModulekNN.h:200
 ModulekNN.h:201
 ModulekNN.h:202
 ModulekNN.h:203
 ModulekNN.h:204
 ModulekNN.h:205
 ModulekNN.h:206
 ModulekNN.h:207
 ModulekNN.h:208
 ModulekNN.h:209
 ModulekNN.h:210
 ModulekNN.h:211
 ModulekNN.h:212
 ModulekNN.h:213
 ModulekNN.h:214
 ModulekNN.h:215
 ModulekNN.h:216
 ModulekNN.h:217
 ModulekNN.h:218
 ModulekNN.h:219
 ModulekNN.h:220
 ModulekNN.h:221
 ModulekNN.h:222
 ModulekNN.h:223
 ModulekNN.h:224
 ModulekNN.h:225
 ModulekNN.h:226
 ModulekNN.h:227
 ModulekNN.h:228
 ModulekNN.h:229
 ModulekNN.h:230
 ModulekNN.h:231
 ModulekNN.h:232
 ModulekNN.h:233
 ModulekNN.h:234
 ModulekNN.h:235
 ModulekNN.h:236
 ModulekNN.h:237