у меня есть пример выаолнения задания:
Реализовать решение задачи на базе нечеткой логики:

Четыре рыцаря. В турнире, устроенным королевой, предстояло сразиться четырем рыцарям. Из них сэр Альбус был самым храбрым, сэр Брюс, восседавший верхом на коне Джеронино был самым могучим, сэр Каспар, чье лицо было скрыто за пурпурным забралом, был самым высокомерным, а сэр Даниель, чье копье украшал сиреневый флажок, был самым хитрым. Рыцарь с серебристым щитом оседлал Евангелину, рыцарь с оранжевым султаном на шлеме ехал на Фурни, а рыцарь с серебристым забралом – на Геркулесе. Рыцарь с пурпурным щитом скрыл лицо оранжевым забралом, шлем другого был украшен серебристым султаном, а в руке он держал оранжевый щит, у третьего на
копье красовался серебристый флажок, а щит был сиреневого цвета, забрало четвертого было сиреневого цвета, а флажок на копье был пурпурный. Брат сэра Каспара щеголял сиреневым султаном и оранжевым флажком. "Кто же этот благородный рыцарь с пурпурным султаном?" – спросила королева своего супруга. Помогите королю ответить на вопрос. Конечно, у всех рыцарей флажки были разного цвета, то же относится и к другим деталям их снаряжения.

import numpy as np

Определяем нечёткие характеристики рыцарей
knights = [
{'name': 'сэр Альбус', 'horse': 'Евангелина', 'attributes': {'sword_flag': {'пурпурный': 0.9, 'оранжевый': 0.1, 'серебристый': 0.2, 'сиреневый': 0.3},
'shield_color': {'серебристый': 1.0, 'пурпурный': 0.2, 'сиреневый': 0.1, 'оранжевый': 0.1},
'helmet_sultan': {'пурпурный': 0.95, 'оранжевый': 0.2, 'сиреневый': 0.3, 'серый': 0.1},
'visor_color': {'сиреневый': 0.85, 'оранжевый': 0.1, 'серебристый': 0.2, 'пурпурный': 0.3}}},


{'name': 'сэр Брюс', 'horse': 'Джеронино', 'attributes': {'sword_flag': {'пурпурный': 0.2, 'оранжевый': 0.9, 'серебристый': 0.3, 'сиреневый': 0.1},
                                                          'shield_color': {'серебристый': 0.1, 'пурпурный': 0.95, 'сиреневый': 0.2, 'оранжевый': 0.3},
                                                          'helmet_sultan': {'пурпурный': 0.2, 'оранжевый': 0.1, 'сиреневый': 0.9, 'серый': 0.2},
                                                          'visor_color': {'сиреневый': 0.3, 'оранжевый': 0.85, 'серебристый': 0.2, 'пурпурный': 0.1}}},



{'name': 'сэр Каспар', 'horse': 'Фурни', 'attributes': {'sword_flag': {'пурпурный': 0.1, 'оранжевый': 0.2, 'серебристый': 0.95, 'сиреневый': 0.3},
                                                        'shield_color': {'серебристый': 0.2, 'пурпурный': 0.1, 'сиреневый': 0.9, 'оранжевый': 0.3},
                                                        'helmet_sultan': {'пурпурный': 0.2, 'оранжевый': 0.85, 'сиреневый': 0.3, 'серый': 0.2},
                                                        'visor_color': {'сиреневый': 0.3, 'оранжевый': 0.2, 'серебристый': 0.1, 'пурпурный': 0.9}}},



{'name': 'сэр Даниель', 'horse': 'Геркулес', 'attributes': {'sword_flag': {'пурпурный': 0.3, 'оранжевый': 0.2, 'серебристый': 0.1, 'сиреневый': 0.95},
                                                            'shield_color': {'серебристый': 0.1, 'пурпурный': 0.2, 'сиреневый': 0.3, 'оранжевый': 0.9},
                                                            'helmet_sultan': {'пурпурный': 0.1, 'оранжевый': 0.2, 'сиреневый': 0.3, 'серый': 0.95},
                                                            'visor_color': {'сиреневый': 0.9, 'оранжевый': 0.2, 'серебристый': 0.1, 'пурпурный': 0.3}}}
]

Нечеткие правила
rules = [
{'condition': {'sword_flag': 'пурпурный', 'shield_color': 'серебристый', 'helmet_sultan': 'пурпурный', 'horse': 'Евангелина'}, 'action': 'сэр Альбус'},
{'condition': {'sword_flag': 'оранжевый', 'shield_color': 'пурпурный', 'helmet_sultan': 'сиреневый', 'horse': 'Джеронино'}, 'action': 'сэр Брюс'},
{'condition': {'sword_flag': 'серебристый', 'shield_color': 'сиреневый', 'helmet_sultan': 'оранжевый', 'horse': 'Фурни'}, 'action': 'сэр Каспар'},
{'condition': {'sword_flag': 'сиреневый', 'shield_color': 'оранжевый', 'helmet_sultan': 'серый', 'horse': 'Геркулес'}, 'action': 'сэр Даниель'}
]

Прямой вывод с расчётом степени соответствия
def direct_inference_fuzzy(knight):
max_confidence = 0
best_match = None
for rule in rules:
confidence = 1.0
print(f"Проверяем рыцаря {knight['name']} для правила {rule['action']}") # Диагностика
for key, value in rule['condition'].items():
if key in knight['attributes']:
confidence *= knight['attributes'][key].get(value, 0)
print(f" -> {key}: значение в рыцаре = {value}, уверенность = {confidence:.2f}") # Диагностика
elif knight[key] != value:
confidence = 0
if confidence > max_confidence:
max_confidence = confidence
best_match = rule['action']
return best_match, max_confidence

Обратный вывод с расчётом вероятности
def reverse_inference_fuzzy(target):
best_knight = None
max_probability = 0
for knight in knights:
probability = knight['attributes']['helmet_sultan'].get(target, 0)
print(f"Рыцарь {knight['name']} -> вероятность {target} султана = {probability:.2f}") # Диагностика
if probability > max_probability:
max_probability = probability
best_knight = knight['name']
return best_knight, max_probability

Вывод информации о рыцарях
print("\nПрямой вывод (нечёткая логика):")
for knight in knights:
match, confidence = direct_inference_fuzzy(knight)
if match:
print(f"{knight['name']} -> {match} (Уверенность: {confidence:.2f})")
else:
print(f"{knight['name']} -> Нет соответствий в правилах")

Поиск рыцаря с пурпурным султаном
target = 'пурпурный'
knight, probability = reverse_inference_fuzzy(target)
if knight:
print(f"\nБлагородный рыцарь с пурпурным султаном: {knight} (Вероятность: {probability:.2f})")
else:
print("\nНе удалось найти рыцаря с пурпурным султаном")
Есть пример такой:
Пятеро школьников из пяти различных городов приехали в Смоленск для участия в
областной математической олимпиаде. "Откуда вы, ребята?" – спросили их. Вот что они
ответили. Андреев: "Я приехал из Рославля, а Григорьев живет в Гагарине". Борисов: "В
Гагарине живет Васильев, я прибыл из Вязьмы". Васильев: "Из Рославля приехал я, а
Борисов из Ельни". Григорьев: "Я прибыл из Гагарина, а Данилов – из Ярцева". Данилов:
"Да, я действительно из Ярцева, Андреева живет в Вязьме". Когда удивились
противоречивости их ответов, ребята объяснили: Каждый высказал одно утверждение
правильное, а другое ложное. Но по нашим ответам вполне можно узнать, откуда мы
приехали. Откуда приехал каждый из школьников?
#include
#include
#include
#include
#include <windows.h>
#include
using namespace std;
// Хранение степеней принадлежности для фактов
map<string, double> fuzzyFacts;
// Структура правила
struct Rule {
string part1; // условие
string part2; // вывод
double weight; // вес правила (степень уверенности)
};
// База правил
vector fuzzyRules;
// Функция для обработки строк
string Trim(string s) {
while (s.length() > 0 && s[0] == ' ') s = s.erase(0, 1);
while (s.length() > 0 && s[s.length() - 1] == ' ') s = s.erase(s.length() - 1, 1);
return s;
}
// Разделение строки по запятой
vector Split(const string& s, char delimiter) {
vector tokens;

size_t start = 0, end = 0;
while ((end = s.find(delimiter, start)) != string::npos) {
tokens.push_back(Trim(s.substr(start, end - start)));
start = end + 1;
}
tokens.push_back(Trim(s.substr(start)));
return tokens;
}
// Проверка факта с учетом степени принадлежности
double GetFactValue(string fact) {
fact = Trim(fact);
if (fuzzyFacts.find(fact) != fuzzyFacts.end()) {
return fuzzyFacts[fact];
}
return 0.0; // Факт отсутствует — принадлежность равна 0
}
// Добавление нового факта
void AddFact(string fact, double value) {
fact = Trim(fact);
fuzzyFacts[fact] = max(fuzzyFacts[fact], value); // Учитываем максимальную принадлежность
}
// Применение правил
void ApplyRules() {
bool updated;
do {
updated = false;
for (const auto& rule : fuzzyRules) {
// Разделяем условия
vector conditions = Split(rule.part1, ',');
double minDegree = 1.0;
// Вычисляем минимальную степень принадлежности среди условий
for (const string& condition : conditions) {
minDegree = min(minDegree, GetFactValue(condition));
}
// Умножаем на вес правила
double conclusionValue = minDegree * rule.weight;
// Добавляем вывод с учетом текущей максимальной степени
if (conclusionValue > GetFactValue(rule.part2)) {
AddFact(rule.part2, conclusionValue);
updated = true;
}
}
} while (updated);
}
// Вывод текущего состояния фактов
void ShowFactsLegacy() {
cout << "\nСостояние рабочей памяти (степени принадлежности):\n";
for (const auto& fact : fuzzyFacts) {
string displayFact = fact.first;
// Заменяем "Лучший" на "Лучшая уверенность"
if (displayFact.find("Лучший") != string::npos) {
displayFact.replace(displayFact.find("Лучший"), 7, "Лучшая уверенность");
}
cout << displayFact << ": " << fact.second << endl;
}
}
// Вывод итогового решения
void ShowBestResults() {

cout << "\nИтоговое решение:\n";
// Храним пары "тип" -> "лучший факт"
map<string, pair<string, double>> bestResults;
for (const auto& fact : fuzzyFacts) {
if (fact.first.find("Лучшая уверенность") == string::npos) {
// Определяем тип человека (имя)
string name = fact.first.substr(0, fact.first.find(" из "));
if (bestResults.find(name) == bestResults.end() || fact.second > bestResults[name].second) {
bestResults[name] = { fact.first, fact.second };
}
}
}
// Выводим лучшие результаты
for (const auto& result : bestResults) {
cout << result.second.first << endl;
}
}
// Главная функция
int main() {
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
// Инициализация фактов
AddFact("Андреев из Вязьмы", 0.5);
AddFact("Андреев из Рославля", 0.9);
AddFact("Борисов из Вязьмы", 0.7);
AddFact("Борисов из Ельни", 1.0);
AddFact("Васильев из Гагарина", 0.85);
AddFact("Григорьев из Вязьмы", 0.75);
AddFact("Данилов из Ярцева", 1.0);
// Добавление правил
fuzzyRules.push_back({ "Андреев из Рославля", "Лучшая уверенность Андреев", 1.0 });
fuzzyRules.push_back({ "Борисов из Ельни", "Лучшая уверенность Борисов", 1.0 });
fuzzyRules.push_back({ "Васильев из Гагарина", "Лучшая уверенность Васильев", 1.0 });
fuzzyRules.push_back({ "Григорьев из Вязьмы", "Лучшая уверенность Григорьев", 1.0 });
fuzzyRules.push_back({ "Данилов из Ярцева", "Лучшая уверенность Данилов", 1.0 });
// Применение правил
ApplyRules();
// Вывод результатов
ShowFactsLegacy();
// Итоговое решение
ShowBestResults();
return 0;
}
мне нужна программа на C# для этой задачи:
На танцах. Эд, Франк, Джордж и Гарри пригласили своих жен
в вечерний клуб на танцы и для разнообразия решили, что
каждый будет танцевать с женой другого. В результате Бетти
танцевала с Эдом, Алиса – с мужем Кэрол, Дороти – с мужем
Алисы, Франк – с женой Джорджа, а Джордж – с женой Эда.
Кто на ком женат? Кто с кем танцевал?
У меня есть такой код, но мне кажется он абсолютно неправильный:

using System;
using System.Collections.Generic;
using System.Linq;

namespace FuzzyLogicMarriage
{
class Program
{
static void Main(string[] args)
{
// Участники
string[] men = { "Эд", "Фрэнк", "Джордж", "Гарри" };
string[] women = { "Бетти", "Алиса", "Дороти", "Кэрол" };


        // Генерация всех возможных перестановок жен
        var marriagePermutations = GetPermutations(women, women.Length).ToList();

        // Для хранения вероятностей браков и танцев
        Dictionary<(string man, string woman), double> marriageProbabilities = new Dictionary<(string, string), double>();
        Dictionary<(string man, string woman), double> danceProbabilities = new Dictionary<(string, string), double>();

        // Инициализация вероятностей браков
        InitializeMarriageProbabilities(marriageProbabilities);

        // Инициализация вероятностей танцев
        InitializeDanceProbabilities(danceProbabilities);

        bool solutionFound = false;

        foreach (var marriage in marriagePermutations)
        {
            // Заполняем карту браков для текущей перестановки
            Dictionary<string, string> marriageMap = new Dictionary<string, string>();
            for (int i = 0; i < men.Length; i++)
            {
                marriageMap[men[i]] = marriage[i];
            }

            // Проверяем браки
            double totalMarriageProbability = 0;

            for (int i = 0; i < men.Length; i++)
            {
                var key = (men[i], marriage[i]);
                totalMarriageProbability += marriageProbabilities.ContainsKey(key) ? marriageProbabilities[key] : 0;
            }

            double averageMarriageProbability = totalMarriageProbability / men.Length;

            if (averageMarriageProbability < 0.5)
                continue;

            // Проверяем танцевальные пары
            double totalDanceProbability = 0;
            Dictionary<string, string> danceMap = new Dictionary<string, string>();
            HashSet<string> usedWomen = new HashSet<string>();

            foreach (var man in men)
            {
                foreach (var woman in women)
                {
                    // Убедимся, что мужчина не танцует с женой и женщина ещё не танцевала
                    if (marriageMap.ContainsKey(man) && marriageMap[man] == woman || usedWomen.Contains(woman))
                        continue;

                    // Проверяем вероятность танцев
                    if (danceProbabilities.ContainsKey((man, woman)))
                    {
                        totalDanceProbability += danceProbabilities[(man, woman)];
                        danceMap[man] = woman;
                        usedWomen.Add(woman); // Женщина больше не может танцевать
                        break;
                    }
                }
            }

            double finalProbability = (averageMarriageProbability + totalDanceProbability / men.Length) / 2;

            if (finalProbability >= 0.6)
            {
                Console.WriteLine("\n=== Решение Найдено ===\n");

                Console.WriteLine("Браки:");
                foreach (var man in men)
                {
                    Console.WriteLine($"{man} женат на {marriageMap[man]}");
                }

                Console.WriteLine("\nТанцевальные пары:");
                foreach (var pair in danceMap)
                {
                    Console.WriteLine($"{pair.Key} танцевал с {pair.Value}");
                }

                solutionFound = true;
                break;
            }
        }

        if (!solutionFound)
        {
            Console.WriteLine("Решение не найдено.");
        }

        // Ожидание нажатия клавиши перед выходом
        Console.WriteLine("\nНажмите любую клавишу, чтобы выйти...");
        Console.ReadKey();
    }

    // Метод для генерации всех перестановок
    static IEnumerable<string[]> GetPermutations(string[] list, int length)
    {
        if (length == 1)
            return list.Select(t => new string[] { t });

        return GetPermutations(list, length - 1)
            .SelectMany(t => list.Where(e => !t.Contains(e)),
                        (t1, t2) => t1.Concat(new string[] { t2 }).ToArray());
    }

    // Инициализация вероятностей браков
    static void InitializeMarriageProbabilities(Dictionary<(string, string), double> marriageProbabilities)
    {
        marriageProbabilities[("Эд", "Бетти")] = 0.0;
        marriageProbabilities[("Эд", "Алиса")] = 0.0;
        marriageProbabilities[("Эд", "Дороти")] = 0.7;
        marriageProbabilities[("Эд", "Кэрол")] = 0.6;

        marriageProbabilities[("Фрэнк", "Бетти")] = 0.1;
        marriageProbabilities[("Фрэнк", "Алиса")] = 0.5;
        marriageProbabilities[("Фрэнк", "Дороти")] = 0.2;
        marriageProbabilities[("Фрэнк", "Кэрол")] = 0.7;

        marriageProbabilities[("Джордж", "Бетти")] = 0.3;
        marriageProbabilities[("Джордж", "Алиса")] = 0.7;
        marriageProbabilities[("Джордж", "Дороти")] = 0.2;
        marriageProbabilities[("Джордж", "Кэрол")] = 0.4;

        marriageProbabilities[("Гарри", "Бетти")] = 0.5;
        marriageProbabilities[("Гарри", "Алиса")] = 0.5;
        marriageProbabilities[("Гарри", "Дороти")] = 0.5;
        marriageProbabilities[("Гарри", "Кэрол")] = 0.5;
    }

    // Инициализация вероятностей танцев
    static void InitializeDanceProbabilities(Dictionary<(string, string), double> danceProbabilities)
    {
        // Вероятности танцевальных пар
        danceProbabilities[("Эд", "Бетти")] = 1.0;
        danceProbabilities[("Эд", "Алиса")] = 0.0;
        danceProbabilities[("Эд", "Дороти")] = 0.0;
        danceProbabilities[("Эд", "Кэрол")] = 0.0;

        danceProbabilities[("Фрэнк", "Бетти")] = 0.0;
        danceProbabilities[("Фрэнк", "Алиса")] = 0.9;
        danceProbabilities[("Фрэнк", "Дороти")] = 0.4;
        danceProbabilities[("Фрэнк", "Кэрол")] = 0.8;

        danceProbabilities[("Джордж", "Бетти")] = 0.0;
        danceProbabilities[("Джордж", "Алиса")] = 0.5;
        danceProbabilities[("Джордж", "Дороти")] = 1.0;
        danceProbabilities[("Джордж", "Кэрол")] = 0.4;

        danceProbabilities[("Гарри", "Бетти")] = 0.0;
        danceProbabilities[("Гарри", "Алиса")] = 0.3;
        danceProbabilities[("Гарри", "Дороти")] = 0.5;
        danceProbabilities[("Гарри", "Кэрол")] = 1.0;
    }
}
}
мне не нравится способ решения, мне кажется в примерах выше задача решается другим способом