2013-11-29 3 views
1
typedef unsigned long Count; 
typedef float Weight; 
typedef std::map<std::string, Count> StringToCountMap; 
typedef std::map<std::string, Weight> StringToWeightMap; 
typedef std::map<unsigned long, StringToCountMap> UnsignedToStringToCountMap; 
typedef std::map<unsigned long, StringToWeightMap> UnsignedToStringToWeightMap; 

typedef std::map<unsigned long, std::size_t> ClustersMap; 


class DefaultClusteringAlgorithm 
{ 
public: 
    // minumum number of documents changing clusters for algorithm to end 
    static const unsigned DocumentChangeThreshold = 0; 

    DefaultClusteringAlgorithm(unsigned numClusters, const UnsignedToStringToWeightMap &documentVectors) 
     : numClusters_(numClusters) 
     , documentVectors_(documentVectors) 
    { 
    } 

~DefaultClusteringAlgorithm() {} 

const ClustersMap &DoClustering(); 

private: 
    void ChooseInitialCentroids(); 
    unsigned ClusterOnCentroids(); 
    void RecalculateCentroids(); 
    float DocumentDotProduct(const StringToWeightMap &left, const StringToWeightMap &right); 
    float DocumentLength(const StringToWeightMap &document); 

    unsigned numClusters_; 

    // stores cluster_id => centroid 
    std::vector<StringToWeightMap> centroids_; 

    // maps question id => cluster id 
    ClustersMap clusters_; 

    // document vector 
    const UnsignedToStringToWeightMap &documentVectors_; 
}; 

void DefaultClusteringAlgorithm::RecalculateCentroids() 
{ 
    std::vector<unsigned> newCentroidsSizes(centroids_.size()); 
    std::vector<StringToWeightMap> newCentroids(centroids_.size()); 

    ClustersMap::const_iterator clusterMapping = clusters_.begin(); 

    for (; clusterMapping != clusters_.end(); ++clusterMapping) 
    { 
     std::size_t clusterId = clusterMapping->second; 

     ++newCentroidsSizes[clusterId]; 
     const StringToWeightMap &document = documentVectors_.at(clusterMapping->first); 

     StringToWeightMap::const_iterator termWeight = document.cbegin(); 

     for (; termWeight != document.end(); ++termWeight); 
     { 
      newCentroids[clusterId][termWeight->first] += termWeight->second; 
     } 
    } 

    std::vector<unsigned>::iterator centroidSize = newCentroidsSizes.begin(); 

    for (; centroidSize != newCentroidsSizes.end(); ++centroidSize) 
    { 
     std::size_t clusterId = centroidSize - newCentroidsSizes.begin(); 

     StringToWeightMap::iterator centroidTermWeight = newCentroids[clusterId].begin(); 

     for (; centroidTermWeight != newCentroids[clusterId].end(); ++centroidTermWeight) 
     { 
      centroidTermWeight->second /= *centroidSize; 
     } 
    } 
} 

debugger watchстанд :: Карта :: начинается() возвращает итератор с мусором

Проблема возникает при создании const_iterator TERMWEIGHT:

StringToWeightMap::const_iterator termWeight = document.begin(); 

Как вы можете видеть на изображении над termWeight const_iterator имеет недопустимые данные. Тем не менее, файл const std :: map является абсолютно допустимой std :: map. Я не могу придумать, почему это происходит.

Недавно я узнал, что std :: map :: cbegin() существует. Должен ли я использовать этот метод вместо этого?

EDIT: метод Включено более контекст

+0

Какая строка кода должна быть выполнена, когда отображается вышеуказанный сброс памяти? Данные, отображаемые для 'termWeight', недействительны до тех пор, пока строка, в которой она впервые назначена, недействительна. –

+0

'cbegin' не поможет. Есть ли 'const_cast' в вашей базе кода? Один из способов получить действительно плохое поведение из «std :: map» - это изменить порядок содержимого «карты», когда они находятся в «карте». Во-вторых, на какой линии вы? Произошла ли какая-либо итерация? Есть ли другие темы? Каков тип 'documentVectors_'? – Yakk

+0

Следующая строка, которая будет исполнена, - это единственная строка в цикле внутри самого большого. Так что termWeight уже назначен. – Osuvaldo

ответ

2

Hah! Я нашел ошибку! Глупая маленькая полуколона в конце моей петли!

0

БППП :: карта начинается() может быть возвращение итератор, который указывает на конец карты, так что не может быть каких-либо элементов в карте вообще.

+0

Он проверяет этот случай в своем цикле for, хотя он должен использовать 'cend()' вместо просто 'end()'. –

+0

Обратите внимание, что 'document' имеет' размер' '24' в окне отладки. – Yakk

+0

@JohnSaxton спасибо, что указал. Недавно я изменил его на cbegin() и забыл внести соответствующие изменения для cend() – Osuvaldo

Смежные вопросы