This repository has been archived by the owner on May 4, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e8ec436
commit 164bf64
Showing
5 changed files
with
130 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# frozen_string_literal: true | ||
|
||
module MOSAIK | ||
module Metrics | ||
## | ||
# Cohesion (S. Chidamber and C. Kemerer, 1994) | ||
# | ||
class Cohesion < Metric | ||
def evaluate | ||
# Total cohesion | ||
cohesion = 0.0 | ||
|
||
# Iterate over each cluster | ||
graph.clusters.each_value do |cluster| | ||
# Find all vertices in the cluster | ||
vertices_in_cluster = cluster.vertices | ||
vertices_in_cluster_id = vertices_in_cluster.map(&:id) | ||
|
||
# Calculate the cardinality of the cluster | ||
cardinality_c = vertices_in_cluster.sum do |v| | ||
warn "No `methods` attribute found for #{v.id}, did you extract structural coupling information?" unless v.attributes.key?(:methods) | ||
|
||
v.attributes.fetch(:methods, 0.0) | ||
end | ||
|
||
# Skip if the vertex has less than 2 methods (denominator would be 0) | ||
if cardinality_c < 2 | ||
warn "Cluster #{cluster.id} has less than 2 methods, skipping cohesion calculation" | ||
|
||
# Store cohesion value in the cluster | ||
cluster.attributes[:cohesion] = 0.0 | ||
|
||
next | ||
end | ||
|
||
# Calculate sum of edges between vertices in the cluster | ||
sum = vertices_in_cluster | ||
.flat_map { |v| v.edges.filter_map { |i, e| e if i.in?(vertices_in_cluster_id) } } | ||
.uniq | ||
.count | ||
|
||
# Calculate cohesion value for the cluster | ||
cohesion_c = sum.to_f / (cardinality_c * (cardinality_c - 1) / 2) | ||
|
||
# Store cohesion value in the cluster | ||
cluster.attributes[:cohesion] = cohesion_c | ||
|
||
# Calculate cohesion contribution from this cluster | ||
cohesion += cohesion_c | ||
end | ||
|
||
# Store cohesion value in the graph | ||
graph.attributes[:cohesion] = cohesion | ||
|
||
# Return the total cohesion | ||
cohesion | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe MOSAIK::Metrics::Cohesion do | ||
subject(:metric) { build(:cohesion_metric, graph:) } | ||
|
||
# Cohesion value calculated by hand: | ||
# | ||
# Directed: | ||
# Cluster A: |A| = 11: (2 + 1 + 0) / (11 * 10 / 2) = 0.05454545454545454 | ||
# Cluster B: |B| = 8: (1 + 0) / (8 * 7 / 2) = 0.03571428571428571 | ||
# Cluster C: |C| = 1: 0 | ||
# | ||
# Cohesion = 0.05454545454545454 + 0.03571428571428571 + 0 = 0.09025974025974026 | ||
# | ||
# Undirected: | ||
# Cluster A: |A| = 11: (2 + 1 + 0) / (11 * 10 / 2) = 0.05454545454545454 | ||
# Cluster B: |B| = 8: (1 + 0) / (8 * 7 / 2) = 0.03571428571428571 | ||
# Cluster C: |C| = 1: 0 | ||
# | ||
# Cohesion = 0.05454545454545454 + 0.03571428571428571 + 0 = 0.09025974025974026 | ||
# | ||
|
||
context "when the graph is directed" do | ||
include_context "with a simple directed graph" | ||
|
||
it "sets the cohesion values for each cluster, and for the graph" do | ||
metric.evaluate | ||
|
||
expect(graph.find_cluster("A").attributes[:cohesion]).to eq 0.05454545454545454 | ||
expect(graph.find_cluster("B").attributes[:cohesion]).to eq 0.03571428571428571 | ||
expect(graph.find_cluster("C").attributes[:cohesion]).to eq 0.0 | ||
expect(graph.attributes[:cohesion]).to eq 0.09025974025974026 | ||
end | ||
|
||
it "returns the total cohesion" do | ||
expect(metric.evaluate).to eq 0.09025974025974026 | ||
end | ||
end | ||
|
||
context "when the graph is undirected" do | ||
include_context "with a simple undirected graph" | ||
|
||
it "sets the cohesion values for each cluster, and for the graph" do | ||
metric.evaluate | ||
|
||
expect(graph.find_cluster("A").attributes[:cohesion]).to eq 0.05454545454545454 | ||
expect(graph.find_cluster("B").attributes[:cohesion]).to eq 0.03571428571428571 | ||
expect(graph.find_cluster("C").attributes[:cohesion]).to eq 0.0 | ||
expect(graph.attributes[:cohesion]).to eq 0.09025974025974026 | ||
end | ||
|
||
it "returns the total cohesion" do | ||
expect(metric.evaluate).to eq 0.09025974025974026 | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters