Main Page | Namespace List | Class Hierarchy | Data Structures | File List | Namespace Members | Data Fields | Globals | Related Pages

hipclus.h

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (c) 2003, Cornell University
00004 All rights reserved.
00005 
00006 Redistribution and use in source and binary forms, with or without
00007 modification, are permitted provided that the following conditions are met:
00008 
00009    - Redistributions of source code must retain the above copyright notice,
00010        this list of conditions and the following disclaimer.
00011    - Redistributions in binary form must reproduce the above copyright
00012        notice, this list of conditions and the following disclaimer in the
00013        documentation and/or other materials provided with the distribution.
00014    - Neither the name of Cornell University nor the names of its
00015        contributors may be used to endorse or promote products derived from
00016        this software without specific prior written permission.
00017 
00018 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00019 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00022 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
00028 THE POSSIBILITY OF SUCH DAMAGE.
00029 
00030 */
00031 
00032 #if !defined(_HIPCLUS_H)
00033 #define    _HIPCLUS_H
00034 
00035 #include    "general.h"
00036 #include    "vec.h"
00037 #include    "extravec.h"
00038 #include    "fmat.h"
00039 #include    "sphclus.h"
00040 #include     "misc.h"
00041 #include    "math.h"
00042 #include    "exceptions.h"
00043 #include    <iostream>
00044 #include    <string>
00045 
00046 /*    The class that implements the HiperPlan Clusters
00047  *    Inherit:    SphericCluster
00048  *    Members:
00049  *        C:    
00050  *        S:    
00051  *        ComputeC2s calculate the value of C2s; used when c1.. changes
00052  *        EigVect: the matrix of eigen vectors
00053  *        SmallerEigVal: the index of the smaller eigen value
00054  *        Elipsoidality: the ponder of the linear characteristic in the
00055  *            final result (takes values between 0 and 1);
00056  *            0 means spheric, 1 means plan
00057  */
00058 
00059 namespace CLUS
00060 {
00061 using namespace TNT;
00062 
00063 /// This class implements hiperclusters with only one possible output
00064 class HiperPlanCluster:public SphericCluster
00065 {    
00066 protected:
00067 
00068     /// coefficients of the hiperplan in the form y=c0+x1*c1*..
00069     Vector<double> C,u;
00070 
00071     /// the spreading matrix; the eigen values will be found on his diagonal
00072     Fortran_Matrix<double> S;
00073     double Elipsoidality, error, slimness;
00074     
00075     void ComputeCCoef(void)
00076     {
00077         // called when u or L is modified and want to reflect modif in C
00078         double uy=u[inDim];
00079         C[0]=L[inDim];
00080         
00081         for(int j=0;j<inDim;j++)
00082         {
00083             C[j+1]=-u[j]/uy;
00084             C[0]+=L[j]*u[j]/uy;
00085         }
00086     }
00087     
00088     void ComputeU(void)
00089     {
00090         u[inDim]=1.0;
00091         L[inDim]=C[0];
00092         for(int j=0; j<inDim; j++)
00093         {
00094             u[j]=-C[j+1];
00095             L[inDim]+=C[j+1]*L[j];
00096         }
00097         Normalize(u);
00098     }
00099     
00100 public:
00101     HiperPlanCluster():SphericCluster(),C(),u(),S()
00102     {
00103         Elipsoidality=0.8;
00104         error=0.0;
00105     }
00106     
00107     HiperPlanCluster(int InDim, int OutDim):SphericCluster(InDim,OutDim),C(InDim+OutDim),
00108             u(InDim+OutDim),S(InDim+OutDim,InDim+OutDim)
00109     {
00110         if (OutDim!=1)
00111             throw ErrMsg("Instances of HiperPlanClusters cannot have more than one output");
00112             
00113         Elipsoidality=0.8;
00114         error=0.0;
00115     }
00116     
00117     HiperPlanCluster(int InDim, int OutDim, int):SphericCluster(InDim,OutDim,0),C(0),
00118             u(InDim+OutDim),S(0,0)
00119     {
00120         if (OutDim!=1)
00121             throw ErrMsg("Instances of HiperPlanClusters cannot have more than one output");
00122         Elipsoidality=0.8;
00123         error=0.0;
00124     }
00125     
00126     void CopyFrom(HiperPlanCluster& aux)
00127     {
00128         weight=aux.weight;
00129         dimension=aux.dimension;
00130         L=aux.L;
00131         u=aux.u;
00132         error=aux.error;
00133         state=aux.state;
00134         Elipsoidality=aux.Elipsoidality;
00135     }
00136 
00137     void RandomCluster(void)
00138     {
00139         SphericCluster::RandomCluster();
00140         ZeroUp(u); // there is no point is choosing something else
00141         u[inDim]=1.0;
00142         ComputeCCoef();
00143     }
00144     
00145     void InitializeOnPoint(const double* point)
00146     {
00147         SphericCluster::InitializeOnPoint(point);
00148         ZeroUp(u); // there is no point is choosing something else
00149         u[inDim]=1.0;
00150         ComputeCCoef();
00151     }
00152     
00153     inline double InferDistance(const double* DataCache)
00154     {
00155         // the corected distance is [c1(Xj[i]-X[i])+..]^2+(Xj[i]-X[i])^2+..
00156         double daux=0;
00157         dataCache=DataCache;
00158         distanceInfer=0.0;
00159         
00160         for(int i=0;i<inDim;i++)
00161         {
00162             register double dif=dataCache[i]-L[i];
00163             distanceInfer+=pow2(dif);
00164             daux+=C[i+1]*dif; // corection for the inclination of the plan
00165         }
00166         
00167         distanceInfer+=pow2(daux);
00168         // we need a correction since on average the square distance to this plane
00169         // is error^2
00170         distanceInfer=(1-Elipsoidality)*distanceInfer+Elipsoidality*error;
00171         distanceInfer*=weight;
00172         
00173         if (distanceInfer==0.0)
00174             distanceInfer=10e-300;
00175             
00176         return distanceInfer;/* added with 10e-16 to avoid 0.0 distances */
00177     }
00178     
00179     inline double ClusDistance(const double* DataCache)
00180     {
00181         distanceClus=SphericCluster::ClusDistance(DataCache)*(1-Elipsoidality);
00182         double dplan=0.0;
00183         
00184         for(int j=0;j<inDim+1;j++)
00185             dplan+=u[j]*(dataCache[j]-L[j]);
00186             
00187         distanceClus+=Elipsoidality*pow2(dplan);//*weight;
00188 
00189         // sphcluster clusdistance gives the protection for 0.0 result
00190         return distanceClus;
00191     }
00192 
00193     /**  In the hiperplan case not only the new gravity center must be
00194          computed but also the dispersion matrix S
00195      */
00196     double CorrectAppartGrade(double Coef)
00197     {
00198         // we could have used spheric cluster implementation for gravity center
00199         // but in this way is probably slightly faster for small dimensions
00200         double Ai;
00201         if (!finite(Coef))
00202             Ai=1.0;
00203         else
00204             Ai=1/(distanceClus*Coef);
00205 
00206         double Ai2=pow2(Ai);
00207 
00208         assert(finite(Ai) || finite(Ai2));
00209 
00210         s_Ai+=Ai2;
00211         for (int i=0;i<inDim+1;i++)
00212         {
00213             double aux=Ai2*dataCache[i];
00214             s_Ai_Xj[i]+=aux;
00215             // fill only the upper part of S
00216             for(int j=i; j<inDim+1; j++)
00217                 S(i+1,j+1)+=aux*dataCache[j];
00218         }
00219         
00220         return distanceClus*Ai2;
00221     }
00222     
00223     inline double HCorrectAppartGrade(double Coef)
00224     {
00225         double ret=CorrectAppartGrade(Coef);
00226         dimension+=ret;
00227         return ret;
00228     }
00229     
00230     double AdjustPrototypes(void)
00231     {
00232         double oldX, distP=0.0;
00233         for(int i=0;i<inDim+1;i++)
00234         {
00235             oldX=L[i];
00236 
00237             double aux=s_Ai_Xj[i]/s_Ai;
00238             L[i]=aux;
00239             for(int j=i; j<inDim+1; j++)
00240                 S(i+1,j+1)-=aux*s_Ai_Xj[j]; // the corection to S
00241             s_Ai_Xj[i]=0.0;
00242             distP+=pow2(oldX-L[i]);
00243         }
00244         
00245         // double lambda=Min(Upper_symmetric_eigenvalue_solve(S));
00246         double lambda,lambda2;
00247 
00248         if (MinEigenvalueUpperSymmetric(S,lambda,lambda2,slimness))
00249         {
00250             if (EigenVector(S,lambda,u))
00251                 error=lambda/s_Ai;
00252             else
00253                 cerr << "OOPS could not find the eigenvector for " << lambda << endl;
00254             slimness/=lambda;
00255         }
00256         else
00257             cerr << "OOPS-eigenvalue problem not solved in " << TypeName() << endl;
00258 
00259         ZeroUp(S);
00260         s_Ai=0.0;
00261         ComputeCCoef(); // must stay here
00262 
00263         return sqrt(distP)/(inDim+1); // how much the centres moved
00264     }
00265     
00266     inline double HAdjustPrototypes(void)
00267     {
00268         dimension/=s_Ai;
00269         return AdjustPrototypes();
00270     }
00271     
00272     void AdjustYwithYoverD(Vector<double>& Y)
00273     {
00274         double y=C[0];
00275         
00276         for(int j=0; j<inDim; j++)
00277             y+=C[j+1]*dataCache[j];
00278             
00279         Y[0]+=y/distanceInfer;
00280     }
00281     
00282     void AdjustYwithYoverD(Vector<double>& Y, double dist)
00283     {
00284         double y=C[0];
00285         
00286         for(int j=0; j<inDim; j++)
00287             y+=C[j+1]*dataCache[j];
00288             
00289         Y[0]+=y/dist;
00290     }
00291     
00292     double ComputeLastY(void)
00293     {
00294         double y=C[0];
00295         
00296         for(int j=0; j<inDim; j++)
00297             y+=C[j+1]*dataCache[j];
00298             
00299         return y;
00300     }
00301     
00302     static string TypeName(void)
00303     {
00304         return string("HiperPlanCluster");
00305     }
00306     
00307     void SaveToStream(ostream& out)
00308     {
00309         ComputeCCoef();
00310 
00311         out << "[ ";
00312         // the centre of the pattern
00313         for(int i=0; i<inDim; i++)
00314             out << L[i] << " ";
00315         out << " ] ( ";
00316         // the C coefs
00317         for(int i=0; i<inDim+1; i++)
00318             out << C[i] << " ";
00319         out << " ) { " << Elipsoidality << " " << error
00320         << " " << weight << " } " << endl;
00321     }
00322     
00323     void LoadFromStream(istream& in)
00324     {
00325         string s;
00326 
00327         in >> s;
00328         if (s!="[")
00329             throw ErrMsg("[ missing in hypercluster");
00330         for(int i=0; i<inDim; i++)
00331             in >> L[i];
00332         in >> s;
00333         if (s!="]")
00334             throw ErrMsg("] missing in hypercluster");
00335         in >> s;
00336         if (s!="(")
00337             throw ErrMsg("( missing in hypercluster");
00338         for(int i=0; i<inDim+1; i++)
00339             in >> C[i];
00340         in >> s;
00341         if (s!=")")
00342             throw ErrMsg(") missing hypercluster");
00343         in >> s;
00344         if (s!="{")
00345             throw ErrMsg("{ missing in hypercluster");
00346         in >> Elipsoidality;
00347         in >> error;
00348         in >> weight;
00349         in >> s;
00350         if (s!="}")
00351             throw ErrMsg("} missing in hypercluster");
00352         ComputeU();
00353     }
00354     
00355     void SetElipsoidality(double val)
00356     {
00357         Elipsoidality=val;
00358     }
00359     
00360     bool SetOptionDbl(char* optName,double value)
00361     {
00362         if ( strcmp(optName,"elipsoidality")==0 )
00363         {
00364             Elipsoidality=value;
00365             return true;
00366         }
00367         
00368         return SphericCluster::SetOptionDbl(optName,value);
00369     }
00370     
00371     bool Split(HiperPlanCluster& right, HiperPlanCluster& save, double minDim)
00372     {
00373         if (state==Final)
00374             return false;
00375         if (state==Dead)
00376             throw ErrMsg("Attempt to split a dead cluster");
00377         if (state==Splited)
00378             throw ErrMsg("Attempt to split a splited cluster");
00379 
00380         cerr << "Slimness=" << slimness << endl;
00381 
00382         if (slimness <=minDim )
00383             return false;
00384 
00385         // save *this in save
00386         save.weight=weight;
00387         save.state=Splited;
00388         save.L=L;
00389         // right.C=save.C=C;
00390         right.u=save.u=u;
00391         save.error=error;
00392         save.dimension=dimension;
00393         right.Elipsoidality=save.Elipsoidality=Elipsoidality;
00394 
00395         state=right.state=Splitable;
00396         weight=right.weight=weight/2; // splited clusters are two times smaller
00397 
00398         Vector<double> delta(L.dim());
00399         GenerateRandomVector2(delta);
00400         // must have u*delta=0 for L-delta and L+delta to be on the plane
00401         double y=0.0;
00402         for(int j=0; j<inDim; j++)
00403             y+=u[j]*delta[j];
00404         delta[inDim]=-y/u[inDim];
00405 
00406         SetNormTo(delta,dimension);
00407 
00408         // this cluster is the left cluster
00409         // first the right cluster
00410         right.L=L+delta;
00411         Dif(L,L.dim(),delta);
00412 
00413         ComputeCCoef();
00414         right.ComputeCCoef();
00415 
00416         dimension=right.dimension=0.0;
00417 
00418         return true;
00419     }
00420     
00421     bool CheckSplit(HiperPlanCluster& left, HiperPlanCluster& right, double splitCrit)
00422     {
00423         if (error*splitCrit > left.error + right.error)
00424         {
00425             // we have a good split
00426             return true;
00427         }
00428         else
00429         {
00430             // we have a bad split
00431             right.state=Dead;
00432             // copy back original version
00433             left.weight=weight;
00434             left.state=Final; // we dont split this anymore
00435             left.L=L;
00436             left.u=u;
00437             left.error=error;
00438             left.Elipsoidality=Elipsoidality;
00439             left.dimension=0.0;
00440             left.ComputeCCoef();
00441 
00442             return false;
00443         }
00444     }
00445 };
00446 }
00447 
00448 
00449 #endif    /* _HIPCLUS_H */

Generated on Mon Jul 21 16:57:24 2003 for SECRET by doxygen 1.3.2