Предыдущие части:
Пример взят из книги: Борисов, Крумберг, Федоров — «Принятие решений на основе нечетких моделей. Примеры использования», 1990. Стр. 94-102
Условие. Руководство института рассматривает кандидатов на замещение вакантной должности на факультете. Задача заключается в том, чтобы, используя описанный выше метод, выявить наилучшеrо из них. Обсуждение среди членов факультета дало следующий результат:
d1: «Если кандидат опытный исследователь, имеет некоторый производственныи стаж и опыт преподавания технических дисциплин, то он удовлетворяющий (отвечающий требованиям)»;
d2: «Если он вдобавок к вышеописанным требованиям может преподавать теорию информационных систем, то он более чем удовлетворяющий»;
d3: «Если он вдобавок к условиям d2 имеет способпость найти заказчика наукоемкой продукции, то он безупречный»;
d4: «Если оп имеет все, oгoвopeннoe в d3, кроме способности преподавать теорию информационных систем, то он очень удовлетворяющий»;
d5: «Если кандидат очень опытный исследователь, имеет способность найти заказчика и хороший преподаватель, но не имеет производственноrо стажа, он все же будет удовлетворяющим»;
d6: «Если он не имеет квалификации исследователя или не имеет проверенной способности к преподаванию, он — неудовлетворяющий».
Анализ шести информационных фраrментов дает пять критериев, используемых в принятии решения:
Х(1) — исследовательские способности;
Х(2) — производственный стаж
X(3) — опыт преподавания технических дисциплин;
Х(4) – опыт преподавания теории информационных систем
X(5) — способность наЙти заказчика.
Будем измерять эти переменные на базовом множестве U кандидатов. Обращансь к шести фрагментам, получаем:
Из строк A,B,C,D,E составляется матрица, передаваемая методу makeSkill класса input, реализующему интерфейс Input. Его описание изложено ниже (см. преобразование высказываний).
Нечеткие функции
После этого фрагменты знаний принимают вид:
d(1):“Если X=A, и B, и C, то Y=S”
d(2):”Если X=A, и B, и C, и D, то Y=MS”
d(3):”Если X=A, и B, и C, и D, и E, то Y=P”
d(4):”Если X=A, и B, иC, и E, то Y=VS”
d(5):”Если X — очень A, и не B, и C, и E, то Y=S”
d(6):”Если X= не А или не C, то Y=US”
В соответствии с вышеизложенным содержание функций в реализации:
Преобразование высказываний
Используя правило для преобразования этих высказываний, получаем
Класс Input, связывающий правило с требуемыми навыками, имеет вид:
Таким образом,
d(1): ”Если X=M(1), то Y=S”
d(2): ”Если X=M(2), то Y=MS”
d(3): ”Если X=M(3), то Y=P”
d(4): ”Если X=M(4), то Y=VS”
d(5): ”Если X=M(5), то Y=S”
d(6): ”Если X=M(6), то Y=US”
Вычисления
Используя соответствующее выражение, получаем матрицы D для каждого высказывания:
Результат работы кода:
D[1]:
0.5 0.60 0.70 0.80 0.9 1.0 1.0 1.0 1.0 1.0 1.0
0.4 0.50 0.60 0.70 0.8 0.9 1.0 1.0 1.0 1.0 1.0
0.5 0.60 0.70 0.80 0.9 1.0 1.0 1.0 1.0 1.0 1.0
0.9 1.00 1.00 1.00 1.0 1.0 1.0 1.0 1.0 1.0 1.0
0.7 0.79 0.89 1.00 1.0 1.0 1.0 1.0 1.0 1.0 1.0
D[2]:
0.5 0.53 0.58 0.66 0.75 0.85 0.96 1.0 1.0 1.0 1.0
0.7 0.73 0.78 0.86 0.95 1.00 1.00 1.0 1.0 1.0 1.0
0.5 0.53 0.58 0.66 0.75 0.85 0.96 1.0 1.0 1.0 1.0
0.9 0.93 0.98 1.00 1.00 1.00 1.00 1.0 1.0 1.0 1.0
0.7 0.73 0.78 0.86 0.95 1.00 1.00 1.0 1.0 1.0 1.0
Вот тут результаты не сходятся, но матлаб и инжереный калькулятор на моей стороне. Скорее всего, это просчет автора.
D[3]:
0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 1.0
0.7 0.7 0.7 0.7 0.7 0.7 0.7 0.7 0.7 0.7 1.0
0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 1.0
0.9 0.9 0.9 0.9 0.9 0.9 0.9 0.9 0.9 0.9 1.0
0.9 0.9 0.9 0.9 0.9 0.9 0.9 0.9 0.9 0.9 1.0
Такая же история, вероятно, одна из функций при расчетах автора была с ошибкой.
D[4]:
0.5 0.51 0.54 0.59 0.66 0.75 0.86 0.99 1.0 1.0 1.0
0.5 0.51 0.54 0.59 0.66 0.75 0.86 0.99 1.0 1.0 1.0
0.5 0.51 0.54 0.59 0.66 0.75 0.86 0.99 1.0 1.0 1.0
0.9 0.91 0.94 0.99 1.00 1.00 1.00 1.00 1.0 1.0 1.0
0.9 0.91 0.94 0.99 1.00 1.00 1.00 1.00 1.0 1.0 1.0
D[5]:
0.50 0.6 0.7 0.8 0.9 1.0 1.0 1.0 1.0 1.0 1.0
1.00 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.00 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
0.99 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.00 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
D[6]:
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.00 1.00 0.90 0.8
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.00 1.00 1.00 0.9
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.00 1.00 1.00 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.99 0.89 0.79 0.7
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.00 1.00 1.00 1.0
Общее функциональное решение D находится как пересечение нечетких множеств D(i):
D:
0.5 0.50 0.50 0.50 0.50 0.5 0.5 0.5 0.50 0.50 0.8
0.4 0.50 0.54 0.59 0.66 0.7 0.7 0.7 0.70 0.70 0.9
0.5 0.50 0.50 0.50 0.50 0.5 0.5 0.5 0.50 0.50 1.0
0.9 0.90 0.90 0.90 0.90 0.9 0.9 0.9 0.89 0.79 0.7
0.7 0.73 0.78 0.86 0.90 0.9 0.9 0.9 0.90 0.90 1.0
Возможная причина несовпадения результатов описана выше, далее сравнение с книгой идет для демонстрации общего хода решения, кто оказался «правильнее» — вопрос. Формулы одинаковые, но в мою пользу говорят эта реализация, матлаб, калькулятор; у автора же учебника на порядок больше опыта, но способ рассчета неизвестен — единственный найденный экземпляр книги датируется 1990м годом и нельзя исключать ту самую ошибку.
Подсчет точечных оценок
Мой результат:
Object #1:
E: 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.8
X: 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
Point estimate :0.6875
Object #2:
E: 0.4 0.5 0.54 0.59 0.66 0.7 0.7 0.7 0.7 0.7 0.9
X: 0.0 0.1 0.20 0.30 0.40 0.5 0.6 0.7 0.8 0.9 1.0
Point estimate :0.6561
Object #3:
E: 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 1.0
X: 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
Point estimate :0.7500
Object #4:
E: 0.7 0.79 0.89 0.9 0.9 0.9 0.9 0.9 0.9 0.9 0.9
X: 0.0 0.10 0.20 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
Point estimate :0.4833
Object #5:
E: 0.7 0.73 0.78 0.86 0.9 0.9 0.9 0.9 0.9 0.9 1.0
X: 0.0 0.10 0.20 0.30 0.4 0.5 0.6 0.7 0.8 0.9 1.0
Point estimate :0.5757308868523388
Очевидно, лучшей является третья альтернатива (оценка 0.75).
В книге лучшим признан второй кандидат (до округления его оценка была выше, чем у первого).
Исходники (проект из NetBeans 6.9.1): ifolder.ru
pass: habrahabr.ru
На всякий случай: исполняемый .jar лежит в папке \dist\
- Многокритериальный выбор альтернатив с использованием правил нечеткого вывода. Часть 1/3: Теория
- Многокритериальный выбор альтернатив с использованием правил нечеткого вывода. Реализация на Java. Часть 2/3: Основной алгоритм
Пример взят из книги: Борисов, Крумберг, Федоров — «Принятие решений на основе нечетких моделей. Примеры использования», 1990. Стр. 94-102
Условие. Руководство института рассматривает кандидатов на замещение вакантной должности на факультете. Задача заключается в том, чтобы, используя описанный выше метод, выявить наилучшеrо из них. Обсуждение среди членов факультета дало следующий результат:
d1: «Если кандидат опытный исследователь, имеет некоторый производственныи стаж и опыт преподавания технических дисциплин, то он удовлетворяющий (отвечающий требованиям)»;
d2: «Если он вдобавок к вышеописанным требованиям может преподавать теорию информационных систем, то он более чем удовлетворяющий»;
d3: «Если он вдобавок к условиям d2 имеет способпость найти заказчика наукоемкой продукции, то он безупречный»;
d4: «Если оп имеет все, oгoвopeннoe в d3, кроме способности преподавать теорию информационных систем, то он очень удовлетворяющий»;
d5: «Если кандидат очень опытный исследователь, имеет способность найти заказчика и хороший преподаватель, но не имеет производственноrо стажа, он все же будет удовлетворяющим»;
d6: «Если он не имеет квалификации исследователя или не имеет проверенной способности к преподаванию, он — неудовлетворяющий».
Анализ шести информационных фраrментов дает пять критериев, используемых в принятии решения:
Х(1) — исследовательские способности;
Х(2) — производственный стаж
X(3) — опыт преподавания технических дисциплин;
Х(4) – опыт преподавания теории информационных систем
X(5) — способность наЙти заказчика.
Будем измерять эти переменные на базовом множестве U кандидатов. Обращансь к шести фрагментам, получаем:
Из строк A,B,C,D,E составляется матрица, передаваемая методу makeSkill класса input, реализующему интерфейс Input. Его описание изложено ниже (см. преобразование высказываний).
Нечеткие функции
После этого фрагменты знаний принимают вид:
d(1):“Если X=A, и B, и C, то Y=S”
d(2):”Если X=A, и B, и C, и D, то Y=MS”
d(3):”Если X=A, и B, и C, и D, и E, то Y=P”
d(4):”Если X=A, и B, иC, и E, то Y=VS”
d(5):”Если X — очень A, и не B, и C, и E, то Y=S”
d(6):”Если X= не А или не C, то Y=US”
В соответствии с вышеизложенным содержание функций в реализации:
package Function;
import Support.Function;
public class mMS extends Function { /*более, чем удовлетворяющий*/
public mMS(){}
public double getY(double x) {
return x*Math.sqrt(x);
}
}
package Function;
import Support.Function;
public class mP extends Function{ /*безупречный*/
public mP(){}
public double getY(double x) {
if (x==1) return 1;
return 0;
}
}
package Function;
import Support.Function;
public class mVS extends Function{ /*очень удовлетворяющий*/
public mVS(){}
public double getY(double x) {
return x*x;
}
}
package Function;
import Support.Function;
public class mS extends Function { /*удовлетворяющий*/
public mS(){}
public double getY(double x) {
return x;
}
}
package Function;
import Support.Function;
public class mUS extends Function{ /*не удовлетворяющий*/
public mUS(){}
public double getY(double x) {
return 1-x;
}
}
Преобразование высказываний
Используя правило для преобразования этих высказываний, получаем
Класс Input, связывающий правило с требуемыми навыками, имеет вид:
package FLO_Engine;
import Support.Function;
import Support.Input;
import Support.Rule;
import Support.Skill;
public class input extends Input{
private Skill A,B,C,D,E,A_M5,B_M5,A_M6,C_M6;
public input(){ /* переменные для контроля количества параметров и функций */
PARAMS_CNT = 5;
FUNC_CNT = 6;
}
public void initFunc(Function[] func){
this.func = func;
}
private void makeSkill(double[][] arr){ /* подсчет навыков для создания правил; так как их объекты еще не созданы, использовать реализации Function нельзя и удобнее пересчитывать их значения вручную */
rl = new Rule[FUNC_CNT];
A = new Skill(arr[0]);
B = new Skill(arr[1]);
C = new Skill(arr[2]);
D = new Skill(arr[3]);
E = new Skill(arr[4]);
double[][] u=arr;
double[] a_m5 = (double[]) u[0].clone();
for (int i=0;i<u[0].length;i++)
a_m5[i]*=a_m5[i]; /*очень удовлетворяющий*/
A_M5 = new Skill(a_m5);
double[] b_m5 = (double[]) u[1].clone();
for (int i=0;i<u[1].length;i++)
b_m5[i]= 1 — b_m5[i]; /* не удовлетворяющий */
B_M5 = new Skill(b_m5);
double[] a_m6 = (double[]) u[0].clone();
for (int i=0;i<u[0].length;i++)
a_m6[i] = 1 — a_m6[i]; /* не удовлетворяющий */
A_M6 = new Skill(a_m6);
double[] c_m6 = (double[]) u[2].clone();
for (int i=0;i<u[2].length;i++)
c_m6[i] = 1 — c_m6[i]; /* не удовлетворяющий */
C_M6 = new Skill(c_m6);
}
public Rule[] makeRules(double[][] arr) throws Exception{
makeSkill(arr);
rl[0] = new Rule(new Skill[]{A,B,C} ,func[0]); // высказывание d1
rl[1] = new Rule(new Skill[]{A,B,C,D} ,func[1]); // высказывание d2
rl[2] = new Rule(new Skill[]{A,B,C,D,E} ,func[2]); // высказывание d3
rl[3] = new Rule(new Skill[]{A,B,C,E} ,func[3]); // высказывание d4
rl[4] = new Rule(new Skill[]{A_M5,B_M5,C,E} ,func[4]); // высказывание d5
rl[5] = new Rule(new Skill[]{A_M6,C_M6} ,func[5]); // высказывание d6
return rl;
}
}
Таким образом,
d(1): ”Если X=M(1), то Y=S”
d(2): ”Если X=M(2), то Y=MS”
d(3): ”Если X=M(3), то Y=P”
d(4): ”Если X=M(4), то Y=VS”
d(5): ”Если X=M(5), то Y=S”
d(6): ”Если X=M(6), то Y=US”
Вычисления
Используя соответствующее выражение, получаем матрицы D для каждого высказывания:
Результат работы кода:
D[1]:
0.5 0.60 0.70 0.80 0.9 1.0 1.0 1.0 1.0 1.0 1.0
0.4 0.50 0.60 0.70 0.8 0.9 1.0 1.0 1.0 1.0 1.0
0.5 0.60 0.70 0.80 0.9 1.0 1.0 1.0 1.0 1.0 1.0
0.9 1.00 1.00 1.00 1.0 1.0 1.0 1.0 1.0 1.0 1.0
0.7 0.79 0.89 1.00 1.0 1.0 1.0 1.0 1.0 1.0 1.0
D[2]:
0.5 0.53 0.58 0.66 0.75 0.85 0.96 1.0 1.0 1.0 1.0
0.7 0.73 0.78 0.86 0.95 1.00 1.00 1.0 1.0 1.0 1.0
0.5 0.53 0.58 0.66 0.75 0.85 0.96 1.0 1.0 1.0 1.0
0.9 0.93 0.98 1.00 1.00 1.00 1.00 1.0 1.0 1.0 1.0
0.7 0.73 0.78 0.86 0.95 1.00 1.00 1.0 1.0 1.0 1.0
Вот тут результаты не сходятся, но матлаб и инжереный калькулятор на моей стороне. Скорее всего, это просчет автора.
D[3]:
0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 1.0
0.7 0.7 0.7 0.7 0.7 0.7 0.7 0.7 0.7 0.7 1.0
0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 1.0
0.9 0.9 0.9 0.9 0.9 0.9 0.9 0.9 0.9 0.9 1.0
0.9 0.9 0.9 0.9 0.9 0.9 0.9 0.9 0.9 0.9 1.0
Такая же история, вероятно, одна из функций при расчетах автора была с ошибкой.
D[4]:
0.5 0.51 0.54 0.59 0.66 0.75 0.86 0.99 1.0 1.0 1.0
0.5 0.51 0.54 0.59 0.66 0.75 0.86 0.99 1.0 1.0 1.0
0.5 0.51 0.54 0.59 0.66 0.75 0.86 0.99 1.0 1.0 1.0
0.9 0.91 0.94 0.99 1.00 1.00 1.00 1.00 1.0 1.0 1.0
0.9 0.91 0.94 0.99 1.00 1.00 1.00 1.00 1.0 1.0 1.0
D[5]:
0.50 0.6 0.7 0.8 0.9 1.0 1.0 1.0 1.0 1.0 1.0
1.00 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.00 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
0.99 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.00 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
D[6]:
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.00 1.00 0.90 0.8
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.00 1.00 1.00 0.9
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.00 1.00 1.00 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.99 0.89 0.79 0.7
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.00 1.00 1.00 1.0
Общее функциональное решение D находится как пересечение нечетких множеств D(i):
D:
0.5 0.50 0.50 0.50 0.50 0.5 0.5 0.5 0.50 0.50 0.8
0.4 0.50 0.54 0.59 0.66 0.7 0.7 0.7 0.70 0.70 0.9
0.5 0.50 0.50 0.50 0.50 0.5 0.5 0.5 0.50 0.50 1.0
0.9 0.90 0.90 0.90 0.90 0.9 0.9 0.9 0.89 0.79 0.7
0.7 0.73 0.78 0.86 0.90 0.9 0.9 0.9 0.90 0.90 1.0
Возможная причина несовпадения результатов описана выше, далее сравнение с книгой идет для демонстрации общего хода решения, кто оказался «правильнее» — вопрос. Формулы одинаковые, но в мою пользу говорят эта реализация, матлаб, калькулятор; у автора же учебника на порядок больше опыта, но способ рассчета неизвестен — единственный найденный экземпляр книги датируется 1990м годом и нельзя исключать ту самую ошибку.
Подсчет точечных оценок
Мой результат:
Object #1:
E: 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.8
X: 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
Point estimate :0.6875
Object #2:
E: 0.4 0.5 0.54 0.59 0.66 0.7 0.7 0.7 0.7 0.7 0.9
X: 0.0 0.1 0.20 0.30 0.40 0.5 0.6 0.7 0.8 0.9 1.0
Point estimate :0.6561
Object #3:
E: 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 1.0
X: 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
Point estimate :0.7500
Object #4:
E: 0.7 0.79 0.89 0.9 0.9 0.9 0.9 0.9 0.9 0.9 0.9
X: 0.0 0.10 0.20 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
Point estimate :0.4833
Object #5:
E: 0.7 0.73 0.78 0.86 0.9 0.9 0.9 0.9 0.9 0.9 1.0
X: 0.0 0.10 0.20 0.30 0.4 0.5 0.6 0.7 0.8 0.9 1.0
Point estimate :0.5757308868523388
Очевидно, лучшей является третья альтернатива (оценка 0.75).
В книге лучшим признан второй кандидат (до округления его оценка была выше, чем у первого).
Исходники (проект из NetBeans 6.9.1): ifolder.ru
pass: habrahabr.ru
На всякий случай: исполняемый .jar лежит в папке \dist\