All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.puresoltechnologies.purifinity.server.metrics.entropy.EntropyMetric Maven / Gradle / Ivy

/***************************************************************************
 *
 *   EntropyMetric.java
 *   -------------------
 *   copyright            : (c) 2009 by PureSol-Technologies
 *   author               : Rick-Rainer Ludwig
 *   email                : [email protected]
 *
 ***************************************************************************/

package com.puresoltechnologies.purifinity.server.metrics.entropy;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Set;

import com.puresoltechnologies.commons.domain.ConfigurationParameter;
import com.puresoltechnologies.purifinity.analysis.api.AnalysisRun;
import com.puresoltechnologies.purifinity.analysis.domain.CodeRange;
import com.puresoltechnologies.purifinity.analysis.domain.ProgrammingLanguage;
import com.puresoltechnologies.purifinity.evaluation.api.iso9126.QualityCharacteristic;
import com.puresoltechnologies.purifinity.evaluation.domain.SourceCodeQuality;
import com.puresoltechnologies.purifinity.evaluation.domain.metrics.MetricValue;
import com.puresoltechnologies.purifinity.server.core.api.evaluation.CodeRangeEvaluator;
import com.puresoltechnologies.purifinity.server.metrics.halstead.HalsteadMetric;
import com.puresoltechnologies.versioning.Version;

/**
 * This class calculates entropy and redundancy for a code range. The entropy is
 * only calculated for operands due to the fact that only they are chosen by the
 * programmer. The entropy gives therefore a hint how well the programmed.
 * 
 * @author Rick-Rainer Ludwig
 * 
 */
public class EntropyMetric extends CodeRangeEvaluator {

	public static final String ID = EntropyMetric.class.getName();

	public static final String NAME = "Entropy Metric";

	public static final Version PLUGIN_VERSION = new Version(1, 0, 0);

	public static final String DESCRIPTION = "Entropy Metric calculation.";

	public static final List> PARAMETERS = new ArrayList<>();

	public static final Set EVALUATED_QUALITY_CHARACTERISTICS = new HashSet();
	static {
		EVALUATED_QUALITY_CHARACTERISTICS
				.add(QualityCharacteristic.ANALYSABILITY);
	}

	public static final Set DEPENDENCIES = new HashSet<>();
	static {
		DEPENDENCIES.add(HalsteadMetric.ID);
	}

	private final AnalysisRun analysisRun;
	private final CodeRange codeRange;
	private final HalsteadMetric halstead;
	private EntropyMetricResult result;

	public EntropyMetric(AnalysisRun analysisRun, ProgrammingLanguage language,
			CodeRange codeRange) {
		super(NAME);
		this.analysisRun = analysisRun;
		this.codeRange = codeRange;
		halstead = new HalsteadMetric(analysisRun, language, getCodeRange());
	}

	@Override
	public AnalysisRun getAnalysisRun() {
		return analysisRun;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public CodeRange getCodeRange() {
		return codeRange;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean run() {
		boolean retVal = calculate();
		recreateResultsList();
		return retVal;
	}

	private boolean calculate() {
		halstead.run();

		Hashtable operands = halstead.getOperands();

		double maxEntropy = Math.log(halstead.getDifferentOperands())
				/ Math.log(2.0);
		double entropy = 0.0;
		for (String operant : operands.keySet()) {
			int count = operands.get(operant);
			entropy += count / (double) halstead.getTotalOperands()
					* Math.log(count / (double) halstead.getTotalOperands())
					/ Math.log(2.0);
		}
		entropy *= -1.0;
		double normEntropy = entropy / maxEntropy;
		double entropyRedundancy = maxEntropy - entropy;
		double redundancy = entropyRedundancy * halstead.getDifferentOperands()
				/ maxEntropy;
		double normalizedRedundancy = redundancy
				/ halstead.getDifferentOperands();
		result = new EntropyMetricResult(halstead.getVocabularySize(),
				halstead.getProgramLength(), entropy, maxEntropy, normEntropy,
				entropyRedundancy, redundancy, normalizedRedundancy);
		return true;
	}

	private void recreateResultsList() {

	}

	public double getNTotal() {
		return result.getNTotal();
	}

	public double getNDiff() {
		return result.getNDiff();
	}

	public double getMaxEntropy() {
		return result.getMaxEntropy();
	}

	public double getEntropy() {
		return result.getEntropy();
	}

	public double getNormEntropy() {
		return result.getNormEntropy();
	}

	public double getEntropyRedundancy() {
		return result.getEntropyRedundancy();
	}

	public double getRedundancy() {
		return result.getRedundancy();
	}

	public double getNormalizedRedundancy() {
		return result.getNormalizedRedundancy();
	}

	public String getResultsAsString() {
		String result = "number of symbols = " + getNTotal() + "\n";
		result += "max entropy = " + getMaxEntropy() + "\n";
		result += "entropy = " + getEntropy() + "\n";
		result += "normalized entropy = " + getNormEntropy() + "\n";
		result += "entropy redundance = " + getEntropyRedundancy() + "\n";
		result += "redundancy = " + getRedundancy() + "\n";
		result += "normalized redundancy = " + getNormalizedRedundancy() + "\n";
		return result;
	}

	public void print() {
		System.out.println(getResultsAsString());
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public SourceCodeQuality getQuality() {
		if (getNormalizedRedundancy() > 0.40) {
			return SourceCodeQuality.LOW;
		}
		if (getNormalizedRedundancy() > 0.20) {
			return SourceCodeQuality.MEDIUM;
		}
		return SourceCodeQuality.HIGH;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public String getDescription() {
		return DESCRIPTION;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Set getEvaluatedQualityCharacteristics() {
		return EVALUATED_QUALITY_CHARACTERISTICS;
	}

	@Override
	public List> getResults() {
		return result.getResults();
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy