private UserToEducationLineAnalysis() { //Получаем полный список доступных кластеров using (var context = new RecomendationSystemModelContainer()) { totalArrayClusters = context.Clusters.ToArray(); } }
/// <summary> /// Ищет в бд информацию о направлениях, из которой строит "таблицу": направления/кластеры. /// </summary> private EducationLineToClusterCell[,] AnalyseAllEducationLineCluster() { using (var context = new RecomendationSystemModelContainer()) { var allEducationLines = (from user in context.DepartmentEducationLines select user).ToArray(); var allEducationLinesClusterMatrix = new EducationLineToClusterCell[allEducationLines.Length, totalArrayClusters.Length]; //пробешамеся по всем направлениям for (int i = 0; i < allEducationLines.Length; i++) { Dictionary <Cluster, double> clusterResult = new Dictionary <Cluster, double>(); foreach (var item in totalArrayClusters) { clusterResult.Add(item, 0); } //заполняем оценками и кластерами foreach (var requipment in allEducationLines[i].DepartmentLinesRequirement) { //Получаем текущую дисциплину и ее весовые коэффициенты. Запонляем : Дисциплина/кластер int mark = requipment.Requirement; foreach (var weight in requipment.Discipline.Weight) { var t = weight.Cluster; var cluster = (from item in totalArrayClusters where item.Name == weight.Cluster.Name select item).SingleOrDefault(); //Прибавляет заданному кластуру значение. Именно прибавляет. //Т.е. если у нас есть к примеру есть значение по математике, //и мы смотрим информатику,которая в свою очередь имеет вклад и в Информатику, и в Математику(меньший). //Соответсвенно начальное значение математики увеличится clusterResult[cluster] += mark * weight.Coefficient; } } for (int j = 0; j < totalArrayClusters.Length; j++) { //Результат allEducationLinesClusterMatrix[i, j] = new EducationLineToClusterCell { EducationLineId = allEducationLines[i].Id, EducationLineName = allEducationLines[i].Name + ", " + allEducationLines[i].EducationForm, ClusterId = clusterResult.ElementAtOrDefault(j).Key.Id, ClusterName = clusterResult.ElementAtOrDefault(j).Key.Name, Value = clusterResult.ElementAtOrDefault(j).Value }; } } return(allEducationLinesClusterMatrix); } }
/// <summary> /// Ищет в бд информацию о пользователях, из которой строит "таблицу": пользователи/кластеры. /// </summary> /// <returns>Таблица с значениеями и описанием ячейки </returns> private UserToClusterCell[,] AnalyseAllUserCluster() { using (var context = new RecomendationSystemModelContainer()) { var allUsers = (from user in context.Users select user).ToArray(); var allUserClusterMatrix = new UserToClusterCell[allUsers.Length, totalArrayClusters.Length]; //берем всех пользователей for (int i = 0; i < allUsers.Length; i++) { Dictionary <Cluster, double> clusterResult = new Dictionary <Cluster, double>(); foreach (var item in totalArrayClusters) { clusterResult.Add(item, 0); } //заполняем оценками и кластерами foreach (var stateExam in allUsers[i].UnitedStateExam) { //Получаем текущую дисциплину и ее весовые коэффициенты. Запонляем : Дисциплина/кластер int mark = stateExam.Result; foreach (var weight in stateExam.Discipline.Weight) { var t = weight.Cluster; var cluster = (from item in totalArrayClusters where item.Name == weight.Cluster.Name select item).SingleOrDefault(); //Прибавляет заданному кластуру значение. Именно прибавляет. //Т.е. если у нас есть к примеру есть значение по математике, //и мы смотрим информатику,которая в свою очередь имеет вклад и в Информатику, и в Математику(меньший). //Соответсвенно начальное значение математики увеличится clusterResult[cluster] += mark * weight.Coefficient; } } for (int j = 0; j < totalArrayClusters.Length; j++) { //Результат allUserClusterMatrix[i, j] = new UserToClusterCell { UserId = allUsers[i].Id, UserName = allUsers[i].FirstName, ClusterId = clusterResult.ElementAtOrDefault(j).Key.Id, ClusterName = clusterResult.ElementAtOrDefault(j).Key.Name, Value = clusterResult.ElementAtOrDefault(j).Value }; } } return(allUserClusterMatrix); } }
/// <summary> /// Получает иноформацию из бд и приводит ее к матричному виду для дальнейшей обработки алгоритмом построения мн-ва Парето. /// В данной версии считается, что порядок названий в бд меняться на протяжении работы не будет(так по идее и должно быть) /// </summary> private void CalculateInfoForParretoSet() { List <EducationLineAndRequirementRow> educationLinesAndRequirementTable; using (var context = new RecomendationSystemModelContainer()) { //TODO: Направлению обучения не хватает названия(одного когда не достаточно) //Получаем списки всех нарпавлений обучения + информация о требованиях educationLinesAndRequirementTable = (from edLines in context.DepartmentEducationLines where edLines.DepartmentLinesRequirement.Count == 3//пока захардкодим(Должно быть обязательно указано 3 экзамена егэ (мин.баллы) select new EducationLineAndRequirementRow() { Id = edLines.Id, Code = edLines.Code, Requirements = (from requirement in edLines.DepartmentLinesRequirement select requirement.Requirement).ToList() }).ToList(); //Получаем остальные списки: оценки, увлечения, предпочтения } if (educationLinesAndRequirementTable.Count > 0) { //Дальше алгоритм построения множества Паретто MulticriterialAnalysis multicriterialAnalysis = new MulticriterialAnalysis(); var parretoSet = multicriterialAnalysis.ParretoSetCreate(educationLinesAndRequirementTable); //Теперь необходимо сузить наше множество: #region 1. Выявлении информации об относительной важности критериев //Опрос ЛПР //TODO: Подумать над возможностью циклического уточнения, с опросом уточяющей информации на каждом шаге //+ проверке непротиворечивости нескольких утверждений #endregion #region 2. Замена менее важных криетриев новыми //Пока сделал 1 шаг с фиксированными коэффициентами(нужно обдумать что они правильные). ЛПР в данном случае -мы(я) //Пусть у нас 3 критерия - минимальные баллы по предметам //На сколько мы готовы пожертвовать русским ради математикик и профильного предмета(информатика) //когда один критерий важнее второго, а он, в свою очередь, //важнее третьего (здесь можно дважды применить теорему 2.5 — //сначала пересчитывается третий критерий, а затем второй; см. //п. 1 разд. 4.1) //Пусть русский<математика<информатика // 80 70 // 30 60 // 60 30 //Пересчитываем сначала русский, потом математику // 72 // 72 // 72 //... double tetaMath_Rus = multicriterialAnalysis.GetTeta(20, 10); double tetaProf_Math = multicriterialAnalysis.GetTeta(20, 5); //Определить на каких позициях стоит какой предмет и пересчить поп формуле. Пусть для начала считаем что на 0 - русский, на 1 - математика, на 3-информатика foreach (var row in parretoSet) { //teta*болееВажный + (1-teta)* менееВажный //Пересчитываем русский 70 80 -> 72 80 //Пересчитываем информатику 80 90-> .. .. //... for (int i = 0; i < row.Requirements.Count - 1; i++) { row.Requirements[i] = RecalculateElementsRow(row.Requirements[i + 1], row.Requirements[i], tetaMath_Rus); } } //или //когда два критерия по отдельности важнее третьего (тогда для формирования //нового векторного критерия следует использовать формулу (4.7) //или еще варианты... //TODO: Решить как распределять коэффициенты и какой у нас случай. По идее мы можем сгруппировать наши требования в группы: ЕГЭ, Оценки, Увлечения и пр. //В каждой из них - есть свои требования(балы по математике, русскому, информтатике) которые так же сравнимы... как быть. Счить все как 1 кучу и выявять нужные или по группам. //Есть идея сделать рекурсивно: //Сначала считаем на вершинах дерева - сравниваем Егэ по русскому, математике и информатике. Получим равнозначные критерии в итоге. //Потом сравниваем полученную группу из 3-х критериев с остальными. //Самый простой вариант на мой взгялд - заранее определить важность в виде a1<a2<a3<a4<...<an //После этого упорядочить наш список критериев(в бд или в коде) #endregion #region Нахождение нового мноежства паретто var parretoSetNew = multicriterialAnalysis.ParretoSetCreate(parretoSet); #endregion #region 3. Анализ ЛПР-ом получившихся значений #endregion } else { throw new Exception("Не удалось получить списко информации об направлениях обучения и требованиях"); } }