Files
AFRYCA/plugins/afryca.consensusmodel/src/afryca/consensusmodel/ConsensusModel.java
T
2026-05-22 11:14:29 +02:00

445 lines
14 KiB
Java

package afryca.consensusmodel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import org.eclipse.e4.core.contexts.ContextInjectionFactory;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.services.nls.Translation;
import afryca.behavior.service.IBehaviorService;
import afryca.consensusmodel.definition.EResultElements;
import afryca.consensusmodel.definition.ERoundResult;
import afryca.consensusmodel.l10n.Messages;
import afryca.consensusmodel.variable.Variable;
import afryca.consensusmodel.variable.definition.EVariableElements;
import afryca.consensusmodel.variable.definition.EVariableTypes;
import afryca.consensusmodel.variable.definition.MockVariableConfigurationElement;
import afryca.consensusmodel.variable.definition.VariableRegistry;
import afryca.structure.Structure;
import afryca.structure.ranking.AbstractDominanceRanking;
import afryca.structure.ranking.AlternativeRanking;
/**
* Interface for consensus models
*
* @author Sinbad²
* @version 3.0
*/
public abstract class ConsensusModel {
// Extension point id
public static final String EXTENSION_POINT = "afryca.consensusmodel"; //$NON-NLS-1$
public static final String EXPERTS = "experts"; //$NON-NLS-1$
public static final String ALTERNATIVES = "alternatives"; //$NON-NLS-1$
public static final String CRITERIA = "criteria"; //$NON-NLS-1$
public static final String PREFERENCES = "preferences"; //$NON-NLS-1$
public static final String WITH_FEEDBACK = "WithFeedback"; //$NON-NLS-1$
public static final String UNDEFINED = "undefined"; //$NON-NLS-1$
protected String[] experts;
protected String[] alternatives;
protected String[] criteria;
protected Integer numberOfExperts;
protected Integer numberOfAlternatives;
protected Integer numberOfCriteria;
protected Structure[] preferences;
protected Map<EResultElements, Object> result;
protected List<Map<ERoundResult, Object>> roundsResults;
protected boolean validConfiguration;
protected Variables variables = null;
protected Configuration configuration;
@Inject
protected IBehaviorService behaviorService;
@Inject
protected IEclipseContext context;
@Inject
@Translation
private Messages messages;
/**
* Set the consensus model variables
*
* @param variables
* Consensus model variables
*/
public void setVariables(Variables variables) {
this.variables = variables;
setDefaultVariables();
}
private void setDefaultVariables() {
addArrayVariable(variables, EXPERTS, messages.experts_description, EVariableTypes.String);
addArrayVariable(variables, ALTERNATIVES, messages.alternatives_description, EVariableTypes.String);
addArrayVariable(variables, CRITERIA, messages.criteria_description, EVariableTypes.String);
addArrayVariable(variables, PREFERENCES, messages.preferences_description, EVariableTypes.FPR);
}
private void addArrayVariable(Variables variables, String id, String description, EVariableTypes type) {
MockVariableConfigurationElement configurationElement = new MockVariableConfigurationElement();
configurationElement.addAttribute(EVariableElements.id.name(), id);
configurationElement.addAttribute(EVariableElements.description.name(), description);
configurationElement.addAttribute(EVariableElements.type.name(), type.name());
configurationElement.addAttribute(EVariableElements.default_value.name(), null);
configurationElement.addAttribute(EVariableElements.array_default_element_value.name(), null);
configurationElement.addAttribute(EVariableElements.is_array.name(), Boolean.toString(true));
configurationElement.addAttribute(EVariableElements.is_internal.name(), Boolean.toString(true));
addVariable(variables, new VariableRegistry(configurationElement));
}
private void addVariable(Variables variables, VariableRegistry variableRegistry) {
Variable variable = ContextInjectionFactory.make(Variable.class, injectInChildContext(variableRegistry));
variables.addVariable(variable);
}
private IEclipseContext injectInChildContext(Object element) {
IEclipseContext childContext = context.createChild();
ContextInjectionFactory.inject(element, childContext);
childContext.set(element.getClass().getName(), element);
return childContext;
}
/**
* Return consensus model variables
*
* @return Consensus model variables
*/
public Variables getVariables() {
return variables;
}
/**
* Configure model
*
* @param configuration
* Model configuration
*
* @return True valid configuration
* <p>
* False invalid configuration
*/
public boolean setConfiguration(Configuration configuration) {
this.configuration = configuration;
validConfiguration = true;
setElementsConfiguration();
if (validConfiguration) {
setModelConfiguration();
}
return validConfiguration;
}
private void setElementsConfiguration() {
try {
roundsResults = new ArrayList<>();
setExpertsConfiguration();
setAlternativesConfiguration();
setCriteriaConfiguration();
setPreferencesConfiguration();
setConsensusModelInformationConfiguration();
} catch (Exception e) {
validConfiguration = false;
}
}
private void setExpertsConfiguration() {
experts = (String[]) configuration.getValue(EXPERTS);
numberOfExperts = experts.length;
}
private void setAlternativesConfiguration() {
alternatives = (String[]) configuration.getValue(ALTERNATIVES);
numberOfAlternatives = alternatives.length;
}
private void setCriteriaConfiguration() {
criteria = (String[]) configuration.getValue(CRITERIA);
numberOfCriteria = criteria.length;
}
private void setPreferencesConfiguration() throws CloneNotSupportedException {
Structure[] configurationPreferences = (Structure[]) configuration.getValue(PREFERENCES);
preferences = new Structure[numberOfExperts * numberOfCriteria + 1];
for (int i = 0; i < numberOfExperts * numberOfCriteria; i++) {
preferences[i] = (Structure) configurationPreferences[i].clone();
}
preferences[numberOfExperts * numberOfCriteria] = (Structure) configurationPreferences[0].clone();
preferences[numberOfExperts * numberOfCriteria].initialize();
configuration.setValue(PREFERENCES, preferences);
}
private void setConsensusModelInformationConfiguration() {
result = new HashMap<>();
for (EResultElements element : EResultElements.values()) {
result.put(element, UNDEFINED);
}
result.put(EResultElements.experts, experts);
result.put(EResultElements.number_of_experts, numberOfExperts);
result.put(EResultElements.alternatives, alternatives);
result.put(EResultElements.number_of_alternatives, numberOfAlternatives);
result.put(EResultElements.criteria, criteria);
result.put(EResultElements.number_of_criteria, numberOfCriteria);
}
/**
* Set model specific configuration
*/
protected abstract void setModelConfiguration();
/**
* Pre save round result
*
* @param round
* Current round
* @param preferences2
* Current preferences
* @param consensusDegreeAchieved
* Consensus degree achieved
*/
public void preSaveRoundResult(int round, Structure[] preferences2,Float[][][] preferencesGroupVisualization, Float consensusDegreeAchieved) {
Map<ERoundResult, Object> r = new HashMap<>();
roundsResults.add(r);
r.put(ERoundResult.round, round);
r.put(ERoundResult.pre_preferences, clonePreferences(preferences2));
r.put(ERoundResult.pre_preferencesGroupVisualization, preferencesGroupVisualization.clone());
r.put(ERoundResult.pre_consensus_degree_achieved, consensusDegreeAchieved);
computePreRoundResults(r);
}
protected Structure[] clonePreferences(Structure[] preferences2) {
Structure[] result = new Structure[preferences2.length];
for (int pos = 0; pos < preferences2.length; pos++) {
try {
result[pos] = (Structure) ((Structure) preferences2[pos]).clone();
} catch (CloneNotSupportedException e) {
// Nothing to do
}
}
return result;
}
private void computePreRoundResults(Map<ERoundResult, Object> roundResults) {
Structure[] preferences = (Structure[]) roundResults.get(ERoundResult.pre_preferences);
int[][] order = new int[numberOfExperts + 1][numberOfAlternatives];
AlternativeRanking[] ranking;
AlternativeRanking[] orderedRanking = null;
for (int i = 0; i <= numberOfExperts; i++) {
ranking = selection(preferences[i]);
orderedRanking = AlternativeRanking.orderRanking(ranking);
for (int j = 0; j < numberOfAlternatives; j++) {
order[i][j] = orderedRanking[j].getPosition() + 1;
}
}
roundResults.put(ERoundResult.pre_ranking_of_alternatives, order);
}
private static AlternativeRanking[] selection(Structure preference) {
AbstractDominanceRanking ranking = preference.createRanking();
return ranking.getAlternativesRanking();
}
/**
* Pos save round result
*
* @param currentPreferences
* Current preferences
* @param consensusDegreeAchieved
* Consensus degree achieved
* @param advises
* Number of advises
* @param preferences2
*/
public void posSaveRoundResult(Structure[] currentPreferences,Float[][][] preferencesGroupVisualization, Float consensusDegreeAchieved, int[] advises) {
Map<ERoundResult, Object> r = roundsResults.get(roundsResults.size() - 1);
r.put(ERoundResult.pos_preferences, clonePreferences(currentPreferences));
r.put(ERoundResult.pos_preferencesGroupVisualization,preferencesGroupVisualization.clone());
r.put(ERoundResult.pos_consensus_degree_achieved, consensusDegreeAchieved);
r.put(ERoundResult.advices, advises);
computePosRoundResults(r);
}
private void computePosRoundResults(Map<ERoundResult, Object> roundResults) {
Structure[] preferences = (Structure[]) roundResults.get(ERoundResult.pos_preferences);
int[][] order = new int[numberOfExperts + 1][numberOfAlternatives];
AlternativeRanking[] ranking;
AlternativeRanking[] orderedRanking = null;
for (int i = 0; i <= numberOfExperts; i++) {
ranking = selection(preferences[i]);
orderedRanking = AlternativeRanking.orderRanking(ranking);
for (int j = 0; j < numberOfAlternatives; j++) {
order[i][j] = orderedRanking[j].getPosition() + 1;
}
}
roundResults.put(ERoundResult.pos_ranking_of_alternatives, order);
}
/**
* Pos save round result
*
* @param preferences2
* Current preferences
* @param consensusDegreeAchieved
* Consensus degree achieved
* @param advises
* Number of advises
* @param preferences3
* Group's preferences
*/
public void posSaveRoundResult(Structure[] preferences2, Float[][][] preferencesGroupVisualization, Float consensusDegreeAchieved, int[] advises, Structure preferences3) {
Map<ERoundResult, Object> r = roundsResults.get(roundsResults.size() - 1);
r.put(ERoundResult.pos_preferences, clonePreferencesUnion(preferences2, preferences3));
r.put(ERoundResult.pos_preferencesGroupVisualization,preferencesGroupVisualization );
r.put(ERoundResult.pos_consensus_degree_achieved, consensusDegreeAchieved);
r.put(ERoundResult.advices, advises);
computePosRoundResults(r);
}
protected Structure[] clonePreferencesUnion(Structure[] preferences2, Structure collective) {
Structure[] result = new Structure[preferences2.length];
for (int pos = 0; pos < preferences2.length; pos++) {
try {
result[pos] = (pos < (preferences2.length - 1)) ? (Structure) ((Structure) preferences2[pos]).clone() : (Structure) ((Structure) collective).clone();
} catch (CloneNotSupportedException e) {
// Nothing to do
}
}
return result;
}
/**
* Execute model
*
* @return Execution result
*/
public Map<EResultElements, Object> execute() {
if (validConfiguration) {
obtainConfigurationValues();
boolean firstRound = true;
do {
if (firstRound) {
preFirstSaveRoundResults();
firstRound = false;
} else {
preSaveRoundResults();
}
consensusRound();
posSaveRoundResults();
} while (mustBeCarriedOutAnotherRound());
computeExecutionResults();
} else {
return null;
}
return getResult();
}
/**
* Obtain configuration values
*/
protected abstract void obtainConfigurationValues();
/**
* Save in 'preferencesGroupVisualization' only one preference by expert and the collective of this preferences
*/
protected abstract Float[][][] obtainVisualizeValues();
/**
* Save pre first round results
*/
protected abstract void preFirstSaveRoundResults();
/**
* Save pre round results
*/
protected abstract void preSaveRoundResults();
/**
* Carried out consensus round
*/
protected abstract void consensusRound();
/**
* Save pos round results
*/
protected abstract void posSaveRoundResults();
/**
* Must be carried out another round
*
* @return True if another round should take place, False in other case
*/
protected abstract boolean mustBeCarriedOutAnotherRound();
/**
* Save execution results
*/
protected abstract void saveExecutionResults();
protected void computeExecutionResults() {
saveExecutionResults();
Structure[] preferences = (Structure[]) configuration.getValue(PREFERENCES);
if(result.get(EResultElements.classification_of_alternatives) == "undefined") {
AlternativeRanking[] ranking = selection(preferences);
AlternativeRanking[] orderedRanking = AlternativeRanking.orderRanking(ranking);
String orderedRankingInStringFormat = AlternativeRanking.orderedAlternativesRankingToString(orderedRanking);
this.result.put(EResultElements.ranking_of_alternatives, orderedRankingInStringFormat);
this.result.put(EResultElements.solution_set_of_alternatives, AlternativeRanking.getAlternativesWithRankingPos(ranking, 1));
}
this.result.put(EResultElements.preferences, preferences);
this.result.put(EResultElements.rounds_results, roundsResults);
}
private static AlternativeRanking[] selection(Structure[] preferences) {
return selection(preferences[preferences.length - 1]);
}
/**
* Return execution result
*
* @return Execution result
*/
public Map<EResultElements, Object> getResult() {
return result;
}
/**
* Return n changes
*
* @param n
* Number of changes
* @return n changes
*/
protected double[] getNChanges(int n) {
return behaviorService.getNChanges(n);
}
}