Skip to content

Commit

Permalink
work on silhouette value, refs #4
Browse files Browse the repository at this point in the history
  • Loading branch information
phspo committed Jan 15, 2018
1 parent 743dd79 commit 4b19502
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 2 deletions.
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ set( Yoshiko_Hdr
src/WorkingCopyInstance.h

src/input/ClusterEditingInput.h

src/measurement/SilhouetteValue.h

src/reductionRules/AlmostCliqueRule.h
src/reductionRules/CliqueRule.h
Expand Down Expand Up @@ -57,6 +59,8 @@ set( Yoshiko_Src
src/WorkingCopyInstance.cpp

src/input/ClusterEditingInput.cpp

src/measurement/SilhouetteValue.cpp

src/reductionRules/AlmostCliqueRule.cpp
src/reductionRules/CliqueRule.cpp
Expand Down
16 changes: 15 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "ClusterEditingSolutions.h"
#include "CoreAlgorithm.h"
#include "Globals.h"
#include "measurement/SilhouetteValue.h"

#include "output/ClusterEditingOutput.h"

Expand Down Expand Up @@ -74,6 +75,7 @@ int main(int argc, char * const argv[]) {
int inputFileFormat = 0;
int outputFileFormat = 0;
bool exportLP = false;
bool printSilhouetteValue = false;

YParameterSet parameter;

Expand All @@ -95,7 +97,9 @@ int main(int argc, char * const argv[]) {
ap.refOption("m", "multiplicative factor for real valued edge weights in SimilarNeighborhoodRule (the higher the better the reduction results and the slower the performance) [1]", parameter.multiplicativeFactor, false);
ap.refOption("g", "graph label []", graphLabel, false);
ap.refOption("r", "explicitly turn on/off reduction rules, bit string (right to left): bit 0 = CliqueRule, bit 1 = CriticalCliqueRule, bit 2 = AlmostCliqueRule, bit 3 = HeavyEdgeRule3in1, bit 4 = ParameterDependentReductionRule, bit 5 = SimilarNeighborhoodRule [111111]", parameter.rulesBitMask, false);
ap.refOption("k", "[EXPERIMENTAL!!!]define the number of desired clusters, -1 determines this value automatically [-1]",parameter.targetClusterCount,false);
ap.refOption("k", "[EXPERIMENTAL!!!] Define the number of desired clusters, -1 determines this value automatically [-1]",parameter.targetClusterCount,false);
ap.refOption("s", "[EXPERIMENTAL!!!] Prints the silhouette value at the end of the run",printSilhouetteValue,false);


// Perform the parsing process
// (in case of any error it terminates the program) -> tb improved
Expand Down Expand Up @@ -126,6 +130,8 @@ int main(int argc, char * const argv[]) {
std::cout << " -g: " << graphLabel << std::endl;
std::cout << " -r: " << parameter.rulesBitMask << std::endl;
std::cout << " -k: " << parameter.targetClusterCount << std::endl;
std::cout << " -s: " << printSilhouetteValue << std::endl;

}

ifstream is(inputFilename.c_str());
Expand Down Expand Up @@ -177,6 +183,14 @@ int main(int argc, char * const argv[]) {

ClusterEditingSolutions* ces = core->run();

//Print Silhouette Value if required
//TODO: Make accessible from library, add support for printing it to certain output formats if required
if (printSilhouetteValue){
for (unsigned int i = 0; i < ces->getNumberOfSolutions(); i++){
cout << "Silhouette Value: " << SilhouetteValue(instance,ces->getSolution(i)).getValue() << endl;
}
}

//Output generation
ClusterEditingOutput* output;
output = ClusterEditingOutput::newInstance(
Expand Down
111 changes: 111 additions & 0 deletions src/measurement/SilhouetteValue.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* SilhouetteValue.cpp
*
* Created on: Jan 15, 2018
* Author: philipp
*/

#include "SilhouetteValue.h"

using namespace std;
using namespace lemon;

namespace ysk{

//TODO: Experimental Stuff, makes 0 sense right now as edges are not a distance function

SilhouetteValue::~SilhouetteValue(){};

double SilhouetteValue::getValue(){
//Calculate average dissimilarities to own clusters (a(i))
map<int,double> _averageDissimilaritiesOwn = map<int,double>();
for(auto const &cluster : _solution){
for (auto const &node : cluster){
double dissim = 1.0/cluster.size();
//Sum Factor
double sum = 0.0;
for (auto const &otherNode : cluster){
if (node == otherNode) continue; //Not of interest
FullGraph::Edge edge = _instance->getOrig().findEdge(
_instance->getOrig().nodeFromId(node),
_instance->getOrig().nodeFromId(otherNode),
INVALID);
sum += _instance->getWeight(edge);
}
//cout << dissim << " " << sum << endl;
dissim *= sum;
_averageDissimilaritiesOwn[node]=dissim;

}
}

// if (verbosity > 5){
// cout << "Average Dissimilarities to own clusters" << endl << endl;
// for (auto const &cluster : _solution){
// for (auto const &node: cluster){
// cout << node << " : " << _averageDissimilaritiesOwn[node]<< endl;
// }
// }
// }

//Calculate average dissimilarities to other clusters (b(i))
map<int,double> _averageDissimilaritiesForeign= map<int,double>();
for(auto const &cluster : _solution){
for (auto const &node : cluster){
double dissim = 1.0/(_instance->getSize()-cluster.size());
//Sum Factor
double sum = 0.0;
for (auto const &otherCluster : _solution){
for (auto const &otherNode : otherCluster){
FullGraph::Edge edge = _instance->getOrig().findEdge(
_instance->getOrig().nodeFromId(node),
_instance->getOrig().nodeFromId(otherNode),
INVALID);
sum += _instance->getWeight(edge);
}
}
dissim *= sum;
_averageDissimilaritiesForeign[node]=dissim;

}
}

if (verbosity > 4){
cout << "Average Dissimilarities to other clusters" << endl << endl;
for (auto const &cluster : _solution){
for (auto const &node: cluster){
cout << node << " : " << _averageDissimilaritiesForeign[node]<< endl;
}
}
}

//Calculate silhouettes
map<int,double> _silhouettes= map<int,double>();
for (auto const &cluster: _solution){
for (auto const &node : cluster){
_silhouettes[node] =
(1.0/_instance->getSize())*
(
(_averageDissimilaritiesForeign[node] -_averageDissimilaritiesOwn[node])
/
(std::max(_averageDissimilaritiesForeign[node],_averageDissimilaritiesOwn[node]))
);
}
}

//Calculate silhouette value

double factor = 1.0/_instance->getSize();
int sum = 0.0;

for (auto const &cluster : _solution){
for (auto const &node : cluster){
sum += _silhouettes[node];
}
}

return factor*sum;
}
}


35 changes: 35 additions & 0 deletions src/measurement/SilhouetteValue.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* SilhouetteValue.h
*
* Created on: Jan 15, 2018
* Author: philipp
*/

#ifndef SRC_MEASUREMENT_SILHOUETTEVALUE_H_
#define SRC_MEASUREMENT_SILHOUETTEVALUE_H_

#include "ClusterEditingInstance.h"

#include <lemon/full_graph.h>
#include <lemon/adaptors.h>
#include <lemon/connectivity.h>

namespace ysk{
class SilhouetteValue {
public:
SilhouetteValue(ClusterEditingInstance* instance,std::vector<std::vector<int>>& solution):
_instance(instance),
_solution(solution)
{};

virtual ~SilhouetteValue();
double getValue();
private:
ClusterEditingInstance* _instance;
std::vector<std::vector<int>> _solution;

};
}


#endif /* SRC_MEASUREMENT_SILHOUETTEVALUE_H_ */
2 changes: 1 addition & 1 deletion src/output/ClusterEditingOutput.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include "ClusterEditingSolutions.h"
#include "WorkingCopyInstance.h"


//TODO: Add Console Output -> Redundant (Verbosity is sufficient?)

namespace ysk {

Expand Down

0 comments on commit 4b19502

Please sign in to comment.