Verbesserung gesucht



  • Hi

    Es geht um eine Umsetzung des Johnson's Algorithm für das Clustering.

    Wie kann ich folgenden Code verbessern im Sinn auf Speicher, Geschwindigkeit und Richtigkeit (zB const correctness)

    #ifndef CLUSTERING_H
    #define CLUSTERING_H
    
    #include <vector>
    #include <map>
    
    class Clustering
    {
        public:
            class Point
            {
                public:
                    Point( double _x = 0, double _y = 0 )
                    :   id( last_id++ ), x( _x ), y( _y )
                    {   }
                    static int last_id;
                    int id;
                    double x;
                    double y;
            };
    
            typedef std::vector< std::pair<double, double> > Points;
            typedef std::map<int, Point> Cluster;
            typedef std::map<int, Cluster> Clusters;
    
            // Ctor: Creates for every single point a cluster
            Clustering( const Points& points );
            virtual ~Clustering();
            const Clusters& get_clusters() const;
    
            // Starts computation
            // max_dist: maximal distance for points in a cluster
            void compute_clusters( const double max_dist = 127 );
    
        private:
            void merge_clusters( Cluster& a, Cluster& b );
            std::pair< double, std::pair<int, int> > find_closest_clusters() const;
            double single_link_dist( const Cluster& a, const Cluster& b ) const;
            double dist( const Point& a, const Point& b ) const;
    
            Clusters clusters;
    };
    
    #endif // CLUSTERING_H
    //-----------------------------------------------------//
    //
    #include "Clustering.h"
    
    #include <cmath>
    #include <iomanip>
    #include <iostream>
    
    Clustering::Clustering( const Clustering::Points& points )
    {
        for( Points::const_iterator it = points.begin();
             it != points.end(); ++it )
        {
            Point point( it->first, it->second );
            Cluster cluster;
            cluster.insert( std::make_pair( point.id, point ) );
            clusters.insert( std::make_pair( point.id, cluster ) );
        }
    }
    
    Clustering::~Clustering()
    {
        //dtor
    }
    
    const Clustering::Clusters& Clustering::get_clusters() const
    {
        return clusters;
    }
    
    void Clustering::compute_clusters( const double max_dist )
    {
        std::pair< double, std::pair<int, int> > result = find_closest_clusters();
        while( result.first < max_dist )
        {
            Clusters::iterator a = clusters.find( result.second.first );
            Clusters::iterator b = clusters.find( result.second.second );
            merge_clusters( a->second, b->second );
            clusters.erase( b );
            result = find_closest_clusters();
        }
    }
    
    void Clustering::merge_clusters
        ( Clustering::Cluster& a, Clustering::Cluster& b )
    {
        a.insert( b.begin(), b.end() );
        b.clear();
    }
    
    std::pair< double, std::pair<int, int> > Clustering::find_closest_clusters() const
    {
        double min = std::numeric_limits<double>::max();
        int a = 0;
        int b = 0;
        for( Clusters::const_iterator it_a = clusters.begin();
             it_a != clusters.end(); ++it_a )
        {
            Clusters::const_iterator it_b = it_a;
            ++it_b;
            for( ; it_b != clusters.end(); ++it_b )
            {
                double dist = single_link_dist( it_a->second, it_b->second );
                if( 0 < dist && dist < min )
                {
                    min = dist;
                    a = it_a->first;
                    b = it_b->first;
                }
            }
        }
        return std::make_pair( min, std::make_pair( a, b ) );
    }
    
    double Clustering::single_link_dist
        ( const Clustering::Cluster& a, const Clustering::Cluster& b ) const
    {
        double min = std::numeric_limits<double>::max();
        double tmp = min;
        for( Cluster::const_iterator it_a = a.begin();
             it_a != a.end(); ++it_a )
        {
            for( Cluster::const_iterator it_b = b.begin();
                 it_b != b.end(); ++it_b )
            {
                tmp = dist( it_a->second, it_b->second );
                if( tmp < min ) min = tmp;
            }
        }
        return min;
    }
    
    double Clustering::dist( const Clustering::Point& a, const Clustering::Point& b ) const
    {
        return fabs( a.x - b.x ) + fabs( a.y - b.y );
    }
    
    int Clustering::Point::last_id = 0;
    

    Für jegliche Tipps, Kritiken und Anregungen offen 🙂

    MfG
    Anton P.



  • *push*



  • das hier: http://www.lim.univ-mrs.fr/~thiel/npic/src/dist_gsym.c
    ist wohl auch eine implementation dieses algos (steht jedenfalls in den comments). kannst' ja mal mit deinem vergleichen...
    🙂



  • Undertaker schrieb:

    das hier: http://www.lim.univ-mrs.fr/~thiel/npic/src/dist_gsym.c
    ist wohl auch eine implementation dieses algos (steht jedenfalls in den comments). kannst' ja mal mit deinem vergleichen...
    🙂

    Danke, aber das ist ein anderer, der macht Permutationen.



  • *push* 😞

    funktionieren tut es ja, wollt nur mal bitten den code anzuschauen obs richtig ist.



  • überflieg sieht gut aus:)


Anmelden zum Antworten