410 lines
12 KiB
Java
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;
|
|
}
|
|
}
|