Предыдущие части:
Пример взят из книги: Борисов, Крумберг, Федоров — «Принятие решений на основе нечетких моделей. Примеры использования», 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\
