<commit_before>package kr.ac.kaist.ds.groupd.topology;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.stream.Collectors;

import org.jscience.mathematics.number.Real;
import org.jscience.mathematics.vector.SparseVector;

import peersim.config.Configuration;
import peersim.core.Node;
import peersim.dynamics.WireGraph;
import peersim.graph.Graph;

public class InterestTopology extends WireGraph {

	private static final String PAR_CLUSTER_COEFF = "coeff";
	private static final String PAR_PROTOCOL = "interest_protocol";
	private static final String PAR_NR_CAND_VOTES = "candVotes";
	private static final String PAR_REP_THRESHOLD = "repThreshold";

	private final double clusteringCoefficient;
	/**
	 * {@link InterestProtocol} pid
	 */
	private final int pid;
	private final int numberCandidateVotes;
	private final int representativeThreshold;

	public InterestTopology(String prefix) {
		super(prefix);
		clusteringCoefficient = Configuration.getDouble(parName(prefix,
				PAR_CLUSTER_COEFF));
		pid = Configuration.getPid(parName(prefix, PAR_PROTOCOL));
		numberCandidateVotes = Configuration.getInt(parName(prefix,
				PAR_NR_CAND_VOTES));
		representativeThreshold = Configuration.getInt(parName(prefix,
				PAR_REP_THRESHOLD));
	}

	private String parName(String prefix, String parName) {
		return prefix + "." + parName;
	}

	@Override
	public void wire(Graph g) {
		createLocalCommunities(g);
		createGlobalCommunities(g);
		resetVotes(g);
	}

	/**
	 * Creates the local community by creating edges between nodes whose similarity is
	 * greater than the {@link #clusteringCoefficient}.
	 */
	private void createLocalCommunities(Graph g) {
		//since I do not know how to combine two Linkable protocols
		//I use this workaround which assumes, that all nodes can see each other
		for (int i = 0; i < g.size(); i++) {
			Node node = (Node) g.getNode(i);
			for (int j = i + 1; j < g.size(); j++) {
				Node node2 = (Node) g.getNode(j);
				double similarity = calculateSimilarity(node, node2);
				if (similarity > clusteringCoefficient) {
					g.setEdge(i, j);
					InterestProtocol nodeProtocol = (InterestProtocol) node
							.getProtocol(pid);
					InterestProtocol node2Protocol = (InterestProtocol) node2
							.getProtocol(pid);
					nodeProtocol.addNeighbor(node2);
					node2Protocol.addNeighbor(node);
				}
			}
		}
	}

	/**
	 * Calculates the similarity based on the cosine similarity. 
	 * See <a href="https://en.wikipedia.org/wiki/Cosine_similarity">Wikipedia<a/>
	 * @param node
	 * @param node2
	 * @return
	 */
	private double calculateSimilarity(Node node, Node node2) {
		InterestProtocol nodeProtocol = (InterestProtocol) node
				.getProtocol(pid);
		InterestProtocol node2Protocol = (InterestProtocol) node2
				.getProtocol(pid);
		SparseVector<Real> interest = nodeProtocol.getInterest();
		SparseVector<Real> interest2 = node2Protocol.getInterest();
		Real dotProduct = interest.times(interest2);
		Double magnitude = calculateMagnitude(interest);
		Double magnitude2 = calculateMagnitude(interest);
		return dotProduct.doubleValue() / (magnitude * magnitude2);
	}

	/**
	 * Calculates the <a href="https://en.wikipedia.org/wiki/Magnitude_%28mathematics%29#Euclidean_vector_space">magnitude</a>
	 * of a vector.
	 * @param interest
	 * @return
	 */
	private Double calculateMagnitude(SparseVector<Real> interest) {
		Double sum = 0.0;
		for(int i = 0; i < interest.getDimension(); i++){
			sum += Math.pow(interest.get(i).doubleValue(), 2.0);
		}<commit_msg>changed some Double to double<commit_after>package kr.ac.kaist.ds.groupd.topology;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.stream.Collectors;

import org.jscience.mathematics.number.Real;
import org.jscience.mathematics.vector.SparseVector;

import peersim.config.Configuration;
import peersim.core.Node;
import peersim.dynamics.WireGraph;
import peersim.graph.Graph;

public class InterestTopology extends WireGraph {

	private static final String PAR_CLUSTER_COEFF = "coeff";
	private static final String PAR_PROTOCOL = "interest_protocol";
	private static final String PAR_NR_CAND_VOTES = "candVotes";
	private static final String PAR_REP_THRESHOLD = "repThreshold";

	private final double clusteringCoefficient;
	/**
	 * {@link InterestProtocol} pid
	 */
	private final int pid;
	private final int numberCandidateVotes;
	private final int representativeThreshold;

	public InterestTopology(String prefix) {
		super(prefix);
		clusteringCoefficient = Configuration.getDouble(parName(prefix,
				PAR_CLUSTER_COEFF));
		pid = Configuration.getPid(parName(prefix, PAR_PROTOCOL));
		numberCandidateVotes = Configuration.getInt(parName(prefix,
				PAR_NR_CAND_VOTES));
		representativeThreshold = Configuration.getInt(parName(prefix,
				PAR_REP_THRESHOLD));
	}

	private String parName(String prefix, String parName) {
		return prefix + "." + parName;
	}

	@Override
	public void wire(Graph g) {
		createLocalCommunities(g);
		createGlobalCommunities(g);
		resetVotes(g);
	}

	/**
	 * Creates the local community by creating edges between nodes whose similarity is
	 * greater than the {@link #clusteringCoefficient}.
	 */
	private void createLocalCommunities(Graph g) {
		//since I do not know how to combine two Linkable protocols
		//I use this workaround which assumes, that all nodes can see each other
		for (int i = 0; i < g.size(); i++) {
			Node node = (Node) g.getNode(i);
			for (int j = i + 1; j < g.size(); j++) {
				Node node2 = (Node) g.getNode(j);
				double similarity = calculateSimilarity(node, node2);
				System.out.println("Similarity between " + node.getID() + " and " + node2.getID() + ": " + similarity);
				if (similarity > clusteringCoefficient) {
					System.out.println("Similarity high enough" );
					System.out.println("");
					g.setEdge(i, j);
					InterestProtocol nodeProtocol = (InterestProtocol) node
							.getProtocol(pid);
					InterestProtocol node2Protocol = (InterestProtocol) node2
							.getProtocol(pid);
					nodeProtocol.addNeighbor(node2);
					node2Protocol.addNeighbor(node);
				}
			}
		}
	}

	/**
	 * Calculates the similarity based on the cosine similarity. 
	 * See <a href="https://en.wikipedia.org/wiki/Cosine_similarity">Wikipedia<a/>
	 * @param node
	 * @param node2
	 * @return
	 */
	private double calculateSimilarity(Node node, Node node2) {
		InterestProtocol nodeProtocol = (InterestProtocol) node
				.getProtocol(pid);
		InterestProtocol node2Protocol = (InterestProtocol) node2
				.getProtocol(pid);
		SparseVector<Real> interest = nodeProtocol.getInterest();
		SparseVector<Real> interest2 = node2Protocol.getInterest();
		Real dotProduct = interest.times(interest2);
		double magnitude = calculateMagnitude(interest);
		double magnitude2 = calculateMagnitude(interest);
		return dotProduct.doubleValue() / (magnitude * magnitude2);
	}

	/**
	 * Calculates the <a href="https://en.wikipedia.org/wiki/Magnitude_%28mathematics%29#Euclidean_vector_space">magnitude</a>
	 * of a vector.
	 * @param interest
	 * @return
	 */
	private double calculateMagnitude(SparseVector<Real> interest) {
		double sum = 0.0;
		for(int i = 0; i < interest.getDimension(); i++){
			sum += Math.pow(interest.get(i).doubleValue(), 2.0);
		}
{'fraction_non_alphanumeric': 0.11093226022803487, 'fraction_numerical': 0.007109322602280348, 'mean_word_length': 4.5724962630792225, 'pattern_counts': {'":': 1, '<': 23, '<?xml version=': 0, '>': 19, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3750849', 'n_tokens_mistral': 2608, 'n_tokens_neox': 2269, 'n_words': 564}