//Результатом вычисления кообласти является коллекция морфизмов, полученная в результате применения функуторов, //являющихся элементами морфизма, другим элементам морфизма. //public static List<Конус> Вычислить(Конус f) //{ // List<Конус> результат = new List<Конус>(); // Конус шаблон = ШаблоныФункторов.FirstOrDefault(p => f.СоответствуетШаблону(p)); // //Если соответствующий f шаблон функтора не найден, возвращаем морфизм как есть (соответствует тождественному функтору) // if (шаблон == null) // { // результат.Add(f); // return результат; // } // //Здесь используется инфиксная для 2-функторов и постфиксная для 1-функторов запись. // //Поэтому второй элемент шаблона (с индексом 1) содержит символ типа функтора. // switch (шаблон.Элементы[1].Имя) // { // case "id": // { // результат = Вычислить(f.Элементы[0]); // } break; // case ">": // { // List<Конус> левыйОперанд = Вычислить(f.Элементы[0]); // List<Конус> правыйОперанд = Вычислить(f.Элементы[2]); // результат = ВычислитьОбласть(левыйОперанд, правыйОперанд); // } break; // case "<": // { // List<Конус> левыйОперанд = Вычислить(f.Элементы[0]); // List<Конус> правыйОперанд = Вычислить(f.Элементы[2]); // результат = ВычислитьКообласть(левыйОперанд, правыйОперанд); // }; break; // case "*": // { // List<Конус> левыйОперанд = Вычислить(f.Элементы[0]); // List<Конус> правыйОперанд = Вычислить(f.Элементы[2]); // результат = ВычислитьПроизведение(левыйОперанд, правыйОперанд); // }; break; // case "+": // { // List<Конус> левыйОперанд = Вычислить(f.Элементы[0]); // List<Конус> правыйОперанд = Вычислить(f.Элементы[2]); // результат = ВычислитьСумму(левыйОперанд, правыйОперанд); // }; break; // case "-": // { // List<Конус> левыйОперанд = Вычислить(f.Элементы[0]); // List<Конус> правыйОперанд = Вычислить(f.Элементы[2]); // результат = ВычислитьРазность(левыйОперанд, правыйОперанд); // }; break; // case "^": // { // List<Конус> левыйОперанд = Вычислить(f.Элементы[0]); // List<Конус> правыйОперанд = Вычислить(f.Элементы[2]); // результат = ВычислитьПересечение(левыйОперанд, правыйОперанд); // }; break; // case "~:": // { // List<Конус> левыйОперанд = Вычислить(f.Элементы[0]); // List<Конус> правыйОперанд = Вычислить(f.Элементы[2]); // результат = ВычислитьПроекцию(левыйОперанд, правыйОперанд); // }; break; // case "~": // { // List<Конус> левыйОперанд = Вычислить(f.Элементы[0]); // List<Конус> правыйОперанд = Вычислить(f.Элементы[2]); // результат = ВычислитьВыбор(левыйОперанд, правыйОперанд); // }; break; // default: // { // результат.Add(f); // }; break; // } // return результат; //} //Метод использует слово как ленту конвеера для выполнения вычислений над словами-элементами исходного слова public static Dictionary <string, Конус> ВычислитьФунктор(Конус f) { Dictionary <string, Конус> результат = new Dictionary <string, Конус>(); if (f.ЭтоАтом() || f.ЭтоШаблон()) { результат.Add(f.Имя, f); return(результат); } Dictionary <string, Конус>[] результаты = new Dictionary <string, Конус> [f.Элементы.Length]; //массив списков результатов for (int i = 0; i < f.Элементы.Length; i++) { Конус e = f.Элементы[i]; результаты[i] = new Dictionary <string, Конус>(); //Если i-й элемент слова не распознается как функтор if (!ЭтоИмяФунктора(e.Имя)) { //и если значение для i-го элемента еще не вычислено, то вычисляем значение рекурсивно Dictionary <string, Конус> результатЭлемента = ВычислитьФунктор(e); foreach (string key in результатЭлемента.Keys) { результаты[i][key] = результатЭлемента[key]; } } else { if (i == 0) { continue; } switch (e.Имя) { case "id": { foreach (string key in результаты[i].Keys) { результаты[i][key] = результаты[i - 1][key]; } }; break; case ">": { Dictionary <string, Конус> результатЭлемента = ВычислитьОбласть(результаты[i - 1]); foreach (string key in результатЭлемента.Keys) { результаты[i][key] = результатЭлемента[key]; } }; break; case "<": { Dictionary <string, Конус> результатЭлемента = ВычислитьКообласть(результаты[i - 1]); foreach (string key in результатЭлемента.Keys) { результаты[i][key] = результатЭлемента[key]; } }; break; case "*": { Dictionary <string, Конус> результатЭлемента = new Dictionary <string, Конус>(); if (i > 1) { результатЭлемента = ВычислитьПроизведение(результаты[i - 2], результаты[i - 1]); } else if (i > 0) { результатЭлемента = результаты[i - 1]; } foreach (string key in результатЭлемента.Keys) { результаты[i][key] = результатЭлемента[key]; } }; break; case "+": { Dictionary <string, Конус> результатЭлемента = new Dictionary <string, Конус>(); if (i > 1) { результатЭлемента = ВычислитьСумму(результаты[i - 2], результаты[i - 1]); } else if (i > 0) { результатЭлемента = результаты[i - 1]; } foreach (string key in результатЭлемента.Keys) { результаты[i][key] = результатЭлемента[key]; } }; break; case "-": { Dictionary <string, Конус> результатЭлемента = new Dictionary <string, Конус>(); if (i > 1) { результатЭлемента = ВычислитьРазность(результаты[i - 2], результаты[i - 1]); } else if (i > 0) { результатЭлемента = результаты[i - 1]; } foreach (string key in результатЭлемента.Keys) { результаты[i][key] = результатЭлемента[key]; } }; break; case "^": { Dictionary <string, Конус> результатЭлемента = new Dictionary <string, Конус>(); if (i > 1) { результатЭлемента = ВычислитьПересечение(результаты[i - 2], результаты[i - 1]); } foreach (string key in результатЭлемента.Keys) { результаты[i][key] = результатЭлемента[key]; } }; break; case "~:": { Dictionary <string, Конус> результатЭлемента = new Dictionary <string, Конус>(); if (i > 1) { результатЭлемента = ВычислитьПроекцию(результаты[i - 2].Values, результаты[i - 1].Values).ToDictionary(m => m.Имя); } foreach (string key in результатЭлемента.Keys) { результаты[i][key] = результатЭлемента[key]; } }; break; case "~": { Dictionary <string, Конус> результатЭлемента = new Dictionary <string, Конус>(); if (i > 1) { результатЭлемента = ВычислитьВыбор(результаты[i - 2], результаты[i - 1]); } foreach (string key in результатЭлемента.Keys) { результаты[i][key] = результатЭлемента[key]; } }; break; case ">:": { Dictionary <string, Конус> результатЭлемента = new Dictionary <string, Конус>(); if (i > 0) { результатЭлемента = ВычислитьКопредел(результаты[i - 1]); } foreach (string key in результатЭлемента.Keys) { результаты[i][key] = результатЭлемента[key]; } }; break; case "<:": { Dictionary <string, Конус> результатЭлемента = new Dictionary <string, Конус>(); if (i > 0) { результатЭлемента = ВычислитьПредел(результаты[i - 1]); } foreach (string key in результатЭлемента.Keys) { результаты[i][key] = результатЭлемента[key]; } }; break; default: { throw new Exception("Неизвестный функтор:" + e.Имя); }; } } } return(результаты[f.Элементы.Length - 1]); }