786 lines
27 KiB
Java
786 lines
27 KiB
Java
package afryca.consensusmodel.labella2020ELICIT;
|
|
|
|
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.ClusterELICITPR;
|
|
import afryca.consensusmodel.clustering.FuzzyCMeansELICITPR;
|
|
import afryca.consensusmodel.definition.EResultElements;
|
|
import afryca.consensusmodel.definition.ERoundResult;
|
|
import afryca.domain.fuzzyset.FuzzySet;
|
|
import afryca.domain.fuzzyset.function.types.TrapezoidalFunction;
|
|
import afryca.elicit.ELICIT;
|
|
import afryca.elicit.ELICITPR;
|
|
import afryca.hlpr.HLPR;
|
|
import afryca.hlpr.valuation.EUnaryRelationType;
|
|
import afryca.hlpr.valuation.HesitantLinguisticValuation;
|
|
import afryca.structure.Structure;
|
|
import afryca.structure.pair.Pair;
|
|
import afryca.twotuple.TwoTuple;
|
|
|
|
public class Labella2020ELICITLarge_2 extends ConsensusModel {
|
|
|
|
private static final String CONSENSUS_MODEL_NAME = "Labella et al. (2020-ELICIT)"; //$NON-NLS-1$
|
|
|
|
private static final float CHANGE_DEGREE_TRANSLATION = 0.2f;
|
|
private static final int CHANGE_DEGREE_LABEL = 3;
|
|
|
|
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 ArrayList<Float[][]> proximityMatrices;
|
|
private Map<Pair<Integer, Integer>, Float[][]> similarityMatrices;
|
|
|
|
private ELICITPR[] preferencesWithoutCollective;
|
|
private Structure[] preferencesAux;
|
|
|
|
private List<ClusterELICITPR> postClusters;
|
|
|
|
private CM cm;
|
|
private Float[] consensusAlternatives;
|
|
private ELICITPR 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;
|
|
|
|
@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);
|
|
|
|
postClusters = new LinkedList<ClusterELICITPR>();
|
|
preferencesWithoutCollective = new ELICITPR[numberOfExperts];
|
|
|
|
round = 0;
|
|
numberOfChanges = 0;
|
|
advises = null;
|
|
|
|
initializeAdvises();
|
|
initializeELICITPreferences();
|
|
computePreferencesWithoutCollective();
|
|
}
|
|
|
|
/**
|
|
* Transform initial CLEs into ELICIT information
|
|
*/
|
|
private void initializeELICITPreferences() {
|
|
Structure[] preferencesAux = new Structure[numberOfExperts + 1];
|
|
|
|
for(int k = 0; k < numberOfExperts; ++k) {
|
|
|
|
HLPR hlpr = (HLPR) preferences[k];
|
|
ELICIT[][] elicit_preference = new ELICIT[numberOfAlternatives][numberOfAlternatives];
|
|
|
|
for(int i = 0; i < numberOfAlternatives; ++i) {
|
|
for(int j = 0; j < numberOfAlternatives; ++j) {
|
|
HesitantLinguisticValuation hlv = hlpr.getHesitantLinguisticValuation(i, j);
|
|
ELICIT elicitValuation = new ELICIT((FuzzySet) hlv.getDomain());
|
|
elicitValuation.createRelation(ConsensusEngine.calculateFuzzyEnvelope((FuzzySet) hlv.getDomain(), hlv));
|
|
elicit_preference[i][j] = elicitValuation;
|
|
}
|
|
}
|
|
|
|
ELICITPR elicitPR = new ELICITPR(numberOfAlternatives);
|
|
elicitPR.setDomain((FuzzySet) hlpr.getDomain());
|
|
elicitPR.setPreferences(elicit_preference);
|
|
preferencesAux[k] = elicitPR;
|
|
}
|
|
|
|
Structure collective = preferencesAux[0].groupPreferences(numberOfExperts, numberOfAlternatives, numberOfCriteria, Arrays.copyOfRange(preferencesAux, 0, preferencesAux.length - 1));
|
|
this.preferencesAux = clonePreferencesUnion(preferencesAux, collective);
|
|
}
|
|
|
|
/**
|
|
* Initialize preferences without collective opinion
|
|
*/
|
|
private void computePreferencesWithoutCollective() {
|
|
// Copy preferences except collective
|
|
for (int i = 0; i < numberOfExperts; i++) {
|
|
try {
|
|
preferencesWithoutCollective[i] = (ELICITPR) 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);
|
|
|
|
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")
|
|
private List<ClusterELICITPR> generateClusters(String[] alternatives, String[] experts, ELICITPR[] preferences, float parameter) {
|
|
return (roundsResults.isEmpty()
|
|
? FuzzyCMeansELICITPR.doClusteringFuzzyCMeansClusterForEachAlternative(alternatives, experts, preferences, null, parameter)
|
|
: FuzzyCMeansELICITPR.doClusteringFuzzyCMeansClusterForEachAlternative(alternatives, experts, preferences,
|
|
(List<ClusterELICITPR>) roundsResults.get(roundsResults.size() - 1).get(ERoundResult.clusters), parameter));
|
|
}
|
|
|
|
private void computeConsensusDegree() {
|
|
computeSimilarityMatrices();
|
|
computeConsensusMatrix();
|
|
computeConsensusAlternatives();
|
|
computeOverallConsensusDegree();
|
|
computeCollective();
|
|
}
|
|
|
|
private void computeSimilarityMatrices() {
|
|
similarityMatrices = new LinkedHashMap<>();
|
|
|
|
Float similarityValue;
|
|
for (int i = 0; i < numberOfExperts - 1; ++i) {
|
|
Float[][] similarityMatrix = new Float[numberOfAlternatives][numberOfAlternatives];
|
|
for (int t = i + 1; t < numberOfExperts; ++t) {
|
|
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) {
|
|
|
|
ELICIT expert1ELICIT = ((ELICITPR) preferencesAux[i]).getELICITValuation(l, k);
|
|
ELICIT expert2ELICIT = ((ELICITPR) preferencesAux[t]).getELICITValuation(l, k);
|
|
|
|
similarityValue = computeSimilarity(expert1ELICIT.getBeta(), expert2ELICIT.getBeta());
|
|
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 = Math.round(ConsensusEngine.consensusBasedOnAlternativesConsensus(numberOfAlternatives, consensusAlternatives) * 10000f) / 10000f;
|
|
}
|
|
|
|
private void computeCollective() {
|
|
collective = (ELICITPR) preferencesAux[0].groupPreferences(numberOfExperts, numberOfAlternatives, numberOfCriteria,
|
|
Arrays.copyOfRange(preferencesAux, 0, preferencesAux.length - 1));
|
|
preferencesAux[preferencesAux.length - 1] = collective;
|
|
}
|
|
|
|
@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();
|
|
|
|
if(cr < mu) {
|
|
|
|
if (cr < delta)
|
|
groupAdviceGeneration();
|
|
else
|
|
individualAdviceGeneration();
|
|
|
|
computePreferencesWithoutCollective();
|
|
|
|
postClusters = generateClusters(alternatives, experts, preferencesWithoutCollective, 1f);
|
|
|
|
round++;
|
|
}
|
|
}
|
|
|
|
private void groupAdviceGeneration() {
|
|
computeProximityMatrices();
|
|
computeGroupChanges();
|
|
}
|
|
|
|
private void computeProximityMatrices() {
|
|
proximityMatrices = new ArrayList<>();
|
|
|
|
Float[][] proximityMatrix;
|
|
Float proximityValue;
|
|
for (int i = 0; i < postClusters.size(); ++i) {
|
|
proximityMatrix = new Float[numberOfAlternatives][numberOfAlternatives];
|
|
for (int l = 0; l < numberOfAlternatives - 1; ++l) {
|
|
for (int k = l + 1; k < numberOfAlternatives; ++k) {
|
|
ELICIT centroidELICIT = ((ELICIT[][]) postClusters.get(i).getCentroid())[l][k];
|
|
ELICIT collectiveELICIT = collective.getELICITValuation(l, k);
|
|
|
|
proximityValue = computeSimilarity(centroidELICIT.getBeta(), collectiveELICIT.getBeta());
|
|
proximityMatrix[l][k] = proximityValue;
|
|
proximityMatrix[k][l] = proximityValue;
|
|
}
|
|
}
|
|
|
|
proximityMatrices.add(proximityMatrix);
|
|
}
|
|
}
|
|
|
|
private void computeGroupChanges() {
|
|
Map<Integer, List<Pair<Integer, Integer>>> groupsToChange = identifyChangesToDoByGroup();
|
|
|
|
EChangeType[][][] changesDirection = computeGroupChangesDirection(groupsToChange);
|
|
makeChanges(changesDirection);
|
|
|
|
computeNumberOfAdvises(changesDirection);
|
|
}
|
|
|
|
private Map<Integer, List<Pair<Integer, Integer>>> identifyChangesToDoByGroup() {
|
|
Map<Integer, List<Pair<Integer, Integer>>> changes = new HashMap<>();
|
|
|
|
List<Integer> alternativesToChange = identifyAlternativesToChange();
|
|
Float[][] overallProximityMatrix = computeOverallProximityValues();
|
|
|
|
for(ClusterELICITPR cluster: postClusters) {
|
|
for(int alt: alternativesToChange) {
|
|
for(int j = 0 ; j < numberOfAlternatives; ++j) {
|
|
if(j > alt) {
|
|
if(proximityMatrices.get(cluster.getId())[alt][j] < overallProximityMatrix[alt][j]) {
|
|
|
|
Pair<Integer, Integer> pair = new Pair<Integer, Integer>(alt, j);
|
|
|
|
if(changes.get(cluster.getId()) == null) {
|
|
List<Pair<Integer, Integer>> pairsAlternatives = new LinkedList<>();
|
|
pairsAlternatives.add(pair);
|
|
changes.put(cluster.getId(), pairsAlternatives);
|
|
} else {
|
|
List<Pair<Integer, Integer>> pairsAlternatives = changes.get(cluster.getId());
|
|
pairsAlternatives.add(pair);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return changes;
|
|
}
|
|
|
|
private List<Integer> identifyAlternativesToChange() {
|
|
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;
|
|
if(l != j) {
|
|
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 = initializeChanges();
|
|
|
|
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();
|
|
|
|
ELICIT expertELICIT = ((ELICIT[][]) postClusters.get(group).getCentroid())[a1][a2];
|
|
ELICIT collectiveELICIT = collective.getELICITValuation(a1, a2);
|
|
|
|
difference = (float) (expertELICIT.getBeta().getSimpleDefuzzifiedValue() - collectiveELICIT.getBeta().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 EChangeType[][][] initializeChanges() {
|
|
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 makeChanges(EChangeType[][][] changes) {
|
|
ELICIT value;
|
|
EChangeType change;
|
|
|
|
double[] changesToMake = getNChanges(numberOfChanges);
|
|
|
|
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++];
|
|
if (ch != 0f) {
|
|
|
|
value = (ELICIT) preferencesAux[i].getValue(l, k);
|
|
|
|
double difference = Math.abs(value.getBeta().centroid() - ((ELICIT) collective.getValue(l, k)).getBeta().centroid());
|
|
|
|
if (change == EChangeType.Increase) {
|
|
|
|
if(difference >= 1d / ((FuzzySet) preferencesAux[i].getDomain()).getLabelSet().getCardinality()) {
|
|
value = increaseCaseLabel(value);
|
|
} else {
|
|
value = increaseCaseTranslation(value);
|
|
}
|
|
|
|
} else if (change == EChangeType.Decrease) {
|
|
|
|
if(difference >= 1d / ((FuzzySet) preferencesAux[i].getDomain()).getLabelSet().getCardinality()) {
|
|
value = decreaseCaseLabel(value);
|
|
} else {
|
|
value = decreaseCaseTranslation(value);
|
|
}
|
|
}
|
|
|
|
((ELICITPR) preferencesAux[i]).setValueSymmetrically(l, k, value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void computeNumberOfAdvises(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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void individualAdviceGeneration() {
|
|
computeProximityMatrices();
|
|
computeIndividualChanges();
|
|
}
|
|
|
|
private void computeIndividualChanges() {
|
|
Map<Integer, List<Pair<Integer, Integer>>> changesToDo = identifyChangesToDoByIndividual();
|
|
|
|
EChangeType[][][] changesDirection = computeIndividualChangesDirection(changesToDo);
|
|
makeChanges(changesDirection);
|
|
|
|
computeNumberOfAdvises(changesDirection);
|
|
}
|
|
|
|
private Map<Integer, List<Pair<Integer, Integer>>> identifyChangesToDoByIndividual() {
|
|
Float similarity;
|
|
|
|
List<Integer> alternativesToChange = identifyAlternativesToChange();
|
|
Float[][] overallProximityMatrix = computeOverallProximityValues();
|
|
|
|
Map<Integer, List<Pair<Integer, Integer>>> expertsToChange = new HashMap<>();
|
|
for (ClusterELICITPR cluster: postClusters) {
|
|
for (Integer exp : cluster.getExperts()) {
|
|
for (int alt: alternativesToChange) {
|
|
for(int j = 0; j < numberOfAlternatives; ++j) {
|
|
if(alt > j) {
|
|
|
|
similarity = computeSimilarity(collective.getELICITValuation(alt, j).getBeta(), ((ELICITPR) preferencesAux[exp]).getELICITValuation(alt, j).getBeta());
|
|
|
|
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;
|
|
for (Integer i: expertsToChange.keySet()) {
|
|
List<Pair<Integer, Integer>> pairAlternativesToChange = expertsToChange.get(i);
|
|
for (int l = 0; l < numberOfAlternatives; l++) {
|
|
for (int k = 0; k < numberOfAlternatives; k++) {
|
|
if(l != k) {
|
|
Pair<Integer, Integer> pairAlternatives = new Pair<Integer, Integer>(l, k);
|
|
if (pairAlternativesToChange.contains(pairAlternatives)) {
|
|
|
|
ELICIT expertELICIT = ((ELICITPR) preferencesAux[i]).getELICITValuation(l, k);
|
|
ELICIT collectiveELICIT = collective.getELICITValuation(l, k);
|
|
|
|
difference = (float) (expertELICIT.getBeta().getSimpleDefuzzifiedValue() - collectiveELICIT.getBeta().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 ELICIT increaseCaseTranslation(ELICIT elicit) {
|
|
FuzzySet domain = elicit.getDomain();
|
|
|
|
if (elicit.isPrimary()) {
|
|
TwoTuple label = elicit.getTwoTupleLabel();
|
|
label.calculateDelta((label.getAlpha() + CHANGE_DEGREE_TRANSLATION) + domain.getLabelSet().getPos(label.getLabel()));
|
|
|
|
} else if (elicit.isUnary()) {
|
|
|
|
TwoTuple term = elicit.getTwoTupleTerm();
|
|
term.calculateDelta((term.getAlpha() + CHANGE_DEGREE_TRANSLATION) + domain.getLabelSet().getPos(term.getLabel()));
|
|
|
|
if(elicit.getUnaryRelation().equals(EUnaryRelationType.AtLeast)) {
|
|
if(domain.getLabelSet().getPos(term.getLabel()) < (domain.getLabelSet().getCardinality() - 1) / 2)
|
|
elicit.setTwoTupleLabel(term);
|
|
} else {
|
|
if(domain.getLabelSet().getPos(term.getLabel()) > (domain.getLabelSet().getCardinality() - 1) / 2)
|
|
elicit.setTwoTupleLabel(term);
|
|
}
|
|
|
|
} else {
|
|
|
|
TwoTuple lowerTerm = elicit.getTwoTupleLowerTerm();
|
|
TwoTuple upperTerm = elicit.getTwoTupleUpperTerm();
|
|
lowerTerm.calculateDelta((lowerTerm.getAlpha() + CHANGE_DEGREE_TRANSLATION) + domain.getLabelSet().getPos(lowerTerm.getLabel()));
|
|
|
|
if(lowerTerm.compareTo(upperTerm) > 0)
|
|
elicit.setTwoTupleLabel(lowerTerm);
|
|
}
|
|
|
|
elicit.createRelation(elicit.calculateFuzzyEnvelope());
|
|
|
|
return elicit;
|
|
}
|
|
|
|
|
|
private ELICIT decreaseCaseTranslation(ELICIT elicit) {
|
|
FuzzySet domain = elicit.getDomain();
|
|
|
|
if (elicit.isPrimary()) {
|
|
|
|
TwoTuple label = elicit.getTwoTupleLabel();
|
|
label.calculateDelta((label.getAlpha() - CHANGE_DEGREE_TRANSLATION) + domain.getLabelSet().getPos(label.getLabel()));
|
|
|
|
} else if (elicit.isUnary()) {
|
|
|
|
TwoTuple term = elicit.getTwoTupleTerm();
|
|
term.calculateDelta((term.getAlpha() - CHANGE_DEGREE_TRANSLATION) + domain.getLabelSet().getPos(term.getLabel()));
|
|
|
|
if(elicit.getUnaryRelation().equals(EUnaryRelationType.AtLeast)) {
|
|
if(domain.getLabelSet().getPos(term.getLabel()) < (domain.getLabelSet().getCardinality() - 1) / 2)
|
|
elicit.setTwoTupleLabel(term);
|
|
} else {
|
|
if(domain.getLabelSet().getPos(term.getLabel()) > (domain.getLabelSet().getCardinality() - 1) / 2)
|
|
elicit.setTwoTupleLabel(term);
|
|
}
|
|
|
|
} else {
|
|
|
|
TwoTuple lowerTerm = elicit.getTwoTupleLowerTerm();
|
|
TwoTuple upperTerm = elicit.getTwoTupleUpperTerm();
|
|
upperTerm.calculateDelta((upperTerm.getAlpha() - CHANGE_DEGREE_TRANSLATION) + domain.getLabelSet().getPos(upperTerm.getLabel()));
|
|
|
|
if(upperTerm.compareTo(lowerTerm) < 0)
|
|
elicit.setTwoTupleLabel(upperTerm);
|
|
}
|
|
|
|
elicit.createRelation(elicit.calculateFuzzyEnvelope());
|
|
|
|
return elicit;
|
|
}
|
|
|
|
private ELICIT increaseCaseLabel(ELICIT elicit) {
|
|
FuzzySet fuzzySet = (FuzzySet) elicit.getDomain();
|
|
|
|
if (elicit.isPrimary()) {
|
|
|
|
int posLabel = fuzzySet.getLabelSet().getPos(elicit.getTwoTupleLabel().getLabel());
|
|
if(posLabel + CHANGE_DEGREE_LABEL < fuzzySet.getLabelSet().getCardinality() - 1) {
|
|
TwoTuple label = elicit.getTwoTupleLabel();
|
|
label.setLabel(posLabel + CHANGE_DEGREE_LABEL);//Keep the symbolic translation
|
|
}
|
|
|
|
} else if (elicit.isUnary()) {
|
|
|
|
int posTerm = fuzzySet.getLabelSet().getPos(elicit.getTwoTupleTerm().getLabel()), cardinality = fuzzySet.getLabelSet().getCardinality();
|
|
|
|
if(posTerm + CHANGE_DEGREE_LABEL < fuzzySet.getLabelSet().getCardinality() - 1) {//Is it possible the change?
|
|
|
|
if((elicit.getUnaryRelation().equals(EUnaryRelationType.AtMost) || elicit.getUnaryRelation().equals(EUnaryRelationType.LowerThan))
|
|
&& (posTerm + CHANGE_DEGREE_LABEL > (cardinality + 1) / 2)) {//Too many labels in the unary expression
|
|
|
|
elicit.setTwoTupleLabel(posTerm + CHANGE_DEGREE_LABEL);//Restart symbolic translation
|
|
|
|
} else if((posTerm + CHANGE_DEGREE_LABEL == cardinality - 1) && (elicit.getUnaryRelation().equals(EUnaryRelationType.GreaterThan)))
|
|
|
|
elicit.setTwoTupleLabel(cardinality - 1);
|
|
else {
|
|
TwoTuple term = elicit.getTwoTupleTerm();
|
|
term.setLabel(posTerm + CHANGE_DEGREE_LABEL);//Keep the symbolic translation
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
int posTerm1 = fuzzySet.getLabelSet().getPos(elicit.getTwoTupleLowerTerm().getLabel());
|
|
int posTerm2 = fuzzySet.getLabelSet().getPos(elicit.getTwoTupleUpperTerm().getLabel());
|
|
|
|
if (posTerm1 + CHANGE_DEGREE_LABEL == posTerm2)
|
|
elicit.setTwoTupleLabel(posTerm2);
|
|
else if (posTerm1 + CHANGE_DEGREE_LABEL < posTerm2) {
|
|
|
|
TwoTuple lowerTerm = elicit.getTwoTupleLowerTerm();
|
|
lowerTerm.setLabel(posTerm1 + CHANGE_DEGREE_LABEL);
|
|
}
|
|
}
|
|
|
|
elicit.createRelation(elicit.calculateFuzzyEnvelope());
|
|
|
|
return elicit;
|
|
}
|
|
|
|
private ELICIT decreaseCaseLabel(ELICIT elicit) {
|
|
FuzzySet fuzzySet = (FuzzySet) elicit.getDomain();
|
|
|
|
if (elicit.isPrimary()) {
|
|
|
|
int posLabel = fuzzySet.getLabelSet().getPos(elicit.getTwoTupleLabel().getLabel());
|
|
|
|
if(posLabel - CHANGE_DEGREE_LABEL >= 0) {
|
|
TwoTuple label = elicit.getTwoTupleLabel();
|
|
label.setLabel(posLabel - CHANGE_DEGREE_LABEL);//Keep the symbolic translation
|
|
}
|
|
|
|
} else if (elicit.isUnary()) {
|
|
|
|
int posTerm = fuzzySet.getLabelSet().getPos(elicit.getTwoTupleTerm().getLabel()), cardinality = fuzzySet.getLabelSet().getCardinality();
|
|
|
|
if(posTerm - CHANGE_DEGREE_LABEL >= 0) {
|
|
if((elicit.getUnaryRelation().equals(EUnaryRelationType.AtLeast) || elicit.getUnaryRelation().equals(EUnaryRelationType.GreaterThan))
|
|
&& (posTerm - CHANGE_DEGREE_LABEL < (cardinality - 1) / 2)) {//To many labels in the unary expression
|
|
|
|
elicit.setTwoTupleLabel(posTerm - CHANGE_DEGREE_LABEL);//Restart symbolic translation
|
|
|
|
} else if((posTerm - CHANGE_DEGREE_LABEL == 0) && (elicit.getUnaryRelation().equals(EUnaryRelationType.LowerThan))) {
|
|
|
|
elicit.setTwoTupleLabel(0);//Restart symbolic translation
|
|
|
|
} else {
|
|
|
|
TwoTuple term = elicit.getTwoTupleTerm();
|
|
term.setLabel(posTerm - CHANGE_DEGREE_LABEL);//Keep the symbolic translation
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
int posTerm1 = fuzzySet.getLabelSet().getPos(elicit.getTwoTupleLowerTerm().getLabel());
|
|
int posTerm2 = fuzzySet.getLabelSet().getPos(elicit.getTwoTupleUpperTerm().getLabel());
|
|
|
|
if (posTerm2 - CHANGE_DEGREE_LABEL == posTerm1)
|
|
elicit.setTwoTupleLabel(posTerm1);//Restart symbolic translation
|
|
else if(posTerm2 - CHANGE_DEGREE_LABEL > posTerm1) {
|
|
TwoTuple upperTerm = elicit.getTwoTupleUpperTerm();
|
|
upperTerm.setLabel(posTerm2 - CHANGE_DEGREE_LABEL);
|
|
}
|
|
}
|
|
|
|
elicit.createRelation(elicit.calculateFuzzyEnvelope());
|
|
|
|
return elicit;
|
|
}
|
|
|
|
|
|
@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);
|
|
}
|
|
|
|
|
|
}
|