コード例 #1
0
        /// <inheritdoc />
        public FinalAnswer Solve(Model model, IDirectTaskSolver checker)
        {
            _model   = model;
            _answer  = Model.Copy(model);
            _checker = checker;
            Best     = new FinalAnswer(_answer, _checker.Solve(_answer));

            _chain   = RailwayChain.FromModel(_answer, reduceCount: true);
            _current = _chain;

            try
            {
                Main();
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("Алгоритм AmplifierFinalSolver остановлен");
            }
            catch (Exception e)
            {
                Console.WriteLine($"Ошибка в AmplifierFinalSolver: {e}");
            }
            finally
            {
                var ans = Model.Copy(Best.Model);
                ans.Blocks.Clear();
                ans.Blocks.AddRange(_model.Blocks);
                Best = new FinalAnswer(ans, _checker.Solve(ans));
            }

            return(Best);
        }
コード例 #2
0
        /// <summary>
        /// Решить обратную задачу
        /// </summary>
        /// <param name="model">Неполная модель исходных данных (только блоки DATA и ROUTE)</param>
        /// <param name="checker">Алгоритм решения прямой задачи - для вычисления стоимости</param>
        /// <returns>Полная модель (включая блоки ORDER и TOP)</returns>
        public FinalAnswer Solve(Model model, IDirectTaskSolver checker)
        {
            _model   = model;
            _answer  = Model.Copy(model);
            _checker = checker;

            var chain = RailwayChain.FromModel(_answer, true);

            _current1 = _chain = new Railway(RailwayType.L0);
            foreach (var railway in chain.GetRailways())
            {
                if (railway.IsHead())
                {
                    continue;
                }
                _current1.Append(railway);
                _current1 = _current1.Next;
            }

            _current1 = _current2 = _chain;

            Context = new DrawableContext();

            Context.BotsRating = "Управление:\n" +
                                 "W: Add L3\n" +
                                 "A: Add 2xT4L\n" +
                                 "S: Remove\n" +
                                 "D: Add 2xT4R\n" +
                                 "B: Add Bridge\n" +
                                 "Q: Prev item\n" +
                                 "E: Next item\n" +
                                 "Shift+W: L1\n" +
                                 "Shift+A: T4L\n" +
                                 "Shift+D: T4R\n" +
                                 "Z: Sync curs\n" +
                                 "X: Swap curs\n" +
                                 "C: Change mode\n" +
                                 "V: Insert tmpl\n" +
                                 "";

            SendAnswer();

            while (!Token.IsCancellationRequested)
            {
                Thread.Sleep(500);
            }

            _answer.Blocks.Clear();
            _answer.Blocks.AddRange(_model.Blocks);

            Context = new DrawableContext();
            SendAnswer();

            return(new FinalAnswer()
            {
                Model = _answer, Price = checker.Solve(_answer)
            });
        }
コード例 #3
0
        public void Test_1_SubTemplate_L6T2R()
        {
            var chain = new RailwayChain(Railway.L3, Railway.L3, Railway.T4R, Railway.T4R);

            var head = new Railway(RailwayType.L0);

            head.Append(chain);

            var destination = new Point(3, 9, -Math.PI / 2);

            var indexes = chain.FindSubTemplate(destination);

            Assert.IsNotNull(indexes);

            Assert.AreEqual(chain[0], indexes?.start);
            Assert.AreEqual(chain[3], indexes?.end);
        }
コード例 #4
0
        public void Test_3_SubTemplate_L6T2L_Rotated()
        {
            var chain = new RailwayChain(Railway.L3, Railway.L3, Railway.T4L, Railway.T4L);

            var head = new Railway(RailwayType.L0);
            var last = head.Append(Railway.T4R);

            last = last.Append(Railway.T4R);
            last.Append(chain);

            var destination = new Point(-3, 9, Math.PI / 2);

            var indexes = chain.FindSubTemplate(destination);

            Assert.IsNotNull(indexes);

            Assert.AreEqual(chain[0], indexes?.start);
            Assert.AreEqual(chain[3], indexes?.end);
        }
コード例 #5
0
        private void Main()
        {
            var library = new List <string>
            {
                "L1L1L1",
                "L1L1",
                "L2",
                "L3",
                "L4",

                "t2",
                "T2",
                "T2L1",
                "t2L1",
                "T2L2",
                "t2L2",
                "T2L3",
                "t2L3",

                "L6t2t2L6",
                "L6T2T2L6",
            };

            library.AddRange(RailwayTemplates.Library);

            // Перебираем каждый шаблон библиотеки
            //foreach (var blueprint in library)

            Parallel.ForEach(library, blueprint =>
            {
                var answer = Model.Copy(_answer);

                if (!RailwayFactory.Default.TryBuildTemplate(out var template, out var error, blueprint, answer))
                {
                    //continue;
                    return;
                }

                var chain = RailwayChain.FromModel(answer);

                // Все под-шаблоны исходной цепочки, которые можно заменить на подходящий шаблон
                var subTemplates = chain.FindSubTemplates(template.Dimensions.Output);
                template.ReturnBlocksToModel(answer);

                var cur = chain[0];

                for (var j = 0; j < subTemplates.Count; j++)
                {
                    //TODO chain = chain.Copy;

                    if (!RailwayFactory.Default.TryBuildTemplate(out template, out _, blueprint, answer))
                    {
                        break;
                    }

                    var(length, start, end) = subTemplates[j];

                    var finish = true;
                    while (cur != null)
                    {
                        if (cur == start)
                        {
                            finish = false;
                        }
                        if (cur == end)
                        {
                            break;
                        }
                        cur = cur.Next;
                        if (cur is Railway r && r.IsHead())
                        {
                            break;
                        }
                    }

                    if (finish)
                    {
                        continue;
                    }

                    // Присоединяем новый шаблон
                    {
                        if (start.Prev != null)
                        {
                            start.Prev.Next = template;
                        }
                        template.Prev = start.Prev;

                        if (end.Next != null)
                        {
                            end.Next.Prev = template;
                        }
                        template.Next = end.Next;

                        template.Start = start.Start;
                    }

                    var result = chain.ConvertToModel(answer);
                    var price  = _checker.Solve(result);

                    lock (_sync)
                    {
                        if (price.Result > Best.Price.Result)
                        {
                            // Проверяем на пересечения:
                            if (RailwayChain.FromModel(result).FindCrosses().Count == 0)
                            {
                                Best = new FinalAnswer(result, price);

                                OnStepEvent?.Invoke(this, Best);
                            }
                        }
                    }
                }
            });
コード例 #6
0
ファイル: RailwayFactory.cs プロジェクト: Berethor/Lillabu
        public bool TryBuildTemplate(out IRailwayTemplate template, out string error, string blueprint, Model model)
        {
            // Копируем список блоков
            var blocks = model?.Blocks.Select(block => (Block)block.Clone()).ToList();

            error = null;

            var regex = new Regex("((?'type'L|T|t|B)(?'lenght'\\d+))");

            var railways = new List <Railway>();

            foreach (Match match in regex.Matches(blueprint))
            {
                var type   = match.Groups["type"].Value;
                var length = int.Parse(match.Groups["lenght"].Value);

                switch (type)
                {
                case "L":
                {
                    for (var k = 4; k > 0; k--)
                    {
                        var lineBlocks = blocks?.FirstOrDefault(_ => _.Name == $"L{k}");
                        while (lineBlocks?.Count > 0 && length >= k)
                        {
                            length -= k;
                            lineBlocks.Count--;
                            var railway =
                                k == 4 ? Railway.L4 :
                                k == 3 ? Railway.L3 :
                                k == 2 ? Railway.L2 :
                                Railway.L1;
                            railways.Add(railway);
                        }
                    }

                    break;
                }

                case "T":
                case "t":
                {
                    var amount = 0;
                    switch (length)
                    {
                    case 1:
                        amount = 8;
                        break;             // T1 = 8 x T8

                    case 2:
                        amount = 4;
                        break;             // T2 = 4 x T8

                    case 4:
                        amount = 2;
                        break;             // T4 = 2 x T8

                    case 8:
                        amount = 1;
                        break;             // T8 = 1 x T8

                    default:
                        error    = $"Некорректная длина блока {type}{length} в шаблоне {blueprint}";
                        template = null;
                        return(false);
                    }

                    var t4Blocks = blocks?.FirstOrDefault(_ => _.Name == "T4");
                    var t8Blocks = blocks?.FirstOrDefault(_ => _.Name == "T8");

                    if (t8Blocks?.Price < t4Blocks?.Price)
                    {
                        while (t8Blocks?.Count > 0 && amount >= 1)
                        {
                            if (t8Blocks?.Count == 1 && amount == 2)
                            {
                                break;
                            }

                            amount -= 1;
                            t8Blocks.Count--;
                            railways.Add(type == "T" ? Railway.T8R : Railway.T8L);
                        }
                    }
                    while (t4Blocks?.Count > 0 && amount >= 2)
                    {
                        amount -= 2;
                        t4Blocks.Count--;
                        railways.Add(type == "T" ? Railway.T4R : Railway.T4L);
                    }
                    while (t8Blocks?.Count > 0 && amount > 0)
                    {
                        amount -= 1;
                        t8Blocks.Count--;
                        railways.Add(type == "T" ? Railway.T8R : Railway.T8L);
                    }

                    if (amount == 0)
                    {
                        length = 0;
                    }

                    break;
                }

                case "B":
                {
                    if (length != 1)
                    {
                        throw new ArgumentException(
                                  $"Некорректная длина блока {type}{length} в шаблоне {blueprint}");
                    }

                    var bridgeBlocks = blocks?.FirstOrDefault(_ => _.Name == "B1");
                    if (bridgeBlocks?.Count > 0)
                    {
                        length--;
                        bridgeBlocks.Count--;
                        railways.Add(Railway.B1);
                    }

                    break;
                }
                }

                if (length != 0)
                {
                    error    = $"Недостаточно блоков для производства {match.Value} в шаблоне {blueprint}";
                    template = null;
                    return(false);
                }
            }

            var chain = new RailwayChain(railways.Cast <IRailwayTemplate>().ToArray());

            // Создаём автоматические связи симметрии
            // TODO переделать
            var directions = chain.GetDirections();

            if (directions.ContainsKey(Direction.N) && directions.ContainsKey(Direction.S))
            {
                foreach (var block in directions[Direction.N])
                {
                    block.Symmetric = directions[Direction.S].First();
                }
            }
            if (directions.ContainsKey(Direction.W) && directions.ContainsKey(Direction.E))
            {
                foreach (var block in directions[Direction.W])
                {
                    block.Symmetric = directions[Direction.E].First();
                }
            }

            // Если произвести блок удалось
            // применяем изменение количества блоков
            model?.Blocks.Clear();
            model?.Blocks.AddRange(blocks);

            if (chain.GetRailways().Count == 1)
            {
                template = chain[0];
                return(true);
            }

            template = chain;
            return(true);
        }