예제 #1
0
        public static MutableEntityTreeNode <int, MatchRule> BuildTree(this IList <MatchRule> rules, out List <MatchRule> unreachableItems)
        {
            if (rules is null)
            {
                throw new ArgumentNullException(nameof(rules));
            }

            var lookup = rules.ToLookup(z => z.ParentId);
            var root   = new MutableEntityTreeNode <int, MatchRule>(GetIdFunc, null);

            void Walk(MutableEntityTreeNode <int, MatchRule> ruleNode)
            {
                foreach (var c in lookup[ruleNode.Item.Id])
                {
                    Walk(ruleNode.AddChild(c));
                }
            }

            foreach (var r in lookup[null])
            {
                Walk(root.AddChild(r));
            }
            unreachableItems = rules.Except(root.Select(z => z.Item)).ToList();
            return(root);
        }
예제 #2
0
        public static void Start()
        {
            var dataRoot = new CategoryTreeLookup("Source2").GetCategoryDataTree();

            var mutableRoot =
                new MutableEntityTreeNode <long, CategoryItem>(CategoryEntityDefinition <CategoryItem> .Instance,
                                                               new CategoryItem(dataRoot.CategoryId, dataRoot.Name));

            mutableRoot.Build(dataRoot, x => new CategoryItem(x.CategoryId, x.Name));
            Display(mutableRoot);

            var readOnlyRoot =
                new ReadOnlyEntityTreeNode <long, CategoryItem>(CategoryEntityDefinition <CategoryItem> .Instance,
                                                                new CategoryItem(dataRoot.CategoryId, dataRoot.Name));

            readOnlyRoot.Build(dataRoot, x => new CategoryItem(x.CategoryId, x.Name));
            Display(readOnlyRoot);
        }
예제 #3
0
        public async Task <Responce> GlrTestAsync([FromBody] InputData input, int maxSubNodesCount = 3, int maxTreeDepth = 5)
        {
            return(await Task.Run(() =>
            {
                try
                {
                    // Проверка аргумента на null
                    _ = input ?? throw new ArgumentNullException(nameof(input));

                    IBalanceSolver solver = new MathlabBalanceSolver();

                    var flows = solver.GetFlows(input.A).ToList();
                    var nodesCount = input.A.GetLength(0);

                    var root = new MutableEntityTreeNode <Guid, TreeElement>(x => x.Id, new TreeElement());
                    var currentNode = root;

                    // Пока текущий узел существует
                    while (currentNode != null)
                    {
                        var newA = input.A;
                        var newX0 = input.X0;
                        var newMeasurability = input.Measurability;
                        var newTolerance = input.Tolerance;

                        // Добавляем к исходным данным новые потоки
                        foreach (var(fi, fj) in currentNode.Item.Flows)
                        {
                            var aColumn = new double[nodesCount];
                            aColumn[fi] = 1;
                            aColumn[fj] = -1;

                            newA = newA.InsertColumn(aColumn);
                            newX0 = newX0.Append(0).ToArray();
                            newMeasurability = newMeasurability.Append(0).ToArray();
                            newTolerance = newTolerance.Append(0).ToArray();
                        }

                        // Текущее значение глобального теста
                        var globalTest = solver.GlobalTest(newX0, newA, newMeasurability,
                                                           newTolerance);

                        // Таблица GLR теста
                        var glr = solver.GlrTest(newX0, newA, newMeasurability,
                                                 newTolerance, flows, globalTest);

                        // Поиск следующего максимума
                        var(i, j) = (0, 0);
                        for (var k = 0; k < currentNode.Children.Count + 1; k++)
                        {
                            // Находим максимальное значение GLR теста в массиве
                            (i, j) = glr.ArgMax();

                            // Если у нас не осталось значений больше нуля, то выходим
                            if (glr[i, j] <= 0)
                            {
                                break;
                            }

                            // Если итерация не последняя
                            if (k != currentNode.Children.Count)
                            {
                                // Сбрасываем значение, чтоб на следующей итерации найти следующий максимум
                                glr[i, j] = 0.0;
                            }
                        }

                        // Проверяем можно ли добавить дочерний узел в дерево
                        if (currentNode.Children.Count < maxSubNodesCount &&
                            currentNode.Level < maxTreeDepth && glr[i, j] > 0 && globalTest >= 1)
                        {
                            // Создаем элемент узла
                            var node = new TreeElement(new List <(int, int)>(currentNode.Item.Flows), globalTest - glr[i, j]);
                            node.Flows.Add((i, j));

                            // Добавляем дочерний элемент и делаем его текущим
                            currentNode = currentNode.AddChild(node);
                        }
                        else
                        {
                            // Поднимаемся выше по дереву
                            currentNode = currentNode.Parent;
                        }
                    }

                    //Находим все листья и выводим их
                    var leafs = root.Where(x => x.IsLeaf);
                    var results = new List <GlrOutput>();

                    foreach (var leaf in leafs)
                    {
                        var result = new List <GlrOutputFlow>();
                        var flowsToAdd = new List <Variable>();

                        foreach (var flow in leaf.Item.Flows)
                        {
                            var(i, j) = flow;

                            // Формируем информацию о потоке
                            var newFlow = new GlrOutputFlow
                            {
                                Id = Guid.NewGuid().ToString(),
                                Name = "New flow",
                                Number = -1,
                                Info = $"{i} -> {j}"
                            };

                            // Если у нас есть существующий поток, то выводим информацию о нем
                            var existingFlowIdx = flows.FindIndex(x => x.Item1 == i && x.Item2 == j);
                            if (existingFlowIdx != -1)
                            {
                                var(_, _, existingFlow) = flows[existingFlowIdx];

                                newFlow.Id = input.Guids[existingFlow];
                                newFlow.Name = input.Names[existingFlow];
                                newFlow.Number = existingFlow;

                                // Формируем информацию о добавляемом потоке
                                var variable = new Variable
                                {
                                    Id = Guid.NewGuid().ToString(),
                                    SourceId = input.NodesGuids[i],
                                    DestinationId = input.NodesGuids[j],
                                    Name = input.Names[existingFlow] + " (additional)",
                                    MetrologicRange = new Models.Range
                                    {
                                        Min = input.LowerMetrologic[existingFlow] - input.X0[existingFlow],
                                        Max = input.UpperMetrologic[existingFlow] - input.X0[existingFlow]
                                    },
                                    TechnologicRange = new Models.Range
                                    {
                                        Min = input.LowerTechnologic[existingFlow] - input.X0[existingFlow],
                                        Max = input.UpperTechnologic[existingFlow] - input.X0[existingFlow]
                                    },
                                    Tolerance = input.Tolerance[existingFlow],
                                    IsMeasured = true,
                                    VarType = "FLOW"
                                };

                                flowsToAdd.Add(variable);
                            }

                            // Добавляем поток в выходной список
                            result.Add(newFlow);
                        }

                        results.Add(new GlrOutput
                        {
                            FlowsInfo = result,
                            FlowsToAdd = flowsToAdd,
                            TestValue = leaf.Item.TestValue
                        });
                    }

                    return new Responce
                    {
                        Type = "result",
                        Data = results.OrderBy(x => x.TestValue)
                    };
                }
                catch (Exception e)
                {
                    return new Responce
                    {
                        Type = "error",
                        Data = e.Message
                    };
                }
            }));
        }
        public async Task <Responce> GlrTestGraphAsync([FromBody] InputGraph input)
        {
            var converted = await GraphToMatrixAsync(input);

            return(await Task.Run(() =>
            {
                try
                {
                    _ = converted ?? throw new ArgumentNullException(nameof(converted));

                    IBalanceSolver solver = new AccordBalanceSolver();

                    const int maxSubNodesCount = 3;
                    const int maxTreeDepth = 5;

                    var flows = solver.GetFlows(converted.A).ToList();
                    var nodesCount = converted.A.GetLength(0);

                    var root = new MutableEntityTreeNode <Guid, TreeElement>(x => x.Id, new TreeElement());
                    var currentNode = root;

                    while (currentNode != null)
                    {
                        var newA = converted.A;
                        var newX0 = converted.X0;
                        var newMeasurability = converted.Measurability;
                        var newTolerance = converted.Tolerance;

                        foreach (var(fi, fj) in currentNode.Item.Flows)
                        {
                            var aColumn = new double[nodesCount];
                            aColumn[fi] = 1;
                            aColumn[fj] = -1;

                            newA = newA.InsertColumn(aColumn);
                            newX0 = newX0.Append(0).ToArray();
                            newMeasurability = newMeasurability.Append(0).ToArray();
                            newTolerance = newTolerance.Append(0).ToArray();
                        }

                        var globalTest = solver.GlobalTest(newX0, newA, newMeasurability,
                                                           newTolerance);

                        var glr = solver.GlrTest(newX0, newA, newMeasurability,
                                                 newTolerance, flows, globalTest);

                        // Поиск следующего максимума
                        var(i, j) = (0, 0);
                        for (var k = 0; k < currentNode.Children.Count + 1; k++)
                        {
                            (i, j) = glr.ArgMax();

                            if (glr[i, j] <= 0)
                            {
                                break;
                            }

                            // Если итерация не последняя, сбрасываем значение
                            if (k != currentNode.Children.Count)
                            {
                                glr[i, j] = 0.0;
                            }
                        }

                        // Проверяем можно ли добавить дочерний узел в дерево
                        if (currentNode.Children.Count < maxSubNodesCount &&
                            currentNode.Level < maxTreeDepth && glr[i, j] > 0 && globalTest >= 1)
                        {
                            var node = new TreeElement(new List <(int, int)>(currentNode.Item.Flows), globalTest - glr[i, j]);
                            node.Flows.Add((i, j));

                            currentNode = currentNode.AddChild(node);
                        }
                        else
                        {
                            currentNode = currentNode.Parent;
                        }
                    }

                    //Находим все листья и выводим их
                    var leafs = root.Where(x => x.IsLeaf);
                    var results = new List <GlrOutput>();

                    foreach (var leaf in leafs)
                    {
                        var result = new List <GlrOutputFlow>();
                        var flowsToAdd = new List <Variable>();

                        foreach (var flow in leaf.Item.Flows)
                        {
                            var(i, j) = flow;

                            var newFlow = new GlrOutputFlow
                            {
                                Id = Guid.NewGuid().ToString(),
                                Name = "New flow",
                                Number = -1,
                                Info = $"{i} -> {j}"
                            };

                            // Если у нас есть существующий поток, то выводим информацию о нем
                            var existingFlowIdx = flows.FindIndex(x => x.Item1 == i && x.Item2 == j);
                            if (existingFlowIdx != -1)
                            {
                                var(_, _, existingFlow) = flows[existingFlowIdx];

                                newFlow.Id = converted.Guids[existingFlow];
                                newFlow.Name = converted.Names[existingFlow];
                                newFlow.Number = existingFlow;

                                // Формируем информацию о добавляемом потоке
                                var variable = new Variable
                                {
                                    Id = Guid.NewGuid().ToString(),
                                    SourceId = converted.NodesGuids[i],
                                    DestinationId = converted.NodesGuids[j],
                                    Name = converted.Names[existingFlow] + " (additional)",
                                    MetrologicRange = new Models.Range
                                    {
                                        Min = converted.LowerMetrologic[existingFlow] - converted.X0[existingFlow],
                                        Max = converted.UpperMetrologic[existingFlow] - converted.X0[existingFlow]
                                    },
                                    TechnologicRange = new Models.Range
                                    {
                                        Min = converted.LowerTechnologic[existingFlow] - converted.X0[existingFlow],
                                        Max = converted.UpperTechnologic[existingFlow] - converted.X0[existingFlow]
                                    },
                                    Tolerance = converted.Tolerance[existingFlow],
                                    IsMeasured = true,
                                    VarType = "FLOW"
                                };

                                flowsToAdd.Add(variable);
                            }

                            result.Add(newFlow);
                        }

                        results.Add(new GlrOutput
                        {
                            FlowsInfo = result,
                            FlowsToAdd = flowsToAdd,
                            TestValue = leaf.Item.TestValue
                        });
                    }

                    return new Responce
                    {
                        Type = "result",
                        Data = results.OrderBy(x => x.TestValue)
                    };
                }
                catch (Exception e)
                {
                    return new Responce
                    {
                        Type = "error",
                        Data = e.Message
                    };
                }
            }));
        }