//Удаление слова из области public void УдалитьИзОбласти(Конус w) { if (Область.Remove(w.Имя)) { w.Кообласть.Remove(Имя); } }
public void TestConstructors() { //Проверка создания слова Конус word1 = new Конус("Word1"); Assert.IsNotNull(word1.Элементы); Assert.AreEqual(word1.Имя, "Word1"); //Проверка инициализации из другого слова Конус word2 = new Конус(word1); Assert.AreEqual(word2.Имя, "Word1"); Конус[] words = new Конус[] { new Конус("1"), new Конус("2"), new Конус("3") }; Конус word3 = new Конус(words); //Проверка изменения имени при присвоении состава элементов слова Assert.AreEqual(word3.Имя, "[1,2,3]"); //Проверка изменения значения Элементы и соответствующего изменения имени слова Конус word4 = new Конус( new Конус[] { word3, new Конус("4"), new Конус("5"), new Конус("6") } ); Assert.AreEqual(word4.Имя, "[[1,2,3],4,5,6]"); }
public Конус(Конус w) { имя = w.Имя; элементы = new Конус[w.Элементы.Length]; w.Элементы.CopyTo(элементы, 0); кообласть = w.Кообласть.Values.ToDictionary(v => v.Имя); область = w.Область.Values.ToDictionary(v => v.Имя); }
//Функция составляет список слов, которые являются кодоменами для слова word public Dictionary <string, Конус> ПолучитьОбласть() { Dictionary <string, Конус> результат = new Dictionary <string, Конус> { //TODO: Единичный морфизм (id) не всегда полезен, так как оставляет соответствующий морфизм в пределе и копределе, а //поиск в диаграмме, часто, должен оставлять только "терминальные" объекты. Нужно решить как по желанию отказываться //от id - в синтаксисе, через спец-символ (например, @ - абстрактный) или оставить добавление id каждый раз на усмотрение //пользователя. При этом, отсутствие id в конусе может привести к "обнулению" декартова произведения конусов, что не даст //создать фильтр конуса (поиск нужных морфизмов в кообластях и областях конусов). { Имя, this } }; ; //предполагаем, что единичный морфизм всегда существует //Если у слова область не пустой, добавляем его к результату if (Область.Count > 0) { foreach (string key in Область.Keys) { результат[key] = Область[key]; } } //Если слово - символ, то есть односложное, то возвращаем результат (дальнейшие вычисления не нужны) if (Элементы.Length == 0) { return(результат); } //Создаем массив массивов для хранения наборов областей каждого элемента слова Конус[][] области = new Конус[Элементы.Length][]; for (int k = 0; k < Элементы.Length; k++) { //Создаем массив кодоменов k-го элемента слова Dictionary <string, Конус> _область = Элементы[k].ПолучитьОбласть(); //Если создание массива областей для k-го элемента неуспешное (у k-го элемента нет областей), //то и создание областей всего слова неуспешно - возвращаем пустой список. if (_область.Count() == 0) { return(результат); } else { //Добавляем в массив новый массив областей для k-го элемента области[k] = _область.Values.ToArray(); } } IEnumerable <Конус> произведение = ДекартовоПроизведение(области); foreach (Конус m in произведение) { результат[m.Имя] = m; } return(результат); }
public static Конус AddLocal(string _name) { if (Local.ContainsKey(_name)) { return(Storage.Local[_name]); } else { Local[_name] = new Конус(_name); return(Local[_name]); }; }
//Вычисляет декартово произведение морфизмов l X r private static Dictionary <string, Конус> ВычислитьПроизведение(Dictionary <string, Конус> l, Dictionary <string, Конус> r) { Dictionary <string, Конус> результат = new Dictionary <string, Конус>(); foreach (Конус left in l.Values) { foreach (Конус right in r.Values) { Конус конус = Storage.AddLocal(new Конус(new Конус[] { left, right })); результат[конус.Имя] = конус; } } return(результат); }
public void TestMatching() { Конус w1 = new Конус("1"); Конус w2 = new Конус("2"); Конус w3 = new Конус("3"); Assert.IsTrue(w1.СоответствуетШаблону(new Конус("_"))); //проверка соответствия шаблону "ЛЮБОЙ" Assert.IsTrue(w1.СоответствуетШаблону(new Конус("1"))); //проверка соответствия шаблону "1" Assert.IsFalse(w1.СоответствуетШаблону(new Конус("2"))); //проверка несоответствия шаблону "2" Конус w4 = new Конус(new Конус[] { w1, w2, w3 }); //слово [1,2,3] Конус w5 = new Конус(new Конус[] { w4, w2, w3 }); //слово [[1,2,3],2,3] Конус pattern = new Конус(new Конус[] { new Конус("_"), w2, w3 }); //проверка паттерна [_,2,3] для слова [[1,2,3],2,3] Assert.IsTrue(w5.СоответствуетШаблону(pattern)); }
private List <Конус> ДекартовоПроизведение(Конус[][] области) { Dictionary <string, Конус> результат = new Dictionary <string, Конус>(); //Для навигации по массиву наборов областей нужен массив индексов - регистр[]. //Значение элемента массива - регистр[i] - это номер области i-го элемента слова. //Максимальное значение регистр[i] - количество кодоменов в области[i]. //Следующий цикл обеспечивает перебор всех вариантов компоновок областей. //Алгоритм изменения регистра подобен увеличению на единицу числа в многоосновной позиционной системе исчисления, //в которой i-й разряд увеличивается при достижении (i+1)-го разряда максимального значения (которое задается количеством кодоменов i+1-го элемента). int[] регистр = new int[области.Length]; //массив разрядов - регистр (инициализирован нулями) int i = 0; //номер разряда do { //Увеличиваем номер разряда, двигаясь к самому последнему (младшему) разряду регистра if (i < области.Length - 1) { i++; } else //Если мы дошли до последнего (младшего) разряда и его можно увеличить на 1 if (регистр[i] < области[i].Length) { //Создадим слово из элементов с текущими значениями разрядов Конус w = Storage.AddLocal(регистр.Select((c, j) => области[j][c])); //Добавим слово в коллекцию результата результат[w.Имя] = w; //Увеличиваем последний разряд на 1 регистр[i]++; } else //Если последний разряд регистра увеличить нельзя { do { регистр[i] = 0; //обнуляем последний разряд i--; //возвращаемся к старшему разряду if (i >= 0) { регистр[i]++; //увеличиваем (i-1)-й разряд на 1 } } while (i >= 0 && регистр[i] == области[i].Length); } } while (i >= 0); //Если результат не содержит ни одного кодомена - возвращаем пустой список return(результат.Values.ToList()); }
public void TestWordDomain() { Конус w1 = new Конус("1"); Конус w2 = new Конус("2"); Конус w3 = new Конус("3"); w1.ДобавитьВКообласть(w2); w1.ДобавитьВКообласть(w3); Assert.IsTrue(w1.Кообласть.Count == 2); //проверка добавления двух слов в домен слова w1 Assert.IsTrue(w2.Область["1"].Имя == "1"); //проверка кодоменов добавляемых слов Assert.IsTrue(w3.Область["1"].Имя == "1"); w1.УдалитьИзКообласти(w2); w1.УдалитьИзКообласти(w3); Assert.IsTrue(w1.Кообласть.Count == 0); //проверка удаления слова из домена w1 Assert.IsTrue(w2.Область.Count == 0); }
//Функция составляет список слов, которые являются кодоменами для слова word public Dictionary <string, Конус> ПолучитьКообласть() { Dictionary <string, Конус> результат = new Dictionary <string, Конус> { //Предполагаем, что единичный морфизм всегда существует { Имя, this } }; //Если у слова кообласть не пустая, добавляем её к результату if (Кообласть.Count > 0) { foreach (string key in Кообласть.Keys) { результат[key] = Кообласть[key]; } } //Если слово - символ, то есть односложное, то возвращаем результат (дальнейшие вычисления не нужны) if (Элементы.Length == 0) { return(результат); } //Создаем массив массивов для хранения наборов кообластей каждого элемента слова Конус[][] кообласти = new Конус[Элементы.Length][]; for (int k = 0; k < Элементы.Length; k++) { //Создаем массив кодоменов k-го элемента слова Dictionary <string, Конус> _кообласть = Элементы[k].ПолучитьКообласть(); //Если создание массива кодоменов для k-го элемента неуспешное (у k-го элемента нет кообластей), //то и создание кодоменов всего слова неуспешно - возвращаем пустой список. if (_кообласть.Count() == 0) { return(результат); } //Добавляем в массив новый массив кообластей для k-го элемента кообласти[k] = _кообласть.Values.ToArray(); } IEnumerable <Конус> произведение = ДекартовоПроизведение(кообласти); foreach (Конус m in произведение) { результат[m.Имя] = m; } return(результат); }
public static Конус AddLocal(Конус word) { //Пробуем вычислить морфизм как функтор if (Функтор.ЭтоФунктор(word)) { //TODO: определить условия вычисления функтора: если он был ранее вычислен, нужно ли его вычислять заново? //Вероятно нужно определить функторы, которые зависят от области и кообласти - их вычислять надо всегда. //Остальные функторы вычислять можно один раз. Dictionary <string, Конус> результат = Функтор.ВычислитьФунктор(word); foreach (string key in результат.Keys) { Storage.AddLocal(результат[key]); } word.ДобавитьВКообласть(результат.Values); Local[word.Имя] = word; } if (!Local.ContainsKey(word.Имя)) { Local[word.Имя] = word; } return(Local[word.Имя]); }
//Функция сравнения с шаблоном слова возвращает истину если: // - шаблон w - это символ '_' ("любой"); // - все элементы шаблона совпадают кроме '_'. public bool СоответствуетШаблону(Конус w) { if (Функтор.ЭтоФунктор(w)) { Dictionary <string, Конус> шаблоны = Функтор.ВычислитьФунктор(w); return(СоответствуетШаблону(шаблоны.Values)); } else { if (w.Имя == ЛюбойСимвол) { return(true); //для символа шаблона "любой" функция возвращает истину } if (Элементы.Length != w.Элементы.Length) { return(false); // Если количество элементов в словах не равно, то слова не равны } if (Имя == w.Имя) { return(true); //слова равны, если их строковые представления равны } if (Элементы.Length == 0) { return(false); //если слово односложное и имена не равны, то слова не равны } // Поэлементное сравнение for (int i = 0; i < Элементы.Length; i++) { if (!Элементы[i].СоответствуетШаблону(w.Элементы[i])) { return(false); } } return(true); //Поэлементное сравнение дало положительный ответ } }
//Результатом вычисления кообласти является коллекция морфизмов, полученная в результате применения функуторов, //являющихся элементами морфизма, другим элементам морфизма. //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]); }
public static Конус AddLocal(IEnumerable <Конус> _elements) { Конус word = new Конус(_elements); return(AddLocal(word)); }
//private static readonly Конус[] ШаблоныФункторов = new Конус[] // { // new Конус(new Конус[] { new Конус("_"), ФункторПоТипу[Тип.ВычислениеОбласти],new Конус("_") }), // шаблон [_,>,_] // new Конус(new Конус[] { new Конус("_"), ФункторПоТипу[Тип.ВычислениеКообласти],new Конус("_") }),// шаблон [_,<,_] - кообласть // new Конус(new Конус[] { new Конус("_"), ФункторПоТипу[Тип.ДекартовоПроизведение],new Конус("_") }), // шаблон [_,*,_] - произведение // new Конус(new Конус[] { new Конус("_"), ФункторПоТипу[Тип.Сумма],new Конус("_") }), // шаблон [_,+,_] - сумма // new Конус(new Конус[] { new Конус("_"), ФункторПоТипу[Тип.Разность],new Конус("_") }), // шаблон [_,-,_] - разность // new Конус(new Конус[] { new Конус("_"), ФункторПоТипу[Тип.Пересечение],new Конус("_") }), // шаблон [_,^,_] - пересечение // new Конус(new Конус[] { new Конус("_"), ФункторПоТипу[Тип.ВыборПоШаблону],new Конус("_") }), // шаблон [_,~,_] - выбор по шаблону // new Конус(new Конус[] { new Конус("_"), ФункторПоТипу[Тип.ПроекцияПоШаблону],new Конус("_") }), // шаблон [_,~:,_] - выбор по шаблону // new Конус(new Конус[] { new Конус("_"), ФункторПоТипу[Тип.Тождество]}), // шаблон [_,id] - тождество // }; //Метод возвращает true, если данный морфизм является эндофунктором. public static bool ЭтоФунктор(Конус m) { return(m.Элементы.Any(p => ЭтоИмяФунктора(p.Имя))); }
public void TestFunctors() { //"<", // получает кообласть морфизма //">", // получает область морфизма //"*", // получает произведение морфизмов //"+", // получет сумму морфизмов //"-", // получает разность морфизмов //"^", // получает пересечение морфизмов //"-:", // получает проекцию морфизмов //"id", // тождество Конус знакОбласть = new Конус("<"); Конус знакКообласть = new Конус(">"); Конус знакПроизведение = new Конус("*"); Конус знакСумма = new Конус("+"); Конус знакРазность = new Конус("-"); Конус знакПересечение = new Конус("^"); Конус знакПроекция = new Конус("~:"); Конус знакВыбор = new Конус("~"); Конус знакТождество = new Конус("id"); Конус знакЛюбой = new Конус("_"); Конус w1 = new Конус("1"); Конус w2 = new Конус("2"); Конус w1s = new Конус("один"); Конус w2s = new Конус("два"); Конус числоЦифрами = new Конус(new Конус("числоЦифрами")); числоЦифрами.ДобавитьВКообласть(new Конус[] { w1, w2 }); Конус числоСловами = new Конус(new Конус("числоСловами")); числоСловами.ДобавитьВКообласть(new Конус[] { w1s, w2s }); Конус числа = new Конус(new Конус("числа")); числа.ДобавитьВКообласть(new Конус[] { числоЦифрами, числоСловами }); //Конус фОбласть = new Конус(new Конус[] { числоЦифрами, знакОбласть }); //List<Конус> область = DataModelLibrary.Функтор.ВычислитьФунктор(фОбласть); //Assert.IsTrue(область.Count==2 && область[0].Имя == "1" && область[1].Имя == "2"); //Конус фКообласть = new Конус(new Конус[] { числоЦифрами, знакКообласть }); //List<Конус> кообласть = DataModelLibrary.Функтор.ВычислитьФунктор(фКообласть); //Assert.IsTrue(кообласть.Count == 1 && кообласть[0].Имя == "числа"); //Конус фПроизведение = new Конус(new Конус[] { числоЦифрами, знакПроизведение, числоСловами }); //List<Конус> произведение = DataModelLibrary.Функтор.ВычислитьФунктор(фПроизведение); //Assert.IsTrue(произведение.Count == 1 && произведение[0].Имя == "[числоЦифрами,числоСловами]"); //Конус фСумма = new Конус(new Конус[] { числоЦифрами, знакСумма, числоСловами }); //List<Конус> сумма = DataModelLibrary.Функтор.ВычислитьФунктор(фСумма); //Assert.IsTrue(сумма.Count == 2 && // сумма.Any(m=>m.Имя == "числоЦифрами")); //Конус фРазность = new Конус(new Конус[] { фСумма, знакРазность, числоСловами }); //List<Конус> разность = DataModelLibrary.Функтор.ВычислитьФунктор(фРазность); //Assert.IsTrue(разность.Count == 1 && // разность.Any(m => m.Имя == "числоЦифрами")); //Конус фПересечение = new Конус(new Конус[] { фСумма, знакПересечение, числоСловами }); //List<Конус> пересечение = DataModelLibrary.Функтор.ВычислитьФунктор(фПересечение); //Assert.IsTrue(пересечение.Count == 1 && пересечение[0].Имя == "числоСловами"); //Конус шаблон = new Конус(new Конус[] { числоЦифрами, знакЛюбой }); //Конус фПроекция = new Конус(new Конус[] { фПроизведение, знакПроекция, шаблон }); //List<Конус> проекция = DataModelLibrary.Функтор.ВычислитьФунктор(фПроекция); //Assert.IsTrue(проекция.Count == 1 && проекция[0].Имя == "числоСловами"); //Конус фКообластьПроизведения = Функтор.СоздатьФунктор(Функтор.Тип.ВычислениеКообласти, произведение.ToArray()); //List<Конус> кообластьПроизведения = DataModelLibrary.Функтор.ВычислитьФунктор(фКообластьПроизведения); //Assert.IsTrue(кообластьПроизведения.Count == 4 && // кообластьПроизведения.Any(m => m.Имя == "[1,один]") && // кообластьПроизведения.Any(m => m.Имя == "[1,два]") && // кообластьПроизведения.Any(m => m.Имя == "[2,один]") && // кообластьПроизведения.Any(m => m.Имя == "[2,два]")); }
public bool Equals(Конус w) { return(w.Имя == Имя); }
public void ДобавитьВОбласть(Конус w) { Область[w.Имя] = w; w.Кообласть[Имя] = this; }