Files
2026-05-22 11:14:29 +02:00

410 lines
12 KiB
Java

package afryca.hlpr;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.core.runtime.preferences.InstanceScope;
import afryca.ase.RunnableScript;
import afryca.domain.Domain;
import afryca.domain.fuzzyset.FuzzySet;
import afryca.domain.fuzzyset.function.types.TrapezoidalFunction;
import afryca.domain.fuzzyset.labelset.Label;
import afryca.hlpr.command.GenerateRandomHLPR;
import afryca.hlpr.preferences.PreferenceConstants;
import afryca.hlpr.ranking.NonDominanceRanking;
import afryca.hlpr.valuation.HesitantLinguisticValuation;
import afryca.pr.PR;
import afryca.structure.Structure;
import afryca.hlpr.addon.E4DIAddon;
import afryca.structure.ranking.AbstractDominanceRanking;
import afryca.twotuple.TwoTuple;
public class HLPR extends PR {
public static final String ID = "afryca.hlpr";
public final static HesitantLinguisticValuation MISSING_VALUE = new HesitantLinguisticValuation();
public final static HesitantLinguisticValuation INDIFFERENCE_VALUE = new HesitantLinguisticValuation();
private FuzzySet fuzzySet;
/**
* Build a empty HPR
*/
public HLPR() {
prepareStructureForNAlternatives(0);
}
/**
* Build a HPR for numberOfAlternatives
*
* @param numberOfAlternatives
* Number of alternatives
*
* @throws IllegalArgumentException
* if numberOfAlternatives is negative
*/
public HLPR(int numberOfAlternatives) {
this.numberOfAlternatives = numberOfAlternatives;
prepareStructureForNAlternatives(numberOfAlternatives);
setIndifferenceAtDiagonal();
}
@Override
public void preparePreferencesStructure() {
preferences = new Object[numberOfAlternatives][numberOfAlternatives];
for (int i = 0; i < numberOfAlternatives; i++) {
for (int j = 0; j < numberOfAlternatives; j++) {
preferences[i][j] = MISSING_VALUE;
}
}
}
@Override
public void setIndifferenceAtDiagonal() {
setIndifferenceDiagonal(null);
}
private void setIndifferenceDiagonal(Domain domain){
for (int i = 0; i < numberOfAlternatives; i++) {
if(domain!=null){
HesitantLinguisticValuation diagonal=new HesitantLinguisticValuation((FuzzySet) domain);
diagonal.setLabel(((FuzzySet)domain).getLabelSet().getCardinality()/2);
preferences[i][i] = diagonal;
}else{
preferences[i][i] = INDIFFERENCE_VALUE;
}
}
}
@Override
public void setDomain(Object...fuzzySet) {
updatePreferences((FuzzySet) fuzzySet[2]);
this.fuzzySet = (FuzzySet) fuzzySet[2];
changes.firePropertyChange(FIELD_PREFERENCES, null, preferences);
}
public void setDomain(FuzzySet fuzzySet) {
updatePreferences(fuzzySet);
this.fuzzySet = fuzzySet;
changes.firePropertyChange(FIELD_PREFERENCES, null, preferences);
}
private void updatePreferences(FuzzySet domain) {
if(domain != null) {
if(this.fuzzySet != domain) {
prepareStructureForNAlternatives(numberOfAlternatives);
setIndifferenceDiagonal(domain);
}
}else{
prepareStructureForNAlternatives(numberOfAlternatives);
}
}
@Override
public Object getDomain(Object...indexes) {
return fuzzySet;
}
@Override
public boolean isValidForPreferences(Object value) {
if (value == null) {
return false;
}
return ((HesitantLinguisticValuation) value).equals(MISSING_VALUE) || checkHesitantValuation((HesitantLinguisticValuation) value);
}
private boolean checkHesitantValuation(HesitantLinguisticValuation value) {
if(fuzzySet == null || value == null) {
return true;
} else {
if(value.isUnary()) {
Label term = value.getTerm();
return fuzzySet.getLabelSet().containsLabel(term);
} else if(value.isBinary()) {
Label lowerTerm = value.getLowerTerm();
Label upperTerm = value.getUpperTerm();
return fuzzySet.getLabelSet().containsLabel(lowerTerm) && fuzzySet.getLabelSet().containsLabel(upperTerm);
} else if(value.isPrimary()) {
Label label = value.getLabel();
return fuzzySet.getLabelSet().containsLabel(label);
}
}
return false;
}
@Override
public void setValueSymmetrically(int i, int j, Object value) {
notInvalidPairOfAlternatives(i, j);
setValueToSymmetricallyPairOfAlternatives(i, j, value);
}
private void setValueToSymmetricallyPairOfAlternatives(int i, int j, Object value) {
checkHesitantValuation((HesitantLinguisticValuation) value);
if (i != j) {
preferences[i][j] = value;
preferences[j][i] = ((HesitantLinguisticValuation) value).getReciprocalHesitantValues();
changes.firePropertyChange(FIELD_PREFERENCES, null, preferences);
}
}
public void setValueToPairOfAlternatives(int i, int j, Object value) {
checkHesitantValuation((HesitantLinguisticValuation) value);
if (i != j) {
preferences[i][j] = value;
changes.firePropertyChange(FIELD_PREFERENCES, null, preferences);
}
}
/**
* Initialize FPR with missing values
*/
@Override
public void initialize() {;
for (int row = 0; row < numberOfAlternatives; row++) {
for (int col = 0; col < numberOfAlternatives; col++) {
preferences[row][col] = (row == col) ? INDIFFERENCE_VALUE : MISSING_VALUE;
}
}
changes.firePropertyChange(FIELD_PREFERENCES, null, preferences);
}
@Override
public Object createDefaultStructure(Object...numberOfAlternatives) {
return new HLPR((int) numberOfAlternatives[0]);
}
@Override
public Object clone() throws CloneNotSupportedException {
HLPR result = new HLPR();
result.preferences = clonePreferences();
if(fuzzySet == null) {
result.fuzzySet = null;
} else {
result.fuzzySet = (FuzzySet) fuzzySet.clone();
}
result.numberOfAlternatives = numberOfAlternatives;
return result;
}
private Object[][] clonePreferences() {
Object[][] result = new Object[preferences.length][];
for (int i = 0; i < preferences.length; i++) {
result[i] = clonePreferencesRow(i);
}
return result;
}
private Object[] clonePreferencesRow(int row) {
Object[] result = new Object[preferences[row].length];
for (int i = 0; i < preferences[row].length; i++) {
if(preferences[row][i] == null){
result[i]=null;
}else{
if(preferences[row][i] instanceof HesitantLinguisticValuation){
result[i] = (HesitantLinguisticValuation) ((HesitantLinguisticValuation) preferences[row][i]).clone();
}else if(preferences[row][i] instanceof TwoTuple){
result[i] = (TwoTuple) ((TwoTuple) preferences[row][i]).clone();
}
}
}
return result;
}
@Override
public Object getValue(Object... indexes) {
int i, j;
i = (Integer) indexes[0];
j = (Integer) indexes[1];
notInvalidPairOfAlternatives(i, j);
return preferences[i][j];
}
public String getHesitantValuationName(int i, int j) {
notInvalidPairOfAlternatives(i, j);
return preferences[i][j].toString();
}
public HesitantLinguisticValuation getHesitantLinguisticValuation(int i, int j) {
notInvalidPairOfAlternatives(i, j);
return (HesitantLinguisticValuation) preferences[i][j];
}
@Override
public Structure parseStructure(String readablePreference, String readableDomains, List<Domain> domains) {
HLPRParser textForGenerateHPR = HLPRParser.discover(readablePreference);
return textForGenerateHPR.parse(readablePreference, readableDomains, domains, this);
}
/**
* Group preferences
*
* @param experts
* Number of experts
* @param alternatives
* Number of alternatives
* @param preferences
* All HPR
* @return Group HPR
*/
@Override
public Structure groupPreferences(int numberOfExperts, int numberOfAlternatives, int numberOfCriteria, Structure[] preferences) {
String function = InstanceScope.INSTANCE.getNode(PreferenceConstants.NODEPATH).get(PreferenceConstants.AGGREGATE_HLPR_FUNCTION_KEY, null);
boolean missing=false;
for (int i = 0; i < preferences.length; i++) {
try {
missing=(boolean) E4DIAddon.aseService
.createFragmentBuilder()
.putVariable("collective", preferences[i]) //$NON-NLS-1$
.putVariable("row", ((Object[][]) preferences[i].getPreferences()).length)
.putVariable("col", ((Object[][]) preferences[i].getPreferences())[0].length)
.setCode("consistency.containsMissingValues(collective, row, col)") //$NON-NLS-1$
.setOutputType(Boolean.class.getName())
.eval()
.getResult();
} catch (Exception e) {}
if(missing)
return new HLPR(numberOfAlternatives);
}
FuzzySet blts = (FuzzySet) E4DIAddon.aseService
.createFragmentBuilder()
.putVariable("preferences", preferences) //$NON-NLS-1$
.setCode("unification.getBLTS(preferences)") //$NON-NLS-1$
.setOutputType(FuzzySet.class.getName())
.eval()
.getResult();
Object[][] collective = (Object[][]) ((RunnableScript)
E4DIAddon.aseService.createExecutionBuilder()
.setFunction(function)
.putVariable("preferences", preferences)
.putVariable("alternatives", numberOfAlternatives)
.putVariable("criteria", numberOfCriteria)
.putVariable("experts", numberOfExperts)
.execute())
.getResult();
if ((collective != null)) {
HLPR result = new HLPR(numberOfAlternatives);
result.setDomain(0,0,blts);
result.setPreferences(collective);
return result;
}
return new HLPR(numberOfAlternatives);
}
/**
* Generate random HPR
*
* @param n
* Number of alternatives
*/
@Override
public Structure random(int n) {
HLPR hlprRandom = new HLPR(n);
hlprRandom.setDomain(null, null, this.fuzzySet);
hlprRandom.setNumberOfAlternatives(n);
for (int i = 0; i < n-1; i++) {
for (int j = (i+1); j < n; j++) {
HesitantLinguisticValuation hesitant = ((HesitantLinguisticValuation) preferences[i][j]).generateHesitantValuationRandom(fuzzySet);
hlprRandom.setValueSymmetrically(i, j, hesitant);
}
}
return hlprRandom;
}
@Override
public AbstractDominanceRanking createRanking() {
return new NonDominanceRanking(this);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + numberOfAlternatives;
result = prime * result + Arrays.deepHashCode(preferences);
result = prime * result + ((fuzzySet == null) ? 0 : fuzzySet.hashCode());
return result;
}
@Override
public String[] getRandomKeys() {
String [] result=new String[2];
result[0] = GenerateRandomHLPR.NUMBER_OF_ALTERNATIVES;
result[1] = GenerateRandomHLPR.ID;
return result;
}
@Override
public String [] getPreferencesKeys() {
String [] result=new String[2];
result[0]=PreferenceConstants.CHART_FUNCTION_KEY;
result[1]=PreferenceConstants.MODULE_BINDINGS_KEY;
return result;
}
@Override
public boolean hasDomain() {
return true;
}
@SuppressWarnings("unchecked")
@Override
public Float[][] obtainVisualizeValues() {
Float[][] result = new Float[numberOfAlternatives][numberOfAlternatives];
if(preferences[0][0] instanceof TrapezoidalFunction) {//Preferences represented by fuzzy numbers
for (int i = 0; i < preferences.length; i++) {
for (int j = 0; j < preferences[i].length; j++)
result[i][j] = ((Double) ((TrapezoidalFunction) preferences[i][j]).centroid()).floatValue();
}
} else {//Preferences represented by CLEs
List<Structure> preferencesDM = new ArrayList<Structure>();
preferencesDM.add(this);
ArrayList<Structure> unifiedValuations = (ArrayList<Structure>) ((RunnableScript) E4DIAddon.aseService.createExecutionBuilder()
.setFunction("Unification")
.putVariable("preferences", preferencesDM)
.putVariable("blts", getDomain(null,null))
.execute())
.getResult();
ArrayList<Structure> twoTuplePreferencesDM = (ArrayList<Structure>) ((RunnableScript) E4DIAddon.aseService.createExecutionBuilder()
.setFunction("Disunification")
.putVariable("preferences", unifiedValuations)
.execute())
.getResult();
for (int i = 0; i < preferences.length; i++) {
for (int j = 0; j < preferences[i].length; j++)
result[i][j] = (float)((TwoTuple)(twoTuplePreferencesDM.get(0).getValue(i,j))).calculateInverseDelta();
}
}
return result;
}
@Override
public Object getIndifferenceValue() {
return INDIFFERENCE_VALUE;
}
}