public code v1

This commit is contained in:
2026-05-22 11:14:29 +02:00
parent 427197ec5a
commit b8141736eb
28859 changed files with 575079 additions and 0 deletions
@@ -0,0 +1,949 @@
package afryca.consensusmodel.labella2020;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import afryca.cm.CM;
import afryca.consensusmodel.ConsensusEngine;
import afryca.consensusmodel.ConsensusModel;
import afryca.consensusmodel.EChangeType;
import afryca.consensusmodel.cluster.ClusterHLPR;
import afryca.consensusmodel.clustering.FuzzyCMeansHLPR;
import afryca.consensusmodel.definition.EResultElements;
import afryca.consensusmodel.definition.ERoundResult;
import afryca.domain.fuzzyset.FuzzySet;
import afryca.domain.fuzzyset.function.types.TrapezoidalFunction;
import afryca.domain.fuzzyset.labelset.LabelSet;
import afryca.hlpr.HLPR;
import afryca.hlpr.valuation.EUnaryRelationType;
import afryca.hlpr.valuation.HesitantLinguisticValuation;
import afryca.pr.PR;
import afryca.structure.Structure;
import afryca.structure.pair.Pair;
public class Labella2020 extends ConsensusModel {
private static final String CONSENSUS_MODEL_NAME = "Labella et al. (2020)"; //$NON-NLS-1$
private static final int CHANGE_DEGREE = 1;
private static final String MU = "mu"; //$NON-NLS-1$
private static final String DELTA = "delta"; //$NON-NLS-1$
private static final String MAX_ROUNDS = "h_max"; //$NON-NLS-1$
private static final String EPSILON = "epsilon"; //$NON-NLS-1$
private static final String ALPHA = "alpha"; //$NON-NLS-1$
private static final String BETA = "beta"; //$NON-NLS-1$
private ArrayList<TrapezoidalFunction[][]> trapezoidalPreferences;
private ArrayList<Float[][]> proximityMatrices;
private Map<Pair<Integer, Integer>, Float[][]> similarityMatrices;
private HLPR[] preferencesWithoutCollective;
private Structure[] preferencesAux;
private List<ClusterHLPR> postClusters;
private Map<Integer, Double> clustersCohesion;
private Map<Integer, Double> weights;
private CM cm;
private Float[] consensusAlternatives;
private TrapezoidalFunction[][] collective;
private int[] advises;
private int numberOfChanges;
private Integer h_max;
private Integer round;
private Float cr;
private Float delta;
private Float mu;
private Float epsilon;
private Float alpha;
private Float beta;
@Override
protected void setModelConfiguration() {}
@Override
protected void obtainConfigurationValues() {
mu = (Float) configuration.getValue(MU);
delta = (Float) configuration.getValue(DELTA);
h_max = (Integer) configuration.getValue(MAX_ROUNDS);
epsilon = (Float) configuration.getValue(EPSILON);
alpha = (Float) configuration.getValue(ALPHA);
beta = (Float) configuration.getValue(BETA);
preferencesAux = clonePreferencesUnion(preferences,
preferences[0].groupPreferences(numberOfExperts, numberOfAlternatives, numberOfCriteria,
Arrays.copyOfRange(preferences, 0, preferences.length - 1)));
preferencesWithoutCollective = new HLPR[preferences.length - 1];
postClusters = new LinkedList<ClusterHLPR>();
round = 0;
numberOfChanges = 0;
advises = null;
computePreferencesWithoutCollective();
initializeAdvises();
}
/**
* Initialize preferences without collective opinion
*/
private void computePreferencesWithoutCollective() {
// Copy preferences except collective
for (int i = 0; i < preferences.length - 1; i++) {
try {
preferencesWithoutCollective[i] = (HLPR) preferencesAux[i].clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
/**
* Initialize advises array
*/
private void initializeAdvises() {
advises = new int[experts.length];
for (int i = 0; i < advises.length; i++) {
advises[i] = 0;
}
}
@Override
protected void preFirstSaveRoundResults() {
Structure[] auxPreferences = clonePreferencesUnion(preferencesAux,
preferencesAux[0].groupPreferences(numberOfExperts, numberOfAlternatives, numberOfCriteria,
Arrays.copyOfRange(preferencesAux, 0, preferencesAux.length - 1)));
postClusters = generateClusters(alternatives, experts, preferencesWithoutCollective, 1);
computeClustersWeights();
computeConsensusDegree();
preSaveRoundResult(1, auxPreferences, obtainVisualizeValues(), cr);
roundsResults.get(roundsResults.size() - 1).put(ERoundResult.clusters, postClusters);
result.put(EResultElements.initial_consensus_degree, cr);
result.put(EResultElements.maxround, h_max);
result.put(EResultElements.consensus_threshold, mu);
result.put(EResultElements.consensus_model, CONSENSUS_MODEL_NAME);
}
@SuppressWarnings("unchecked")
public List<ClusterHLPR> generateClusters(String[] alternatives, String[] experts, HLPR[] preferences, float parameter) {
return (roundsResults.isEmpty()
? FuzzyCMeansHLPR.doClusteringFuzzyCMeansClusterForEachAlternative(alternatives, experts, preferences,
null, parameter)
: FuzzyCMeansHLPR.doClusteringFuzzyCMeansClusterForEachAlternative(alternatives, experts, preferences,
(List<ClusterHLPR>) roundsResults.get(roundsResults.size() - 1).get(ERoundResult.clusters),
parameter));
}
private void computeClustersWeights() {
Map<Integer, ArrayList<TrapezoidalFunction>[][]> clustersEnvelopes = computeFuzzyEnvelopes();
clustersCohesion = computeCohesion(clustersEnvelopes);
weights = computeWeights();
}
private Map<Integer, ArrayList<TrapezoidalFunction>[][]> computeFuzzyEnvelopes() {
ArrayList<TrapezoidalFunction>[][] envelopes;
Map<Integer, ArrayList<TrapezoidalFunction>[][]> clustersEnvelopes = new HashMap<>();
for (ClusterHLPR cluster: postClusters) {
if(cluster.getSize() != 0)
envelopes = computeFuzzyEnvelopesCluster(cluster.getPreferences());
else
envelopes = null;
clustersEnvelopes.put(cluster.getId(), envelopes);
}
return clustersEnvelopes;
}
@SuppressWarnings("unchecked")
private ArrayList<TrapezoidalFunction>[][] computeFuzzyEnvelopesCluster(Map<Integer, PR> preferences) {
ArrayList<TrapezoidalFunction>[][] envelopes = new ArrayList[this.numberOfAlternatives][this.numberOfAlternatives];
for (int i = 0; i < this.numberOfAlternatives; ++i) {
for (int j = 0; j < this.numberOfAlternatives; ++j) {
if (i != j) {
ArrayList<TrapezoidalFunction> fuzzyEnvelopes = new ArrayList<>();
for(Integer expertId: preferences.keySet()) {
HesitantLinguisticValuation cle = ((HLPR) preferences.get(expertId)).getHesitantLinguisticValuation(i, j);
fuzzyEnvelopes.add(ConsensusEngine.calculateFuzzyEnvelope((FuzzySet) cle.getDomain(), cle));
}
envelopes[i][j] = fuzzyEnvelopes;
}
}
}
return envelopes;
}
private Map<Integer, Double> computeCohesion(Map<Integer, ArrayList<TrapezoidalFunction>[][]> clustersEnvelopes) {
Map<Integer, Double> cohesion_cluster = new HashMap<>();
Double[][] cohesion_distance_pairs = new Double[numberOfAlternatives][numberOfAlternatives];
for(int cluster: clustersEnvelopes.keySet()) {
for (int i = 0; i < this.numberOfAlternatives - 1; ++i) {
for (int j = i + 1; j < this.numberOfAlternatives; ++j) {
if(clustersEnvelopes.get(cluster) == null)// clusters without experts
cohesion_distance_pairs[i][j] = 0d;
else if(postClusters.get(cluster).getSize() == 1)
cohesion_distance_pairs[i][j] = 1d;
else {
ArrayList<TrapezoidalFunction> envelopes_pair = clustersEnvelopes.get(cluster)[i][j];
cohesion_distance_pairs[i][j] = computeDistanceCohesionPairAlternatives(envelopes_pair);
}
}
}
cohesion_cluster.put(cluster, computeCohesionCluster(cohesion_distance_pairs));
}
return cohesion_cluster;
}
private double computeDistanceCohesionPairAlternatives(ArrayList<TrapezoidalFunction> envelopes) {
double numerator;
ArrayList<TrapezoidalFunction> pairEnvelopes = new ArrayList<>();
ArrayList<Double> cohesionValuesPairEnvelopes = new ArrayList<Double>();
if(envelopes == null) return 0d;
for(int i = 0; i < envelopes.size() - 1; ++i) {
pairEnvelopes.clear();
pairEnvelopes.add(envelopes.get(i));
for(int j = i + 1; j < envelopes.size(); ++j) {
pairEnvelopes.add(envelopes.get(j));
numerator = computeCohesionNumerator(pairEnvelopes);
pairEnvelopes.remove(1);
cohesionValuesPairEnvelopes.add(numerator);
}
}
return cohesionValuesPairEnvelopes.stream().mapToDouble(value -> value).sum() / cohesionValuesPairEnvelopes.size();
}
private double computeCohesionNumerator(ArrayList<TrapezoidalFunction> envelopes_pair) {
double m = computem(envelopes_pair);
double M = computeM(envelopes_pair);
return 1d - (Math.abs(M - m));
}
private double computem(ArrayList<TrapezoidalFunction> envelopes_pair) {
double min = Double.MAX_VALUE;
for(TrapezoidalFunction envelope: envelopes_pair) {
if(envelope.getA() < min)
min = envelope.getA();
}
return min;
}
private double computeM(ArrayList<TrapezoidalFunction> envelopes_pair) {
double max = Double.MIN_VALUE;
for(TrapezoidalFunction envelope: envelopes_pair) {
if(envelope.getD() > max)
max = envelope.getD();
}
return max;
}
/*@SuppressWarnings("serial")
private double computeCohesionDenominator(ArrayList<TrapezoidalFunction> envelopes_pair) {
double m, M;
ArrayList<Double> envelopes_values = new ArrayList<>();
for(TrapezoidalFunction envelope: envelopes_pair) {
m = computem(new ArrayList<TrapezoidalFunction>() {{add(envelope);}});
M = computeM(new ArrayList<TrapezoidalFunction>() {{add(envelope);}});
envelopes_values.add(1d - (Math.abs(M - m)));
}
return Collections.max(envelopes_values);
}*/
private Double computeCohesionCluster(Double[][] cohesion_pairs) {
double clusterCohesion = 0;
for (int i = 0; i < this.numberOfAlternatives - 1; ++i) {
for (int j = i + 1; j < this.numberOfAlternatives; ++j)
clusterCohesion += cohesion_pairs[i][j];
}
return clusterCohesion / ((numberOfAlternatives * (numberOfAlternatives - 1)) / 2d);
}
private Map<Integer, Double> computeWeights() {
Map<Integer, Double> nonNormalizedWeights = new HashMap<>();
double A, sigma, acumSigma = 0, size;
for (Integer clusterId : clustersCohesion.keySet()) {
size = postClusters.get(clusterId).getSize();
if(size == 0)
nonNormalizedWeights.put(clusterId, 0d);
else {
A = clustersCohesion.get(clusterId);
sigma = Math.sqrt(Math.pow(A, alpha) * Math.pow(size, beta));
nonNormalizedWeights.put(clusterId, sigma);
acumSigma += sigma;
}
}
return normalizeWeights(nonNormalizedWeights, acumSigma);
}
/*private double computeMembershipClusterSize(int size) {
TrapezoidalFunction membershipFunctionSize = new TrapezoidalFunction(pointA, pointB, 100f, 100f);
return membershipFunctionSize.getMembershipValue(size);
}*/
private Map<Integer, Double> normalizeWeights(Map<Integer, Double> nonNormalizedWeights, double acumSigma) {
List<Double> weight_clusters = new ArrayList<Double>();
weights = new HashMap<>();
for (Integer clusterId : nonNormalizedWeights.keySet()) {
weights.put(clusterId, nonNormalizedWeights.get(clusterId) / acumSigma);
weight_clusters.add(clusterId, weights.get(clusterId));
}
//results.add(weight_clusters);
//printResultsWord();
return weights;
}
/*private void printResultsLatex() {
String info = "";
for(int i = 0; i < postClusters.size(); ++i) {
info = "";
for(int j = 0; j < results.size(); ++j) {
if(j == 0) {
info += " & " + Math.round(results.get(j).get(i) * 1000d) / 1000d;
} else if(j == 1) {
info += " & " + Math.round(results.get(j).get(i));
} else {
info += " & " + Math.round(results.get(j).get(i) * 1000d) / 1000d;
}
}
//info = info.substring(0, info.length() - 2);
System.out.println(info);
}
}*/
/*private void printResultsWord() {
for(int i = 0; i < postClusters.size(); ++i) {
System.out.println("group" + (i+1) + ": " + "size = " + postClusters.get(i).getSize() + " coh = " +
Math.round(results.get(0).get(i) * 1000d) / 1000d + " w = " + Math.round(weights.get(i) * 1000d) / 1000d + " con = " + Math.round(results.get(2).get(i) * 100d) / 100d
+ " rank = " + computeRankingCluster(postClusters.get(i)));
}
}*/
private void computeConsensusDegree() {
transformValuationIntroTrapezoidalFuctions();
computeSimilarityMatrices();
computeConsensusMatrix();
computeConsensusAlternatives();
computeOverallConsensusDegree();
computeCollective();
}
private void transformValuationIntroTrapezoidalFuctions() {
Structure[] auxPreferences = Arrays.copyOfRange(preferencesAux, 0, preferencesAux.length - 1);
trapezoidalPreferences = new ArrayList<>();
TrapezoidalFunction[][] trapezoidalMatrix;
for (Structure hlpr : auxPreferences) {
trapezoidalMatrix = new TrapezoidalFunction[numberOfAlternatives][numberOfAlternatives];
for (int i = 0; i < numberOfAlternatives; ++i) {
for (int j = 0; j < numberOfAlternatives; ++j) {
trapezoidalMatrix[i][j] = ConsensusEngine.calculateFuzzyEnvelope((FuzzySet) hlpr.getDomain(),
(HesitantLinguisticValuation) hlpr.getValue(i, j));
}
}
trapezoidalPreferences.add(trapezoidalMatrix);
}
}
private void computeSimilarityMatrices() {
similarityMatrices = new LinkedHashMap<>();
Float similarityValue;
for (int i = 0; i < numberOfExperts - 1; ++i) {
for (int t = i + 1; t < numberOfExperts; ++t) {
Float[][] similarityMatrix = new Float[numberOfAlternatives][numberOfAlternatives];
Pair<Integer, Integer> pairExperts = new Pair<Integer, Integer>(i, t);
for (int l = 0; l < numberOfAlternatives - 1; ++l) {
for (int k = l + 1; k < numberOfAlternatives; ++k) {
similarityValue = computeSimilarity(trapezoidalPreferences.get(i)[l][k], trapezoidalPreferences.get(t)[l][k]);
similarityMatrix[l][k] = similarityValue;
similarityMatrix[k][l] = similarityValue;
}
}
similarityMatrices.put(pairExperts, similarityMatrix);
}
}
}
private Float computeSimilarity(TrapezoidalFunction trp1, TrapezoidalFunction trp2) {
return (float) (1f - trp1.distance(trp2, 1));
}
private void computeConsensusMatrix() {
List<Float> sim = new LinkedList<Float>();
cm = new CM(numberOfAlternatives);
for (int l = 0; l < numberOfAlternatives; ++l) {
for (int k = 0; k < numberOfAlternatives; ++k) {
sim.clear();
if(l != k) {
for (Pair<Integer, Integer> pairExperts : similarityMatrices.keySet())
sim.add(similarityMatrices.get(pairExperts)[l][k]);
cm.setValue(l, k, aggregateSIMValues(sim));
} else {
cm.setValue(l, k, 1f);
}
}
}
}
private Float aggregateSIMValues(List<Float> sim) {
Float arithmeticMean = 0f;
for (Float simValue : sim)
arithmeticMean += simValue;
return arithmeticMean / sim.size();
}
private void computeConsensusAlternatives() {
consensusAlternatives = ConsensusEngine.computeAlternativesConsensus(numberOfAlternatives, cm);
}
private void computeOverallConsensusDegree() {
cr = ConsensusEngine.consensusBasedOnAlternativesConsensus(numberOfAlternatives, consensusAlternatives);
}
private void computeCollective() {
preferencesAux[preferencesAux.length - 1] = preferencesAux[0].groupPreferences(numberOfExperts,
numberOfAlternatives, numberOfCriteria,
Arrays.copyOfRange(preferencesAux, 0, preferencesAux.length - 1));
}
@Override
protected void preSaveRoundResults() {
preSaveRoundResult(round + 1, preferencesAux, obtainVisualizeValues(), cr);
roundsResults.get(roundsResults.size() - 1).put(ERoundResult.clusters, postClusters);
}
@Override
protected void consensusRound() {
advises = null;
computeConsensusDegree();
computeTrapezoidalCollective();
if (cr < mu) {
if (cr < delta)
groupAdviceGeneration();
else
individualAdviceGeneration();
computePreferencesWithoutCollective();
postClusters = generateClusters(alternatives, experts, preferencesWithoutCollective, 2f);
computeClustersWeights();
round++;
}
}
private void groupAdviceGeneration() {
computeProximityMatrices();
computeGroupChanges();
}
private void computeTrapezoidalCollective() {
collective = new TrapezoidalFunction[numberOfAlternatives][numberOfAlternatives];
for (int l = 0; l < numberOfAlternatives; ++l) {
for (int k = 0; k < numberOfAlternatives; ++k) {
if(l != k) {
collective[l][k] = new TrapezoidalFunction(new double[] {0d, 0d, 0d, 0d});
for (ClusterHLPR cluster : postClusters) {
TrapezoidalFunction envelope = ((TrapezoidalFunction[][]) cluster.getCentroid())[l][k];
TrapezoidalFunction weightedEnvelope = envelope.multiplicationScalar(weights.get(cluster.getId()));
collective[l][k] = collective[l][k].addition(weightedEnvelope);
}
} else {
LabelSet labels = ((ClusterHLPR) postClusters.get(0)).getDomain().getLabelSet();
collective[l][k] = (TrapezoidalFunction) labels.getLabel((labels.getCardinality() + 1) / 2).getSemantic();
}
}
}
}
private void computeProximityMatrices() {
proximityMatrices = new ArrayList<>();
Float[][] proximityMatrix;
for (int i = 0; i < postClusters.size(); ++i) {
proximityMatrix = new Float[numberOfAlternatives][numberOfAlternatives];
for (int l = 0; l < numberOfAlternatives; ++l) {
for (int k = 0; k < numberOfAlternatives; ++k)
proximityMatrix[l][k] = computeSimilarity(((TrapezoidalFunction[][]) postClusters.get(i).getCentroid())[l][k], collective[l][k]);
}
proximityMatrices.add(proximityMatrix);
}
}
private void computeGroupChanges() {
List<Integer> clustersLessCohesion = getClustersWithLessCohesion();
Map<Integer, List<Pair<Integer, Integer>>> changesToDo = identifyChangesToDoByGroup(clustersLessCohesion);
EChangeType[][][] changesDirection = computeGroupChangesDirection(changesToDo);
makeChanges(changesDirection);
computeIndividualNumberOfAdvises(changesDirection);
}
private List<Integer> getClustersWithLessCohesion() {
List<Integer> clustersWithLessCohesion = new ArrayList<>();
for(Integer cluster: clustersCohesion.keySet())
clustersWithLessCohesion.add(cluster);
return clustersWithLessCohesion;
}
private Map<Integer, List<Pair<Integer, Integer>>> identifyChangesToDoByGroup(List<Integer> clustersLessCohesion) {
Map<Integer, List<Pair<Integer, Integer>>> changes = new HashMap<>();
List<Integer> alternativesToChange = getAlternativesToChange();
Float[][] overallProximityMatrix = computeOverallProximityValues();
for(Integer cluster: clustersLessCohesion) {
for(int alt: alternativesToChange) {
for(int j = 0 ; j < numberOfAlternatives; ++j) {
if(j > alt) {
if(proximityMatrices.get(cluster)[alt][j] < overallProximityMatrix[alt][j]) {
Pair<Integer, Integer> pair = new Pair<Integer, Integer>(alt, j);
if(changes.get(cluster) == null) {
List<Pair<Integer, Integer>> pairsAlternatives = new LinkedList<>();
pairsAlternatives.add(pair);
changes.put(cluster, pairsAlternatives);
} else {
List<Pair<Integer, Integer>> pairsAlternatives = changes.get(cluster);
pairsAlternatives.add(pair);
}
}
}
}
}
}
return changes;
}
private List<Integer> getAlternativesToChange() {
List<Integer> alternativesToChange = new LinkedList<>();
for (int l = 0; l < numberOfAlternatives; ++l) {
Float consensusAlternative = consensusAlternatives[l];
if (consensusAlternative < mu)
alternativesToChange.add(l);
}
return alternativesToChange;
}
private Float[][] computeOverallProximityValues() {
Float[][] overallProximityMatrix = new Float[numberOfAlternatives][numberOfAlternatives];
Float[][] proximityMatrix;
float acum;
for(int l = 0; l < numberOfAlternatives; ++l) {
for(int j = 0; j < numberOfAlternatives; ++j) {
acum = 0;
for(int u = 0; u < postClusters.size(); ++u) {
proximityMatrix = proximityMatrices.get(u);
acum += proximityMatrix[l][j];
}
overallProximityMatrix[l][j] = acum / postClusters.size();
}
}
return overallProximityMatrix;
}
private EChangeType[][][] computeGroupChangesDirection(Map<Integer, List<Pair<Integer, Integer>>> groupsToChange) {
int a1, a2;
Float difference;
EChangeType[][][] result = initializeIndividualChanges();
for (Integer group : groupsToChange.keySet()) {
List<Pair<Integer, Integer>> pairAlternativesToChange = groupsToChange.get(group);
for(Pair<Integer, Integer> pairAlternatives: pairAlternativesToChange) {
a1 = pairAlternatives.getLeft();
a2 = pairAlternatives.getRight();
difference = (float) (((TrapezoidalFunction[][]) postClusters.get(group).getCentroid())[a1][a2].getSimpleDefuzzifiedValue() - collective[a1][a2].getSimpleDefuzzifiedValue());
if (difference < (-epsilon)) {
for(Integer exp: postClusters.get(group).getExperts()) {
result[exp][a1][a2] = EChangeType.Increase;
numberOfChanges++;
}
} else if (difference > epsilon) {
for(Integer exp: postClusters.get(group).getExperts()) {
result[exp][a1][a2] = EChangeType.Decrease;
numberOfChanges++;
}
}
}
}
return result;
}
private void makeChanges(EChangeType[][][] changes) {
HesitantLinguisticValuation value;
EChangeType change;
double[] changesToMake = getNChanges(numberOfChanges);
//===========================100===================================//
/*double[] changesToMake = new double[numberOfExperts];
for(int i = 0; i < numberOfExperts; ++i) {
changesToMake[i] = 1;
}*/
//===========================75===================================//
/*double[] changesToMake = new double[numberOfExperts];
for(int i = 0; i < numberOfExperts; ++i) {
if(i == 13 || i == 31 ||
i == 9 || i == 47 ||
i == 32 || i == 37 ||
i == 4)
changesToMake[i] = 0;
else
changesToMake[i] = 1;
}*/
/*double[] changesToMake = new double[numberOfExperts];
for(int i = 0; i < numberOfExperts; ++i) {
if(i == 13 || i == 19 || i == 30 ||
i == 7 || i == 24 || i == 40 ||
i == 6 || i == 17 || i == 31 || i == 37 ||
i == 3 || i == 25)
changesToMake[i] = 0;
else
changesToMake[i] = 1;
}*/
/*double[] changesToMake = new double[numberOfExperts];
for(int i = 0; i < numberOfExperts; ++i) {
if(i == 7 || i == 17 || i == 30 || i == 51 ||
i == 19 || i == 29 || i == 38 || i == 46 || i == 67 ||
i == 5 || i == 18 || i == 31 || i == 37 || i == 55 ||
i == 1 || i == 14 || i == 21 || i == 41 || i == 72)
changesToMake[i] = 0;
else
changesToMake[i] = 1;
}*/
//===========================50===================================//
/*double[] changesToMake = new double[numberOfExperts];
for(int i = 0; i < numberOfExperts; ++i) {
if(i == 5 || i == 7 || i == 18 || i == 11 || i == 24 ||
i == 0 || i == 19 || i == 22 ||
i == 4 || i == 20 || i == 26 ||
i == 2 || i == 6 || i == 13 || i == 16)
changesToMake[i] = 0;
else
changesToMake[i] = 1;
}*/
/*double[] changesToMake = new double[numberOfExperts];
for(int i = 0; i < numberOfExperts; ++i) {
if(i == 10 || i == 13 || i == 19 || i == 30 || i == 34 || i == 42 ||
i == 0 || i == 7 || i == 24 || i == 40 || i == 43 || i == 49 ||
i == 1 || i == 4 || i == 6 || i == 16 || i == 17 || i == 31 || i == 37 ||
i == 2 || i == 3 || i == 9 || i == 22 || i == 25 || i == 41)
changesToMake[i] = 0;
else
changesToMake[i] = 1;
}*/
int currentChange = 0;
float ch;
for (int i = 0; i < numberOfExperts; i++) {
for (int l = 0; l < numberOfAlternatives; l++) {
for (int k = 0; k < numberOfAlternatives; k++) {
if (l != k) {
change = changes[i][l][k];
if (change != EChangeType.NotChange) {
ch = (float) changesToMake[currentChange++];
//ch = (float) changesToMake[i];
if (ch != 0f) {
value = (HesitantLinguisticValuation) preferencesAux[i].getValue(l, k);
if (change == EChangeType.Increase) {
value = increaseCase(i, l, k);
} else if (change == EChangeType.Decrease) {
value = decreaseCase(i, l, k);
}
((HLPR) preferencesAux[i]).setValueSymmetrically(l, k, value);
}
}
}
}
}
}
}
private HesitantLinguisticValuation increaseCase(int i, int l, int k) {
HesitantLinguisticValuation hlv = (HesitantLinguisticValuation) preferencesAux[i].getValue(l, k);
FuzzySet fuzzySet = (FuzzySet) hlv.getDomain();
if (hlv.isPrimary()) {
int posLabel = fuzzySet.getLabelSet().getPos(hlv.getLabel());
if(posLabel + CHANGE_DEGREE < fuzzySet.getLabelSet().getCardinality() - 1)
hlv.setLabel(posLabel + CHANGE_DEGREE);
} else if (hlv.isUnary()) {
int posTerm = fuzzySet.getLabelSet().getPos(hlv.getTerm()), cardinality = fuzzySet.getLabelSet().getCardinality();
if(posTerm + CHANGE_DEGREE < fuzzySet.getLabelSet().getCardinality() - 1) {//Is it possible the change?
if((hlv.getUnaryRelation().equals(EUnaryRelationType.AtMost) || hlv.getUnaryRelation().equals(EUnaryRelationType.LowerThan))
&& (posTerm + CHANGE_DEGREE > (cardinality + 1) / 2)) {//Too many labels in the unary expression
hlv.setLabel(posTerm + CHANGE_DEGREE);
} else if((posTerm + CHANGE_DEGREE == cardinality - 1) && (hlv.getUnaryRelation().equals(EUnaryRelationType.GreaterThan)))
hlv.setLabel(cardinality - 1);
else
hlv.setUnaryRelation(hlv.getUnaryRelation(), posTerm + CHANGE_DEGREE);
}
} else {
int posTerm1 = fuzzySet.getLabelSet().getPos(hlv.getLowerTerm());
int posTerm2 = fuzzySet.getLabelSet().getPos(hlv.getUpperTerm());
if (posTerm1 + CHANGE_DEGREE == posTerm2)
hlv.setLabel(posTerm2);
else if (posTerm1 + CHANGE_DEGREE < posTerm2)
hlv.setBinaryRelation(posTerm1 + CHANGE_DEGREE, posTerm2);
}
return hlv;
}
private HesitantLinguisticValuation decreaseCase(int i, int l, int k) {
HesitantLinguisticValuation hlv = (HesitantLinguisticValuation) preferencesAux[i].getValue(l, k);
FuzzySet fuzzySet = (FuzzySet) hlv.getDomain();
if (hlv.isPrimary()) {
int posLabel = fuzzySet.getLabelSet().getPos(hlv.getLabel());
if(posLabel - CHANGE_DEGREE >= 0)
hlv.setLabel(posLabel - CHANGE_DEGREE);
} else if (hlv.isUnary()) {
int posTerm = fuzzySet.getLabelSet().getPos(hlv.getTerm()), cardinality = fuzzySet.getLabelSet().getCardinality();
if(posTerm - CHANGE_DEGREE >= 0)
if((hlv.getUnaryRelation().equals(EUnaryRelationType.AtLeast) || hlv.getUnaryRelation().equals(EUnaryRelationType.GreaterThan))
&& (posTerm - CHANGE_DEGREE < ((cardinality + 1) / 2) - 1)) {//To many labels in the unary expression
hlv.setLabel(posTerm - CHANGE_DEGREE);
} else if((posTerm - CHANGE_DEGREE == 0) && (hlv.getUnaryRelation().equals(EUnaryRelationType.LowerThan)))
hlv.setLabel(0);
else
hlv.setUnaryRelation(hlv.getUnaryRelation(), posTerm - CHANGE_DEGREE);
} else {
int posTerm1 = fuzzySet.getLabelSet().getPos(hlv.getLowerTerm());
int posTerm2 = fuzzySet.getLabelSet().getPos(hlv.getUpperTerm());
if (posTerm2 - CHANGE_DEGREE == posTerm1)
hlv.setLabel(posTerm1);
else if(posTerm2 - CHANGE_DEGREE >= posTerm1)
hlv.setBinaryRelation(posTerm1, posTerm2 - CHANGE_DEGREE);
}
return hlv;
}
private void individualAdviceGeneration() {
computeProximityMatrices();
computeIndividualChanges();
}
private void computeIndividualChanges() {
Map<Integer, List<Pair<Integer, Integer>>> changesToDo = identifyChangesToDoByIndividual();
EChangeType[][][] changesDirection = computeIndividualChangesDirection(changesToDo);
makeChanges(changesDirection);
computeIndividualNumberOfAdvises(changesDirection);
}
private Map<Integer, List<Pair<Integer, Integer>>> identifyChangesToDoByIndividual() {
Float similarity;
List<Integer> alternativesToChange = getAlternativesToChange();
Float[][] overallProximityMatrix = computeOverallProximityValues();
Map<Integer, List<Pair<Integer, Integer>>> expertsToChange = new HashMap<>();
for (ClusterHLPR cluster: postClusters) {
for (Integer exp : cluster.getExperts()) {
for (int alt: alternativesToChange) {
for(int j = 0; j < numberOfAlternatives; ++j) {
//if(alt > j) {
similarity = computeSimilarity(collective[alt][j], trapezoidalPreferences.get(exp)[alt][j]);
if (similarity <= overallProximityMatrix[alt][j]) {
if (expertsToChange.get(exp) == null) {
List<Pair<Integer, Integer>> pairAlternativesToChangeByGroup = new LinkedList<>();
pairAlternativesToChangeByGroup.add(new Pair<Integer, Integer>(alt, j));
expertsToChange.put(exp, pairAlternativesToChangeByGroup);
} else {
expertsToChange.get(exp).add(new Pair<Integer, Integer>(alt, j));
}
}
//}
}
}
}
}
return expertsToChange;
}
private EChangeType[][][] computeIndividualChangesDirection(Map<Integer, List<Pair<Integer, Integer>>> expertsToChange) {
EChangeType[][][] result = initializeIndividualChanges();
Float difference;
int l,k;
for (Integer i : expertsToChange.keySet()) {
List<Pair<Integer, Integer>> pairAlternativesToChange = expertsToChange.get(i);
for(Pair<Integer, Integer> pairAlternatives: pairAlternativesToChange) {
l = pairAlternatives.getLeft();
k = pairAlternatives.getRight();
difference = (float) ((float) trapezoidalPreferences.get(i)[l][k].getSimpleDefuzzifiedValue() - collective[l][k].getSimpleDefuzzifiedValue());
if (difference < (-epsilon)) {
result[i][l][k] = EChangeType.Increase;
numberOfChanges++;
} else if (difference > epsilon) {
result[i][l][k] = EChangeType.Decrease;
numberOfChanges++;
} else if ((-epsilon) <= difference && difference <= epsilon) {
result[i][l][k] = EChangeType.NotChange;
}
}
}
return result;
}
private EChangeType[][][] initializeIndividualChanges() {
EChangeType[][][] result = new EChangeType[numberOfExperts][numberOfAlternatives][numberOfAlternatives];
for (int i = 0; i < numberOfExperts; i++) {
for (int l = 0; l < numberOfAlternatives; l++) {
for (int k = 0; k < numberOfAlternatives; k++) {
result[i][l][k] = EChangeType.NotChange;
}
}
}
numberOfChanges = 0;
return result;
}
private void computeIndividualNumberOfAdvises(EChangeType[][][] changesDirection) {
advises = new int[numberOfExperts];
for (int i = 0; i < numberOfExperts; i++) {
advises[i] = 0;
for (int l = 0; l < numberOfAlternatives; l++) {
for (int k = 0; k < numberOfAlternatives; k++) {
if (changesDirection[i][l][k] != EChangeType.NotChange) {
advises[i] = advises[i] + 1;
}
}
}
}
}
@Override
protected void posSaveRoundResults() {
computeConsensusDegree();
posSaveRoundResult(preferencesAux, obtainVisualizeValues(), cr, advises,
preferencesAux[preferencesAux.length - 1]);
}
@Override
protected boolean mustBeCarriedOutAnotherRound() {
return (cr < mu) && (round < h_max);
}
@Override
protected Float[][][] obtainVisualizeValues() {
Structure[] auxPreferences = clonePreferencesUnion(preferencesAux,
preferencesAux[0].groupPreferences(numberOfExperts, numberOfAlternatives, numberOfCriteria,
Arrays.copyOfRange(preferencesAux, 0, preferencesAux.length - 1)));
Float[][][] preferencesGroupVisualization = new Float[numberOfExperts
+ 1][numberOfAlternatives][numberOfAlternatives];
for (int i = 0; i < numberOfExperts + 1; i++)
preferencesGroupVisualization[i] = auxPreferences[i].obtainVisualizeValues();
return preferencesGroupVisualization;
}
@Override
protected void saveExecutionResults() {
this.configuration.setValue(PREFERENCES, preferencesAux);
result.put(EResultElements.number_of_rounds_required, round);
result.put(EResultElements.consensus_degree_achieved, cr);
}
}